[PATCH] ipfw logging through tcpdump ?
David Horn
dhorn2000 at gmail.com
Tue Dec 15 05:55:26 UTC 2009
On Mon, Dec 14, 2009 at 6:53 PM, Luigi Rizzo <rizzo at iet.unipi.it> wrote:
> 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");
Code works well for me with latest current r200562, although a bit of
extra fuzz factor was needed for the patch to apply cleanly.
My only comment is that I would prefer a tunable or sysctl to having
to recompile with CFLAGS+= -DDEV_IPFW added to the ipfw module
Makefile.
Very useful code.
---Dave Horn
More information about the freebsd-current
mailing list