Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 4 Jan 2001 05:32:37 -0800 (PST)
From:      Jon Simola <jon@abccom.bc.ca>
To:        ipfw@freebsd.org
Subject:   Indexing IPFW rule
Message-ID:  <Pine.BSF.3.96.1010104052129.462T-200000@newmail.netbistro.com>

next in thread | raw e-mail | index | archive | help

[-- Attachment #1 --]

I have a bridging firewall in place, and I needed to be able to allow and deny
traffic from single IPs and change whether they're allowed or denied rather
quickly. Looking through the IPFW code at the skipto rule, I figured it
couldn't be too hard. This (very rough) code actually does the job (albeit in
only one direction currently).

It's designed to be used like:

ipfw add 9000 index 10000 ip from any to 192.168.0.0/24 in recv rl0
# make sure you don't fall through into this block of rules
ipfw add 10001 allow ip from any to any   # 192.168.0.1 will be thrown here
ipfw add 10002 deny ip from any to any   # 192.168.0.2 will be thrown here
# skip a few for readability
ipfw add 10254 deny ip from any to any   # 192.168.0.254 will be thrown here 
ipfw add 10255 allow ip from any to any   # 192.168.0.255 will be thrown here


Now, I'm hoping to garner some feedback on:
 - ways to clean up the code
 - things to improve (besides it's current unidirectional nature)
 - whether this is interesting

Oh, it's a patch against 4.2-RELEASE. Thanks!

---
Jon Simola <jon@abccom.bc.ca> | "In the near future - corporate networks
    Systems Administrator     |  reach out to the stars, electrons and light 
     ABC  Communications      |  flow throughout the universe." -- GITS

[-- Attachment #2 --]

--- sys/netinet/ip_fw.c.orig	Thu Jan  4 02:27:04 2001
+++ sys/netinet/ip_fw.c	Thu Jan  4 04:33:52 2001
@@ -506,6 +506,10 @@
 		    snprintf(SNPARGS(action2, 0), "SkipTo %d",
 			f->fw_skipto_rule);
 		    break;
+	    case IP_FW_F_INDEX:
+		    snprintf(SNPARGS(action2, 0), "Index %d",
+			f->fw_skipto_rule);
+		    break;
 #ifdef DUMMYNET
 	    case IP_FW_F_PIPE:
 		    snprintf(SNPARGS(action2, 0), "Pipe %d",
@@ -878,6 +882,29 @@
 }
 
 /*
+ * given an ip_fw_chain *, lookup_index_rule will return a pointer
+ * of the same type to the next one. This can be either the index
+ * target (for index instructions) or the next one in the chain (in
+ * all other cases including a missing jump target).
+ * Backward jumps are not allowed, so start looking from the next
+ * rule...
+ */ 
+static struct ip_fw_chain * lookup_index_rule(struct ip_fw_chain *me, u_int32_t dst_ip);
+
+static struct ip_fw_chain *
+lookup_index_rule(struct ip_fw_chain *me, u_int32_t dst_ip)
+{
+    struct ip_fw_chain *chain ;
+    int rule = me->rule->fw_skipto_rule + ((dst_ip>>24) & IN_CLASSC_HOST); /* guess... */
+    if ( (me->rule->fw_flg & IP_FW_F_COMMAND) == IP_FW_F_INDEX )
+	for (chain = me->chain.le_next; chain ; chain = chain->chain.le_next )
+	    if (chain->rule->fw_number >= rule)
+                return chain ;
+    return me->chain.le_next ; /* failure or not a skipto */
+}
+
+
+/*
  * Parameters:
  *
  *	pip	Pointer to packet header (struct ip **)
@@ -1304,6 +1331,13 @@
 			    chain = lookup_next_rule(chain) ;
 			if (! chain) goto dropit;
 			goto again ;
+		case IP_FW_F_INDEX: /* dst_ip */
+			if ( f->next_rule_ptr )
+			    chain = f->next_rule_ptr ;
+			else
+			    chain = lookup_index_rule(chain, dst_ip.s_addr) ;
+			if (! chain) goto dropit;
+			goto again ;
 #ifdef DUMMYNET
 		case IP_FW_F_PIPE:
 		case IP_FW_F_QUEUE:
@@ -1744,6 +1778,7 @@
 	case IP_FW_F_ACCEPT:
 	case IP_FW_F_COUNT:
 	case IP_FW_F_SKIPTO:
+	case IP_FW_F_INDEX:
 #ifdef IPFIREWALL_FORWARD
 	case IP_FW_F_FWD:
 #endif

--- sys/netinet/ip_fw.h.orig	Mon Aug 21 17:33:18 2000
+++ sys/netinet/ip_fw.h	Thu Jan  4 02:26:08 2001
@@ -168,6 +168,7 @@
 #define IP_FW_F_FWD	0x00000007	/* This is a "change forwarding address" rule */
 #define IP_FW_F_PIPE	0x00000008	/* This is a dummynet rule */
 #define IP_FW_F_QUEUE	0x00000009	/* This is a dummynet queue */
+#define IP_FW_F_INDEX	0x0000000A	/* This is a index rule */
 
 #define IP_FW_F_IN	0x00000100	/* Check inbound packets		*/
 #define IP_FW_F_OUT	0x00000200	/* Check outbound packets		*/

--- sbin/ipfw/ipfw.c.orig	Thu Jan  4 03:02:24 2001
+++ sbin/ipfw/ipfw.c	Thu Jan  4 03:04:20 2001
@@ -241,6 +241,9 @@
 		case IP_FW_F_SKIPTO:
 			printf("skipto %u", chain->fw_skipto_rule);
 			break;
+		case IP_FW_F_INDEX:
+			printf("index %u", chain->fw_skipto_rule);
+			break;
                 case IP_FW_F_PIPE:
                         printf("pipe %u", chain->fw_skipto_rule);
                         break ;
@@ -1648,6 +1651,11 @@
 		rule.fw_flg |= IP_FW_F_SKIPTO; av++; ac--;
 		if (!ac)
 			show_usage("missing skipto rule number");
+		rule.fw_skipto_rule = strtoul(*av, NULL, 0); av++; ac--;
+	} else if (!strncmp(*av,"index",strlen(*av))) {
+		rule.fw_flg |= IP_FW_F_INDEX; av++; ac--;
+		if (!ac)
+			show_usage("missing index rule number");
 		rule.fw_skipto_rule = strtoul(*av, NULL, 0); av++; ac--;
 	} else if ((!strncmp(*av,"deny",strlen(*av))
 		    || !strncmp(*av,"drop",strlen(*av)))) {


Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?Pine.BSF.3.96.1010104052129.462T-200000>