summaryrefslogtreecommitdiff
path: root/sbin/pfctl/pf_print_state.c
diff options
context:
space:
mode:
Diffstat (limited to 'sbin/pfctl/pf_print_state.c')
-rw-r--r--sbin/pfctl/pf_print_state.c244
1 files changed, 244 insertions, 0 deletions
diff --git a/sbin/pfctl/pf_print_state.c b/sbin/pfctl/pf_print_state.c
new file mode 100644
index 00000000000..9f26045d160
--- /dev/null
+++ b/sbin/pfctl/pf_print_state.c
@@ -0,0 +1,244 @@
+/* $OpenBSD: pf_print_state.c,v 1.1 2002/06/06 22:22:44 mickey Exp $ */
+
+/*
+ * Copyright (c) 2001 Daniel Hartmeier
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/ip_icmp.h>
+#include <netinet/icmp6.h>
+#define TCPSTATES
+#include <netinet/tcp_fsm.h>
+#include <net/pfvar.h>
+#include <arpa/inet.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <netdb.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <err.h>
+
+#include "pfctl_parser.h"
+#include "pf_print_state.h"
+
+int
+unmask(struct pf_addr *m, u_int8_t af)
+{
+ int i = 31, j = 0, b = 0, msize;
+ u_int32_t tmp;
+
+ if (af == AF_INET)
+ msize = 1;
+ else
+ msize = 4;
+ while (j < msize && m->addr32[j] == 0xffffffff) {
+ b += 32;
+ j++;
+ }
+ if (j < msize) {
+ tmp = ntohl(m->addr32[j]);
+ for (i = 31; tmp & (1 << i); --i)
+ b++;
+ }
+ return (b);
+}
+
+void
+print_addr(struct pf_addr_wrap *addr, struct pf_addr *mask, u_int8_t af)
+{
+ char buf[48];
+
+ if (addr->addr_dyn != NULL)
+ printf("(%s)", addr->addr.pfa.ifname);
+ else {
+ if (inet_ntop(af, &addr->addr, buf, sizeof(buf)) == NULL)
+ printf("?");
+ else
+ printf("%s", buf);
+ }
+ if (mask != NULL) {
+ int bits = unmask(mask, af);
+
+ if (bits != (af == AF_INET ? 32 : 128))
+ printf("/%u", bits);
+ }
+}
+
+void
+print_name(struct pf_addr *addr, struct pf_addr *mask, int af)
+{
+ char buf[48];
+ struct hostent *hp;
+
+ if (inet_ntop(af, addr, buf, sizeof(buf)) == NULL)
+ printf("?");
+ else {
+ hp = getpfhostname(buf);
+ printf("%s", hp->h_name);
+ }
+ if (mask != NULL) {
+ if (!PF_AZERO(mask, af))
+ printf("/%u", unmask(mask, af));
+ }
+}
+
+void
+print_host(struct pf_state_host *h, u_int8_t af, int opts)
+{
+ u_int16_t p = ntohs(h->port);
+
+ if (opts & PF_OPT_USEDNS)
+ print_name(&h->addr, NULL, af);
+ else {
+ struct pf_addr_wrap aw;
+
+ aw.addr = h->addr;
+ aw.addr_dyn = NULL;
+ print_addr(&aw, NULL, af);
+ }
+
+ if (p) {
+ if (af == AF_INET)
+ printf(":%u", p);
+ else
+ printf("[%u]", p);
+ }
+}
+
+void
+print_seq(struct pf_state_peer *p)
+{
+ if (p->seqdiff)
+ printf("[%u + %u](+%u)", p->seqlo, p->seqhi - p->seqlo,
+ p->seqdiff);
+ else
+ printf("[%u + %u]", p->seqlo, p->seqhi - p->seqlo);
+}
+
+void
+print_state(struct pf_state *s, int opts)
+{
+ struct pf_state_peer *src, *dst;
+ struct protoent *p;
+ u_int8_t hrs, min, sec;
+
+ if (s->direction == PF_OUT) {
+ src = &s->src;
+ dst = &s->dst;
+ } else {
+ src = &s->dst;
+ dst = &s->src;
+ }
+ if ((p = getprotobynumber(s->proto)) != NULL)
+ printf("%s ", p->p_name);
+ else
+ printf("%u ", s->proto);
+ if (PF_ANEQ(&s->lan.addr, &s->gwy.addr, s->af) ||
+ (s->lan.port != s->gwy.port)) {
+ print_host(&s->lan, s->af, opts);
+ if (s->direction == PF_OUT)
+ printf(" -> ");
+ else
+ printf(" <- ");
+ }
+ print_host(&s->gwy, s->af, opts);
+ if (s->direction == PF_OUT)
+ printf(" -> ");
+ else
+ printf(" <- ");
+ print_host(&s->ext, s->af, opts);
+
+ printf(" ");
+ if (s->proto == IPPROTO_TCP) {
+ if (src->state <= TCPS_TIME_WAIT &&
+ dst->state <= TCPS_TIME_WAIT) {
+ printf(" %s:%s\n", tcpstates[src->state],
+ tcpstates[dst->state]);
+ } else {
+ printf(" <BAD STATE LEVELS>\n");
+ }
+ if (opts & PF_OPT_VERBOSE) {
+ printf(" ");
+ print_seq(src);
+ printf(" ");
+ print_seq(dst);
+ printf("\n");
+ }
+ } else {
+ printf(" %u:%u\n", src->state, dst->state);
+ }
+
+ if (opts & PF_OPT_VERBOSE) {
+ sec = s->creation % 60;
+ s->creation /= 60;
+ min = s->creation % 60;
+ s->creation /= 60;
+ hrs = s->creation;
+ printf(" age %.2u:%.2u:%.2u", hrs, min, sec);
+ sec = s->expire % 60;
+ s->expire /= 60;
+ min = s->expire % 60;
+ s->expire /= 60;
+ hrs = s->expire;
+ printf(", expires in %.2u:%.2u:%.2u", hrs, min, sec);
+ printf(", %u pkts, %u bytes", s->packets, s->bytes);
+ if (s->rule.nr != USHRT_MAX)
+ printf(", rule %u", s->rule.nr);
+ printf("\n");
+ }
+}
+
+struct hostent *
+getpfhostname(const char *addr_str)
+{
+ in_addr_t addr_num;
+ struct hostent *hp;
+ static struct hostent myhp;
+
+ addr_num = inet_addr(addr_str);
+ if (addr_num == INADDR_NONE) {
+ myhp.h_name = (char *)addr_str;
+ hp = &myhp;
+ return (hp);
+ }
+ hp = gethostbyaddr((char *)&addr_num, sizeof(addr_num), AF_INET);
+ if (hp == NULL) {
+ myhp.h_name = (char *)addr_str;
+ hp = &myhp;
+ }
+ return (hp);
+}