[PATCH] ipfw logging through tcpdump ?
Luigi Rizzo
rizzo at iet.unipi.it
Mon Dec 14 23:45:44 UTC 2009
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");
More information about the freebsd-current
mailing list