From: Bill Yuan Date: Thu, 17 Dec 2015 09:06:54 +0000 (+0000) Subject: ipfw3: logging feature X-Git-Tag: v4.6.0rc~1173 X-Git-Url: https://gitweb.dragonflybsd.org/~tuxillo/dragonfly.git/commitdiff_plain/1f750495e03e0d6ed31468936cafed567c175671 ipfw3: logging feature ifconfig ipfw0 create ipfw3 add allow log 0 icmp support max=9 pseudo ipfw interfaces. the logged packets header will be 0x41 & 0x42. the logged frames can keep the original MAC. --- diff --git a/sbin/ipfw3/ipfw3.c b/sbin/ipfw3/ipfw3.c index cad8f5d0e6..8271e7f069 100644 --- a/sbin/ipfw3/ipfw3.c +++ b/sbin/ipfw3/ipfw3.c @@ -287,6 +287,14 @@ parse_accept(ipfw_insn **cmd, int *ac, char **av[]) (*cmd)->module = MODULE_BASIC_ID; (*cmd)->len = (*cmd)->len|LEN_OF_IPFWINSN; NEXT_ARG1; + if (!strncmp(**av, "log", strlen(**av))) { + (*cmd)->arg3 = 1; + NEXT_ARG1; + if (isdigit(***av)) { + (*cmd)->arg1 = strtoul(**av, NULL, 10); + NEXT_ARG1; + } + } } void @@ -296,18 +304,32 @@ parse_deny(ipfw_insn **cmd, int *ac, char **av[]) (*cmd)->module = MODULE_BASIC_ID; (*cmd)->len = (*cmd)->len|LEN_OF_IPFWINSN; NEXT_ARG1; + if (!strncmp(**av, "log", strlen(**av))) { + (*cmd)->arg3 = 1; + NEXT_ARG1; + if (isdigit(***av)) { + (*cmd)->arg1 = strtoul(**av, NULL, 10); + NEXT_ARG1; + } + } } void show_accept(ipfw_insn *cmd, int show_or) { printf(" allow"); + if (cmd->arg3) { + printf(" log %d", cmd->arg1); + } } void show_deny(ipfw_insn *cmd, int show_or) { printf(" deny"); + if (cmd->arg3) { + printf(" log %d", cmd->arg1); + } } static void diff --git a/sys/net/ipfw3/Makefile b/sys/net/ipfw3/Makefile index daa08e7cb7..b3503d84bf 100644 --- a/sys/net/ipfw3/Makefile +++ b/sys/net/ipfw3/Makefile @@ -3,6 +3,7 @@ KMOD= ipfw3 SRCS= ip_fw3.c +SRCS+= ip_fw3_log.c ip_fw3_log.h SRCS+= ip_fw3_table.c ip_fw3_table.h SRCS+= opt_ipfw.h opt_inet.h @@ -17,7 +18,6 @@ opt_ipfw.h: # # If you want it verbose #echo '#define IPFIREWALL_VERBOSE 1' >> ${.OBJDIR}/${.TARGET} - #echo '#define IPFIREWALL_VERBOSE_LIMIT 100' >> ${.OBJDIR}/${.TARGET} # # If you want it to pass all packets by default #echo '#define IPFIREWALL_DEFAULT_TO_ACCEPT 1' >> ${.OBJDIR}/${.TARGET} diff --git a/sys/net/ipfw3/ip_fw3.c b/sys/net/ipfw3/ip_fw3.c index 0772b8df39..c48db199a5 100644 --- a/sys/net/ipfw3/ip_fw3.c +++ b/sys/net/ipfw3/ip_fw3.c @@ -81,6 +81,7 @@ #include #include +#include #include #include #include @@ -149,8 +150,7 @@ extern int ip_fw_loaded; static uint32_t static_count; /* # of static rules */ static uint32_t static_ioc_len; /* bytes of static rules */ static int ipfw_flushing; -static int fw_verbose; -static int verbose_limit; +static int fw_verbose = 0; static int fw_debug; static int autoinc_step = IPFW_AUTOINC_STEP_DEF; @@ -170,8 +170,6 @@ SYSCTL_INT(_net_inet_ip_fw3, OID_AUTO, debug, CTLFLAG_RW, &fw_debug, 0, "Enable printing of debug ip_fw statements"); SYSCTL_INT(_net_inet_ip_fw3, OID_AUTO, verbose, CTLFLAG_RW, &fw_verbose, 0, "Log matches to ipfw rules"); -SYSCTL_INT(_net_inet_ip_fw3, OID_AUTO, verbose_limit, CTLFLAG_RW, - &verbose_limit, 0, "Set upper limit of matches of ipfw rules logged"); SYSCTL_INT(_net_inet_ip_fw3, OID_AUTO, static_count, CTLFLAG_RD, &static_count, 0, "Number of static rules"); @@ -272,6 +270,9 @@ check_accept(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, { *cmd_val = IP_FW_PASS; *cmd_ctl = IP_FW_CTL_DONE; + if (cmd->arg3) { + ipfw_log((*args)->m, (*args)->eh, cmd->arg1); + } } void @@ -280,6 +281,9 @@ check_deny(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, { *cmd_val = IP_FW_DENY; *cmd_ctl = IP_FW_CTL_DONE; + if (cmd->arg3) { + ipfw_log((*args)->m, (*args)->eh, cmd->arg1); + } } void @@ -2025,17 +2029,9 @@ ipfw_init_dispatch(netmsg_t nmsg) #ifdef IPFIREWALL_VERBOSE fw_verbose = 1; -#endif -#ifdef IPFIREWALL_VERBOSE_LIMIT - verbose_limit = IPFIREWALL_VERBOSE_LIMIT; #endif if (fw_verbose == 0) { kprintf("disabled "); - } else if (verbose_limit == 0) { - kprintf("unlimited "); - } else { - kprintf("limited to %d packets/entry by default ", - verbose_limit); } kprintf("\n"); ip_fw3_loaded = 1; @@ -2051,6 +2047,7 @@ ipfw3_init(void) struct netmsg_base smsg; int error; + ipfw3_log_modevent(MOD_LOAD); init_module(); netmsg_init(&smsg, NULL, &curthread->td_msgport, 0, ipfw_init_dispatch); @@ -2095,6 +2092,8 @@ static int ipfw3_fini(void) { struct netmsg_base smsg; + + ipfw3_log_modevent(MOD_UNLOAD); netmsg_init(&smsg, NULL, &curthread->td_msgport, 0, ipfw_fini_dispatch); return lwkt_domsg(IPFW_CFGPORT, &smsg.lmsg, 0); diff --git a/sys/net/ipfw3/ip_fw3_log.c b/sys/net/ipfw3/ip_fw3_log.c new file mode 100644 index 0000000000..d7bc46b289 --- /dev/null +++ b/sys/net/ipfw3/ip_fw3_log.c @@ -0,0 +1,264 @@ +/* + * Copyright (c) 2002-2009 Luigi Rizzo, Universita` di Pisa + * + * Copyright (c) 2015 The DragonFly Project. All rights reserved. + * + * This code is derived from software contributed to The DragonFly Project + * by Bill Yuan + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name of The DragonFly Project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific, prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "opt_inet.h" +#ifndef INET +#error IPFIREWALL3 requires INET. +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* for ETHERTYPE_IP */ +#include +#include +#include +#include +#include /* for IFT_PFLOG */ +#include /* for BPF */ + +#include +#include +#include +#include +#include +#include + +#ifdef INET6 +#include +#include +#include /* ip6_sprintf() */ +#endif + +#include +#include + +extern int fw_verbose; +extern struct if_clone *if_clone_lookup(const char *, int *); + +static const char ipfw_log_ifname[] = "ipfw"; +static int log_if_count; +struct ifnet *log_if_table[LOG_IF_MAX]; +struct lock log_if_lock; + + +u_char fake_eh[14] = {0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x08, 0x00}; + +static const u_char ipfwbroadcastaddr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + +#define LOGIF_LOCK_INIT(x) lockinit(&log_if_lock, "fw3log_lk", 0, LK_CANRECURSE) +#define LOGIF_LOCK_DESTROY(x) lockuninit(&log_if_lock) +#define LOGIF_RLOCK(x) lockmgr(&log_if_lock, LK_SHARED) +#define LOGIF_RUNLOCK(x) lockmgr(&log_if_lock, LK_RELEASE) +#define LOGIF_WLOCK(x) lockmgr(&log_if_lock, LK_EXCLUSIVE) +#define LOGIF_WUNLOCK(x) lockmgr(&log_if_lock, LK_RELEASE) + + +/* we use this dummy function for all ifnet callbacks */ +static int +log_dummy(struct ifnet *ifp, u_long cmd, caddr_t addr, struct ucred *uc) +{ + return EINVAL; +} + +static int +ipfw_log_output(struct ifnet *ifp, struct mbuf *m, + struct sockaddr *dst, struct rtentry *rtent) +{ + if (m != NULL) { + m_freem(m); + } + return EINVAL; +} + +static void +ipfw_log_start(struct ifnet* ifp, struct ifaltq_subque *subque) +{ +} + +/* + * bpf_mtap into the ipfw interface. + * eh == NULL when mbuf is a packet, then use the fake_eh + * the ip_len need to be twisted before and after bpf copy. + */ +void +ipfw_log(struct mbuf *m, struct ether_header *eh, uint16_t id) +{ + struct ifnet *the_if = NULL; + + if (fw_verbose) { +#ifndef WITHOUT_BPF + LOGIF_RLOCK(); + the_if = log_if_table[id]; + if (the_if == NULL || the_if->if_bpf == NULL) { + LOGIF_RUNLOCK(); + return; + } + if (eh != NULL) { + bpf_gettoken(); + bpf_mtap_hdr(the_if->if_bpf, (caddr_t)eh, + ETHER_HDR_LEN, m, 0); + bpf_reltoken(); + + } else { + struct ip *ip; + ip = mtod(m, struct ip *); + /* twist the ip_len for the bpf copy */ + ip->ip_len =htons(ip->ip_len); + + bpf_gettoken(); + bpf_mtap_hdr(the_if->if_bpf, (caddr_t)fake_eh, + ETHER_HDR_LEN, m, 0); + bpf_reltoken(); + ip->ip_len =ntohs(ip->ip_len); + + } + LOGIF_RUNLOCK(); +#endif /* !WITHOUT_BPF */ + } +} + +static int +ipfw_log_clone_create(struct if_clone *ifc, int unit, caddr_t param __unused) +{ + struct ifnet *ifp; + + if (unit < 0 || unit >= LOG_IF_MAX) { + return EINVAL; + } + if (log_if_table[unit] != NULL) { + return EINVAL; + } + + ifp = if_alloc(IFT_PFLOG); + if_initname(ifp, ipfw_log_ifname, unit); + ifq_set_maxlen(&ifp->if_snd, ifqmaxlen); + ifq_set_ready(&ifp->if_snd); + + 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 = ipfw_log_start; + ifp->if_output = ipfw_log_output; + ifp->if_addrlen = 6; + ifp->if_hdrlen = 14; + ifp->if_broadcastaddr = ipfwbroadcastaddr; + ifp->if_baudrate = IF_Mbps(10); + + LOGIF_WLOCK(); + log_if_table[unit] = ifp; + log_if_count++; + if_attach(ifp, NULL); + bpfattach(ifp, DLT_EN10MB, ETHER_HDR_LEN); + LOGIF_WUNLOCK(); + + return (0); +} + +static int +ipfw_log_clone_destroy(struct ifnet *ifp) +{ + int unit; + + if (ifp == NULL) + return (0); + + unit = ifp->if_dunit; + if (unit < 0 || unit >= LOG_IF_MAX) { + return EINVAL; + } + if (log_if_table[unit] == NULL) { + return EINVAL; + } + LOGIF_WLOCK(); + log_if_table[unit] = NULL; + bpfdetach(ifp); + if_detach(ifp); + if_free(ifp); + log_if_count--; + LOGIF_WUNLOCK(); + + return (0); +} + +static eventhandler_tag ipfw_log_ifdetach_cookie; +static struct if_clone ipfw_log_cloner = IF_CLONE_INITIALIZER(ipfw_log_ifname, + ipfw_log_clone_create, ipfw_log_clone_destroy, 0, 9); + + +void ipfw3_log_modevent(int type){ + struct ifnet *tmpif; + int i; + + switch (type) { + case MOD_LOAD: + LOGIF_LOCK_INIT(); + log_if_count = 0; + if_clone_attach(&ipfw_log_cloner); + ipfw_log_ifdetach_cookie = + EVENTHANDLER_REGISTER(ifnet_detach_event, + ipfw_log_clone_destroy, &ipfw_log_cloner, + EVENTHANDLER_PRI_ANY); + break; + case MOD_UNLOAD: + EVENTHANDLER_DEREGISTER(ifnet_detach_event, + ipfw_log_ifdetach_cookie); + if_clone_detach(&ipfw_log_cloner); + for(i = 0; log_if_count > 0 && i < LOG_IF_MAX; i++){ + tmpif = log_if_table[i]; + if (tmpif != NULL) { + ipfw_log_clone_destroy(tmpif); + } + } + LOGIF_LOCK_DESTROY(); + break; + + default: + break; + } +} + +/* end of file */ diff --git a/sys/net/ipfw3/ip_fw3_log.h b/sys/net/ipfw3/ip_fw3_log.h new file mode 100644 index 0000000000..d7f62277cf --- /dev/null +++ b/sys/net/ipfw3/ip_fw3_log.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2002-2009 Luigi Rizzo, Universita` di Pisa + * + * Copyright (c) 2015 The DragonFly Project. All rights reserved. + * + * This code is derived from software contributed to The DragonFly Project + * by Bill Yuan + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name of The DragonFly Project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific, prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#ifndef _IP_FW3_LOG_H_ +#define _IP_FW3_LOG_H_ + +#define LOG_IF_MAX 10 + +void ipfw3_log_modevent(int type); + +void +ipfw_log(struct mbuf *m, struct ether_header *eh, uint16_t id); + +#endif