Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 8 May 2014 19:11:14 +0000 (UTC)
From:      "Alexander V. Chernikov" <melifaro@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-9@freebsd.org
Subject:   svn commit: r265699 - in stable/9: sbin/ipfw sys/netpfil/ipfw
Message-ID:  <201405081911.s48JBEre060044@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: melifaro
Date: Thu May  8 19:11:14 2014
New Revision: 265699
URL: http://svnweb.freebsd.org/changeset/base/265699

Log:
  Merge r258708, r258711, r260247, r261117.
  
  r258708:
  Check ipfw table numbers in both user and kernel space before rule addition.
  Found by:       Saychik Pavel <umka@localka.net>
  
  r258711:
  Simplify O_NAT opcode handling.
  
  r260247:
  Use rnh_matchaddr instead of rnh_lookup for longest-prefix match.
  rnh_lookup is effectively the same as rnh_matchaddr if called with
  empy network mask.
  
  r261117:
  Reorder struct ip_fw_chain:
  * move rarely-used fields down
  * move uh_lock to different cacheline
  * remove some usused fields

Modified:
  stable/9/sbin/ipfw/ipfw2.c
  stable/9/sbin/ipfw/ipfw2.h
  stable/9/sys/netpfil/ipfw/ip_fw2.c
  stable/9/sys/netpfil/ipfw/ip_fw_private.h
  stable/9/sys/netpfil/ipfw/ip_fw_sockopt.c
  stable/9/sys/netpfil/ipfw/ip_fw_table.c
Directory Properties:
  stable/9/sbin/   (props changed)
  stable/9/sbin/ipfw/   (props changed)
  stable/9/sys/   (props changed)
  stable/9/sys/netpfil/   (props changed)

Modified: stable/9/sbin/ipfw/ipfw2.c
==============================================================================
--- stable/9/sbin/ipfw/ipfw2.c	Thu May  8 19:10:04 2014	(r265698)
+++ stable/9/sbin/ipfw/ipfw2.c	Thu May  8 19:11:14 2014	(r265699)
@@ -60,6 +60,8 @@ int resvd_set_number = RESVD_SET;
 
 int ipfw_socket = -1;
 
+uint32_t ipfw_tables_max = 0; /* Number of tables supported by kernel */
+
 #ifndef s6_addr32
 #define s6_addr32 __u6_addr.__u6_addr32
 #endif
@@ -2202,6 +2204,7 @@ fill_ip(ipfw_insn_ip *cmd, char *av, int
 {
 	int len = 0;
 	uint32_t *d = ((ipfw_insn_u32 *)cmd)->d;
+	uint32_t tables_max;
 
 	cmd->o.len &= ~F_LEN_MASK;	/* zero len */
 
@@ -2220,6 +2223,10 @@ fill_ip(ipfw_insn_ip *cmd, char *av, int
 			*p++ = '\0';
 		cmd->o.opcode = O_IP_DST_LOOKUP;
 		cmd->o.arg1 = strtoul(av + 6, NULL, 0);
+		tables_max = ipfw_get_tables_max();
+		if (cmd->o.arg1 > tables_max)
+			errx(EX_USAGE, "The table number exceeds the maximum "
+			    "allowed value (%u)", tables_max - 1);
 		if (p) {
 			cmd->o.len |= F_INSN_SIZE(ipfw_insn_u32);
 			d[0] = strtoul(p, NULL, 0);
@@ -4108,6 +4115,33 @@ static void table_list(uint16_t num, int
 static void table_fill_xentry(char *arg, ipfw_table_xentry *xent);
 
 /*
+ * Retrieve maximum number of tables supported by ipfw(4) module.
+ */
+uint32_t
+ipfw_get_tables_max()
+{
+	size_t len;
+	uint32_t tables_max;
+
+	if (ipfw_tables_max != 0)
+		return (ipfw_tables_max);
+
+	len = sizeof(tables_max);
+	if (sysctlbyname("net.inet.ip.fw.tables_max", &tables_max, &len,
+	    NULL, 0) == -1) {
+		if (co.test_only)
+			tables_max = 128; /* Old conservative default */
+		else
+			errx(1, "Can't determine maximum number of ipfw tables."
+			    " Perhaps you forgot to load ipfw module?");
+	}
+
+	ipfw_tables_max = tables_max;
+
+	return (ipfw_tables_max);
+}
+
+/*
  * This one handles all table-related commands
  * 	ipfw table N add addr[/masklen] [value]
  * 	ipfw table N delete addr[/masklen]
@@ -4120,19 +4154,10 @@ ipfw_table_handler(int ac, char *av[])
 	ipfw_table_xentry xent;
 	int do_add;
 	int is_all;
-	size_t len;
 	uint32_t a;
 	uint32_t tables_max;
 
-	len = sizeof(tables_max);
-	if (sysctlbyname("net.inet.ip.fw.tables_max", &tables_max, &len,
-	    NULL, 0) == -1) {
-		if (co.test_only)
-			tables_max = 128; /* Old conservative default */
-		else
-			errx(1, "Can't determine maximum number of ipfw tables."
-			    " Perhaps you forgot to load ipfw module?");
-	}
+	tables_max = ipfw_get_tables_max();
 
 	memset(&xent, 0, sizeof(xent));
 

Modified: stable/9/sbin/ipfw/ipfw2.h
==============================================================================
--- stable/9/sbin/ipfw/ipfw2.h	Thu May  8 19:10:04 2014	(r265698)
+++ stable/9/sbin/ipfw/ipfw2.h	Thu May  8 19:11:14 2014	(r265699)
@@ -228,6 +228,8 @@ char const *match_value(struct _s_x *p, 
 
 int do_cmd(int optname, void *optval, uintptr_t optlen);
 
+uint32_t ipfw_get_tables_max(void);
+
 struct in6_addr;
 void n2mask(struct in6_addr *mask, int n);
 int contigmask(uint8_t *p, int len);

Modified: stable/9/sys/netpfil/ipfw/ip_fw2.c
==============================================================================
--- stable/9/sys/netpfil/ipfw/ip_fw2.c	Thu May  8 19:10:04 2014	(r265698)
+++ stable/9/sys/netpfil/ipfw/ip_fw2.c	Thu May  8 19:11:14 2014	(r265699)
@@ -2395,38 +2395,35 @@ do {								\
 			}
 
 			case O_NAT:
+				l = 0;          /* exit inner loop */
+				done = 1;       /* exit outer loop */
  				if (!IPFW_NAT_LOADED) {
 				    retval = IP_FW_DENY;
-				} else {
-				    struct cfg_nat *t;
-				    int nat_id;
+				    break;
+				}
 
-				    set_match(args, f_pos, chain);
-				    /* Check if this is 'global' nat rule */
-				    if (cmd->arg1 == 0) {
-					    retval = ipfw_nat_ptr(args, NULL, m);
-					    l = 0;
-					    done = 1;
-					    break;
-				    }
-				    t = ((ipfw_insn_nat *)cmd)->nat;
-				    if (t == NULL) {
+				struct cfg_nat *t;
+				int nat_id;
+
+				set_match(args, f_pos, chain);
+				/* Check if this is 'global' nat rule */
+				if (cmd->arg1 == 0) {
+					retval = ipfw_nat_ptr(args, NULL, m);
+					break;
+				}
+				t = ((ipfw_insn_nat *)cmd)->nat;
+				if (t == NULL) {
 					nat_id = IP_FW_ARG_TABLEARG(cmd->arg1);
 					t = (*lookup_nat_ptr)(&chain->nat, nat_id);
 
 					if (t == NULL) {
 					    retval = IP_FW_DENY;
-					    l = 0;	/* exit inner loop */
-					    done = 1;	/* exit outer loop */
 					    break;
 					}
 					if (cmd->arg1 != IP_FW_TABLEARG)
 					    ((ipfw_insn_nat *)cmd)->nat = t;
-				    }
-				    retval = ipfw_nat_ptr(args, t, m);
 				}
-				l = 0;          /* exit inner loop */
-				done = 1;       /* exit outer loop */
+				retval = ipfw_nat_ptr(args, t, m);
 				break;
 
 			case O_REASS: {
@@ -2657,7 +2654,7 @@ vnet_ipfw_init(const void *unused)
 	rule->set = RESVD_SET;
 	rule->cmd[0].len = 1;
 	rule->cmd[0].opcode = default_to_accept ? O_ACCEPT : O_DENY;
-	chain->rules = chain->default_rule = chain->map[0] = rule;
+	chain->default_rule = chain->map[0] = rule;
 	chain->id = rule->id = 1;
 
 	IPFW_LOCK_INIT(chain);

Modified: stable/9/sys/netpfil/ipfw/ip_fw_private.h
==============================================================================
--- stable/9/sys/netpfil/ipfw/ip_fw_private.h	Thu May  8 19:10:04 2014	(r265698)
+++ stable/9/sys/netpfil/ipfw/ip_fw_private.h	Thu May  8 19:11:14 2014	(r265699)
@@ -213,25 +213,27 @@ VNET_DECLARE(unsigned int, fw_tables_max
 #define V_fw_tables_max		VNET(fw_tables_max)
 
 struct ip_fw_chain {
-	struct ip_fw	*rules;		/* list of rules */
-	struct ip_fw	*reap;		/* list of rules to reap */
-	struct ip_fw	*default_rule;
-	int		n_rules;	/* number of static rules */
-	int		static_len;	/* total len of static rules */
 	struct ip_fw	**map;		/* array of rule ptrs to ease lookup */
+	uint32_t	id;		/* ruleset id */
+	int		n_rules;	/* number of static rules */
 	LIST_HEAD(nat_list, cfg_nat) nat;       /* list of nat entries */
 	struct radix_node_head **tables;	/* IPv4 tables */
 	struct radix_node_head **xtables;	/* extended tables */
 	uint8_t		*tabletype;	/* Array of table types */
 #if defined( __linux__ ) || defined( _WIN32 )
 	spinlock_t rwmtx;
-	spinlock_t uh_lock;
 #else
 	struct rwlock	rwmtx;
+#endif
+	int		static_len;	/* total len of static rules */
+	uint32_t	gencnt;		/* NAT generation count */
+	struct ip_fw	*reap;		/* list of rules to reap */
+	struct ip_fw	*default_rule;
+#if defined( __linux__ ) || defined( _WIN32 )
+	spinlock_t uh_lock;
+#else
 	struct rwlock	uh_lock;	/* lock for upper half */
 #endif
-	uint32_t	id;		/* ruleset id */
-	uint32_t	gencnt;		/* generation count */
 };
 
 struct sockopt;	/* used by tcp_var.h */

Modified: stable/9/sys/netpfil/ipfw/ip_fw_sockopt.c
==============================================================================
--- stable/9/sys/netpfil/ipfw/ip_fw_sockopt.c	Thu May  8 19:10:04 2014	(r265698)
+++ stable/9/sys/netpfil/ipfw/ip_fw_sockopt.c	Thu May  8 19:11:14 2014	(r265699)
@@ -159,7 +159,7 @@ ipfw_add_rule(struct ip_fw_chain *chain,
 	int i, l, insert_before;
 	struct ip_fw **map;	/* the new array of pointers */
 
-	if (chain->rules == NULL || input_rule->rulenum > IPFW_DEFAULT_RULE-1)
+	if (chain->map == NULL || input_rule->rulenum > IPFW_DEFAULT_RULE - 1)
 		return (EINVAL);
 
 	l = RULESIZE(input_rule);
@@ -655,7 +655,7 @@ check_ipfw_struct(struct ip_fw *rule, in
 
 		case O_IP_SRC_LOOKUP:
 		case O_IP_DST_LOOKUP:
-			if (cmd->arg1 >= IPFW_TABLES_MAX) {
+			if (cmd->arg1 >= V_fw_tables_max) {
 				printf("ipfw: invalid table number %d\n",
 				    cmd->arg1);
 				return (EINVAL);

Modified: stable/9/sys/netpfil/ipfw/ip_fw_table.c
==============================================================================
--- stable/9/sys/netpfil/ipfw/ip_fw_table.c	Thu May  8 19:10:04 2014	(r265698)
+++ stable/9/sys/netpfil/ipfw/ip_fw_table.c	Thu May  8 19:11:14 2014	(r265699)
@@ -544,7 +544,7 @@ ipfw_lookup_table(struct ip_fw_chain *ch
 		return (0);
 	KEY_LEN(sa) = KEY_LEN_INET;
 	sa.sin_addr.s_addr = addr;
-	ent = (struct table_entry *)(rnh->rnh_lookup(&sa, NULL, rnh));
+	ent = (struct table_entry *)(rnh->rnh_matchaddr(&sa, rnh));
 	if (ent != NULL) {
 		*val = ent->value;
 		return (1);
@@ -570,7 +570,7 @@ ipfw_lookup_table_extended(struct ip_fw_
 	case IPFW_TABLE_CIDR:
 		KEY_LEN(sa6) = KEY_LEN_INET6;
 		memcpy(&sa6.sin6_addr, paddr, sizeof(struct in6_addr));
-		xent = (struct table_xentry *)(rnh->rnh_lookup(&sa6, NULL, rnh));
+		xent = (struct table_xentry *)(rnh->rnh_matchaddr(&sa6, rnh));
 		break;
 
 	case IPFW_TABLE_INTERFACE:
@@ -578,7 +578,7 @@ ipfw_lookup_table_extended(struct ip_fw_
 		    strlcpy(iface.ifname, (char *)paddr, IF_NAMESIZE) + 1;
 		/* Assume direct match */
 		/* FIXME: Add interface pattern matching */
-		xent = (struct table_xentry *)(rnh->rnh_lookup(&iface, NULL, rnh));
+		xent = (struct table_xentry *)(rnh->rnh_matchaddr(&iface, rnh));
 		break;
 
 	default:



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