{ NULL, 0 } /* terminator */
};
+/*
+ * The 'lookup' instruction accepts one of the following arguments.
+ * -1 is a terminator for the list.
+ * Arguments are passed as v[1] in O_DST_LOOKUP options.
+ */
+static int lookup_key[] = {
+ TOK_DSTIP, TOK_SRCIP, TOK_DSTPORT, TOK_SRCPORT,
+ TOK_UID, TOK_JAIL, -1 };
+
static struct _s_x rule_options[] = {
{ "tagged", TOK_TAGGED },
{ "uid", TOK_UID },
{ "dst-ip6", TOK_DSTIP6},
{ "src-ipv6", TOK_SRCIP6},
{ "src-ip6", TOK_SRCIP6},
+ { "lookup", TOK_LOOKUP},
{ "//", TOK_COMMENT },
{ "not", TOK_NOT }, /* pseudo option */
err(EX_UNAVAILABLE, "socket");
if (optname == IP_FW_GET || optname == IP_DUMMYNET_GET ||
+ optname == IP_FW_DYN_GET ||
optname == IP_FW_ADD || optname == IP_FW_TABLE_LIST ||
optname == IP_FW_TABLE_GETSIZE ||
optname == IP_FW_NAT_GET_CONFIG ||
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 = "<invalid>";
+
+ if (d < sizeof(lookup_key)/sizeof(lookup_key[0]))
+ arg = match_value(rule_options, lookup_key[d]);
+ printf("%s lookup %s %d", cmd->o.len & F_NOT ? " not": "",
+ arg, cmd->o.arg1);
+ 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) {
ipfw_list(int ac, char *av[], int show_counters)
{
struct ip_fw *r;
- ipfw_dyn_rule *dynrules, *d;
+ ipfw_dyn_rule *dynrules = NULL;
+ ipfw_dyn_rule *d;
#define NEXT(r) ((struct ip_fw *)((char *)r + RULESIZE(r)))
char *lim;
void *data = NULL;
- int bcwidth, n, nbytes, nstat, ndyn, pcwidth, width;
+ int bcwidth, n, nbytes, pcwidth, width, nstat;
+ int ndyn = 0;
int exitval = EX_OK;
int lac;
char **lav;
char *endptr;
int seen = 0;
uint8_t set;
+ int ocmd = IP_FW_GET;
+
+ if (co.do_pipe)
+ ocmd = IP_DUMMYNET_GET;
+ else if (co.do_dynamic)
+ ocmd = IP_FW_DYN_GET;
- const int ocmd = co.do_pipe ? IP_DUMMYNET_GET : IP_FW_GET;
int nalloc = 1024; /* start somewhere... */
last = 0;
* Count static rules. They have variable size so we
* need to scan the list to count them.
*/
+ nstat = 0;
+ r = data;
+
+ if (!co.do_dynamic) {
for (nstat = 1, r = data, lim = (char *)data + nbytes;
r->rulenum < IPFW_DEFAULT_RULE && (char *)r < lim;
++nstat, r = NEXT(r) )
; /* nothing */
+ }
/*
* Count dynamic rules. This is easier as they have
* fixed size.
*/
- r = NEXT(r);
- dynrules = (ipfw_dyn_rule *)r ;
- n = (char *)r - (char *)data;
- ndyn = (nbytes - n) / sizeof *dynrules;
+ if (co.do_dynamic) {
+ dynrules = (ipfw_dyn_rule *)r ;
+ n = (char *)r - (char *)data;
+ ndyn = (nbytes - n) / sizeof *dynrules;
+ }
/* if showing stats, figure out column widths ahead of time */
bcwidth = pcwidth = 0;
/* display specific rules requested on command line */
+ if (!co.do_dynamic) {
for (lac = ac, lav = av; lac != 0; lac--) {
/* convert command line rule # */
last = rnum = strtoul(*lav++, &endptr, 10);
warnx("rule %lu does not exist", rnum);
}
}
+ }
if (co.do_dynamic && ndyn) {
printf("## Dynamic rules:\n");
/*
* 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 ',')
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);
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++;
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);
}
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");
+ 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] >= 0 ; 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++;
+ cmd->arg1 = strtoul(*av, &p, 0);
+ if (p && *p)
+ errx(EX_USAGE, "format: lookup argument tablenum");
+ ac--; av++;
+ }
+ break;
+
default:
errx(EX_USAGE, "unrecognised option [%d] %s\n", i, s);
}