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
This commit is contained in:
parent
3b44443626
commit
825398f946
@ -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 .
|
||||
|
@ -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 @@ compile_rule(char *av[], uint32_t *rbuf, int *rbufsize, struct tidx *tstate)
|
||||
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:
|
||||
|
@ -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" */
|
||||
|
Loading…
Reference in New Issue
Block a user