diff options
author | luigi <luigi@FreeBSD.org> | 2009-12-17 23:11:16 +0000 |
---|---|---|
committer | luigi <luigi@FreeBSD.org> | 2009-12-17 23:11:16 +0000 |
commit | 0ef00561d597e14bfd248467a2fb4e30690fcc74 (patch) | |
tree | 6138ef33bddec38839d5b696e107c3a19c5ee436 | |
parent | 6710b5f1158d9772396ba4f7e6f664bb6aa04c7b (diff) | |
download | FreeBSD-src-0ef00561d597e14bfd248467a2fb4e30690fcc74.zip FreeBSD-src-0ef00561d597e14bfd248467a2fb4e30690fcc74.tar.gz |
Add some experimental code to log traffic with tcpdump,
similar to pflog(4).
To use the feature, just put the 'log' options on rules
you are interested in, e.g.
ipfw add 5000 count log ....
and run
tcpdump -ni ipfw0 ...
net.inet.ip.fw.verbose=0 enables logging to ipfw0,
net.inet.ip.fw.verbose=1 sends logging to syslog as before.
More features can be added, similar to pflog(), to store in
the MAC header metadata such as rule numbers and actions.
Manpage to come once features are settled.
-rw-r--r-- | sys/netinet/ipfw/ip_fw2.c | 5 | ||||
-rw-r--r-- | sys/netinet/ipfw/ip_fw_log.c | 76 | ||||
-rw-r--r-- | sys/netinet/ipfw/ip_fw_private.h | 1 |
3 files changed, 79 insertions, 3 deletions
diff --git a/sys/netinet/ipfw/ip_fw2.c b/sys/netinet/ipfw/ip_fw2.c index df0af0e..32cd548 100644 --- a/sys/netinet/ipfw/ip_fw2.c +++ b/sys/netinet/ipfw/ip_fw2.c @@ -1651,8 +1651,7 @@ do { \ } case O_LOG: - if (V_fw_verbose) - ipfw_log(f, hlen, args, m, + ipfw_log(f, hlen, args, m, oif, offset, tablearg, ip); match = 1; break; @@ -2287,6 +2286,7 @@ ipfw_init(void) printf("limited to %d packets/entry by default\n", V_verbose_limit); + ipfw_log_bpf(1); /* init */ return (error); } @@ -2297,6 +2297,7 @@ static void ipfw_destroy(void) { + ipfw_log_bpf(0); /* uninit */ ipfw_dyn_detach(); printf("IP firewall unloaded\n"); } diff --git a/sys/netinet/ipfw/ip_fw_log.c b/sys/netinet/ipfw/ip_fw_log.c index 5e566fd..cd404d4 100644 --- a/sys/netinet/ipfw/ip_fw_log.c +++ b/sys/netinet/ipfw/ip_fw_log.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2002 Luigi Rizzo, Universita` di Pisa + * Copyright (c) 2002-2009 Luigi Rizzo, Universita` di Pisa * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -55,6 +55,8 @@ __FBSDID("$FreeBSD$"); #include <net/ethernet.h> /* for ETHERTYPE_IP */ #include <net/if.h> #include <net/vnet.h> +#include <net/if_types.h> /* for IFT_ETHER */ +#include <net/bpf.h> /* for BPF */ #include <netinet/in.h> #include <netinet/ip.h> @@ -88,6 +90,48 @@ __FBSDID("$FreeBSD$"); #define SNPARGS(buf, len) buf + len, sizeof(buf) > len ? sizeof(buf) - len : 0 #define SNP(buf) buf, sizeof(buf) +static struct ifnet *log_if; /* hook to attach to bpf */ + +/* we use this dummy function for all ifnet callbacks */ +static int +log_dummy(struct ifnet *ifp, u_long cmd, caddr_t addr) +{ + return EINVAL; +} + +void +ipfw_log_bpf(int onoff) +{ + struct ifnet *ifp; + + if (onoff) { + if (log_if) + return; + ifp = if_alloc(IFT_ETHER); + if (ifp == NULL) + return; + if_initname(ifp, "ipfw", 0); + ifp->if_mtu = 65536; + ifp->if_flags = IFF_UP | IFF_SIMPLEX | IFF_MULTICAST; + ifp->if_init = (void *)log_dummy; + ifp->if_ioctl = log_dummy; + ifp->if_start = (void *)log_dummy; + ifp->if_output = (void *)log_dummy; + ifp->if_addrlen = 6; + ifp->if_hdrlen = 14; + if_attach(ifp); + ifp->if_baudrate = IF_Mbps(10); + bpfattach(ifp, DLT_EN10MB, 14); + log_if = ifp; + } else { + if (log_if) { + ether_ifdetach(log_if); + if_free(log_if); + } + log_if = NULL; + } +} + /* * We enter here when we have a rule with O_LOG. * XXX this function alone takes about 2Kbytes of code! @@ -102,6 +146,36 @@ ipfw_log(struct ip_fw *f, u_int hlen, struct ip_fw_args *args, int limit_reached = 0; char action2[40], proto[128], fragment[32]; + if (V_fw_verbose == 0) { + struct m_hdr mh; + + if (log_if == NULL || log_if->if_bpf == NULL) + return; + /* BPF treats the "mbuf" as read-only */ + mh.mh_next = m; + mh.mh_len = ETHER_HDR_LEN; + if (args->eh) { /* layer2, use orig hdr */ + mh.mh_data = (char *)args->eh; + } else { + /* add fake header. Later we will store + * more info in the header + */ + mh.mh_data = "DDDDDDSSSSSS\x08\x00"; + if (args->f_id.addr_type == 4) { + /* restore wire format */ + ip->ip_off = ntohs(ip->ip_off); + ip->ip_len = ntohs(ip->ip_len); + } + } + BPF_MTAP(log_if, (struct mbuf *)&mh); + if (args->eh == NULL && args->f_id.addr_type == 4) { + /* restore host format */ + ip->ip_off = htons(ip->ip_off); + ip->ip_len = htons(ip->ip_len); + } + return; + } + /* the old 'log' function */ fragment[0] = '\0'; proto[0] = '\0'; diff --git a/sys/netinet/ipfw/ip_fw_private.h b/sys/netinet/ipfw/ip_fw_private.h index 8253d8d..095de66 100644 --- a/sys/netinet/ipfw/ip_fw_private.h +++ b/sys/netinet/ipfw/ip_fw_private.h @@ -113,6 +113,7 @@ void ipfw_nat_destroy(void); /* In ip_fw_log.c */ struct ip; +void ipfw_log_bpf(int); void ipfw_log(struct ip_fw *f, u_int hlen, struct ip_fw_args *args, struct mbuf *m, struct ifnet *oif, u_short offset, uint32_t tablearg, struct ip *ip); |