[iptables] COMMIT_NOTES: notice to check for soversion bumps

Patrick McHardy netfilter-cvslog-bounces at lists.netfilter.org
Mon Jun 29 14:56:18 CEST 2009


Gitweb:		http://git.netfilter.org/cgi-bin/gitweb.cgi?p=iptables.git;a=commit;h=add2457a23b9894905b498b13c8328f9cffcaada
commit add2457a23b9894905b498b13c8328f9cffcaada
Author:     Jan Engelhardt <jengelh at medozas.de>
AuthorDate: Thu Jun 25 21:33:23 2009 +0200
Commit:     Jan Engelhardt <jengelh at medozas.de>
CommitDate: Fri Jun 26 21:13:10 2009 +0200

    COMMIT_NOTES: notice to check for soversion bumps
    
    Signed-off-by: Jan Engelhardt <jengelh at medozas.de>

commit c284de545d03aad9a04a4e17cfb55d911a96810c
Author:     Jan Engelhardt <jengelh at medozas.de>
AuthorDate: Thu Jun 25 21:25:24 2009 +0200
Commit:     Jan Engelhardt <jengelh at medozas.de>
CommitDate: Fri Jun 26 21:13:10 2009 +0200

    xtables: warn of missing version identifier in extensions
    
    Signed-off-by: Jan Engelhardt <jengelh at medozas.de>

commit f2a77520693f0a6dd1df1f87be4b81913961c1f5
Author:     Jan Engelhardt <jengelh at medozas.de>
AuthorDate: Thu Jun 25 20:12:12 2009 +0200
Commit:     Jan Engelhardt <jengelh at medozas.de>
CommitDate: Fri Jun 26 21:13:10 2009 +0200

    extensions: collapse data variables to use multi-reg calls
    
    Signed-off-by: Jan Engelhardt <jengelh at medozas.de>

commit 9a8fc4f89ef120d7beda3724994a1544346b947d
Author:     Jan Engelhardt <jengelh at medozas.de>
AuthorDate: Thu Jun 25 17:13:46 2009 +0200
Commit:     Jan Engelhardt <jengelh at medozas.de>
CommitDate: Fri Jun 26 21:13:10 2009 +0200

    xtables: add multi-registration functions
    
    Similar to the ones that are present in the kernel.
    
    Signed-off-by: Jan Engelhardt <jengelh at medozas.de>

commit 7d68df47fad305673958351a4e2a5c6e75927caa
Author:     Jan Engelhardt <jengelh at medozas.de>
AuthorDate: Fri Jun 12 20:59:34 2009 +0200
Commit:     Jan Engelhardt <jengelh at medozas.de>
CommitDate: Fri Jun 26 21:13:10 2009 +0200

    extensions: remove empty help and parse functions
    
    Signed-off-by: Jan Engelhardt <jengelh at medozas.de>

commit f89c1716a7743ca6e2e6164d3b64c15b2e285e1e
Author:     Jan Engelhardt <jengelh at medozas.de>
AuthorDate: Fri Jun 12 20:48:52 2009 +0200
Commit:     Jan Engelhardt <jengelh at medozas.de>
CommitDate: Fri Jun 26 21:13:10 2009 +0200

    iptables: allow for help-less extensions
    
    This is for extensions that do not take any options, and which
    subsequently do not offer any help text either.
    
    Signed-off-by: Jan Engelhardt <jengelh at medozas.de>

commit 92edcb0cf517ddb7976e396eabc7a79f8a1016ba
Author:     Jan Engelhardt <jengelh at medozas.de>
AuthorDate: Fri Jun 12 20:35:42 2009 +0200
Commit:     Jan Engelhardt <jengelh at medozas.de>
CommitDate: Fri Jun 26 21:13:09 2009 +0200

    iptables: allow for parse-less extensions
    
    This means we can do some code removal in extensions.
    
    Signed-off-by: Jan Engelhardt <jengelh at medozas.de>

commit c5e85736c207f211d82d2878a5781f512327dfce
Author:     Jan Engelhardt <jengelh at medozas.de>
AuthorDate: Fri Jun 12 20:55:44 2009 +0200
Commit:     Jan Engelhardt <jengelh at medozas.de>
CommitDate: Fri Jun 26 21:13:09 2009 +0200

    extensions: collapse registration structures
    
    There are no different code paths between IPV4 and IPV6, so
    data can be consolidated here.
    
       text    data     bss     dec     hex filename
     243757   12212    2576  258545   3f1f1 ip6tables-static[before.i586]
     243613    9428    2576  255617   3e681 ip6tables-static[after.i586]
       -144   -2784
    
    Signed-off-by: Jan Engelhardt <jengelh at medozas.de>

commit cc4344042e8c0bb6eef877975588321aa152660d
Author:     Jan Engelhardt <jengelh at medozas.de>
AuthorDate: Mon Jun 1 13:36:30 2009 +0200
Commit:     Jan Engelhardt <jengelh at medozas.de>
CommitDate: Fri Jun 26 21:13:09 2009 +0200

    libiptc: split v4 and v6
    
    The split can save some diskspace for constrained systems running
    which are only running one protocol.
    
    Signed-off-by: Jan Engelhardt <jengelh at medozas.de>

commit 332e4acc574e3a348fe611d55bf642de0d50fbda
Author:     Michael Granzow <mgranzow at zeus.com>
AuthorDate: Thu Apr 9 18:24:36 2009 +0100
Commit:     Jan Engelhardt <jengelh at medozas.de>
CommitDate: Fri Jun 26 21:13:06 2009 +0200

    iptables: accept multiple IP address specifications for -s, -d
    
    libiptc already supports adding and deleting multiple rules with
    different addresses, so it only needs to be wired up to the options.
    
    	# ip6tables -I INPUT -s 2001:db8::d,2001:db8::e -j DROP
    
    References: http://marc.info/?l=netfilter-devel&m=123929790719202&w=2
    
    Adjustments made: syntax, removal of unneeded variables, manpage
    adjustment, soversion bump.
    
    Signed-off-by: Jan Engelhardt <jengelh at medozas.de>
       via  add2457a23b9894905b498b13c8328f9cffcaada (commit)
       via  c284de545d03aad9a04a4e17cfb55d911a96810c (commit)
       via  f2a77520693f0a6dd1df1f87be4b81913961c1f5 (commit)
       via  9a8fc4f89ef120d7beda3724994a1544346b947d (commit)
       via  7d68df47fad305673958351a4e2a5c6e75927caa (commit)
       via  f89c1716a7743ca6e2e6164d3b64c15b2e285e1e (commit)
       via  92edcb0cf517ddb7976e396eabc7a79f8a1016ba (commit)
       via  c5e85736c207f211d82d2878a5781f512327dfce (commit)
       via  cc4344042e8c0bb6eef877975588321aa152660d (commit)
       via  332e4acc574e3a348fe611d55bf642de0d50fbda (commit)
      from  f9bf812aed50949db584cdf93752193c802fefcb (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit add2457a23b9894905b498b13c8328f9cffcaada
Author: Jan Engelhardt <jengelh at medozas.de>
Date:   Thu Jun 25 21:33:23 2009 +0200

    COMMIT_NOTES: notice to check for soversion bumps
    
    Signed-off-by: Jan Engelhardt <jengelh at medozas.de>

commit c284de545d03aad9a04a4e17cfb55d911a96810c
Author: Jan Engelhardt <jengelh at medozas.de>
Date:   Thu Jun 25 21:25:24 2009 +0200

    xtables: warn of missing version identifier in extensions
    
    Signed-off-by: Jan Engelhardt <jengelh at medozas.de>

commit f2a77520693f0a6dd1df1f87be4b81913961c1f5
Author: Jan Engelhardt <jengelh at medozas.de>
Date:   Thu Jun 25 20:12:12 2009 +0200

    extensions: collapse data variables to use multi-reg calls
    
    Signed-off-by: Jan Engelhardt <jengelh at medozas.de>

commit 9a8fc4f89ef120d7beda3724994a1544346b947d
Author: Jan Engelhardt <jengelh at medozas.de>
Date:   Thu Jun 25 17:13:46 2009 +0200

    xtables: add multi-registration functions
    
    Similar to the ones that are present in the kernel.
    
    Signed-off-by: Jan Engelhardt <jengelh at medozas.de>

commit 7d68df47fad305673958351a4e2a5c6e75927caa
Author: Jan Engelhardt <jengelh at medozas.de>
Date:   Fri Jun 12 20:59:34 2009 +0200

    extensions: remove empty help and parse functions
    
    Signed-off-by: Jan Engelhardt <jengelh at medozas.de>

commit f89c1716a7743ca6e2e6164d3b64c15b2e285e1e
Author: Jan Engelhardt <jengelh at medozas.de>
Date:   Fri Jun 12 20:48:52 2009 +0200

    iptables: allow for help-less extensions
    
    This is for extensions that do not take any options, and which
    subsequently do not offer any help text either.
    
    Signed-off-by: Jan Engelhardt <jengelh at medozas.de>

commit 92edcb0cf517ddb7976e396eabc7a79f8a1016ba
Author: Jan Engelhardt <jengelh at medozas.de>
Date:   Fri Jun 12 20:35:42 2009 +0200

    iptables: allow for parse-less extensions
    
    This means we can do some code removal in extensions.
    
    Signed-off-by: Jan Engelhardt <jengelh at medozas.de>

commit c5e85736c207f211d82d2878a5781f512327dfce
Author: Jan Engelhardt <jengelh at medozas.de>
Date:   Fri Jun 12 20:55:44 2009 +0200

    extensions: collapse registration structures
    
    There are no different code paths between IPV4 and IPV6, so
    data can be consolidated here.
    
       text    data     bss     dec     hex filename
     243757   12212    2576  258545   3f1f1 ip6tables-static[before.i586]
     243613    9428    2576  255617   3e681 ip6tables-static[after.i586]
       -144   -2784
    
    Signed-off-by: Jan Engelhardt <jengelh at medozas.de>

commit cc4344042e8c0bb6eef877975588321aa152660d
Author: Jan Engelhardt <jengelh at medozas.de>
Date:   Mon Jun 1 13:36:30 2009 +0200

    libiptc: split v4 and v6
    
    The split can save some diskspace for constrained systems running
    which are only running one protocol.
    
    Signed-off-by: Jan Engelhardt <jengelh at medozas.de>

commit 332e4acc574e3a348fe611d55bf642de0d50fbda
Author: Michael Granzow <mgranzow at zeus.com>
Date:   Thu Apr 9 18:24:36 2009 +0100

    iptables: accept multiple IP address specifications for -s, -d
    
    libiptc already supports adding and deleting multiple rules with
    different addresses, so it only needs to be wired up to the options.
    
    	# ip6tables -I INPUT -s 2001:db8::d,2001:db8::e -j DROP
    
    References: http://marc.info/?l=netfilter-devel&m=123929790719202&w=2
    
    Adjustments made: syntax, removal of unneeded variables, manpage
    adjustment, soversion bump.
    
    Signed-off-by: Jan Engelhardt <jengelh at medozas.de>

-----------------------------------------------------------------------

 COMMIT_NOTES                   |    6 +-
 Makefile.am                    |   35 ++++---
 configure.ac                   |    4 +-
 extensions/libip6t_eui64.c     |   26 -----
 extensions/libipt_MIRROR.c     |   20 ----
 extensions/libipt_addrtype.c   |   58 ++++++------
 extensions/libipt_unclean.c    |   16 ---
 extensions/libxt_CONNMARK.c    |   98 +++++++-------------
 extensions/libxt_CONNSECMARK.c |   18 +----
 extensions/libxt_DSCP.c        |   17 +---
 extensions/libxt_MARK.c        |  106 +++++++++-------------
 extensions/libxt_NFLOG.c       |   17 +---
 extensions/libxt_NFQUEUE.c     |   16 +---
 extensions/libxt_NOTRACK.c     |   33 +-------
 extensions/libxt_TCPOPTSTRIP.c |   18 +----
 extensions/libxt_TOS.c         |   76 ++++++---------
 extensions/libxt_TRACE.c       |   13 ---
 extensions/libxt_comment.c     |   17 +---
 extensions/libxt_connbytes.c   |   17 +---
 extensions/libxt_connlimit.c   |   60 ++++++------
 extensions/libxt_connmark.c    |   92 ++++++-------------
 extensions/libxt_conntrack.c   |   90 +++++++++---------
 extensions/libxt_dccp.c        |   17 +---
 extensions/libxt_dscp.c        |   17 +---
 extensions/libxt_esp.c         |   17 +---
 extensions/libxt_hashlimit.c   |  113 ++++++++++-------------
 extensions/libxt_helper.c      |   16 +---
 extensions/libxt_iprange.c     |   90 +++++++++---------
 extensions/libxt_mac.c         |   17 +---
 extensions/libxt_mark.c        |   60 ++++++------
 extensions/libxt_multiport.c   |  120 ++++++++++++-------------
 extensions/libxt_owner.c       |  106 +++++++++-------------
 extensions/libxt_physdev.c     |   17 +---
 extensions/libxt_policy.c      |   56 ++++++------
 extensions/libxt_recent.c      |   19 +----
 extensions/libxt_sctp.c        |   17 +---
 extensions/libxt_socket.c      |   20 ----
 extensions/libxt_standard.c    |   12 ---
 extensions/libxt_state.c       |   17 +---
 extensions/libxt_string.c      |   64 +++++++-------
 extensions/libxt_tcp.c         |   17 +---
 extensions/libxt_tcpmss.c      |   17 +---
 extensions/libxt_tos.c         |   76 ++++++---------
 extensions/libxt_udp.c         |   17 +---
 include/xtables.h.in           |    7 ++
 ip6tables.8.in                 |    3 +
 ip6tables.c                    |   76 ++++++++--------
 iptables.8.in                  |    7 +-
 iptables.c                     |   69 ++++++++-------
 xshared.c                      |   31 ++++++
 xshared.h                      |   10 ++
 xtables.c                      |  199 ++++++++++++++++++++++++++++++++++++++++
 52 files changed, 929 insertions(+), 1248 deletions(-)
 create mode 100644 xshared.c
 create mode 100644 xshared.h
libiptc already supports adding and deleting multiple rules with
different addresses, so it only needs to be wired up to the options.

	# ip6tables -I INPUT -s 2001:db8::d,2001:db8::e -j DROP

References: http://marc.info/?l=netfilter-devel&m=123929790719202&w=2

Adjustments made: syntax, removal of unneeded variables, manpage
adjustment, soversion bump.

Signed-off-by: Jan Engelhardt <jengelh at medozas.de>

diff --git a/configure.ac b/configure.ac
index 74c3835..bc74efe 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2,8 +2,8 @@
 AC_INIT([iptables], [1.4.4])
 
 # See libtool.info "Libtool's versioning system"
-libxtables_vcurrent=2
-libxtables_vage=0
+libxtables_vcurrent=3
+libxtables_vage=1
 
 AC_CONFIG_HEADERS([config.h])
 AC_CONFIG_MACRO_DIR([m4])
diff --git a/include/xtables.h.in b/include/xtables.h.in
index 4d4ca0a..037fae1 100644
--- a/include/xtables.h.in
+++ b/include/xtables.h.in
@@ -215,6 +215,7 @@ extern void xtables_init(void);
 extern void xtables_set_nfproto(uint8_t);
 extern void *xtables_calloc(size_t, size_t);
 extern void *xtables_malloc(size_t);
+extern void *xtables_realloc(void *, size_t);
 
 extern int xtables_insmod(const char *, const char *, bool);
 extern int xtables_load_ko(const char *, bool);
@@ -260,6 +261,8 @@ extern struct in_addr *xtables_numeric_to_ipaddr(const char *);
 extern struct in_addr *xtables_numeric_to_ipmask(const char *);
 extern void xtables_ipparse_any(const char *, struct in_addr **,
 	struct in_addr *, unsigned int *);
+extern void xtables_ipparse_multiple(const char *, struct in_addr **,
+	struct in_addr **, unsigned int *);
 
 extern struct in6_addr *xtables_numeric_to_ip6addr(const char *);
 extern const char *xtables_ip6addr_to_numeric(const struct in6_addr *);
@@ -267,6 +270,8 @@ extern const char *xtables_ip6addr_to_anyname(const struct in6_addr *);
 extern const char *xtables_ip6mask_to_numeric(const struct in6_addr *);
 extern void xtables_ip6parse_any(const char *, struct in6_addr **,
 	struct in6_addr *, unsigned int *);
+extern void xtables_ip6parse_multiple(const char *, struct in6_addr **,
+	struct in6_addr **, unsigned int *);
 
 /**
  * Print the specified value to standard output, quoting dangerous
diff --git a/ip6tables.8.in b/ip6tables.8.in
index a31887e..8037dc7 100644
--- a/ip6tables.8.in
+++ b/ip6tables.8.in
@@ -248,6 +248,9 @@ specifying the number of 1's at the left side of the network mask.
 A "!" argument before the address specification inverts the sense of
 the address. The flag \fB\-\-src\fP
 is an alias for this option.
+Multiple addresses can be specified, but this will \fBexpand to multiple
+rules\fP (when adding with \-A), or will cause multiple rules to be
+deleted (with \-D).
 .TP
 [\fB!\fP] \fB\-d\fP, \fB\-\-destination\fP \fIaddress\fP[\fB/\fP\fImask\fP]
 Destination specification. 
diff --git a/ip6tables.c b/ip6tables.c
index 35067f8..31c4b45 100644
--- a/ip6tables.c
+++ b/ip6tables.c
@@ -281,9 +281,9 @@ exit_printhelp(struct xtables_rule_match *matches)
 
 "Options:\n"
 "[!] --proto	-p proto	protocol: by number or name, eg. `tcp'\n"
-"[!] --source	-s address[/mask]\n"
+"[!] --source	-s address[/mask][,...]\n"
 "				source specification\n"
-"[!] --destination -d address[/mask]\n"
+"[!] --destination -d address[/mask][,...]\n"
 "				destination specification\n"
 "[!] --in-interface -i input name[+]\n"
 "				network interface name ([+] for wildcard)\n"
@@ -740,8 +740,10 @@ append_entry(const ip6t_chainlabel chain,
 	     struct ip6t_entry *fw,
 	     unsigned int nsaddrs,
 	     const struct in6_addr saddrs[],
+	     const struct in6_addr smasks[],
 	     unsigned int ndaddrs,
 	     const struct in6_addr daddrs[],
+	     const struct in6_addr dmasks[],
 	     int verbose,
 	     struct ip6tc_handle *handle)
 {
@@ -750,8 +752,10 @@ append_entry(const ip6t_chainlabel chain,
 
 	for (i = 0; i < nsaddrs; i++) {
 		fw->ipv6.src = saddrs[i];
+		fw->ipv6.smsk = smasks[i];
 		for (j = 0; j < ndaddrs; j++) {
 			fw->ipv6.dst = daddrs[j];
+			fw->ipv6.dmsk = dmasks[j];
 			if (verbose)
 				print_firewall_line(fw, handle);
 			ret &= ip6tc_append_entry(chain, fw, handle);
@@ -784,8 +788,10 @@ insert_entry(const ip6t_chainlabel chain,
 	     unsigned int rulenum,
 	     unsigned int nsaddrs,
 	     const struct in6_addr saddrs[],
+	     const struct in6_addr smasks[],
 	     unsigned int ndaddrs,
 	     const struct in6_addr daddrs[],
+	     const struct in6_addr dmasks[],
 	     int verbose,
 	     struct ip6tc_handle *handle)
 {
@@ -794,8 +800,10 @@ insert_entry(const ip6t_chainlabel chain,
 
 	for (i = 0; i < nsaddrs; i++) {
 		fw->ipv6.src = saddrs[i];
+		fw->ipv6.smsk = smasks[i];
 		for (j = 0; j < ndaddrs; j++) {
 			fw->ipv6.dst = daddrs[j];
+			fw->ipv6.dmsk = dmasks[j];
 			if (verbose)
 				print_firewall_line(fw, handle);
 			ret &= ip6tc_insert_entry(chain, fw, rulenum, handle);
@@ -806,7 +814,7 @@ insert_entry(const ip6t_chainlabel chain,
 }
 
 static unsigned char *
-make_delete_mask(struct ip6t_entry *fw, struct xtables_rule_match *matches)
+make_delete_mask(struct xtables_rule_match *matches)
 {
 	/* Establish mask for comparison */
 	unsigned int size;
@@ -843,8 +851,10 @@ delete_entry(const ip6t_chainlabel chain,
 	     struct ip6t_entry *fw,
 	     unsigned int nsaddrs,
 	     const struct in6_addr saddrs[],
+	     const struct in6_addr smasks[],
 	     unsigned int ndaddrs,
 	     const struct in6_addr daddrs[],
+	     const struct in6_addr dmasks[],
 	     int verbose,
 	     struct ip6tc_handle *handle,
 	     struct xtables_rule_match *matches)
@@ -853,11 +863,13 @@ delete_entry(const ip6t_chainlabel chain,
 	int ret = 1;
 	unsigned char *mask;
 
-	mask = make_delete_mask(fw, matches);
+	mask = make_delete_mask(matches);
 	for (i = 0; i < nsaddrs; i++) {
 		fw->ipv6.src = saddrs[i];
+		fw->ipv6.smsk = smasks[i];
 		for (j = 0; j < ndaddrs; j++) {
 			fw->ipv6.dst = daddrs[j];
+			fw->ipv6.dmsk = dmasks[j];
 			if (verbose)
 				print_firewall_line(fw, handle);
 			ret &= ip6tc_delete_entry(chain, fw, mask, handle);
@@ -1291,9 +1303,9 @@ int do_command6(int argc, char *argv[], char **table, struct ip6tc_handle **hand
 	int invert = 0;
 	unsigned int nsaddrs = 0, ndaddrs = 0;
 	struct in6_addr *saddrs = NULL, *daddrs = NULL;
+	struct in6_addr *smasks = NULL, *dmasks = NULL;
 
 	int c, verbose = 0;
-	unsigned i;
 	const char *chain = NULL;
 	const char *shostnetworkmask = NULL, *dhostnetworkmask = NULL;
 	const char *policy = NULL, *newname = NULL;
@@ -1811,12 +1823,12 @@ int do_command6(int argc, char *argv[], char **table, struct ip6tc_handle **hand
 	}
 
 	if (shostnetworkmask)
-		xtables_ip6parse_any(shostnetworkmask, &saddrs,
-		                         &fw.ipv6.smsk, &nsaddrs);
+		xtables_ip6parse_multiple(shostnetworkmask, &saddrs,
+					  &smasks, &nsaddrs);
 
 	if (dhostnetworkmask)
-		xtables_ip6parse_any(dhostnetworkmask, &daddrs,
-		                         &fw.ipv6.dmsk, &ndaddrs);
+		xtables_ip6parse_multiple(dhostnetworkmask, &daddrs,
+					  &dmasks, &ndaddrs);
 
 	if ((nsaddrs > 1 || ndaddrs > 1) &&
 	    (fw.ipv6.invflags & (IP6T_INV_SRCIP | IP6T_INV_DSTIP)))
@@ -1921,13 +1933,15 @@ int do_command6(int argc, char *argv[], char **table, struct ip6tc_handle **hand
 	switch (command) {
 	case CMD_APPEND:
 		ret = append_entry(chain, e,
-				   nsaddrs, saddrs, ndaddrs, daddrs,
+				   nsaddrs, saddrs, smasks,
+				   ndaddrs, daddrs, dmasks,
 				   options&OPT_VERBOSE,
 				   *handle);
 		break;
 	case CMD_DELETE:
 		ret = delete_entry(chain, e,
-				   nsaddrs, saddrs, ndaddrs, daddrs,
+				   nsaddrs, saddrs, smasks,
+				   ndaddrs, daddrs, dmasks,
 				   options&OPT_VERBOSE,
 				   *handle, matches);
 		break;
@@ -1941,7 +1955,8 @@ int do_command6(int argc, char *argv[], char **table, struct ip6tc_handle **hand
 		break;
 	case CMD_INSERT:
 		ret = insert_entry(chain, e, rulenum - 1,
-				   nsaddrs, saddrs, ndaddrs, daddrs,
+				   nsaddrs, saddrs, smasks,
+				   ndaddrs, daddrs, dmasks,
 				   options&OPT_VERBOSE,
 				   *handle);
 		break;
@@ -2001,12 +2016,10 @@ int do_command6(int argc, char *argv[], char **table, struct ip6tc_handle **hand
 		e = NULL;
 	}
 
-	for (i = 0; i < nsaddrs; i++)
-		free(&saddrs[i]);
-
-	for (i = 0; i < ndaddrs; i++)
-		free(&daddrs[i]);
-
+	free(saddrs);
+	free(smasks);
+	free(daddrs);
+	free(dmasks);
 	xtables_free_opts(1);
 
 	return ret;
diff --git a/iptables.8.in b/iptables.8.in
index 10dcb73..14fc23a 100644
--- a/iptables.8.in
+++ b/iptables.8.in
@@ -236,7 +236,7 @@ Protocol \fBall\fP
 will match with all protocols and is taken as default when this
 option is omitted.
 .TP
-[\fB!\fP] \fB\-s\fP, \fB\-\-source\fP \fIaddress\fP[\fB/\fP\fImask\fP]
+[\fB!\fP] \fB\-s\fP, \fB\-\-source\fP \fIaddress\fP[\fB/\fP\fImask\fP][\fB,\fP\fI...\fP]
 Source specification. \fIAddress\fP
 can be either a network name, a hostname (please note that specifying
 any name to be resolved with a remote query such as DNS is a really bad idea),
@@ -247,8 +247,11 @@ specifying the number of 1's at the left side of the network mask.
 Thus, a mask of \fI24\fP is equivalent to \fI255.255.255.0\fP.
 A "!" argument before the address specification inverts the sense of
 the address. The flag \fB\-\-src\fP is an alias for this option.
+Multiple addresses can be specified, but this will \fBexpand to multiple
+rules\fP (when adding with \-A), or will cause multiple rules to be
+deleted (with \-D).
 .TP
-[\fB!\fP] \fB\-d\fP, \fB\-\-destination\fP \fIaddress\fP[\fB/\fP\fImask\fP]
+[\fB!\fP] \fB\-d\fP, \fB\-\-destination\fP \fIaddress\fP[\fB/\fP\fImask\fP][\fB,\fP\fI...\fP]
 Destination specification. 
 See the description of the \fB\-s\fP
 (source) flag for a detailed description of the syntax.  The flag
diff --git a/iptables.c b/iptables.c
index 649baf4..7c075da 100644
--- a/iptables.c
+++ b/iptables.c
@@ -294,9 +294,9 @@ exit_printhelp(struct xtables_rule_match *matches)
 
 "Options:\n"
 "[!] --proto	-p proto	protocol: by number or name, eg. `tcp'\n"
-"[!] --source	-s address[/mask]\n"
+"[!] --source	-s address[/mask][...]\n"
 "				source specification\n"
-"[!] --destination -d address[/mask]\n"
+"[!] --destination -d address[/mask][...]\n"
 "				destination specification\n"
 "[!] --in-interface -i input name[+]\n"
 "				network interface name ([+] for wildcard)\n"
@@ -742,8 +742,10 @@ append_entry(const ipt_chainlabel chain,
 	     struct ipt_entry *fw,
 	     unsigned int nsaddrs,
 	     const struct in_addr saddrs[],
+	     const struct in_addr smasks[],
 	     unsigned int ndaddrs,
 	     const struct in_addr daddrs[],
+	     const struct in_addr dmasks[],
 	     int verbose,
 	     struct iptc_handle *handle)
 {
@@ -752,8 +754,10 @@ append_entry(const ipt_chainlabel chain,
 
 	for (i = 0; i < nsaddrs; i++) {
 		fw->ip.src.s_addr = saddrs[i].s_addr;
+		fw->ip.smsk.s_addr = smasks[i].s_addr;
 		for (j = 0; j < ndaddrs; j++) {
 			fw->ip.dst.s_addr = daddrs[j].s_addr;
+			fw->ip.dmsk.s_addr = dmasks[j].s_addr;
 			if (verbose)
 				print_firewall_line(fw, handle);
 			ret &= iptc_append_entry(chain, fw, handle);
@@ -786,8 +790,10 @@ insert_entry(const ipt_chainlabel chain,
 	     unsigned int rulenum,
 	     unsigned int nsaddrs,
 	     const struct in_addr saddrs[],
+	     const struct in_addr smasks[],
 	     unsigned int ndaddrs,
 	     const struct in_addr daddrs[],
+	     const struct in_addr dmasks[],
 	     int verbose,
 	     struct iptc_handle *handle)
 {
@@ -796,8 +802,10 @@ insert_entry(const ipt_chainlabel chain,
 
 	for (i = 0; i < nsaddrs; i++) {
 		fw->ip.src.s_addr = saddrs[i].s_addr;
+		fw->ip.smsk.s_addr = smasks[i].s_addr;
 		for (j = 0; j < ndaddrs; j++) {
 			fw->ip.dst.s_addr = daddrs[j].s_addr;
+			fw->ip.dmsk.s_addr = dmasks[j].s_addr;
 			if (verbose)
 				print_firewall_line(fw, handle);
 			ret &= iptc_insert_entry(chain, fw, rulenum, handle);
@@ -808,7 +816,7 @@ insert_entry(const ipt_chainlabel chain,
 }
 
 static unsigned char *
-make_delete_mask(struct ipt_entry *fw, struct xtables_rule_match *matches)
+make_delete_mask(struct xtables_rule_match *matches)
 {
 	/* Establish mask for comparison */
 	unsigned int size;
@@ -845,8 +853,10 @@ delete_entry(const ipt_chainlabel chain,
 	     struct ipt_entry *fw,
 	     unsigned int nsaddrs,
 	     const struct in_addr saddrs[],
+	     const struct in_addr smasks[],
 	     unsigned int ndaddrs,
 	     const struct in_addr daddrs[],
+	     const struct in_addr dmasks[],
 	     int verbose,
 	     struct iptc_handle *handle,
 	     struct xtables_rule_match *matches)
@@ -855,11 +865,13 @@ delete_entry(const ipt_chainlabel chain,
 	int ret = 1;
 	unsigned char *mask;
 
-	mask = make_delete_mask(fw, matches);
+	mask = make_delete_mask(matches);
 	for (i = 0; i < nsaddrs; i++) {
 		fw->ip.src.s_addr = saddrs[i].s_addr;
+		fw->ip.smsk.s_addr = smasks[i].s_addr;
 		for (j = 0; j < ndaddrs; j++) {
 			fw->ip.dst.s_addr = daddrs[j].s_addr;
+			fw->ip.dmsk.s_addr = dmasks[j].s_addr;
 			if (verbose)
 				print_firewall_line(fw, handle);
 			ret &= iptc_delete_entry(chain, fw, mask, handle);
@@ -1313,7 +1325,8 @@ int do_command(int argc, char *argv[], char **table, struct iptc_handle **handle
 	struct ipt_entry fw, *e = NULL;
 	int invert = 0;
 	unsigned int nsaddrs = 0, ndaddrs = 0;
-	struct in_addr *saddrs = NULL, *daddrs = NULL;
+	struct in_addr *saddrs = NULL, *smasks = NULL;
+	struct in_addr *daddrs = NULL, *dmasks = NULL;
 
 	int c, verbose = 0;
 	const char *chain = NULL;
@@ -1848,12 +1861,12 @@ int do_command(int argc, char *argv[], char **table, struct iptc_handle **handle
 	}
 
 	if (shostnetworkmask)
-		xtables_ipparse_any(shostnetworkmask, &saddrs,
-					&fw.ip.smsk, &nsaddrs);
+		xtables_ipparse_multiple(shostnetworkmask, &saddrs,
+					 &smasks, &nsaddrs);
 
 	if (dhostnetworkmask)
-		xtables_ipparse_any(dhostnetworkmask, &daddrs,
-					&fw.ip.dmsk, &ndaddrs);
+		xtables_ipparse_multiple(dhostnetworkmask, &daddrs,
+					 &dmasks, &ndaddrs);
 
 	if ((nsaddrs > 1 || ndaddrs > 1) &&
 	    (fw.ip.invflags & (IPT_INV_SRCIP | IPT_INV_DSTIP)))
@@ -1961,13 +1974,15 @@ int do_command(int argc, char *argv[], char **table, struct iptc_handle **handle
 	switch (command) {
 	case CMD_APPEND:
 		ret = append_entry(chain, e,
-				   nsaddrs, saddrs, ndaddrs, daddrs,
+				   nsaddrs, saddrs, smasks,
+				   ndaddrs, daddrs, dmasks,
 				   options&OPT_VERBOSE,
 				   *handle);
 		break;
 	case CMD_DELETE:
 		ret = delete_entry(chain, e,
-				   nsaddrs, saddrs, ndaddrs, daddrs,
+				   nsaddrs, saddrs, smasks,
+				   ndaddrs, daddrs, dmasks,
 				   options&OPT_VERBOSE,
 				   *handle, matches);
 		break;
@@ -1981,7 +1996,8 @@ int do_command(int argc, char *argv[], char **table, struct iptc_handle **handle
 		break;
 	case CMD_INSERT:
 		ret = insert_entry(chain, e, rulenum - 1,
-				   nsaddrs, saddrs, ndaddrs, daddrs,
+				   nsaddrs, saddrs, smasks,
+				   ndaddrs, daddrs, dmasks,
 				   options&OPT_VERBOSE,
 				   *handle);
 		break;
@@ -2042,7 +2058,9 @@ int do_command(int argc, char *argv[], char **table, struct iptc_handle **handle
 	}
 
 	free(saddrs);
+	free(smasks);
 	free(daddrs);
+	free(dmasks);
 	xtables_free_opts(1);
 
 	return ret;
diff --git a/xtables.c b/xtables.c
index e018331..05154dd 100644
--- a/xtables.c
+++ b/xtables.c
@@ -271,6 +271,18 @@ void *xtables_malloc(size_t size)
 	return p;
 }
 
+void *xtables_realloc(void *ptr, size_t size)
+{
+	void *p;
+
+	if ((p = realloc(ptr, size)) == NULL) {
+		perror("ip[6]tables: realloc failed");
+		exit(1);
+	}
+
+	return p;
+}
+
 static char *get_modprobe(void)
 {
 	int procfile;
@@ -1133,6 +1145,86 @@ static struct in_addr *parse_ipmask(const char *mask)
 	return &maskaddr;
 }
 
+void xtables_ipparse_multiple(const char *name, struct in_addr **addrpp,
+                              struct in_addr **maskpp, unsigned int *naddrs)
+{
+	struct in_addr *addrp;
+	char buf[256], *p;
+	unsigned int len, i, j, n, count = 1;
+	const char *loop = name;
+
+	while ((loop = strchr(loop, ',')) != NULL) {
+		++count;
+		++loop; /* skip ',' */
+	}
+
+	*addrpp = xtables_malloc(sizeof(struct in_addr) * count);
+	*maskpp = xtables_malloc(sizeof(struct in_addr) * count);
+
+	loop = name;
+
+	for (i = 0; i < count; ++i) {
+		if (loop == NULL)
+			break;
+		if (*loop == ',')
+			++loop;
+		if (*loop == '\0')
+			break;
+		p = strchr(loop, ',');
+		if (p != NULL)
+			len = p - loop;
+		else
+			len = strlen(loop);
+		if (len == 0 || sizeof(buf) - 1 < len)
+			break;
+
+		strncpy(buf, loop, len);
+		buf[len] = '\0';
+		loop += len;
+		if ((p = strrchr(buf, '/')) != NULL) {
+			*p = '\0';
+			addrp = parse_ipmask(p + 1);
+		} else {
+			addrp = parse_ipmask(NULL);
+		}
+		memcpy(*maskpp + i, addrp, sizeof(*addrp));
+
+		/* if a null mask is given, the name is ignored, like in "any/0" */
+		if ((*maskpp + i)->s_addr == 0)
+			/*
+			 * A bit pointless to process multiple addresses
+			 * in this case...
+			 */
+			strcpy(buf, "0.0.0.0");
+
+		addrp = ipparse_hostnetwork(buf, &n);
+		if (n > 1) {
+			count += n - 1;
+			*addrpp = xtables_realloc(*addrpp,
+			          sizeof(struct in_addr) * count);
+			*maskpp = xtables_realloc(*maskpp,
+			          sizeof(struct in_addr) * count);
+			for (j = 0; j < n; ++j)
+				/* for each new addr */
+				memcpy(*addrpp + i + j, addrp + j,
+				       sizeof(*addrp));
+			for (j = 1; j < n; ++j)
+				/* for each new mask */
+				memcpy(*maskpp + i + j, *maskpp + i,
+				       sizeof(*addrp));
+			i += n - 1;
+		} else {
+			memcpy(*addrpp + i, addrp, sizeof(*addrp));
+		}
+		/* free what ipparse_hostnetwork had allocated: */
+		free(addrp);
+	}
+	*naddrs = count;
+	for (i = 0; i < n; ++i)
+		(*addrpp+i)->s_addr &= (*maskpp+i)->s_addr;
+}
+
+
 /**
  * xtables_ipparse_any - transform arbitrary name to in_addr
  *
@@ -1364,6 +1456,89 @@ static struct in6_addr *parse_ip6mask(char *mask)
 	return &maskaddr;
 }
 
+void
+xtables_ip6parse_multiple(const char *name, struct in6_addr **addrpp,
+		      struct in6_addr **maskpp, unsigned int *naddrs)
+{
+	struct in6_addr *addrp;
+	char buf[256], *p;
+	unsigned int len, i, j, n, count = 1;
+	const char *loop = name;
+
+	while ((loop = strchr(loop, ',')) != NULL) {
+		++count;
+		++loop; /* skip ',' */
+	}
+
+	*addrpp = xtables_malloc(sizeof(struct in6_addr) * count);
+	*maskpp = xtables_malloc(sizeof(struct in6_addr) * count);
+
+	loop = name;
+
+	for (i = 0; i < count /*NB: count can grow*/; ++i) {
+		if (loop == NULL)
+			break;
+		if (*loop == ',')
+			++loop;
+		if (*loop == '\0')
+			break;
+		p = strchr(loop, ',');
+		if (p != NULL)
+			len = p - loop;
+		else
+			len = strlen(loop);
+		if (len == 0 || sizeof(buf) - 1 < len)
+			break;
+
+		strncpy(buf, loop, len);
+		buf[len] = '\0';
+		loop += len;
+		if ((p = strrchr(buf, '/')) != NULL) {
+			*p = '\0';
+			addrp = parse_ip6mask(p + 1);
+		} else {
+			addrp = parse_ip6mask(NULL);
+		}
+		memcpy(*maskpp + i, addrp, sizeof(*addrp));
+
+		/* if a null mask is given, the name is ignored, like in "any/0" */
+		if (memcmp(*maskpp + i, &in6addr_any, sizeof(in6addr_any)) == 0)
+			strcpy(buf, "::");
+
+		addrp = ip6parse_hostnetwork(buf, &n);
+		/* ip6parse_hostnetwork only ever returns one IP
+		address (it exits if the resolution fails).
+		Therefore, n will always be 1 here.  Leaving the
+		code below in anyway in case ip6parse_hostnetwork
+		is improved some day to behave like
+		ipparse_hostnetwork: */
+		if (n > 1) {
+			count += n - 1;
+			*addrpp = xtables_realloc(*addrpp,
+			          sizeof(struct in6_addr) * count);
+			*maskpp = xtables_realloc(*maskpp,
+			          sizeof(struct in6_addr) * count);
+			for (j = 0; j < n; ++j)
+				/* for each new addr */
+				memcpy(*addrpp + i + j, addrp + j,
+				       sizeof(*addrp));
+			for (j = 1; j < n; ++j)
+				/* for each new mask */
+				memcpy(*maskpp + i + j, *maskpp + i,
+				       sizeof(*addrp));
+			i += n - 1;
+		} else {
+			memcpy(*addrpp + i, addrp, sizeof(*addrp));
+		}
+		/* free what ip6parse_hostnetwork had allocated: */
+		free(addrp);
+	}
+	*naddrs = count;
+	for (i = 0; i < n; ++i)
+		for (j = 0; j < 4; ++j)
+			(*addrpp+i)->s6_addr32[j] &= (*maskpp+i)->s6_addr32[j];
+}
+
 void xtables_ip6parse_any(const char *name, struct in6_addr **addrpp,
                           struct in6_addr *maskp, unsigned int *naddrs)
 {



More information about the netfilter-cvslog mailing list