[patch] teach tcpdump(1) to cope with the new-style pflog(4) output

From: Eygene Ryabinkin <rea-fbsd_at_codelabs.ru>
Date: Mon, 24 Sep 2007 21:35:51 +0400 (MSD)
>Submitter-Id:	current-users
>Originator:	Eygene Ryabinkin
>Organization:	Code Labs
>Confidential:	no 
>Synopsis:	[patch] teach tcpdump(1) to cope with the new-style pflog(4) output
>Severity:	serious
>Priority:	medium
>Category:	bin
>Class:		sw-bug
>Release:	FreeBSD 7.0-CURRENT i386
>Environment:

System: FreeBSD XXX 7.0-CURRENT FreeBSD 7.0-CURRENT #10: Wed Sep 12 16:16:49 MSD 2007 root_at_XXX:/usr/src/sys/i386/compile/XXX i386

>Description:

Version 1.9 of /sys/contrib/pf/net/if_pflog.h (Import of pf from
OpenBSD 4.1) introduced the backwards-incompatible change to the
'struct pfloghdr': the 'dir' and 'pad' members moved far away from
their previous positions.

This is not a problem for the pf itself, but tcpdump is no longer
able to print the packet direction correctly.

>How-To-Repeat:

Spawn tcpdump like 'tcpdump -lvvnetti pflog0' on the 7-CURRENT built
from the sources later than Tue Jul 3 16:16:07 2007 MSD and see
that the link-level header contains weird 'unkn(255)' direction:
"rule 14/0(match): block unkn(255) on uplink".

>Fix:

The following patch will cure the situation.  I know that the best
thing that can be done is to commit it to the tcpdump itself, but

a) this is a long process, since it requires tcpdump team to accept
   the patch and Someone (TM) to import new tcpdump sources to
   FreeBSD;
b) other eyes should see and criticize this patch.

I myself was tested this patch on the 7-CURRENT and 6.2-STABLE.
No regressions were seen yet and tcpdump works like a charm with
the new pflog0 packets showing 'in' and 'out' ;))

--- tcpdump-pflog-v2.patch begins here ---
--- contrib/tcpdump/pf.h.orig	2007-09-24 19:59:29.000000000 +0400
+++ contrib/tcpdump/pf.h	2007-09-24 20:31:40.000000000 +0400
_at__at_ -29,6 +29,9 _at__at_
  * _at_(#) $Header: /tcpdump/master/tcpdump/pf.h,v 1.2 2004/04/02 06:36:25 guy Exp $ (LBL)
  */
 
+/* We need offsetof() macro */
+#include <stddef.h>
+
 /*	from $OpenBSD: pfvar.h,v 1.170 2003/08/22 21:50:34 david Exp $ */
 
 enum	{ PF_INOUT=0, PF_IN=1, PF_OUT=2 };
_at__at_ -75,3 +78,23 _at__at_
 	u_int8_t	pad[3];
 };
 #define PFLOG_HDRLEN		sizeof(struct pfloghdr)
+
+/*	from $OpenBSD: if_pflog.h,v 1.14 2006/10/25 11:27:01 henning Exp $ */
+
+struct pfloghdr_v2 {
+	u_int8_t	length;
+	sa_family_t	af;
+	u_int8_t	action;
+	u_int8_t	reason;
+	char		ifname[IFNAMSIZ];
+	char		ruleset[PF_RULESET_NAME_SIZE];
+	u_int32_t	rulenr;
+	u_int32_t	subrulenr;
+	uid_t		uid;
+	pid_t		pid;
+	uid_t		rule_uid;
+	pid_t		rule_pid;
+	u_int8_t	dir;
+	u_int8_t	pad[3];
+};
+#define PFLOG_HDRV2_LEN		offsetof(struct pfloghdr_v2, pad)
--- contrib/tcpdump/print-pflog.c.orig	2007-09-24 19:10:09.000000000 +0400
+++ contrib/tcpdump/print-pflog.c	2007-09-24 20:30:36.000000000 +0400
_at__at_ -72,25 +72,43 _at__at_
 #define	OPENBSD_AF_INET		2
 #define	OPENBSD_AF_INET6	24
 
+#define __PFLOG_PRINT_HDR(hdr)						\
+do {									\
+	u_int32_t rulenr, subrulenr;					\
+									\
+	rulenr = ntohl((hdr)->rulenr);					\
+	subrulenr = ntohl((hdr)->subrulenr);				\
+	if (subrulenr == (u_int32_t)-1)					\
+		printf("rule %u/", rulenr);				\
+	else								\
+		printf("rule %u.%s.%u/", rulenr, (hdr)->ruleset,	\
+		    subrulenr);						\
+									\
+	printf("%s: %s %s on %s: ",					\
+	    tok2str(pf_reasons, "unkn(%u)", (hdr)->reason),		\
+	    tok2str(pf_actions, "unkn(%u)", (hdr)->action),		\
+	    tok2str(pf_directions, "unkn(%u)", (hdr)->dir),		\
+	    (hdr)->ifname);						\
+} while (0)
+
 static void
 pflog_print(const struct pfloghdr *hdr)
 {
-	u_int32_t rulenr, subrulenr;
+	u_int8_t hdr_version;
+	struct pfloghdr_v2 *v2hdr;
 
-	rulenr = ntohl(hdr->rulenr);
-	subrulenr = ntohl(hdr->subrulenr);
-	if (subrulenr == (u_int32_t)-1)
-		printf("rule %u/", rulenr);
-	else
-		printf("rule %u.%s.%u/", rulenr, hdr->ruleset, subrulenr);
-
-	printf("%s: %s %s on %s: ",
-	    tok2str(pf_reasons, "unkn(%u)", hdr->reason),
-	    tok2str(pf_actions, "unkn(%u)", hdr->action),
-	    tok2str(pf_directions, "unkn(%u)", hdr->dir),
-	    hdr->ifname);
+	if (hdr->length == PFLOG_HDRV2_LEN) {
+		hdr_version = 2;
+		v2hdr = (struct pfloghdr_v2 *)hdr;
+		__PFLOG_PRINT_HDR(v2hdr);
+	} else {
+		hdr_version = 1;
+		__PFLOG_PRINT_HDR(hdr);
+	}
 }
 
+#undef __PFLOG_PRINT_HDR
+
 u_int
 pflog_if_print(const struct pcap_pkthdr *h, register const u_char *p)
 {
--- tcpdump-pflog-v2.patch ends here ---
Received on Mon Sep 24 2007 - 15:35:54 UTC

This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:39:18 UTC