From owner-cvs-src@FreeBSD.ORG Tue Dec 13 14:15:10 2005 Return-Path: X-Original-To: cvs-src@FreeBSD.org Delivered-To: cvs-src@FreeBSD.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 5124616A41F; Tue, 13 Dec 2005 14:15:10 +0000 (GMT) (envelope-from rizzo@icir.org) Received: from xorpc.icir.org (xorpc.icir.org [192.150.187.68]) by mx1.FreeBSD.org (Postfix) with ESMTP id 94FF643D66; Tue, 13 Dec 2005 14:15:09 +0000 (GMT) (envelope-from rizzo@icir.org) Received: from xorpc.icir.org (localhost [127.0.0.1]) by xorpc.icir.org (8.12.11/8.12.11) with ESMTP id jBDEF4rL010461; Tue, 13 Dec 2005 06:15:04 -0800 (PST) (envelope-from rizzo@xorpc.icir.org) Received: (from rizzo@localhost) by xorpc.icir.org (8.12.11/8.12.3/Submit) id jBDEF4b1010460; Tue, 13 Dec 2005 06:15:04 -0800 (PST) (envelope-from rizzo) Date: Tue, 13 Dec 2005 06:15:04 -0800 From: Luigi Rizzo To: Gleb Smirnoff Message-ID: <20051213061503.A10373@xorpc.icir.org> References: <200512131216.jBDCG3FJ042136@repoman.freebsd.org> <20051213134143.GC77985@FreeBSD.org> <20051213140744.GH37414@FreeBSD.org> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.2.5.1i In-Reply-To: <20051213140744.GH37414@FreeBSD.org>; from glebius@FreeBSD.org on Tue, Dec 13, 2005 at 05:07:44PM +0300 Cc: cvs-src@FreeBSD.org, Alexey Dokuchaev , src-committers@FreeBSD.org, cvs-all@FreeBSD.org Subject: ipfw2 logs to bpf (was Re: cvs commit: src/sbin/ipfw ipfw2.c...) X-BeenThere: cvs-src@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: CVS commit messages for the src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 13 Dec 2005 14:15:10 -0000 talking about ipfw2, a couple of years ago i posted some code for 4.x to let ipfw2 "log" packets to a pseudo interface called /dev/ipfw0 so that people in need of detailed logging could just get it from there through tcpdump or whatever. If someone is interested, here it is a copy of the message and patch. It is very very trivial, so i don't expect to require a lot of porting work to be adapted to HEAD and more recent versions of FreeBSD. cheers luigi -------------------------------------------------------- Basically, if net.inet.ip.fw.verbose=1 the log command works as usual, whereas if it is 0 you can run tcpdump -i ipfw0 ... and catch packets that would normally go to the log output. There are still some minor glitches in that "ipfw0" looks weird, i cannot figure out what am i missing in the initialization to make it look as an ethernet interface, and also what needs to be done to assign an address to it so that it works ok with things like trafshow. Suggestions welcome... cheers luigi On Mon, Sep 15, 2003 at 04:15:26AM -0700, Luigi Rizzo wrote: > having recently played a bit with largish ipfw configurations, > i would have really liked to have a more flexible logging facility > for ipfw. > > It occurred to me that one way could be to extend the ipfw2 > "log" option to optionally pass to a bpf listener a copy of the packets > selected by the ipfw rule (maybe with some tag showing the rule > they come from) so that one can run a tcpdump on that stream when > detailed analysis is required, and have essentially zero overhead in > other cases. > > What do people think ? Implementation should be almost trivial, > amounting to creating a fake struct ifnet for ipfw2 (suitably > initialized to give it a name and pretend it is up and running and > has an address assigned), calling > bpfattach() on it, and then implement an ipfw2 instruction > which always succeeds and, if there is a listener, passes > calls bpf_mtap on the mbuf. > > Does this make sense ? And, any idea on how to tag the packet with > a rule number in a way that tcpdump can filter (yes, i am looking > for dirty hacks here...) > > (and speaking of dirty hacks, of course layer3 packets can be > easily prepended with a fake MAC header which includes the matching > rule number in the ether src/dst addresses, but this trick won't > work for layer2 packets, which we do care about). > > cheers > luigi Index: netinet/ip_fw2.c =================================================================== RCS file: /home/ncvs/src/sys/netinet/ip_fw2.c,v retrieving revision 1.6.2.16 diff -u -r1.6.2.16 ip_fw2.c --- netinet/ip_fw2.c 17 Jul 2003 06:03:39 -0000 1.6.2.16 +++ netinet/ip_fw2.c 15 Sep 2003 14:49:30 -0000 @@ -55,6 +55,8 @@ #include #include #include +#include /* for IFT_ETHER */ +#include /* for BPF */ #include #include #include @@ -234,6 +236,11 @@ ip_dn_ruledel_t *ip_dn_ruledel_ptr = NULL; /* hook into dummynet */ /* + * hook to attach to bpf + */ +static struct ifnet ifn; + +/* * This macro maps an ip pointer into a layer3 header pointer of type T */ #define L3HDR(T, ip) ((T *)((u_int32_t *)(ip) + (ip)->ip_hl)) @@ -1812,6 +1819,26 @@ case O_LOG: if (fw_verbose) ipfw_log(f, hlen, args->eh, m, oif); + else if (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); + } + } match = 1; break; @@ -2767,11 +2794,29 @@ ipfw_timeout_h = timeout(ipfw_tick, NULL, dyn_keepalive_period*hz); } +static int +ipfw_ifnet_ioctl(struct ifnet *ifp, u_long cmd, caddr_t addr) +{ + return 0; /* always succeed... */ +} + static void ipfw_init(void) { struct ip_fw default_rule; +/** bpf code **/ + ifn.if_name = "ipfw"; + ifn.if_flags = IFF_UP | IFF_SIMPLEX | IFF_MULTICAST; + ifn.if_ioctl = ipfw_ifnet_ioctl; /* getaddr */ + ifn.if_type = IFT_ETHER; + ifn.if_addrlen = 6; + ifn.if_hdrlen = 14; + if_attach(&ifn); + bpfattach(&ifn, DLT_EN10MB, sizeof(struct ether_header)); + +/** end bpf code **/ + ip_fw_chk_ptr = ipfw_chk; ip_fw_ctl_ptr = ipfw_ctl; layer3_chain = NULL; @@ -2844,6 +2889,7 @@ err = EBUSY; #else s = splimp(); + ether_ifdetach(&ifn, 1 /* we want bpf */); untimeout(ipfw_tick, NULL, ipfw_timeout_h); ip_fw_chk_ptr = NULL; ip_fw_ctl_ptr = NULL; _______________________________________________ freebsd-ipfw@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/freebsd-ipfw To unsubscribe, send any mail to "freebsd-ipfw-unsubscribe@freebsd.org"