ipfw: Add ipfrag filter.
authorSepherosa Ziehau <sephe@dragonflybsd.org>
Wed, 20 Sep 2017 00:21:58 +0000 (08:21 +0800)
committerSepherosa Ziehau <sephe@dragonflybsd.org>
Wed, 20 Sep 2017 00:48:17 +0000 (08:48 +0800)
Unlike 'frag' filter, which only matches non-first IP fragments,
this filter matches all IP fragments.

sbin/ipfw/ipfw.8
sbin/ipfw/ipfw2.c
sys/net/ipfw/ip_fw2.c
sys/net/ipfw/ip_fw2.h

index 3e09bb5..f734faa 100644 (file)
@@ -2,7 +2,7 @@
 .\" $FreeBSD: src/sbin/ipfw/ipfw.8,v 1.63.2.33 2003/02/04 01:36:02 brueffer Exp $
 .\" $DragonFly: src/sbin/ipfw/ipfw.8,v 1.20 2008/11/23 21:55:52 swildner Exp $
 .\"
-.Dd September 10, 2017
+.Dd September 20, 2017
 .Dt IPFW 8
 .Os
 .Sh NAME
@@ -442,7 +442,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),
+fragment flag,
 Time To Live
 .It IP options
 .It Misc. TCP header fields
@@ -861,7 +861,12 @@ fragment) will never match a rule which has one or more port
 specifications.
 See the
 .Cm frag
-option for details on matching fragmented packets.
+and
+.Cm ipfrag
+options for details on matching fragmented packets.
+Ane see the
+.Cm defrag
+action for reassembling IP fragments.
 .El
 .Ss RULE OPTIONS (MATCH PATTERNS)
 Additional match patterns can be used within
@@ -884,9 +889,14 @@ specified as argument.
 Matches TCP packets that have the RST or ACK bits set.
 .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.
+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.
+See also
+.Cm ipfrag
+option and
+.Cm defrag
+action.
 .It Cm gid Ar group
 Matches all TCP or UDP packets sent by or received for a
 .Ar group .
@@ -939,6 +949,14 @@ are mutually exclusive (in fact,
 .Cm out
 is implemented as
 .Cm not in Ns No ).
+.It Cm ipfrag
+Matches IP fragment,
+even if it's the first fragment.
+See also
+.Cm frag
+option and
+.Cm defrag
+action.
 .It Cm ipid Ar id
 Matches IP packets whose
 .Cm ip_id
@@ -1130,7 +1148,12 @@ specification can never match a fragmented packet which has
 a non-zero offset.
 See the
 .Cm frag
-option for details on matching fragmented packets.
+and
+.Cm ipfrag
+options for details on matching fragmented packets.
+And see the
+.Cm defrag
+action for reassembling IP fragments.
 .It Cm tcpseq Ar seq
 TCP packets only.
 Match if the TCP header sequence number field is set to
index 556800d..028c2ec 100644 (file)
@@ -207,6 +207,7 @@ enum tokens {
        TOK_RECV,
        TOK_VIA,
        TOK_FRAG,
+       TOK_IPFRAG,
        TOK_IPOPTS,
        TOK_IPLEN,
        TOK_IPID,
@@ -304,6 +305,7 @@ struct _s_x rule_options[] = {
        { "via",                TOK_VIA },
        { "fragment",           TOK_FRAG },
        { "frag",               TOK_FRAG },
+       { "ipfrag",             TOK_IPFRAG },
        { "ipoptions",          TOK_IPOPTS },
        { "ipopts",             TOK_IPOPTS },
        { "iplen",              TOK_IPLEN },
@@ -1067,6 +1069,10 @@ show_ipfw(struct ipfw_ioc_rule *rule, int pcwidth, int bcwidth)
                                printf(" frag");
                                break;
 
+                       case O_IPFRAG:
+                               printf(" ipfrag");
+                               break;
+
                        case O_IN:
                                printf(cmd->len & F_NOT ? " out" : " in");
                                break;
@@ -2966,6 +2972,10 @@ read_options:
                        fill_cmd(cmd, O_FRAG, 0, 0);
                        break;
 
+               case TOK_IPFRAG:
+                       fill_cmd(cmd, O_IPFRAG, 0, 0);
+                       break;
+
                case TOK_LAYER2:
                        fill_cmd(cmd, O_LAYER2, 0, 0);
                        break;
index 383a8c2..ac6ab41 100644 (file)
@@ -3103,6 +3103,19 @@ check_body:
                                match = (hlen > 0 && offset != 0);
                                break;
 
+                       case O_IPFRAG:
+                               if (hlen > 0) {
+                                       uint16_t off;
+
+                                       if (args->eh != NULL)
+                                               off = ntohs(ip->ip_off);
+                                       else
+                                               off = ip->ip_off;
+                                       if (off & (IP_MF | IP_OFFMASK))
+                                               match = 1;
+                               }
+                               break;
+
                        case O_IN:      /* "out" is "not in" */
                                match = (oif == NULL);
                                break;
@@ -4608,6 +4621,7 @@ ipfw_check_ioc_rule(struct ipfw_ioc_rule *rule, int size, uint32_t *rule_flags)
                case O_LAYER2:
                case O_IN:
                case O_FRAG:
+               case O_IPFRAG:
                case O_IPOPT:
                case O_IPLEN:
                case O_IPID:
index b2b4a25..eed9785 100644 (file)
@@ -117,6 +117,9 @@ enum ipfw_opcodes {         /* arguments (4 byte each)      */
        /* Action. */
        O_DEFRAG,               /* none                         */
 
+       /* Filter. */
+       O_IPFRAG,               /* none                         */
+
        O_LAST_OPCODE           /* not an opcode!               */
 };