From 8ed2d7497bc11b70aa2df374376a06818d1b0a19 Mon Sep 17 00:00:00 2001 From: Luigi Rizzo Date: Sat, 10 Aug 2002 15:10:15 +0000 Subject: [PATCH] Fix one parsing bug introduced by last commit, and correct parsing and printing of or-blocks in address, ports and options lists. --- sbin/ipfw/ipfw2.c | 81 ++++++++++++++++++++++++++++++++++++----------- 1 file changed, 63 insertions(+), 18 deletions(-) diff --git a/sbin/ipfw/ipfw2.c b/sbin/ipfw/ipfw2.c index 78b32a1d00ba..0f577e583945 100644 --- a/sbin/ipfw/ipfw2.c +++ b/sbin/ipfw/ipfw2.c @@ -178,6 +178,8 @@ enum tokens { TOK_OR, TOK_NOT, + TOK_STARTBRACE, + TOK_ENDBRACE, TOK_ACCEPT, TOK_COUNT, @@ -323,6 +325,10 @@ struct _s_x rule_options[] = { { "!", /* escape ? */ TOK_NOT }, /* pseudo option */ { "or", TOK_OR }, /* pseudo option */ { "|", /* escape */ TOK_OR }, /* pseudo option */ + { "{", TOK_STARTBRACE }, /* pseudo option */ + { "(", TOK_STARTBRACE }, /* pseudo option */ + { "}", TOK_ENDBRACE }, /* pseudo option */ + { ")", TOK_ENDBRACE }, /* pseudo option */ { NULL, TOK_NULL }, { NULL, 0 } }; @@ -935,6 +941,8 @@ show_ipfw(struct ip_fw *rule) HAVE_PROTO|HAVE_SRCIP|HAVE_DSTIP); case O_IP_SRCPORT: show_prerequisites(&flags, HAVE_PROTO|HAVE_SRCIP); + if ((cmd->len & F_OR) && !or_block) + printf(" {"); print_newports((ipfw_insn_u16 *)cmd, proto); break; @@ -1696,7 +1704,7 @@ delete(int ac, char *av[]) else if (!strncmp(*av, "enable", strlen(*av))) do_set = 3; /* enable set */ av++; ac--; - if (!strncmp(*av, "set", strlen(*av))) { + if (ac > 0 && !strncmp(*av, "set", strlen(*av))) { if (do_set == 0) do_set = 1; /* delete set */ ac--; av++; @@ -2407,6 +2415,7 @@ add(int ac, char *av[]) if (ac && (*av[0] == '(' || *av[0] == '{')) { \ if (open_par) \ errx(EX_USAGE, "nested \"(\" not allowed\n"); \ + prev = NULL; \ open_par = 1; \ if ( (av[0])[1] == '\0') { \ ac--; av++; \ @@ -2421,6 +2430,7 @@ add(int ac, char *av[]) if (ac && ( \ !strncmp(*av, ")", strlen(*av)) || \ !strncmp(*av, "}", strlen(*av)) )) { \ + prev = NULL; \ open_par = 0; \ ac--; av++; \ } else \ @@ -2508,17 +2518,24 @@ add(int ac, char *av[]) cmd = next_cmd(cmd); OR_BLOCK(source_ip); + OR_START(source_port); /* * source ports, optional */ NOT_BLOCK; /* optional "not" */ - if (ac && fill_newports((ipfw_insn_u16 *)cmd, *av, proto)) { - /* XXX todo: check that we have a protocol with ports */ - cmd->opcode = O_IP_SRCPORT; - ac--; - av++; - cmd = next_cmd(cmd); + if (ac) { + if (!strncmp(*av, "any", strlen(*av))) { + ac--; + av++; + } else if (fill_newports((ipfw_insn_u16 *)cmd, *av, proto)) { + /* XXX todo: check that we have a protocol with ports */ + cmd->opcode = O_IP_SRCPORT; + ac--; + av++; + cmd = next_cmd(cmd); + } } + OR_BLOCK(source_port); read_to: /* @@ -2552,23 +2569,33 @@ add(int ac, char *av[]) cmd = next_cmd(cmd); OR_BLOCK(dest_ip); + OR_START(dest_port); /* * dest. ports, optional */ NOT_BLOCK; /* optional "not" */ - if (ac && fill_newports((ipfw_insn_u16 *)cmd, *av, proto)) { - /* XXX todo: check that we have a protocol with ports */ - cmd->opcode = O_IP_DSTPORT; - ac--; - av++; - cmd += F_LEN(cmd); + if (ac) { + if (!strncmp(*av, "any", strlen(*av))) { + ac--; + av++; + } else if (fill_newports((ipfw_insn_u16 *)cmd, *av, proto)) { + /* XXX todo: check that we have a protocol with ports */ + cmd->opcode = O_IP_DSTPORT; + ac--; + av++; + cmd += F_LEN(cmd); + } } + OR_BLOCK(dest_port); read_options: prev = NULL; while (ac) { - char *s = *av; - ipfw_insn_u32 *cmd32 = (ipfw_insn_u32 *)cmd; /* alias */ + char *s; + ipfw_insn_u32 *cmd32; /* alias for cmd */ + + s = *av; + cmd32 = (ipfw_insn_u32 *)cmd; if (*s == '!') { /* alternate syntax for NOT */ if (cmd->len & F_NOT) @@ -2586,11 +2613,23 @@ add(int ac, char *av[]) break; case TOK_OR: - if (prev == NULL) + if (open_par == 0 || prev == NULL) errx(EX_USAGE, "invalid \"or\" block\n"); prev->len |= F_OR; break; - + + case TOK_STARTBRACE: + if (open_par) + errx(EX_USAGE, "+nested \"(\" not allowed\n"); + open_par = 1; + break; + + case TOK_ENDBRACE: + if (!open_par) + errx(EX_USAGE, "+missing \")\"\n"); + open_par = 0; + break; + case TOK_IN: fill_cmd(cmd, O_IN, 0, 0); break; @@ -2750,6 +2789,9 @@ add(int ac, char *av[]) break; case TOK_KEEPSTATE: + if (open_par) + errx(EX_USAGE, "keep-state cannot be part " + "of an or block"); if (have_state) errx(EX_USAGE, "only one of keep-state " "and limit is allowed"); @@ -2758,10 +2800,13 @@ add(int ac, char *av[]) break; case TOK_LIMIT: - NEED1("limit needs mask and # of connections"); + if (open_par) + errx(EX_USAGE, "limit cannot be part " + "of an or block"); if (have_state) errx(EX_USAGE, "only one of keep-state " "and limit is allowed"); + NEED1("limit needs mask and # of connections"); have_state = cmd; { ipfw_insn_limit *c = (ipfw_insn_limit *)cmd;