Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 23 Sep 2003 11:31:26 -0700
From:      Luigi Rizzo <rizzo@icir.org>
To:        Matthew George <mdg@secureworks.net>
Cc:        Uwe Klann <u.klann@t-online.de>
Subject:   Re: IPFW2
Message-ID:  <20030923113126.A24717@xorpc.icir.org>
In-Reply-To: <20030923122509.S87821@localhost>; from mdg@secureworks.net on Tue, Sep 23, 2003 at 12:28:07PM -0400
References:  <LIEAKECJDNPINKLJPFODIEPGDHAA.u.klann@t-online.de> <20030922134531.A44366@xorpc.icir.org> <20030923122509.S87821@localhost>

next in thread | previous in thread | raw e-mail | index | archive | help
On Tue, Sep 23, 2003 at 12:28:07PM -0400, Matthew George wrote:
...
> > you can count the traffic with dynamic rules (but this does not go
> > to the logfile), not sure what you mean by 'see the transfered data file'
> 
> from ipf(5):
> 
> LOGGING
>        When a packet is logged, with either the  log  action  or  option, the
>        headers  of  the  packet  are written to the ipl packet logging psuedo-
>        device. Immediately following the log keyword, the following qualifiers
>        may be used (in order):
> 
>        body   indicates  that  the first 128 bytes of the packet contents will
>               be logged after the headers.
> 
> I don't believe there is a comparable ipfw option ...

no, there isn't. However the attached patch lets you run any bpf-based
application on the packets which match an ipfw rule with 'log'
specifier when net.inet.ip.fw.verbose=0, thus achieving a very similar
if not a lot more powerful effect. Just use

	sysctl net.inet.ip.fw.verbose=0
	ipfw add count log ...

	tcpdump -i ipfw0 ...

cheers
luigi

Index: sys/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
--- sys/netinet/ip_fw2.c	17 Jul 2003 06:03:39 -0000	1.6.2.16
+++ sys/netinet/ip_fw2.c	22 Sep 2003 22:21:38 -0000
@@ -51,10 +51,12 @@
 #include <sys/proc.h>
 #include <sys/socket.h>
 #include <sys/socketvar.h>
+#include <sys/sockio.h>		/* for SIOC* */
 #include <sys/sysctl.h>
 #include <sys/syslog.h>
 #include <sys/ucred.h>
 #include <net/if.h>
+#include <net/bpf.h>	/* for BPF */
 #include <net/route.h>
 #include <netinet/in.h>
 #include <netinet/in_systm.h>
@@ -225,9 +227,14 @@
     &dyn_short_lifetime, 0, "Lifetime of dyn. rules for other situations");
 SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, dyn_keepalive, CTLFLAG_RW,
     &dyn_keepalive, 0, "Enable keepalives for dyn. rules");
+static int fw_bpf_info = 1;
+SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, bpf_info,
+    CTLFLAG_RW,
+    &fw_bpf_info, 0, "Add info in mac hdr");
 
 #endif /* SYSCTL_NODE */
 
+static struct ifnet ifn;	/* dummy ifnet to attach to bpf */
 
 static ip_fw_chk_t	ipfw_chk;
 
@@ -1812,6 +1819,44 @@
 			case O_LOG:
 				if (fw_verbose)
 					ipfw_log(f, hlen, args->eh, m, oif);
+				else if (ifn.if_bpf != NULL) {
+				    /*
+				     * Prepend a (readonly) header, fill it
+				     * with the real MAC header, or a dummy
+				     * one if not available. In this case
+				     * (layer3 packets) also restore the
+				     * byte ordering of some fields, and put
+				     * them back after bpf_mtap.
+				     * If requested, the first two bytes
+				     * of the src mac are replaced by the
+				     * rule number for userland filtering.
+				     */
+				    struct m_hdr mh;
+				    struct ether_header my_eh;
+				    char *h;
+
+				    mh.mh_next = m;
+				    mh.mh_len = ETHER_HDR_LEN;
+				    mh.mh_data = (char *)&my_eh;
+				    if (args->eh)	/* layer2, complete */
+					h = (char *)args->eh;
+				    else {
+					h = "DDDDDDSSSSSS\x08\x00";
+					ip->ip_off = ntohs(ip->ip_off);
+					ip->ip_len = ntohs(ip->ip_len);
+				    }
+				    bcopy(h, &my_eh, ETHER_HDR_LEN);
+				    if (fw_bpf_info) {
+					mh.mh_data[0] = f->rulenum >> 8;
+					mh.mh_data[1] = f->rulenum & 0xff;
+				    }
+				    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 +2833,34 @@
 	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)
+{
+	int error = 0;
+
+	switch (cmd) {
+	default:
+		error = EINVAL;
+		break;
+
+	case SIOCSIFADDR:
+	case SIOCGIFADDR:
+	case SIOCSIFFLAGS:
+		break;
+	}
+	return error;
+}
+
 static void
 ipfw_init(void)
 {
 	struct ip_fw default_rule;
 
+	ifn.if_name = "ipfw";
+	ifn.if_flags = IFF_UP | IFF_SIMPLEX | IFF_MULTICAST;
+	ifn.if_ioctl = ipfw_ifnet_ioctl;	/* getaddr */
+	ether_ifattach(&ifn, ETHER_BPF_SUPPORTED);
+
 	ip_fw_chk_ptr = ipfw_chk;
 	ip_fw_ctl_ptr = ipfw_ctl;
 	layer3_chain = NULL;
@@ -2844,6 +2933,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;



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