Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 15 Dec 2009 00:53:07 +0100
From:      Luigi Rizzo <rizzo@iet.unipi.it>
To:        current@freebsd.org
Subject:   [PATCH] ipfw logging through tcpdump ?
Message-ID:  <20091214235307.GA5345@onelab2.iet.unipi.it>

next in thread | raw e-mail | index | archive | help
The following ipfw patch (which i wrote back in 2001/2002) makes
ipfw logging possible through tcpdump -- it works by passing to the
fake device 'ipfw0' all packets matching rules marked 'log' .
The use is very simple -- to test it just do

	ipfw add 100 count log ip from any to any

and then

	tcpdump -ni ipfw0

will show all matching traffic.

I think this is a quite convenient and flexible option, so if there
are no objections I plan to commit it to head.

	cheers
	luigi

Index: ../head/sys/netinet/ipfw/ip_fw2.c
===================================================================
--- ../head/sys/netinet/ipfw/ip_fw2.c	(revision 200551)
+++ ../head/sys/netinet/ipfw/ip_fw2.c	(working copy)
@@ -65,6 +65,8 @@
 #include <sys/ucred.h>
 #include <net/ethernet.h> /* for ETHERTYPE_IP */
 #include <net/if.h>
+#include <net/if_types.h>	/* for IFT_ETHER */
+#include <net/bpf.h>		/* for BPF */
 #include <net/radix.h>
 #include <net/route.h>
 #include <net/pf_mtag.h>
@@ -338,6 +340,15 @@
     "Enable keepalives for dyn. rules");
 #endif /* SYSCTL_NODE */
 
+#ifdef DEV_IPFW
+static struct ifnet *ifn;	/* hook to attach to bpf */
+static int
+ipfw_ifnet_ioctl(struct ifnet *ifp, u_long cmd, caddr_t addr)
+{
+	return EINVAL;
+}
+#endif
+
 /*
  * L3HDR maps an ipv4 pointer into a layer3 header pointer of type T
  * Other macros just cast void * into the appropriate type
@@ -3056,6 +3067,29 @@
 				if (V_fw_verbose)
 					ipfw_log(f, hlen, args, m,
 					    oif, offset, tablearg, ip);
+#ifdef DEV_IPFW
+				else if (ifn && ifn->if_bpf != NULL) {
+				    /* This kludge is OK; BPF treats
+				     *the "mbuf" as read-only */
+				    struct m_hdr mh;
+				    mh.mh_next = m;
+				    mh.mh_len = ETHER_HDR_LEN;
+				    if (args->eh)       /* layer2, complete */
+					mh.mh_data = (char *)args->eh;
+				    else {
+					/* fake header and restore wire format*/
+					mh.mh_data = "DDDDDDSSSSSS\x08\x00";
+					ip->ip_off = ntohs(ip->ip_off);
+					ip->ip_len = ntohs(ip->ip_len);
+				    }
+				    BPF_MTAP(ifn, (struct mbuf *)&mh);
+				    if (args->eh == NULL) {
+					/* restore IP format */
+					ip->ip_off = htons(ip->ip_off);
+					ip->ip_len = htons(ip->ip_len);
+				    }
+				}
+#endif /* DEV_IPFW */
 				match = 1;
 				break;
 
@@ -4830,6 +4864,19 @@
 		printf("limited to %d packets/entry by default\n",
 		    V_verbose_limit);
 
+#ifdef DEV_IPFW	/** bpf code **/
+	ifn = if_alloc(IFT_ETHER);
+	if_initname(ifn, "ipfw", 0);
+	ifn->if_mtu = 65536;
+	ifn->if_flags = IFF_UP | IFF_SIMPLEX | IFF_MULTICAST;
+	ifn->if_ioctl = ipfw_ifnet_ioctl;        /* getaddr */
+	ifn->if_addrlen = 6;
+	ifn->if_hdrlen = 14;
+	if_attach(ifn);
+	ifn->if_baudrate = IF_Mbps(10);
+	bpfattach(ifn, DLT_EN10MB, 14);
+#endif	/** end bpf code **/
+
 	return (error);
 }
 
@@ -4840,6 +4887,11 @@
 ipfw_destroy(void)
 {
 
+#ifdef DEV_IPFW
+	ether_ifdetach(ifn);
+	if_free(ifn);
+	ifn = NULL;
+#endif
 	uma_zdestroy(ipfw_dyn_rule_zone);
 	IPFW_DYN_LOCK_DESTROY();
 	printf("IP firewall unloaded\n");



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20091214235307.GA5345>