diff options
Diffstat (limited to 'sbin/ipfw/ipfw2.c')
-rw-r--r-- | sbin/ipfw/ipfw2.c | 104 |
1 files changed, 91 insertions, 13 deletions
diff --git a/sbin/ipfw/ipfw2.c b/sbin/ipfw/ipfw2.c index 951ebd3..faf7b97 100644 --- a/sbin/ipfw/ipfw2.c +++ b/sbin/ipfw/ipfw2.c @@ -588,7 +588,7 @@ do_cmd(int optname, void *optval, uintptr_t optlen) * Returns 0 on success or errno otherwise. */ int -do_set3(int optname, ip_fw3_opheader *op3, uintptr_t optlen) +do_set3(int optname, ip_fw3_opheader *op3, size_t optlen) { if (co.test_only) @@ -618,6 +618,7 @@ int do_get3(int optname, ip_fw3_opheader *op3, size_t *optlen) { int error; + socklen_t len; if (co.test_only) return (0); @@ -629,8 +630,9 @@ do_get3(int optname, ip_fw3_opheader *op3, size_t *optlen) op3->opcode = optname; - error = getsockopt(ipfw_socket, IPPROTO_IP, IP_FW3, op3, - (socklen_t *)optlen); + len = *optlen; + error = getsockopt(ipfw_socket, IPPROTO_IP, IP_FW3, op3, &len); + *optlen = len; return (error); } @@ -1403,6 +1405,7 @@ show_static_rule(struct cmdline_opts *co, struct format_opts *fo, int l; ipfw_insn *cmd, *has_eaction = NULL, *tagptr = NULL; const char *comment = NULL; /* ptr to comment if we have one */ + const char *ename; int proto = 0; /* default */ int flags = 0; /* prerequisites */ ipfw_insn_log *logptr = NULL; /* set if we find an O_LOG */ @@ -1472,6 +1475,12 @@ show_static_rule(struct cmdline_opts *co, struct format_opts *fo, switch(cmd->opcode) { case O_CHECK_STATE: bprintf(bp, "check-state"); + if (cmd->arg1 != 0) + ename = object_search_ctlv(fo->tstate, + cmd->arg1, IPFW_TLV_STATE_NAME); + else + ename = NULL; + bprintf(bp, " :%s", ename ? ename: "any"); /* avoid printing anything else */ flags = HAVE_PROTO | HAVE_SRCIP | HAVE_DSTIP | HAVE_IP; @@ -1589,8 +1598,6 @@ show_static_rule(struct cmdline_opts *co, struct format_opts *fo, break; case O_EXTERNAL_ACTION: { - const char *ename; - /* * The external action can consists of two following * each other opcodes - O_EXTERNAL_ACTION and @@ -1611,8 +1618,6 @@ show_static_rule(struct cmdline_opts *co, struct format_opts *fo, } case O_EXTERNAL_INSTANCE: { - const char *ename; - if (has_eaction == NULL) break; /* @@ -2080,6 +2085,9 @@ show_static_rule(struct cmdline_opts *co, struct format_opts *fo, case O_KEEP_STATE: bprintf(bp, " keep-state"); + bprintf(bp, " :%s", + object_search_ctlv(fo->tstate, cmd->arg1, + IPFW_TLV_STATE_NAME)); break; case O_LIMIT: { @@ -2096,6 +2104,9 @@ show_static_rule(struct cmdline_opts *co, struct format_opts *fo, comma = ","; } bprint_uint_arg(bp, " ", c->conn_limit); + bprintf(bp, " :%s", + object_search_ctlv(fo->tstate, cmd->arg1, + IPFW_TLV_STATE_NAME)); break; } @@ -2194,7 +2205,10 @@ show_dyn_state(struct cmdline_opts *co, struct format_opts *fo, bprintf(bp, " <-> %s %d", inet_ntop(AF_INET6, &d->id.dst_ip6, buf, sizeof(buf)), d->id.dst_port); } else - bprintf(bp, " UNKNOWN <-> UNKNOWN\n"); + bprintf(bp, " UNKNOWN <-> UNKNOWN"); + if (d->kidx != 0) + bprintf(bp, " :%s", object_search_ctlv(fo->tstate, + d->kidx, IPFW_TLV_STATE_NAME)); } static int @@ -2835,6 +2849,18 @@ ipfw_check_object_name(const char *name) return (0); } +static char *default_state_name = "default"; +static int +state_check_name(const char *name) +{ + + if (ipfw_check_object_name(name) != 0) + return (EINVAL); + if (strcmp(name, "any") == 0) + return (EINVAL); + return (0); +} + static int eaction_check_name(const char *name) { @@ -3705,6 +3731,25 @@ compile_rule(char *av[], uint32_t *rbuf, int *rbufsize, struct tidx *tstate) case TOK_CHECKSTATE: have_state = action; action->opcode = O_CHECK_STATE; + if (*av == NULL || + match_token(rule_options, *av) == TOK_COMMENT) { + action->arg1 = pack_object(tstate, + default_state_name, IPFW_TLV_STATE_NAME); + break; + } + if (*av[0] == ':') { + if (strcmp(*av + 1, "any") == 0) + action->arg1 = 0; + else if (state_check_name(*av + 1) == 0) + action->arg1 = pack_object(tstate, *av + 1, + IPFW_TLV_STATE_NAME); + else + errx(EX_DATAERR, "Invalid state name %s", + *av); + av++; + break; + } + errx(EX_DATAERR, "Invalid state name %s", *av); break; case TOK_ACCEPT: @@ -4093,8 +4138,17 @@ chkarg: cmd = next_cmd(cmd, &cblen); } - if (have_state) /* must be a check-state, we are done */ + if (have_state) { /* must be a check-state, we are done */ + if (*av != NULL && + match_token(rule_options, *av) == TOK_COMMENT) { + /* check-state has a comment */ + av++; + fill_comment(cmd, av, cblen); + cmd = next_cmd(cmd, &cblen); + av[0] = NULL; + } goto done; + } #define OR_START(target) \ if (av[0] && (*av[0] == '(' || *av[0] == '{')) { \ @@ -4529,16 +4583,29 @@ read_options: av++; break; - case TOK_KEEPSTATE: + case TOK_KEEPSTATE: { + uint16_t uidx; + 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"); + if (*av != NULL && *av[0] == ':') { + if (state_check_name(*av + 1) != 0) + errx(EX_DATAERR, + "Invalid state name %s", *av); + uidx = pack_object(tstate, *av + 1, + IPFW_TLV_STATE_NAME); + av++; + } else + uidx = pack_object(tstate, default_state_name, + IPFW_TLV_STATE_NAME); have_state = cmd; - fill_cmd(cmd, O_KEEP_STATE, 0, 0); + fill_cmd(cmd, O_KEEP_STATE, 0, uidx); break; + } case TOK_LIMIT: { ipfw_insn_limit *c = (ipfw_insn_limit *)cmd; @@ -4569,8 +4636,18 @@ read_options: GET_UINT_ARG(c->conn_limit, IPFW_ARG_MIN, IPFW_ARG_MAX, TOK_LIMIT, rule_options); - av++; + + if (*av != NULL && *av[0] == ':') { + if (state_check_name(*av + 1) != 0) + errx(EX_DATAERR, + "Invalid state name %s", *av); + cmd->arg1 = pack_object(tstate, *av + 1, + IPFW_TLV_STATE_NAME); + av++; + } else + cmd->arg1 = pack_object(tstate, + default_state_name, IPFW_TLV_STATE_NAME); break; } @@ -4777,7 +4854,7 @@ done: * generate O_PROBE_STATE if necessary */ if (have_state && have_state->opcode != O_CHECK_STATE) { - fill_cmd(dst, O_PROBE_STATE, 0, 0); + fill_cmd(dst, O_PROBE_STATE, 0, have_state->arg1); dst = next_cmd(dst, &rblen); } @@ -5162,6 +5239,7 @@ static struct _s_x intcmds[] = { static struct _s_x otypes[] = { { "EACTION", IPFW_TLV_EACTION }, + { "DYNSTATE", IPFW_TLV_STATE_NAME }, { NULL, 0 } }; |