X-Git-Url: http://git.onelab.eu/?p=ipfw.git;a=blobdiff_plain;f=ipfw%2Fipfw2.c;h=571ff39950b8afccbb624aace757b3dd6fc8f442;hp=e9b3fb39a7db3743f819f6836b9e9ee8e5d32e9a;hb=5ad9fec40da13c449d50def12f9cea6e24b6a708;hpb=f1a44f1ebacf274e0f35970bfc8ee5aa07aa9aca diff --git a/ipfw/ipfw2.c b/ipfw/ipfw2.c index e9b3fb3..571ff39 100644 --- a/ipfw/ipfw2.c +++ b/ipfw/ipfw2.c @@ -224,6 +224,12 @@ static struct _s_x rule_action_params[] = { { NULL, 0 } /* terminator */ }; +/* index of 'lookup ... ' keys in the kernel */ +static int lookup_key[] = { + TOK_DSTIP, TOK_SRCIP, TOK_DSTPORT, TOK_SRCPORT, + TOK_UID, TOK_GID, TOK_JAIL, + TOK_PROTO, TOK_MACTYPE, 0, }; + static struct _s_x rule_options[] = { { "tagged", TOK_TAGGED }, { "uid", TOK_UID }, @@ -290,6 +296,7 @@ static struct _s_x rule_options[] = { { "dst-ip6", TOK_DSTIP6}, { "src-ipv6", TOK_SRCIP6}, { "src-ip6", TOK_SRCIP6}, + { "lookup", TOK_LOOKUP}, { "//", TOK_COMMENT }, { "not", TOK_NOT }, /* pseudo option */ @@ -743,6 +750,16 @@ print_ip(ipfw_insn_ip *cmd, char const *s) int len = F_LEN((ipfw_insn *)cmd); uint32_t *a = ((ipfw_insn_u32 *)cmd)->d; + if (cmd->o.opcode == O_IP_DST_LOOKUP && len > F_INSN_SIZE(ipfw_insn_u32)) { + uint32_t d = a[1]; + const char *arg = ""; + + if (d < sizeof(lookup_key)/sizeof(lookup_key[0])) + arg = match_value(rule_options, lookup_key[d]); + printf("%s lookup %s %d,%d", cmd->o.len & F_NOT ? " not": "", + arg, cmd->o.arg1, a[0]); + return; + } printf("%s%s ", cmd->o.len & F_NOT ? " not": "", s); if (cmd->o.opcode == O_IP_SRC_ME || cmd->o.opcode == O_IP_DST_ME) { @@ -2756,9 +2773,11 @@ chkarg: /* * In the kernel we assume AF_INET and use only - * sin_port and sin_addr. + * sin_port and sin_addr. Remember to set sin_len as + * the routing code seems to use it too. */ p->sa.sin_family = AF_INET; + //p->sa.sin_len = sizeof(struct sockaddr_in); p->sa.sin_port = 0; /* * locate the address-port separator (':' or ',') @@ -2875,7 +2894,7 @@ chkarg: if (have_tag) errx(EX_USAGE, "tag and untag cannot be " "specified more than once"); - GET_UINT_ARG(tag, 1, IPFW_DEFAULT_RULE - 1, i, + GET_UINT_ARG(tag, IPFW_ARG_MIN, IPFW_ARG_MAX, i, rule_action_params); have_tag = cmd; fill_cmd(cmd, O_TAG, (i == TOK_TAG) ? 0: F_NOT, tag); @@ -3352,7 +3371,7 @@ read_options: if (c->limit_mask == 0) errx(EX_USAGE, "limit: missing limit mask"); - GET_UINT_ARG(c->conn_limit, 1, IPFW_DEFAULT_RULE - 1, + GET_UINT_ARG(c->conn_limit, IPFW_ARG_MIN, IPFW_ARG_MAX, TOK_LIMIT, rule_options); ac--; av++; @@ -3480,7 +3499,7 @@ read_options: else { uint16_t tag; - GET_UINT_ARG(tag, 1, IPFW_DEFAULT_RULE - 1, + GET_UINT_ARG(tag, IPFW_ARG_MIN, IPFW_ARG_MAX, TOK_TAGGED, rule_options); fill_cmd(cmd, O_TAGGED, 0, tag); } @@ -3493,6 +3512,36 @@ read_options: ac--; av++; break; + case TOK_LOOKUP: { + ipfw_insn_u32 *c = (ipfw_insn_u32 *)cmd; + char *p; + int j; + + if (ac < 2) + errx(EX_USAGE, "format: lookup argument tablenum[,arg]"); + cmd->opcode = O_IP_DST_LOOKUP; + cmd->len |= F_INSN_SIZE(ipfw_insn) + 2; + i = match_token(rule_options, *av); + for (j = 0; lookup_key[j] ; j++) { + if (i == lookup_key[j]) + break; + } + if (lookup_key[j] == 0) + errx(EX_USAGE, "format: cannot lookup on %s", *av); + c->d[1] = j; // i converted to option + ac--; av++; + p = strchr(*av, ','); + if (p) { + *p++ = '\0'; + c->d[0] = strtoul(p, NULL, 0); + } else { + c->d[0] = ~0; + } + cmd->arg1 = strtoul(*av, NULL, 0); + ac--; av++; + } + break; + default: errx(EX_USAGE, "unrecognised option [%d] %s\n", i, s); }