From nobody@FreeBSD.org  Wed May 27 05:32:52 2009
Return-Path: <nobody@FreeBSD.org>
Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34])
	by hub.freebsd.org (Postfix) with ESMTP id 59F751065672
	for <freebsd-gnats-submit@FreeBSD.org>; Wed, 27 May 2009 05:32:52 +0000 (UTC)
	(envelope-from nobody@FreeBSD.org)
Received: from www.freebsd.org (www.freebsd.org [IPv6:2001:4f8:fff6::21])
	by mx1.freebsd.org (Postfix) with ESMTP id 488EE8FC12
	for <freebsd-gnats-submit@FreeBSD.org>; Wed, 27 May 2009 05:32:52 +0000 (UTC)
	(envelope-from nobody@FreeBSD.org)
Received: from www.freebsd.org (localhost [127.0.0.1])
	by www.freebsd.org (8.14.3/8.14.3) with ESMTP id n4R5WqQW085241
	for <freebsd-gnats-submit@FreeBSD.org>; Wed, 27 May 2009 05:32:52 GMT
	(envelope-from nobody@www.freebsd.org)
Received: (from nobody@localhost)
	by www.freebsd.org (8.14.3/8.14.3/Submit) id n4R5Wqsb085240;
	Wed, 27 May 2009 05:32:52 GMT
	(envelope-from nobody)
Message-Id: <200905270532.n4R5Wqsb085240@www.freebsd.org>
Date: Wed, 27 May 2009 05:32:52 GMT
From: Cyberman Wu <cyberman.wu@gmail.com>
To: freebsd-gnats-submit@FreeBSD.org
Subject: ipfw can't work with set in rule file.
X-Send-Pr-Version: www-3.1
X-GNATS-Notify:

>Number:         134975
>Category:       bin
>Synopsis:       [patch] ipfw(8) can't work with set in rule file.
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-ipfw
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Wed May 27 05:40:00 UTC 2009
>Closed-Date:    Mon Jun 20 13:55:47 UTC 2011
>Last-Modified:  Mon Jun 20 14:00:25 UTC 2011
>Originator:     Cyberman Wu
>Release:        FreeBSD 7.0r-p5
>Organization:
Meganovo
>Environment:
FreeBSD test.freebsd.com 7.0-RELEASE-p5 FreeBSD 7.0-RELEASE-p5 #0: Wed Oct  1 10:10:12 UTC 2008     root@i386-builder.daemonology.net:/usr/obj/usr/src/sys/GENERIC  i386
>Description:
First to say, I've tested on both FreeBSD 7.1 and 7.2 and the problem is still here. The only change is the later versions use a structure to organize global variables. Since I'm more familiar with 7.0 I'll use its code to illustrate the problem.

These days I'm thinking to port ipfw to another system, and when I read the source code I found here will cause a problem in ipfw_main from ipfw2.c:
	/*
	 * Optional: pipe, queue or nat.
	 */
	do_nat = 0;
	do_pipe = 0;
	if (!strncmp(*av, "nat", strlen(*av)))
 	        do_nat = 1;
 	else if (!strncmp(*av, "pipe", strlen(*av)))
		do_pipe = 1;
	else if (_substrcmp(*av, "queue") == 0)
		do_pipe = 2;
	else if (!strncmp(*av, "set", strlen(*av))) {
		if (ac > 1 && isdigit(av[1][0])) {
			use_set = strtonum(av[1], 0, RESVD_SET, &errstr);
			if (errstr)
				errx(EX_DATAERR,
				    "invalid set number %s\n", av[1]);
			ac -= 2; av += 2; use_set++;
		}
	}

If we specify rule file using 'pathname' on command line rather than a command, ipfw_main will be called in loop, but once 'use_set' is set, it will never be clear again, if the next rule is some command like 'add', since 'use_set' is not  zero, it will either say 'bad command' or do some other things:
	int try_next = 0;
	if (use_set == 0) {
		if (_substrcmp(*av, "add") == 0)
			add(ac, av);
		else if (do_nat && _substrcmp(*av, "show") == 0)
 			show_nat(ac, av);
		else if (do_pipe && _substrcmp(*av, "config") == 0)
			config_pipe(ac, av);
		else if (do_nat && _substrcmp(*av, "config") == 0)
 			config_nat(ac, av);
			else if (_substrcmp(*av, "set") == 0)
				sets_handler(ac, av);
			else if (_substrcmp(*av, "table") == 0)
				table_handler(ac, av);
			else if (_substrcmp(*av, "enable") == 0)
				sysctl_handler(ac, av, 1);
			else if (_substrcmp(*av, "disable") == 0)
				sysctl_handler(ac, av, 0);
			else
				try_next = 1;
	}

	if (use_set || try_next) {
		if (_substrcmp(*av, "delete") == 0)
			delete(ac, av);
		else if (_substrcmp(*av, "flush") == 0)
			flush(do_force);
		else if (_substrcmp(*av, "zero") == 0)
			zero(ac, av, IP_FW_ZERO);
		else if (_substrcmp(*av, "resetlog") == 0)
			zero(ac, av, IP_FW_RESETLOG);
		else if (_substrcmp(*av, "print") == 0 ||
		         _substrcmp(*av, "list") == 0)
			list(ac, av, do_acct);
		else if (_substrcmp(*av, "show") == 0)
			list(ac, av, 1 /* show counters */);
		else
			errx(EX_USAGE, "bad command `%s'", *av);
	}

Then I test it on FreeBSD 7.0/7.1/7.2, all the same.
>How-To-Repeat:
First create a file 'fw_test.rule' which including the following commands:

-q set 12 flush
add set 12 allow tcp from any to me 12345 in
add set 12 allow tcp from me 12345 to any out


Then use ipfw to execute it:

test# ipfw /root/fw_test.rule
Line 2: bad command `add'
>Fix:

	/*
	 * Optional: pipe, queue or nat.
	 */
	do_nat = 0;
	do_pipe = 0;
	/*
	 * Added by Cyberman Wu on May 16th, 2009.
	 */
	use_set = 0;
	if (!strncmp(*av, "nat", strlen(*av)))
 	        do_nat = 1;
 	else if (!strncmp(*av, "pipe", strlen(*av)))
		do_pipe = 1;
	else if (_substrcmp(*av, "queue") == 0)
		do_pipe = 2;
	else if (!strncmp(*av, "set", strlen(*av))) {
		if (ac > 1 && isdigit(av[1][0])) {
			use_set = strtonum(av[1], 0, RESVD_SET, &errstr);
			if (errstr)
				errx(EX_DATAERR,
				    "invalid set number %s\n", av[1]);
			ac -= 2; av += 2; use_set++;
		}
	}

>Release-Note:
>Audit-Trail:
Responsible-Changed-From-To: freebsd-bugs->freebsd-ipfw 
Responsible-Changed-By: linimon 
Responsible-Changed-When: Tue Jun 2 08:04:12 UTC 2009 
Responsible-Changed-Why:  
Over to maintainer(s). 

http://www.freebsd.org/cgi/query-pr.cgi?pr=134975 
State-Changed-From-To: open->patched 
State-Changed-By: ae 
State-Changed-When: Mon Jun 6 11:10:59 UTC 2011 
State-Changed-Why:  
Committed to head/. Thanks! 

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

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: bin/134975: commit references a PR
Date: Mon,  6 Jun 2011 11:12:18 +0000 (UTC)

 Author: ae
 Date: Mon Jun  6 11:10:38 2011
 New Revision: 222745
 URL: http://svn.freebsd.org/changeset/base/222745
 
 Log:
   Initialize co.use_set variable before parsing each new rule.
   
   PR:		bin/134975
   MFC after:	2 weeks
 
 Modified:
   head/sbin/ipfw/main.c
 
 Modified: head/sbin/ipfw/main.c
 ==============================================================================
 --- head/sbin/ipfw/main.c	Mon Jun  6 10:52:26 2011	(r222744)
 +++ head/sbin/ipfw/main.c	Mon Jun  6 11:10:38 2011	(r222745)
 @@ -356,6 +356,7 @@ ipfw_main(int oldac, char **oldav)
  	 */
  	co.do_nat = 0;
  	co.do_pipe = 0;
 +	co.use_set = 0;
  	if (!strncmp(*av, "nat", strlen(*av)))
   		co.do_nat = 1;
   	else if (!strncmp(*av, "pipe", strlen(*av)))
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 
State-Changed-From-To: patched->closed 
State-Changed-By: ae 
State-Changed-When: Mon Jun 20 13:55:21 UTC 2011 
State-Changed-Why:  
Merged to stable/8 and stable/7. Thanks! 

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

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: bin/134975: commit references a PR
Date: Mon, 20 Jun 2011 13:52:14 +0000 (UTC)

 Author: ae
 Date: Mon Jun 20 13:51:53 2011
 New Revision: 223338
 URL: http://svn.freebsd.org/changeset/base/223338
 
 Log:
   MFC r222745:
     Initialize co.use_set variable before parsing each new rule.
   
     PR:		bin/134975
 
 Modified:
   stable/8/sbin/ipfw/main.c
 Directory Properties:
   stable/8/sbin/ipfw/   (props changed)
 
 Modified: stable/8/sbin/ipfw/main.c
 ==============================================================================
 --- stable/8/sbin/ipfw/main.c	Mon Jun 20 13:46:57 2011	(r223337)
 +++ stable/8/sbin/ipfw/main.c	Mon Jun 20 13:51:53 2011	(r223338)
 @@ -356,6 +356,7 @@ ipfw_main(int oldac, char **oldav)
  	 */
  	co.do_nat = 0;
  	co.do_pipe = 0;
 +	co.use_set = 0;
  	if (!strncmp(*av, "nat", strlen(*av)))
   	        co.do_nat = 1;
   	else if (!strncmp(*av, "pipe", strlen(*av)))
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: bin/134975: commit references a PR
Date: Mon, 20 Jun 2011 13:52:35 +0000 (UTC)

 Author: ae
 Date: Mon Jun 20 13:52:14 2011
 New Revision: 223339
 URL: http://svn.freebsd.org/changeset/base/223339
 
 Log:
   MFC r222745:
     Initialize co.use_set variable before parsing each new rule.
   
     PR:		bin/134975
 
 Modified:
   stable/7/sbin/ipfw/main.c
 Directory Properties:
   stable/7/sbin/ipfw/   (props changed)
 
 Modified: stable/7/sbin/ipfw/main.c
 ==============================================================================
 --- stable/7/sbin/ipfw/main.c	Mon Jun 20 13:51:53 2011	(r223338)
 +++ stable/7/sbin/ipfw/main.c	Mon Jun 20 13:52:14 2011	(r223339)
 @@ -298,6 +298,7 @@ ipfw_main(int oldac, char **oldav)
  	 */
  	co.do_nat = 0;
  	co.do_pipe = 0;
 +	co.use_set = 0;
  	if (!strncmp(*av, "nat", strlen(*av)))
   	        co.do_nat = 1;
   	else if (!strncmp(*av, "pipe", strlen(*av)))
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 
>Unformatted:
