diff options
author | glebius <glebius@FreeBSD.org> | 2005-12-13 12:16:03 +0000 |
---|---|---|
committer | glebius <glebius@FreeBSD.org> | 2005-12-13 12:16:03 +0000 |
commit | d5ab5191cf5df5bcf63257124ddb49c77c2d7137 (patch) | |
tree | 6cd65aeebdffa5fddf4f8da962ba7f377ec1a186 | |
parent | 97acc24830d83fc3b09a8cf246b54ccb44f0940e (diff) | |
download | FreeBSD-src-d5ab5191cf5df5bcf63257124ddb49c77c2d7137.zip FreeBSD-src-d5ab5191cf5df5bcf63257124ddb49c77c2d7137.tar.gz |
Add a new feature for optimizining ipfw rulesets - substitution of the
action argument with the value obtained from table lookup. The feature
is now applicable only to "pipe", "queue", "divert", "tee", "netgraph"
and "ngtee" rules.
An example usage:
ipfw pipe 1000 config bw 1000Kbyte/s
ipfw pipe 4000 config bw 4000Kbyte/s
ipfw table 1 add x.x.x.x 1000
ipfw table 1 add x.x.x.y 4000
ipfw pipe tablearg ip from table(1) to any
In the example above the rule will throw different packets to different pipes.
TODO:
- Support "skipto" action, but without searching all rules.
- Improve parser, so that it warns about bad rules. These are:
- "tablearg" argument to action, but no "table" in the rule. All
traffic will be blocked.
- "tablearg" argument to action, but "table" searches for entry with
a specific value. All traffic will be blocked.
- "tablearg" argument to action, and two "table" looks - for src and
for dst. The last lookup will match.
-rw-r--r-- | sbin/ipfw/ipfw2.c | 90 | ||||
-rw-r--r-- | sys/netinet/ip_fw.h | 2 | ||||
-rw-r--r-- | sys/netinet/ip_fw2.c | 21 |
3 files changed, 62 insertions, 51 deletions
diff --git a/sbin/ipfw/ipfw2.c b/sbin/ipfw/ipfw2.c index 28a8c98..13e1df3 100644 --- a/sbin/ipfw/ipfw2.c +++ b/sbin/ipfw/ipfw2.c @@ -420,6 +420,8 @@ struct _s_x rule_options[] = { { NULL, 0 } /* terminator */ }; +#define TABLEARG "tablearg" + static __inline uint64_t align_uint64(uint64_t *pll) { uint64_t ret; @@ -1457,33 +1459,28 @@ show_ipfw(struct ip_fw *rule, int pcwidth, int bcwidth) print_unreach6_code(cmd->arg1); break; - case O_SKIPTO: - printf("skipto %u", cmd->arg1); +#define PRINT_WITH_ARG(o) \ + if (cmd->arg1 == IP_FW_TABLEARG) \ + printf("%s tablearg", (o)); \ + else \ + printf("%s %u", (o), cmd->arg1); \ break; + case O_SKIPTO: + PRINT_WITH_ARG("skipto"); case O_PIPE: - printf("pipe %u", cmd->arg1); - break; - + PRINT_WITH_ARG("pipe"); case O_QUEUE: - printf("queue %u", cmd->arg1); - break; - + PRINT_WITH_ARG("queue"); case O_DIVERT: - printf("divert %u", cmd->arg1); - break; - + PRINT_WITH_ARG("divert"); case O_TEE: - printf("tee %u", cmd->arg1); - break; - + PRINT_WITH_ARG("tee"); case O_NETGRAPH: - printf("netgraph %u", cmd->arg1); - break; - + PRINT_WITH_ARG("netgraph"); case O_NGTEE: - printf("ngtee %u", cmd->arg1); - break; + PRINT_WITH_ARG("ngtee"); +#undef PRINT_WITH_ARG case O_FORWARD_IP: { @@ -3863,26 +3860,36 @@ add(int ac, char *av[]) break; case TOK_QUEUE: + action->opcode = O_QUEUE; + goto chkarg; case TOK_PIPE: - action->len = F_INSN_SIZE(ipfw_insn); + action->opcode = O_PIPE; + goto chkarg; case TOK_SKIPTO: - if (i == TOK_QUEUE) - action->opcode = O_QUEUE; - else if (i == TOK_PIPE) - action->opcode = O_PIPE; - else if (i == TOK_SKIPTO) - action->opcode = O_SKIPTO; - NEED1("missing skipto/pipe/queue number"); - action->arg1 = strtoul(*av, NULL, 10); - av++; ac--; - break; - + action->opcode = O_SKIPTO; + goto chkarg; + case TOK_NETGRAPH: + action->opcode = O_NETGRAPH; + goto chkarg; + case TOK_NGTEE: + action->opcode = O_NGTEE; + goto chkarg; case TOK_DIVERT: + action->opcode = O_DIVERT; + goto chkarg; case TOK_TEE: - action->opcode = (i == TOK_DIVERT) ? O_DIVERT : O_TEE; - NEED1("missing divert/tee port"); - action->arg1 = strtoul(*av, NULL, 0); - if (action->arg1 == 0) { + action->opcode = O_TEE; +chkarg: + if (!ac) + errx(EX_USAGE, "missing argument for %s", *(av - 1)); + if (isdigit(**av)) { + action->arg1 = strtoul(*av, NULL, 10); + if (action->arg1 <= 0 || action->arg1 >= IP_FW_TABLEARG) + errx(EX_DATAERR, "illegal argument for %s", + *(av - 1)); + } else if (_substrcmp(*av, TABLEARG) == 0) { + action->arg1 = IP_FW_TABLEARG; + } else if (i == TOK_DIVERT || i == TOK_TEE) { struct servent *s; setservent(1); s = getservbyname(av[0], "divert"); @@ -3890,17 +3897,8 @@ add(int ac, char *av[]) action->arg1 = ntohs(s->s_port); else errx(EX_DATAERR, "illegal divert/tee port"); - } - ac--; av++; - break; - - case TOK_NETGRAPH: - case TOK_NGTEE: - action->opcode = (i == TOK_NETGRAPH ) ? O_NETGRAPH : O_NGTEE; - NEED1("missing netgraph cookie"); - action->arg1 = strtoul(*av, NULL, 0); - if (action->arg1 == 0) - errx(EX_DATAERR, "illegal netgraph cookie"); + } else + errx(EX_DATAERR, "illegal argument for %s", *(av - 1)); ac--; av++; break; diff --git a/sys/netinet/ip_fw.h b/sys/netinet/ip_fw.h index dc5b563..e6ab185 100644 --- a/sys/netinet/ip_fw.h +++ b/sys/netinet/ip_fw.h @@ -461,6 +461,8 @@ typedef struct _ipfw_table { ipfw_table_entry ent[0]; /* entries */ } ipfw_table; +#define IP_FW_TABLEARG 65535 + /* * Main firewall chains definitions and global var's definitions. */ diff --git a/sys/netinet/ip_fw2.c b/sys/netinet/ip_fw2.c index 92c01a4..7627080 100644 --- a/sys/netinet/ip_fw2.c +++ b/sys/netinet/ip_fw2.c @@ -2383,9 +2383,9 @@ do { \ * Now scan the rules, and parse microinstructions for each rule. */ for (; f; f = f->next) { - int l, cmdlen; ipfw_insn *cmd; - int skip_or; /* skip rest of OR block */ + uint32_t tablearg = 0; + int l, cmdlen, skip_or; /* skip rest of OR block */ again: if (set_disable & (1 << f->set) ) @@ -2548,6 +2548,8 @@ check_body: if (cmdlen == F_INSN_SIZE(ipfw_insn_u32)) match = ((ipfw_insn_u32 *)cmd)->d[0] == v; + else + tablearg = v; } break; @@ -2999,7 +3001,10 @@ check_body: case O_PIPE: case O_QUEUE: args->rule = f; /* report matching rule */ - args->cookie = cmd->arg1; + if (cmd->arg1 == IP_FW_TABLEARG) + args->cookie = tablearg; + else + args->cookie = cmd->arg1; retval = IP_FW_DUMMYNET; goto done; @@ -3020,7 +3025,10 @@ check_body: } dt = (struct divert_tag *)(mtag+1); dt->cookie = f->rulenum; - dt->info = cmd->arg1; + if (cmd->arg1 == IP_FW_TABLEARG) + dt->info = tablearg; + else + dt->info = cmd->arg1; m_tag_prepend(m, mtag); retval = (cmd->opcode == O_DIVERT) ? IP_FW_DIVERT : IP_FW_TEE; @@ -3085,7 +3093,10 @@ check_body: case O_NETGRAPH: case O_NGTEE: args->rule = f; /* report matching rule */ - args->cookie = cmd->arg1; + if (cmd->arg1 == IP_FW_TABLEARG) + args->cookie = tablearg; + else + args->cookie = cmd->arg1; retval = (cmd->opcode == O_NETGRAPH) ? IP_FW_NETGRAPH : IP_FW_NGTEE; goto done; |