Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 25 Apr 2012 00:26:00 +0900 (JST)
From:      Hiroki Sato <hrs@FreeBSD.org>
To:        freebsd-ipfw@FreeBSD.org
Subject:   CFR: ipfw0 pseudo-interface clonable
Message-ID:  <20120425.002600.1631867625819249738.hrs@allbsd.org>

next in thread | raw e-mail | index | archive | help
----Security_Multipart0(Wed_Apr_25_00_26_00_2012_958)--
Content-Type: Multipart/Mixed;
	boundary="--Next_Part(Wed_Apr_25_00_26_00_2012_602)--"
Content-Transfer-Encoding: 7bit

----Next_Part(Wed_Apr_25_00_26_00_2012_602)--
Content-Type: Text/Plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

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

----Next_Part(Wed_Apr_25_00_26_00_2012_602)--
Content-Type: Text/X-Patch; charset=us-ascii
Content-Transfer-Encoding: 7bit
Content-Disposition: inline; filename="ipfw_clone_interface.20120421-1.diff"

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 */

 /*

----Next_Part(Wed_Apr_25_00_26_00_2012_602)----

----Security_Multipart0(Wed_Apr_25_00_26_00_2012_958)--
Content-Type: application/pgp-signature
Content-Transfer-Encoding: 7bit

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.11 (FreeBSD)

iEYEABECAAYFAk+WxggACgkQTyzT2CeTzy2e3ACggqHzMzIW8AQHrVq2L7wPrF3V
ZnMAn19hiyq9/J1gmQv/KqDhYrD6EJ4d
=nevM
-----END PGP SIGNATURE-----

----Security_Multipart0(Wed_Apr_25_00_26_00_2012_958)----



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20120425.002600.1631867625819249738.hrs>