Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 26 Jun 2001 14:43:15 -0700
From:      Brooks Davis <brooks@one-eyed-alien.net>
To:        net@freebsd.org, audit@freebsd.org
Subject:   review request: network interface cloning
Message-ID:  <20010626144313.A7909@Odin.AC.HMC.Edu>

next in thread | raw e-mail | index | archive | help

--PNTmBPCT7hxwcZjr
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Content-Transfer-Encoding: quoted-printable

Please review the attached patch.  It does the following:

- implementes network interface cloning via ifconfig
- adds cloning support to gif
- removes gif dependencies from stf
- makes gif and stf modular

Notes:

The cloning API isn't quite that of NetBSD because the NetBSD API only
supported the creation of staticaly numbered interfaces which can lead
to races and starvation in theory.  This patch instead allows interfaces
to implement wildcard interface creation via "ifconfig gif# create".

Hajimu UMEMOTO found a bug related to deletion of gif IPv6 tunnels in
certain situations.  We're fairly certain it's in the IPv6 routing code
rather then in gif.  Since even with this bug, the world will be a better
place with this patch, I've documented it in gif(4)'s BUGS section and
suggest we commit anyway to get cloning into the system.

-- Brooks

P.S. The patch can also be found at:

http://people.freebsd.org/~brooks/patches/gif.diff

--=20
Any statement of the form "X is the one, true Y" is FALSE.
PGP fingerprint 655D 519C 26A7 82E7 2529  9BF0 5D8E 8BE9 F238 1AD4


Index: sbin/ifconfig/ifconfig.8
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /home/ncvs/src/sbin/ifconfig/ifconfig.8,v
retrieving revision 1.42
diff -u -u -r1.42 ifconfig.8
--- sbin/ifconfig/ifconfig.8	2001/06/11 12:38:43	1.42
+++ sbin/ifconfig/ifconfig.8	2001/06/22 01:11:23
@@ -43,6 +43,7 @@
 .Op Fl L
 .Op Fl m
 .Ar interface
+.Op Cm create
 .Op Ar address_family
 .Oo
 .Ar address Ns Op Cm / Ns Ar prefixlength
@@ -50,6 +51,9 @@
 .Oc
 .Op Ar parameters
 .Nm
+.Ar interface
+.Cm destroy
+.Nm
 .Fl a
 .Op Fl L
 .Op Fl d
@@ -66,6 +70,7 @@
 .Op Fl d
 .Op Fl m
 .Op Fl u
+.Op Fl C
 .Sh DESCRIPTION
 .Nm Ifconfig
 is used to assign an address
@@ -269,6 +274,18 @@
 Unconfigure the physical source and destination address for IP tunnel
 interfaces previously configured with
 .Cm tunnel .
+.It Cm create
+Create the specified network pseudo-device.
+.It Cm destroy
+Destroy the specified network pseudo-device.
+.It Cm plumb
+Another name for the
+.Fl create
+parameter.  Included for Solaris compatability.
+.It Cm unplumb
+Another name for the
+.Fl destroy
+parameter.  Included for Solaris compatability.
 .It Cm vlan Ar vlan_tag
 If the interface is a vlan pseudo interface, set the vlan tag value
 to
@@ -586,6 +603,12 @@
 and
 .Fl u=20
 (only list interfaces that are up).
+.Pp
+The
+.Fl C
+flag may be used to list all of the interface cloners available on
+the system, with no additional information.  Use of this flag is
+mutually exclusive with all other flags and commands.
 .Pp
 Only the super-user may modify the configuration of a network interface.
 .Sh NOTES
Index: sbin/ifconfig/ifconfig.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /home/ncvs/src/sbin/ifconfig/ifconfig.c,v
retrieving revision 1.63
diff -u -u -r1.63 ifconfig.c
--- sbin/ifconfig/ifconfig.c	2001/06/11 12:38:43	1.63
+++ sbin/ifconfig/ifconfig.c	2001/06/22 01:12:06
@@ -135,6 +135,7 @@
 struct	afswtch;
=20
 int supmedia =3D 0;
+int listcloners =3D 0;
=20
 #ifdef INET6
 char	addr_buf[MAXHOSTNAMELEN *2 + 1];	/*for getnameinfo()*/
@@ -144,6 +145,7 @@
 void	checkatrange __P((struct sockaddr_at *));
 int	ifconfig __P((int argc, char *const *argv, const struct afswtch *afp));
 void	notealias __P((const char *, int, int, const struct afswtch *afp));
+void	list_cloners __P((void));
 void	printb __P((const char *s, unsigned value, const char *bits));
 void	rt_xaddrs __P((caddr_t, caddr_t, struct rt_addrinfo *));
 void	status __P((const struct afswtch *afp, int addrcount,
@@ -175,8 +177,12 @@
 #endif
 c_func	setifipdst;
 c_func	setifflags, setifmetric, setifmtu, setiflladdr;
+c_func	clone_destroy;
=20
=20
+void clone_create __P((void));
+
+
 #define	NEXTARG		0xffffff
 #define	NEXTARG2	0xfffffe
=20
@@ -239,6 +245,13 @@
 	{ "vlandev",	NEXTARG,	setvlandev },
 	{ "-vlandev",	NEXTARG,	unsetvlandev },
 #endif
+#if 0
+	/* XXX `create' special-cased below */
+	{"create",	0,		clone_create },
+	{"plumb",	0,		clone_create },
+#endif
+	{"destroy",	0,		clone_destroy },
+	{"unplumb",	0,		clone_destroy },
 #ifdef USE_IEEE80211
 	{ "ssid",	NEXTARG,	set80211ssid },
 	{ "nwid",	NEXTARG,	set80211ssid },
@@ -364,16 +377,20 @@
 usage()
 {
 #ifndef INET6
-	fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n",
+	fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n%s\n%s\n",
 	"usage: ifconfig interface address_family [address [dest_address]]",
 	"                [parameters]",
+	"       ifconfig -C",
+	"       ifconfig interface create",
 	"       ifconfig -a [-d] [-m] [-u] [address_family]",
 	"       ifconfig -l [-d] [-u] [address_family]",
 	"       ifconfig [-d] [-m] [-u]");
 #else
-	fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n",
+	fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n%s\n%s\n",
 	"usage: ifconfig [-L] interface address_family [address [dest_address]]",
 	"                [parameters]",
+	"       ifconfig -C",
+	"       ifconfig interface create",
 	"       ifconfig -a [-L] [-d] [-m] [-u] [address_family]",
 	"       ifconfig -l [-d] [-u] [address_family]",
 	"       ifconfig [-L] [-d] [-m] [-u]");
@@ -402,7 +419,7 @@
=20
 	/* Parse leading line options */
 	all =3D downonly =3D uponly =3D namesonly =3D 0;
-	while ((c =3D getopt(argc, argv, "adlmu"
+	while ((c =3D getopt(argc, argv, "Cadlmu"
 #ifdef INET6
 					"L"
 #endif
@@ -428,6 +445,9 @@
 		case 'm':	/* show media choices in status */
 			supmedia =3D 1;
 			break;
+		case 'C':
+			listcloners =3D 1;
+			break;
 		default:
 			usage();
 			break;
@@ -436,6 +456,16 @@
 	argc -=3D optind;
 	argv +=3D optind;
=20
+	if (listcloners) {
+		/* -C must be solitary */
+		if (all || supmedia || uponly || downonly || namesonly ||
+		    argc > 0)
+			usage();
+	=09
+		list_cloners();
+		exit(0);
+	}
+
 	/* -l cannot be used with -a or -m */
 	if (namesonly && (all || supmedia))
 		usage();
@@ -448,6 +478,7 @@
 	if (!namesonly && argc < 1)
 		all =3D 1;
=20
+
 	/* -a and -l allow an address family arg to limit the output */
 	if (all || namesonly) {
 		if (argc > 1)
@@ -473,6 +504,18 @@
=20
 		/* check and maybe load support for this interface */
 		ifmaybeload(name);
+
+		/*
+		 * NOTE:  We must special-case the `create' command right
+		 * here as we would otherwise fail when trying to find
+		 * the interface.
+		 */
+		if (argc > 0 && strcmp(argv[0], "create") =3D=3D 0) {
+			clone_create();
+			argc--, argv++;
+			if (argc =3D=3D 0)
+				exit(0);
+		}
 	}
=20
 	/* Check for address family */
@@ -1861,7 +1904,8 @@
=20
 	/* turn interface and unit into module name */
 	strcpy(ifkind, "if_");
-	for (cp =3D name, dp =3D ifkind + 3; (*cp !=3D 0) && !isdigit(*cp); cp++,=
 dp++)
+	for (cp =3D name, dp =3D ifkind + 3;
+	    (*cp !=3D 0) && !isdigit(*cp) && *cp !=3D '#'; cp++, dp++)
 		*dp =3D *cp;
 	*dp =3D 0;
=20
@@ -1887,4 +1931,82 @@
=20
 	/* not present, we should try to load it */
 	kldload(ifkind);
+}
+
+void
+list_cloners(void)
+{
+	struct if_clonereq ifcr;
+	char *cp, *buf;
+	int idx;
+	int s;
+
+	s =3D socket(AF_INET, SOCK_DGRAM, 0);
+	if (s < 0)
+		err(1, "socket");
+
+	memset(&ifcr, 0, sizeof(ifcr));
+
+	if (ioctl(s, SIOCIFGCLONERS, &ifcr) < 0)
+		err(1, "SIOCIFGCLONERS for count");
+
+	buf =3D malloc(ifcr.ifcr_total * IFNAMSIZ);
+	if (buf =3D=3D NULL)
+		err(1, "unable to allocate cloner name buffer");
+
+	ifcr.ifcr_count =3D ifcr.ifcr_total;
+	ifcr.ifcr_buffer =3D buf;
+
+	if (ioctl(s, SIOCIFGCLONERS, &ifcr) < 0)
+		err(1, "SIOCIFGCLONERS for names");
+
+	/*
+	 * In case some disappeared in the mean time, clamp it down.
+	 */
+	if (ifcr.ifcr_count > ifcr.ifcr_total)
+		ifcr.ifcr_count =3D ifcr.ifcr_total;
+
+	for (cp =3D buf, idx =3D 0; idx < ifcr.ifcr_count; idx++, cp +=3D IFNAMSI=
Z) {
+		if (idx > 0)
+			putchar(' ');
+		printf("%s", cp);
+	}
+
+	putchar('\n');
+	free(buf);
+	return;
+}
+
+void
+clone_create()
+{
+	int s;
+
+	s =3D socket(AF_INET, SOCK_DGRAM, 0);
+	if (s < 0)
+		err(1, "socket");
+
+	bzero(&ifr, sizeof(ifr));
+	(void) strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
+	if (ioctl(s, SIOCIFCREATE, &ifr) < 0)
+		err(1, "SIOCIFCREATE");
+
+	if (strcmp(name, ifr.ifr_name) !=3D 0) {
+		printf("%s\n", ifr.ifr_name);
+		strlcpy(name, ifr.ifr_name, sizeof(name));
+	}
+
+	close(s);
+}
+
+void
+clone_destroy(val, d, s, rafp)
+	const char *val;
+	int d;
+	int s;
+	const struct afswtch *rafp;
+{
+	(void) strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
+	if (ioctl(s, SIOCIFDESTROY, &ifr) < 0)
+		err(1, "SIOCIFDESTROY");
 }
Index: sys/conf/files
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /home/ncvs/src/sys/conf/files,v
retrieving revision 1.535
diff -u -u -r1.535 files
--- sys/conf/files	2001/06/22 06:34:40	1.535
+++ sys/conf/files	2001/06/23 06:40:44
@@ -893,7 +893,7 @@
 net/if_ethersubr.c	optional ether
 net/if_faith.c		count faith
 net/if_fddisubr.c	optional fddi
-net/if_gif.c		count gif
+net/if_gif.c		optional gif
 net/if_iso88025subr.c	optional token
 net/if_loop.c		optional loop
 net/if_media.c		standard
@@ -901,7 +901,7 @@
 net/if_ppp.c		count ppp
 net/if_sl.c		optional sl
 net/if_spppsubr.c	optional sppp
-net/if_stf.c		count stf
+net/if_stf.c		optional stf
 net/if_tun.c		optional tun
 net/if_tap.c		optional tap
 net/if_vlan.c		count vlan
Index: sys/i386/conf/GENERIC
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /home/ncvs/src/sys/i386/conf/GENERIC,v
retrieving revision 1.312
diff -u -u -r1.312 GENERIC
--- sys/i386/conf/GENERIC	2001/06/12 09:39:57	1.312
+++ sys/i386/conf/GENERIC	2001/06/18 22:04:21
@@ -210,7 +210,7 @@
 device		tun		# Packet tunnel.
 device		pty		# Pseudo-ttys (telnet etc)
 device		md		# Memory "disks"
-device		gif	4	# IPv6 and IPv4 tunneling
+device		gif		# IPv6 and IPv4 tunneling
 device		faith	1	# IPv6-to-IPv4 relaying (translation)
=20
 # The `bpf' device enables the Berkeley Packet Filter.
Index: sys/ia64/conf/GENERIC
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /home/ncvs/src/sys/ia64/conf/GENERIC,v
retrieving revision 1.10
diff -u -u -r1.10 GENERIC
--- sys/ia64/conf/GENERIC	2001/05/29 18:49:03	1.10
+++ sys/ia64/conf/GENERIC	2001/06/09 00:55:41
@@ -140,7 +140,7 @@
 device		tun		# Packet tunnel.
 device		pty		# Pseudo-ttys (telnet etc)
 device		md		# Memory "disks"
-device		gif	4	# IPv6 and IPv4 tunneling
+device		gif		# IPv6 and IPv4 tunneling
 device		faith	1	# IPv6-to-IPv4 relaying/(translation)
=20
 # The `bpf' device enables the Berkeley Packet Filter.
Index: sys/alpha/conf/GENERIC
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /home/ncvs/src/sys/alpha/conf/GENERIC,v
retrieving revision 1.113
diff -u -u -r1.113 GENERIC
--- sys/alpha/conf/GENERIC	2001/05/30 03:19:05	1.113
+++ sys/alpha/conf/GENERIC	2001/06/09 00:55:14
@@ -165,7 +165,7 @@
 device		tun		# Packet tunnel.
 device		pty		# Pseudo-ttys (telnet etc)
 device		md		# Memory "disks"
-device		gif	4	# IPv6 and IPv4 tunneling
+device		gif		# IPv6 and IPv4 tunneling
 device		faith	1	# IPv6-to-IPv4 relaying/(translation)
=20
 # The `bpf' device enables the Berkeley Packet Filter.
Index: sys/net/if.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /home/ncvs/src/sys/net/if.c,v
retrieving revision 1.109
diff -u -u -r1.109 if.c
--- sys/net/if.c	2001/06/11 12:38:58	1.109
+++ sys/net/if.c	2001/06/22 00:11:09
@@ -56,6 +56,7 @@
 #include <net/if_arp.h>
 #include <net/if_dl.h>
 #include <net/if_types.h>
+#include <net/if_var.h>
 #include <net/radix.h>
 #include <net/route.h>
=20
@@ -96,6 +97,12 @@
 extern void	nd6_setmtu __P((struct ifnet *));
 #endif
=20
+struct if_clone *if_clone_lookup __P((const char *, int *));
+int if_clone_list __P((struct if_clonereq *));
+
+LIST_HEAD(, if_clone) if_cloners =3D LIST_HEAD_INITIALIZER(if_cloners);
+int if_cloners_count;
+
 /*
  * Network interface utility routines.
  *
@@ -350,6 +357,179 @@
 }
=20
 /*
+ * Create a clone network interface.
+ */
+int
+if_clone_create(name, len)
+	char *name;
+	int len;
+{
+	struct if_clone *ifc;
+	char *dp;
+	int wildcard =3D 0;
+	int unit;
+	int err;
+
+	ifc =3D if_clone_lookup(name, &unit);
+	if (ifc =3D=3D NULL)
+		return (EINVAL);
+
+	if (ifunit(name) !=3D NULL)
+		return (EEXIST);
+
+	if (unit < 0)
+		wildcard =3D 1;
+
+	err =3D (*ifc->ifc_create)(ifc, &unit);
+	if (err !=3D 0)
+		return (err);
+
+	/* In the wildcard case, we need to update the name. */
+	if (wildcard) {
+		for (dp =3D name; *dp !=3D '#'; dp++);
+		if (snprintf(dp, len - (dp-name), "%d", unit) >
+		    len - (dp-name) - 1) {
+			/*
+			 * This can only be a programmer error and
+			 * there's no straightforward way to recover if
+			 * it happens.
+			 */
+			panic("interface name too long");
+		}
+		=09
+	}
+
+	return (0);
+}
+
+/*
+ * Destroy a clone network interface.
+ */
+int
+if_clone_destroy(name)
+	const char *name;
+{
+	struct if_clone *ifc;
+	struct ifnet *ifp;
+
+	ifc =3D if_clone_lookup(name, NULL);
+	if (ifc =3D=3D NULL)
+		return (EINVAL);
+
+	ifp =3D ifunit(name);
+	if (ifp =3D=3D NULL)
+		return (ENXIO);
+
+	if (ifc->ifc_destroy =3D=3D NULL)
+		return (EOPNOTSUPP);
+
+	(*ifc->ifc_destroy)(ifp);
+	return (0);
+}
+
+/*
+ * Look up a network interface cloner.
+ */
+struct if_clone *
+if_clone_lookup(name, unitp)
+	const char *name;
+	int *unitp;
+{
+	struct if_clone *ifc;
+	const char *cp;
+	int i;
+
+	for (ifc =3D LIST_FIRST(&if_cloners); ifc !=3D NULL;) {
+		for (cp =3D name, i =3D 0; i < ifc->ifc_namelen; i++, cp++) {
+			if (ifc->ifc_name[i] !=3D *cp)
+				goto next_ifc;
+		}
+		goto found_name;
+ next_ifc:
+		ifc =3D LIST_NEXT(ifc, ifc_list);
+	}
+
+	/* No match. */
+	return (NULL);
+
+ found_name:
+	if (*cp =3D=3D '#' && *(cp+1) =3D=3D '\0') {
+		i =3D -1;
+	} else {
+		for (i =3D 0; *cp !=3D '\0'; cp++) {
+			if (*cp < '0' || *cp > '9') {
+				/* Bogus unit number. */
+				return (NULL);
+			}
+			i =3D (i * 10) + (*cp - '0');
+		}
+	}
+
+	if (unitp !=3D NULL)
+		*unitp =3D i;
+	return (ifc);
+}
+
+/*
+ * Register a network interface cloner.
+ */
+void
+if_clone_attach(ifc)
+	struct if_clone *ifc;
+{
+
+	LIST_INSERT_HEAD(&if_cloners, ifc, ifc_list);
+	if_cloners_count++;
+}
+
+/*
+ * Unregister a network interface cloner.
+ */
+void
+if_clone_detach(ifc)
+	struct if_clone *ifc;
+{
+
+	LIST_REMOVE(ifc, ifc_list);
+	if_cloners_count--;
+}
+
+/*
+ * Provide list of interface cloners to userspace.
+ */
+int
+if_clone_list(ifcr)
+	struct if_clonereq *ifcr;
+{
+	char outbuf[IFNAMSIZ], *dst;
+	struct if_clone *ifc;
+	int count, error =3D 0;
+
+	ifcr->ifcr_total =3D if_cloners_count;
+	if ((dst =3D ifcr->ifcr_buffer) =3D=3D NULL) {
+		/* Just asking how many there are. */
+		return (0);
+	}
+
+	if (ifcr->ifcr_count < 0)
+		return (EINVAL);
+
+	count =3D (if_cloners_count < ifcr->ifcr_count) ?
+	    if_cloners_count : ifcr->ifcr_count;
+
+	for (ifc =3D LIST_FIRST(&if_cloners); ifc !=3D NULL && count !=3D 0;
+	     ifc =3D LIST_NEXT(ifc, ifc_list), count--, dst +=3D IFNAMSIZ) {
+		strncpy(outbuf, ifc->ifc_name, IFNAMSIZ);
+		outbuf[IFNAMSIZ - 1] =3D '\0';	/* sanity */
+		error =3D copyout(outbuf, dst, IFNAMSIZ);
+		if (error)
+			break;
+	}
+
+	return (error);
+}
+
+/*
  * Locate an interface based on a complete address.
  */
 /*ARGSUSED*/
@@ -687,10 +867,10 @@
  * interface structure pointer.
  */
 struct ifnet *
-ifunit(char *name)
+ifunit(const char *name)
 {
 	char namebuf[IFNAMSIZ + 1];
-	char *cp;
+	const char *cp;
 	struct ifnet *ifp;
 	int unit;
 	unsigned len, m;
@@ -781,6 +961,20 @@
 		return (ifconf(cmd, data));
 	}
 	ifr =3D (struct ifreq *)data;
+
+	switch (cmd) {
+	case SIOCIFCREATE:
+	case SIOCIFDESTROY:
+		if ((error =3D suser(p)) !=3D 0)
+			return (error);
+		return ((cmd =3D=3D SIOCIFCREATE) ?
+			if_clone_create(ifr->ifr_name, sizeof(ifr->ifr_name)) :
+			if_clone_destroy(ifr->ifr_name));
+=09
+	case SIOCIFGCLONERS:
+		return (if_clone_list((struct if_clonereq *)data));
+	}
+
 	ifp =3D ifunit(ifr->ifr_name);
 	if (ifp =3D=3D 0)
 		return (ENXIO);
Index: sys/net/if.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /home/ncvs/src/sys/net/if.h,v
retrieving revision 1.61
diff -u -u -r1.61 if.h
--- sys/net/if.h	2001/02/21 06:39:56	1.61
+++ sys/net/if.h	2001/06/22 06:03:23
@@ -37,6 +37,8 @@
 #ifndef _NET_IF_H_
 #define	_NET_IF_H_
=20
+#include <sys/queue.h>
+
 /*
  * <net/if.h> does not depend on <sys/time.h> on most other systems.  This
  * helps userland compatibility.  (struct timeval ifi_lastchange)
@@ -45,6 +47,40 @@
 #include <sys/time.h>
 #endif
=20
+struct ifnet;
+
+/*
+ * Length of interface external name, including terminating '\0'.
+ * Note: this is the same size as a generic device's external name.
+ */
+#define		IFNAMSIZ	16
+#define		IF_NAMESIZE	IFNAMSIZ
+
+/*
+ * Structure describing a `cloning' interface.
+ */
+struct if_clone {
+	LIST_ENTRY(if_clone) ifc_list;	/* on list of cloners */
+	const char *ifc_name;		/* name of device, e.g. `gif' */
+	size_t ifc_namelen;		/* length of name */
+
+	int	(*ifc_create)(struct if_clone *, int *);
+	void	(*ifc_destroy)(struct ifnet *);
+};
+
+#define IF_CLONE_INITIALIZER(name, create, destroy)			\
+	{ { 0 }, name, sizeof(name) - 1, create, destroy }
+
+/*
+ * Structure used to query names of interface cloners.
+ */
+
+struct if_clonereq {
+	int	ifcr_total;		/* total cloners (out) */
+	int	ifcr_count;		/* room for this many in user buffer */
+	char	*ifcr_buffer;		/* buffer for cloner names */
+};
+
 /*
  * Structure describing information about an interface
  * which may be of interest to management entities.
@@ -151,8 +187,6 @@
  * remainder may be interface specific.
  */
 struct	ifreq {
-#define	IFNAMSIZ	16
-#define	IF_NAMESIZE	IFNAMSIZ
 	char	ifr_name[IFNAMSIZ];		/* if name, e.g. "en0" */
 	union {
 		struct	sockaddr ifru_addr;
Index: sys/net/if_var.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /home/ncvs/src/sys/net/if_var.h,v
retrieving revision 1.33
diff -u -u -r1.33 if_var.h
--- sys/net/if_var.h	2001/03/28 09:17:55	1.33
+++ sys/net/if_var.h	2001/06/22 00:00:59
@@ -401,7 +401,7 @@
 /*void	ifinit __P((void));*/ /* declared in systm.h for main() */
 int	ifioctl __P((struct socket *, u_long, caddr_t, struct proc *));
 int	ifpromisc __P((struct ifnet *, int));
-struct	ifnet *ifunit __P((char *));
+struct	ifnet *ifunit __P((const char *));
 struct	ifnet *if_withname __P((struct sockaddr *));
=20
 int	if_poll_recv_slow __P((struct ifnet *ifp, int *quotap));
@@ -422,6 +422,12 @@
 struct	ifmultiaddr *ifmaof_ifpforaddr __P((struct sockaddr *,
 					    struct ifnet *));
 int	if_simloop __P((struct ifnet *ifp, struct mbuf *m, int af, int hlen));
+
+void	if_clone_attach __P((struct if_clone *));
+void	if_clone_detach __P((struct if_clone *));
+
+int	if_clone_create __P((char *, int));
+int	if_clone_destroy __P((const char *));
=20
 #endif /* _KERNEL */
=20
Index: sys/net/if_gif.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /home/ncvs/src/sys/net/if_gif.c,v
retrieving revision 1.11
diff -u -u -r1.11 if_gif.c
--- sys/net/if_gif.c	2001/06/19 15:53:51	1.11
+++ sys/net/if_gif.c	2001/06/25 20:21:24
@@ -44,6 +44,9 @@
 #include <sys/time.h>
 #include <sys/syslog.h>
 #include <sys/protosw.h>
+#include <sys/conf.h>
+#include <machine/bus.h>	/* XXX: Shouldn't really be required! */
+#include <sys/rman.h>
 #include <machine/cpu.h>
=20
 #include <net/if.h>
@@ -58,6 +61,8 @@
 #ifdef	INET
 #include <netinet/in_var.h>
 #include <netinet/in_gif.h>
+#include <netinet/ip_var.h>
+#include <netinet/ipprotosw.h>
 #endif	/* INET */
=20
 #ifdef INET6
@@ -74,29 +79,47 @@
 #include <netinet/ip_encap.h>
 #include <net/if_gif.h>
=20
-#include "gif.h"
-#include "bpf.h"
-#define NBPFILTER	NBPF
-
 #include <net/net_osdep.h>
+
+#define GIFNAME		"gif"
+#define GIFDEV		"if_gif"
+#define GIF_MAXUNIT	0x7fff	/* ifp->if_unit is only 15 bits */
+
+static MALLOC_DEFINE(M_GIF, "gif", "Generic Tunnel Interface");
+static struct rman gifunits[1];
+TAILQ_HEAD(gifhead, gif_softc) gifs =3D TAILQ_HEAD_INITIALIZER(gifs);
=20
-#if NGIF > 0
+int	gif_clone_create __P((struct if_clone *, int *));
+void	gif_clone_destroy __P((struct ifnet *));
=20
-void gifattach __P((void *));
+struct if_clone gif_cloner =3D
+    IF_CLONE_INITIALIZER("gif", gif_clone_create, gif_clone_destroy);
+
+static int gifmodevent __P((module_t, int, void *));
+void gif_delete_tunnel __P((struct gif_softc *));
 static int gif_encapcheck __P((const struct mbuf *, int, int, void *));
+
 #ifdef INET
-extern struct protosw in_gif_protosw;
+extern  struct domain inetdomain;
+struct ipprotosw in_gif_protosw =3D
+{ SOCK_RAW,	&inetdomain,	0/*IPPROTO_IPV[46]*/,	PR_ATOMIC|PR_ADDR,
+  in_gif_input,	rip_output,	0,		rip_ctloutput,
+  0,
+  0,		0,		0,		0,
+  &rip_usrreqs
+};
+#endif
+#ifdef INET6
+extern  struct domain6 inet6domain;
+struct ip6protosw in6_gif_protosw =3D
+{ SOCK_RAW,	&inet6domain,	0/*IPPROTO_IPV[46]*/,	PR_ATOMIC|PR_ADDR,
+  in6_gif_input, rip6_output,	0,		rip6_ctloutput,
+  0,
+  0,		0,		0,		0,
+  &rip6_usrreqs
+};
 #endif
-#ifdef INET6
-extern struct ip6protosw in6_gif_protosw;
-#endif
=20
-/*
- * gif global variable definitions
- */
-static int ngif;		/* number of interfaces */
-static struct gif_softc *gif =3D 0;
-
 #ifndef MAX_GIF_NEST
 /*
  * This macro controls the upper limitation on nesting of gif tunnels.
@@ -110,64 +133,158 @@
 #endif
 static int max_gif_nesting =3D MAX_GIF_NEST;
=20
-void
-gifattach(dummy)
-	void *dummy;
+int
+gif_clone_create(ifc, unit)
+	struct if_clone *ifc;
+	int *unit;
 {
+	struct resource *r;
 	struct gif_softc *sc;
-	int i;
=20
-	ngif =3D NGIF;
-	gif =3D sc =3D malloc(ngif * sizeof(struct gif_softc), M_DEVBUF, M_WAITOK=
);
-	bzero(sc, ngif * sizeof(struct gif_softc));
-	for (i =3D 0; i < ngif; sc++, i++) {
-		sc->gif_if.if_name =3D "gif";
-		sc->gif_if.if_unit =3D i;
-
-		sc->encap_cookie4 =3D sc->encap_cookie6 =3D NULL;
-#ifdef INET
-		sc->encap_cookie4 =3D encap_attach_func(AF_INET, -1,
-		    gif_encapcheck, &in_gif_protosw, sc);
-		if (sc->encap_cookie4 =3D=3D NULL) {
-			printf("%s: attach failed\n", if_name(&sc->gif_if));
-			continue;
-		}
+	if (*unit > GIF_MAXUNIT)
+		return (ENXIO);
+
+	if (*unit < 0) {
+		r =3D rman_reserve_resource(gifunits, 0, GIF_MAXUNIT, 1,
+		    RF_ALLOCATED | RF_ACTIVE, NULL);
+		if (r =3D=3D NULL)
+			return (ENOSPC);
+		*unit =3D rman_get_start(r);
+	} else {
+		r =3D rman_reserve_resource(gifunits, *unit, *unit, 1,
+		    RF_ALLOCATED | RF_ACTIVE, NULL);
+		if (r =3D=3D NULL)
+			return (EEXIST);
+	}
+=09
+	sc =3D malloc (sizeof(struct gif_softc), M_GIF, M_WAITOK);
+	bzero(sc, sizeof(struct gif_softc));
+
+	sc->gif_if.if_softc =3D sc;
+	sc->gif_if.if_name =3D GIFNAME;
+	sc->gif_if.if_unit =3D *unit;
+	sc->r_unit =3D r;
+
+	sc->encap_cookie4 =3D sc->encap_cookie6 =3D NULL;
+#ifdef INET
+	sc->encap_cookie4 =3D encap_attach_func(AF_INET, -1,
+	    gif_encapcheck, (struct protosw*)&in_gif_protosw, sc);
+	if (sc->encap_cookie4 =3D=3D NULL) {
+		printf("%s: unable to attach encap4\n", if_name(&sc->gif_if));
+		free(sc, M_GIF);
+		return (EIO);	/* XXX */
+	}
 #endif
 #ifdef INET6
-		sc->encap_cookie6 =3D encap_attach_func(AF_INET6, -1,
-		    gif_encapcheck, (struct protosw *)&in6_gif_protosw, sc);
-		if (sc->encap_cookie6 =3D=3D NULL) {
-			if (sc->encap_cookie4) {
-				encap_detach(sc->encap_cookie4);
-				sc->encap_cookie4 =3D NULL;
-			}
-			printf("%s: attach failed\n", if_name(&sc->gif_if));
-			continue;
+	sc->encap_cookie6 =3D encap_attach_func(AF_INET6, -1,
+	    gif_encapcheck, (struct protosw *)&in6_gif_protosw, sc);
+	if (sc->encap_cookie6 =3D=3D NULL) {
+		if (sc->encap_cookie4) {
+			encap_detach(sc->encap_cookie4);
+			sc->encap_cookie4 =3D NULL;
 		}
+		printf("%s: unable to attach encap6\n", if_name(&sc->gif_if));
+		free(sc, M_GIF);
+		return (EIO);	/* XXX */
+	}
 #endif
=20
-		sc->gif_if.if_mtu    =3D GIF_MTU;
-		sc->gif_if.if_flags  =3D IFF_POINTOPOINT | IFF_MULTICAST;
+	sc->gif_if.if_mtu    =3D GIF_MTU;
+	sc->gif_if.if_flags  =3D IFF_POINTOPOINT | IFF_MULTICAST;
 #if 0
-		/* turn off ingress filter */
-		sc->gif_if.if_flags  |=3D IFF_LINK2;
+	/* turn off ingress filter */
+	sc->gif_if.if_flags  |=3D IFF_LINK2;
 #endif
-		sc->gif_if.if_ioctl  =3D gif_ioctl;
-		sc->gif_if.if_output =3D gif_output;
-		sc->gif_if.if_type   =3D IFT_GIF;
-		sc->gif_if.if_snd.ifq_maxlen =3D IFQ_MAXLEN;
-		if_attach(&sc->gif_if);
-#if NBPFILTER > 0
-#ifdef HAVE_OLD_BPF
-		bpfattach(&sc->gif_if, DLT_NULL, sizeof(u_int));
-#else
-		bpfattach(&sc->gif_if.if_bpf, &sc->gif_if, DLT_NULL, sizeof(u_int));
+	sc->gif_if.if_ioctl  =3D gif_ioctl;
+	sc->gif_if.if_output =3D gif_output;
+	sc->gif_if.if_type   =3D IFT_GIF;
+	sc->gif_if.if_snd.ifq_maxlen =3D IFQ_MAXLEN;
+	if_attach(&sc->gif_if);
+	bpfattach(&sc->gif_if, DLT_NULL, sizeof(u_int));
+	TAILQ_INSERT_TAIL(&gifs, sc, gif_link);
+	return (0);
+}
+
+void
+gif_clone_destroy(ifp)
+	struct ifnet *ifp;
+{
+	int err;
+	struct gif_softc *sc =3D ifp->if_softc;
+
+	gif_delete_tunnel(sc);
+	TAILQ_REMOVE(&gifs, sc, gif_link);
+	if (sc->encap_cookie4 !=3D NULL) {
+		err =3D encap_detach(sc->encap_cookie4);
+		KASSERT(err =3D=3D 0, ("Unexpected error detaching encap_cookie4"));
+	}
+	if (sc->encap_cookie6 !=3D NULL) {
+		err =3D encap_detach(sc->encap_cookie6);
+		KASSERT(err =3D=3D 0, ("Unexpected error detaching encap_cookie6"));
+	}
+
+	bpfdetach(ifp);
+	if_detach(ifp);
+
+	err =3D rman_release_resource(sc->r_unit);
+	KASSERT(err =3D=3D 0, ("Unexpected error freeing resource"));
+
+	free(sc, M_GIF);
+}
+
+static int
+gifmodevent(mod, type, data)
+	module_t mod;
+	int type;
+	void *data;
+{
+	int err;
+
+	switch (type) {
+	case MOD_LOAD:
+		gifunits->rm_type =3D RMAN_ARRAY;
+		gifunits->rm_descr =3D "configurable if_gif units";
+		err =3D rman_init(gifunits);
+		if (err !=3D 0)
+			return (err);
+		err =3D rman_manage_region(gifunits, 0, GIF_MAXUNIT);
+		if (err !=3D 0) {
+			printf("%s: gifunits: rman_manage_region: Failed %d\n",
+			    GIFNAME, err);
+			rman_fini(gifunits);
+			return (err);
+		}
+		if_clone_attach(&gif_cloner);
+
+#ifdef INET6
+		ip6_gif_hlim =3D GIF_HLIM;
 #endif
+
+		break;
+	case MOD_UNLOAD:
+		if_clone_detach(&gif_cloner);
+
+		while (!TAILQ_EMPTY(&gifs))
+			gif_clone_destroy(&TAILQ_FIRST(&gifs)->gif_if);
+
+		err =3D rman_fini(gifunits);
+		if (err !=3D 0)
+			return (err);
+#ifdef INET6
+		ip6_gif_hlim =3D 0;
 #endif
+		break;
 	}
+	return 0;
 }
+
+static moduledata_t gif_mod =3D {
+	"if_gif",
+	gifmodevent,
+	0
+};
=20
-PSEUDO_SET(gifattach, if_gif);
+DECLARE_MODULE(if_gif, gif_mod, SI_SUB_PSEUDO, SI_ORDER_ANY);
=20
 static int
 gif_encapcheck(m, off, proto, arg)
@@ -261,7 +378,6 @@
 		goto end;
 	}
=20
-#if NBPFILTER > 0
 	if (ifp->if_bpf) {
 		/*
 		 * We need to prepend the address family as
@@ -277,13 +393,8 @@
 		m0.m_len =3D 4;
 		m0.m_data =3D (char *)&af;
 	=09
-#ifdef HAVE_OLD_BPF
 		bpf_mtap(ifp, &m0);
-#else
-		bpf_mtap(ifp->if_bpf, &m0);
-#endif
 	}
-#endif
 	ifp->if_opackets++;=09
 	ifp->if_obytes +=3D m->m_pkthdr.len;
=20
@@ -333,7 +444,6 @@
=20
 	m->m_pkthdr.rcvif =3D gifp;
 =09
-#if NBPFILTER > 0
 	if (gifp->if_bpf) {
 		/*
 		 * We need to prepend the address family as
@@ -349,13 +459,8 @@
 		m0.m_len =3D 4;
 		m0.m_data =3D (char *)&af1;
 	=09
-#ifdef HAVE_OLD_BPF
 		bpf_mtap(gifp, &m0);
-#else
-		bpf_mtap(gifp->if_bpf, &m0);
-#endif
 	}
-#endif /*NBPFILTER > 0*/
=20
 	/*
 	 * Put the packet to the network layer input queue according to the
@@ -408,8 +513,8 @@
 	int error =3D 0, size;
 	struct sockaddr *dst, *src;
 	struct sockaddr *sa;
-	int i;
 	int s;
+	struct ifnet *ifp2;
 	struct gif_softc *sc2;
 	=09
 	switch (cmd) {
@@ -523,8 +628,10 @@
 			break;
 		}
=20
-		for (i =3D 0; i < ngif; i++) {
-			sc2 =3D gif + i;
+		TAILQ_FOREACH(ifp2, &ifnet, if_link) {
+			if (strcmp(ifp2->if_name, GIFNAME) !=3D 0)
+				continue;
+			sc2 =3D ifp2->if_softc;
 			if (sc2 =3D=3D sc)
 				continue;
 			if (!sc2->gif_pdst || !sc2->gif_psrc)
@@ -697,5 +804,21 @@
 	}
  bad:
 	return error;
+}
+
+void
+gif_delete_tunnel(sc)
+	struct gif_softc *sc;
+{
+	/* XXX: NetBSD protects this function with splsoftnet() */
+
+	if (sc->gif_psrc) {
+		free((caddr_t)sc->gif_psrc, M_IFADDR);
+		sc->gif_psrc =3D NULL;
+	}
+	if (sc->gif_pdst) {
+		free((caddr_t)sc->gif_pdst, M_IFADDR);
+		sc->gif_pdst =3D NULL;
+	}
+	/* change the IFF_UP flag as well? */
 }
-#endif /*NGIF > 0*/
Index: sys/net/if_gif.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /home/ncvs/src/sys/net/if_gif.h,v
retrieving revision 1.4
diff -u -u -r1.4 if_gif.h
--- sys/net/if_gif.h	2001/06/11 12:38:58	1.4
+++ sys/net/if_gif.h	2001/06/25 20:16:12
@@ -60,6 +60,8 @@
 	int		gif_flags;
 	const struct encaptab *encap_cookie4;
 	const struct encaptab *encap_cookie6;
+	struct resource *r_unit;	/* resource allocated for this unit */
+	TAILQ_ENTRY(gif_softc) gif_link; /* all gif's are linked */
 };
=20
 #define gif_ro gifsc_gifscr.gifscr_ro
Index: sys/net/if_stf.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /home/ncvs/src/sys/net/if_stf.c,v
retrieving revision 1.7
diff -u -u -r1.7 if_stf.c
--- sys/net/if_stf.c	2001/06/11 12:38:58	1.7
+++ sys/net/if_stf.c	2001/06/25 20:11:52
@@ -98,12 +98,12 @@
 #include <netinet/in.h>
 #include <netinet/in_systm.h>
 #include <netinet/ip.h>
+#include <netinet/ipprotosw.h>
 #include <netinet/ip_var.h>
 #include <netinet/in_var.h>
=20
 #include <netinet/ip6.h>
 #include <netinet6/ip6_var.h>
-#include <netinet6/in6_gif.h>
 #include <netinet6/in6_var.h>
 #include <netinet/ip_ecn.h>
=20
@@ -113,23 +113,7 @@
=20
 #include <net/net_osdep.h>
=20
-#include "bpf.h"
-#define NBPFILTER	NBPF
-#include "stf.h"
-#include "gif.h"	/*XXX*/
-
-#if NBPFILTER > 0
 #include <net/bpf.h>
-#endif
-
-#if NGIF > 0
-#include <net/if_gif.h>
-#endif
-
-#if NSTF > 0
-#if NSTF !=3D 1
-# error only single stf interface allowed
-#endif
=20
 #define IN6_IS_ADDR_6TO4(x)	(ntohs((x)->s6_addr16[0]) =3D=3D 0x2002)
 #define GET_V4(x)	((struct in_addr *)(&(x)->s6_addr16[1]))
@@ -145,17 +129,20 @@
 };
=20
 static struct stf_softc *stf;
-static int nstf;
=20
-#if NGIF > 0
-extern int ip_gif_ttl;	/*XXX*/
-#else
-static int ip_gif_ttl =3D 40;	/*XXX*/
-#endif
+static MALLOC_DEFINE(M_STF, "stf", "6to4 Tunnel Interface");
+static int ip_stf_ttl =3D 40;
=20
-extern struct protosw in_stf_protosw;
+extern  struct domain inetdomain;
+struct ipprotosw in_stf_protosw =3D
+{ SOCK_RAW,	&inetdomain,	IPPROTO_IPV6,	PR_ATOMIC|PR_ADDR,
+  in_stf_input, rip_output,	0,		rip_ctloutput,
+  0,
+  0,            0,              0,              0,
+  &rip_usrreqs
+};
=20
-void stfattach __P((void *));
+static int stfmodevent __P((module_t, int, void *));
 static int stf_encapcheck __P((const struct mbuf *, int, int, void *));
 static struct in6_ifaddr *stf_getsrcifa6 __P((struct ifnet *));
 static int stf_output __P((struct ifnet *, struct mbuf *, struct sockaddr =
*,
@@ -167,31 +154,31 @@
 static void stf_rtrequest __P((int, struct rtentry *, struct sockaddr *));
 static int stf_ioctl __P((struct ifnet *, u_long, caddr_t));
=20
-void
-stfattach(dummy)
-	void *dummy;
+static int
+stfmodevent(mod, type, data)
+	module_t mod;
+	int type;
+	void *data;
 {
 	struct stf_softc *sc;
-	int i;
+	int err;
 	const struct encaptab *p;
+
+	switch (type) {
+	case MOD_LOAD:
+		stf =3D malloc(sizeof(struct stf_softc), M_STF, M_WAITOK);
+		bzero(stf, sizeof(struct stf_softc));
+		sc =3D stf;
=20
-	nstf =3D NSTF;
-	stf =3D malloc(nstf * sizeof(struct stf_softc), M_DEVBUF, M_WAITOK);
-	bzero(stf, nstf * sizeof(struct stf_softc));
-	sc =3D stf;
-
-	/* XXX just in case... */
-	for (i =3D 0; i < nstf; i++) {
-		sc =3D &stf[i];
 		bzero(sc, sizeof(*sc));
 		sc->sc_if.if_name =3D "stf";
-		sc->sc_if.if_unit =3D i;
+		sc->sc_if.if_unit =3D 0;
=20
 		p =3D encap_attach_func(AF_INET, IPPROTO_IPV6, stf_encapcheck,
 		    &in_stf_protosw, sc);
 		if (p =3D=3D NULL) {
 			printf("%s: attach failed\n", if_name(&sc->sc_if));
-			continue;
+			return (ENOMEM);
 		}
 		sc->encap_cookie =3D p;
=20
@@ -206,18 +193,33 @@
 #endif
 		sc->sc_if.if_snd.ifq_maxlen =3D IFQ_MAXLEN;
 		if_attach(&sc->sc_if);
-#if NBPFILTER > 0
 #ifdef HAVE_OLD_BPF
 		bpfattach(&sc->sc_if, DLT_NULL, sizeof(u_int));
 #else
 		bpfattach(&sc->sc_if.if_bpf, &sc->sc_if, DLT_NULL, sizeof(u_int));
 #endif
-#endif
+		break;
+	case MOD_UNLOAD:
+		sc =3D stf;
+		bpfdetach(&sc->sc_if);
+		if_detach(&sc->sc_if);
+		err =3D encap_detach(sc->encap_cookie);
+		KASSERT(err =3D=3D 0, ("Unexpected error detaching encap_cookie"));
+		free(sc, M_STF);
+		break;
 	}
+
+	return (0);
 }
=20
-PSEUDO_SET(stfattach, if_stf);
+static moduledata_t stf_mod =3D {
+	"if_stf",
+	stfmodevent,
+	0
+};
=20
+DECLARE_MODULE(if_stf, stf_mod, SI_SUB_PSEUDO, SI_ORDER_ANY);
+
 static int
 stf_encapcheck(m, off, proto, arg)
 	const struct mbuf *m;
@@ -389,7 +391,7 @@
 	    &ip->ip_src, sizeof(ip->ip_src));
 	bcopy(in4, &ip->ip_dst, sizeof(ip->ip_dst));
 	ip->ip_p =3D IPPROTO_IPV6;
-	ip->ip_ttl =3D ip_gif_ttl;	/*XXX*/
+	ip->ip_ttl =3D ip_stf_ttl;
 	ip->ip_len =3D m->m_pkthdr.len;	/*host order*/
 	if (ifp->if_flags & IFF_LINK1)
 		ip_ecn_ingress(ECN_ALLOWED, &ip->ip_tos, &tos);
@@ -583,7 +585,6 @@
=20
 	m->m_pkthdr.rcvif =3D ifp;
 =09
-#if NBPFILTER > 0
 	if (ifp->if_bpf) {
 		/*
 		 * We need to prepend the address family as
@@ -605,7 +606,6 @@
 		bpf_mtap(ifp->if_bpf, &m0);
 #endif
 	}
-#endif /*NBPFILTER > 0*/
=20
 	/*
 	 * Put the packet to the network layer input queue according to the
@@ -679,5 +679,3 @@
=20
 	return error;
 }
-
-#endif /* NSTF > 0 */
Index: sys/netinet/in_gif.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /home/ncvs/src/sys/netinet/in_gif.c,v
retrieving revision 1.10
diff -u -u -r1.10 in_gif.c
--- sys/netinet/in_gif.c	2001/06/11 12:39:00	1.10
+++ sys/netinet/in_gif.c	2001/06/22 19:21:57
@@ -67,17 +67,9 @@
=20
 #include <net/if_gif.h>=09
=20
-#include "gif.h"
-
-#include <machine/stdarg.h>
-
 #include <net/net_osdep.h>
=20
-#if NGIF > 0
 int ip_gif_ttl =3D GIF_TTL;
-#else
-int ip_gif_ttl =3D 0;
-#endif
 SYSCTL_INT(_net_inet_ip, IPCTL_GIF_TTL, gifttl, CTLFLAG_RW,
 	&ip_gif_ttl,	0, "");
=20
@@ -210,25 +202,15 @@
 }
=20
 void
-#if __STDC__
-in_gif_input(struct mbuf *m, ...)
-#else
-in_gif_input(m, va_alist)
+in_gif_input(m, off, proto)
 	struct mbuf *m;
-	va_dcl
-#endif
+	int off;
+	int proto;
 {
-	int off, proto;
 	struct ifnet *gifp =3D NULL;
 	struct ip *ip;
-	va_list ap;
 	int af;
 	u_int8_t otos;
-
-	va_start(ap, m);
-	off =3D va_arg(ap, int);
-	proto =3D va_arg(ap, int);
-	va_end(ap);
=20
 	ip =3D mtod(m, struct ip *);
=20
Index: sys/netinet/in_gif.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /home/ncvs/src/sys/netinet/in_gif.h,v
retrieving revision 1.4
diff -u -u -r1.4 in_gif.h
--- sys/netinet/in_gif.h	2000/07/04 16:35:05	1.4
+++ sys/netinet/in_gif.h	2001/06/22 19:19:23
@@ -37,7 +37,7 @@
=20
 extern int ip_gif_ttl;
=20
-void in_gif_input __P((struct mbuf *, ...));
+void in_gif_input __P((struct mbuf *, int off, int proto));
 int in_gif_output __P((struct ifnet *, int, struct mbuf *, struct rtentry =
*));
 int gif_encapcheck4 __P((const struct mbuf *, int, int, void *));
=20
Index: sys/netinet/in_proto.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /home/ncvs/src/sys/netinet/in_proto.c,v
retrieving revision 1.56
diff -u -u -r1.56 in_proto.c
--- sys/netinet/in_proto.c	2001/06/11 12:39:00	1.56
+++ sys/netinet/in_proto.c	2001/06/11 17:41:06
@@ -78,16 +78,6 @@
 #include <netinet6/ipcomp.h>
 #endif /* IPSEC */
=20
-#include "gif.h"
-#if NGIF > 0
-#include <netinet/in_gif.h>
-#endif
-
-#include "stf.h"
-#if NSTF > 0
-#include <net/if_stf.h>
-#endif
-
 #ifdef IPXIP
 #include <netipx/ipx_ip.h>
 #endif
@@ -212,26 +202,6 @@
   &rip_usrreqs
 },
 };
-
-#if NGIF > 0
-struct ipprotosw in_gif_protosw =3D
-{ SOCK_RAW,	&inetdomain,	0/*IPPROTO_IPV[46]*/,	PR_ATOMIC|PR_ADDR,
-  in_gif_input, rip_output,	0,		rip_ctloutput,
-  0,
-  0,            0,              0,              0,
-  &rip_usrreqs
-};
-#endif /*NGIF*/
-
-#if NSTF > 0
-struct ipprotosw in_stf_protosw =3D
-{ SOCK_RAW,	&inetdomain,	IPPROTO_IPV6,	PR_ATOMIC|PR_ADDR,
-  in_stf_input, rip_output,	0,		rip_ctloutput,
-  0,
-  0,            0,              0,              0,
-  &rip_usrreqs
-};
-#endif /*NSTF*/
=20
 extern int in_inithead __P((void **, int));
=20
Index: sys/netinet6/in6.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /home/ncvs/src/sys/netinet6/in6.c,v
retrieving revision 1.12
diff -u -u -r1.12 in6.c
--- sys/netinet6/in6.c	2001/06/11 12:39:05	1.12
+++ sys/netinet6/in6.c	2001/06/11 17:00:35
@@ -105,11 +105,6 @@
 #include <netinet6/in6_pcb.h>
 #endif
=20
-#include "gif.h"
-#if NGIF > 0
-#include <net/if_gif.h>
-#endif
-
 #include <net/net_osdep.h>
=20
 MALLOC_DEFINE(M_IPMADDR, "in6_multi", "internet multicast address");
Index: sys/netinet6/in6_proto.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /home/ncvs/src/sys/netinet6/in6_proto.c,v
retrieving revision 1.14
diff -u -u -r1.14 in6_proto.c
--- sys/netinet6/in6_proto.c	2001/06/11 12:39:05	1.14
+++ sys/netinet6/in6_proto.c	2001/06/11 17:01:55
@@ -128,11 +128,6 @@
=20
 #include <netinet6/ip6protosw.h>
=20
-#include "gif.h"
-#if NGIF > 0
-#include <netinet6/in6_gif.h>
-#endif
-
 #include <net/net_osdep.h>
=20
 /*
@@ -251,16 +246,6 @@
 },
 };
=20
-#if NGIF > 0
-struct ip6protosw in6_gif_protosw =3D
-{ SOCK_RAW,	&inet6domain,	0/*IPPROTO_IPV[46]*/,	PR_ATOMIC|PR_ADDR,
-  in6_gif_input, rip6_output,	0,		rip6_ctloutput,
-  0,
-  0,            0,              0,              0,
-  &rip6_usrreqs
-};
-#endif /*NGIF*/
-
 extern int in6_inithead __P((void **, int));
=20
 struct domain inet6domain =3D
@@ -299,11 +284,7 @@
 int	ip6_dad_count =3D 1;	/* DupAddrDetectionTransmits */
 u_int32_t ip6_flow_seq;
 int	ip6_auto_flowlabel =3D 1;
-#if NGIF > 0
-int	ip6_gif_hlim =3D GIF_HLIM;
-#else
 int	ip6_gif_hlim =3D 0;
-#endif
 int	ip6_use_deprecated =3D 1;	/* allow deprecated addr (RFC2462 5.5.4) */
 int	ip6_rr_prune =3D 5;	/* router renumbering prefix
 				 * walk list every 5 sec.    */
Index: sys/netinet6/ip6_input.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /home/ncvs/src/sys/netinet6/ip6_input.c,v
retrieving revision 1.27
diff -u -u -r1.27 ip6_input.c
--- sys/netinet6/ip6_input.c	2001/06/11 12:39:05	1.27
+++ sys/netinet6/ip6_input.c	2001/06/11 16:58:56
@@ -121,7 +121,6 @@
 #include <netinet6/ip6protosw.h>
=20
 #include "faith.h"
-#include "gif.h"
=20
 #include <net/net_osdep.h>
=20
Index: sys/sys/sockio.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /home/ncvs/src/sys/sys/sockio.h,v
retrieving revision 1.18
diff -u -u -r1.18 sockio.h
--- sys/sys/sockio.h	2001/06/11 20:34:19	1.18
+++ sys/sys/sockio.h	2001/06/21 21:22:58
@@ -100,4 +100,8 @@
 #define	SIOCGIFSTATUS	_IOWR('i', 59, struct ifstat)	/* get IF status */
 #define	SIOCSIFLLADDR	_IOW('i', 60, struct ifreq)	/* set link level addr */
=20
+#define SIOCIFCREATE	_IOWR('i', 122, struct ifreq)	/* create clone if */
+#define SIOCIFDESTROY	 _IOW('i', 121, struct ifreq)	/* destroy clone if */
+#define SIOCIFGCLONERS	_IOWR('i', 120, struct if_clonereq) /* get cloners =
*/
+
 #endif /* !_SYS_SOCKIO_H_ */
Index: sys/modules/Makefile
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /home/ncvs/src/sys/modules/Makefile,v
retrieving revision 1.186
diff -u -u -r1.186 Makefile
--- sys/modules/Makefile	2001/06/14 15:15:54	1.186
+++ sys/modules/Makefile	2001/06/22 01:10:08
@@ -8,7 +8,8 @@
=20
 SUBDIR=3D	3dfx accf_data accf_http agp aha amr an aue \
 	cam ccd cd9660 coda cue dc de dgm digi ed fdescfs fs fxp if_disc if_ef \
-	if_ppp if_sl if_tap if_tun ip6fw ipfilter ipfw ispfw joy kue lge \
+	if_gif if_ppp if_sl if_stf if_tap if_tun \
+	ip6fw ipfilter ipfw ispfw joy kue lge \
 	libmchain linux lnc md mii mlx msdosfs ncp netgraph nfs nge ntfs \
 	nullfs nwfs pcn portalfs procfs ${_random}  \
 	rl rp sf sis sk sn snp sound sppp ste sym syscons sysvipc ti tl twe \
--- sys/modules/if_gif/Makefile.orig	Fri Jun  8 19:00:25 2001
+++ sys/modules/if_gif/Makefile	Fri Jun  8 19:04:43 2001
@@ -0,0 +1,18 @@
+# $FreeBSD$
+
+.PATH: ${.CURDIR}/../../net ${.CURDIR}/../../netinet ${.CURDIR}/../../neti=
net6
+
+KMOD=3D	if_gif
+SRCS=3D	if_gif.c in_gif.c in6_gif.c opt_inet.h opt_inet6.h opt_mrouting.h
+NOMAN=3D
+
+opt_inet.h:
+	echo "#define INET 1" > ${.TARGET}
+
+opt_inet6.h:
+	echo "#define INET6 1" > ${.TARGET}
+
+opt_mrouting.h:
+	echo "#define MROUTING 1" > ${.TARGET}
+
+.include <bsd.kmod.mk>
--- sys/modules/if_stf/Makefile.orig	Mon Jun 11 11:34:03 2001
+++ sys/modules/if_stf/Makefile	Mon Jun 11 11:36:30 2001
@@ -0,0 +1,15 @@
+# $FreeBSD$
+
+.PATH: ${.CURDIR}/../../net
+
+KMOD=3D	if_stf
+SRCS=3D	if_stf.c opt_inet.h opt_inet6.h
+NOMAN=3D
+
+opt_inet.h:
+	echo "#define INET 1" > ${.TARGET}
+
+opt_inet6.h:
+	echo "#define INET6 1" > ${.TARGET}
+
+.include <bsd.kmod.mk>
Index: etc/rc.network
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /home/ncvs/src/etc/rc.network,v
retrieving revision 1.99
diff -u -u -r1.99 rc.network
--- etc/rc.network	2001/06/16 15:48:43	1.99
+++ etc/rc.network	2001/06/22 01:29:04
@@ -766,7 +766,7 @@
 				continue
 				;;
 			*)
-				ifconfig $i tunnel ${peers}
+				ifconfig $i create tunnel ${peers}
 				;;
 			esac
 		done
Index: share/man/man4/gif.4
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /home/ncvs/src/share/man/man4/gif.4,v
retrieving revision 1.9
diff -u -r1.9 gif.4
--- share/man/man4/gif.4	2001/06/11 12:38:48	1.9
+++ share/man/man4/gif.4	2001/06/25 20:42:04
@@ -35,7 +35,7 @@
 .Nm gif
 .Nd generic tunnel interface
 .Sh SYNOPSIS
-.Cd "device gif" Op Ar count
+.Cd "device gif"
 .Sh DESCRIPTION
 The
 .Nm
@@ -210,3 +210,19 @@
 .Dv IFF_LINK0
 flag.
 The behavior was obsoleted and is no longer supported.
+.Pp
+In some cases, when
+.Cm ifconfig gifN destroy
+is executed, an IPv6 default route is removed.
+This problem occures when the following conditions are met:
+.Bl -dash -offset indent -compact
+.It
+The host doesn't accept RA (i.e. net.inet6.ip6.accept_rtadv=3D0),
+.It
+the default route is installed manually, and
+.It
+.Cm ifconfig gifN destroy
+is executed.
+.El
+It is thought that this is not actually a bug in gif, but rather lies
+somewhere around a manipulation of an IPv6 routing table.

--PNTmBPCT7hxwcZjr
Content-Type: application/pgp-signature
Content-Disposition: inline

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.0.4 (GNU/Linux)
Comment: For info see http://www.gnupg.org

iD8DBQE7OQHwXY6L6fI4GtQRAjnsAKC3laFZY6DXqns41zRclOrTtYKPLwCfRxrn
NZRRjCE/ol1qSUMwRxh+mkg=
=uDfo
-----END PGP SIGNATURE-----

--PNTmBPCT7hxwcZjr--

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-audit" in the body of the message




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