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>
