From owner-svn-src-head@FreeBSD.ORG Mon Jul 9 07:16:20 2012 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 408321065670; Mon, 9 Jul 2012 07:16:20 +0000 (UTC) (envelope-from hrs@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 29E5F8FC17; Mon, 9 Jul 2012 07:16:20 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id q697GKWb001979; Mon, 9 Jul 2012 07:16:20 GMT (envelope-from hrs@svn.freebsd.org) Received: (from hrs@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id q697GJ7A001973; Mon, 9 Jul 2012 07:16:19 GMT (envelope-from hrs@svn.freebsd.org) Message-Id: <201207090716.q697GJ7A001973@svn.freebsd.org> From: Hiroki Sato Date: Mon, 9 Jul 2012 07:16:19 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r238277 - in head: etc/defaults etc/rc.d sbin/ipfw share/man/man5 sys/netinet/ipfw X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 09 Jul 2012 07:16:20 -0000 Author: hrs Date: Mon Jul 9 07:16:19 2012 New Revision: 238277 URL: http://svn.freebsd.org/changeset/base/238277 Log: Make ipfw0 logging pseudo-interface clonable. It can be created automatically by $firewall_logif rc.conf(5) variable at boot time or manually by ifconfig(8) after a boot. Discussed on: freebsd-ipfw@ Modified: head/etc/defaults/rc.conf head/etc/rc.d/ipfw head/sbin/ipfw/ipfw.8 head/share/man/man5/rc.conf.5 head/sys/netinet/ipfw/ip_fw_log.c Modified: head/etc/defaults/rc.conf ============================================================================== --- head/etc/defaults/rc.conf Mon Jul 9 06:41:18 2012 (r238276) +++ head/etc/defaults/rc.conf Mon Jul 9 07:16:19 2012 (r238277) @@ -123,6 +123,7 @@ firewall_script="/etc/rc.firewall" # Whi firewall_type="UNKNOWN" # Firewall type (see /etc/rc.firewall) firewall_quiet="NO" # Set to YES to suppress rule display firewall_logging="NO" # Set to YES to enable events logging +firewall_logif="NO" # Set to YES to create logging-pseudo interface firewall_flags="" # Flags passed to ipfw when type is a file firewall_coscripts="" # List of executables/scripts to run after # firewall starts/stops Modified: head/etc/rc.d/ipfw ============================================================================== --- head/etc/rc.d/ipfw Mon Jul 9 06:41:18 2012 (r238276) +++ head/etc/rc.d/ipfw Mon Jul 9 07:16:19 2012 (r238277) @@ -57,6 +57,10 @@ ipfw_start() echo 'Firewall logging enabled.' sysctl net.inet.ip.fw.verbose=1 >/dev/null fi + if checkyesno firewall_logif; then + ifconfig ipfw0 create + echo 'Firewall logging pseudo-interface (ipfw0) created.' + fi } ipfw_poststart() Modified: head/sbin/ipfw/ipfw.8 ============================================================================== --- head/sbin/ipfw/ipfw.8 Mon Jul 9 06:41:18 2012 (r238276) +++ head/sbin/ipfw/ipfw.8 Mon Jul 9 07:16:19 2012 (r238277) @@ -1,7 +1,7 @@ .\" .\" $FreeBSD$ .\" -.Dd July 3, 2012 +.Dd July 9, 2012 .Dt IPFW 8 .Os .Sh NAME @@ -560,7 +560,22 @@ is set to 0 (default), one can use .Xr bpf 4 attached to the .Li ipfw0 -pseudo interface. There is no overhead if no +pseudo interface. +This pseudo interface can be created after a boot +manually by using the following command: +.Bd -literal -offset indent +# ifconfig ipfw0 create +.Ed +.Pp +Or, automatically at boot time by adding the following +line to the +.Xr rc.conf 5 +file: +.Bd -literal -offset indent +firewall_logif="YES" +.Ed +.Pp +There is no overhead if no .Xr bpf 4 is attached to the pseudo interface. .Pp Modified: head/share/man/man5/rc.conf.5 ============================================================================== --- head/share/man/man5/rc.conf.5 Mon Jul 9 06:41:18 2012 (r238276) +++ head/share/man/man5/rc.conf.5 Mon Jul 9 07:16:19 2012 (r238277) @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd May 6, 2012 +.Dd July 9, 2012 .Dt RC.CONF 5 .Os .Sh NAME @@ -501,6 +501,16 @@ to enable firewall event logging. This is equivalent to the .Dv IPFIREWALL_VERBOSE kernel option. +.It Va firewall_logif +.Pq Vt bool +Set to +.Dq Li YES +to create pseudo interface +.Li ipfw0 +for logging. +For more details, see +.Xr ipfw 8 +manual page. .It Va firewall_flags .Pq Vt str Flags passed to Modified: head/sys/netinet/ipfw/ip_fw_log.c ============================================================================== --- head/sys/netinet/ipfw/ip_fw_log.c Mon Jul 9 06:41:18 2012 (r238276) +++ head/sys/netinet/ipfw/ip_fw_log.c Mon Jul 9 07:16:19 2012 (r238277) @@ -44,8 +44,11 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include +#include #include /* for ETHERTYPE_IP */ #include +#include #include #include /* for IFT_ETHER */ #include /* for BPF */ @@ -90,6 +93,15 @@ ipfw_log_bpf(int onoff) } #else /* !WITHOUT_BPF */ static struct ifnet *log_if; /* hook to attach to bpf */ +static struct rwlock log_if_lock; +#define LOGIF_LOCK_INIT(x) rw_init(&log_if_lock, "ipfw log_if lock") +#define LOGIF_LOCK_DESTROY(x) rw_destroy(&log_if_lock) +#define LOGIF_RLOCK(x) rw_rlock(&log_if_lock) +#define LOGIF_RUNLOCK(x) rw_runlock(&log_if_lock) +#define LOGIF_WLOCK(x) rw_wlock(&log_if_lock) +#define LOGIF_WUNLOCK(x) rw_wunlock(&log_if_lock) + +#define IPFWNAME "ipfw" /* we use this dummy function for all ifnet callbacks */ static int @@ -116,37 +128,105 @@ ipfw_log_start(struct ifnet* ifp) static const u_char ipfwbroadcastaddr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; +static int +ipfw_log_clone_match(struct if_clone *ifc, const char *name) +{ + + return (strncmp(name, IPFWNAME, sizeof(IPFWNAME) - 1) == 0); +} + +static int +ipfw_log_clone_create(struct if_clone *ifc, char *name, size_t len, + caddr_t params) +{ + int error; + int unit; + struct ifnet *ifp; + + error = ifc_name2unit(name, &unit); + if (error) + return (error); + + error = ifc_alloc_unit(ifc, &unit); + if (error) + return (error); + + ifp = if_alloc(IFT_ETHER); + if (ifp == NULL) { + ifc_free_unit(ifc, unit); + return (ENOSPC); + } + ifp->if_dname = IPFWNAME; + ifp->if_dunit = unit; + snprintf(ifp->if_xname, IFNAMSIZ, "%s%d", IPFWNAME, unit); + strlcpy(name, ifp->if_xname, len); + 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(); + if (log_if == NULL) + log_if = ifp; + else { + LOGIF_WUNLOCK(); + if_free(ifp); + ifc_free_unit(ifc, unit); + return (EEXIST); + } + LOGIF_WUNLOCK(); + if_attach(ifp); + bpfattach(ifp, DLT_EN10MB, 14); + + return (0); +} + +static int +ipfw_log_clone_destroy(struct if_clone *ifc, struct ifnet *ifp) +{ + int unit; + + if (ifp == NULL) + return (0); + + LOGIF_WLOCK(); + if (log_if != NULL && ifp == log_if) + log_if = NULL; + else { + LOGIF_WUNLOCK(); + return (EINVAL); + } + LOGIF_WUNLOCK(); + + unit = ifp->if_dunit; + bpfdetach(ifp); + if_detach(ifp); + if_free(ifp); + ifc_free_unit(ifc, unit); + + return (0); +} + +static struct if_clone ipfw_log_cloner = IFC_CLONE_INITIALIZER( + IPFWNAME, NULL, IF_MAXUNIT, + NULL, ipfw_log_clone_match, ipfw_log_clone_create, ipfw_log_clone_destroy); + 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 = ipfw_log_start; - ifp->if_output = ipfw_log_output; - ifp->if_addrlen = 6; - ifp->if_hdrlen = 14; - if_attach(ifp); - ifp->if_broadcastaddr = ipfwbroadcastaddr; - ifp->if_baudrate = IF_Mbps(10); - bpfattach(ifp, DLT_EN10MB, 14); - log_if = ifp; + LOGIF_LOCK_INIT(); + if_clone_attach(&ipfw_log_cloner); } else { - if (log_if) { - ether_ifdetach(log_if); - if_free(log_if); - } - log_if = NULL; + if_clone_detach(&ipfw_log_cloner); + LOGIF_LOCK_DESTROY(); } } #endif /* !WITHOUT_BPF */ @@ -166,9 +246,11 @@ ipfw_log(struct ip_fw *f, u_int hlen, st if (V_fw_verbose == 0) { #ifndef WITHOUT_BPF - - if (log_if == NULL || log_if->if_bpf == NULL) + LOGIF_RLOCK(); + if (log_if == NULL || log_if->if_bpf == NULL) { + LOGIF_RUNLOCK(); return; + } if (args->eh) /* layer2, use orig hdr */ BPF_MTAP2(log_if, args->eh, ETHER_HDR_LEN, m); @@ -177,6 +259,7 @@ ipfw_log(struct ip_fw *f, u_int hlen, st * more info in the header. */ BPF_MTAP2(log_if, "DDDDDDSSSSSS\x08\x00", ETHER_HDR_LEN, m); + LOGIF_RUNLOCK(); #endif /* !WITHOUT_BPF */ return; }