IPFW2
Luigi Rizzo
rizzo at icir.org
Tue Sep 23 11:31:30 PDT 2003
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;
More information about the freebsd-hackers
mailing list