Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 17 Aug 2009 09:19:40 GMT
From:      Marta Carbone <marta@FreeBSD.org>
To:        Perforce Change Reviews <perforce@FreeBSD.org>
Subject:   PERFORCE change 167434 for review
Message-ID:  <200908170919.n7H9JedE027727@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=167434

Change 167434 by marta@marta_onelab1 on 2009/08/17 09:19:25

	Split the rules listing in two separated requests.

Affected files ...

.. //depot/projects/soc2009/marta_ipfw/src/sbin/ipfw/ipfw2.c#3 edit
.. //depot/projects/soc2009/marta_ipfw/src/sbin/ipfw/ipfw2.h#3 edit
.. //depot/projects/soc2009/marta_ipfw/src/sys/netinet/in.h#2 edit
.. //depot/projects/soc2009/marta_ipfw/src/sys/netinet/ipfw/ip_fw2.c#3 edit
.. //depot/projects/soc2009/marta_ipfw/src/sys/netinet/raw_ip.c#2 edit

Differences ...

==== //depot/projects/soc2009/marta_ipfw/src/sbin/ipfw/ipfw2.c#3 (text+ko) ====

@@ -357,7 +357,8 @@
 	if (s < 0)
 		err(EX_UNAVAILABLE, "socket");
 
-	if (optname == IP_FW_GET || optname == IP_DUMMYNET_GET ||
+	if (optname == IP_FW_GET || optname == IP_FW_DYN_GET ||
+	    optname == IP_DUMMYNET_GET ||
 	    optname == IP_FW_ADD || optname == IP_FW_TABLE_LIST ||
 	    optname == IP_FW_TABLE_GETSIZE || 
 	    optname == IP_FW_NAT_GET_CONFIG || 
@@ -1727,19 +1728,17 @@
  *
  * In case of success EX_OK is returned.
  */
+/* decompile static rules */
 int
-ipfw_list_decompile(void *data, int nbytes, struct sbuf *out, struct cmdline_opts *co)
+decompile_static_rules(void *data, int nbytes, struct sbuf *out, struct cmdline_opts *co)
 {
 	struct ip_fw *r;
-	ipfw_dyn_rule *dynrules, *d;
 	int exitval = EX_OK;
 
 	char *lim;
 	int bcwidth, n, pcwidth, width;
 	int nstat;		/* number of static rules */
-	int ndyn;		/* number of dynamic rules */
 	int seen = 0;		/* flag for rules presence */
-	uint8_t set;
 
 	if (co->do_pipe) {
 		ipfw_list_pipes(data, nbytes, out, co);
@@ -1756,15 +1755,6 @@
 		    ++nstat, r = NEXT(r) )
 		; /* nothing */
 
-	/*
-	 * Count dynamic rules. This is easier as they have
-	 * fixed size.
-	 */
-	r = NEXT(r);
-	dynrules = (ipfw_dyn_rule *)r ;
-	n = (char *)r - (char *)data;
-	ndyn = (nbytes - n) / sizeof *dynrules;
-
 	/* if showing stats, figure out column widths ahead of time */
 	bcwidth = pcwidth = 0;
 	if (co->do_acct) {
@@ -1786,27 +1776,7 @@
 				bcwidth = width;
 		}
 	}
-	if (co->do_dynamic && ndyn) {
-		for (n = 0, d = dynrules; n < ndyn; n++, d++) {
-			if (co->use_set) {
-				/* skip rules from another set */
-				bcopy((char *)&d->rule + sizeof(uint16_t),
-				      &set, sizeof(uint8_t));
-				if (set != co->use_set - 1)
-					continue;
-			}
-			width = snprintf(NULL, 0, "%llu",
-			    align_uint64(&d->pcnt));
-			if (width > pcwidth)
-				pcwidth = width;
 
-			width = snprintf(NULL, 0, "%llu",
-			    align_uint64(&d->bcnt));
-			if (width > bcwidth)
-				bcwidth = width;
-		}
-	}
-
 	/* show static rules */
 	for (n = 0, r = data; n < nstat; n++, r = NEXT(r)) {
 		/* skip boundaries */
@@ -1833,30 +1803,75 @@
 			warnx("rules %lu-%lu does not exist", co->first, co->last);
 	}
 
-	/* show dynamic rules */
-	if (co->do_dynamic && ndyn) {
-		sbuf_printf(out, "## Dynamic rules (%d):\n", ndyn);
+#undef NEXT
+
+	return exitval;
+}
+
+/* decompile dynamic rules */
+int
+decompile_dynamic_rules(void *data, int nbytes, struct sbuf *out, struct cmdline_opts *co)
+{
+	struct ip_fw *r = data;
+	ipfw_dyn_rule *dynrules, *d;
+	int exitval = EX_OK;
+
+	int bcwidth, n, pcwidth, width;
+	int ndyn;		/* number of dynamic rules */
+	uint8_t set;
+
+	/*
+	 * Count dynamic rules. This is easier as they have
+	 * fixed size.
+	 */
+	dynrules = (ipfw_dyn_rule *)r ;
+	ndyn = nbytes / sizeof *dynrules;
+
+	if (ndyn == 0)
+		return exitval;
+
+        /* if showing stats, figure out column widths ahead of time */
 
-		for (n = 0, d = dynrules; n < ndyn; n++, d++) {
-			/* skip boundaries */
-			if (r->rulenum < co->first)
+        bcwidth = pcwidth = 0;
+	for (n = 0, d = dynrules; n < ndyn; n++, d++) {
+		if (co->use_set) {
+			/* skip rules from another set */
+			bcopy((char *)&d->rule + sizeof(uint16_t),
+			      &set, sizeof(uint8_t));
+			if (set != co->use_set - 1)
 				continue;
-			if (r->rulenum > co->last)
-				break;
+		}
+		width = snprintf(NULL, 0, "%llu",
+		    align_uint64(&d->pcnt));
+		if (width > pcwidth)
+			pcwidth = width;
+
+		width = snprintf(NULL, 0, "%llu",
+		    align_uint64(&d->bcnt));
+		if (width > bcwidth)
+			bcwidth = width;
+	}
+
+	/* show dynamic rules */
+	sbuf_printf(out, "## Dynamic rules (%d):\n", ndyn);
 
-			if (co->use_set) {
-				bcopy((char *)&d->rule + sizeof(uint16_t),
-					      &set, sizeof(uint8_t));
-				if (set != co->use_set - 1)
-					continue;
-			}
+	for (n = 0, d = dynrules; n < ndyn; n++, d++) {
+		/* skip boundaries */
+		if (r->rulenum < co->first)
+			continue;
+		if (r->rulenum > co->last)
+			break;
 
-			show_dyn_ipfw(d, pcwidth, bcwidth, out, co);
+		if (co->use_set) {
+			bcopy((char *)&d->rule + sizeof(uint16_t),
+				      &set, sizeof(uint8_t));
+			if (set != co->use_set - 1)
+				continue;
 		}
+
+		show_dyn_ipfw(d, pcwidth, bcwidth, out, co);
 	}
 
-#undef NEXT
-
 	return exitval;
 }
 
@@ -1867,7 +1882,7 @@
 	void *data = NULL;
 	int nbytes;
 
-	const int ocmd = co->do_pipe ? IP_DUMMYNET_GET : IP_FW_GET;
+	int ocmd = IP_FW_GET;	/* default command is request static rules */
 	int nalloc = 1024;	/* start somewhere... */
 
 	if (co->test_only) {
@@ -1875,6 +1890,12 @@
 		return;
 	}
 
+	/* get pipes or dynamic rules according command options */
+	if (co->do_pipe)
+		ocmd = IP_DUMMYNET_GET;
+	else if (co->do_dynamic)
+		ocmd = IP_FW_DYN_GET;
+
 	ac--;
 	av++;
 
@@ -1890,7 +1911,10 @@
 				co->do_pipe ? "DUMMYNET" : "FW");
 	}
 
-	exitval = ipfw_list_decompile(data, nbytes, out, co);
+	if (co->do_dynamic)
+		exitval = decompile_dynamic_rules(data, nbytes, out, co);
+	else
+		exitval = decompile_static_rules(data, nbytes, out, co);
 
         /* free resources */
 	free(data);

==== //depot/projects/soc2009/marta_ipfw/src/sbin/ipfw/ipfw2.h#3 (text+ko) ====

@@ -20,6 +20,8 @@
  * $FreeBSD: src/sbin/ipfw/ipfw2.h,v 1.9 2009/06/24 22:57:07 oleg Exp $
  */
 
+#include <netinet/in.h>
+
 /*
  * Options that can be set on the command line.
  * When reading commands from a file, a subset of the options can also
@@ -262,7 +264,8 @@
 extern void ipfw_add_compile_str(char *cmdstr, uint32_t *rulebuf, int *rulesize);
 struct ip_fw;
 extern void decompile_rule(struct ip_fw *rule, int pcwidth, int bcwidth, struct sbuf *out, struct cmdline_opts *co);
-extern int ipfw_list_decompile(void *data, int nbytes, struct sbuf *out, struct cmdline_opts *co);
+extern int decompile_static_rules(void *data, int nbytes, struct sbuf *out, struct cmdline_opts *co);
+extern int decompile_dynamic_rules(void *data, int nbytes, struct sbuf *out, struct cmdline_opts *co);
 
 /* convert a rule in ac, av format, as required by the internal compilation process */
 extern char **strtoargs(char *arg, int *ac);

==== //depot/projects/soc2009/marta_ipfw/src/sys/netinet/in.h#2 (text+ko) ====

@@ -443,6 +443,7 @@
 #define	IP_ONESBCAST		23   /* bool: send all-ones broadcast */
 #define	IP_BINDANY		24   /* bool: allow bind to any address */
 
+#define	IP_FW_DYN_GET		39   /* get dynamic rule chain */
 #define	IP_FW_TABLE_ADD		40   /* add entry */
 #define	IP_FW_TABLE_DEL		41   /* delete entry */
 #define	IP_FW_TABLE_FLUSH	42   /* flush table */
@@ -453,7 +454,7 @@
 #define	IP_FW_DEL		51   /* delete a firewall rule from chain */
 #define	IP_FW_FLUSH		52   /* flush firewall rule chain */
 #define	IP_FW_ZERO		53   /* clear single/all firewall counter(s) */
-#define	IP_FW_GET		54   /* get entire firewall rule chain */
+#define	IP_FW_GET		54   /* get static rule chain */
 #define	IP_FW_RESETLOG		55   /* reset logging counters */
 
 #define IP_FW_NAT_CFG           56   /* add/config a nat rule */

==== //depot/projects/soc2009/marta_ipfw/src/sys/netinet/ipfw/ip_fw2.c#3 (text+ko) ====

@@ -4644,7 +4644,7 @@
 }
 
 /*
- * Copy the static and dynamic rules to the supplied buffer
+ * Copy the static rules to the supplied buffer
  * and return the amount of space actually used.
  */
 static size_t
@@ -4683,6 +4683,23 @@
 		}
 	}
 	IPFW_RUNLOCK(chain);
+	return (bp - (char *)buf);
+}
+
+/*
+ * Copy the dynamic rules to the supplied buffer
+ * and return the amount of space actually used.
+ */
+static size_t
+ipfw_getdynrules(struct ip_fw_chain *chain, void *buf, size_t space)
+{
+	char *bp = buf;
+	char *ep = bp + space;
+	int i;
+	time_t	boot_seconds;
+
+        boot_seconds = boottime.tv_sec;
+	/* XXX this can take a long time and locking will block packet flow */
 	if (V_ipfw_dyn_v) {
 		ipfw_dyn_rule *p, *last = NULL;
 
@@ -4724,7 +4741,6 @@
 	return (bp - (char *)buf);
 }
 
-
 /**
  * {set|get}sockopt parser.
  */
@@ -4733,7 +4749,7 @@
 {
 #define	RULE_MAXSIZE	(256*sizeof(u_int32_t))
 	int error;
-	size_t size;
+	size_t size = 0;
 	struct ip_fw *buf, *rule;
 	u_int32_t rulenum[2];
 
@@ -4757,10 +4773,8 @@
 	switch (sopt->sopt_name) {
 	case IP_FW_GET:
 		/*
-		 * pass up a copy of the current rules. Static rules
-		 * come first (the last of which has number IPFW_DEFAULT_RULE),
-		 * followed by a possibly empty list of dynamic rule.
-		 * The last dynamic rule has NULL in the "next" field.
+		 * Pass up a copy of the current static rules.
+		 * The last staic rule has number IPFW_DEFAULT_RULE.
 		 *
 		 * Note that the calculated size is used to bound the
 		 * amount of data returned to the user.  The rule set may
@@ -4768,8 +4782,6 @@
 		 * data in which case we'll just return what fits.
 		 */
 		size = V_static_len;	/* size of static rules */
-		if (V_ipfw_dyn_v)		/* add size of dyn.rules */
-			size += (V_dyn_count * sizeof(ipfw_dyn_rule));
 
 		if (size >= sopt->sopt_valsize)
 			break;
@@ -4784,6 +4796,27 @@
 		free(buf, M_TEMP);
 		break;
 
+	case IP_FW_DYN_GET:
+		/*
+		 * Pass up a copy of the current dynamic rules.
+		 * The last dynamic rule has NULL in the "next" field.
+		 */
+		if (V_ipfw_dyn_v)		/* size of dyn. rules */
+			size = (V_dyn_count * sizeof(ipfw_dyn_rule));
+
+		if (size >= sopt->sopt_valsize)
+			break;
+		/*
+		 * XXX todo: if the user passes a short length just to know
+		 * how much room is needed, do not bother filling up the
+		 * buffer, just jump to the sooptcopyout.
+		 */
+		buf = malloc(size, M_TEMP, M_WAITOK);
+		error = sooptcopyout(sopt, buf,
+				ipfw_getdynrules(&V_layer3_chain, buf, size));
+		free(buf, M_TEMP);
+		break;
+
 	case IP_FW_FLUSH:
 		/*
 		 * Normally we cannot release the lock on each iteration.

==== //depot/projects/soc2009/marta_ipfw/src/sys/netinet/raw_ip.c#2 (text+ko) ====

@@ -31,7 +31,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/netinet/raw_ip.c,v 1.220 2009/08/01 19:26:27 rwatson Exp $");
+__FBSDID("$FreeBSD: src/sys/netinet/raw_ip.c,v 1.219 2009/07/16 21:13:04 rwatson Exp $");
 
 #include "opt_inet6.h"
 #include "opt_ipsec.h"
@@ -519,6 +519,7 @@
 
 		case IP_FW_ADD:	/* ADD actually returns the body... */
 		case IP_FW_GET:
+		case IP_FW_DYN_GET:
 		case IP_FW_TABLE_GETSIZE:
 		case IP_FW_TABLE_LIST:
 		case IP_FW_NAT_GET_CONFIG:



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200908170919.n7H9JedE027727>