Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 3 Jan 2021 13:27:04 GMT
From:      Gordon Bergling <gbe@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org
Subject:   git: e56b2f0b2804 - stable/12 - MFC r364117 by glebius:
Message-ID:  <202101031327.103DR4e9032656@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch stable/12 has been updated by gbe (doc committer):

URL: https://cgit.FreeBSD.org/src/commit/?id=e56b2f0b28048cea88fa6000a2bf08a75f055526

commit e56b2f0b28048cea88fa6000a2bf08a75f055526
Author:     Gleb Smirnoff <glebius@FreeBSD.org>
AuthorDate: 2020-08-11 15:46:22 +0000
Commit:     Gordon Bergling <gbe@FreeBSD.org>
CommitDate: 2021-01-03 13:23:48 +0000

    MFC r364117 by glebius:
    
    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
    Approved by:    glebius
    Differential Revision:  https://reviews.freebsd.org/D26021
    
    (cherry picked from commit 825398f946221045c565363a0349f68d054d6455)
---
 sbin/ipfw/ipfw.8          | 33 +++++++++++++++++++++++++--------
 sbin/ipfw/ipfw2.c         | 20 ++++++++++++++++++--
 sys/netpfil/ipfw/ip_fw2.c | 18 +++++++++++++++++-
 3 files changed, 60 insertions(+), 11 deletions(-)

diff --git a/sbin/ipfw/ipfw.8 b/sbin/ipfw/ipfw.8
index ea35a2767845..58bc3662fcc7 100644
--- a/sbin/ipfw/ipfw.8
+++ b/sbin/ipfw/ipfw.8
@@ -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 given in
 .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 .
diff --git a/sbin/ipfw/ipfw2.c b/sbin/ipfw/ipfw2.c
index cf66422d2ff0..e0b5371adb91 100644
--- a/sbin/ipfw/ipfw2.c
+++ b/sbin/ipfw/ipfw2.c
@@ -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 format_opts *fo,
 		    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:
diff --git a/sys/netpfil/ipfw/ip_fw2.c b/sys/netpfil/ipfw/ip_fw2.c
index 90f3b3c08198..f639a3bfabbd 100644
--- a/sys/netpfil/ipfw/ip_fw2.c
+++ b/sys/netpfil/ipfw/ip_fw2.c
@@ -1916,7 +1916,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" */



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202101031327.103DR4e9032656>