From 0ef00561d597e14bfd248467a2fb4e30690fcc74 Mon Sep 17 00:00:00 2001 From: luigi Date: Thu, 17 Dec 2009 23:11:16 +0000 Subject: 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. --- sys/netinet/ipfw/ip_fw2.c | 5 +-- sys/netinet/ipfw/ip_fw_log.c | 76 +++++++++++++++++++++++++++++++++++++++- 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 /* for ETHERTYPE_IP */ #include #include +#include /* for IFT_ETHER */ +#include /* for BPF */ #include #include @@ -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); -- cgit v1.1