svn commit: r269277 - projects/ipfw/sys/netpfil/ipfw

Alexander V. Chernikov melifaro at FreeBSD.org
Tue Jul 29 23:06:07 UTC 2014


Author: melifaro
Date: Tue Jul 29 23:06:06 2014
New Revision: 269277
URL: http://svnweb.freebsd.org/changeset/base/269277

Log:
  * Introduce ipfw_ctl3() handler and move all IP_FW3 opcodes there.
   The long-term goal is to switch remaining opcodes to IP_FW3 versions
   and use ipfw_ctl3() as default handler simplifying ipfw(4) interaction
   with external world.

Modified:
  projects/ipfw/sys/netpfil/ipfw/ip_fw_private.h
  projects/ipfw/sys/netpfil/ipfw/ip_fw_sockopt.c

Modified: projects/ipfw/sys/netpfil/ipfw/ip_fw_private.h
==============================================================================
--- projects/ipfw/sys/netpfil/ipfw/ip_fw_private.h	Tue Jul 29 22:44:26 2014	(r269276)
+++ projects/ipfw/sys/netpfil/ipfw/ip_fw_private.h	Tue Jul 29 23:06:06 2014	(r269277)
@@ -496,6 +496,7 @@ int ipfw_list_ifaces(struct ip_fw_chain 
 /* In ip_fw_sockopt.c */
 int ipfw_find_rule(struct ip_fw_chain *chain, uint32_t key, uint32_t id);
 int ipfw_ctl(struct sockopt *sopt);
+int ipfw_ctl3(struct sockopt *sopt);
 int ipfw_chk(struct ip_fw_args *args);
 void ipfw_reap_rules(struct ip_fw *head);
 void ipfw_init_counters(void);

Modified: projects/ipfw/sys/netpfil/ipfw/ip_fw_sockopt.c
==============================================================================
--- projects/ipfw/sys/netpfil/ipfw/ip_fw_sockopt.c	Tue Jul 29 22:44:26 2014	(r269276)
+++ projects/ipfw/sys/netpfil/ipfw/ip_fw_sockopt.c	Tue Jul 29 23:06:06 2014	(r269277)
@@ -1719,28 +1719,26 @@ add_entry(struct ip_fw_chain *chain, str
 	return (error);
 }
 
-/**
- * {set|get}sockopt parser.
- */
 int
-ipfw_ctl(struct sockopt *sopt)
+ipfw_ctl3(struct sockopt *sopt)
 {
-#define	RULE_MAXSIZE	(256*sizeof(u_int32_t))
 	int error;
 	size_t bsize_max, size, valsize;
-	struct ip_fw *buf;
-	struct ip_fw_rule0 *rule;
 	struct ip_fw_chain *chain;
-	u_int32_t rulenum[2];
 	uint32_t opt;
 	char xbuf[128];
 	struct sockopt_data sdata;
 	ip_fw3_opheader *op3 = NULL;
-	struct rule_check_info ci;
 
+	/* Do not check privs twice untile we're called from ipfw_ctl() */
+#if 0
 	error = priv_check(sopt->sopt_td, PRIV_NETINET_IPFW);
-	if (error)
+	if (error != 0)
 		return (error);
+#endif
+
+	if (sopt->sopt_name != IP_FW3)
+		return (ENOTSUP);
 
 	chain = &V_layer3_chain;
 	error = 0;
@@ -1749,14 +1747,12 @@ ipfw_ctl(struct sockopt *sopt)
 	valsize = sopt->sopt_valsize;
 	memset(&sdata, 0, sizeof(sdata));
 	/* Read op3 header first to determine actual operation */
-	if ((opt = sopt->sopt_name) == IP_FW3) {
-		op3 = (ip_fw3_opheader *)xbuf;
-		error = sooptcopyin(sopt, op3, sizeof(*op3), sizeof(*op3));
-		if (error != 0)
-			return (error);
-		opt = op3->opcode;
-		sopt->sopt_valsize = valsize;
-	}
+	op3 = (ip_fw3_opheader *)xbuf;
+	error = sooptcopyin(sopt, op3, sizeof(*op3), sizeof(*op3));
+	if (error != 0)
+		return (error);
+	opt = op3->opcode;
+	sopt->sopt_valsize = valsize;
 
 	/*
 	 * Disallow modifications in really-really secure mode, but still allow
@@ -1765,59 +1761,186 @@ ipfw_ctl(struct sockopt *sopt)
 	if (opt == IP_FW_ADD ||
 	    (sopt->sopt_dir == SOPT_SET && opt != IP_FW_RESETLOG)) {
 		error = securelevel_ge(sopt->sopt_td->td_ucred, 3);
-		if (error != 0) {
-			if (sdata.kbuf != xbuf)
-				free(sdata.kbuf, M_TEMP);
+		if (error != 0)
 			return (error);
-		}
 	}
 
-	if (op3 != NULL) {
+	/*
+	 * Determine buffer size:
+	 * use on-stack xbuf for short request,
+	 * allocate sliding-window buf for data export or
+	 * contigious buffer for special ops.
+	 */
+	bsize_max = IP_FW3_WRITEBUF;
+	if (opt == IP_FW_ADD)
+		bsize_max = IP_FW3_READBUF;
 
-		/*
-		 * Determine buffer size:
-		 * use on-stack xbuf for short request,
-		 * allocate sliding-window buf for data export or
-		 * contigious buffer for special ops.
-		 */
-		bsize_max = IP_FW3_WRITEBUF;
-		if (opt == IP_FW_ADD)
-			bsize_max = IP_FW3_READBUF;
+	/*
+	 * Fill in sockopt_data structure that may be useful for
+	 * IP_FW3 get requests.
+	 */
 
-		/*
-		 * Fill in sockopt_data structure that may be useful for
-		 * IP_FW3 get requests.
-		 */
+	if (valsize <= sizeof(xbuf)) {
+		sdata.kbuf = xbuf;
+		sdata.ksize = sizeof(xbuf);
+		sdata.kavail = valsize;
+	} else {
+		if (valsize < bsize_max)
+			size = valsize;
+		else
+			size = bsize_max;
+
+		sdata.kbuf = malloc(size, M_TEMP, M_WAITOK | M_ZERO);
+		sdata.ksize = size;
+		sdata.kavail = size;
+	}
+
+	sdata.sopt = sopt;
+	sdata.valsize = valsize;
+
+	/*
+	 * Copy either all request (if valsize < bsize_max)
+	 * or first bsize_max bytes to guarantee most consumers
+	 * that all necessary data has been copied).
+	 * Anyway, copy not less than sizeof(ip_fw3_opheader).
+	 */
+	if ((error = sooptcopyin(sopt, sdata.kbuf, sdata.ksize,
+	    sizeof(ip_fw3_opheader))) != 0)
+		return (error);
+	op3 = (ip_fw3_opheader *)sdata.kbuf;
+	opt = op3->opcode;
+
+	switch (opt) {
+	case IP_FW_XGET:
+		error = dump_config(chain, &sdata);
+		break;
+
+	case IP_FW_XIFLIST:
+		error = ipfw_list_ifaces(chain, &sdata);
+		break;
+
+	case IP_FW_XADD:
+		error = add_entry(chain, &sdata);
+		break;
+	/*--- TABLE opcodes ---*/
+	case IP_FW_TABLE_XCREATE:
+		error = ipfw_create_table(chain, op3, &sdata);
+		break;
+
+	case IP_FW_TABLE_XDESTROY:
+	case IP_FW_TABLE_XFLUSH:
+		error = ipfw_flush_table(chain, op3, &sdata);
+		break;
 
-		if (valsize <= sizeof(xbuf)) {
-			sdata.kbuf = xbuf;
-			sdata.ksize = sizeof(xbuf);
-			sdata.kavail = valsize;
-		} else {
-			if (valsize < bsize_max)
-				size = valsize;
-			else
-				size = bsize_max;
-
-			sdata.kbuf = malloc(size, M_TEMP, M_WAITOK | M_ZERO);
-			sdata.ksize = size;
-			sdata.kavail = size;
+	case IP_FW_TABLE_XINFO:
+		error = ipfw_describe_table(chain, &sdata);
+		break;
+
+	case IP_FW_TABLES_XGETSIZE:
+		error = ipfw_listsize_tables(chain, &sdata);
+		break;
+
+	case IP_FW_TABLES_XLIST:
+		error = ipfw_list_tables(chain, &sdata);
+		break;
+
+	case IP_FW_TABLE_XLIST:
+		error = ipfw_dump_table(chain, op3, &sdata);
+		break;
+
+	case IP_FW_TABLE_XADD:
+	case IP_FW_TABLE_XDEL:
+		error = ipfw_manage_table_ent(chain, op3, &sdata);
+		break;
+
+	case IP_FW_TABLE_XFIND:
+		error = ipfw_find_table_entry(chain, op3, &sdata);
+		break;
+
+	case IP_FW_TABLES_ALIST:
+		error = ipfw_list_table_algo(chain, &sdata);
+		break;
+
+	case IP_FW_TABLE_XGETSIZE:
+		{
+			uint32_t *tbl;
+			struct tid_info ti;
+
+			if (IP_FW3_OPLENGTH(sopt) < sizeof(uint32_t)) {
+				error = EINVAL;
+				break;
+			}
+
+			tbl = (uint32_t *)(op3 + 1);
+
+			memset(&ti, 0, sizeof(ti));
+			ti.uidx = *tbl;
+			IPFW_UH_RLOCK(chain);
+			error = ipfw_count_xtable(chain, &ti, tbl);
+			IPFW_UH_RUNLOCK(chain);
+			if (error)
+				break;
+			error = sooptcopyout(sopt, op3, sopt->sopt_valsize);
 		}
+		break;
+
+	default:
+		printf("ipfw: ipfw_ctl3 invalid option %d\n", opt);
+		error = EINVAL;
+	}
+
+	/* Flush state and free buffers */
+	if (error == 0)
+		error = ipfw_flush_sopt_data(&sdata);
+	else
+		ipfw_flush_sopt_data(&sdata);
 
-		sdata.sopt = sopt;
-		sdata.valsize = valsize;
+	if (sdata.kbuf != xbuf)
+		free(sdata.kbuf, M_TEMP);
 
-		/*
-		 * Copy either all request (if valsize < bsize_max)
-		 * or first bsize_max bytes to guarantee most consumers
-		 * that all necessary data has been copied).
-		 * Anyway, copy not less than sizeof(ip_fw3_opheader).
-		 */
-		if ((error = sooptcopyin(sopt, sdata.kbuf, sdata.ksize,
-		    sizeof(ip_fw3_opheader))) != 0)
+	return (error);
+}
+
+/**
+ * {set|get}sockopt parser.
+ */
+int
+ipfw_ctl(struct sockopt *sopt)
+{
+#define	RULE_MAXSIZE	(256*sizeof(u_int32_t))
+	int error;
+	size_t size, valsize;
+	struct ip_fw *buf;
+	struct ip_fw_rule0 *rule;
+	struct ip_fw_chain *chain;
+	u_int32_t rulenum[2];
+	uint32_t opt;
+	struct rule_check_info ci;
+
+	error = priv_check(sopt->sopt_td, PRIV_NETINET_IPFW);
+	if (error)
+		return (error);
+
+	chain = &V_layer3_chain;
+	error = 0;
+
+	/* Save original valsize before it is altered via sooptcopyin() */
+	valsize = sopt->sopt_valsize;
+	opt = sopt->sopt_name;
+
+	/* Pass IP_FW3 to a new handler */
+	if (opt == IP_FW3)
+		return (ipfw_ctl3(sopt));
+
+	/*
+	 * Disallow modifications in really-really secure mode, but still allow
+	 * the logging counters to be reset.
+	 */
+	if (opt == IP_FW_ADD ||
+	    (sopt->sopt_dir == SOPT_SET && opt != IP_FW_RESETLOG)) {
+		error = securelevel_ge(sopt->sopt_td->td_ucred, 3);
+		if (error != 0)
 			return (error);
-		op3 = (ip_fw3_opheader *)sdata.kbuf;
-		opt = op3->opcode;
 	}
 
 	switch (opt) {
@@ -1855,18 +1978,6 @@ ipfw_ctl(struct sockopt *sopt)
 		}
 		break;
 
-	case IP_FW_XGET: /* IP_FW3 */
-		error = dump_config(chain, &sdata);
-		break;
-
-	case IP_FW_XIFLIST: /* IP_FW3 */
-		error = ipfw_list_ifaces(chain, &sdata);
-		break;
-
-	case IP_FW_XADD: /* IP_FW3 */
-		error = add_entry(chain, &sdata);
-		break;
-
 	case IP_FW_FLUSH:
 		/* locking is done within del_entry() */
 		error = del_entry(chain, 0); /* special case, rule=0, cmd=0 means all */
@@ -1969,43 +2080,6 @@ ipfw_ctl(struct sockopt *sopt)
 		break;
 
 	/*--- TABLE opcodes ---*/
-	case IP_FW_TABLE_XCREATE: /* IP_FW3 */
-		error = ipfw_create_table(chain, op3, &sdata);
-		break;
-
-	case IP_FW_TABLE_XDESTROY: /* IP_FW3 */
-	case IP_FW_TABLE_XFLUSH: /* IP_FW3 */
-		error = ipfw_flush_table(chain, op3, &sdata);
-		break;
-
-	case IP_FW_TABLE_XINFO: /* IP_FW3 */
-		error = ipfw_describe_table(chain, &sdata);
-		break;
-
-	case IP_FW_TABLES_XGETSIZE: /* IP_FW3 */
-		error = ipfw_listsize_tables(chain, &sdata);
-		break;
-
-	case IP_FW_TABLES_XLIST: /* IP_FW3 */
-		error = ipfw_list_tables(chain, &sdata);
-		break;
-
-	case IP_FW_TABLE_XLIST: /* IP_FW3 */
-		error = ipfw_dump_table(chain, op3, &sdata);
-		break;
-
-	case IP_FW_TABLE_XADD: /* IP_FW3 */
-	case IP_FW_TABLE_XDEL: /* IP_FW3 */
-		error = ipfw_manage_table_ent(chain, op3, &sdata);
-		break;
-	case IP_FW_TABLE_XFIND: /* IP_FW3 */
-		error = ipfw_find_table_entry(chain, op3, &sdata);
-		break;
-	case IP_FW_TABLES_ALIST: /* IP_FW3 */
-		error = ipfw_list_table_algo(chain, &sdata);
-		break;
-
-	/*--- LEGACY API ---*/
 	case IP_FW_TABLE_ADD:
 	case IP_FW_TABLE_DEL:
 		{
@@ -2100,28 +2174,6 @@ ipfw_ctl(struct sockopt *sopt)
 		}
 		break;
 
-	case IP_FW_TABLE_XGETSIZE: /* IP_FW3 */
-		{
-			uint32_t *tbl;
-			struct tid_info ti;
-
-			if (IP_FW3_OPLENGTH(sopt) < sizeof(uint32_t)) {
-				error = EINVAL;
-				break;
-			}
-
-			tbl = (uint32_t *)(op3 + 1);
-
-			memset(&ti, 0, sizeof(ti));
-			ti.uidx = *tbl;
-			IPFW_UH_RLOCK(chain);
-			error = ipfw_count_xtable(chain, &ti, tbl);
-			IPFW_UH_RUNLOCK(chain);
-			if (error)
-				break;
-			error = sooptcopyout(sopt, op3, sopt->sopt_valsize);
-		}
-		break;
 	/*--- NAT operations are protected by the IPFW_LOCK ---*/
 	case IP_FW_NAT_CFG:
 		if (IPFW_NAT_LOADED)
@@ -2168,17 +2220,6 @@ ipfw_ctl(struct sockopt *sopt)
 		error = EINVAL;
 	}
 
-	if (op3 != NULL) {
-		/* Flush state and free buffers */
-		if (error == 0)
-			error = ipfw_flush_sopt_data(&sdata);
-		else
-			ipfw_flush_sopt_data(&sdata);
-
-		if (sdata.kbuf != xbuf)
-			free(sdata.kbuf, M_TEMP);
-	}
-
 	return (error);
 #undef RULE_MAXSIZE
 }


More information about the svn-src-projects mailing list