kern/60154: [ipfw] ipfw core (crash)
Andrey V. Elsukov
bu7cher at yandex.ru
Fri Dec 16 00:57:16 PST 2005
Maxim Konovalov wrote:
> Synopsis: [ipfw] ipfw core (crash)
> http://www.freebsd.org/cgi/query-pr.cgi?pr=60154
I have updated patch and make the perl script for testing.
--
WBR, Andrey V. Elsukov
-------------- next part --------------
#!/usr/local/bin/perl -w
#===============================================================================
#
# FILE: test.pl
# DESCRIPTION: ipfw parser test
# AUTHOR: (c) Andrey V. Elsukov, <bu7cher at yandex.ru>
# CREATED: 16.12.2005 06:05:09 UTC
#===============================================================================
use strict;
sub result
{
if ($? == -1) {
print "ipfw failed to execute: $!\n";
} elsif ($? & 127) {
printf "ipfw died with signal %d, %s coredump\n",
($? & 127), ($? & 128) ? 'with':'without';
} else {
printf "ipfw exited with value %d\n", $? >> 8;
}
}
sub ip($$)
{
my $dig = shift;
my $separator = shift;
my $str;
$str .= "10.0.0.$_$separator" foreach(1..$dig-1);
$str .= "10.0.0.$dig";
return $str;
}
sub port($$)
{
my $dig = shift;
my $separator = shift;
my $str;
$str .= "$_$separator" foreach(1..$dig-1);
$str .= $dig;
return $str;
}
my $rule;
my @cnt = (5, 10, 25, 50, 100, 250, 500);
my @tests = (
{ description => "protocols",
rule => "allow {\$ } from any to any",
func => \&port, separator => ' or ' },
{ description => "source addresses (or block)",
rule => "allow ip from { \$ } to any",
func => \&ip, separator => ' or ' },
{ description => "source addresses (list)",
rule => "allow ip from { \$ } to any",
func => \&ip,
separator => ',' },
{ description => "source addresses (sets)",
rule => "allow ip from 10.0.0.0/24{\$} to any",
func => \&port,
separator => ',' },
{ description => "source ports (list)",
rule => "allow ip from 10.0.0.1 \$ to any",
func => \&port,
separator => ',' },
{ description => "destination addresses (or block)",
rule => "allow ip from any to { \$ }",
func => \&ip,
separator => ' or ' },
{ description => "destination addresses (lists)",
rule => "allow ip from any to { \$ }",
func => \&ip,
separator => ',' }
);
foreach my $test (@tests) {
print "Check with multiple ", $test->{description}, ":\n";
foreach my $c (@cnt) {
print "try $c count ... ";
my $rule = $test->{rule};
my $substr = $test->{func}($c, $test->{separator});
$rule =~ s/\$/$substr/;
# print "ipfw -q add $rule\n";
system("ipfw -q add $rule");
&result();
}
}
-------------- next part --------------
--- ipfw2.c.orig Tue Dec 13 12:16:02 2005
+++ ipfw2.c Fri Dec 16 11:39:44 2005
@@ -83,6 +83,26 @@
#define NEED1(msg) {if (!ac) errx(EX_USAGE, msg);}
/*
+ * Some functions here get as argumet an ipfw_insn pointer
+ * and fills him. This pointer typically stored in statical
+ * buffer with fixed size. And some ipfw_insn can have a
+ * variable size (for example, ipfw_insn_u16, ipfw_insn_u32,..).
+ * Free left space of this buffers do not controlled.
+ * As result we have some stange core dumps when user try
+ * add rules. To fix this errors we add the "size_left"
+ * paramter to thises functions. size_left indicates which
+ * size we can write into buffer. Before any writes we
+ * must check this size and update him after each write.
+ *
+ */
+#define CHECK_SIZE(size) \
+ { \
+ if ((int)(size_left - (size)) < 0) \
+ errx(EX_DATAERR, "too big rule size\n"); \
+ }
+#define UPDATE_SIZE(size) size_left -= (size)
+
+/*
* _s_x is a structure that stores a string <-> token pairs, used in
* various places in the parser. Entries are stored in arrays,
* with an entry with s=NULL as terminator.
@@ -777,12 +797,14 @@
* Fill the body of the command with the list of port ranges.
*/
static int
-fill_newports(ipfw_insn_u16 *cmd, char *av, int proto)
+fill_newports(ipfw_insn_u16 *cmd, char *av, int proto, int size_left)
{
uint16_t a, b, *p = cmd->ports;
int i = 0;
char *s = av;
+ CHECK_SIZE(F_INSN_SIZE(*cmd));
+ UPDATE_SIZE(F_INSN_SIZE(ipfw_insn));
while (*s) {
a = strtoport(av, &s, 0, proto);
if (s == av) /* no parameter */
@@ -802,12 +824,14 @@
i++;
p += 2;
av = s+1;
- }
- if (i > 0) {
+ /* sizeof(u_int16_t[2]) = sizeof(u_int32_t) */
+ UPDATE_SIZE(F_INSN_SIZE(u_int32_t));
+ CHECK_SIZE(F_INSN_SIZE(u_int32_t));
if (i+1 > F_LEN_MASK)
errx(EX_DATAERR, "too many ports/ranges\n");
- cmd->o.len |= i+1; /* leave F_NOT and F_OR untouched */
}
+ if (i > 0)
+ cmd->o.len |= i+1; /* leave F_NOT and F_OR untouched */
return i;
}
@@ -1055,10 +1079,11 @@
}
static void
-fill_icmptypes(ipfw_insn_u32 *cmd, char *av)
+fill_icmptypes(ipfw_insn_u32 *cmd, char *av, int size_left)
{
uint8_t type;
+ CHECK_SIZE(F_INSN_SIZE(*cmd));
cmd->d[0] = 0;
while (*av) {
if (*av == ',')
@@ -1148,10 +1173,11 @@
}
static void
-fill_icmp6types(ipfw_insn_icmp6 *cmd, char *av)
+fill_icmp6types(ipfw_insn_icmp6 *cmd, char *av, int size_left)
{
uint8_t type;
+ CHECK_SIZE(F_INSN_SIZE(*cmd));
cmd->d[0] = 0;
while (*av) {
if (*av == ',')
@@ -1217,11 +1243,12 @@
/* fills command for the extension header filtering */
int
-fill_ext6hdr( ipfw_insn *cmd, char *av)
+fill_ext6hdr( ipfw_insn *cmd, char *av, int size_left)
{
int tok;
char *s = av;
+ CHECK_SIZE(F_INSN_SIZE(*cmd));
cmd->arg1 = 0;
while(s) {
@@ -2595,11 +2622,12 @@
* We can have multiple comma-separated address/mask entries.
*/
static void
-fill_ip(ipfw_insn_ip *cmd, char *av)
+fill_ip(ipfw_insn_ip *cmd, char *av, int size_left)
{
int len = 0;
uint32_t *d = ((ipfw_insn_u32 *)cmd)->d;
+ CHECK_SIZE(F_INSN_SIZE(ipfw_insn));
cmd->o.len &= ~F_LEN_MASK; /* zero len */
if (_substrcmp(av, "any") == 0)
@@ -2610,6 +2638,7 @@
return;
}
+ CHECK_SIZE(F_INSN_SIZE(ipfw_insn_u32));
if (strncmp(av, "table(", 6) == 0) {
char *p = strchr(av + 6, ',');
@@ -2625,6 +2654,7 @@
return;
}
+ UPDATE_SIZE(F_INSN_SIZE(ipfw_insn));
while (av) {
/*
* After the address we can have '/' or ':' indicating a mask,
@@ -2695,6 +2725,7 @@
d[0] = ntohl(d[0]); /* base addr in host format */
cmd->o.opcode = O_IP_DST_SET; /* default */
cmd->o.len |= F_INSN_SIZE(ipfw_insn_u32) + (cmd->o.arg1+31)/32;
+ CHECK_SIZE(cmd->o.len);
for (i = 0; i < (cmd->o.arg1+31)/32 ; i++)
map[i] = 0; /* clear map */
@@ -2766,8 +2797,16 @@
cmd->o.len |= F_INSN_SIZE(ipfw_insn_u32);
return;
}
- len += 2; /* two words... */
- d += 2;
+ len += F_INSN_SIZE(u_int32_t)*2; /* two words... */
+ d += F_INSN_SIZE(u_int32_t)*2;
+ UPDATE_SIZE(F_INSN_SIZE(u_int32_t)*2);
+ CHECK_SIZE(F_INSN_SIZE(u_int32_t)*2);
+ /*
+ * O_IP_SRC_MASK and O_IP_DST_MASK can not have length
+ * greater that 31
+ */
+ if (len > 30)
+ errx(EX_DATAERR, "too many addresses\n");
} /* end while */
cmd->o.len |= len+1;
}
@@ -2824,7 +2863,7 @@
* Return 1 on success, 0 on failure.
*/
static int
-fill_ip6(ipfw_insn_ip6 *cmd, char *av)
+fill_ip6(ipfw_insn_ip6 *cmd, char *av, int size_left)
{
int len = 0;
struct in6_addr *d = &(cmd->addr6);
@@ -2833,6 +2872,7 @@
* Note d[1] points to struct in6_add r mask6 of cmd
*/
+ CHECK_SIZE(F_INSN_SIZE(ipfw_insn));
cmd->o.len &= ~F_LEN_MASK; /* zero len */
if (strcmp(av, "any") == 0)
@@ -2850,6 +2890,9 @@
}
av = strdup(av);
+
+ CHECK_SIZE(F_INSN_SIZE(ipfw_insn_ip6));
+ UPDATE_SIZE(F_INSN_SIZE(ipfw_insn));
while (av) {
/*
* After the address we can have '/' indicating a mask,
@@ -2914,6 +2957,10 @@
/* Update length and pointer to arguments */
len += F_INSN_SIZE(struct in6_addr)*2;
d += 2;
+ UPDATE_SIZE(F_INSN_SIZE(struct in6_addr)*2);
+ CHECK_SIZE(F_INSN_SIZE(struct in6_addr)*2);
+ if (len + 1 > F_LEN_MASK)
+ errx(EX_DATAERR, "too many addresses\n");
} /* end while */
/*
@@ -2932,13 +2979,15 @@
* additional flow-id we want to filter, the basic is 1
*/
void
-fill_flow6( ipfw_insn_u32 *cmd, char *av )
+fill_flow6(ipfw_insn_u32 *cmd, char *av, int size_left)
{
u_int32_t type; /* Current flow number */
u_int16_t nflow = 0; /* Current flow index */
char *s = av;
- cmd->d[0] = 0; /* Initializing the base number*/
+ CHECK_SIZE(F_INSN_SIZE(ipfw_insn_u32));
+ UPDATE_SIZE(F_INSN_SIZE(ipfw_insn));
+ cmd->d[0] = 0; /* Initializing the base number*/
while (s) {
av = strsep( &s, ",") ;
type = strtoul(av, &av, 0);
@@ -2947,6 +2996,8 @@
if (type > 0xfffff)
errx(EX_DATAERR, "flow number out of range %s", av);
cmd->d[nflow] |= type;
+ UPDATE_SIZE(F_INSN_SIZE(u_int32_t));
+ CHECK_SIZE(F_INSN_SIZE(u_int32_t));
nflow++;
}
if( nflow > 0 ) {
@@ -2960,10 +3011,10 @@
}
static ipfw_insn *
-add_srcip6(ipfw_insn *cmd, char *av)
+add_srcip6(ipfw_insn *cmd, char *av, int size_left)
{
- fill_ip6((ipfw_insn_ip6 *)cmd, av);
+ fill_ip6((ipfw_insn_ip6 *)cmd, av, size_left);
if (F_LEN(cmd) == 0) /* any */
;
if (F_LEN(cmd) == F_INSN_SIZE(ipfw_insn)) { /* "me" */
@@ -2979,10 +3030,10 @@
}
static ipfw_insn *
-add_dstip6(ipfw_insn *cmd, char *av)
+add_dstip6(ipfw_insn *cmd, char *av, int size_left)
{
- fill_ip6((ipfw_insn_ip6 *)cmd, av);
+ fill_ip6((ipfw_insn_ip6 *)cmd, av, size_left);
if (F_LEN(cmd) == 0) /* any */
;
if (F_LEN(cmd) == F_INSN_SIZE(ipfw_insn)) { /* "me" */
@@ -3088,8 +3139,9 @@
* patterns which match interfaces.
*/
static void
-fill_iface(ipfw_insn_if *cmd, char *arg)
+fill_iface(ipfw_insn_if *cmd, char *arg, int size_left)
{
+ CHECK_SIZE(F_INSN_SIZE(*cmd));
cmd->name[0] = '\0';
cmd->o.len |= F_INSN_SIZE(ipfw_insn_if);
@@ -3511,11 +3563,12 @@
* Takes arguments and copies them into a comment
*/
static void
-fill_comment(ipfw_insn *cmd, int ac, char **av)
+fill_comment(ipfw_insn *cmd, int ac, char **av, int size_left)
{
int i, l;
char *p = (char *)(cmd + 1);
+ CHECK_SIZE(F_INSN_SIZE(*cmd))
cmd->opcode = O_NOP;
cmd->len = (cmd->len & (F_NOT | F_OR));
@@ -3528,6 +3581,7 @@
errx(EX_DATAERR,
"comment too long (max 80 chars)");
l = 1 + (l+3)/4;
+ CHECK_SIZE(l);
cmd->len = (cmd->len & (F_NOT | F_OR)) | l;
for (i = 0; i < ac; i++) {
strcpy(p, av[i]);
@@ -3554,10 +3608,11 @@
* two microinstructions, and returns the pointer to the last one.
*/
static ipfw_insn *
-add_mac(ipfw_insn *cmd, int ac, char *av[])
+add_mac(ipfw_insn *cmd, int ac, char *av[], int size_left)
{
ipfw_insn_mac *mac;
+ CHECK_SIZE(F_INSN_SIZE(ipfw_insn_mac));
if (ac < 2)
errx(EX_DATAERR, "MAC dst src");
@@ -3571,12 +3626,14 @@
}
static ipfw_insn *
-add_mactype(ipfw_insn *cmd, int ac, char *av)
+add_mactype(ipfw_insn *cmd, int ac, char *av, int size_left)
{
if (ac < 1)
errx(EX_DATAERR, "missing MAC type");
if (strcmp(av, "any") != 0) { /* we have a non-null type */
- fill_newports((ipfw_insn_u16 *)cmd, av, IPPROTO_ETHERTYPE);
+ fill_newports((ipfw_insn_u16 *)cmd, av, IPPROTO_ETHERTYPE, size_left);
+ if (F_LEN(cmd) > 31)
+ errx(EX_DATAERR, "too many MAC types\n");
cmd->opcode = O_MAC_TYPE;
return cmd;
} else
@@ -3645,9 +3702,9 @@
}
static ipfw_insn *
-add_srcip(ipfw_insn *cmd, char *av)
+add_srcip(ipfw_insn *cmd, char *av, int size_left)
{
- fill_ip((ipfw_insn_ip *)cmd, av);
+ fill_ip((ipfw_insn_ip *)cmd, av, size_left);
if (cmd->opcode == O_IP_DST_SET) /* set */
cmd->opcode = O_IP_SRC_SET;
else if (cmd->opcode == O_IP_DST_LOOKUP) /* table */
@@ -3662,9 +3719,9 @@
}
static ipfw_insn *
-add_dstip(ipfw_insn *cmd, char *av)
+add_dstip(ipfw_insn *cmd, char *av, int size_left)
{
- fill_ip((ipfw_insn_ip *)cmd, av);
+ fill_ip((ipfw_insn_ip *)cmd, av, size_left);
if (cmd->opcode == O_IP_DST_SET) /* set */
;
else if (cmd->opcode == O_IP_DST_LOOKUP) /* table */
@@ -3679,30 +3736,42 @@
}
static ipfw_insn *
-add_ports(ipfw_insn *cmd, char *av, u_char proto, int opcode)
+add_ports(ipfw_insn *cmd, char *av, u_char proto, int opcode, int size_left)
{
- if (_substrcmp(av, "any") == 0) {
+ if (_substrcmp(av, "any") == 0)
return NULL;
- } else if (fill_newports((ipfw_insn_u16 *)cmd, av, proto)) {
+
+ if (fill_newports((ipfw_insn_u16 *)cmd, av, proto, size_left)) {
/* XXX todo: check that we have a protocol with ports */
cmd->opcode = opcode;
+ if(F_LEN(cmd) > 31)
+ switch(opcode) {
+ case O_IPID:
+ case O_IPTTL:
+ case O_IPLEN:
+ case O_TCPDATALEN:
+ errx(EX_DATAERR, "too many options\n");
+ case O_IP_SRCPORT:
+ case O_IP_DSTPORT:
+ errx(EX_DATAERR, "too many ports\n");
+ };
return cmd;
}
return NULL;
}
static ipfw_insn *
-add_src(ipfw_insn *cmd, char *av, u_char proto)
+add_src(ipfw_insn *cmd, char *av, u_char proto, int size_left)
{
struct in6_addr a;
if (proto == IPPROTO_IPV6 || strcmp(av, "me6") == 0 ||
inet_pton(AF_INET6, av, &a))
- return add_srcip6(cmd, av);
+ return add_srcip6(cmd, av, size_left);
/* XXX: should check for IPv4, not !IPv6 */
if (proto == IPPROTO_IP || strcmp(av, "me") == 0 ||
!inet_pton(AF_INET6, av, &a))
- return add_srcip(cmd, av);
+ return add_srcip(cmd, av, size_left);
if (strcmp(av, "any") != 0)
return cmd;
@@ -3710,17 +3779,17 @@
}
static ipfw_insn *
-add_dst(ipfw_insn *cmd, char *av, u_char proto)
+add_dst(ipfw_insn *cmd, char *av, u_char proto, int size_left)
{
struct in6_addr a;
if (proto == IPPROTO_IPV6 || strcmp(av, "me6") == 0 ||
inet_pton(AF_INET6, av, &a))
- return add_dstip6(cmd, av);
+ return add_dstip6(cmd, av, size_left);
/* XXX: should check for IPv4, not !IPv6 */
if (proto == IPPROTO_IP || strcmp(av, "me") == 0 ||
!inet_pton(AF_INET6, av, &a))
- return add_dstip(cmd, av);
+ return add_dstip(cmd, av, size_left);
if (strcmp(av, "any") != 0)
return cmd;
@@ -3748,7 +3817,11 @@
* Some things that need to go out of order (prob, action etc.)
* go into actbuf[].
*/
- static uint32_t rulebuf[255], actbuf[255], cmdbuf[255];
+
+#define MAX_INSN 255
+ static uint32_t rulebuf[MAX_INSN], actbuf[MAX_INSN], cmdbuf[MAX_INSN];
+ int size_left = MAX_INSN;
+ int off; /* av offset */
ipfw_insn *src, *dst, *cmd, *action, *prev=NULL;
ipfw_insn *first_cmd; /* first match pattern */
@@ -3780,6 +3853,7 @@
action = (ipfw_insn *)actbuf;
av++; ac--;
+ CHECK_SIZE(F_INSN_SIZE(struct ip_fw));
/* [rule N] -- Rule number optional */
if (ac && isdigit(**av)) {
@@ -3797,12 +3871,15 @@
av += 2; ac -= 2;
}
+ UPDATE_SIZE(F_INSN_SIZE(struct ip_fw) - F_INSN_SIZE(ipfw_insn));
/* [prob D] -- match probability, optional */
if (ac > 1 && _substrcmp(*av, "prob") == 0) {
match_prob = strtod(av[1], NULL);
if (match_prob <= 0 || match_prob > 1)
errx(EX_DATAERR, "illegal match prob. %s", av[1]);
+ /* reserve size for O_PROB */
+ UPDATE_SIZE(F_INSN_SIZE(ipfw_insn_u32));
av += 2; ac -= 2;
}
@@ -3810,7 +3887,8 @@
NEED1("missing action");
i = match_token(rule_actions, *av);
ac--; av++;
- action->len = 1; /* default */
+ CHECK_SIZE(F_INSN_SIZE(ipfw_insn));
+ action->len = F_INSN_SIZE(ipfw_insn); /* default */
switch(i) {
case TOK_CHECKSTATE:
have_state = action;
@@ -3907,6 +3985,7 @@
char *s, *end;
NEED1("missing forward address[:port]");
+ CHECK_SIZE(F_INSN_SIZE(ipfw_insn_sa));
action->opcode = O_FORWARD_IP;
action->len = F_INSN_SIZE(ipfw_insn_sa);
@@ -3942,6 +4021,8 @@
default:
errx(EX_DATAERR, "invalid action %s\n", av[-1]);
}
+ UPDATE_SIZE(action->len);
+ CHECK_SIZE(F_INSN_SIZE(ipfw_insn));
action = next_cmd(action);
/*
@@ -3962,6 +4043,7 @@
if (have_log)
errx(EX_DATAERR,
"log cannot be specified more than once");
+ CHECK_SIZE(F_INSN_SIZE(ipfw_insn_log));
have_log = (ipfw_insn *)c;
cmd->len = F_INSN_SIZE(ipfw_insn_log);
cmd->opcode = O_LOG;
@@ -3992,6 +4074,7 @@
if (have_altq)
errx(EX_DATAERR,
"altq cannot be specified more than once");
+ CHECK_SIZE(F_INSN_SIZE(ipfw_insn_altq));
have_altq = (ipfw_insn *)a;
cmd->len = F_INSN_SIZE(ipfw_insn_altq);
cmd->opcode = O_ALTQ;
@@ -4003,6 +4086,7 @@
default:
abort();
}
+ UPDATE_SIZE(F_LEN(cmd));
cmd = next_cmd(cmd);
}
@@ -4016,9 +4100,9 @@
prev = NULL; \
open_par = 1; \
if ( (av[0])[1] == '\0') { \
- ac--; av++; \
+ ac--; av++; off = 0; \
} else \
- (*av)++; \
+ off = 1; \
} \
target: \
@@ -4044,6 +4128,7 @@
}
#define OR_BLOCK(target) \
+ off = 0; \
if (ac && _substrcmp(*av, "or") == 0) { \
if (prev == NULL || open_par == 0) \
errx(EX_DATAERR, "invalid OR block"); \
@@ -4084,9 +4169,11 @@
OR_START(get_proto);
NOT_BLOCK;
NEED1("missing protocol");
- if (add_proto_compat(cmd, *av, &proto)) {
+ CHECK_SIZE(F_INSN_SIZE(ipfw_insn));
+ if (add_proto_compat(cmd, *av + off, &proto)) {
av++; ac--;
if (F_LEN(cmd) != 0) {
+ UPDATE_SIZE(F_LEN(cmd));
prev = cmd;
cmd = next_cmd(cmd);
}
@@ -4109,9 +4196,10 @@
OR_START(source_ip);
NOT_BLOCK; /* optional "not" */
NEED1("missing source address");
- if (add_src(cmd, *av, proto)) {
+ if (add_src(cmd, *av + off, proto, size_left)) {
ac--; av++;
if (F_LEN(cmd) != 0) { /* ! any */
+ UPDATE_SIZE(F_LEN(cmd));
prev = cmd;
cmd = next_cmd(cmd);
}
@@ -4125,12 +4213,14 @@
NOT_BLOCK; /* optional "not" */
if (ac) {
if (_substrcmp(*av, "any") == 0 ||
- add_ports(cmd, *av, proto, O_IP_SRCPORT)) {
+ add_ports(cmd, *av, proto, O_IP_SRCPORT, size_left)) {
ac--; av++;
- if (F_LEN(cmd) != 0)
+ if (F_LEN(cmd) != 0) {
+ UPDATE_SIZE(F_LEN(cmd));
cmd = next_cmd(cmd);
}
}
+ }
/*
* "to", mandatory
@@ -4145,9 +4235,10 @@
OR_START(dest_ip);
NOT_BLOCK; /* optional "not" */
NEED1("missing dst address");
- if (add_dst(cmd, *av, proto)) {
+ if (add_dst(cmd, *av + off, proto, size_left)) {
ac--; av++;
if (F_LEN(cmd) != 0) { /* ! any */
+ UPDATE_SIZE(F_LEN(cmd));
prev = cmd;
cmd = next_cmd(cmd);
}
@@ -4161,12 +4252,14 @@
NOT_BLOCK; /* optional "not" */
if (ac) {
if (_substrcmp(*av, "any") == 0 ||
- add_ports(cmd, *av, proto, O_IP_DSTPORT)) {
+ add_ports(cmd, *av, proto, O_IP_DSTPORT, size_left)) {
ac--; av++;
- if (F_LEN(cmd) != 0)
+ if (F_LEN(cmd) != 0) {
+ UPDATE_SIZE(F_LEN(cmd));
cmd = next_cmd(cmd);
}
}
+ }
read_options:
if (ac && first_cmd == cmd) {
@@ -4184,6 +4277,8 @@
s = *av;
cmd32 = (ipfw_insn_u32 *)cmd;
+ CHECK_SIZE(F_INSN_SIZE(ipfw_insn_u32));
+
if (*s == '!') { /* alternate syntax for NOT */
if (cmd->len & F_NOT)
errx(EX_USAGE, "double \"not\" not allowed\n");
@@ -4252,7 +4347,7 @@
case TOK_VIA:
NEED1("recv, xmit, via require interface name"
" or address");
- fill_iface((ipfw_insn_if *)cmd, av[0]);
+ fill_iface((ipfw_insn_if *)cmd, av[0], size_left);
ac--; av++;
if (F_LEN(cmd) == 0) /* not a valid address */
break;
@@ -4266,20 +4361,20 @@
case TOK_ICMPTYPES:
NEED1("icmptypes requires list of types");
- fill_icmptypes((ipfw_insn_u32 *)cmd, *av);
+ fill_icmptypes((ipfw_insn_u32 *)cmd, *av, size_left);
av++; ac--;
break;
case TOK_ICMP6TYPES:
NEED1("icmptypes requires list of types");
- fill_icmp6types((ipfw_insn_icmp6 *)cmd, *av);
+ fill_icmp6types((ipfw_insn_icmp6 *)cmd, *av, size_left);
av++; ac--;
break;
case TOK_IPTTL:
NEED1("ipttl requires TTL");
if (strpbrk(*av, "-,")) {
- if (!add_ports(cmd, *av, 0, O_IPTTL))
+ if (!add_ports(cmd, *av, 0, O_IPTTL, size_left))
errx(EX_DATAERR, "invalid ipttl %s", *av);
} else
fill_cmd(cmd, O_IPTTL, 0, strtoul(*av, NULL, 0));
@@ -4289,7 +4384,7 @@
case TOK_IPID:
NEED1("ipid requires id");
if (strpbrk(*av, "-,")) {
- if (!add_ports(cmd, *av, 0, O_IPID))
+ if (!add_ports(cmd, *av, 0, O_IPID, size_left))
errx(EX_DATAERR, "invalid ipid %s", *av);
} else
fill_cmd(cmd, O_IPID, 0, strtoul(*av, NULL, 0));
@@ -4299,7 +4394,7 @@
case TOK_IPLEN:
NEED1("iplen requires length");
if (strpbrk(*av, "-,")) {
- if (!add_ports(cmd, *av, 0, O_IPLEN))
+ if (!add_ports(cmd, *av, 0, O_IPLEN, size_left))
errx(EX_DATAERR, "invalid ip len %s", *av);
} else
fill_cmd(cmd, O_IPLEN, 0, strtoul(*av, NULL, 0));
@@ -4395,7 +4490,7 @@
case TOK_TCPDATALEN:
NEED1("tcpdatalen requires length");
if (strpbrk(*av, "-,")) {
- if (!add_ports(cmd, *av, 0, O_TCPDATALEN))
+ if (!add_ports(cmd, *av, 0, O_TCPDATALEN, size_left))
errx(EX_DATAERR, "invalid tcpdata len %s", *av);
} else
fill_cmd(cmd, O_TCPDATALEN, 0,
@@ -4451,6 +4546,7 @@
errx(EX_USAGE, "only one of keep-state "
"and limit is allowed");
NEED1("limit needs mask and # of connections");
+ CHECK_SIZE(F_INSN_SIZE(ipfw_insn_limit));
have_state = cmd;
{
ipfw_insn_limit *c = (ipfw_insn_limit *)cmd;
@@ -4488,28 +4584,28 @@
case TOK_SRCIP:
NEED1("missing source IP");
- if (add_srcip(cmd, *av)) {
+ if (add_srcip(cmd, *av, size_left)) {
ac--; av++;
}
break;
case TOK_DSTIP:
NEED1("missing destination IP");
- if (add_dstip(cmd, *av)) {
+ if (add_dstip(cmd, *av, size_left)) {
ac--; av++;
}
break;
case TOK_SRCIP6:
NEED1("missing source IP6");
- if (add_srcip6(cmd, *av)) {
+ if (add_srcip6(cmd, *av, size_left)) {
ac--; av++;
}
break;
case TOK_DSTIP6:
NEED1("missing destination IP6");
- if (add_dstip6(cmd, *av)) {
+ if (add_dstip6(cmd, *av, size_left)) {
ac--; av++;
}
break;
@@ -4517,7 +4613,7 @@
case TOK_SRCPORT:
NEED1("missing source port");
if (_substrcmp(*av, "any") == 0 ||
- add_ports(cmd, *av, proto, O_IP_SRCPORT)) {
+ add_ports(cmd, *av, proto, O_IP_SRCPORT, size_left)) {
ac--; av++;
} else
errx(EX_DATAERR, "invalid source port %s", *av);
@@ -4526,7 +4622,7 @@
case TOK_DSTPORT:
NEED1("missing destination port");
if (_substrcmp(*av, "any") == 0 ||
- add_ports(cmd, *av, proto, O_IP_DSTPORT)) {
+ add_ports(cmd, *av, proto, O_IP_DSTPORT, size_left)) {
ac--; av++;
} else
errx(EX_DATAERR, "invalid destination port %s",
@@ -4534,14 +4630,14 @@
break;
case TOK_MAC:
- if (add_mac(cmd, ac, av)) {
+ if (add_mac(cmd, ac, av, size_left)) {
ac -= 2; av += 2;
}
break;
case TOK_MACTYPE:
NEED1("missing mac type");
- if (!add_mactype(cmd, ac, *av))
+ if (!add_mactype(cmd, ac, *av, size_left))
errx(EX_DATAERR, "invalid mac type %s", *av);
ac--; av++;
break;
@@ -4571,7 +4667,7 @@
break;
case TOK_EXT6HDR:
- fill_ext6hdr( cmd, *av );
+ fill_ext6hdr(cmd, *av, size_left);
ac--; av++;
break;
@@ -4579,12 +4675,12 @@
if (proto != IPPROTO_IPV6 )
errx( EX_USAGE, "flow-id filter is active "
"only for ipv6 protocol\n");
- fill_flow6( (ipfw_insn_u32 *) cmd, *av );
+ fill_flow6((ipfw_insn_u32 *)cmd, *av, size_left);
ac--; av++;
break;
case TOK_COMMENT:
- fill_comment(cmd, ac, av);
+ fill_comment(cmd, ac, av, size_left);
av += ac;
ac = 0;
break;
@@ -4593,6 +4689,7 @@
errx(EX_USAGE, "unrecognised option [%d] %s\n", i, s);
}
if (F_LEN(cmd) > 0) { /* prepare to advance */
+ UPDATE_SIZE(F_LEN(cmd));
prev = cmd;
cmd = next_cmd(cmd);
}
More information about the freebsd-ipfw
mailing list