summaryrefslogtreecommitdiffstats
path: root/sbin/ipfw/ipfw2.c
diff options
context:
space:
mode:
Diffstat (limited to 'sbin/ipfw/ipfw2.c')
-rw-r--r--sbin/ipfw/ipfw2.c144
1 files changed, 130 insertions, 14 deletions
diff --git a/sbin/ipfw/ipfw2.c b/sbin/ipfw/ipfw2.c
index 2c98466..687d707 100644
--- a/sbin/ipfw/ipfw2.c
+++ b/sbin/ipfw/ipfw2.c
@@ -61,6 +61,7 @@ struct format_opts {
int bcwidth;
int pcwidth;
int show_counters;
+ int show_time; /* show timestamp */
uint32_t set_mask; /* enabled sets mask */
uint32_t flags; /* request flags */
uint32_t first; /* first rule to request */
@@ -374,6 +375,13 @@ static int ipfw_show_config(struct cmdline_opts *co, struct format_opts *fo,
ipfw_cfg_lheader *cfg, size_t sz, int ac, char **av);
static void ipfw_list_tifaces(void);
+struct tidx;
+static uint16_t pack_object(struct tidx *tstate, char *name, int otype);
+static uint16_t pack_table(struct tidx *tstate, char *name);
+
+static char *table_search_ctlv(ipfw_obj_ctlv *ctlv, uint16_t idx);
+static void object_sort_ctlv(ipfw_obj_ctlv *ctlv);
+
/*
* Simple string buffer API.
* Used to simplify buffer passing between function and for
@@ -1524,11 +1532,14 @@ show_static_rule(struct cmdline_opts *co, struct format_opts *fo,
case O_FORWARD_IP6:
{
- char buf[4 + INET6_ADDRSTRLEN + 1];
+ char buf[INET6_ADDRSTRLEN + IF_NAMESIZE + 2];
ipfw_insn_sa6 *s = (ipfw_insn_sa6 *)cmd;
- bprintf(bp, "fwd %s", inet_ntop(AF_INET6,
- &s->sa.sin6_addr, buf, sizeof(buf)));
+ bprintf(bp, "fwd ");
+ if (getnameinfo((const struct sockaddr *)&s->sa,
+ sizeof(struct sockaddr_in6), buf, sizeof(buf),
+ NULL, 0, NI_NUMERICHOST) == 0)
+ bprintf(bp, "%s", buf);
if (s->sa.sin6_port)
bprintf(bp, ",%d", s->sa.sin6_port);
}
@@ -2402,7 +2413,7 @@ list_static_range(struct cmdline_opts *co, struct format_opts *fo,
for (n = seen = 0; n < rcnt; n++,
rtlv = (ipfw_obj_tlv *)((caddr_t)rtlv + rtlv->length)) {
- if (fo->show_counters != 0) {
+ if ((fo->show_counters | fo->show_time) != 0) {
cntr = (struct ip_fw_bcounter *)(rtlv + 1);
r = (struct ip_fw_rule *)((caddr_t)cntr + cntr->size);
} else {
@@ -2504,10 +2515,11 @@ ipfw_list(int ac, char *av[], int show_counters)
/* get configuraion from kernel */
cfg = NULL;
sfo.show_counters = show_counters;
+ sfo.show_time = co.do_time;
sfo.flags = IPFW_CFG_GET_STATIC;
if (co.do_dynamic != 0)
sfo.flags |= IPFW_CFG_GET_STATES;
- if (sfo.show_counters != 0)
+ if ((sfo.show_counters | sfo.show_time) != 0)
sfo.flags |= IPFW_CFG_GET_COUNTERS;
if (ipfw_get_config(&co, &sfo, &cfg, &sz) != 0)
err(EX_OSERR, "retrieving config failed");
@@ -2553,6 +2565,7 @@ ipfw_show_config(struct cmdline_opts *co, struct format_opts *fo,
if (cfg->flags & IPFW_CFG_GET_STATIC) {
/* We've requested static rules */
if (ctlv->head.type == IPFW_TLV_TBLNAME_LIST) {
+ object_sort_ctlv(ctlv);
fo->tstate = ctlv;
readsz += ctlv->head.length;
ctlv = (ipfw_obj_ctlv *)((caddr_t)ctlv +
@@ -2719,19 +2732,18 @@ struct tidx {
};
static uint16_t
-pack_table(struct tidx *tstate, char *name)
+pack_object(struct tidx *tstate, char *name, int otype)
{
int i;
ipfw_obj_ntlv *ntlv;
- if (table_check_name(name) != 0)
- return (0);
-
for (i = 0; i < tstate->count; i++) {
if (strcmp(tstate->idx[i].name, name) != 0)
continue;
if (tstate->idx[i].set != tstate->set)
continue;
+ if (tstate->idx[i].head.type != otype)
+ continue;
return (tstate->idx[i].idx);
}
@@ -2747,7 +2759,7 @@ pack_table(struct tidx *tstate, char *name)
ntlv = &tstate->idx[i];
memset(ntlv, 0, sizeof(ipfw_obj_ntlv));
strlcpy(ntlv->name, name, sizeof(ntlv->name));
- ntlv->head.type = IPFW_TLV_TBL_NAME;
+ ntlv->head.type = otype;
ntlv->head.length = sizeof(ipfw_obj_ntlv);
ntlv->set = tstate->set;
ntlv->idx = ++tstate->counter;
@@ -2756,6 +2768,16 @@ pack_table(struct tidx *tstate, char *name)
return (ntlv->idx);
}
+static uint16_t
+pack_table(struct tidx *tstate, char *name)
+{
+
+ if (table_check_name(name) != 0)
+ return (0);
+
+ return (pack_object(tstate, name, IPFW_TLV_TBL_NAME));
+}
+
static void
fill_table(ipfw_insn *cmd, char *av, uint8_t opcode, struct tidx *tstate)
{
@@ -3606,7 +3628,6 @@ compile_rule(char *av[], uint32_t *rbuf, int *rbufsize, struct tidx *tstate)
break;
} else
goto chkarg;
-
case TOK_QUEUE:
action->opcode = O_QUEUE;
goto chkarg;
@@ -3739,8 +3760,8 @@ chkarg:
p->sa.sin6_family = AF_INET6;
p->sa.sin6_port = port_number;
p->sa.sin6_flowinfo = 0;
- p->sa.sin6_scope_id = 0;
- /* No table support for v6 yet. */
+ p->sa.sin6_scope_id =
+ ((struct sockaddr_in6 *)&result)->sin6_scope_id;
bcopy(&((struct sockaddr_in6*)&result)->sin6_addr,
&p->sa.sin6_addr, sizeof(p->sa.sin6_addr));
} else {
@@ -4651,6 +4672,101 @@ done:
*rbufsize = (char *)dst - (char *)rule;
}
+static int
+compare_ntlv(const void *_a, const void *_b)
+{
+ ipfw_obj_ntlv *a, *b;
+
+ a = (ipfw_obj_ntlv *)_a;
+ b = (ipfw_obj_ntlv *)_b;
+
+ if (a->set < b->set)
+ return (-1);
+ else if (a->set > b->set)
+ return (1);
+
+ if (a->idx < b->idx)
+ return (-1);
+ else if (a->idx > b->idx)
+ return (1);
+
+ if (a->head.type < b->head.type)
+ return (-1);
+ else if (a->head.type > b->head.type)
+ return (1);
+
+ return (0);
+}
+
+/*
+ * Provide kernel with sorted list of referenced objects
+ */
+static void
+object_sort_ctlv(ipfw_obj_ctlv *ctlv)
+{
+
+ qsort(ctlv + 1, ctlv->count, ctlv->objsize, compare_ntlv);
+}
+
+struct object_kt {
+ uint16_t uidx;
+ uint16_t type;
+};
+static int
+compare_object_kntlv(const void *k, const void *v)
+{
+ ipfw_obj_ntlv *ntlv;
+ struct object_kt key;
+
+ key = *((struct object_kt *)k);
+ ntlv = (ipfw_obj_ntlv *)v;
+
+ if (key.uidx < ntlv->idx)
+ return (-1);
+ else if (key.uidx > ntlv->idx)
+ return (1);
+
+ if (key.type < ntlv->head.type)
+ return (-1);
+ else if (key.type > ntlv->head.type)
+ return (1);
+
+ return (0);
+}
+
+/*
+ * Finds object name in @ctlv by @idx and @type.
+ * Uses the following facts:
+ * 1) All TLVs are the same size
+ * 2) Kernel implementation provides already sorted list.
+ *
+ * Returns table name or NULL.
+ */
+static char *
+object_search_ctlv(ipfw_obj_ctlv *ctlv, uint16_t idx, uint16_t type)
+{
+ ipfw_obj_ntlv *ntlv;
+ struct object_kt key;
+
+ key.uidx = idx;
+ key.type = type;
+
+ ntlv = bsearch(&key, (ctlv + 1), ctlv->count, ctlv->objsize,
+ compare_object_kntlv);
+
+ if (ntlv != 0)
+ return (ntlv->name);
+
+ return (NULL);
+}
+
+static char *
+table_search_ctlv(ipfw_obj_ctlv *ctlv, uint16_t idx)
+{
+
+ return (object_search_ctlv(ctlv, idx, IPFW_TLV_TBL_NAME));
+}
+
/*
* Adds one or more rules to ipfw chain.
* Data layout:
@@ -4719,7 +4835,7 @@ ipfw_add(char *av[])
ctlv->count = ts.count;
ctlv->objsize = sizeof(ipfw_obj_ntlv);
memcpy(ctlv + 1, ts.idx, tlen);
- table_sort_ctlv(ctlv);
+ object_sort_ctlv(ctlv);
tstate = ctlv;
/* Rule next */
ctlv = (ipfw_obj_ctlv *)((caddr_t)ctlv + ctlv->head.length);
OpenPOWER on IntegriCloud