svn commit: r268009 - in projects/ipfw: sbin/ipfw sys/netinet sys/netpfil/ipfw
Alexander V. Chernikov
melifaro at FreeBSD.org
Sat Jun 28 23:20:25 UTC 2014
Author: melifaro
Date: Sat Jun 28 23:20:24 2014
New Revision: 268009
URL: http://svnweb.freebsd.org/changeset/base/268009
Log:
Suppord showing named tables in ipfw(8) rule listing.
Kernel changes:
* change base TLV header to be u64 (so size can be u32).
* Introduce ipfw_obj_ctlv generc container TLV.
* Add IP_FW_XGET opcode which is now used for atomic configuration
retrieval. One can specify needed configuration pieces to retrieve
via flags field. Currently supported are
IPFW_CFG_GET_STATIC (static rules) and
IPFW_CFG_GET_STATES (dynamic states).
Other configuration pieces (tables, pipes, etc..) support is planned.
Userland changes:
* Switch ipfw(8) to use new IP_FW_XGET for rule listing.
* Split rule listing code get and show pieces.
* Make several steps forward towards libipfw:
permit printing states and rules(paritally) to supplied buffer.
do not die on malloc/kernel failure inside given printing functions.
stop assuming cmdline_opts is global symbol.
Modified:
projects/ipfw/sbin/ipfw/altq.c
projects/ipfw/sbin/ipfw/dummynet.c
projects/ipfw/sbin/ipfw/ipfw2.c
projects/ipfw/sbin/ipfw/ipfw2.h
projects/ipfw/sbin/ipfw/tables.c
projects/ipfw/sys/netinet/ip_fw.h
projects/ipfw/sys/netpfil/ipfw/ip_fw_dynamic.c
projects/ipfw/sys/netpfil/ipfw/ip_fw_private.h
projects/ipfw/sys/netpfil/ipfw/ip_fw_sockopt.c
projects/ipfw/sys/netpfil/ipfw/ip_fw_table.c
projects/ipfw/sys/netpfil/ipfw/ip_fw_table.h
Modified: projects/ipfw/sbin/ipfw/altq.c
==============================================================================
--- projects/ipfw/sbin/ipfw/altq.c Sat Jun 28 21:47:15 2014 (r268008)
+++ projects/ipfw/sbin/ipfw/altq.c Sat Jun 28 23:20:24 2014 (r268009)
@@ -137,15 +137,15 @@ altq_qid_to_name(u_int32_t qid)
}
void
-print_altq_cmd(ipfw_insn_altq *altqptr)
+print_altq_cmd(struct buf_pr *bp, ipfw_insn_altq *altqptr)
{
if (altqptr) {
const char *qname;
qname = altq_qid_to_name(altqptr->qid);
if (qname == NULL)
- printf(" altq ?<%u>", altqptr->qid);
+ bprintf(bp, " altq ?<%u>", altqptr->qid);
else
- printf(" altq %s", qname);
+ bprintf(bp, " altq %s", qname);
}
}
Modified: projects/ipfw/sbin/ipfw/dummynet.c
==============================================================================
--- projects/ipfw/sbin/ipfw/dummynet.c Sat Jun 28 21:47:15 2014 (r268008)
+++ projects/ipfw/sbin/ipfw/dummynet.c Sat Jun 28 23:20:24 2014 (r268009)
@@ -174,48 +174,44 @@ print_header(struct ipfw_flow_id *id)
}
static void
-list_flow(struct dn_flow *ni, int *print)
+list_flow(struct buf_pr *bp, struct dn_flow *ni)
{
char buff[255];
struct protoent *pe = NULL;
struct in_addr ina;
struct ipfw_flow_id *id = &ni->fid;
- if (*print) {
- print_header(&ni->fid);
- *print = 0;
- }
pe = getprotobynumber(id->proto);
/* XXX: Should check for IPv4 flows */
- printf("%3u%c", (ni->oid.id) & 0xff,
+ bprintf(bp, "%3u%c", (ni->oid.id) & 0xff,
id->extra ? '*' : ' ');
if (!IS_IP6_FLOW_ID(id)) {
if (pe)
- printf("%-4s ", pe->p_name);
+ bprintf(bp, "%-4s ", pe->p_name);
else
- printf("%4u ", id->proto);
+ bprintf(bp, "%4u ", id->proto);
ina.s_addr = htonl(id->src_ip);
- printf("%15s/%-5d ",
+ bprintf(bp, "%15s/%-5d ",
inet_ntoa(ina), id->src_port);
ina.s_addr = htonl(id->dst_ip);
- printf("%15s/%-5d ",
+ bprintf(bp, "%15s/%-5d ",
inet_ntoa(ina), id->dst_port);
} else {
/* Print IPv6 flows */
if (pe != NULL)
- printf("%9s ", pe->p_name);
+ bprintf(bp, "%9s ", pe->p_name);
else
- printf("%9u ", id->proto);
- printf("%7d %39s/%-5d ", id->flow_id6,
+ bprintf(bp, "%9u ", id->proto);
+ bprintf(bp, "%7d %39s/%-5d ", id->flow_id6,
inet_ntop(AF_INET6, &(id->src_ip6), buff, sizeof(buff)),
id->src_port);
- printf(" %39s/%-5d ",
+ bprintf(bp, " %39s/%-5d ",
inet_ntop(AF_INET6, &(id->dst_ip6), buff, sizeof(buff)),
id->dst_port);
}
- pr_u64(&ni->tot_pkts, 4);
- pr_u64(&ni->tot_bytes, 8);
- printf("%2u %4u %3u\n",
+ pr_u64(bp, &ni->tot_pkts, 4);
+ pr_u64(bp, &ni->tot_bytes, 8);
+ bprintf(bp, "%2u %4u %3u",
ni->length, ni->len_bytes, ni->drops);
}
@@ -303,8 +299,10 @@ list_pipes(struct dn_id *oid, struct dn_
{
char buf[160]; /* pending buffer */
int toPrint = 1; /* print header */
+ struct buf_pr bp;
buf[0] = '\0';
+ bp_alloc(&bp, 4096);
for (; oid != end; oid = O_NEXT(oid, oid->len)) {
if (oid->len < sizeof(*oid))
errx(1, "invalid oid len %d\n", oid->len);
@@ -346,7 +344,12 @@ list_pipes(struct dn_id *oid, struct dn_
break;
case DN_FLOW:
- list_flow((struct dn_flow *)oid, &toPrint);
+ if (toPrint != 0) {
+ print_header(&((struct dn_flow *)oid)->fid);
+ toPrint = 0;
+ }
+ list_flow(&bp, (struct dn_flow *)oid);
+ printf("%s\n", bp.buf);
break;
case DN_LINK: {
@@ -384,6 +387,8 @@ list_pipes(struct dn_id *oid, struct dn_
}
flush_buf(buf); // XXX does it really go here ?
}
+
+ bp_free(&bp);
}
/*
Modified: projects/ipfw/sbin/ipfw/ipfw2.c
==============================================================================
--- projects/ipfw/sbin/ipfw/ipfw2.c Sat Jun 28 21:47:15 2014 (r268008)
+++ projects/ipfw/sbin/ipfw/ipfw2.c Sat Jun 28 23:20:24 2014 (r268009)
@@ -35,6 +35,7 @@
#include <netdb.h>
#include <pwd.h>
#include <stdio.h>
+#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <sysexits.h>
@@ -56,6 +57,15 @@
struct cmdline_opts co; /* global options */
+struct format_opts {
+ int bcwidth;
+ int pcwidth;
+ int show_counters;
+ int first;
+ int last;
+ ipfw_obj_ctlv *tstate;
+};
+
int resvd_set_number = RESVD_SET;
int ipfw_socket = -1;
@@ -364,6 +374,102 @@ static struct _s_x rule_options[] = {
{ NULL, 0 } /* terminator */
};
+void bprint_uint_arg(struct buf_pr *bp, const char *str, uint32_t arg);
+static int ipfw_get_config(struct cmdline_opts *co, uint32_t flags,
+ ipfw_cfg_lheader **pcfg, size_t *psize);
+static int ipfw_show_config(struct cmdline_opts *co, struct format_opts *fo,
+ ipfw_cfg_lheader *cfg, size_t sz, int ac, char **av);
+
+/*
+ * Simple string buffer API.
+ * Used to simplify buffer passing between function and for
+ * transparent overrun handling.
+ */
+
+/*
+ * Allocates new buffer of given size @sz.
+ *
+ * Returns 0 on success.
+ */
+int
+bp_alloc(struct buf_pr *b, size_t size)
+{
+ memset(b, 0, sizeof(struct buf_pr));
+
+ if ((b->buf = calloc(1, size)) == NULL)
+ return (ENOMEM);
+
+ b->ptr = b->buf;
+ b->size = size;
+ b->avail = b->size;
+
+ return (0);
+}
+
+void
+bp_free(struct buf_pr *b)
+{
+
+ free(b->buf);
+}
+
+/*
+ * Flushes buffer so new writer start from beginning.
+ */
+void
+bp_flush(struct buf_pr *b)
+{
+
+ b->ptr = b->buf;
+ b->avail = b->size;
+}
+
+/*
+ * Print message specified by @format and args.
+ * Automatically manage buffer space and transparently handle
+ * buffer overruns.
+ *
+ * Returns number of bytes that should have been printed.
+ */
+int
+bprintf(struct buf_pr *b, char *format, ...)
+{
+ va_list args;
+ int i;
+
+ va_start(args, format);
+
+ i = vsnprintf(b->ptr, b->avail, format, args);
+ va_end(args);
+
+ if (i > b->avail || i < 0) {
+ /* Overflow or print error */
+ b->avail = 0;
+ } else {
+ b->ptr += i;
+ b->avail -= i;
+ }
+
+ b->needed += i;
+
+ return (i);
+}
+
+/*
+ * Special values printer for tablearg-aware opcodes.
+ */
+void
+bprint_uint_arg(struct buf_pr *bp, const char *str, uint32_t arg)
+{
+
+ if (str != NULL)
+ bprintf(bp, "%s", str);
+ if (arg == IP_FW_TABLEARG)
+ bprintf(bp, "tablearg");
+ else
+ bprintf(bp, "%u", arg);
+}
+
/*
* Helper routine to print a possibly unaligned uint64_t on
* various platform. If width > 0, print the value with
@@ -371,7 +477,7 @@ static struct _s_x rule_options[] = {
* otherwise, return the required width.
*/
int
-pr_u64(uint64_t *pd, int width)
+pr_u64(struct buf_pr *b, uint64_t *pd, int width)
{
#ifdef TCC
#define U64_FMT "I64"
@@ -384,11 +490,12 @@ pr_u64(uint64_t *pd, int width)
bcopy (pd, &u, sizeof(u));
d = u;
return (width > 0) ?
- printf("%*" U64_FMT " ", width, d) :
+ bprintf(b, "%*" U64_FMT " ", width, d) :
snprintf(NULL, 0, "%" U64_FMT, d) ;
#undef U64_FMT
}
+
void *
safe_calloc(size_t number, size_t size)
{
@@ -866,14 +973,14 @@ fill_reject_code(u_short *codep, char *s
}
static void
-print_reject_code(uint16_t code)
+print_reject_code(struct buf_pr *bp, uint16_t code)
{
- char const *s = match_value(icmpcodes, code);
+ char const *s;
- if (s != NULL)
- printf("unreach %s", s);
+ if ((s = match_value(icmpcodes, code)) != NULL)
+ bprintf(bp, "unreach %s", s);
else
- printf("unreach %u", code);
+ bprintf(bp, "unreach %u", code);
}
/*
@@ -937,7 +1044,7 @@ print_flags(char const *name, ipfw_insn
* Print the ip address contained in a command.
*/
static void
-print_ip(ipfw_insn_ip *cmd, char const *s)
+print_ip(struct format_opts *fo, ipfw_insn_ip *cmd, char const *s)
{
struct hostent *he = NULL;
uint32_t len = F_LEN((ipfw_insn *)cmd);
@@ -961,7 +1068,9 @@ print_ip(ipfw_insn_ip *cmd, char const *
}
if (cmd->o.opcode == O_IP_SRC_LOOKUP ||
cmd->o.opcode == O_IP_DST_LOOKUP) {
- printf("table(%u", ((ipfw_insn *)cmd)->arg1);
+ char *t;
+ t = table_search_ctlv(fo->tstate, ((ipfw_insn *)cmd)->arg1);
+ printf("table(%s", t);
if (len == F_INSN_SIZE(ipfw_insn_u32))
printf(",%u", *a);
printf(")");
@@ -1162,7 +1271,8 @@ show_prerequisites(int *flags, int want,
}
static void
-show_ipfw(struct ip_fw *rule, int pcwidth, int bcwidth)
+show_static_rule(struct cmdline_opts *co, struct format_opts *fo,
+ struct buf_pr *bp, struct ip_fw *rule)
{
static int twidth = 0;
int l;
@@ -1178,21 +1288,21 @@ show_ipfw(struct ip_fw *rule, int pcwidt
bcopy(&rule->next_rule, &set_disable, sizeof(set_disable));
if (set_disable & (1 << rule->set)) { /* disabled */
- if (!co.show_sets)
+ if (!co->show_sets)
return;
else
- printf("# DISABLED ");
+ bprintf(bp, "# DISABLED ");
}
- printf("%05u ", rule->rulenum);
+ bprintf(bp, "%05u ", rule->rulenum);
- if (pcwidth > 0 || bcwidth > 0) {
- pr_u64(&rule->pcnt, pcwidth);
- pr_u64(&rule->bcnt, bcwidth);
+ if (fo->pcwidth > 0 || fo->bcwidth > 0) {
+ pr_u64(bp, &rule->pcnt, fo->pcwidth);
+ pr_u64(bp, &rule->bcnt, fo->bcwidth);
}
- if (co.do_time == 2)
- printf("%10u ", rule->timestamp);
- else if (co.do_time == 1) {
+ if (co->do_time == 2)
+ bprintf(bp, "%10u ", rule->timestamp);
+ else if (co->do_time == 1) {
char timestr[30];
time_t t = (time_t)0;
@@ -1206,14 +1316,14 @@ show_ipfw(struct ip_fw *rule, int pcwidt
strcpy(timestr, ctime(&t));
*strchr(timestr, '\n') = '\0';
- printf("%s ", timestr);
+ bprintf(bp, "%s ", timestr);
} else {
- printf("%*s", twidth, " ");
+ bprintf(bp, "%*s", twidth, " ");
}
}
- if (co.show_sets)
- printf("set %d ", rule->set);
+ if (co->show_sets)
+ bprintf(bp, "set %d ", rule->set);
/*
* print the optional "match probability"
@@ -1225,7 +1335,7 @@ show_ipfw(struct ip_fw *rule, int pcwidt
double d = 1.0 * p->d[0];
d = (d / 0x7fffffff);
- printf("prob %f ", d);
+ bprintf(bp, "prob %f ", d);
}
}
@@ -1236,66 +1346,66 @@ show_ipfw(struct ip_fw *rule, int pcwidt
l > 0 ; l -= F_LEN(cmd), cmd += F_LEN(cmd)) {
switch(cmd->opcode) {
case O_CHECK_STATE:
- printf("check-state");
+ bprintf(bp, "check-state");
/* avoid printing anything else */
flags = HAVE_PROTO | HAVE_SRCIP |
HAVE_DSTIP | HAVE_IP;
break;
case O_ACCEPT:
- printf("allow");
+ bprintf(bp, "allow");
break;
case O_COUNT:
- printf("count");
+ bprintf(bp, "count");
break;
case O_DENY:
- printf("deny");
+ bprintf(bp, "deny");
break;
case O_REJECT:
if (cmd->arg1 == ICMP_REJECT_RST)
- printf("reset");
+ bprintf(bp, "reset");
else if (cmd->arg1 == ICMP_UNREACH_HOST)
- printf("reject");
+ bprintf(bp, "reject");
else
- print_reject_code(cmd->arg1);
+ print_reject_code(bp, cmd->arg1);
break;
case O_UNREACH6:
if (cmd->arg1 == ICMP6_UNREACH_RST)
- printf("reset6");
+ bprintf(bp, "reset6");
else
print_unreach6_code(cmd->arg1);
break;
case O_SKIPTO:
- PRINT_UINT_ARG("skipto ", cmd->arg1);
+ bprint_uint_arg(bp, "skipto ", cmd->arg1);
break;
case O_PIPE:
- PRINT_UINT_ARG("pipe ", cmd->arg1);
+ bprint_uint_arg(bp, "pipe ", cmd->arg1);
break;
case O_QUEUE:
- PRINT_UINT_ARG("queue ", cmd->arg1);
+ bprint_uint_arg(bp, "queue ", cmd->arg1);
break;
case O_DIVERT:
- PRINT_UINT_ARG("divert ", cmd->arg1);
+ bprint_uint_arg(bp, "divert ", cmd->arg1);
break;
case O_TEE:
- PRINT_UINT_ARG("tee ", cmd->arg1);
+ bprint_uint_arg(bp, "tee ", cmd->arg1);
break;
case O_NETGRAPH:
- PRINT_UINT_ARG("netgraph ", cmd->arg1);
+ bprint_uint_arg(bp, "netgraph ", cmd->arg1);
break;
case O_NGTEE:
- PRINT_UINT_ARG("ngtee ", cmd->arg1);
+ bprint_uint_arg(bp, "ngtee ", cmd->arg1);
break;
case O_FORWARD_IP:
@@ -1303,12 +1413,12 @@ show_ipfw(struct ip_fw *rule, int pcwidt
ipfw_insn_sa *s = (ipfw_insn_sa *)cmd;
if (s->sa.sin_addr.s_addr == INADDR_ANY) {
- printf("fwd tablearg");
+ bprintf(bp, "fwd tablearg");
} else {
- printf("fwd %s", inet_ntoa(s->sa.sin_addr));
+ bprintf(bp, "fwd %s",inet_ntoa(s->sa.sin_addr));
}
if (s->sa.sin_port)
- printf(",%d", s->sa.sin_port);
+ bprintf(bp, ",%d", s->sa.sin_port);
}
break;
@@ -1317,10 +1427,10 @@ show_ipfw(struct ip_fw *rule, int pcwidt
char buf[4 + INET6_ADDRSTRLEN + 1];
ipfw_insn_sa6 *s = (ipfw_insn_sa6 *)cmd;
- printf("fwd %s", inet_ntop(AF_INET6, &s->sa.sin6_addr,
- buf, sizeof(buf)));
+ bprintf(bp, "fwd %s", inet_ntop(AF_INET6,
+ &s->sa.sin6_addr, buf, sizeof(buf)));
if (s->sa.sin6_port)
- printf(",%d", s->sa.sin6_port);
+ bprintf(bp, ",%d", s->sa.sin6_port);
}
break;
@@ -1338,13 +1448,13 @@ show_ipfw(struct ip_fw *rule, int pcwidt
case O_NAT:
if (cmd->arg1 != 0)
- PRINT_UINT_ARG("nat ", cmd->arg1);
+ bprint_uint_arg(bp, "nat ", cmd->arg1);
else
- printf("nat global");
+ bprintf(bp, "nat global");
break;
case O_SETFIB:
- PRINT_UINT_ARG("setfib ", cmd->arg1);
+ bprint_uint_arg(bp, "setfib ", cmd->arg1);
break;
case O_SETDSCP:
@@ -1352,47 +1462,53 @@ show_ipfw(struct ip_fw *rule, int pcwidt
const char *code;
if ((code = match_value(f_ipdscp, cmd->arg1)) != NULL)
- printf("setdscp %s", code);
+ bprintf(bp, "setdscp %s", code);
else
- PRINT_UINT_ARG("setdscp ", cmd->arg1);
+ bprint_uint_arg(bp, "setdscp ", cmd->arg1);
}
break;
case O_REASS:
- printf("reass");
+ bprintf(bp, "reass");
break;
case O_CALLRETURN:
if (cmd->len & F_NOT)
- printf("return");
+ bprintf(bp, "return");
else
- PRINT_UINT_ARG("call ", cmd->arg1);
+ bprint_uint_arg(bp, "call ", cmd->arg1);
break;
default:
- printf("** unrecognized action %d len %d ",
+ bprintf(bp, "** unrecognized action %d len %d ",
cmd->opcode, cmd->len);
}
}
if (logptr) {
if (logptr->max_log > 0)
- printf(" log logamount %d", logptr->max_log);
+ bprintf(bp, " log logamount %d", logptr->max_log);
else
- printf(" log");
+ bprintf(bp, " log");
}
#ifndef NO_ALTQ
if (altqptr) {
- print_altq_cmd(altqptr);
+ print_altq_cmd(bp, altqptr);
}
#endif
if (tagptr) {
if (tagptr->len & F_NOT)
- PRINT_UINT_ARG(" untag ", tagptr->arg1);
+ bprint_uint_arg(bp, " untag ", tagptr->arg1);
else
- PRINT_UINT_ARG(" tag ", tagptr->arg1);
+ bprint_uint_arg(bp, " tag ", tagptr->arg1);
}
/*
+ * TODO: convert remainings to use @bp buffer
+ *
+ */
+ printf("%s", bp->buf);
+
+ /*
* then print the body.
*/
for (l = rule->act_ofs, cmd = rule->cmd ;
@@ -1408,7 +1524,7 @@ show_ipfw(struct ip_fw *rule, int pcwidt
}
}
if (rule->_pad & 1) { /* empty rules before options */
- if (!co.do_compact) {
+ if (!co->do_compact) {
show_prerequisites(&flags, HAVE_PROTO, 0);
printf(" from any to any");
}
@@ -1416,7 +1532,7 @@ show_ipfw(struct ip_fw *rule, int pcwidt
HAVE_SRCIP | HAVE_DSTIP;
}
- if (co.comment_only)
+ if (co->comment_only)
comment = "...";
for (l = rule->act_ofs, cmd = rule->cmd ;
@@ -1424,7 +1540,7 @@ show_ipfw(struct ip_fw *rule, int pcwidt
/* useful alias */
ipfw_insn_u32 *cmd32 = (ipfw_insn_u32 *)cmd;
- if (co.comment_only) {
+ if (co->comment_only) {
if (cmd->opcode != O_NOP)
continue;
printf(" // %s\n", (char *)(cmd + 1));
@@ -1450,7 +1566,7 @@ show_ipfw(struct ip_fw *rule, int pcwidt
printf(" from");
if ((cmd->len & F_OR) && !or_block)
printf(" {");
- print_ip((ipfw_insn_ip *)cmd,
+ print_ip(fo, (ipfw_insn_ip *)cmd,
(flags & HAVE_OPTIONS) ? " src-ip" : "");
flags |= HAVE_SRCIP;
break;
@@ -1465,7 +1581,7 @@ show_ipfw(struct ip_fw *rule, int pcwidt
printf(" to");
if ((cmd->len & F_OR) && !or_block)
printf(" {");
- print_ip((ipfw_insn_ip *)cmd,
+ print_ip(fo, (ipfw_insn_ip *)cmd,
(flags & HAVE_OPTIONS) ? " dst-ip" : "");
flags |= HAVE_DSTIP;
break;
@@ -1610,7 +1726,7 @@ show_ipfw(struct ip_fw *rule, int pcwidt
case O_RECV:
case O_VIA:
{
- char const *s;
+ char const *s, *t;
ipfw_insn_if *cmdif = (ipfw_insn_if *)cmd;
if (cmd->opcode == O_XMIT)
@@ -1622,9 +1738,12 @@ show_ipfw(struct ip_fw *rule, int pcwidt
if (cmdif->name[0] == '\0')
printf(" %s %s", s,
inet_ntoa(cmdif->p.ip));
- else if (cmdif->name[0] == '\1') /* interface table */
- printf(" %s table(%d)", s, cmdif->p.glob);
- else
+ else if (cmdif->name[0] == '\1') {
+ /* interface table */
+ t = table_search_ctlv(fo->tstate,
+ cmdif->p.glob);
+ printf(" %s table(%s)", s, t);
+ } else
printf(" %s %s", s, cmdif->name);
break;
@@ -1825,57 +1944,56 @@ show_ipfw(struct ip_fw *rule, int pcwidt
}
static void
-show_dyn_ipfw(ipfw_dyn_rule *d, int pcwidth, int bcwidth)
+show_dyn_state(struct cmdline_opts *co, struct format_opts *fo,
+ struct buf_pr *bp, ipfw_dyn_rule *d)
{
struct protoent *pe;
struct in_addr a;
uint16_t rulenum;
char buf[INET6_ADDRSTRLEN];
- if (!co.do_expired) {
+ if (!co->do_expired) {
if (!d->expire && !(d->dyn_type == O_LIMIT_PARENT))
return;
}
bcopy(&d->rule, &rulenum, sizeof(rulenum));
- printf("%05d", rulenum);
- if (pcwidth > 0 || bcwidth > 0) {
- printf(" ");
- pr_u64(&d->pcnt, pcwidth);
- pr_u64(&d->bcnt, bcwidth);
- printf("(%ds)", d->expire);
+ bprintf(bp, "%05d", rulenum);
+ if (fo->pcwidth > 0 || fo->bcwidth > 0) {
+ bprintf(bp, " ");
+ pr_u64(bp, &d->pcnt, fo->pcwidth);
+ pr_u64(bp, &d->bcnt, fo->bcwidth);
+ bprintf(bp, "(%ds)", d->expire);
}
switch (d->dyn_type) {
case O_LIMIT_PARENT:
- printf(" PARENT %d", d->count);
+ bprintf(bp, " PARENT %d", d->count);
break;
case O_LIMIT:
- printf(" LIMIT");
+ bprintf(bp, " LIMIT");
break;
case O_KEEP_STATE: /* bidir, no mask */
- printf(" STATE");
+ bprintf(bp, " STATE");
break;
}
if ((pe = getprotobynumber(d->id.proto)) != NULL)
- printf(" %s", pe->p_name);
+ bprintf(bp, " %s", pe->p_name);
else
- printf(" proto %u", d->id.proto);
+ bprintf(bp, " proto %u", d->id.proto);
if (d->id.addr_type == 4) {
a.s_addr = htonl(d->id.src_ip);
- printf(" %s %d", inet_ntoa(a), d->id.src_port);
+ bprintf(bp, " %s %d", inet_ntoa(a), d->id.src_port);
a.s_addr = htonl(d->id.dst_ip);
- printf(" <-> %s %d", inet_ntoa(a), d->id.dst_port);
+ bprintf(bp, " <-> %s %d", inet_ntoa(a), d->id.dst_port);
} else if (d->id.addr_type == 6) {
- printf(" %s %d", inet_ntop(AF_INET6, &d->id.src_ip6, buf,
+ bprintf(bp, " %s %d", inet_ntop(AF_INET6, &d->id.src_ip6, buf,
sizeof(buf)), d->id.src_port);
- printf(" <-> %s %d", inet_ntop(AF_INET6, &d->id.dst_ip6, buf,
- sizeof(buf)), d->id.dst_port);
+ bprintf(bp, " <-> %s %d", inet_ntop(AF_INET6, &d->id.dst_ip6,
+ buf, sizeof(buf)), d->id.dst_port);
} else
- printf(" UNKNOWN <-> UNKNOWN\n");
-
- printf("\n");
+ bprintf(bp, " UNKNOWN <-> UNKNOWN\n");
}
/*
@@ -2026,28 +2144,112 @@ ipfw_sysctl_handler(char *av[], int whic
}
}
-void
-ipfw_list(int ac, char *av[], int show_counters)
+static void
+prepare_format_opts(struct cmdline_opts *co, struct format_opts *fo,
+ struct ip_fw *r, ipfw_dyn_rule *d, int rcnt, int dcnt)
{
- struct ip_fw *r;
- ipfw_dyn_rule *dynrules, *d;
-
+ int bcwidth, pcwidth, width;
+ int n;
+ uint32_t set;
#define NEXT(r) ((struct ip_fw *)((char *)r + RULESIZE(r)))
- char *lim;
- void *data = NULL;
- int bcwidth, n, nbytes, nstat, ndyn, pcwidth, width;
- int exitval = EX_OK;
- int lac;
- char **lav;
- u_long rnum, last;
- char *endptr;
- int seen = 0;
+
+ bcwidth = 0;
+ pcwidth = 0;
+ if (fo->show_counters != 0) {
+ for (n = 0; n < rcnt; n++, r = NEXT(r)) {
+ /* skip rules from another set */
+ if (co->use_set && r->set != co->use_set - 1)
+ continue;
+
+ /* packet counter */
+ width = pr_u64(NULL, &r->pcnt, 0);
+ if (width > pcwidth)
+ pcwidth = width;
+
+ /* byte counter */
+ width = pr_u64(NULL, &r->bcnt, 0);
+ if (width > bcwidth)
+ bcwidth = width;
+ }
+ }
+ if (co->do_dynamic && dcnt > 0) {
+ for (n = 0; n < dcnt; n++, d++) {
+ if (co->use_set) {
+ /* skip rules from another set */
+ bcopy((char *)&d->rule + sizeof(uint16_t),
+ &set, sizeof(uint8_t));
+ if (set != co->use_set - 1)
+ continue;
+ }
+ width = pr_u64(NULL, &d->pcnt, 0);
+ if (width > pcwidth)
+ pcwidth = width;
+
+ width = pr_u64(NULL, &d->bcnt, 0);
+ if (width > bcwidth)
+ bcwidth = width;
+ }
+ }
+
+ fo->bcwidth = bcwidth;
+ fo->pcwidth = pcwidth;
+}
+
+static int
+ipfw_list_static_range(struct cmdline_opts *co, struct format_opts *fo,
+ struct buf_pr *bp, struct ip_fw *r, int nstat)
+{
+ int n, seen;
+
+ for (n = seen = 0; n < nstat; n++, r = NEXT(r) ) {
+ if (r->rulenum > fo->last)
+ break;
+ if (co->use_set && r->set != co->use_set - 1)
+ continue;
+ if (r->rulenum >= fo->first && r->rulenum <= fo->last) {
+ show_static_rule(co, fo, bp, r);
+ bp_flush(bp);
+ seen++;
+ }
+ }
+
+ return (seen);
+}
+
+static void
+ipfw_list_dyn_range(struct cmdline_opts *co, struct format_opts *fo,
+ struct buf_pr *bp, ipfw_dyn_rule *d, int ndyn)
+{
+ int n;
uint8_t set;
+ uint16_t rulenum;
- const int ocmd = co.do_pipe ? IP_DUMMYNET_GET : IP_FW_GET;
- int nalloc = 1024; /* start somewhere... */
+ for (n = 0; n < ndyn; n++, d++) {
+ bcopy(&d->rule, &rulenum, sizeof(rulenum));
+ if (rulenum > fo->last)
+ break;
+ if (co->use_set) {
+ bcopy((char *)&d->rule + sizeof(uint16_t),
+ &set, sizeof(uint8_t));
+ if (set != co->use_set - 1)
+ continue;
+ }
+ if (rulenum >= fo->first) {
+ show_dyn_state(co, fo, bp, d);
+ printf("%s\n", bp->buf);
+ bp_flush(bp);
+ }
+ }
+}
- last = 0;
+void
+ipfw_list(int ac, char *av[], int show_counters)
+{
+ ipfw_cfg_lheader *cfg;
+ struct format_opts sfo;
+ size_t sz;
+ int error;
+ uint32_t flags;
if (co.test_only) {
fprintf(stderr, "Testing only, list disabled\n");
@@ -2061,119 +2263,108 @@ ipfw_list(int ac, char *av[], int show_c
ac--;
av++;
- /* get rules or pipes from kernel, resizing array as necessary */
- nbytes = nalloc;
+ /* get configuraion from kernel */
+ cfg = NULL;
+ flags = IPFW_CFG_GET_STATIC;
+ if (co.do_dynamic != 0)
+ flags |= IPFW_CFG_GET_STATES;
+ if ((error = ipfw_get_config(&co, flags, &cfg, &sz)) != 0)
+ err(EX_OSERR, "retrieving config failed");
+
+ memset(&sfo, 0, sizeof(sfo));
+ sfo.show_counters = show_counters;
+ error = ipfw_show_config(&co, &sfo, cfg, sz, ac, av);
- while (nbytes >= nalloc) {
- nalloc = nalloc * 2 + 200;
- nbytes = nalloc;
- data = safe_realloc(data, nbytes);
- if (do_cmd(ocmd, data, (uintptr_t)&nbytes) < 0)
- err(EX_OSERR, "getsockopt(IP_%s_GET)",
- co.do_pipe ? "DUMMYNET" : "FW");
- }
+ free(cfg);
- /*
- * Count static rules. They have variable size so we
- * need to scan the list to count them.
- */
- for (nstat = 1, r = data, lim = (char *)data + nbytes;
- r->rulenum < IPFW_DEFAULT_RULE && (char *)r < lim;
- ++nstat, r = NEXT(r) )
- ; /* nothing */
+ if (error != EX_OK)
+ exit(error);
+#undef NEXT
+}
+
+static int
+ipfw_show_config(struct cmdline_opts *co, struct format_opts *fo,
+ ipfw_cfg_lheader *cfg, size_t sz, int ac, char *av[])
+{
+ struct ip_fw *rbase;
+ ipfw_dyn_rule *dynbase;
+ int rcnt, dcnt;
+ int exitval = EX_OK;
+ int lac;
+ char **lav;
+ u_long rnum;
+ char *endptr;
+ size_t read;
+ struct buf_pr bp;
+ ipfw_obj_ctlv *ctlv, *tstate;
/*
- * Count dynamic rules. This is easier as they have
- * fixed size.
+ * Handle tablenames TLV first, if any
*/
- r = NEXT(r);
- 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;
- if (show_counters) {
- for (n = 0, r = data; n < nstat; n++, r = NEXT(r)) {
- /* skip rules from another set */
- if (co.use_set && r->set != co.use_set - 1)
- continue;
+ tstate = NULL;
+ rbase = NULL;
+ dynbase = NULL;
+ read = 0;
- /* packet counter */
- width = pr_u64(&r->pcnt, 0);
- if (width > pcwidth)
- pcwidth = width;
+ ctlv = (ipfw_obj_ctlv *)(cfg + 1);
- /* byte counter */
- width = pr_u64(&r->bcnt, 0);
- if (width > bcwidth)
- bcwidth = width;
+ if (cfg->flags & IPFW_CFG_GET_STATIC) {
+ /* We've requested static rules */
+ if (ctlv->head.type == IPFW_TLV_TBLNAME_LIST) {
+ fo->tstate = ctlv;
+ read += ctlv->head.length;
+ ctlv = (ipfw_obj_ctlv *)((caddr_t)ctlv +
+ ctlv->head.length);
}
- }
- if (co.do_dynamic && ndyn) {
- for (n = 0, d = dynrules; n < ndyn; n++, d++) {
- if (co.use_set) {
- /* skip rules from another set */
- bcopy((char *)&d->rule + sizeof(uint16_t),
- &set, sizeof(uint8_t));
- if (set != co.use_set - 1)
- continue;
- }
- width = pr_u64(&d->pcnt, 0);
- if (width > pcwidth)
- pcwidth = width;
- width = pr_u64(&d->bcnt, 0);
- if (width > bcwidth)
- bcwidth = width;
+ if (ctlv->head.type == IPFW_TLV_RULE_LIST) {
+ rbase = (struct ip_fw *)(ctlv + 1);
+ rcnt = ctlv->count;
+ read += ctlv->head.length;
+ ctlv = (ipfw_obj_ctlv *)((caddr_t)ctlv +
+ ctlv->head.length);
}
}
+
+ if ((cfg->flags & IPFW_CFG_GET_STATES) && (read != sz)) {
+ /* We may have some dynamic rules */
+ read += sizeof(ipfw_obj_ctlv);
+ dcnt = ((sz - read) / ctlv->objsize);
+ if (dcnt != 0)
+ dynbase = (ipfw_dyn_rule *)(ctlv + 1);
+ }
+
+ prepare_format_opts(co, fo, rbase, dynbase, rcnt, dcnt);
+ bp_alloc(&bp, 4096);
+
/* if no rule numbers were specified, list all rules */
if (ac == 0) {
- for (n = 0, r = data; n < nstat; n++, r = NEXT(r)) {
- if (co.use_set && r->set != co.use_set - 1)
- continue;
- show_ipfw(r, pcwidth, bcwidth);
- }
+ fo->first = 0;
+ fo->last = IPFW_DEFAULT_RULE;
+ ipfw_list_static_range(co, fo, &bp, rbase, rcnt);
- if (co.do_dynamic && ndyn) {
- printf("## Dynamic rules (%d):\n", ndyn);
- for (n = 0, d = dynrules; n < ndyn; n++, d++) {
*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
More information about the svn-src-projects
mailing list