svn commit: r268016 - in projects/ipfw: sbin/ipfw sys/netpfil/ipfw

Alexander V. Chernikov melifaro at FreeBSD.org
Sun Jun 29 09:29:28 UTC 2014


Author: melifaro
Date: Sun Jun 29 09:29:27 2014
New Revision: 268016
URL: http://svnweb.freebsd.org/changeset/base/268016

Log:
  Enable kernel-side rule filtering based on user request.
  Make do_get3() function return real error.

Modified:
  projects/ipfw/sbin/ipfw/ipfw2.c
  projects/ipfw/sys/netpfil/ipfw/ip_fw_sockopt.c

Modified: projects/ipfw/sbin/ipfw/ipfw2.c
==============================================================================
--- projects/ipfw/sbin/ipfw/ipfw2.c	Sun Jun 29 07:02:47 2014	(r268015)
+++ projects/ipfw/sbin/ipfw/ipfw2.c	Sun Jun 29 09:29:27 2014	(r268016)
@@ -61,9 +61,10 @@ struct format_opts {
 	int bcwidth;
 	int pcwidth;
 	int show_counters;
-	int first;
-	int last;
-	ipfw_obj_ctlv *tstate;
+	uint32_t flags;		/* request flags */
+	uint32_t first;		/* first rule to request */
+	uint32_t last;		/* last rule to request */
+	ipfw_obj_ctlv *tstate;	/* table state data */
 };
 
 int resvd_set_number = RESVD_SET;
@@ -375,7 +376,7 @@ static struct _s_x rule_options[] = {
 };
 
 void bprint_uint_arg(struct buf_pr *bp, const char *str, uint32_t arg);
-static int ipfw_get_config(struct cmdline_opts *co, uint32_t flags,
+static int ipfw_get_config(struct cmdline_opts *co, struct format_opts *fo,
     ipfw_cfg_lheader **pcfg, size_t *psize);
 static int ipfw_show_config(struct cmdline_opts *co, struct format_opts *fo,
     ipfw_cfg_lheader *cfg, size_t sz, int ac, char **av);
@@ -593,6 +594,11 @@ do_get3(int optname, ip_fw3_opheader *op
 	error = getsockopt(ipfw_socket, IPPROTO_IP, IP_FW3, op3,
 	    (socklen_t *)optlen);
 
+	if (error == -1) {
+		if (errno != 0)
+			error = errno;
+	}
+
 	return (error);
 }
 
@@ -2197,11 +2203,11 @@ prepare_format_opts(struct cmdline_opts 
 
 static int
 ipfw_list_static_range(struct cmdline_opts *co, struct format_opts *fo,
-    struct buf_pr *bp, struct ip_fw *r, int nstat)
+    struct buf_pr *bp, struct ip_fw *r, int rcnt)
 {
 	int n, seen;
 
-	for (n = seen = 0; n < nstat; n++, r = NEXT(r) ) {
+	for (n = seen = 0; n < rcnt; n++, r = NEXT(r) ) {
 		if (r->rulenum > fo->last)
 			break;
 		if (co->use_set && r->set != co->use_set - 1)
@@ -2218,27 +2224,31 @@ ipfw_list_static_range(struct cmdline_op
 
 static void
 ipfw_list_dyn_range(struct cmdline_opts *co, struct format_opts *fo,
-    struct buf_pr *bp, ipfw_dyn_rule *d, int ndyn)
+    struct buf_pr *bp, ipfw_dyn_rule *d, int dcnt, int objsize)
 {
 	int n;
 	uint8_t set;
 	uint16_t rulenum;
 
-	for (n = 0; n < ndyn; n++, d++) {
+	for (n = 0; n < dcnt; n++) {
 		bcopy(&d->rule, &rulenum, sizeof(rulenum));
 		if (rulenum > fo->last)
 			break;
 		if (co->use_set) {
 			bcopy((char *)&d->rule + sizeof(uint16_t),
 			      &set, sizeof(uint8_t));
-			if (set != co->use_set - 1)
+			if (set != co->use_set - 1) {
+				d = (ipfw_dyn_rule *)((caddr_t)d + objsize);
 				continue;
+			}
 		}
 		if (rulenum >= fo->first) {
 			show_dyn_state(co, fo, bp, d);
 			printf("%s\n", bp->buf);
 			bp_flush(bp);
 		}
+
+		d = (ipfw_dyn_rule *)((caddr_t)d + objsize);
 	}
 }
 
@@ -2249,7 +2259,10 @@ ipfw_list(int ac, char *av[], int show_c
 	struct format_opts sfo;
 	size_t sz;
 	int error;
-	uint32_t flags;
+	int lac;
+	char **lav;
+	uint32_t rnum;
+	char *endptr;
 
 	if (co.test_only) {
 		fprintf(stderr, "Testing only, list disabled\n");
@@ -2262,16 +2275,30 @@ ipfw_list(int ac, char *av[], int show_c
 
 	ac--;
 	av++;
+	memset(&sfo, 0, sizeof(sfo));
+
+	/* Determine rule range to request */
+	if (ac > 0) {
+		for (lac = ac, lav = av; lac != 0; lac--) {
+			rnum = strtoul(*lav++, &endptr, 10);
+			if (sfo.first == 0 || rnum < sfo.first)
+				sfo.first = rnum;
+
+			if (*endptr == '-')
+				rnum = strtoul(endptr + 1, &endptr, 10);
+			if (sfo.last == 0 || rnum > sfo.last)
+				sfo.last = rnum;
+		}
+	}
 
 	/* get configuraion from kernel */
 	cfg = NULL;
-	flags = IPFW_CFG_GET_STATIC;
+	sfo.flags = IPFW_CFG_GET_STATIC;
 	if (co.do_dynamic != 0)
-		flags |= IPFW_CFG_GET_STATES;
-	if ((error = ipfw_get_config(&co, flags, &cfg, &sz)) != 0)
+		sfo.flags |= IPFW_CFG_GET_STATES;
+	if ((error = ipfw_get_config(&co, &sfo, &cfg, &sz)) != 0)
 		err(EX_OSERR, "retrieving config failed");
 
-	memset(&sfo, 0, sizeof(sfo));
 	sfo.show_counters = show_counters;
 	error = ipfw_show_config(&co, &sfo, cfg, sz, ac, av);
 
@@ -2292,9 +2319,8 @@ ipfw_show_config(struct cmdline_opts *co
 	int exitval = EX_OK;
 	int lac;
 	char **lav;
-	u_long rnum;
 	char *endptr;
-	size_t read;
+	size_t dobjsz, read;
 	struct buf_pr bp;
 	ipfw_obj_ctlv *ctlv, *tstate;
 
@@ -2304,6 +2330,7 @@ ipfw_show_config(struct cmdline_opts *co
 	tstate = NULL;
 	rbase = NULL;
 	dynbase = NULL;
+	dobjsz = 0;
 	read = 0;
 
 	ctlv = (ipfw_obj_ctlv *)(cfg + 1);
@@ -2329,7 +2356,8 @@ ipfw_show_config(struct cmdline_opts *co
 	if ((cfg->flags & IPFW_CFG_GET_STATES) && (read != sz))  {
 		/* We may have some dynamic rules */
 		read += sizeof(ipfw_obj_ctlv);
-		dcnt = ((sz - read) / ctlv->objsize);
+		dobjsz = ctlv->objsize;
+		dcnt = (sz - read) / dobjsz;
 		if (dcnt != 0)
 			dynbase = (ipfw_dyn_rule *)(ctlv + 1);
 	}
@@ -2345,7 +2373,7 @@ ipfw_show_config(struct cmdline_opts *co
 
 		if (co->do_dynamic && dcnt) {
 			printf("## Dynamic rules (%d):\n", dcnt);
-			ipfw_list_dyn_range(co, fo, &bp, dynbase, dcnt);
+			ipfw_list_dyn_range(co, fo, &bp, dynbase, dcnt, dobjsz);
 		}
 
 		bp_free(&bp);
@@ -2368,7 +2396,11 @@ ipfw_show_config(struct cmdline_opts *co
 			/* give precedence to other error(s) */
 			if (exitval == EX_OK)
 				exitval = EX_UNAVAILABLE;
-			warnx("rule %lu does not exist", rnum);
+			if (fo->first == fo->last)
+				warnx("rule %u does not exist", fo->first);
+			else
+				warnx("no rules in range %u-%u",
+				    fo->first, fo->last);
 		}
 	}
 
@@ -2381,7 +2413,7 @@ ipfw_show_config(struct cmdline_opts *co
 			if (*endptr)
 				/* already warned */
 				continue;
-			ipfw_list_dyn_range(co, fo, &bp, dynbase, dcnt);
+			ipfw_list_dyn_range(co, fo, &bp, dynbase, dcnt, dobjsz);
 		}
 	}
 
@@ -2400,7 +2432,7 @@ ipfw_show_config(struct cmdline_opts *co
  */
 
 static int
-ipfw_get_config(struct cmdline_opts *co, uint32_t flags,
+ipfw_get_config(struct cmdline_opts *co, struct format_opts *fo,
     ipfw_cfg_lheader **pcfg, size_t *psize)
 {
 	ipfw_cfg_lheader *cfg;
@@ -2423,9 +2455,11 @@ ipfw_get_config(struct cmdline_opts *co,
 		if ((cfg = calloc(1, sz)) == NULL)
 			return (ENOMEM);
 
-		cfg->flags = flags;
+		cfg->flags = fo->flags;
+		cfg->start_rule = fo->first;
+		cfg->end_rule = fo->last;
 
-		if (do_get3(IP_FW_XGET, &cfg->opheader, &sz) < 0) {
+		if ((error = do_get3(IP_FW_XGET, &cfg->opheader, &sz)) != 0) {
 			if (error != ENOMEM) {
 				free(cfg);
 				return (error);

Modified: projects/ipfw/sys/netpfil/ipfw/ip_fw_sockopt.c
==============================================================================
--- projects/ipfw/sys/netpfil/ipfw/ip_fw_sockopt.c	Sun Jun 29 07:02:47 2014	(r268015)
+++ projects/ipfw/sys/netpfil/ipfw/ip_fw_sockopt.c	Sun Jun 29 09:29:27 2014	(r268016)
@@ -1087,7 +1087,7 @@ dump_config(struct ip_fw_chain *chain, s
 {
 	ipfw_cfg_lheader *hdr;
 	struct ip_fw *rule;
-	uint32_t sz;
+	uint32_t sz, rnum;
 	int error, i;
 	struct dump_args da;
 	uint32_t *bmask;
@@ -1114,6 +1114,16 @@ dump_config(struct ip_fw_chain *chain, s
 	da.b = 0;
 	da.e = chain->n_rules;
 
+	if (hdr->end_rule != 0) {
+		/* Handle custom range */
+		if ((rnum = hdr->start_rule) > IPFW_DEFAULT_RULE)
+			rnum = IPFW_DEFAULT_RULE;
+		da.b = ipfw_find_rule(chain, rnum, 0);
+		rnum = hdr->end_rule;
+		rnum = (rnum < IPFW_DEFAULT_RULE) ? rnum+1 : IPFW_DEFAULT_RULE;
+		da.e = ipfw_find_rule(chain, rnum, 0);
+	}
+
 	if (hdr->flags & IPFW_CFG_GET_STATIC) {
 		for (i = da.b; i < da.e; i++) {
 			rule = chain->map[i];


More information about the svn-src-projects mailing list