From root@atlantis.dp.ua  Wed Mar 29 21:18:58 2006
Return-Path: <root@atlantis.dp.ua>
Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125])
	by hub.freebsd.org (Postfix) with ESMTP id 2C30E16A422
	for <FreeBSD-gnats-submit@freebsd.org>; Wed, 29 Mar 2006 21:18:58 +0000 (UTC)
	(envelope-from root@atlantis.dp.ua)
Received: from postman.atlantis.dp.ua (postman.atlantis.dp.ua [193.108.47.1])
	by mx1.FreeBSD.org (Postfix) with ESMTP id 0595843D72
	for <FreeBSD-gnats-submit@freebsd.org>; Wed, 29 Mar 2006 21:18:55 +0000 (GMT)
	(envelope-from root@atlantis.dp.ua)
Received: from homelynx.homenet (p161.atlantis.dp.ua [193.19.241.161])
	by postman.atlantis.dp.ua (8.13.1/8.13.1) with ESMTP id k2TLIiYH055638
	for <FreeBSD-gnats-submit@freebsd.org>; Thu, 30 Mar 2006 00:18:44 +0300 (EEST)
	(envelope-from root@atlantis.dp.ua)
Received: from homelynx.homenet (localhost [127.0.0.1])
	by homelynx.homenet (8.13.4/8.13.4) with ESMTP id k2TLIhYU001521
	for <FreeBSD-gnats-submit@freebsd.org>; Thu, 30 Mar 2006 00:18:43 +0300 (EEST)
	(envelope-from root@homelynx.homenet)
Received: (from root@localhost)
	by homelynx.homenet (8.13.4/8.13.4/Submit) id k2TLIhe9001520;
	Thu, 30 Mar 2006 00:18:43 +0300 (EEST)
	(envelope-from root)
Message-Id: <200603292118.k2TLIhe9001520@homelynx.homenet>
Date: Thu, 30 Mar 2006 00:18:43 +0300 (EEST)
From: Dmitry Pryanishnikov <lynx.ripe@gmail.com>
Reply-To: Dmitry Pryanishnikov <lynx.ripe@gmail.com>
To: FreeBSD-gnats-submit@freebsd.org
Cc:
Subject: [patch] IPFW2 ignores "recv/xmit/via any" (IPFW1->2 regression)
X-Send-Pr-Version: 3.113
X-GNATS-Notify:

>Number:         95084
>Category:       kern
>Synopsis:       [ipfw] [regression] [patch] IPFW2 ignores "recv/xmit/via any" (IPFW1->2 regression)
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    freebsd-ipfw
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Wed Mar 29 21:20:19 GMT 2006
>Closed-Date:    
>Last-Modified:  Mon May 05 01:14:31 UTC 2008
>Originator:     Dmitry Pryanishnikov
>Release:        FreeBSD 7.0-CURRENT i386
>Organization:
Atlantis ISP
>Environment:
System: FreeBSD homelynx.homenet 7.0-CURRENT FreeBSD 7.0-CURRENT #0: Sun Mar 19 00:33:05 EET 2006 root@homelynx.homenet:/usr/CURRENT/obj/usr/CURRENT/src/sys/lynx i386

>Description:

 IPFW2 (unlike IPFW1) ignores documented construction "recv/xmit/via any".

See ipfw(8):

     recv | xmit | via {ifX | if* | ipno | any}
	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.
...................................^^^^^^^^^^^^^^^^^^^^^^^^^
        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.

So it's OK (and convenient) to use "recv any" as a marker of transit
(in contrast to locally-originated) packets. However, ipfw2 completely
(and silently) ignores "recv/xmit/via any", which can break e.g.
traffic accounting: rule "count all from any to any out recv any" becomes
"count all from any to any out" and thus starts to count all outgoing
traffic instead of just transit one. This can be dangerous because
the change is silent, and can only be found by the analysis of resulting
ruleset.

 Note that "xmit any" seems to be useless (though harmless) because
packets destined for the local host don't hit rules marked "out",
and "xmit" interface is undefined for "in" rules. I don't see the point
in special handling for this case. This fact just probably should be documented.

>How-To-Repeat:

 Do it on transit router which also originates some traffic:

root@homelynx# cat a.sh
ipfw -f flush
ipfw add 10 count all from any to any out
ipfw add 20 count all from any to any out recv any
ipfw add 60000 pass all from any to any
root@homelynx# sh a.sh
...
root@homelynx# ipfw show
00010 216 25555 count ip from any to any out
00020 216 25555 count ip from any to any out
60000 425 52158 allow ip from any to any
65535   0     0 deny ip from any to any

>Fix:

 The following patch fixes the problem in CURRENT:

--- sys/netinet/ip_fw2.c.orig	Tue Mar 14 10:05:15 2006
+++ sys/netinet/ip_fw2.c	Tue Mar 28 21:13:03 2006
@@ -453,7 +453,8 @@
 	if (cmd->name[0] != '\0') { /* match by name */
 		/* Check name */
 		if (cmd->p.glob) {
-			if (fnmatch(cmd->name, ifp->if_xname, 0) == 0)
+			if ((cmd->name[0] == '*' && cmd->name[1] == '\0') ||
+			    fnmatch(cmd->name, ifp->if_xname, 0) == 0)
 				return(1);
 		} else {
 			if (strncmp(ifp->if_xname, cmd->name, IFNAMSIZ) == 0)
--- sbin/ipfw/ipfw2.c.orig	Tue Mar 14 10:02:52 2006
+++ sbin/ipfw/ipfw2.c	Wed Mar 29 00:22:43 2006
@@ -1741,6 +1741,8 @@
 				if (cmdif->name[0] == '\0')
 					printf(" %s %s", s,
 					    inet_ntoa(cmdif->p.ip));
+				else if (strcmp(cmdif->name, "*") == 0)
+					printf(" %s any", s);
 				else
 					printf(" %s %s", s, cmdif->name);
 
@@ -3094,11 +3096,11 @@
 	cmd->o.len |= F_INSN_SIZE(ipfw_insn_if);
 
 	/* Parse the interface or address */
-	if (strcmp(arg, "any") == 0)
-		cmd->o.len = 0;		/* effectively ignore this command */
-	else if (!isdigit(*arg)) {
+	if (!isdigit(*arg)) {
 		strlcpy(cmd->name, arg, sizeof(cmd->name));
-		cmd->p.glob = strpbrk(arg, "*?[") != NULL ? 1 : 0;
+		if (strcmp(arg, "any") == 0)
+		    strcpy(cmd->name, "*");
+		cmd->p.glob = strpbrk(cmd->name, "*?[") != NULL ? 1 : 0;
 	} else if (!inet_aton(arg, &cmd->p.ip))
 		errx(EX_DATAERR, "bad ip address ``%s''", arg);
 }


Patch tries to maintain maximum compatibility (new /sbin/ipfw is even
functional with old kernel and vice versa). It just converts "any" to
logically equivalent "*" (code in ipfw) and optimizes this partucular
construction (code in kernel) to improve scalability (in traffic
accounting session "recv any" tends to repeat many times). With this
patch applied my example works correctly:

root@homelynx# ipfw show
00010  821 333189 count ip from any to any out
00020  751 328766 count ip from any to any out recv any
60000 1638 668605 allow ip from any to any
65535    0      0 deny ip from any to any
>Release-Note:
>Audit-Trail:
Responsible-Changed-From-To: freebsd-bugs->freebsd-ipfw 
Responsible-Changed-By: linimon 
Responsible-Changed-When: Fri Mar 31 17:52:29 UTC 2006 
Responsible-Changed-Why:  
Over to maintainer(s). 

http://www.freebsd.org/cgi/query-pr.cgi?pr=95084 

From: Marcelo Araujo <araujobsdport@gmail.com>
To: bug-followup@FreeBSD.org
Cc:  
Subject: kern/95084: [ipfw] [patch] IPFW2 ignores "recv/xmit/via any" (IPFW1->2
 regression)
Date: Tue, 26 Feb 2008 08:31:50 -0300

 This is an OpenPGP/MIME signed message (RFC 2440 and 3156)
 --------------enig647B1A8628059BB1DC3BD3FE
 Content-Type: text/plain; charset=UTF-8
 Content-Transfer-Encoding: quoted-printable
 
 Hi dear,
 
 For this situation you can't use:
 island# ipfw add 10 count all from any to any recv out
 island# ipfw show 10
 00010      0        0 count ip from any to any recv out
 
 Best Regards,
 
 --=20
 Marcelo Araujo            (__)
 araujo@FreeBSD.org     \\\'',)
 http://www.FreeBSD.org   \/  \ ^
 Power To Server.         .\. /_)
 
 
 
 --------------enig647B1A8628059BB1DC3BD3FE
 Content-Type: application/pgp-signature; name="signature.asc"
 Content-Description: OpenPGP digital signature
 Content-Disposition: attachment; filename="signature.asc"
 
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1.4.7 (FreeBSD)
 
 iD8DBQFHw/iqovxJd1Pkz6gRAmO+AJ0c4qgWL1a0ntAnOPWJUo2mJcqapACeJMax
 Zil7Q2vgME0Z2YhrKpCSF2o=
 =FqQ1
 -----END PGP SIGNATURE-----
 
 --------------enig647B1A8628059BB1DC3BD3FE--
>Unformatted:
