From elsukov@rdu.kirov.ru  Thu May  5 06:02:55 2005
Return-Path: <elsukov@rdu.kirov.ru>
Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125])
	by hub.freebsd.org (Postfix) with ESMTP id 7B3DC16A4CE
	for <FreeBSD-gnats-submit@freebsd.org>; Thu,  5 May 2005 06:02:55 +0000 (GMT)
Received: from mail.rdu.kirov.ru (ns.rdu.kirov.ru [217.9.151.217])
	by mx1.FreeBSD.org (Postfix) with ESMTP id DE44543D94
	for <FreeBSD-gnats-submit@freebsd.org>; Thu,  5 May 2005 06:02:53 +0000 (GMT)
	(envelope-from elsukov@rdu.kirov.ru)
Received: from rdu.kirov.ru (localhost [127.0.0.1])
	by mail.rdu.kirov.ru (Postfix) with ESMTP id 1702CFDDE
	for <FreeBSD-gnats-submit@freebsd.org>; Thu,  5 May 2005 10:02:52 +0400 (MSD)
Received: (from elsukov@localhost)
	by rdu.kirov.ru (8.12.10/8.12.9/Submit) id j4562qgC052950;
	Thu, 5 May 2005 10:02:52 +0400 (MSD)
Message-Id: <200505050602.j4562qgC052950@rdu.kirov.ru>
Date: Thu, 5 May 2005 10:02:52 +0400 (MSD)
From: "Andrey V. Elsukov" <bu7cher@yandex.ru>
Reply-To: "Andrey V. Elsukov" <bu7cher@yandex.ru>
To: FreeBSD-gnats-submit@freebsd.org
Cc:
Subject: IPFW small patch - new RULE OPTION
X-Send-Pr-Version: 3.113
X-GNATS-Notify:

>Number:         80642
>Category:       kern
>Synopsis:       [ipfw] [patch] ipfw small patch - new RULE OPTION
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-ipfw
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Thu May 05 06:10:02 GMT 2005
>Closed-Date:    Mon Dec 13 11:15:47 UTC 2010
>Last-Modified:  Mon Dec 13 11:15:47 UTC 2010
>Originator:     Andrey V. Elsukov
>Release:        FreeBSD 5.4-STABLE i386
>Organization:
>Environment:
	RELENG_5
>Description:
This is small patch for IPFW.
Patch add new rule option - bound value. Rules with this option match while rule bytes counter below specified bound value. Example:

ipfw add 100 allow ip from any to A.B.C.D in recv Ext_Interface bound 1000000
ipfw add 200 deny ip from any to A.B.C.D

While bytes counter below that 1000000, then rule 100 matchs. 
>How-To-Repeat:
>Fix:


--- ipfw_bound.diff begins here ---
--- sys/netinet/ip_fw.h.orig	Tue Feb  1 02:26:35 2005
+++ sys/netinet/ip_fw.h	Tue May  3 22:38:07 2005
@@ -78,6 +78,7 @@
 	O_RECV,			/* none				*/
 	O_XMIT,			/* none				*/
 	O_VIA,			/* none				*/
+	O_BOUND,		/* u64 = bound in bytes */
 
 	O_IPOPT,		/* arg1 = 2*u8 bitmap		*/
 	O_IPLEN,		/* arg1 = len			*/
@@ -198,6 +199,14 @@
 	ipfw_insn o;
 	u_int32_t d[1];	/* one or more */
 } ipfw_insn_u32;
+
+/*
+ * This is used to store 64-bit bound value.
+ */
+typedef struct	_ipfw_insn_u64 {
+	ipfw_insn o;
+	u_int64_t bound;
+} ipfw_insn_u64;
 
 /*
  * This is used to store IP addr-mask pairs.

--- sys/netinet/ip_fw2.c.orig	Sun Feb  6 19:16:20 2005
+++ sys/netinet/ip_fw2.c	Tue May  3 22:22:04 2005
@@ -2294,6 +2294,9 @@
 				/* otherwise no match */
 				break;
 
+			case O_BOUND:
+				match = (f->bcnt < ((ipfw_insn_u64 *)cmd)->bound);
+				break;
 			/*
 			 * The second set of opcodes represents 'actions',
 			 * i.e. the terminal part of a rule once the packet
@@ -2939,6 +2942,11 @@
 			if (cmdlen != F_INSN_SIZE(ipfw_insn_u32))
 				goto bad_size;
 			break;
+
+		case O_BOUND:
+			if (cmdlen != F_INSN_SIZE(ipfw_insn_u64))
+				goto bad_size;
+			break;	
 
 		case O_LIMIT:
 			if (cmdlen != F_INSN_SIZE(ipfw_insn_limit))

--- sbin/ipfw/ipfw2.c.orig	Tue Jan 25 10:23:34 2005
+++ sbin/ipfw/ipfw2.c	Tue May  3 22:56:41 2005
@@ -236,6 +236,7 @@
 	TOK_ANTISPOOF,
 	TOK_IPSEC,
 	TOK_COMMENT,
+	TOK_BOUND,
 
 	TOK_PLR,
 	TOK_NOERROR,
@@ -351,6 +352,7 @@
 	{ "antispoof",		TOK_ANTISPOOF },
 	{ "ipsec",		TOK_IPSEC },
 	{ "//",			TOK_COMMENT },
+	{ "bound",		TOK_BOUND },
 
 	{ "not",		TOK_NOT },		/* pseudo option */
 	{ "!", /* escape ? */	TOK_NOT },		/* pseudo option */
@@ -1198,6 +1200,9 @@
 
 				break;
 			    }
+			case O_BOUND:
+				printf(" bound %u", ((ipfw_insn_u64 *)cmd)->bound);
+				break;
 			case O_IPID:
 				if (F_LEN(cmd) == 1)
 				    printf(" ipid %u", cmd->arg1 );
@@ -1917,7 +1922,7 @@
 "	ipttl LIST | ipversion VER | keep-state | layer2 | limit ... |\n"
 "	mac ... | mac-type LIST | proto LIST | {recv|xmit|via} {IF|IPADDR} |\n"
 "	setup | {tcpack|tcpseq|tcpwin} NN | tcpflags SPEC | tcpoptions SPEC |\n"
-"	verrevpath | versrcreach | antispoof\n"
+"	bound VALUE | verrevpath | versrcreach | antispoof\n"
 );
 exit(0);
 }
@@ -3220,6 +3225,14 @@
 				cmd->opcode = O_RECV;
 			else if (i == TOK_VIA)
 				cmd->opcode = O_VIA;
+			break;
+
+		case TOK_BOUND:
+			NEED1("bound requires numeric value");
+            cmd->opcode = O_BOUND;
+			((ipfw_insn_u64 *)cmd)->bound = strtoull(*av, NULL, 0);
+            cmd->len |= F_INSN_SIZE(ipfw_insn_u64);
+            ac--; av++;
 			break;
 
 		case TOK_ICMPTYPES:

--- sbin/ipfw/ipfw.8.orig	Wed Mar  2 22:50:11 2005
+++ sbin/ipfw/ipfw.8	Wed May  4 19:23:13 2005
@@ -920,6 +920,8 @@
 .It Cm bridged
 Alias for
 .Cm layer2 .
+.It Cm bound Ar value
+Matches while bytes counter below bound value.
 .It Cm dst-ip Ar ip-address
 Matches IP packets whose destination IP is one of the address(es)
 specified as argument.
--- ipfw_bound.diff ends here ---


>Release-Note:
>Audit-Trail:

From: Robert Watson <rwatson@FreeBSD.org>
To: FreeBSD-gnats-submit@FreeBSD.org
Cc:  
Subject: Re: kern/80642: IPFW small patch - new RULE OPTION
Date: Sun, 15 May 2005 06:30:20 +0100 (BST)

 This patch breaks the ABI by inserting a new type into an implicitly 
 numbered enumeration, renumbering all entries later in the enum. 
 O_BOUND, if added, should be appended to the end, and/or we should number 
 the operations explicitly.
 
 Robert N M Watson
 
 On Thu, 5 May 2005, Andrey V. Elsukov wrote:
 
 >
 >> Number:         80642
 >> Category:       kern
 >> Synopsis:       IPFW small patch - new RULE OPTION
 >> Confidential:   no
 >> Severity:       non-critical
 >> Priority:       low
 >> Responsible:    freebsd-bugs
 >> State:          open
 >> Quarter:
 >> Keywords:
 >> Date-Required:
 >> Class:          change-request
 >> Submitter-Id:   current-users
 >> Arrival-Date:   Thu May 05 06:10:02 GMT 2005
 >> Closed-Date:
 >> Last-Modified:
 >> Originator:     Andrey V. Elsukov
 >> Release:        FreeBSD 5.4-STABLE i386
 >> Organization:
 >> Environment:
 > 	RELENG_5
 >> Description:
 > This is small patch for IPFW.
 > Patch add new rule option - bound value. Rules with this option match while rule bytes counter below specified bound value. Example:
 >
 > ipfw add 100 allow ip from any to A.B.C.D in recv Ext_Interface bound 1000000
 > ipfw add 200 deny ip from any to A.B.C.D
 >
 > While bytes counter below that 1000000, then rule 100 matchs.
 >> How-To-Repeat:
 >> Fix:
 >
 >
 > --- ipfw_bound.diff begins here ---
 > --- sys/netinet/ip_fw.h.orig	Tue Feb  1 02:26:35 2005
 > +++ sys/netinet/ip_fw.h	Tue May  3 22:38:07 2005
 > @@ -78,6 +78,7 @@
 > 	O_RECV,			/* none				*/
 > 	O_XMIT,			/* none				*/
 > 	O_VIA,			/* none				*/
 > +	O_BOUND,		/* u64 = bound in bytes */
 >
 > 	O_IPOPT,		/* arg1 = 2*u8 bitmap		*/
 > 	O_IPLEN,		/* arg1 = len			*/
 > @@ -198,6 +199,14 @@
 > 	ipfw_insn o;
 > 	u_int32_t d[1];	/* one or more */
 > } ipfw_insn_u32;
 > +
 > +/*
 > + * This is used to store 64-bit bound value.
 > + */
 > +typedef struct	_ipfw_insn_u64 {
 > +	ipfw_insn o;
 > +	u_int64_t bound;
 > +} ipfw_insn_u64;
 >
 > /*
 >  * This is used to store IP addr-mask pairs.
 >
 > --- sys/netinet/ip_fw2.c.orig	Sun Feb  6 19:16:20 2005
 > +++ sys/netinet/ip_fw2.c	Tue May  3 22:22:04 2005
 > @@ -2294,6 +2294,9 @@
 > 				/* otherwise no match */
 > 				break;
 >
 > +			case O_BOUND:
 > +				match = (f->bcnt < ((ipfw_insn_u64 *)cmd)->bound);
 > +				break;
 > 			/*
 > 			 * The second set of opcodes represents 'actions',
 > 			 * i.e. the terminal part of a rule once the packet
 > @@ -2939,6 +2942,11 @@
 > 			if (cmdlen != F_INSN_SIZE(ipfw_insn_u32))
 > 				goto bad_size;
 > 			break;
 > +
 > +		case O_BOUND:
 > +			if (cmdlen != F_INSN_SIZE(ipfw_insn_u64))
 > +				goto bad_size;
 > +			break;
 >
 > 		case O_LIMIT:
 > 			if (cmdlen != F_INSN_SIZE(ipfw_insn_limit))
 >
 > --- sbin/ipfw/ipfw2.c.orig	Tue Jan 25 10:23:34 2005
 > +++ sbin/ipfw/ipfw2.c	Tue May  3 22:56:41 2005
 > @@ -236,6 +236,7 @@
 > 	TOK_ANTISPOOF,
 > 	TOK_IPSEC,
 > 	TOK_COMMENT,
 > +	TOK_BOUND,
 >
 > 	TOK_PLR,
 > 	TOK_NOERROR,
 > @@ -351,6 +352,7 @@
 > 	{ "antispoof",		TOK_ANTISPOOF },
 > 	{ "ipsec",		TOK_IPSEC },
 > 	{ "//",			TOK_COMMENT },
 > +	{ "bound",		TOK_BOUND },
 >
 > 	{ "not",		TOK_NOT },		/* pseudo option */
 > 	{ "!", /* escape ? */	TOK_NOT },		/* pseudo option */
 > @@ -1198,6 +1200,9 @@
 >
 > 				break;
 > 			    }
 > +			case O_BOUND:
 > +				printf(" bound %u", ((ipfw_insn_u64 *)cmd)->bound);
 > +				break;
 > 			case O_IPID:
 > 				if (F_LEN(cmd) == 1)
 > 				    printf(" ipid %u", cmd->arg1 );
 > @@ -1917,7 +1922,7 @@
 > "	ipttl LIST | ipversion VER | keep-state | layer2 | limit ... |\n"
 > "	mac ... | mac-type LIST | proto LIST | {recv|xmit|via} {IF|IPADDR} |\n"
 > "	setup | {tcpack|tcpseq|tcpwin} NN | tcpflags SPEC | tcpoptions SPEC |\n"
 > -"	verrevpath | versrcreach | antispoof\n"
 > +"	bound VALUE | verrevpath | versrcreach | antispoof\n"
 > );
 > exit(0);
 > }
 > @@ -3220,6 +3225,14 @@
 > 				cmd->opcode = O_RECV;
 > 			else if (i == TOK_VIA)
 > 				cmd->opcode = O_VIA;
 > +			break;
 > +
 > +		case TOK_BOUND:
 > +			NEED1("bound requires numeric value");
 > +            cmd->opcode = O_BOUND;
 > +			((ipfw_insn_u64 *)cmd)->bound = strtoull(*av, NULL, 0);
 > +            cmd->len |= F_INSN_SIZE(ipfw_insn_u64);
 > +            ac--; av++;
 > 			break;
 >
 > 		case TOK_ICMPTYPES:
 >
 > --- sbin/ipfw/ipfw.8.orig	Wed Mar  2 22:50:11 2005
 > +++ sbin/ipfw/ipfw.8	Wed May  4 19:23:13 2005
 > @@ -920,6 +920,8 @@
 > .It Cm bridged
 > Alias for
 > .Cm layer2 .
 > +.It Cm bound Ar value
 > +Matches while bytes counter below bound value.
 > .It Cm dst-ip Ar ip-address
 > Matches IP packets whose destination IP is one of the address(es)
 > specified as argument.
 > --- ipfw_bound.diff ends here ---
 >
 >
 >> Release-Note:
 >> Audit-Trail:
 >> Unformatted:
 > _______________________________________________
 > freebsd-bugs@freebsd.org mailing list
 > http://lists.freebsd.org/mailman/listinfo/freebsd-bugs
 > To unsubscribe, send any mail to "freebsd-bugs-unsubscribe@freebsd.org"
 >

From: "Andrey V. Elsukov" <elsukov@rdu.kirov.ru>
To: bug-followup@FreeBSD.org, bu7cher@yandex.ru
Cc:  
Subject: Re: kern/80642: [patch] IPFW small patch - new RULE OPTION
Date: Tue, 24 May 2005 07:42:53 +0400

 Sorry, my english is bad.  :(
 
 Patch to IPFW2 for adding restrictions of the traffic with use IPFW
 bytes counters.
 It include two parts:
 
 * First part is ipfw_bound.patch, this part add ipfw rule options "bound
 VALUE" and "check-bound NUM".
 Example:
 # ipfw add 100 allow ip from any to any bound 10K
 # ipfw add 200 deny ip from any to any
 
 While bytes counter of rule 100 below 10 KBytes, it work.
 
 Example:
 # ipfw add 100 allow ip from A.B.C.D to any out xmit internet
 check-bound 200
 # ipfw add 200 allow ip from any to A.B.C.D in recv internet bound 100M
 # ipfw add 300 deny ip from any to any via internet
 
 While bytes counter of rule 200 below 100 MBytes, rules 100 and 200 work.
 NOTE: Check-bound option search rule NUM like "ipfw skipto", but if rule
 NUM not contain bound option, then match fail.
 
 Second part is bound_change.patch, this part add control call to ipfw
 for boundary value change without bytes counter reset.
 Syntax:
 # ipfw bound NUM [set N] change VALUE.
 
 Files:
 For CURRENT:
 http://butcher.heavennet.ru/ipfw_bound/CURRENT/ipfw_bound.patch
 http://butcher.heavennet.ru/ipfw_bound/CURRENT/bound_change.patch
 
 For RELENG_5:
 http://butcher.heavennet.ru/ipfw_bound/RELENG_5/ipfw_bound.patch
 http://butcher.heavennet.ru/ipfw_bound/RELENG_5/bound_change.patch
 
 For RELENG_5_4:
 http://butcher.heavennet.ru/ipfw_bound/RELENG_5_4/ipfw_bound.patch
 http://butcher.heavennet.ru/ipfw_bound/RELENG_5_4/bound_change.patch
 
 -- 
 WBR, Andrey V. Elsukov
 

From: "Andrey V. Elsukov" <elsukov@rdu.kirov.ru>
To: freebsd-bugs@FreeBSD.org
Cc:  
Subject: Re: kern/80642: [patch] IPFW small patch - new RULE OPTION
Date: Tue, 24 May 2005 03:50:06 GMT

 The following reply was made to PR kern/80642; it has been noted by GNATS.
 
 From: "Andrey V. Elsukov" <elsukov@rdu.kirov.ru>
 To: bug-followup@FreeBSD.org, bu7cher@yandex.ru
 Cc:  
 Subject: Re: kern/80642: [patch] IPFW small patch - new RULE OPTION
 Date: Tue, 24 May 2005 07:42:53 +0400
 
  Sorry, my english is bad.  :(
  
  Patch to IPFW2 for adding restrictions of the traffic with use IPFW
  bytes counters.
  It include two parts:
  
  * First part is ipfw_bound.patch, this part add ipfw rule options "bound
  VALUE" and "check-bound NUM".
  Example:
  # ipfw add 100 allow ip from any to any bound 10K
  # ipfw add 200 deny ip from any to any
  
  While bytes counter of rule 100 below 10 KBytes, it work.
  
  Example:
  # ipfw add 100 allow ip from A.B.C.D to any out xmit internet
  check-bound 200
  # ipfw add 200 allow ip from any to A.B.C.D in recv internet bound 100M
  # ipfw add 300 deny ip from any to any via internet
  
  While bytes counter of rule 200 below 100 MBytes, rules 100 and 200 work.
  NOTE: Check-bound option search rule NUM like "ipfw skipto", but if rule
  NUM not contain bound option, then match fail.
  
  Second part is bound_change.patch, this part add control call to ipfw
  for boundary value change without bytes counter reset.
  Syntax:
  # ipfw bound NUM [set N] change VALUE.
  
  Files:
  For CURRENT:
  http://butcher.heavennet.ru/ipfw_bound/CURRENT/ipfw_bound.patch
  http://butcher.heavennet.ru/ipfw_bound/CURRENT/bound_change.patch
  
  For RELENG_5:
  http://butcher.heavennet.ru/ipfw_bound/RELENG_5/ipfw_bound.patch
  http://butcher.heavennet.ru/ipfw_bound/RELENG_5/bound_change.patch
  
  For RELENG_5_4:
  http://butcher.heavennet.ru/ipfw_bound/RELENG_5_4/ipfw_bound.patch
  http://butcher.heavennet.ru/ipfw_bound/RELENG_5_4/bound_change.patch
  
  -- 
  WBR, Andrey V. Elsukov
  
 _______________________________________________
 freebsd-bugs@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/freebsd-bugs
 To unsubscribe, send any mail to "freebsd-bugs-unsubscribe@freebsd.org"
Responsible-Changed-From-To: freebsd-bugs->freebsd-ipfw 
Responsible-Changed-By: arved 
Responsible-Changed-When: Tue Jun 14 16:59:45 GMT 2005 
Responsible-Changed-Why:  
Over to ipfw Mailinglist for discussion 

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

From: "Andrey V. Elsukov" <elsukov@rdu.kirov.ru>
To: bug-followup@FreeBSD.org, bu7cher@yandex.ru
Cc:  
Subject: Re: kern/80642: [patch] IPFW small patch - new RULE OPTION
Date: Fri, 17 Jun 2005 14:31:20 +0400

 This is a multi-part message in MIME format.
 --------------020602060206080505060104
 Content-Type: text/plain; charset=KOI8-R; format=flowed
 Content-Transfer-Encoding: 7bit
 
 Robert Watson wrote:
  > This patch breaks the ABI by inserting a new type into an implicitly
  > numbered enumeration, renumbering all entries later in the enum.
  > O_BOUND, if added, should be appended to the end, and/or we should
  > number  the operations explicitly.
 
 Ok. I have corrected this.
 * ipfw_bound.diff - the patch with smallest changes, with only bound option.
 * ipfw_bound2.diff - bound and check-bound option.
 
 Examples:
 
 We can limit incoming traffic (internet is external interface):
 # ipfw add allow ip from any to 10.0.0.20 in recv internet bound 10MB
 # ipfw add deny ip from any to 10.0.0.0/24 in recv internet
 
 We can use traffic shaper after excess of a limit:
 # ipfw add allow ip from any to 10.0.0.20 in recv internet bound 10MB
 # ipfw add pipe 1 ip from any to 10.0.0.20 in recv internet
 # ipfw pipe 1 config bw 5Kbit/s queue 10Kbytes
 
 We can block any access after limit excess:
 # ipfw add 100 allow ip from 10.0.0.20 to any out xmit internet \ 
 check-bound 200
 # ipfw add 200 allow ip from any to 10.0.0.20 in recv internet bound \ 10MB
 # ipfw add 300 deny ip from any to any
 
 More details you can read on http://butcher.heavennet.ru/
 -- 
 WBR, Andrey V. Elsukov
 
 --------------020602060206080505060104
 Content-Type: text/plain;
  name="ipfw_bound.diff"
 Content-Transfer-Encoding: 7bit
 Content-Disposition: inline;
  filename="ipfw_bound.diff"
 
 --- sbin/ipfw/ipfw2.c	Tue Jun  7 18:11:17 2005
 +++ sbin/ipfw/ipfw2.c	Fri Jun 17 13:09:43 2005
 @@ -277,6 +277,7 @@
  	TOK_SRCIP6,
  
  	TOK_IPV4,
 +	TOK_BOUND,
  };
  
  struct _s_x dummynet_params[] = {
 @@ -403,6 +404,7 @@
  	{ "dst-ip6",		TOK_DSTIP6},
  	{ "src-ipv6",		TOK_SRCIP6},
  	{ "src-ip6",		TOK_SRCIP6},
 +	{ "bound",		TOK_BOUND},
  	{ "//",			TOK_COMMENT },
  
  	{ "not",		TOK_NOT },		/* pseudo option */
 @@ -1858,6 +1860,10 @@
  				print_ext6hdr( (ipfw_insn *) cmd );
  				break;
  
 +			case O_BOUND:
 +				printf(" bound %u", ((ipfw_insn_u64 *)cmd)->bound);
 +				break;
 +
  			default:
  				printf(" [opcode %d len %d]",
  				    cmd->opcode, cmd->len);
 @@ -2515,7 +2521,7 @@
  "	icmp6types LIST | ext6hdr LIST | flow-id N[,N] |\n"
  "	mac ... | mac-type LIST | proto LIST | {recv|xmit|via} {IF|IPADDR} |\n"
  "	setup | {tcpack|tcpseq|tcpwin} NN | tcpflags SPEC | tcpoptions SPEC |\n"
 -"	tcpdatalen LIST | verrevpath | versrcreach | antispoof\n"
 +"	tcpdatalen LIST | verrevpath | versrcreach | antispoof | bound VALUE\n"
  );
  exit(0);
  }
 @@ -3683,6 +3689,7 @@
  	int i;
  
  	int open_par = 0;	/* open parenthesis ( */
 +	int have_bound = 0;
  
  	/* proto is here because it is used to fetch ports */
  	u_char proto = IPPROTO_IP;	/* default protocol */
 @@ -4492,6 +4499,33 @@
  			fill_comment(cmd, ac, av);
  			av += ac;
  			ac = 0;
 +			break;
 +
 +		case TOK_BOUND:
 +			NEED1("bound requires numeric value");
 +			if (have_bound)
 +				errx(EX_USAGE, "only one of bound is allowed");
 +			if (open_par)
 +				errx(EX_USAGE, "bound cannot be part "
 +						"of an or block"); 
 +			if (cmd->len & F_NOT)
 +				errx(EX_USAGE, 
 +				"\"not\" not allowed with bound option"); 
 +			{
 +				char *end = NULL;
 +				uint64_t bound = strtoull(*av, &end, 0);
 +				if (bound)
 +				switch (*end){
 +					case 'G': bound *= 1024;
 +					case 'M': bound *= 1024;
 +					case 'K': bound *= 1024;
 +				};
 +				cmd->opcode = O_BOUND;
 +				((ipfw_insn_u64 *)cmd)->bound = bound;
 +				cmd->len = F_INSN_SIZE(ipfw_insn_u64) & F_LEN_MASK;
 +				have_bound = 1;
 +				ac--; av++;
 +			} 
  			break;
  
  		default:
 --- sys/netinet/ip_fw.h	Fri Jun  3 05:10:28 2005
 +++ sys/netinet/ip_fw.h	Fri Jun 17 11:30:30 2005
 @@ -154,6 +154,7 @@
  	O_NGTEE,		/* copy to ng_ipfw		*/
  
  	O_IP4,
 +	O_BOUND,		/* u64 = bound in bytes */
  
  	O_LAST_OPCODE		/* not an opcode!		*/
  };
 @@ -228,6 +229,14 @@
  	ipfw_insn o;
  	u_int32_t d[1];	/* one or more */
  } ipfw_insn_u32;
 +
 +/*
 + * This is used to store 64-bit bound value.
 + */
 +typedef struct	_ipfw_insn_u64 {
 +	ipfw_insn o;
 +	u_int64_t bound;
 +} ipfw_insn_u64; 
  
  /*
   * This is used to store IP addr-mask pairs.
 --- sys/netinet/ip_fw2.c	Thu Jun 16 18:55:58 2005
 +++ sys/netinet/ip_fw2.c	Fri Jun 17 11:46:36 2005
 @@ -2251,6 +2251,10 @@
  			 * logic to deal with F_NOT and F_OR flags associated
  			 * with the opcode.
  			 */
 +			case O_BOUND:
 +				match = (f->bcnt < ((ipfw_insn_u64 *)cmd)->bound);
 +				break;
 +
  			case O_NOP:
  				match = 1;
  				break;
 @@ -3387,6 +3391,11 @@
  		case O_PROB:
  		case O_ICMPTYPE:
  			if (cmdlen != F_INSN_SIZE(ipfw_insn_u32))
 +				goto bad_size;
 +			break;
 +		
 +		case O_BOUND:
 +			if (cmdlen != F_INSN_SIZE(ipfw_insn_u64))
  				goto bad_size;
  			break;
  
 
 --------------020602060206080505060104
 Content-Type: text/plain;
  name="ipfw_bound2.diff"
 Content-Transfer-Encoding: 7bit
 Content-Disposition: inline;
  filename="ipfw_bound2.diff"
 
 --- sbin/ipfw/ipfw2.c	Tue Jun  7 18:11:17 2005
 +++ sbin/ipfw/ipfw2.c	Fri Jun 17 13:40:54 2005
 @@ -277,6 +277,8 @@
  	TOK_SRCIP6,
  
  	TOK_IPV4,
 +	TOK_BOUND,
 +	TOK_CHECK_BOUND,
  };
  
  struct _s_x dummynet_params[] = {
 @@ -403,6 +405,8 @@
  	{ "dst-ip6",		TOK_DSTIP6},
  	{ "src-ipv6",		TOK_SRCIP6},
  	{ "src-ip6",		TOK_SRCIP6},
 +	{ "bound",		TOK_BOUND},
 +	{ "check-bound",	TOK_CHECK_BOUND},
  	{ "//",			TOK_COMMENT },
  
  	{ "not",		TOK_NOT },		/* pseudo option */
 @@ -1636,6 +1640,9 @@
  			flags |= HAVE_PROTO;
  			break;
  
 +		case O_BOUND:
 +			break;
 +
  		default: /*options ... */
  			if (!(cmd->len & (F_OR|F_NOT)))
  				if (((cmd->opcode == O_IP6) &&
 @@ -1858,6 +1865,10 @@
  				print_ext6hdr( (ipfw_insn *) cmd );
  				break;
  
 +			case O_CHECK_BOUND:
 +				printf(" check-bound %d", cmd->arg1);
 +				break;
 +
  			default:
  				printf(" [opcode %d len %d]",
  				    cmd->opcode, cmd->len);
 @@ -1872,6 +1883,8 @@
  		}
  	}
  	show_prerequisites(&flags, HAVE_IP, 0);
 +	if (rule->cmd->opcode == O_BOUND) 
 +		printf(" bound %u", ((ipfw_insn_u64 *)(rule->cmd))->bound);
  	if (comment)
  		printf(" // %s", comment);
  	printf("\n");
 @@ -2515,7 +2528,8 @@
  "	icmp6types LIST | ext6hdr LIST | flow-id N[,N] |\n"
  "	mac ... | mac-type LIST | proto LIST | {recv|xmit|via} {IF|IPADDR} |\n"
  "	setup | {tcpack|tcpseq|tcpwin} NN | tcpflags SPEC | tcpoptions SPEC |\n"
 -"	tcpdatalen LIST | verrevpath | versrcreach | antispoof\n"
 +"	tcpdatalen LIST | verrevpath | versrcreach | antispoof | bound VALUE |\n"
 +"	check-bound NUM\n"
  );
  exit(0);
  }
 @@ -3677,7 +3691,8 @@
  	 * various flags used to record that we entered some fields.
  	 */
  	ipfw_insn *have_state = NULL;	/* check-state or keep-state */
 -	ipfw_insn *have_log = NULL, *have_altq = NULL;
 +	ipfw_insn *have_log = NULL, *have_altq = NULL,
 +		  *have_bound = NULL;
  	size_t len;
  
  	int i;
 @@ -4494,6 +4509,39 @@
  			ac = 0;
  			break;
  
 +		case TOK_BOUND:
 +			NEED1("bound requires numeric value");
 +			if (have_bound)
 +				errx(EX_USAGE, "only one of bound is allowed");
 +			if (open_par)
 +				errx(EX_USAGE, "bound cannot be part "
 +						"of an or block"); 
 +			if (cmd->len & F_NOT)
 +				errx(EX_USAGE, 
 +				"\"not\" not allowed with bound option"); 
 +			{
 +				char *end = NULL;
 +				uint64_t bound = strtoull(*av, &end, 0);
 +				if (bound)
 +				switch (*end){
 +					case 'G': bound *= 1024;
 +					case 'M': bound *= 1024;
 +					case 'K': bound *= 1024;
 +				};
 +				cmd->opcode = O_BOUND;
 +				((ipfw_insn_u64 *)cmd)->bound = bound;
 +				cmd->len = F_INSN_SIZE(ipfw_insn_u64) & F_LEN_MASK;
 +				have_bound = cmd;
 +				ac--; av++;
 +			} 
 +			break;
 +
 +		case TOK_CHECK_BOUND:
 +			NEED1("check-bound requires rule number"); 
 +			fill_cmd(cmd, O_CHECK_BOUND, 0, strtoul(*av, NULL, 0));
 +			ac--; av++; 
 +			break;
 +
  		default:
  			errx(EX_USAGE, "unrecognised option [%d] %s\n", i, s);
  		}
 @@ -4506,6 +4554,8 @@
  done:
  	/*
  	 * Now copy stuff into the rule.
 +	 * If we have a bound option, the first instruction MUST BE 
 +	 * a O_BOUND.
  	 * If we have a keep-state option, the first instruction
  	 * must be a PROBE_STATE (which is generated here).
  	 * If we have a LOG option, it was stored as the first command,
 @@ -4514,7 +4564,15 @@
  	dst = (ipfw_insn *)rule->cmd;
  
  	/*
 -	 * First thing to write into the command stream is the match probability.
 +	 * First write into the command stream bound instruction
 +	 */
 +	if (have_bound) {
 +		bcopy(have_bound, dst, F_LEN(have_bound) * sizeof(uint32_t));
 +		dst = next_cmd(dst);
 +	}
 +
 +	/*
 +	 * write the match probability 	
  	 */
  	if (match_prob != 1) { /* 1 means always match */
  		dst->opcode = O_PROB;
 @@ -4531,7 +4589,8 @@
  		dst = next_cmd(dst);
  	}
  	/*
 -	 * copy all commands but O_LOG, O_KEEP_STATE, O_LIMIT, O_ALTQ
 +	 * copy all commands but O_LOG, O_KEEP_STATE, O_LIMIT, O_ALTQ,
 +	 * O_BOUND
  	 */
  	for (src = (ipfw_insn *)cmdbuf; src != cmd; src += i) {
  		i = F_LEN(src);
 @@ -4541,6 +4600,7 @@
  		case O_KEEP_STATE:
  		case O_LIMIT:
  		case O_ALTQ:
 +		case O_BOUND:
  			break;
  		default:
  			bcopy(src, dst, i * sizeof(uint32_t));
 --- sys/netinet/ip_fw.h	Fri Jun  3 05:10:28 2005
 +++ sys/netinet/ip_fw.h	Fri Jun 17 13:18:47 2005
 @@ -154,6 +154,8 @@
  	O_NGTEE,		/* copy to ng_ipfw		*/
  
  	O_IP4,
 +	O_BOUND,		/* u64 = bound in bytes */
 +	O_CHECK_BOUND,		/* u16 = rule number */
  
  	O_LAST_OPCODE		/* not an opcode!		*/
  };
 @@ -230,6 +232,14 @@
  } ipfw_insn_u32;
  
  /*
 + * This is used to store 64-bit bound value.
 + */
 +typedef struct	_ipfw_insn_u64 {
 +	ipfw_insn o;
 +	u_int64_t bound;
 +} ipfw_insn_u64; 
 +
 +/*
   * This is used to store IP addr-mask pairs.
   */
  typedef struct	_ipfw_insn_ip {
 @@ -351,11 +361,16 @@
   *
   * When assembling instruction, remember the following:
   *
 + *  + if a rule has a "bound" option, then the first instruction
 + *	(at r->cmd) MUST BE an O_BOUND
   *  + if a rule has a "keep-state" (or "limit") option, then the
   *	first instruction (at r->cmd) MUST BE an O_PROBE_STATE
   *  + if a rule has a "log" option, then the first action
   *	(at ACTION_PTR(r)) MUST be O_LOG
   *  + if a rule has an "altq" option, it comes after "log"
 + *
 + * NOTE: actually, O_PROB instruction may be first too. But O_BOUND 
 + *	MUST BE always first (at r->cmd). 
   *
   * NOTE: we use a simple linked list of rules because we never need
   * 	to delete a rule without scanning the list. We do not use
 --- sys/netinet/ip_fw2.c	Thu Jun 16 18:55:58 2005
 +++ sys/netinet/ip_fw2.c	Fri Jun 17 13:26:19 2005
 @@ -2251,6 +2251,26 @@
  			 * logic to deal with F_NOT and F_OR flags associated
  			 * with the opcode.
  			 */
 +			case O_BOUND:
 +				match = (f->bcnt < ((ipfw_insn_u64 *)cmd)->bound);
 +				break;
 +
 +			case O_CHECK_BOUND:
 +				{
 +				struct ip_fw* rule;
 +				for (rule = f->next; 
 +					 rule && cmd->arg1 >= rule->rulenum; 
 +					 rule = rule->next) 
 +					if (rule->rulenum == cmd->arg1 && 
 +						rule->cmd->opcode == O_BOUND )
 +				   	{
 +						match = (rule->bcnt < 
 +							((ipfw_insn_u64 *)(rule->cmd))->bound);
 +						break;
 +					}
 +				}
 +				break;
 + 
  			case O_NOP:
  				match = 1;
  				break;
 @@ -3373,6 +3393,7 @@
  		case O_EXT_HDR:
  		case O_IP6:
  		case O_IP4:
 +		case O_CHECK_BOUND:
  			if (cmdlen != F_INSN_SIZE(ipfw_insn))
  				goto bad_size;
  			break;
 @@ -3388,6 +3409,16 @@
  		case O_ICMPTYPE:
  			if (cmdlen != F_INSN_SIZE(ipfw_insn_u32))
  				goto bad_size;
 +			break;
 +		
 +		case O_BOUND:
 +			if (cmdlen != F_INSN_SIZE(ipfw_insn_u64))
 +				goto bad_size;
 +			if (cmd != rule->cmd) {
 +				printf("ipfw: bogus rule, opcode %d must be first\n",
 +						cmd->opcode);
 +				return EINVAL;
 +			} 
  			break;
  
  		case O_LIMIT:
 
 --------------020602060206080505060104--
 

From: "Andrey V. Elsukov" <bu7cher@yandex.ru>
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: kern/80642: [ipfw] [patch] ipfw small patch - new RULE OPTION
Date: Tue, 27 Jun 2006 16:39:21 +0400

 I think this PR can be closed. I don't see any interest in him
 among committers.
 
 -- 
 WBR, Andrey V. Elsukov
State-Changed-From-To: open->suspended 
State-Changed-By: vwe 
State-Changed-When: Wed Mar 12 20:58:32 UTC 2008 
State-Changed-Why:  

Awaiting maintainer interest. 
This may be useful for one, so we're not just closing this silently. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=80642 
State-Changed-From-To: suspended->closed 
State-Changed-By: ae 
State-Changed-When: Mon Dec 13 11:15:21 UTC 2010 
State-Changed-Why:  
It is my PR. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=80642 
>Unformatted:
