Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 9 May 2007 00:30:12 +0600
From:      "A. Skrobov" <tyomitch@gmail.com>
To:        freebsd-ipfw@freebsd.org
Subject:   a sysctl variable to query last ipfw rule number
Message-ID:  <2a38baa40705081130o52ad24d6l9ab1e6d6647e81ef@mail.gmail.com>

Next in thread | Raw E-Mail | Index | Archive | Help
Such a variable is useful in scripts that add blocks of rules
containing skipto actions; instead of hardcoding numbers for all the
rules, they could be derived dynamically.

As an additional bonus, keeping track of the last rule number reduces
overhead in add_rule when no rule number is specified (and partially
puts that overhead to remove_rule instead). Since rules are added more
often than they are deleted, this seems a performance improvement as
well.

Could someone please review my patch? It's made for a very old ipfw2
version, the one bundled with 5.4-RELEASE, but the relevant code
doesn't seem to have changed since then.

*** ip_fw2.c.orig	Sun Feb  6 21:16:20 2005
--- ip_fw2.c	Tue May  8 23:38:37 2007
***************
*** 191,196 ****
--- 191,197 ----

  static int fw_debug = 1;
  static int autoinc_step = 100; /* bounded to 1..1000 in add_rule() */
+ static unsigned int last_rule = 0;

  #ifdef SYSCTL_NODE
  SYSCTL_NODE(_net_inet_ip, OID_AUTO, fw, CTLFLAG_RW, 0, "Firewall");
***************
*** 199,204 ****
--- 200,207 ----
      &fw_enable, 0, "Enable ipfw");
  SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, autoinc_step, CTLFLAG_RW,
      &autoinc_step, 0, "Rule number autincrement step");
+ SYSCTL_UINT(_net_inet_ip_fw, OID_AUTO, last_rule, CTLFLAG_RD,
+     &last_rule, 0, "Number of last added rule");
  SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, one_pass,
      CTLFLAG_RW | CTLFLAG_SECURE3,
      &fw_one_pass, 0,
***************
*** 2585,2595 ****
  		/*
  		 * locate the highest numbered rule before default
  		 */
! 		for (f = chain->rules; f; f = f->next) {
! 			if (f->rulenum == IPFW_DEFAULT_RULE)
! 				break;
! 			rule->rulenum = f->rulenum;
! 		}
  		if (rule->rulenum < IPFW_DEFAULT_RULE - autoinc_step)
  			rule->rulenum += autoinc_step;
  		input_rule->rulenum = rule->rulenum;
--- 2588,2594 ----
  		/*
  		 * locate the highest numbered rule before default
  		 */
! 		rule->rulenum = last_rule;
  		if (rule->rulenum < IPFW_DEFAULT_RULE - autoinc_step)
  			rule->rulenum += autoinc_step;
  		input_rule->rulenum = rule->rulenum;
***************
*** 2612,2617 ****
--- 2611,2618 ----
  	}
  	flush_rule_ptrs(chain);
  done:
+ 	if (last_rule < rule->rulenum)
+ 	    last_rule = rule->rulenum;
  	static_count++;
  	static_len += l;
  	IPFW_WUNLOCK(chain);
***************
*** 2631,2637 ****
  static struct ip_fw *
  remove_rule(struct ip_fw_chain *chain, struct ip_fw *rule, struct ip_fw *prev)
  {
! 	struct ip_fw *n;
  	int l = RULESIZE(rule);

  	IPFW_WLOCK_ASSERT(chain);
--- 2632,2638 ----
  static struct ip_fw *
  remove_rule(struct ip_fw_chain *chain, struct ip_fw *rule, struct ip_fw *prev)
  {
! 	struct ip_fw *n, *f;
  	int l = RULESIZE(rule);

  	IPFW_WLOCK_ASSERT(chain);
***************
*** 2647,2652 ****
--- 2648,2660 ----
  	static_count--;
  	static_len -= l;

+ 	if (rule->rulenum >= last_rule) /* it should always be <=, but who knows */
+ 		for (f = chain->rules; f; f = f->next) {
+ 			if (f->rulenum == IPFW_DEFAULT_RULE)
+ 				break;
+ 			last_rule = f->rulenum;
+ 		}
+
  	rule->next = chain->reap;
  	chain->reap = rule;

***************
*** 2690,2695 ****
--- 2698,2705 ----
  			prev = rule;
  			rule = rule->next;
  		}
+ 		
+ 	last_rule = 0; /* how come static_count doesn't need the explicit reset? */
  }

  /**
***************
*** 3454,3459 ****
--- 3464,3470 ----
  		IPFW_LOCK_DESTROY(&layer3_chain);
  		return (error);
  	}
+ 	last_rule = 0;

  	ip_fw_default_rule = layer3_chain.rules;
  	printf("ipfw2 initialized, divert %s, "



Want to link to this message? Use this URL: <http://docs.FreeBSD.org/cgi/mid.cgi?2a38baa40705081130o52ad24d6l9ab1e6d6647e81ef>