svn commit: r364117 - in head: sbin/ipfw sys/netpfil/ipfw

Gleb Smirnoff glebius at FreeBSD.org
Tue Aug 11 15:46:23 UTC 2020


Author: glebius
Date: Tue Aug 11 15:46:22 2020
New Revision: 364117
URL: https://svnweb.freebsd.org/changeset/base/364117

Log:
  ipfw: make the "frag" keyword accept additional options "mf",
  "df", "rf" and "offset".  This allows to match on specific
  bits of ip_off field.
  
  For compatibility reasons lack of keyword means "offset".
  
  Reviewed by:	ae
  Differential Revision:	https://reviews.freebsd.org/D26021

Modified:
  head/sbin/ipfw/ipfw.8
  head/sbin/ipfw/ipfw2.c
  head/sys/netpfil/ipfw/ip_fw2.c

Modified: head/sbin/ipfw/ipfw.8
==============================================================================
--- head/sbin/ipfw/ipfw.8	Tue Aug 11 15:08:32 2020	(r364116)
+++ head/sbin/ipfw/ipfw.8	Tue Aug 11 15:46:22 2020	(r364117)
@@ -1,7 +1,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd June 21, 2019
+.Dd August 10, 2020
 .Dt IPFW 8
 .Os
 .Sh NAME
@@ -600,7 +600,7 @@ See Section
 By name or address
 .It Misc. IP header fields
 Version, type of service, datagram length, identification,
-fragment flag (non-zero IP offset),
+fragmentation flags,
 Time To Live
 .It IP options
 .It IPv6 Extension headers
@@ -1602,12 +1602,29 @@ Matches IPv6 packets containing any of the flow labels
 .Ar labels .
 .Ar labels
 is a comma separated list of numeric flow labels.
-.It Cm frag
-Matches packets that are fragments and not the first
-fragment of an IP datagram.
-Note that these packets will not have
-the next protocol header (e.g.\& TCP, UDP) so options that look into
-these headers cannot match.
+.It Cm frag Ar spec
+Matches IPv4 packets whose
+.Cm ip_off 
+field contains the comma separated list of IPv4 fragmentation
+options specified in
+.Ar spec .
+The recognized options are:
+.Cm df
+.Pq Dv don't fragment ,
+.Cm mf
+.Pq Dv more fragments ,
+.Cm rf
+.Pq Dv reserved fragment bit
+.Cm offset
+.Pq Dv non-zero fragment offset .
+The absence of a particular options may be denoted
+with a
+.Ql \&! .
+.Pp
+Empty list of options defaults to matching on non-zero fragment offset.
+Such rule would match all not the first fragment datagrams,
+both IPv4 and IPv6.
+This is a backward compatibility with older rulesets.
 .It Cm gid Ar group
 Matches all TCP or UDP packets sent by or received for a
 .Ar group .

Modified: head/sbin/ipfw/ipfw2.c
==============================================================================
--- head/sbin/ipfw/ipfw2.c	Tue Aug 11 15:08:32 2020	(r364116)
+++ head/sbin/ipfw/ipfw2.c	Tue Aug 11 15:46:22 2020	(r364117)
@@ -168,6 +168,14 @@ static struct _s_x f_iptos[] = {
 	{ NULL,	0 }
 };
 
+static struct _s_x f_ipoff[] = {
+	{ "rf", IP_RF >> 8 },
+	{ "df", IP_DF >> 8 },
+	{ "mf", IP_MF >> 8 },
+	{ "offset", 0x1 },
+	{ NULL, 0}
+};
+
 struct _s_x f_ipdscp[] = {
 	{ "af11", IPTOS_DSCP_AF11 >> 2 },	/* 001010 */
 	{ "af12", IPTOS_DSCP_AF12 >> 2 },	/* 001100 */
@@ -1531,7 +1539,7 @@ print_instruction(struct buf_pr *bp, const struct form
 		    IPPROTO_ETHERTYPE, cmd->opcode);
 		break;
 	case O_FRAG:
-		bprintf(bp, " frag");
+		print_flags(bp, "frag", cmd, f_ipoff);
 		break;
 	case O_FIB:
 		bprintf(bp, " fib %u", cmd->arg1);
@@ -4553,7 +4561,15 @@ read_options:
 			break;
 
 		case TOK_FRAG:
-			fill_cmd(cmd, O_FRAG, 0, 0);
+			fill_flags_cmd(cmd, O_FRAG, f_ipoff, *av);
+			/*
+			 * Compatibility: no argument after "frag"
+			 * keyword equals to "frag offset".
+			 */
+			if (cmd->arg1 == 0)
+				cmd->arg1 = 0x1;
+			else
+				av++;
 			break;
 
 		case TOK_LAYER2:

Modified: head/sys/netpfil/ipfw/ip_fw2.c
==============================================================================
--- head/sys/netpfil/ipfw/ip_fw2.c	Tue Aug 11 15:08:32 2020	(r364116)
+++ head/sys/netpfil/ipfw/ip_fw2.c	Tue Aug 11 15:46:22 2020	(r364117)
@@ -1944,7 +1944,23 @@ do {								\
 				break;
 
 			case O_FRAG:
-				match = (offset != 0);
+				if (is_ipv4) {
+					/*
+					 * Since flags_match() works with
+					 * uint8_t we pack ip_off into 8 bits.
+					 * For this match offset is a boolean.
+					 */
+					match = flags_match(cmd,
+					    ((ntohs(ip->ip_off) & ~IP_OFFMASK)
+					    >> 8) | (offset != 0));
+				} else {
+					/*
+					 * Compatiblity: historically bare
+					 * "frag" would match IPv6 fragments.
+					 */
+					match = (cmd->arg1 == 0x1 &&
+					    (offset != 0));
+				}
 				break;
 
 			case O_IN:	/* "out" is "not in" */


More information about the svn-src-head mailing list