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 <sys/socket.h>
 #include <sys/sysctl.h>
 #include <sys/syslog.h>
+#include <sys/lock.h>
+#include <sys/rwlock.h>
 #include <net/ethernet.h> /* for ETHERTYPE_IP */
 #include <net/if.h>
+#include <net/if_clone.h>
 #include <net/vnet.h>
 #include <net/if_types.h>      /* for IFT_ETHER */
 #include <net/bpf.h>           /* 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;
        }
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to