summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorhrs <hrs@FreeBSD.org>2012-07-09 07:16:19 +0000
committerhrs <hrs@FreeBSD.org>2012-07-09 07:16:19 +0000
commit9a711a67d4aa86f9a25f182702a0f82bc85a7859 (patch)
tree832647ea9dbdde90423233f17877e38369f18bc5
parentfd33b54fca41db793fb39ad39751f4e2ff775e67 (diff)
downloadFreeBSD-src-9a711a67d4aa86f9a25f182702a0f82bc85a7859.zip
FreeBSD-src-9a711a67d4aa86f9a25f182702a0f82bc85a7859.tar.gz
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@
-rw-r--r--etc/defaults/rc.conf1
-rwxr-xr-xetc/rc.d/ipfw4
-rw-r--r--sbin/ipfw/ipfw.819
-rw-r--r--share/man/man5/rc.conf.512
-rw-r--r--sys/netinet/ipfw/ip_fw_log.c137
5 files changed, 143 insertions, 30 deletions
diff --git a/etc/defaults/rc.conf b/etc/defaults/rc.conf
index 0d31d54..c04dab2b 100644
--- a/etc/defaults/rc.conf
+++ b/etc/defaults/rc.conf
@@ -123,6 +123,7 @@ firewall_script="/etc/rc.firewall" # Which script to run to set up the firewall
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
diff --git a/etc/rc.d/ipfw b/etc/rc.d/ipfw
index 4beb609..625d07d 100755
--- a/etc/rc.d/ipfw
+++ b/etc/rc.d/ipfw
@@ -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()
diff --git a/sbin/ipfw/ipfw.8 b/sbin/ipfw/ipfw.8
index 7974ed6..7f38157 100644
--- a/sbin/ipfw/ipfw.8
+++ b/sbin/ipfw/ipfw.8
@@ -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
diff --git a/share/man/man5/rc.conf.5 b/share/man/man5/rc.conf.5
index 1802fca..02e1cb6 100644
--- a/share/man/man5/rc.conf.5
+++ b/share/man/man5/rc.conf.5
@@ -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
diff --git a/sys/netinet/ipfw/ip_fw_log.c b/sys/netinet/ipfw/ip_fw_log.c
index b9ed6b3..14eb2a2 100644
--- a/sys/netinet/ipfw/ip_fw_log.c
+++ b/sys/netinet/ipfw/ip_fw_log.c
@@ -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, struct ip_fw_args *args,
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, struct ip_fw_args *args,
* more info in the header.
*/
BPF_MTAP2(log_if, "DDDDDDSSSSSS\x08\x00", ETHER_HDR_LEN, m);
+ LOGIF_RUNLOCK();
#endif /* !WITHOUT_BPF */
return;
}
OpenPOWER on IntegriCloud