Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F151006935
D30244.id89523.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
14 KB
Referenced Files
None
Subscribers
None
D30244.id89523.diff
View Options
diff --git a/lib/libpfctl/libpfctl.h b/lib/libpfctl/libpfctl.h
--- a/lib/libpfctl/libpfctl.h
+++ b/lib/libpfctl/libpfctl.h
@@ -197,6 +197,64 @@
bool kill_match;
};
+struct pfctl_state_scrub {
+ bool timestamp;
+ uint8_t ttl;
+ uint32_t ts_mod;
+};
+
+struct pfctl_state_peer {
+ struct pfctl_state_scrub *scrub;
+ uint32_t seqlo;
+ uint32_t seqhi;
+ uint32_t seqdiff;
+ uint16_t max_win;
+ uint16_t mss;
+ uint8_t state;
+ uint8_t wscale;
+};
+
+struct pfctl_state_key {
+ struct pf_addr addr[2];
+ uint16_t port[2];
+ sa_family_t af;
+ uint8_t proto;
+};
+
+struct pfctl_state {
+ TAILQ_ENTRY(pfctl_state) entry;
+
+ uint64_t id;
+ uint32_t creatorid;
+ uint8_t direction;
+
+ struct pfctl_state_peer src;
+ struct pfctl_state_peer dst;
+
+ uint32_t rule;
+ uint32_t anchor;
+ uint32_t nat_rule;
+ struct pf_addr rt_addr;
+ struct pfctl_state_key key[2]; /* addresses stack and wire */
+ char ifname[IFNAMSIZ];
+ uint64_t packets[2];
+ uint64_t bytes[2];
+ uint32_t creation;
+ uint32_t expire;
+ uint32_t pfsync_time;
+ uint16_t tag;
+ uint8_t log;
+ uint8_t state_flags;
+ uint8_t timeout;
+ uint32_t sync_flags;
+};
+
+TAILQ_HEAD(pfctl_statelist, pfctl_state);
+struct pfctl_states {
+ struct pfctl_statelist states;
+ size_t count;
+};
+
int pfctl_get_rule(int dev, u_int32_t nr, u_int32_t ticket,
const char *anchor, u_int32_t ruleset, struct pfctl_rule *rule,
char *anchor_call);
@@ -207,6 +265,8 @@
const char *anchor, const char *anchor_call, u_int32_t ticket,
u_int32_t pool_ticket);
int pfctl_set_keepcounters(int dev, bool keep);
+int pfctl_get_states(int dev, struct pfctl_states *states);
+void pfctl_free_states(struct pfctl_states *states);
int pfctl_clear_states(int dev, const struct pfctl_kill *kill,
unsigned int *killed);
int pfctl_kill_states(int dev, const struct pfctl_kill *kill,
diff --git a/lib/libpfctl/libpfctl.c b/lib/libpfctl/libpfctl.c
--- a/lib/libpfctl/libpfctl.c
+++ b/lib/libpfctl/libpfctl.c
@@ -627,6 +627,179 @@
nvlist_add_nvlist(nvl, name, nv);
}
+static void
+pf_nvstate_scrub_to_state_scrub(const nvlist_t *nvl,
+ struct pfctl_state_scrub *scrub)
+{
+ bzero(scrub, sizeof(*scrub));
+
+ scrub->timestamp = nvlist_get_bool(nvl, "timestamp");
+ scrub->ttl = nvlist_get_number(nvl, "ttl");
+ scrub->ts_mod = nvlist_get_number(nvl, "ts_mod");
+}
+
+static void
+pf_nvstate_peer_to_state_peer(const nvlist_t *nvl,
+ struct pfctl_state_peer *peer)
+{
+ bzero(peer, sizeof(*peer));
+
+ if (nvlist_exists_nvlist(nvl, "scrub")) {
+ peer->scrub = malloc(sizeof(*peer->scrub));
+ pf_nvstate_scrub_to_state_scrub(
+ nvlist_get_nvlist(nvl, "scrub"),
+ peer->scrub);
+ }
+
+ peer->seqlo = nvlist_get_number(nvl, "seqlo");
+ peer->seqhi = nvlist_get_number(nvl, "seqhi");
+ peer->seqdiff = nvlist_get_number(nvl, "seqdiff");
+ peer->max_win = nvlist_get_number(nvl, "max_win");
+ peer->mss = nvlist_get_number(nvl, "mss");
+ peer->state = nvlist_get_number(nvl, "state");
+ peer->wscale = nvlist_get_number(nvl, "wscale");
+}
+
+static void
+pf_nvstate_key_to_state_key(const nvlist_t *nvl, struct pfctl_state_key *key)
+{
+ const nvlist_t * const *tmp;
+ size_t count;
+
+ bzero(key, sizeof(*key));
+
+ tmp = nvlist_get_nvlist_array(nvl, "addr", &count);
+ assert(count == 2);
+
+ for (int i = 0; i < 2; i++)
+ pf_nvaddr_to_addr(tmp[i], &key->addr[i]);
+
+ pf_nvuint_16_array(nvl, "port", 2, key->port, NULL);
+
+ key->af = nvlist_get_number(nvl, "af");
+ key->proto = nvlist_get_number(nvl, "proto");
+}
+
+static void
+pf_nvstate_to_state(const nvlist_t *nvl, struct pfctl_state *s)
+{
+ bzero(s, sizeof(*s));
+
+ s->id = nvlist_get_number(nvl, "id");
+ s->creatorid = nvlist_get_number(nvl, "creatorid");
+ s->direction = nvlist_get_number(nvl, "direction");
+
+ pf_nvstate_peer_to_state_peer(nvlist_get_nvlist(nvl, "src"), &s->src);
+ pf_nvstate_peer_to_state_peer(nvlist_get_nvlist(nvl, "dst"), &s->dst);
+
+ pf_nvstate_key_to_state_key(nvlist_get_nvlist(nvl, "stack_key"),
+ &s->key[0]);
+ pf_nvstate_key_to_state_key(nvlist_get_nvlist(nvl, "wire_key"),
+ &s->key[1]);
+
+ strlcpy(s->ifname, nvlist_get_string(nvl, "ifname"),
+ sizeof(s->ifname));
+
+ pf_nvaddr_to_addr(nvlist_get_nvlist(nvl, "rt_addr"), &s->rt_addr);
+ s->rule = nvlist_get_number(nvl, "rule");
+ s->anchor = nvlist_get_number(nvl, "anchor");
+ s->nat_rule = nvlist_get_number(nvl, "nat_rule");
+ s->creation = nvlist_get_number(nvl, "creation");
+ s->expire = nvlist_get_number(nvl, "expire");
+
+ pf_nvuint_64_array(nvl, "packets", 2, s->packets, NULL);
+ pf_nvuint_64_array(nvl, "bytes", 2, s->bytes, NULL);
+
+ s->log = nvlist_get_number(nvl, "log");
+ s->state_flags = nvlist_get_number(nvl, "state_flags");
+ s->timeout = nvlist_get_number(nvl, "timeout");
+ s->sync_flags = nvlist_get_number(nvl, "sync_flags");
+}
+
+int
+pfctl_get_states(int dev, struct pfctl_states *states)
+{
+ struct pfioc_nv nv;
+ nvlist_t *nvl;
+ const nvlist_t * const *slist;
+ size_t found_count;
+
+ bzero(states, sizeof(*states));
+ TAILQ_INIT(&states->states);
+
+ /* Just enough to get a number, and we'll grow from there. */
+ nv.data = malloc(64);
+ nv.len = nv.size = 64;
+
+ for (;;) {
+ if (ioctl(dev, DIOCGETSTATESNV, &nv)) {
+ free(nv.data);
+ return (errno);
+ }
+
+ nvl = nvlist_unpack(nv.data, nv.len, 0);
+ if (nvl == NULL) {
+ free(nv.data);
+ return (EIO);
+ }
+
+ states->count = nvlist_get_number(nvl, "count");
+
+ /* Are there any states? */
+ if (states->count == 0)
+ break;
+
+ if (nvlist_exists_nvlist_array(nvl, "states"))
+ slist = nvlist_get_nvlist_array(nvl, "states", &found_count);
+ else
+ found_count = 0;
+
+ if (found_count < states->count) {
+ size_t new_size = nv.size +
+ (nv.size * states->count / (found_count + 1) * 2);
+
+ /* Our buffer is too small. Estimate what we need based
+ * on how many states fit in the previous allocation
+ * and how many states there are. Doubled for margin.
+ * */
+ nv.data = realloc(nv.data, new_size);
+ nv.size = new_size;
+
+ if (nv.data == NULL)
+ return (ENOMEM);
+ continue;
+ }
+
+ for (size_t i = 0; i < found_count; i++) {
+ struct pfctl_state *s = malloc(sizeof(*s));
+ if (s == NULL) {
+ pfctl_free_states(states);
+ nvlist_destroy(nvl);
+ free(nv.data);
+ return (ENOMEM);
+ }
+
+ pf_nvstate_to_state(slist[i], s);
+ TAILQ_INSERT_TAIL(&states->states, s, entry);
+ }
+ break;
+ }
+
+ return (0);
+}
+
+void
+pfctl_free_states(struct pfctl_states *states)
+{
+ struct pfctl_state *s, *tmp;
+
+ TAILQ_FOREACH_SAFE(s, &states->states, entry, tmp) {
+ free(s);
+ }
+
+ bzero(states, sizeof(*states));
+}
+
static int
_pfctl_clear_states(int dev, const struct pfctl_kill *kill,
unsigned int *killed, uint64_t ioctlval)
diff --git a/sbin/pfctl/pf_print_state.c b/sbin/pfctl/pf_print_state.c
--- a/sbin/pfctl/pf_print_state.c
+++ b/sbin/pfctl/pf_print_state.c
@@ -196,25 +196,27 @@
}
void
-print_seq(struct pfsync_state_peer *p)
+print_seq(struct pfctl_state_peer *p)
{
if (p->seqdiff)
- printf("[%u + %u](+%u)", ntohl(p->seqlo),
- ntohl(p->seqhi) - ntohl(p->seqlo), ntohl(p->seqdiff));
+ printf("[%u + %u](+%u)", p->seqlo,
+ p->seqhi - p->seqlo, p->seqdiff);
else
- printf("[%u + %u]", ntohl(p->seqlo),
- ntohl(p->seqhi) - ntohl(p->seqlo));
+ printf("[%u + %u]", p->seqlo,
+ p->seqhi - p->seqlo);
}
void
-print_state(struct pfsync_state *s, int opts)
+print_state(struct pfctl_state *s, int opts)
{
- struct pfsync_state_peer *src, *dst;
- struct pfsync_state_key *key, *sk, *nk;
+ struct pfctl_state_peer *src, *dst;
+ struct pfctl_state_key *key, *sk, *nk;
struct protoent *p;
int min, sec;
+ sa_family_t af;
+ uint8_t proto;
#ifndef __NO_STRICT_ALIGNMENT
- struct pfsync_state_key aligned_key[2];
+ struct pfctl_state_key aligned_key[2];
bcopy(&s->key, aligned_key, sizeof(aligned_key));
key = aligned_key;
@@ -222,48 +224,51 @@
key = s->key;
#endif
+ af = s->key[PF_SK_WIRE].af;
+ proto = s->key[PF_SK_WIRE].proto;
+
if (s->direction == PF_OUT) {
src = &s->src;
dst = &s->dst;
sk = &key[PF_SK_STACK];
nk = &key[PF_SK_WIRE];
- if (s->proto == IPPROTO_ICMP || s->proto == IPPROTO_ICMPV6)
+ if (proto == IPPROTO_ICMP || proto == IPPROTO_ICMPV6)
sk->port[0] = nk->port[0];
} else {
src = &s->dst;
dst = &s->src;
sk = &key[PF_SK_WIRE];
nk = &key[PF_SK_STACK];
- if (s->proto == IPPROTO_ICMP || s->proto == IPPROTO_ICMPV6)
+ if (proto == IPPROTO_ICMP || proto == IPPROTO_ICMPV6)
sk->port[1] = nk->port[1];
}
printf("%s ", s->ifname);
- if ((p = getprotobynumber(s->proto)) != NULL)
+ if ((p = getprotobynumber(proto)) != NULL)
printf("%s ", p->p_name);
else
- printf("%u ", s->proto);
+ printf("%u ", proto);
- print_host(&nk->addr[1], nk->port[1], s->af, opts);
- if (PF_ANEQ(&nk->addr[1], &sk->addr[1], s->af) ||
+ print_host(&nk->addr[1], nk->port[1], af, opts);
+ if (PF_ANEQ(&nk->addr[1], &sk->addr[1], af) ||
nk->port[1] != sk->port[1]) {
printf(" (");
- print_host(&sk->addr[1], sk->port[1], s->af, opts);
+ print_host(&sk->addr[1], sk->port[1], af, opts);
printf(")");
}
if (s->direction == PF_OUT)
printf(" -> ");
else
printf(" <- ");
- print_host(&nk->addr[0], nk->port[0], s->af, opts);
- if (PF_ANEQ(&nk->addr[0], &sk->addr[0], s->af) ||
+ print_host(&nk->addr[0], nk->port[0], af, opts);
+ if (PF_ANEQ(&nk->addr[0], &sk->addr[0], af) ||
nk->port[0] != sk->port[0]) {
printf(" (");
- print_host(&sk->addr[0], sk->port[0], s->af, opts);
+ print_host(&sk->addr[0], sk->port[0], af, opts);
printf(")");
}
printf(" ");
- if (s->proto == IPPROTO_TCP) {
+ if (proto == IPPROTO_TCP) {
if (src->state <= TCPS_TIME_WAIT &&
dst->state <= TCPS_TIME_WAIT)
printf(" %s:%s\n", tcpstates[src->state],
@@ -290,16 +295,16 @@
dst->wscale & PF_WSCALE_MASK);
printf("\n");
}
- } else if (s->proto == IPPROTO_UDP && src->state < PFUDPS_NSTATES &&
+ } else if (proto == IPPROTO_UDP && src->state < PFUDPS_NSTATES &&
dst->state < PFUDPS_NSTATES) {
const char *states[] = PFUDPS_NAMES;
printf(" %s:%s\n", states[src->state], states[dst->state]);
#ifndef INET6
- } else if (s->proto != IPPROTO_ICMP && src->state < PFOTHERS_NSTATES &&
+ } else if (proto != IPPROTO_ICMP && src->state < PFOTHERS_NSTATES &&
dst->state < PFOTHERS_NSTATES) {
#else
- } else if (s->proto != IPPROTO_ICMP && s->proto != IPPROTO_ICMPV6 &&
+ } else if (proto != IPPROTO_ICMP && proto != IPPROTO_ICMPV6 &&
src->state < PFOTHERS_NSTATES && dst->state < PFOTHERS_NSTATES) {
#endif
/* XXX ICMP doesn't really have state levels */
@@ -311,10 +316,8 @@
}
if (opts & PF_OPT_VERBOSE) {
- u_int64_t packets[2];
- u_int64_t bytes[2];
- u_int32_t creation = ntohl(s->creation);
- u_int32_t expire = ntohl(s->expire);
+ u_int32_t creation = s->creation;
+ u_int32_t expire = s->expire;
sec = creation % 60;
creation /= 60;
@@ -327,19 +330,15 @@
expire /= 60;
printf(", expires in %.2u:%.2u:%.2u", expire, min, sec);
- bcopy(s->packets[0], &packets[0], sizeof(u_int64_t));
- bcopy(s->packets[1], &packets[1], sizeof(u_int64_t));
- bcopy(s->bytes[0], &bytes[0], sizeof(u_int64_t));
- bcopy(s->bytes[1], &bytes[1], sizeof(u_int64_t));
printf(", %ju:%ju pkts, %ju:%ju bytes",
- (uintmax_t )be64toh(packets[0]),
- (uintmax_t )be64toh(packets[1]),
- (uintmax_t )be64toh(bytes[0]),
- (uintmax_t )be64toh(bytes[1]));
- if (ntohl(s->anchor) != -1)
- printf(", anchor %u", ntohl(s->anchor));
- if (ntohl(s->rule) != -1)
- printf(", rule %u", ntohl(s->rule));
+ s->packets[0],
+ s->packets[1],
+ s->bytes[0],
+ s->bytes[1]);
+ if (s->anchor != -1)
+ printf(", anchor %u", s->anchor);
+ if (s->rule != -1)
+ printf(", rule %u", s->rule);
if (s->state_flags & PFSTATE_SLOPPY)
printf(", sloppy");
if (s->sync_flags & PFSYNC_FLAG_SRCNODE)
@@ -352,10 +351,9 @@
u_int64_t id;
bcopy(&s->id, &id, sizeof(u_int64_t));
- printf(" id: %016jx creatorid: %08x",
- (uintmax_t )be64toh(id), ntohl(s->creatorid));
+ printf(" id: %016jx creatorid: %08x", id, s->creatorid);
printf(" gateway: ");
- print_host(&s->rt_addr, 0, s->af, opts);
+ print_host(&s->rt_addr, 0, af, opts);
printf("\n");
}
}
diff --git a/sbin/pfctl/pfctl.h b/sbin/pfctl/pfctl.h
--- a/sbin/pfctl/pfctl.h
+++ b/sbin/pfctl/pfctl.h
@@ -120,8 +120,8 @@
void print_addr(struct pf_addr_wrap *, sa_family_t, int);
void print_host(struct pf_addr *, u_int16_t p, sa_family_t, int);
-void print_seq(struct pfsync_state_peer *);
-void print_state(struct pfsync_state *, int);
+void print_seq(struct pfctl_state_peer *);
+void print_state(struct pfctl_state *, int);
int unmask(struct pf_addr *, sa_family_t);
int pfctl_cmdline_symset(char *);
diff --git a/sbin/pfctl/pfctl.c b/sbin/pfctl/pfctl.c
--- a/sbin/pfctl/pfctl.c
+++ b/sbin/pfctl/pfctl.c
@@ -1237,48 +1237,27 @@
int
pfctl_show_states(int dev, const char *iface, int opts)
{
- struct pfioc_states ps;
- struct pfsync_state *p;
- char *inbuf = NULL, *newinbuf = NULL;
- unsigned int len = 0;
- int i, dotitle = (opts & PF_OPT_SHOWALL);
+ struct pfctl_states states;
+ struct pfctl_state *s;
+ int dotitle = (opts & PF_OPT_SHOWALL);
- memset(&ps, 0, sizeof(ps));
- for (;;) {
- ps.ps_len = len;
- if (len) {
- newinbuf = realloc(inbuf, len);
- if (newinbuf == NULL)
- err(1, "realloc");
- ps.ps_buf = inbuf = newinbuf;
- }
- if (ioctl(dev, DIOCGETSTATES, &ps) < 0) {
- warn("DIOCGETSTATES");
- free(inbuf);
- return (-1);
- }
- if (ps.ps_len + sizeof(struct pfioc_states) < len)
- break;
- if (len == 0 && ps.ps_len == 0)
- goto done;
- if (len == 0 && ps.ps_len != 0)
- len = ps.ps_len;
- if (ps.ps_len == 0)
- goto done; /* no states */
- len *= 2;
- }
- p = ps.ps_states;
- for (i = 0; i < ps.ps_len; i += sizeof(*p), p++) {
- if (iface != NULL && strcmp(p->ifname, iface))
+ memset(&states, 0, sizeof(states));
+
+ if (pfctl_get_states(dev, &states))
+ return (-1);
+
+ TAILQ_FOREACH(s, &states.states, entry) {
+ if (iface != NULL && strcmp(s->ifname, iface))
continue;
if (dotitle) {
pfctl_print_title("STATES:");
dotitle = 0;
}
- print_state(p, opts);
+ print_state(s, opts);
}
-done:
- free(inbuf);
+
+ pfctl_free_states(&states);
+
return (0);
}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Mon, Apr 6, 10:33 AM (42 m, 21 s)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
30890525
Default Alt Text
D30244.id89523.diff (14 KB)
Attached To
Mode
D30244: pfctl: Use DIOCGETSTATESNV
Attached
Detach File
Event Timeline
Log In to Comment