Make the 'tcpwin' option of ipfw(8) accept ranges and lists.

Submitted by:	sem
This commit is contained in:
Gleb Smirnoff 2012-02-06 11:35:29 +00:00
parent c480f781ea
commit 23ccd3d976
4 changed files with 35 additions and 10 deletions

View File

@ -1652,10 +1652,12 @@ option for details on matching fragmented packets.
TCP packets only.
Match if the TCP header sequence number field is set to
.Ar seq .
.It Cm tcpwin Ar win
TCP packets only.
Match if the TCP header window field is set to
.Ar win .
.It Cm tcpwin Ar tcpwin-list
Matches TCP packets whose header window field is set to
.Ar tcpwin-list ,
which is either a single value or a list of values or ranges
specified in the same way as
.Ar ports .
.It Cm tcpoptions Ar spec
TCP packets only.
Match if the TCP header contains the comma separated list of

View File

@ -512,6 +512,7 @@ static struct _s_x _port_name[] = {
{"ipttl", O_IPTTL},
{"mac-type", O_MAC_TYPE},
{"tcpdatalen", O_TCPDATALEN},
{"tcpwin", O_TCPWIN},
{"tagged", O_TAGGED},
{NULL, 0}
};
@ -1480,7 +1481,11 @@ show_ipfw(struct ip_fw *rule, int pcwidth, int bcwidth)
break;
case O_TCPWIN:
printf(" tcpwin %d", ntohs(cmd->arg1));
if (F_LEN(cmd) == 1)
printf(" tcpwin %u", cmd->arg1);
else
print_newports((ipfw_insn_u16 *)cmd, 0,
O_TCPWIN);
break;
case O_TCPACK:
@ -3447,8 +3452,12 @@ ipfw_add(char *av[])
case TOK_TCPWIN:
NEED1("tcpwin requires length");
fill_cmd(cmd, O_TCPWIN, 0,
htons(strtoul(*av, NULL, 0)));
if (strpbrk(*av, "-,")) {
if (!add_ports(cmd, *av, 0, O_TCPWIN))
errx(EX_DATAERR, "invalid tcpwin len %s", *av);
} else
fill_cmd(cmd, O_TCPWIN, 0,
strtoul(*av, NULL, 0));
av++;
break;

View File

@ -1650,8 +1650,22 @@ do { \
break;
case O_TCPWIN:
match = (proto == IPPROTO_TCP && offset == 0 &&
cmd->arg1 == TCP(ulp)->th_win);
if (proto == IPPROTO_TCP && offset == 0) {
uint16_t x;
uint16_t *p;
int i;
x = ntohs(TCP(ulp)->th_win);
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_ESTAB:

View File

@ -569,7 +569,6 @@ check_ipfw_struct(struct ip_fw *rule, int size)
case O_IPPRECEDENCE:
case O_IPVER:
case O_SOCKARG:
case O_TCPWIN:
case O_TCPFLAGS:
case O_TCPOPTS:
case O_ESTAB:
@ -679,6 +678,7 @@ check_ipfw_struct(struct ip_fw *rule, int size)
case O_IPTTL:
case O_IPLEN:
case O_TCPDATALEN:
case O_TCPWIN:
case O_TAGGED:
if (cmdlen < 1 || cmdlen > 31)
goto bad_size;