From owner-freebsd-net Thu Sep 28 21: 5:34 2000 Delivered-To: freebsd-net@freebsd.org Received: from alcanet.com.au (mail.alcanet.com.au [203.62.196.10]) by hub.freebsd.org (Postfix) with SMTP id 1777637B423 for ; Thu, 28 Sep 2000 21:05:20 -0700 (PDT) Received: by border.alcanet.com.au id <115252>; Fri, 29 Sep 2000 15:04:54 +1000 Content-return: prohibited Date: Fri, 29 Sep 2000 15:05:03 +1100 From: Peter Jeremy Subject: ipfw(8) divert handling To: freebsd-net@FreeBSD.ORG Reply-To: freebsd-net@FreeBSD.ORG, peter.jeremy@alcatel.com.au Message-Id: <00Sep29.150454est.115252@border.alcanet.com.au> MIME-version: 1.0 Content-type: text/plain; charset=us-ascii Content-disposition: inline User-Agent: Mutt/1.2.5i Sender: owner-freebsd-net@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.org [Please include me in any replies] The behaviour of the ipfw divert rule in both 4-STABLE and -CURRENT is different to the ipfw(8) man page. The actual behaviour is that if the diverted packet is written back into the IP stack, it will re-enter ipfw rule processing at the rule number following the divert rule[1]. According to my reading of the code, the same thing happens for a tee rule. The man page describes two different actions: - In the section RULE FORMAT.action.divert, it states "[t]he search terminates". - In the section SYSCTL VARIABLES, net.inet.ip.fw.one_pass is described as controlling divert action as well as pipe action, with the packet being re-injected at the next rule. The term "next rule", used in several places in the man page, is also slightly misleading: For pipe and queue rules it is the next rule in sequence. For divert and tee, it is the next rule with a higher rule number (ie subsequent rules with the same rule number are skipped). IMHO, there should be a way to make the rule search terminate following a successful divert (which fw.one_pass does for pipes). The patch below does this, except when the divert process changes the rule number to 0 - in which case it restarts processing. Comments please. On a different topic, I notice that struct ip_fw includes a field next_rule_ptr which is documented as "next rule in case of match". The code in ip_fw_chk() checks this field on skipto's (to avoid needing to do a linear search for skipto rules). There's even a function flush_rule_ptrs() which back this use up. Unfortunately, the code to actually assign next_rule_ptr is missing... Is there some reason why this isn't used? [1] If the divert application uses recvfrom(2)/sendto(2), it can change the rule number, but the most common divert application (natd) don't support this. Index: ip_fw.c =================================================================== RCS file: /home/CVSROOT/src/sys/netinet/ip_fw.c,v retrieving revision 1.140 diff -u -r1.140 ip_fw.c --- ip_fw.c 2000/09/12 02:38:05 1.140 +++ ip_fw.c 2000/09/29 04:01:41 @@ -1017,6 +1017,9 @@ */ chain = LIST_FIRST(&ip_fw_chain); if (skipto != 0) { + /* Accept if passed first test */ + if (fw_one_pass) + return 0; if (skipto >= IPFW_DEFAULT_RULE) goto dropit; while (chain && chain->rule->fw_number <= skipto) Peter To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-net" in the body of the message