Hi,

 I created the attached patch to make the current ipfw0
 pseudo-interface clonable.  The functionality of ipfw0 logging
 interface is not changed by this patch, but the ipfw0
 pseudo-interface is not created by default and can be created with
 the following command:

  # ifconfig ipfw0 create

 Any objection to commit this patch?  The primary motivation for this
 change is that presence of the interface by default increases size of
 the interface list, which is returned by NET_RT_IFLIST sysctl even
 when the sysadmin does not need it.  Also this pseudo-interface can
 confuse the sysadmin and/or network-related userland utilities like
 SNMP agent.  With this patch, one can use ifconfig(8) to
 create/destroy the pseudo-interface as necessary.

-- Hiroki
Index: sys/netinet/ipfw/ip_fw_log.c
===================================================================
--- sys/netinet/ipfw/ip_fw_log.c	(revision 234428)
+++ sys/netinet/ipfw/ip_fw_log.c	(working copy)
@@ -46,6 +46,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/syslog.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 */
@@ -89,8 +90,11 @@ ipfw_log_bpf(int onoff)
 {
 }
 #else /* !WITHOUT_BPF */
+static struct mtx log_if_mtx;
 static struct ifnet *log_if;	/* hook to attach to bpf */

+#define	IPFWNAME	"ipfw"
+
 /* we use this dummy function for all ifnet callbacks */
 static int
 log_dummy(struct ifnet *ifp, u_long cmd, caddr_t addr)
@@ -116,39 +120,106 @@ ipfw_log_start(struct ifnet* ifp)
 static const u_char ipfwbroadcastaddr[6] =
 	{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };

-void
-ipfw_log_bpf(int onoff)
+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;

-	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);
+	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);
+
+	mtx_lock(&log_if_mtx);
+	if (log_if == NULL) {
 		log_if = ifp;
+		mtx_unlock(&log_if_mtx);
 	} else {
-		if (log_if) {
-			ether_ifdetach(log_if);
-			if_free(log_if);
-		}
+		mtx_unlock(&log_if_mtx);
+		if_free(ifp);
+		ifc_free_unit(ifc, unit);
+		return (EEXIST);
+	}
+	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);
+
+	mtx_lock(&log_if_mtx);
+	if (log_if != NULL && ifp == log_if)
 		log_if = NULL;
+	else {
+		mtx_unlock(&log_if_mtx);
+		return (EINVAL);
 	}
+	mtx_unlock(&log_if_mtx);
+
+	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)
+{
+
+	if (onoff) {
+		mtx_init(&log_if_mtx, "ipfw log_if mtx", NULL, 0);
+		if_clone_attach(&ipfw_log_cloner);
+	} else {
+		if_clone_detach(&ipfw_log_cloner);
+		mtx_destroy(&log_if_mtx);
+	}
+}
 #endif /* !WITHOUT_BPF */

 /*

Attachment: pgpSsBQkAqBtv.pgp
Description: PGP signature

Reply via email to