Re: [NETFILTER]: Deploy a prefix length to network mask mapping table

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Mar 3 2008 03:52, Pablo Neira Ayuso wrote:
>Jan Engelhardt wrote:
>> On Feb 21 2008 16:38, Jan Engelhardt wrote:
>>> this is now the proposed memory reduction of xt_conntrack as previously 
>>> mentioned in http://marc.info/?l=netfilter-devel&m=120334779109237&w=2 .
>>>
>>> Since xt_conntrack r1 is new, we can still modify it.
>>>
>>> ===
>>> commit 84622a5c5190ea1bf0a37695961714a04a99a9c0
>>> Author: Jan Engelhardt <jengelh@xxxxxxxxxxxxxxx>
>>> Date:   Thu Feb 21 16:33:32 2008 +0100
>>>
>>>    [NETFILTER]: Deploy a prefix length to network mask mapping table
>>>    
>>>    Userspace utilities commonly transform a prefix length (CIDR notation
>>>    like 192.168.222.1/32) into a full netmask before submitting it to
>>>    the kernel.
>>>    
>>>    The size of struct xt_conntrack_mtinfo1 is currently 152 bytes, of
>>>    which 64 bytes are for masks. By submitting prefix lengths to the
>>>    kernel, we can save 60 bytes (almost 40%) as prefix lengths can fit
>>>    into one uint8_t. Since we do not want to recompute the mask for each
>>>    invocation of the match function, a static translation table will be
>>>    used (net/core/pfxlen.c).
>>>    
>>>    The patch also removes xt_hashlimit's obsolete mask computation.
>> 
>> 
>> Can we merge this while r1 is not yet used by userspace?
>> If not, that's fine too, will queue it for 2.6.26.
>
>Attention, I'm about to release iptables-1.4.1 which includes the
>userspace part for this. I can still delay it a couple of days and
>rework the release tarball if you pass me the userspace part asap.

commit 55ad85c12405b61b8c3c082888c75d1559a93c1e
Author: Jan Engelhardt <jengelh@xxxxxxxxxxxxxxx>
Date:   Tue Feb 19 23:47:31 2008 +0100

    Reduce size of struct xt_conntrack_mtinfo1
    
    Reduce size of struct xt_conntrack_mtinfo1 by sending the prefix
    length to kernel-space and let it do a lookup to full IPv6 mask there.
    
    Signed-off-by: Jan Engelhardt <jengelh@xxxxxxxxxxxxxxx>

diff --git a/extensions/libxt_conntrack.c b/extensions/libxt_conntrack.c
index d1c0aa0..d459611 100644
--- a/extensions/libxt_conntrack.c
+++ b/extensions/libxt_conntrack.c
@@ -548,63 +548,41 @@ conntrack_mt4_parse(int c, char **argv, int invert, unsigned int *flags,
                     const void *entry, struct xt_entry_match **match)
 {
 	struct xt_conntrack_mtinfo1 *info = (void *)(*match)->data;
-	struct in_addr *addr = NULL;
-	unsigned int naddrs = 0;
+	unsigned int pfx;
 
 	switch (c) {
 	case '3': /* --ctorigsrc */
-		ipparse_hostnetworkmask(optarg, &addr, &info->origsrc_mask.in,
-		                        &naddrs);
-		if (naddrs > 1)
-			exit_error(PARAMETER_PROBLEM,
-			           "multiple IP addresses not allowed");
-		if (naddrs == 1)
-			memcpy(&info->origsrc_addr.in, addr, sizeof(*addr));
+		ipparse_hostnetworkpfx(optarg, &info->origsrc_addr, &pfx);
+		info->origsrc_pfx  = pfx;
 		info->match_flags |= XT_CONNTRACK_ORIGSRC;
 		if (invert)
 			info->invert_flags |= XT_CONNTRACK_ORIGSRC;
 		break;
 
 	case '4': /* --ctorigdst */
-		ipparse_hostnetworkmask(optarg, &addr, &info->origdst_mask.in,
-		                        &naddrs);
-		if (naddrs > 1)
-			exit_error(PARAMETER_PROBLEM,
-			           "multiple IP addresses not allowed");
-		if (naddrs == 1)
-			memcpy(&info->origdst_addr.in, addr, sizeof(*addr));
+		ipparse_hostnetworkpfx(optarg, &info->origdst_addr, &pfx);
+		info->origdst_pfx  = pfx;
 		info->match_flags |= XT_CONNTRACK_ORIGDST;
 		if (invert)
 			info->invert_flags |= XT_CONNTRACK_ORIGDST;
 		break;
 
 	case '5': /* --ctreplsrc */
-		ipparse_hostnetworkmask(optarg, &addr, &info->replsrc_mask.in,
-		                        &naddrs);
-		if (naddrs > 1)
-			exit_error(PARAMETER_PROBLEM,
-			           "multiple IP addresses not allowed");
-		if (naddrs == 1)
-			memcpy(&info->replsrc_addr.in, addr, sizeof(*addr));
+		ipparse_hostnetworkpfx(optarg, &info->replsrc_addr, &pfx);
+		info->replsrc_pfx  = pfx;
 		info->match_flags |= XT_CONNTRACK_REPLSRC;
 		if (invert)
 			info->invert_flags |= XT_CONNTRACK_REPLSRC;
 		break;
 
 	case '6': /* --ctrepldst */
-		ipparse_hostnetworkmask(optarg, &addr, &info->repldst_mask.in,
-		                        &naddrs);
-		if (naddrs > 1)
-			exit_error(PARAMETER_PROBLEM,
-			           "multiple IP addresses not allowed");
-		if (naddrs == 1)
-			memcpy(&info->repldst_addr.in, addr, sizeof(*addr));
+		ipparse_hostnetworkpfx(optarg, &info->repldst_addr, &pfx);
+		info->repldst_pfx  = pfx;
 		info->match_flags |= XT_CONNTRACK_REPLDST;
 		if (invert)
 			info->invert_flags |= XT_CONNTRACK_REPLDST;
 		break;
 
-
 	default:
 		return conntrack_mt_parse(c, argv, invert, flags, match);
 	}
@@ -618,63 +596,41 @@ conntrack_mt6_parse(int c, char **argv, int invert, unsigned int *flags,
                     const void *entry, struct xt_entry_match **match)
 {
 	struct xt_conntrack_mtinfo1 *info = (void *)(*match)->data;
-	struct in6_addr *addr = NULL;
-	unsigned int naddrs = 0;
+	unsigned int pfx;
 
 	switch (c) {
 	case '3': /* --ctorigsrc */
-		ip6parse_hostnetworkmask(optarg, &addr,
-		                         &info->origsrc_mask.in6, &naddrs);
-		if (naddrs > 1)
-			exit_error(PARAMETER_PROBLEM,
-			           "multiple IP addresses not allowed");
-		if (naddrs == 1)
-			memcpy(&info->origsrc_addr.in6, addr, sizeof(*addr));
+		ip6parse_hostnetworkpfx(optarg, &info->origsrc_addr, &pfx);
+		info->origsrc_pfx  = pfx;
 		info->match_flags |= XT_CONNTRACK_ORIGSRC;
 		if (invert)
 			info->invert_flags |= XT_CONNTRACK_ORIGSRC;
 		break;
 
 	case '4': /* --ctorigdst */
-		ip6parse_hostnetworkmask(optarg, &addr,
-		                         &info->origdst_mask.in6, &naddrs);
-		if (naddrs > 1)
-			exit_error(PARAMETER_PROBLEM,
-			           "multiple IP addresses not allowed");
-		if (naddrs == 1)
-			memcpy(&info->origdst_addr.in, addr, sizeof(*addr));
+		ip6parse_hostnetworkpfx(optarg, &info->origdst_addr, &pfx);
+		info->origdst_pfx  = pfx;
 		info->match_flags |= XT_CONNTRACK_ORIGDST;
 		if (invert)
 			info->invert_flags |= XT_CONNTRACK_ORIGDST;
 		break;
 
 	case '5': /* --ctreplsrc */
-		ip6parse_hostnetworkmask(optarg, &addr,
-		                         &info->replsrc_mask.in6, &naddrs);
-		if (naddrs > 1)
-			exit_error(PARAMETER_PROBLEM,
-			           "multiple IP addresses not allowed");
-		if (naddrs == 1)
-			memcpy(&info->replsrc_addr.in, addr, sizeof(*addr));
+		ip6parse_hostnetworkpfx(optarg, &info->replsrc_addr, &pfx);
+		info->replsrc_pfx  = pfx;
 		info->match_flags |= XT_CONNTRACK_REPLSRC;
 		if (invert)
 			info->invert_flags |= XT_CONNTRACK_REPLSRC;
 		break;
 
 	case '6': /* --ctrepldst */
-		ip6parse_hostnetworkmask(optarg, &addr,
-		                         &info->repldst_mask.in6, &naddrs);
-		if (naddrs > 1)
-			exit_error(PARAMETER_PROBLEM,
-			           "multiple IP addresses not allowed");
-		if (naddrs == 1)
-			memcpy(&info->repldst_addr.in, addr, sizeof(*addr));
+		ip6parse_hostnetworkpfx(optarg, &info->repldst_addr, &pfx);
+		info->repldst_pfx  = pfx;
 		info->match_flags |= XT_CONNTRACK_REPLDST;
 		if (invert)
 			info->invert_flags |= XT_CONNTRACK_REPLDST;
 		break;
 
-
 	default:
 		return conntrack_mt_parse(c, argv, invert, flags, match);
 	}
@@ -753,23 +709,26 @@ print_status(unsigned int statusmask)
 }
 
 static void
-conntrack_dump_addr(const union nf_inet_addr *addr,
-                    const union nf_inet_addr *mask,
+conntrack_dump_addr(const union nf_inet_addr *addr, unsigned int prefix,
                     unsigned int family, bool numeric)
 {
 	if (family == AF_INET) {
-		if (!numeric && addr->ip == 0) {
+		if (numeric)
+			printf("%s/%u ", ipaddr_to_numeric(&addr->in), prefix);
+		else if (addr->ip == 0)
 			printf("anywhere ");
-			return;
-		}
-		printf("%s ", ipaddr_to_anyname(&addr->in));
+		else
+			printf("%s/%u ", ipaddr_to_anyname(&addr->in), prefix);
 	} else if (family == AF_INET6) {
-		if (!numeric && addr->ip6[0] == 0 && addr->ip6[1] == 0 &&
-		    addr->ip6[2] == 0 && addr->ip6[3] == 0) {
+		if (numeric)
+			printf("%s/%u ", ip6addr_to_numeric(&addr->in6),
+			       prefix);
+		else if ((addr->ip6[0] | addr->ip6[1] | addr->ip6[2] |
+		    addr->ip6[3]) == 0)
 			printf("anywhere ");
-			return;
-		}
-		printf("%s ", ip6addr_to_anyname(&addr->in6));
+		else
+			printf("%s/%u ", ip6addr_to_anyname(&addr->in6),
+			       prefix);
 	}
 }
 
@@ -901,7 +860,7 @@ conntrack_dump(const struct xt_conntrack_mtinfo1 *info, const char *prefix,
 		if (info->invert_flags & XT_CONNTRACK_PROTO)
 			printf("! ");
 		printf("%sctorigsrc ", prefix);
-		conntrack_dump_addr(&info->origsrc_addr, &info->origsrc_mask,
+		conntrack_dump_addr(&info->origsrc_addr, info->origsrc_pfx,
 		                    family, numeric);
 	}
 
@@ -909,7 +868,7 @@ conntrack_dump(const struct xt_conntrack_mtinfo1 *info, const char *prefix,
 		if (info->invert_flags & XT_CONNTRACK_PROTO)
 			printf("! ");
 		printf("%sctorigdst ", prefix);
-		conntrack_dump_addr(&info->origdst_addr, &info->origdst_mask,
+		conntrack_dump_addr(&info->origdst_addr, info->origdst_pfx,
 		                    family, numeric);
 	}
 
@@ -917,7 +876,7 @@ conntrack_dump(const struct xt_conntrack_mtinfo1 *info, const char *prefix,
 		if (info->invert_flags & XT_CONNTRACK_PROTO)
 			printf("! ");
 		printf("%sctreplsrc ", prefix);
-		conntrack_dump_addr(&info->replsrc_addr, &info->replsrc_mask,
+		conntrack_dump_addr(&info->replsrc_addr, info->replsrc_pfx,
 		                    family, numeric);
 	}
 
@@ -925,7 +884,7 @@ conntrack_dump(const struct xt_conntrack_mtinfo1 *info, const char *prefix,
 		if (info->invert_flags & XT_CONNTRACK_PROTO)
 			printf("! ");
 		printf("%sctrepldst ", prefix);
-		conntrack_dump_addr(&info->repldst_addr, &info->repldst_mask,
+		conntrack_dump_addr(&info->repldst_addr, info->repldst_pfx,
 		                    family, numeric);
 	}
 
diff --git a/include/linux/netfilter/xt_conntrack.h b/include/linux/netfilter/xt_conntrack.h
index 9e35ccd..d787786 100644
--- a/include/linux/netfilter/xt_conntrack.h
+++ b/include/linux/netfilter/xt_conntrack.h
@@ -68,16 +68,18 @@ struct xt_conntrack_info
 };
 
 struct xt_conntrack_mtinfo1 {
-	union nf_inet_addr origsrc_addr, origsrc_mask;
-	union nf_inet_addr origdst_addr, origdst_mask;
-	union nf_inet_addr replsrc_addr, replsrc_mask;
-	union nf_inet_addr repldst_addr, repldst_mask;
+	union nf_inet_addr origsrc_addr;
+	union nf_inet_addr origdst_addr;
+	union nf_inet_addr replsrc_addr;
+	union nf_inet_addr repldst_addr;
 	u_int32_t expires_min, expires_max;
 	u_int16_t l4proto;
-	u_int16_t origsrc_port, origdst_port;
-	u_int16_t replsrc_port, repldst_port;
+	__be16 origsrc_port, origdst_port;
+	__be16 replsrc_port, repldst_port;
 	u_int16_t match_flags, invert_flags;
 	u_int8_t state_mask, status_mask;
+	u_int8_t origsrc_pfx, origdst_pfx;
+	u_int8_t replsrc_pfx, repldst_pfx;
 };
 
 #endif /*_XT_CONNTRACK_H*/
diff --git a/include/xtables.h b/include/xtables.h
index 484e436..7a25b59 100644
--- a/include/xtables.h
+++ b/include/xtables.h
@@ -171,6 +171,8 @@ struct xtables_target
 #endif
 };
 
+union nf_inet_addr;
+
 extern char *lib_dir;
 
 extern void *fw_calloc(size_t count, size_t size);
@@ -241,6 +243,8 @@ extern const char *ipaddr_to_anyname(const struct in_addr *);
 extern const char *ipmask_to_numeric(const struct in_addr *);
 extern struct in_addr *numeric_to_ipaddr(const char *);
 extern struct in_addr *numeric_to_ipmask(const char *);
+extern void ipparse_hostnetworkpfx(const char *, union nf_inet_addr *,
+	unsigned int *);
 extern void ipparse_hostnetworkmask(const char *, struct in_addr **,
 	struct in_addr *, unsigned int *);
 
@@ -248,6 +252,8 @@ extern struct in6_addr *numeric_to_ip6addr(const char *);
 extern const char *ip6addr_to_numeric(const struct in6_addr *);
 extern const char *ip6addr_to_anyname(const struct in6_addr *);
 extern const char *ip6mask_to_numeric(const struct in6_addr *);
+extern void ip6parse_hostnetworkpfx(const char *, union nf_inet_addr *,
+	unsigned int *);
 extern void ip6parse_hostnetworkmask(const char *, struct in6_addr **,
 	struct in6_addr *, unsigned int *);
 
diff --git a/xtables.c b/xtables.c
index af4d3dc..4a9bedd 100644
--- a/xtables.c
+++ b/xtables.c
@@ -32,6 +32,7 @@
 #include <arpa/inet.h>
 
 #include <xtables.h>
+#include <linux/netfilter.h>
 
 #ifndef NO_SHARED_LIBS
 #include <dlfcn.h>
@@ -909,6 +910,36 @@ static struct in_addr *parse_ipmask(const char *mask)
 	return &maskaddr;
 }
 
+void ipparse_hostnetworkpfx(const char *name, union nf_inet_addr *addrp,
+                            unsigned int *maskp)
+{
+	unsigned int naddrs = 0;
+	struct in_addr *res;
+	char buf[256], *p;
+
+	strncpy(buf, name, sizeof(buf) - 1);
+	if ((p = strchr(buf, '/')) != NULL) {
+		*p = '\0';
+		if (!strtonum(p + 1, NULL, maskp, 0, 32))
+			exit_error(PARAMETER_PROBLEM, "Invalid mask");
+	} else {
+		*maskp = 32;
+	}
+
+	/* if a null mask is given, the name is ignored, like in "any/0" */
+	if (*maskp == 0)
+		strcpy(buf, "0.0.0.0");
+
+	res = ipparse_hostnetwork(buf, &naddrs);
+	if (naddrs == 0)
+		exit_error(PARAMETER_PROBLEM, "%s did not resolve to an address", name);
+	if (naddrs > 1)
+		exit_error(PARAMETER_PROBLEM, "%s resolved to more than one address", name);
+
+	memcpy(&addrp->in, res, sizeof(struct in_addr));
+	free(res);
+}
+
 void ipparse_hostnetworkmask(const char *name, struct in_addr **addrpp,
                              struct in_addr *maskp, unsigned int *naddrs)
 {
@@ -1133,6 +1164,36 @@ static struct in6_addr *parse_ip6mask(char *mask)
 	return &maskaddr;
 }
 
+void ip6parse_hostnetworkpfx(const char *name, union nf_inet_addr *addrp,
+                             unsigned int *maskp)
+{
+	unsigned int naddrs = 0;
+	struct in6_addr *res;
+	char buf[256], *p;
+
+	strncpy(buf, name, sizeof(buf) - 1);
+	if ((p = strchr(buf, '/')) != NULL) {
+		*p = '\0';
+		if (!strtonum(p + 1, NULL, maskp, 0, 128))
+			exit_error(PARAMETER_PROBLEM, "Invalid mask");
+	} else {
+		*maskp = 128;
+	}
+
+	/* if a null mask is given, the name is ignored, like in "any/0" */
+	if (*maskp == 0)
+		strcpy(buf, "::");
+
+	res = ip6parse_hostnetwork(buf, &naddrs);
+	if (naddrs == 0)
+		exit_error(PARAMETER_PROBLEM, "%s did not resolve to an address", name);
+	if (naddrs > 1)
+		exit_error(PARAMETER_PROBLEM, "%s resolved to more than one address", name);
+
+	memcpy(&addrp->in6, res, sizeof(struct in6_addr));
+	free(res);
+}
+
 void ip6parse_hostnetworkmask(const char *name, struct in6_addr **addrpp,
                               struct in6_addr *maskp, unsigned int *naddrs)
 {


--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Netfitler Users]     [LARTC]     [Bugtraq]     [Yosemite Forum]

  Powered by Linux