Date: Tue, 29 Jul 2008 08:41:23 -0700 From: Jeff Kletsky <jeff+freebsd@wagsky.com> To: freebsd-ipfw@freebsd.org Subject: ipfw "bug" - recv any = not recv any Message-ID: <488F3A23.7070203@wagsky.com>
next in thread | raw e-mail | index | archive | help
The "recv any" = "not recv any" = noop behavior got me this weekend, even after careful reading of the man page. My situation is attempting to use "not recv any" to discriminate between packets generated by the host from those being routed through the host. It is reasonably easy to confirm that, at least in 7.0-RELEASE-p3, "recv any" and "not recv any" are both behaving as no-ops in the ipfw syntax. This was discussed to some extent in the post and related thread: <http://lists.freebsd.org/mailman/htdig/freebsd-ipfw/2005-August/001969.html> Luigi Rizzo wrote: > ok, so the problem is the following: when i implemented ipfw2 > i thought that 'recv any' or 'xmit any' were effectively NOPs > so the parser erroneously removes them, together with any 'not' prefix > (which is processed before). > > To fix this one should > - patch the function ipfw2.c:fill_iface() > so that an argument of 'any' puts some special pattern > in the ipfw_insn_if (e.g. an * in the first char of name[] > should suffice as i doubt it is a legal interface name). > > [...] While there are ways to do this (e.g., tagging, or "[not] recv *"), I would suggest at least clarification of the documentation. At this point, I suspect that there are enough "overly cautious" rule writers that have included "recv any" in their now-deployed rules that (properly for them) match both externally and internally generated packets that changing "recv any" to only match packets that were received would break more things than it fixes. Changing the parsing of "not recv any" to produce the code behind "not recv *" would be "less dangerous" and might be considered at some time. Let me preface this by saying that I don't know the internals of ipfw2 well enough to confirm that a doc change like this matches the operation of the code, but something along the lines of: recv | xmit | via {ifX | if* | ipno | * } Matches packets received, transmitted or going through, respec- tively, the interface specified by exact name (ifX), by device name (if*), by IP address, or through some interface (*). The via keyword causes the interface to always be checked. If recv or xmit is used instead of via, then only the receive or transmit interface (respectively) is checked. By specifying both, it is possible to match packets based on both receive and transmit interface, e.g.: ipfw add deny ip from any to any out recv ed0 xmit ed1 The recv interface can be tested on either incoming or outgoing packets, while the xmit interface can only be tested on outgoing packets. So out is required (and in is invalid) whenever xmit is used. A packet may not have a receive or transmit interface: packets originating from the local host have no receive interface, while packets destined for the local host have no transmit interface. To match packets that have no receive interface, the construct "not recv *" may be used. The constructs "recv any" and "not recv any" are presently both treated equivalently as a match-all condition and both are stripped during parsing. This behavior, especially of the latter, is subject to change in future releases, and is not suggested for new rule sets. I hope this post at least helps the next person who trips across this. I'm very open to ideas on how to clarify and/or improve the behavior. I haven't looked into the other "any" matches to see if they have similar behavior that would benefit from additional documentation Jeff P.S. Thanks to Julian Elischer for suggesting "not recv *" as an approach.
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?488F3A23.7070203>