From novel@FreeBSD.org  Thu Sep 21 10:27:19 2006
Return-Path: <novel@FreeBSD.org>
Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125])
	by hub.freebsd.org (Postfix) with ESMTP id 3257016A403
	for <FreeBSD-gnats-submit@freebsd.org>; Thu, 21 Sep 2006 10:27:19 +0000 (UTC)
	(envelope-from novel@FreeBSD.org)
Received: from freefall.freebsd.org (freefall.freebsd.org [216.136.204.21])
	by mx1.FreeBSD.org (Postfix) with ESMTP id 88E1543D67
	for <FreeBSD-gnats-submit@freebsd.org>; Thu, 21 Sep 2006 10:27:14 +0000 (GMT)
	(envelope-from novel@FreeBSD.org)
Received: from freefall.freebsd.org (novel@localhost [127.0.0.1])
	by freefall.freebsd.org (8.13.4/8.13.4) with ESMTP id k8LARE8j054746
	for <FreeBSD-gnats-submit@freebsd.org>; Thu, 21 Sep 2006 10:27:14 GMT
	(envelope-from novel@freefall.freebsd.org)
Received: (from novel@localhost)
	by freefall.freebsd.org (8.13.4/8.13.4/Submit) id k8LARErU054745;
	Thu, 21 Sep 2006 10:27:14 GMT
	(envelope-from novel)
Message-Id: <200609211027.k8LARErU054745@freefall.freebsd.org>
Date: Thu, 21 Sep 2006 10:27:14 GMT
From: Roman Bogorodskiy <novel@FreeBSD.org>
Reply-To: Roman Bogorodskiy <novel@FreeBSD.org>
To: FreeBSD-gnats-submit@freebsd.org
Cc:
Subject: [ipfw] [patch] add a facility to modify DF bit of the IP packet
X-Send-Pr-Version: 3.113
X-GNATS-Notify:

>Number:         103454
>Category:       kern
>Synopsis:       [ipfw] [patch] [request] add a facility to modify DF bit of the IP packet
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    freebsd-ipfw
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Thu Sep 21 10:30:19 GMT 2006
>Closed-Date:    
>Last-Modified:  Sun Jan 27 10:39:11 UTC 2008
>Originator:     Roman Bogorodskiy
>Release:        FreeBSD 6.0-STABLE i386
>Organization:
>Environment:
>Description:
Add a facility to modify DF bit of the IP packet with ipfw.
Example:
  ipfw add 100 setdf 0 all from any to any

That will set DF to 0 (May Fragment) for all packets. Possible
values are 0 (May Fragment) and 1 (Don't Fragment).

References:
  RFC 791 (http://www.ietf.org/rfc/rfc0791.txt)

Patch was tested on -CURRENT. It's avaible via web as well:
http://people.freebsd.org/~novel/patches/freebsd/ipfw_setdf_20060921_2_CURRENT.diff
>How-To-Repeat:
>Fix:

--- ipfw_setdf_20060921_2_CURRENT.diff begins here ---
? sbin/ipfw/ipfw
Index: sbin/ipfw/ipfw.8
===================================================================
RCS file: /home/ncvs/src/sbin/ipfw/ipfw.8,v
retrieving revision 1.195
diff -u -r1.195 ipfw.8
--- sbin/ipfw/ipfw.8	18 Sep 2006 11:55:10 -0000	1.195
+++ sbin/ipfw/ipfw.8	21 Sep 2006 10:12:51 -0000
@@ -822,6 +822,11 @@
 and
 .Cm ngtee
 actions.
+.It Cm setdf Ar value
+Changes
+.Cm DF
+bit of the IP packet.
+Value may be 0 (May Fragment) or 1 (Don't Fragment).
 .El
 .Ss RULE BODY
 The body of a rule contains zero or more patterns (such as
Index: sbin/ipfw/ipfw2.c
===================================================================
RCS file: /home/ncvs/src/sbin/ipfw/ipfw2.c,v
retrieving revision 1.98
diff -u -r1.98 ipfw2.c
--- sbin/ipfw/ipfw2.c	16 Sep 2006 19:27:40 -0000	1.98
+++ sbin/ipfw/ipfw2.c	21 Sep 2006 10:12:51 -0000
@@ -247,7 +247,8 @@
 	TOK_RESET,
 	TOK_UNREACH,
 	TOK_CHECKSTATE,
-
+	TOK_SETDF,
+	
 	TOK_ALTQ,
 	TOK_LOG,
 	TOK_TAG,
@@ -374,6 +375,7 @@
 	{ "unreach6",		TOK_UNREACH6 },
 	{ "unreach",		TOK_UNREACH },
 	{ "check-state",	TOK_CHECKSTATE },
+	{ "setdf",		TOK_SETDF },
 	{ "//",			TOK_COMMENT },
 	{ NULL, 0 }	/* terminator */
 };
@@ -1555,6 +1557,10 @@
 		    }
 			break;
 
+		case O_SET_IPDF:
+			PRINT_UINT_ARG("setdf ", cmd->arg1);
+			break;
+
 		case O_LOG: /* O_LOG is printed last */
 			logptr = (ipfw_insn_log *)cmd;
 			break;
@@ -2635,7 +2641,7 @@
 "RULE-BODY:	check-state [PARAMS] | ACTION [PARAMS] ADDR [OPTION_LIST]\n"
 "ACTION:	check-state | allow | count | deny | unreach{,6} CODE |\n"
 "               skipto N | {divert|tee} PORT | forward ADDR |\n"
-"               pipe N | queue N\n"
+"               pipe N | queue N | setdf DF\n"
 "PARAMS: 	[log [logamount LOGLIMIT]] [altq QUEUE_NAME]\n"
 "ADDR:		[ MAC dst src ether_type ] \n"
 "		[ ip from IPADDR [ PORT ] to IPADDR [ PORTLIST ] ]\n"
@@ -3970,6 +3976,20 @@
 		action->opcode = O_COUNT;
 		break;
 
+	case TOK_SETDF:
+	   {
+		int df;
+		   
+		NEED1("need setdf arg\n");
+		df = strtoul(*av, NULL, 0);
+		if (df < 0 || df > 1)
+			errx(EX_DATAERR, "illegal argument for %s",
+				*(av - 1));
+		fill_cmd(action, O_SET_IPDF, 0, df);
+		ac--; av++;
+	   }
+		break;
+		
 	case TOK_QUEUE:
 		action->opcode = O_QUEUE;
 		goto chkarg;
Index: sys/netinet/ip_fw.h
===================================================================
RCS file: /home/ncvs/src/sys/netinet/ip_fw.h,v
retrieving revision 1.108
diff -u -r1.108 ip_fw.h
--- sys/netinet/ip_fw.h	18 Aug 2006 22:36:04 -0000	1.108
+++ sys/netinet/ip_fw.h	21 Sep 2006 10:13:15 -0000
@@ -160,6 +160,8 @@
 	O_TAG,   		/* arg1=tag number */
 	O_TAGGED,		/* arg1=tag number */
 
+	O_SET_IPDF,		/* arg1=[0|1] */
+	
 	O_LAST_OPCODE		/* not an opcode!		*/
 };
 
Index: sys/netinet/ip_fw2.c
===================================================================
RCS file: /home/ncvs/src/sys/netinet/ip_fw2.c,v
retrieving revision 1.147
diff -u -r1.147 ip_fw2.c
--- sys/netinet/ip_fw2.c	16 Sep 2006 10:27:05 -0000	1.147
+++ sys/netinet/ip_fw2.c	21 Sep 2006 10:13:15 -0000
@@ -3127,6 +3127,22 @@
 				goto done;
 			}
 
+			case O_SET_IPDF:
+				switch (cmd->arg1) {
+					case 0:
+						ip->ip_off &= ~IP_DF;
+						break;
+					case 1:
+						ip->ip_off |= IP_DF;
+						break;
+					default:
+						break;
+				}
+				f->pcnt++;
+				f->bcnt += pktlen;
+				f->timestamp = time_second;
+				goto next_rule;
+
 			case O_COUNT:
 			case O_SKIPTO:
 				f->pcnt++;	/* update stats */
@@ -3654,6 +3670,10 @@
 				goto bad_size;
 			break;
 
+		case O_SET_IPDF:
+			have_action = 1;
+			break;
+
 		case O_UID:
 		case O_GID:
 		case O_JAIL:
--- ipfw_setdf_20060921_2_CURRENT.diff ends here ---


>Release-Note:
>Audit-Trail:
Responsible-Changed-From-To: freebsd-bugs->freebsd-ipfw 
Responsible-Changed-By: linimon 
Responsible-Changed-When: Thu Sep 21 11:26:49 UTC 2006 
Responsible-Changed-Why:  
Over to maintainer(s). 

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

From: Roman Bogorodskiy <novel@FreeBSD.org>
To: bug-followup@FreeBSD.org
Cc: novel@FreeBSD.org
Subject: Re: kern/103454: [ipfw] [patch] add a facility to modify DF bit of the IP packet
Date: Thu, 21 Sep 2006 17:56:15 +0400

 --5G06lTa6Jq83wMTw
 Content-Type: multipart/mixed; boundary="Bn2rw/3z4jIqBvZU"
 Content-Disposition: inline
 
 
 --Bn2rw/3z4jIqBvZU
 Content-Type: text/plain; charset=us-ascii
 Content-Disposition: inline
 
 Hi,
 
 Attaching a slightly updated patch. Changes:
 
 - If we got not 0 or 1 as cmd->arg1, just jump to the next rule
   without updatating stats. Actually, ipfw(8) checks if the arg
   for 'setdf' is only 0 or 1, so it should never happen.
 - s/setdf DF/setdf N/ in `ipfw -h' output
 
 http://novel.fannet.ru/~novel/ipfw_setdf_20060921_3_CURRENT.diff
 
 --Bn2rw/3z4jIqBvZU
 Content-Type: text/plain; charset=us-ascii
 Content-Disposition: attachment; filename="ipfw_setdf_20060921_3_CURRENT.diff"
 Content-Transfer-Encoding: quoted-printable
 
 ? sbin/ipfw/ipfw
 Index: sbin/ipfw/ipfw.8
 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
 RCS file: /home/ncvs/src/sbin/ipfw/ipfw.8,v
 retrieving revision 1.195
 diff -u -r1.195 ipfw.8
 --- sbin/ipfw/ipfw.8	18 Sep 2006 11:55:10 -0000	1.195
 +++ sbin/ipfw/ipfw.8	21 Sep 2006 13:41:49 -0000
 @@ -822,6 +822,11 @@
  and
  .Cm ngtee
  actions.
 +.It Cm setdf Ar value
 +Changes
 +.Cm DF
 +bit of the IP packet.
 +Value may be 0 (May Fragment) or 1 (Don't Fragment).
  .El
  .Ss RULE BODY
  The body of a rule contains zero or more patterns (such as
 Index: sbin/ipfw/ipfw2.c
 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
 RCS file: /home/ncvs/src/sbin/ipfw/ipfw2.c,v
 retrieving revision 1.98
 diff -u -r1.98 ipfw2.c
 --- sbin/ipfw/ipfw2.c	16 Sep 2006 19:27:40 -0000	1.98
 +++ sbin/ipfw/ipfw2.c	21 Sep 2006 13:41:50 -0000
 @@ -247,7 +247,8 @@
  	TOK_RESET,
  	TOK_UNREACH,
  	TOK_CHECKSTATE,
 -
 +	TOK_SETDF,
 +=09
  	TOK_ALTQ,
  	TOK_LOG,
  	TOK_TAG,
 @@ -374,6 +375,7 @@
  	{ "unreach6",		TOK_UNREACH6 },
  	{ "unreach",		TOK_UNREACH },
  	{ "check-state",	TOK_CHECKSTATE },
 +	{ "setdf",		TOK_SETDF },
  	{ "//",			TOK_COMMENT },
  	{ NULL, 0 }	/* terminator */
  };
 @@ -1555,6 +1557,10 @@
  		    }
  			break;
 =20
 +		case O_SET_IPDF:
 +			PRINT_UINT_ARG("setdf ", cmd->arg1);
 +			break;
 +
  		case O_LOG: /* O_LOG is printed last */
  			logptr =3D (ipfw_insn_log *)cmd;
  			break;
 @@ -2635,7 +2641,7 @@
  "RULE-BODY:	check-state [PARAMS] | ACTION [PARAMS] ADDR [OPTION_LIST]\n"
  "ACTION:	check-state | allow | count | deny | unreach{,6} CODE |\n"
  "               skipto N | {divert|tee} PORT | forward ADDR |\n"
 -"               pipe N | queue N\n"
 +"               pipe N | queue N | setdf N\n"
  "PARAMS: 	[log [logamount LOGLIMIT]] [altq QUEUE_NAME]\n"
  "ADDR:		[ MAC dst src ether_type ] \n"
  "		[ ip from IPADDR [ PORT ] to IPADDR [ PORTLIST ] ]\n"
 @@ -3970,6 +3976,20 @@
  		action->opcode =3D O_COUNT;
  		break;
 =20
 +	case TOK_SETDF:
 +	   {
 +		int df;
 +		  =20
 +		NEED1("need setdf arg\n");
 +		df =3D strtoul(*av, NULL, 0);
 +		if (df < 0 || df > 1)
 +			errx(EX_DATAERR, "illegal argument for %s",
 +				*(av - 1));
 +		fill_cmd(action, O_SET_IPDF, 0, df);
 +		ac--; av++;
 +	   }
 +		break;
 +	=09
  	case TOK_QUEUE:
  		action->opcode =3D O_QUEUE;
  		goto chkarg;
 Index: sys/netinet/ip_fw.h
 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
 RCS file: /home/ncvs/src/sys/netinet/ip_fw.h,v
 retrieving revision 1.108
 diff -u -r1.108 ip_fw.h
 --- sys/netinet/ip_fw.h	18 Aug 2006 22:36:04 -0000	1.108
 +++ sys/netinet/ip_fw.h	21 Sep 2006 13:42:11 -0000
 @@ -160,6 +160,8 @@
  	O_TAG,   		/* arg1=3Dtag number */
  	O_TAGGED,		/* arg1=3Dtag number */
 =20
 +	O_SET_IPDF,		/* arg1=3D[0|1] */
 +=09
  	O_LAST_OPCODE		/* not an opcode!		*/
  };
 =20
 Index: sys/netinet/ip_fw2.c
 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
 RCS file: /home/ncvs/src/sys/netinet/ip_fw2.c,v
 retrieving revision 1.147
 diff -u -r1.147 ip_fw2.c
 --- sys/netinet/ip_fw2.c	16 Sep 2006 10:27:05 -0000	1.147
 +++ sys/netinet/ip_fw2.c	21 Sep 2006 13:42:11 -0000
 @@ -3127,6 +3127,23 @@
  				goto done;
  			}
 =20
 +			case O_SET_IPDF:
 +				switch (cmd->arg1) {
 +					case 0:
 +						ip->ip_off &=3D ~IP_DF;
 +						break;
 +					case 1:
 +						ip->ip_off |=3D IP_DF;
 +						break;
 +					default:
 +						goto next_rule;
 +						/* NOTREACHED */
 +				}
 +				f->pcnt++;
 +				f->bcnt +=3D pktlen;
 +				f->timestamp =3D time_second;
 +				goto next_rule;
 +
  			case O_COUNT:
  			case O_SKIPTO:
  				f->pcnt++;	/* update stats */
 @@ -3654,6 +3671,10 @@
  				goto bad_size;
  			break;
 =20
 +		case O_SET_IPDF:
 +			have_action =3D 1;
 +			break;
 +
  		case O_UID:
  		case O_GID:
  		case O_JAIL:
 
 --Bn2rw/3z4jIqBvZU--
 
 --5G06lTa6Jq83wMTw
 Content-Type: application/pgp-signature
 Content-Disposition: inline
 
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1.4.5 (FreeBSD)
 
 iQCVAwUBRRKZ/4B0WzgdqspGAQK5wgP/ZiaI62k5RvNb6G71CH114zGX5SH6EYFa
 WDJ7T8Q/0By/KH0aHXlcBO5R3b1bEOoppaAYGOx4DXjFA75vqF17lPh9vi2Cs5R+
 RKOY84KANWLvATgVe48iaUIVQvvLUXaY6E7NFgyekhEywcqRpCId1WcSElCwi4jB
 uy2l78sTklU=
 =VnhE
 -----END PGP SIGNATURE-----
 
 --5G06lTa6Jq83wMTw--
>Unformatted:
