]> The Tcpdump Group git mirrors - tcpdump/commitdiff
Add DLT_PFSYNC support.
authorGuy Harris <[email protected]>
Wed, 29 Feb 2012 09:51:27 +0000 (01:51 -0800)
committerGuy Harris <[email protected]>
Wed, 29 Feb 2012 09:51:27 +0000 (01:51 -0800)
From FreeBSD PR bin/124825: tcpdump(8) does not support pfsync(4) data,
which in turn was ported over from OpenBSD.  We already have CARP
support, so we did not port that part over.

Makefile.in
addrtoname.c
addrtoname.h
configure
configure.in
interface.h
pf_print_state.c [new file with mode: 0644]
print-ip.c
print-pfsync.c [new file with mode: 0644]
tcpdump.c

index aefd3a478d158efe94ad111df4d4af6bd8f0b269..d75140a608818fd85998f05a613291377e10baea 100644 (file)
@@ -245,6 +245,7 @@ EXTRA_DIST = \
        mkdep \
        packetdat.awk \
        pcap_dump_ftell.c \
+       pf_print_state.c \
        print-babel.c \
        print-dhcp6.c \
        print-frag6.c \
@@ -255,6 +256,7 @@ EXTRA_DIST = \
        print-netbios.c \
        print-ospf6.c \
        print-pflog.c \
+       print-pfsync.c \
        print-ripng.c \
        print-rt6.c \
        print-smb.c \
index d77f27b0ac4fd999e29cf48fa8f49df82270582a..eb7b4501138a77417e64a5266ebf9a04c96db9ba 100644 (file)
@@ -156,6 +156,7 @@ struct enamemem {
 static struct enamemem enametable[HASHNAMESIZE];
 static struct enamemem nsaptable[HASHNAMESIZE];
 static struct enamemem bytestringtable[HASHNAMESIZE];
+static const char *ipprototable[256];
 
 struct protoidmem {
        u_int32_t p_oui;
@@ -717,6 +718,12 @@ ipxsap_string(u_short port)
        return (tp->name);
 }
 
+const char *
+ipproto_string(u_int proto)
+{
+       return ipprototable[proto & 0xff];
+}
+
 static void
 init_servarray(void)
 {
@@ -748,6 +755,25 @@ init_servarray(void)
        endservent();
 }
 
+static void
+init_ipprotoarray(void)
+{
+       int i;
+       char buf[sizeof("000")];
+       struct protoent *pr;
+
+       if (!nflag) {
+               while ((pr = getprotoent()) != NULL)
+                       ipprototable[pr->p_proto & 0xff] = strdup(pr->p_name);
+               endprotoent();
+       }
+       for (i = 0; i < 256; i++)
+               if (ipprototable[i] == NULL) {
+                       (void)snprintf(buf, sizeof(buf), "%d", i);
+                       ipprototable[i] = strdup(buf);
+               }
+}
+
 /* in libpcap.a (nametoaddr.c) */
 #if defined(WIN32) && !defined(USE_STATIC_LIBPCAP)
 __declspec(dllimport)
@@ -1137,6 +1163,7 @@ init_addrtoname(u_int32_t localnet, u_int32_t mask)
                f_localnet = localnet;
                f_netmask = mask;
        }
+       init_ipprotoarray();
        if (nflag)
                /*
                 * Simplest way to suppress names.
index cd5c41f4a5ff1e57ffd7d8939266a958d135d168..c0cd033306eca3c0f866748ab8de73278f3976f0 100644 (file)
@@ -38,6 +38,7 @@ extern const char *le64addr_string(const u_char *);
 extern const char *etherproto_string(u_short);
 extern const char *tcpport_string(u_short);
 extern const char *udpport_string(u_short);
+extern const char *ipproto_string(u_int);
 extern const char *getname(const u_char *);
 #ifdef INET6
 extern const char *getname6(const u_char *);
index f481d333d3f9fe5786962ab03d1e4d2353198c77..5ba607119fae9480f235b9876ffed5b78a554f2d 100755 (executable)
--- a/configure
+++ b/configure
@@ -4190,7 +4190,7 @@ fi
 done
 
 if test "$ac_cv_header_net_pfvar_h" = yes; then
-       LOCALSRC="print-pflog.c $LOCALSRC"
+       LOCALSRC="print-pflog.c print-pfsync.c pf_print_state.c $LOCALSRC"
 fi
 
 for ac_header in netinet/if_ether.h
index 4ac664ecf099508410469699d8c05ace4667e000..49fd4e8c6a14ae06bcc68ac89fa3137e80b0299a 100644 (file)
@@ -34,7 +34,7 @@ AC_CHECK_HEADERS(net/pfvar.h, , , [#include <sys/types.h>
 #include <sys/socket.h>
 #include <net/if.h>])
 if test "$ac_cv_header_net_pfvar_h" = yes; then
-       LOCALSRC="print-pflog.c $LOCALSRC"
+       LOCALSRC="print-pflog.c print-pfsync.c pf_print_state.c $LOCALSRC"
 fi
 AC_CHECK_HEADERS(netinet/if_ether.h, , , [#include <sys/types.h>
 #include <sys/socket.h>])
index 18668a21f3773758056e53363af8007a7d4f210d..563c4cb5457a7777ab4b932cddbcd8519fbda9ae 100644 (file)
@@ -183,6 +183,8 @@ extern void dvmrp_print(const u_char *, u_int);
 extern void egp_print(const u_char *, u_int);
 extern u_int enc_if_print(const struct pcap_pkthdr *, const u_char *);
 extern u_int pflog_if_print(const struct pcap_pkthdr *, const u_char *);
+extern u_int pfsync_if_print(const struct pcap_pkthdr *, const u_char *);
+extern void pfsync_ip_print(const u_char *, u_int, const u_char *);
 extern u_int arcnet_if_print(const struct pcap_pkthdr *, const u_char *);
 extern u_int arcnet_linux_if_print(const struct pcap_pkthdr *, const u_char *);
 extern u_int token_print(const u_char *, u_int, u_int);
diff --git a/pf_print_state.c b/pf_print_state.c
new file mode 100644 (file)
index 0000000..602874a
--- /dev/null
@@ -0,0 +1,289 @@
+/*     $OpenBSD: pf_print_state.c,v 1.3 2005/11/04 08:24:15 mcbride 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>
+#define TCPSTATES
+#include <netinet/tcp_fsm.h>
+#include <net/pfvar.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+
+#include <stdio.h>
+#include <string.h>
+
+#include "pfctl_parser.h"
+#include "pfctl.h"
+#include "addrtoname.h"
+
+#include <sys/endian.h>
+#define        betoh64(x)              (unsigned long long)be64toh(x)
+
+void   print_name(struct pf_addr *, sa_family_t);
+
+void
+print_addr(struct pf_addr_wrap *addr, sa_family_t af, int verbose)
+{
+       switch (addr->type) {
+       case PF_ADDR_DYNIFTL:
+               printf("(%s", addr->v.ifname);
+               if (addr->iflags & PFI_AFLAG_NETWORK)
+                       printf(":network");
+               if (addr->iflags & PFI_AFLAG_BROADCAST)
+                       printf(":broadcast");
+               if (addr->iflags & PFI_AFLAG_PEER)
+                       printf(":peer");
+               if (addr->iflags & PFI_AFLAG_NOALIAS)
+                       printf(":0");
+               if (verbose) {
+                       if (addr->p.dyncnt <= 0)
+                               printf(":*");
+                       else
+                               printf(":%d", addr->p.dyncnt);
+               }
+               printf(")");
+               break;
+       case PF_ADDR_TABLE:
+               if (verbose)
+                       if (addr->p.tblcnt == -1)
+                               printf("<%s:*>", addr->v.tblname);
+                       else
+                               printf("<%s:%d>", addr->v.tblname,
+                                   addr->p.tblcnt);
+               else
+                       printf("<%s>", addr->v.tblname);
+               return;
+       case PF_ADDR_ADDRMASK:
+               if (PF_AZERO(&addr->v.a.addr, AF_INET6) &&
+                   PF_AZERO(&addr->v.a.mask, AF_INET6))
+                       printf("any");
+               else {
+                       char buf[48];
+
+                       if (inet_ntop(af, &addr->v.a.addr, buf,
+                           sizeof(buf)) == NULL)
+                               printf("?");
+                       else
+                               printf("%s", buf);
+               }
+               break;
+       case PF_ADDR_NOROUTE:
+               printf("no-route");
+               return;
+       default:
+               printf("?");
+               return;
+       }
+       if (! PF_AZERO(&addr->v.a.mask, af)) {
+               int bits = unmask(&addr->v.a.mask, af);
+
+               if (bits != (af == AF_INET ? 32 : 128))
+                       printf("/%d", bits);
+       }
+}
+
+void
+print_name(struct pf_addr *addr, sa_family_t af)
+{
+       const char *host;
+
+       switch (af) {
+       case AF_INET:
+               host = getname((const char *)&addr->v4);
+               break;
+       case AF_INET6:
+               host = getname6((const char *)&addr->v6);
+               break;
+       default:
+               host = "?";
+               break;
+       }
+       printf("%s", host);
+}
+
+void
+print_host(struct pf_state_host *h, sa_family_t af, int opts)
+{
+       u_int16_t p = ntohs(h->port);
+
+       if (opts & PF_OPT_USEDNS)
+               print_name(&h->addr, af);
+       else {
+               struct pf_addr_wrap aw;
+
+               memset(&aw, 0, sizeof(aw));
+               aw.v.a.addr = h->addr;
+               if (af == AF_INET)
+                       aw.v.a.mask.addr32[0] = 0xffffffff;
+               else {
+                       memset(&aw.v.a.mask, 0xff, sizeof(aw.v.a.mask));
+                       af = AF_INET6;
+               }
+               print_addr(&aw, af, opts & PF_OPT_VERBOSE2);
+       }
+
+       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;
+       int min, sec;
+
+       if (s->direction == PF_OUT) {
+               src = &s->src;
+               dst = &s->dst;
+       } else {
+               src = &s->dst;
+               dst = &s->src;
+       }
+       printf("%s ", s->u.ifname);
+       printf("%s ", ipproto_string(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("\n   %s:%s", tcpstates[src->state],
+                           tcpstates[dst->state]);
+               else if (src->state == PF_TCPS_PROXY_SRC ||
+                   dst->state == PF_TCPS_PROXY_SRC)
+                       printf("\n   PROXY:SRC");
+               else if (src->state == PF_TCPS_PROXY_DST ||
+                   dst->state == PF_TCPS_PROXY_DST)
+                       printf("\n   PROXY:DST");
+               else
+                       printf("\n   <BAD STATE LEVELS %u:%u>",
+                           src->state, dst->state);
+               if (opts & PF_OPT_VERBOSE) {
+                       printf("\n   ");
+                       print_seq(src);
+                       if (src->wscale && dst->wscale)
+                               printf(" wscale %u",
+                                   src->wscale & PF_WSCALE_MASK);
+                       printf("  ");
+                       print_seq(dst);
+                       if (src->wscale && dst->wscale)
+                               printf(" wscale %u",
+                                   dst->wscale & PF_WSCALE_MASK);
+               }
+       } else if (s->proto == IPPROTO_UDP && src->state < PFUDPS_NSTATES &&
+           dst->state < PFUDPS_NSTATES) {
+               const char *states[] = PFUDPS_NAMES;
+
+               printf("   %s:%s", states[src->state], states[dst->state]);
+       } else if (s->proto != IPPROTO_ICMP && src->state < PFOTHERS_NSTATES &&
+           dst->state < PFOTHERS_NSTATES) {
+               /* XXX ICMP doesn't really have state levels */
+               const char *states[] = PFOTHERS_NAMES;
+
+               printf("   %s:%s", states[src->state], states[dst->state]);
+       } else {
+               printf("   %u:%u", src->state, dst->state);
+       }
+
+       if (opts & PF_OPT_VERBOSE) {
+               sec = s->creation % 60;
+               s->creation /= 60;
+               min = s->creation % 60;
+               s->creation /= 60;
+               printf("\n   age %.2u:%.2u:%.2u", s->creation, min, sec);
+               sec = s->expire % 60;
+               s->expire /= 60;
+               min = s->expire % 60;
+               s->expire /= 60;
+               printf(", expires in %.2u:%.2u:%.2u", s->expire, min, sec);
+               printf(", %llu:%llu pkts, %llu:%llu bytes",
+                   s->packets[0], s->packets[1], s->bytes[0], s->bytes[1]);
+               if (s->anchor.nr != -1)
+                       printf(", anchor %u", s->anchor.nr);
+               if (s->rule.nr != -1)
+                       printf(", rule %u", s->rule.nr);
+               if (s->src_node != NULL)
+                       printf(", source-track");
+               if (s->nat_src_node != NULL)
+                       printf(", sticky-address");
+       }
+       if (opts & PF_OPT_VERBOSE2) {
+               printf("\n   id: %016llx creatorid: %08x",
+                   betoh64(s->id), ntohl(s->creatorid));
+       }
+}
+
+int
+unmask(struct pf_addr *m, sa_family_t af)
+{
+       int i = 31, j = 0, b = 0;
+       u_int32_t tmp;
+
+       while (j < 4 && m->addr32[j] == 0xffffffff) {
+               b += 32;
+               j++;
+       }
+       if (j < 4) {
+               tmp = ntohl(m->addr32[j]);
+               for (i = 31; tmp & (1 << i); --i)
+                       b++;
+       }
+       return (b);
+}
index c0c91888bdc3a6d30b3a81a150c6650b74fb8b40..a7d95eb94ead36aa2e36626dadce2f96b7e87568 100644 (file)
@@ -477,6 +477,14 @@ again:
                }
                break;
 
+#ifdef HAVE_NET_PFVAR_H
+       case IPPROTO_PFSYNC:
+               pfsync_ip_print(ipds->cp,
+                   (int)(snapend - (u_char *)ipds->ip) - IP_HL(ipds->ip) * 4,
+                               (const u_char *)ipds->ip);
+               break;
+#endif
+
        case IPPROTO_PGM:
                pgm_print(ipds->cp, ipds->len, (const u_char *)ipds->ip);
                break;
diff --git a/print-pfsync.c b/print-pfsync.c
new file mode 100644 (file)
index 0000000..2799980
--- /dev/null
@@ -0,0 +1,248 @@
+/*     $OpenBSD: print-pfsync.c,v 1.32 2007/10/07 16:41:05 deraadt Exp $       */
+
+/*
+ * Copyright (c) 2002 Michael Shalayeff
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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 AUTHOR ``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 AUTHOR OR HIS RELATIVES 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 MIND, 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.
+ */
+
+#ifndef lint
+static const char rcsid[] =
+    "@(#) $Id: print-pfsync.c,v 1.32 2007/10/07 16:41:05 deraadt Exp $";
+#endif
+
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <sys/file.h>
+#include <sys/ioctl.h>
+#include <sys/mbuf.h>
+
+#ifdef __STDC__
+struct rtentry;
+#endif
+#include <net/if.h>
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+
+#include <net/pfvar.h>
+#include <net/if_pfsync.h>
+
+#include <ctype.h>
+#include <netdb.h>
+#include <pcap.h>
+#include <signal.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "interface.h"
+#include "addrtoname.h"
+#include "pfctl_parser.h"
+#include "pfctl.h"
+
+#include <sys/endian.h>
+#define        betoh64(x)              (unsigned long long)be64toh(x)
+
+const char *pfsync_acts[] = { PFSYNC_ACTIONS };
+
+void   pfsync_print(struct pfsync_header *, int);
+
+u_int
+pfsync_if_print(const struct pcap_pkthdr *h, const u_char *p)
+{
+       u_int caplen = h->caplen;
+       u_int hdrlen;
+
+       if (caplen < PFSYNC_HDRLEN) {
+               printf("[|pfsync]");
+               goto out;
+       }
+
+       pfsync_print((struct pfsync_header *)p,
+           caplen - sizeof(struct pfsync_header));
+out:
+       return (PFSYNC_HDRLEN);
+}
+
+void
+pfsync_ip_print(const u_char *bp, u_int len, const u_char *bp2)
+{
+       struct pfsync_header *hdr = (struct pfsync_header *)bp;
+       struct ip *ip = (struct ip *)bp2;
+
+       if (vflag)
+               printf("%s > %s: ", ipaddr_string(&ip->ip_src),
+                   ipaddr_string(&ip->ip_dst));
+       else
+               printf("%s: ", ipaddr_string(&ip->ip_src));
+
+       if (len < PFSYNC_HDRLEN)
+               printf("[|pfsync]");
+       else
+               pfsync_print(hdr, (len - sizeof(struct pfsync_header)));
+       putchar('\n');
+}
+
+void
+pfsync_print(struct pfsync_header *hdr, int len)
+{
+       struct pfsync_state *s;
+       struct pfsync_state_upd *u;
+       struct pfsync_state_del *d;
+       struct pfsync_state_clr *c;
+       struct pfsync_state_upd_req *r;
+       struct pfsync_state_bus *b;
+#ifdef PFSYNC_TDB
+       struct pfsync_tdb *t;
+#endif
+       int i, flags = 0, min, sec;
+       u_int64_t id;
+
+       if (eflag)
+               printf("PFSYNCv%d count %d: ",
+                   hdr->version, hdr->count);
+
+       if (hdr->action < PFSYNC_ACT_MAX)
+               printf("%s:", pfsync_acts[hdr->action]);
+       else
+               printf("%d?:", hdr->action);
+       if (vflag)
+               flags |= PF_OPT_VERBOSE;
+       if (vflag > 1)
+               flags |= PF_OPT_VERBOSE2;
+       if (!nflag)
+               flags |= PF_OPT_USEDNS;
+
+       switch (hdr->action) {
+       case PFSYNC_ACT_CLR:
+               if (sizeof(*c) <= len) {
+                       c = (void *)((char *)hdr + PFSYNC_HDRLEN);
+                       printf("\n\tcreatorid: %08x", htonl(c->creatorid));
+                       if (c->ifname[0] != '\0')
+                               printf(" interface: %s", c->ifname);
+               }
+       case PFSYNC_ACT_INS:
+       case PFSYNC_ACT_UPD:
+       case PFSYNC_ACT_DEL:
+               for (i = 1, s = (void *)((char *)hdr + PFSYNC_HDRLEN);
+                   i <= hdr->count && i * sizeof(*s) <= len; i++, s++) {
+                       struct pf_state st;
+
+                       bzero(&st, sizeof(st));
+                       bcopy(&s->id, &st.id, sizeof(st.id));
+
+                       strlcpy(st.u.ifname, s->ifname, sizeof(st.u.ifname));
+                       pf_state_host_ntoh(&s->lan, &st.lan);
+                       pf_state_host_ntoh(&s->gwy, &st.gwy);
+                       pf_state_host_ntoh(&s->ext, &st.ext);
+                       pf_state_peer_ntoh(&s->src, &st.src);
+                       pf_state_peer_ntoh(&s->dst, &st.dst);
+                       st.rule.nr = ntohl(s->rule);
+                       st.nat_rule.nr = ntohl(s->nat_rule);
+                       st.anchor.nr = ntohl(s->anchor);
+                       bcopy(&s->rt_addr, &st.rt_addr, sizeof(st.rt_addr));
+                       st.creation = ntohl(s->creation);
+                       st.expire = ntohl(s->expire);
+                       pf_state_counter_ntoh(s->packets[0], st.packets[0]);
+                       pf_state_counter_ntoh(s->packets[1], st.packets[1]);
+                       pf_state_counter_ntoh(s->bytes[0], st.bytes[0]);
+                       pf_state_counter_ntoh(s->bytes[1], st.bytes[1]);
+                       st.creatorid = s->creatorid;
+                       st.af = s->af;
+                       st.proto = s->proto;
+                       st.direction = s->direction;
+                       st.log = s->log;
+                       st.timeout = s->timeout;
+                       st.allow_opts = s->allow_opts;
+                       st.sync_flags = s->sync_flags;
+
+                       putchar('\n');
+                       print_state(&st, flags);
+                       if (vflag > 1 && hdr->action == PFSYNC_ACT_UPD)
+                               printf(" updates: %d", s->updates);
+               }
+               break;
+       case PFSYNC_ACT_UPD_C:
+               for (i = 1, u = (void *)((char *)hdr + PFSYNC_HDRLEN);
+                   i <= hdr->count && i * sizeof(*u) <= len; i++, u++) {
+                       bcopy(&u->id, &id, sizeof(id));
+                       printf("\n\tid: %016llx creatorid: %08x",
+                           betoh64(id), ntohl(u->creatorid));
+                       if (vflag > 1)
+                               printf(" updates: %d", u->updates);
+               }
+               break;
+       case PFSYNC_ACT_DEL_C:
+               for (i = 1, d = (void *)((char *)hdr + PFSYNC_HDRLEN);
+                   i <= hdr->count && i * sizeof(*d) <= len; i++, d++) {
+                       bcopy(&d->id, &id, sizeof(id));
+                       printf("\n\tid: %016llx creatorid: %08x",
+                           betoh64(id), ntohl(d->creatorid));
+               }
+               break;
+       case PFSYNC_ACT_UREQ:
+               for (i = 1, r = (void *)((char *)hdr + PFSYNC_HDRLEN);
+                   i <= hdr->count && i * sizeof(*r) <= len; i++, r++) {
+                       bcopy(&r->id, &id, sizeof(id));
+                       printf("\n\tid: %016llx creatorid: %08x",
+                           betoh64(id), ntohl(r->creatorid));
+               }
+               break;
+       case PFSYNC_ACT_BUS:
+               if (sizeof(*b) <= len) {
+                       b = (void *)((char *)hdr + PFSYNC_HDRLEN);
+                       printf("\n\tcreatorid: %08x", htonl(b->creatorid));
+                       sec = b->endtime % 60;
+                       b->endtime /= 60;
+                       min = b->endtime % 60;
+                       b->endtime /= 60;
+                       printf(" age %.2u:%.2u:%.2u", b->endtime, min, sec);
+                       switch (b->status) {
+                       case PFSYNC_BUS_START:
+                               printf(" status: start");
+                               break;
+                       case PFSYNC_BUS_END:
+                               printf(" status: end");
+                               break;
+                       default:
+                               printf(" status: ?");
+                               break;
+                       }
+               }
+               break;
+#ifdef PFSYNC_TDB
+       case PFSYNC_ACT_TDB_UPD:
+               for (i = 1, t = (void *)((char *)hdr + PFSYNC_HDRLEN);
+                   i <= hdr->count && i * sizeof(*t) <= len; i++, t++)
+                       printf("\n\tspi: %08x rpl: %u cur_bytes: %llu",
+                           htonl(t->spi), htonl(t->rpl),
+                           betoh64(t->cur_bytes));
+                       /* XXX add dst and sproto? */
+               break;
+#endif
+       default:
+               break;
+       }
+}
index 587ed32170ac925df013cd2d8cb8473737e71003..5427182dcdcccccd8ba9a142781986bf1e5f184f 100644 (file)
--- a/tcpdump.c
+++ b/tcpdump.c
@@ -209,6 +209,9 @@ static struct printer printers[] = {
 #if defined(DLT_PFLOG) && defined(HAVE_NET_PFVAR_H)
        { pflog_if_print,       DLT_PFLOG },
 #endif
+#if defined(DLT_PFSYNC) && defined(HAVE_NET_PFVAR_H)
+       { pfsync_if_print,      DLT_PFSYNC },
+#endif
 #ifdef DLT_FR
        { fr_if_print,          DLT_FR },
 #endif