svn commit: r193894 - head/sys/netinet/ipfw

Luigi Rizzo luigi at FreeBSD.org
Wed Jun 10 10:35:00 UTC 2009


Author: luigi
Date: Wed Jun 10 10:34:59 2009
New Revision: 193894
URL: http://svn.freebsd.org/changeset/base/193894

Log:
  small simplifications to the code in charge of reaping deleted rules:
  - clear the head pointer immediately before using it, so there is
    no chance of mistakes;
  - call reap_rules() unconditionally. The function can handle a NULL
    argument just fine, and the cost of the extra call is hardly
    significant given that we do it rarely and outside the lock.
  
  MFC after:	3 days

Modified:
  head/sys/netinet/ipfw/ip_fw2.c

Modified: head/sys/netinet/ipfw/ip_fw2.c
==============================================================================
--- head/sys/netinet/ipfw/ip_fw2.c	Wed Jun 10 10:31:11 2009	(r193893)
+++ head/sys/netinet/ipfw/ip_fw2.c	Wed Jun 10 10:34:59 2009	(r193894)
@@ -3631,6 +3631,7 @@ remove_rule(struct ip_fw_chain *chain, s
 /*
  * Reclaim storage associated with a list of rules.  This is
  * typically the list created using remove_rule.
+ * A NULL pointer on input is handled correctly.
  */
 static void
 reap_rules(struct ip_fw *head)
@@ -3655,6 +3656,7 @@ free_chain(struct ip_fw_chain *chain, in
 
 	IPFW_WLOCK_ASSERT(chain);
 
+	chain->reap = NULL;
 	flush_rule_ptrs(chain); /* more efficient to do outside the loop */
 	for (prev = NULL, rule = chain->rules; rule ; )
 		if (kill_default || rule->set != RESVD_SET)
@@ -3701,8 +3703,8 @@ del_entry(struct ip_fw_chain *chain, u_i
 	}
 
 	IPFW_WLOCK(chain);
-	rule = chain->rules;
-	chain->reap = NULL;
+	rule = chain->rules;	/* common starting point */
+	chain->reap = NULL;	/* prepare for deletions */
 	switch (cmd) {
 	case 0:	/* delete rules with given number */
 		/*
@@ -3726,18 +3728,17 @@ del_entry(struct ip_fw_chain *chain, u_i
 
 	case 1:	/* delete all rules with given set number */
 		flush_rule_ptrs(chain);
-		rule = chain->rules;
-		while (rule->rulenum < IPFW_DEFAULT_RULE)
+		while (rule->rulenum < IPFW_DEFAULT_RULE) {
 			if (rule->set == rulenum)
 				rule = remove_rule(chain, rule, prev);
 			else {
 				prev = rule;
 				rule = rule->next;
 			}
+		}
 		break;
 
 	case 2:	/* move rules with given number to new set */
-		rule = chain->rules;
 		for (; rule->rulenum < IPFW_DEFAULT_RULE; rule = rule->next)
 			if (rule->rulenum == rulenum)
 				rule->set = new_set;
@@ -3756,6 +3757,7 @@ del_entry(struct ip_fw_chain *chain, u_i
 			else if (rule->set == new_set)
 				rule->set = rulenum;
 		break;
+
 	case 5: /* delete rules with given number and with given set number.
 		 * rulenum - given rule number;
 		 * new_set - given set number.
@@ -3782,10 +3784,8 @@ del_entry(struct ip_fw_chain *chain, u_i
 	 * avoid a LOR with dummynet.
 	 */
 	rule = chain->reap;
-	chain->reap = NULL;
 	IPFW_WUNLOCK(chain);
-	if (rule)
-		reap_rules(rule);
+	reap_rules(rule);
 	return 0;
 }
 
@@ -4315,6 +4315,8 @@ ipfw_ctl(struct sockopt *sopt)
 		if (V_ipfw_dyn_v)		/* add 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
@@ -4341,13 +4343,10 @@ ipfw_ctl(struct sockopt *sopt)
 		 */
 
 		IPFW_WLOCK(&V_layer3_chain);
-		V_layer3_chain.reap = NULL;
 		free_chain(&V_layer3_chain, 0 /* keep default rule */);
 		rule = V_layer3_chain.reap;
-		V_layer3_chain.reap = NULL;
 		IPFW_WUNLOCK(&V_layer3_chain);
-		if (rule != NULL)
-			reap_rules(rule);
+		reap_rules(rule);
 		break;
 
 	case IP_FW_ADD:
@@ -4735,12 +4734,10 @@ ipfw_destroy(void)
 	callout_drain(&V_ipfw_timeout);
 	IPFW_WLOCK(&V_layer3_chain);
 	flush_tables(&V_layer3_chain);
-	V_layer3_chain.reap = NULL;
 	free_chain(&V_layer3_chain, 1 /* kill default rule */);
-	reap = V_layer3_chain.reap, V_layer3_chain.reap = NULL;
+	reap = V_layer3_chain.reap;
 	IPFW_WUNLOCK(&V_layer3_chain);
-	if (reap != NULL)
-		reap_rules(reap);
+	reap_rules(reap);
 	IPFW_DYN_LOCK_DESTROY();
 	uma_zdestroy(ipfw_dyn_rule_zone);
 	if (V_ipfw_dyn_v != NULL)


More information about the svn-src-head mailing list