From owner-svn-src-all@freebsd.org Tue Aug 11 15:46:23 2020 Return-Path: Delivered-To: svn-src-all@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id 32A213B0FD9; Tue, 11 Aug 2020 15:46:23 +0000 (UTC) (envelope-from glebius@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4BQxyR0Zx6z4ft1; Tue, 11 Aug 2020 15:46:23 +0000 (UTC) (envelope-from glebius@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id EABD51D4CC; Tue, 11 Aug 2020 15:46:22 +0000 (UTC) (envelope-from glebius@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id 07BFkMDr076123; Tue, 11 Aug 2020 15:46:22 GMT (envelope-from glebius@FreeBSD.org) Received: (from glebius@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id 07BFkMfS076120; Tue, 11 Aug 2020 15:46:22 GMT (envelope-from glebius@FreeBSD.org) Message-Id: <202008111546.07BFkMfS076120@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: glebius set sender to glebius@FreeBSD.org using -f From: Gleb Smirnoff Date: Tue, 11 Aug 2020 15:46:22 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r364117 - in head: sbin/ipfw sys/netpfil/ipfw X-SVN-Group: head X-SVN-Commit-Author: glebius X-SVN-Commit-Paths: in head: sbin/ipfw sys/netpfil/ipfw X-SVN-Commit-Revision: 364117 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.33 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 11 Aug 2020 15:46:23 -0000 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" */