Add support to IPFW for matching by TCP data length.
This commit is contained in:
parent
391a0e3306
commit
c99ee9e042
@ -1236,6 +1236,12 @@ specified as argument.
|
||||
TCP packets only.
|
||||
Match if the TCP header acknowledgment number field is set to
|
||||
.Ar ack .
|
||||
.It Cm tcpdatalen Ar tcpdatalen-list
|
||||
Matches TCP packets whose length of TCP data is
|
||||
.Ar tcpdatalen-list ,
|
||||
which is either a single value or a list of values or ranges
|
||||
specified in the same way as
|
||||
.Ar ports .
|
||||
.It Cm tcpflags Ar spec
|
||||
TCP packets only.
|
||||
Match if the TCP header contains the comma separated list of
|
||||
|
@ -233,6 +233,7 @@ enum tokens {
|
||||
TOK_IPVER,
|
||||
TOK_ESTAB,
|
||||
TOK_SETUP,
|
||||
TOK_TCPDATALEN,
|
||||
TOK_TCPFLAGS,
|
||||
TOK_TCPOPTS,
|
||||
TOK_TCPSEQ,
|
||||
@ -348,6 +349,7 @@ struct _s_x rule_options[] = {
|
||||
{ "estab", TOK_ESTAB },
|
||||
{ "established", TOK_ESTAB },
|
||||
{ "setup", TOK_SETUP },
|
||||
{ "tcpdatalen", TOK_TCPDATALEN },
|
||||
{ "tcpflags", TOK_TCPFLAGS },
|
||||
{ "tcpflgs", TOK_TCPFLAGS },
|
||||
{ "tcpoptions", TOK_TCPOPTS },
|
||||
@ -481,6 +483,7 @@ struct _s_x _port_name[] = {
|
||||
{"iplen", O_IPLEN},
|
||||
{"ipttl", O_IPTTL},
|
||||
{"mac-type", O_MAC_TYPE},
|
||||
{"tcpdatalen", O_TCPDATALEN},
|
||||
{NULL, 0}
|
||||
};
|
||||
|
||||
@ -1395,6 +1398,14 @@ show_ipfw(struct ip_fw *rule, int pcwidth, int bcwidth)
|
||||
printf(" established");
|
||||
break;
|
||||
|
||||
case O_TCPDATALEN:
|
||||
if (F_LEN(cmd) == 1)
|
||||
printf(" tcpdatalen %u", cmd->arg1 );
|
||||
else
|
||||
print_newports((ipfw_insn_u16 *)cmd, 0,
|
||||
O_TCPDATALEN);
|
||||
break;
|
||||
|
||||
case O_TCPFLAGS:
|
||||
print_flags("tcpflags", cmd, f_tcpflags);
|
||||
break;
|
||||
@ -2072,6 +2083,7 @@ help(void)
|
||||
" mac ... | mac-type LIST | proto LIST | {recv|xmit|via} {IF|IPADDR} |\n"
|
||||
" setup | {tcpack|tcpseq|tcpwin} NN | tcpflags SPEC | tcpoptions SPEC |\n"
|
||||
" verrevpath | versrcreach | antispoof\n"
|
||||
" tcpdatalen LIST | verrevpath | versrcreach | antispoof\n"
|
||||
);
|
||||
exit(0);
|
||||
}
|
||||
@ -3542,6 +3554,17 @@ add(int ac, char *av[])
|
||||
(TH_SYN) | ( (TH_ACK) & 0xff) <<8 );
|
||||
break;
|
||||
|
||||
case TOK_TCPDATALEN:
|
||||
NEED1("tcpdatalen requires length");
|
||||
if (strpbrk(*av, "-,")) {
|
||||
if (!add_ports(cmd, *av, 0, O_TCPDATALEN))
|
||||
errx(EX_DATAERR, "invalid tcpdata len %s", *av);
|
||||
} else
|
||||
fill_cmd(cmd, O_TCPDATALEN, 0,
|
||||
strtoul(*av, NULL, 0));
|
||||
ac--; av++;
|
||||
break;
|
||||
|
||||
case TOK_TCPOPTS:
|
||||
NEED1("missing argument for tcpoptions");
|
||||
fill_flags(cmd, O_TCPOPTS, f_tcpopts, *av);
|
||||
|
@ -136,6 +136,7 @@ enum ipfw_opcodes { /* arguments (4 byte each) */
|
||||
O_JAIL, /* u32 = id */
|
||||
O_ALTQ, /* u32 = altq classif. qid */
|
||||
O_DIVERTED, /* arg1=bitmap (1:loop, 2:out) */
|
||||
O_TCPDATALEN, /* arg1 = tcp data len */
|
||||
|
||||
O_LAST_OPCODE /* not an opcode! */
|
||||
};
|
||||
|
@ -2203,6 +2203,28 @@ ipfw_chk(struct ip_fw_args *args)
|
||||
flags_match(cmd, ip->ip_tos));
|
||||
break;
|
||||
|
||||
case O_TCPDATALEN:
|
||||
if (proto == IPPROTO_TCP && offset == 0) {
|
||||
struct tcphdr *tcp;
|
||||
uint16_t x;
|
||||
uint16_t *p;
|
||||
int i;
|
||||
|
||||
tcp = L3HDR(struct tcphdr,ip);
|
||||
x = ip_len -
|
||||
((ip->ip_hl + tcp->th_off) << 2);
|
||||
if (cmdlen == 1) {
|
||||
match = (cmd->arg1 == x);
|
||||
break;
|
||||
}
|
||||
/* otherwise we have ranges */
|
||||
p = ((ipfw_insn_u16 *)cmd)->ports;
|
||||
i = cmdlen - 1;
|
||||
for (; !match && i>0; i--, p += 2)
|
||||
match = (x >= p[0] && x <= p[1]);
|
||||
}
|
||||
break;
|
||||
|
||||
case O_TCPFLAGS:
|
||||
match = (proto == IPPROTO_TCP && offset == 0 &&
|
||||
flags_match(cmd,
|
||||
@ -3014,6 +3036,7 @@ check_ipfw_struct(struct ip_fw *rule, int size)
|
||||
case O_IPID:
|
||||
case O_IPTTL:
|
||||
case O_IPLEN:
|
||||
case O_TCPDATALEN:
|
||||
if (cmdlen < 1 || cmdlen > 31)
|
||||
goto bad_size;
|
||||
break;
|
||||
|
Loading…
Reference in New Issue
Block a user