From owner-freebsd-current@FreeBSD.ORG Mon Dec 14 23:45:44 2009 Return-Path: Delivered-To: current@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 38B401065676 for ; Mon, 14 Dec 2009 23:45:44 +0000 (UTC) (envelope-from luigi@onelab2.iet.unipi.it) Received: from onelab2.iet.unipi.it (onelab2.iet.unipi.it [131.114.59.238]) by mx1.freebsd.org (Postfix) with ESMTP id 027658FC15 for ; Mon, 14 Dec 2009 23:45:43 +0000 (UTC) Received: by onelab2.iet.unipi.it (Postfix, from userid 275) id 0D4F973098; Tue, 15 Dec 2009 00:53:07 +0100 (CET) Date: Tue, 15 Dec 2009 00:53:07 +0100 From: Luigi Rizzo To: current@freebsd.org Message-ID: <20091214235307.GA5345@onelab2.iet.unipi.it> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.4.2.3i Cc: Subject: [PATCH] ipfw logging through tcpdump ? X-BeenThere: freebsd-current@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Discussions about the use of FreeBSD-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 14 Dec 2009 23:45:44 -0000 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 #include /* for ETHERTYPE_IP */ #include +#include /* for IFT_ETHER */ +#include /* for BPF */ #include #include #include @@ -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");