Skip site navigation (1)Skip section navigation (2)
Date:      Fri,  8 Jun 2001 19:20:51 -0700 (PDT)
From:      Brooks Davis <brooks@one-eyed-alien.net>
To:        FreeBSD-gnats-submit@freebsd.org
Subject:   kern/27983: [PATCH] make gif fully dynamic
Message-ID:  <20010609022051.DE1CE24D1F@minya.sea.one-eyed-alien.net>

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

>Number:         27983
>Category:       kern
>Synopsis:       [PATCH] make gif fully dynamic
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Fri Jun 08 19:20:01 PDT 2001
>Closed-Date:
>Last-Modified:
>Originator:     Brooks Davis
>Release:        FreeBSD 5.0-CURRENT i386
>Organization:
The Aerospace Corporation
>Environment:
System: FreeBSD minya.sea.one-eyed-alien.net 5.0-CURRENT FreeBSD 5.0-CURRENT #41: Fri Jun 8 18:53:08 PDT 2001 root@minya.sea.one-eyed-alien.net:/usr/src/sys/compile/MINYA i386


>Description:

Make the gif(4) interface both loadable and demand allocatable.
Add generic ifconfig support to enable similar changes to other pseudo
devices such as lp, faith, ppp, and stf.

>How-To-Repeat:
>Fix:

in /usr/src do "mkdir sys/modules/if_gif" and apply the following patch:

Index: sbin/ifconfig/ifconfig.8
===================================================================
RCS file: /home/ncvs/src/sbin/ifconfig/ifconfig.8,v
retrieving revision 1.41
diff -u -u -r1.41 ifconfig.8
--- sbin/ifconfig/ifconfig.8	2001/06/02 04:09:53	1.41
+++ sbin/ifconfig/ifconfig.8	2001/06/09 01:14:31
@@ -50,6 +50,9 @@
 .Oc
 .Op Ar parameters
 .Nm
+.Fl D
+.Ar interface
+.Nm
 .Fl a
 .Op Fl L
 .Op Fl d
@@ -142,6 +145,16 @@
 .Dq name unit ,
 for example,
 .Dq en0 .
+Generally this device must exist, but some pseudo interfaces support
+creation of demand.
+For those devices, an arbitrary unit number may be specified and the
+interface will be created so long as another parameter is specified.
+Additionally, a wildcard name of the form
+.Dq driver# ,
+for example,
+.Dq gif# ,
+may be specified which will cause a new interface to be created.
+In this case the new interface name will be printed to stdout.
 .El
 .Pp
 The following parameters may be set with 
@@ -537,12 +550,18 @@
 .Nm
 will report only the details specific to that protocol family.
 .Pp
-If the driver does supports the media selection system, the supported
-media list will be included in the output.
+If the
+.Fl D
+flag is passed before an interface name
+.Nm
+will attempt to delete
+the interface via its control device.
 .Pp
 If the
 .Fl m
-flag is passed before an interface name, ifconfig will display all
+flag is passed before an interface name,
+.Nm
+will display all
 of the supported media for the specified interface.
 If
 .Fl L
Index: sbin/ifconfig/ifconfig.c
===================================================================
RCS file: /home/ncvs/src/sbin/ifconfig/ifconfig.c,v
retrieving revision 1.62
diff -u -u -r1.62 ifconfig.c
--- sbin/ifconfig/ifconfig.c	2001/05/29 09:13:44	1.62
+++ sbin/ifconfig/ifconfig.c	2001/06/09 01:25:27
@@ -104,6 +104,10 @@
 #define	NI_WITHSCOPEID	0
 #endif
 
+#ifndef WILDCARDUNIT
+#define WILDCARDUNIT	'#'
+#endif
+
 struct	ifreq		ifr, ridreq;
 struct	ifaliasreq	addreq;
 #ifdef INET6
@@ -128,6 +132,7 @@
 int	doalias;
 int	clearaddr;
 int	newaddr = 1;
+int	deleteif;
 #ifdef INET6
 static	int ip6lifetime;
 #endif
@@ -150,7 +155,13 @@
 		    struct sockaddr_dl *sdl, struct if_msghdr *ifm,
 		    struct ifa_msghdr *ifam));
 void	usage __P((void));
-void	ifmaybeload __P((char *name));
+void	name2typeunit __P((const char *name, char *type, size_t tlen,
+			    int *unit));
+void	typeunit2name __P((char *name, size_t nlen, const char *type,
+			    int unit));
+void	ifmaybeload __P((const char *name));
+int	ifmaybecreate __P((char *name, size_t len, int trystatic));
+void	ifdelete __P((const char *name));
 
 #ifdef INET6
 int	prefix __P((void *, int));
@@ -350,16 +361,18 @@
 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",
 	"usage: ifconfig interface address_family [address [dest_address]]",
 	"                [parameters]",
+	"       ifconfig -D interface",
 	"       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",
 	"usage: ifconfig [-L] interface address_family [address [dest_address]]",
 	"                [parameters]",
+	"       ifconfig -D interface",
 	"       ifconfig -a [-L] [-d] [-m] [-u] [address_family]",
 	"       ifconfig -l [-d] [-u] [address_family]",
 	"       ifconfig [-L] [-d] [-m] [-u]");
@@ -388,7 +401,7 @@
 
 	/* Parse leading line options */
 	all = downonly = uponly = namesonly = 0;
-	while ((c = getopt(argc, argv, "adlmu"
+	while ((c = getopt(argc, argv, "adDlmu"
 #ifdef INET6
 					"L"
 #endif
@@ -411,6 +424,9 @@
 		case 'u':	/* restrict scan to "up" interfaces */
 			uponly++;
 			break;
+		case 'D':	/* delete the specified interface */
+			deleteif++;
+			break;
 		case 'm':	/* show media choices in status */
 			supmedia = 1;
 			break;
@@ -430,10 +446,19 @@
 	if (uponly && downonly)
 		usage();
 
+	/* -D make no sense with any other flags or other then one argument */
+	if (deleteif && (argc != 1 || all || namesonly || uponly ||
+	    downonly || supmedia))
+		usage();
+
 	/* no arguments is equivalent to '-a' */
 	if (!namesonly && argc < 1)
 		all = 1;
 
+	/* -u and -d are meaningless with a specified interface */
+	if (!namesonly && !all && (uponly || downonly))
+		usage();
+
 	/* -a and -l allow an address family arg to limit the output */
 	if (all || namesonly) {
 		if (argc > 1)
@@ -457,8 +482,26 @@
 		strncpy(name, *argv, sizeof(name));
 		argc--, argv++;
 
+		if (deleteif) {
+			ifdelete(name);
+			return 0;
+		}
+
 		/* check and maybe load support for this interface */
 		ifmaybeload(name);
+
+		/*
+		 * If we're actually going to try and do something with
+		 * this device or the user want's a wildcard device, try
+		 * and create it for them.  If we create a wild card
+		 * device and we don't have anything to do with it, just
+		 * return now rather then printing it's status.  This
+		 * insures that wildcard creation prints the device name
+		 * and only the device name.
+		 */
+		if (ifmaybecreate(name, sizeof(name), (argc != 0)) == 2 &&
+		    argc == 0)
+			return 0;
 	}
 
 	/* Check for address family */
@@ -1644,19 +1687,73 @@
 #endif /*INET6*/
 
 void
-ifmaybeload(name)
+name2typeunit(name, type, tlen, unit)
+	const char *name;
+	char *type;
+	size_t tlen;
+	int *unit;
+{
+	char *cp;
+
+	/* copy the type */
+	for (cp = type; !isdigit(name[0]) && name[0] != WILDCARDUNIT &&
+	    name[0] != '\0' && tlen > 0; name++, cp++, tlen--)
+		cp[0] = name[0];
+	if (tlen == 0) {
+		goto error;
+	}
+
+	/* figure out the unit */
+	if (name[0] == WILDCARDUNIT) {
+		*unit = -1;
+		name++;
+	} else if (isdigit(name[0])) {
+		*unit = atoi(name);
+		for (; isdigit(name[0]); name++);
+	} else {
+		goto error;
+	}
+
+	if (name[0] != '\0')
+		goto error;
+
+	return;
+
+error:
+	type[0] = '\0';
+}
+
+void
+typeunit2name(name, nlen, type, unit)
 	char *name;
+	size_t nlen;
+	const char *type;
+	int unit;
+{
+	if(nlen <= 0)
+		return;
+
+	if(snprintf(name, nlen, "%s%d", type, unit) > nlen-1) {
+		/* just null the name if it doesn't fit */
+		name[0] = '\0';
+	}
+}
+
+void
+ifmaybeload(name)
+	const char *name;
 {
 	struct module_stat mstat;
-	int fileid, modid;
-	char ifkind[35], *cp, *dp;
+	int fileid, modid, unit;
+	char ifkind[35], type[35], *cp;
 
 
 	/* turn interface and unit into module name */
-	strcpy(ifkind, "if_");
-	for (cp = name, dp = ifkind + 3; (*cp != 0) && !isdigit(*cp); cp++, dp++)
-		*dp = *cp;
-	*dp = 0;
+	name2typeunit(name, type, sizeof(type), &unit);
+	if (type[0] == '\0')
+		return;
+	if (snprintf(ifkind, sizeof(ifkind), "if_%s", type) >= sizeof(ifkind))
+		return;
 
 	/* scan files in kernel */
 	mstat.version = sizeof(struct module_stat);
@@ -1680,4 +1777,98 @@
 
 	/* not present, we should try to load it */
 	kldload(ifkind);
+}
+
+/*
+ * Try to create the interface through a control node.  If nothing is
+ * created, return 0.  If a static interface is created return 1.  If a
+ * wildcard interface is created, return 2.
+ */
+int
+ifmaybecreate(name, len, trystatic)
+	char *name;
+	size_t len;
+	int trystatic;
+{
+	char if_dev[40];
+	int d;
+	int wildcard = 0;
+	struct if_manage ifman;
+
+	bzero(&ifman, sizeof(ifman));
+
+	/* turn interface and unit into control device name */
+	name2typeunit(name, ifman.ifman_name, sizeof(ifman.ifman_name),
+	    &ifman.ifman_unit);
+	if (ifman.ifman_name[0] == '\0')
+		return (0);
+	if (ifman.ifman_unit >= 0 && !trystatic)
+		return (0);
+	if (snprintf(if_dev, sizeof(if_dev), "/dev/if_%s",
+	    ifman.ifman_name) >= sizeof(if_dev))
+		return (0);
+	if (ifman.ifman_unit < 0)
+		wildcard = 1;
+
+	/* try to open the control device */
+	d = open(if_dev, O_RDWR);
+	if (d == -1)
+		return (0);
+
+	/* try to create the device in question */
+	ifman.ifman_action = IFMAN_CREATE;
+	if (ioctl(d, IOCIFMANAGE, &ifman) == -1) {
+		close(d);
+		return (0);
+	}
+	close(d);
+
+	/*
+	 * our name might have been changed (in the wildcard case) so
+	 * update it.
+	 * XXX: if the device is on crack and mangles non-wildcard
+	 * units, this could be weird.
+	 */
+	typeunit2name(name, len, ifman.ifman_name, ifman.ifman_unit);
+
+	if (name[0] != '\0' && wildcard) {
+		printf("%s\n", name);
+		return (2);
+	}
+
+	return (1);
+}
+
+void
+ifdelete(name)
+	const char *name;
+{
+	char if_dev[40];
+	int d;
+	struct if_manage ifman;
+
+	bzero(&ifman, sizeof(ifman));
+
+	ifman.ifman_action = IFMAN_DELETE;
+	name2typeunit(name, ifman.ifman_name, sizeof(ifman.ifman_name),
+	    &ifman.ifman_unit);
+	if (ifman.ifman_name[0] == '\0')
+		errx(1, "invalid interface");
+	if (ifman.ifman_unit < 0)
+		errx(1, "can't delete wildcard interface");
+	if (snprintf(if_dev, sizeof(if_dev), "/dev/if_%s",
+	    ifman.ifman_name) >= sizeof(if_dev))
+		return;
+
+	/* try to open the control device */
+	d = open(if_dev, O_RDWR);
+	if (d == -1)
+		return;
+
+	/* try to create the device in question */
+	if (ioctl(d, IOCIFMANAGE, &ifman) == -1) {
+		close(d);
+		err(1, "IOCIFMANAGE error");
+	}
+	close(d);
 }
Index: sys/conf/files
===================================================================
RCS file: /home/ncvs/src/sys/conf/files,v
retrieving revision 1.530
diff -u -u -r1.530 files
--- sys/conf/files	2001/06/05 04:26:12	1.530
+++ sys/conf/files	2001/06/08 19:48:21
@@ -881,7 +881,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
Index: sys/conf/majors
===================================================================
RCS file: /home/ncvs/src/sys/conf/majors,v
retrieving revision 1.124
diff -u -u -r1.124 majors
--- sys/conf/majors	2001/05/29 18:49:46	1.124
+++ sys/conf/majors	2001/06/07 23:58:18
@@ -179,6 +179,7 @@
 160	spic		Sony Programmable I/O Controller (jogdial)
 161	swdoc		Sitara networks watchdog device
 162	digi		Digiboard
+163	if_gif		Generic Tunneling control device
 200	??		entries from 200-252 are reserved for local use
 252	??		entries from 200-252 are reserved for local use
 254	internal	Used internally by the kernel
Index: sys/i386/conf/GENERIC
===================================================================
RCS file: /home/ncvs/src/sys/i386/conf/GENERIC,v
retrieving revision 1.311
diff -u -u -r1.311 GENERIC
--- sys/i386/conf/GENERIC	2001/05/30 03:18:22	1.311
+++ sys/i386/conf/GENERIC	2001/06/08 23:16:04
@@ -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)
 
 # The `bpf' device enables the Berkeley Packet Filter.
Index: sys/ia64/conf/GENERIC
===================================================================
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)
 
 # The `bpf' device enables the Berkeley Packet Filter.
Index: sys/alpha/conf/GENERIC
===================================================================
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)
 
 # The `bpf' device enables the Berkeley Packet Filter.
Index: sys/net/if_gif.c
===================================================================
RCS file: /home/ncvs/src/sys/net/if_gif.c,v
retrieving revision 1.9
diff -u -u -r1.9 if_gif.c
--- sys/net/if_gif.c	2001/06/03 17:31:11	1.9
+++ sys/net/if_gif.c	2001/06/08 23:52:55
@@ -1,4 +1,4 @@
-/*	$FreeBSD: src/sys/net/if_gif.c,v 1.9 2001/06/03 17:31:11 yar Exp $	*/
+/*	$FreeBSD: src/sys/net/if_gif.c,v 1.9 2001/06/03 17:31:11 yar Exp $ */
 /*	$KAME: if_gif.c,v 1.28 2000/06/20 12:30:03 jinmei Exp $	*/
 
 /*
@@ -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>
 
 #include <net/if.h>
@@ -58,6 +61,8 @@
 #include <netinet/in_var.h>
 #include <netinet/ip.h>
 #include <netinet/in_gif.h>
+#include <netinet/ip_var.h>
+#include <netinet/ipprotosw.h>
 #endif	/* INET */
 
 #ifdef INET6
@@ -74,28 +79,68 @@
 #include <netinet/ip_encap.h>
 #include <net/if_gif.h>
 
-#include "gif.h"
+#if defined(__FreeBSD__)
+#define NBPFILTER	1
+#else
 #include "bpf.h"
 #define NBPFILTER	NBPF
+#endif
 
 #include <net/net_osdep.h>
-
-#if NGIF > 0
 
-void gifattach __P((void *));
+#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 = TAILQ_HEAD_INITIALIZER(gifs);
+
+static int gifcreate __P((int *));
+static int gifdelete __P((int));
+static int gifmodevent __P((module_t, int, void *));
+static struct gif_softc *gifunit2sc __P((int unit));
 static int gif_encapcheck __P((const struct mbuf *, int, int, void *));
-#ifdef INET
-extern struct protosw in_gif_protosw;
-#endif
-#ifdef INET6
-extern struct ip6protosw in6_gif_protosw;
-#endif
 
-/*
- * gif global variable definitions
- */
-static int ngif;		/* number of interfaces */
-static struct gif_softc *gif = 0;
+#ifdef INET
+extern  struct domain inetdomain;
+struct ipprotosw in_gif_protosw =
+{ 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 =
+{ 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
+
+static d_ioctl_t	gifioctl;
+
+#define CDEV_MAJOR 163
+static struct cdevsw gif_cdevsw = {
+	/* open */	nullopen,
+	/* close */	nullclose,
+	/* read */	noread,
+	/* write */	nowrite,
+	/* ioctl */	gifioctl,
+	/* poll */	nopoll,
+	/* mmap */	nommap,
+	/* strategy */	nostrategy,
+	/* name */	GIFDEV,
+	/* maj */	CDEV_MAJOR,
+	/* dump */	nodump,
+	/* psize */	nopsize,
+	/* flags */	0,
+};
 
 #ifndef MAX_GIF_NEST
 /*
@@ -110,62 +155,252 @@
 #endif
 static int max_gif_nesting = MAX_GIF_NEST;
 
-void
-gifattach(dummy)
-	void *dummy;
+static struct gif_softc *
+gifunit2sc(unit)
+	int unit;
 {
-	register struct gif_softc *sc;
-	register int i;
+	struct gif_softc *sc;
+
+	TAILQ_FOREACH(sc, &gifs, gif_link) {
+		if (sc->gif_if.if_unit == unit)
+			break;
+	}
+	if (sc->gif_if.if_unit != unit)
+		return NULL;
+
+	return sc;
+}
+
+static int
+gifcreate(unit)
+	int *unit;
+{
+	struct resource *r;
+	struct gif_softc *sc;
+
+	if (*unit > GIF_MAXUNIT)
+		return (ENXIO);
 
-	ngif = NGIF;
-	gif = sc = malloc (ngif * sizeof(struct gif_softc), M_DEVBUF, M_WAITOK);
-	bzero(sc, ngif * sizeof(struct gif_softc));
-	for (i = 0; i < ngif; sc++, i++) {
-		sc->gif_if.if_name = "gif";
-		sc->gif_if.if_unit = i;
+	if (*unit < 0) {
+		r = rman_reserve_resource(gifunits, 0, GIF_MAXUNIT, 1,
+		    RF_ALLOCATED | RF_ACTIVE, NULL);
+		if (r == NULL)
+			return (ENOSPC);
+		*unit = rman_get_start(r);
+	} else {
+		r = rman_reserve_resource(gifunits, *unit, *unit, 1,
+		    RF_ALLOCATED | RF_ACTIVE, NULL);
+		if (r == NULL)
+			return (EBUSY);
+	}
+
+	sc = malloc (sizeof(struct gif_softc), M_GIF, M_WAITOK);
+	bzero(sc, sizeof(struct gif_softc));
+	sc->gif_if.if_softc = sc;
+	sc->gif_if.if_name = GIFNAME;
+	sc->gif_if.if_unit = *unit;
+	sc->r_unit = r;
 
-		sc->encap_cookie4 = sc->encap_cookie6 = NULL;
+	sc->encap_cookie4 = sc->encap_cookie6 = NULL;
 #ifdef INET
-		sc->encap_cookie4 = encap_attach_func(AF_INET, -1,
-		    gif_encapcheck, &in_gif_protosw, sc);
-		if (sc->encap_cookie4 == NULL) {
-			printf("%s: attach failed\n", if_name(&sc->gif_if));
-			continue;
-		}
+	sc->encap_cookie4 = encap_attach_func(AF_INET, -1,
+	    gif_encapcheck, &in_gif_protosw, sc);
+	if (sc->encap_cookie4 == NULL) {
+		free(sc, M_GIF);
+		return (ENOMEM);
+	}
 #endif
 #ifdef INET6
-		sc->encap_cookie6 = encap_attach_func(AF_INET6, -1,
-		    gif_encapcheck, (struct protosw *)&in6_gif_protosw, sc);
-		if (sc->encap_cookie6 == NULL) {
-			if (sc->encap_cookie4) {
-				encap_detach(sc->encap_cookie4);
-				sc->encap_cookie4 = NULL;
-			}
-			printf("%s: attach failed\n", if_name(&sc->gif_if));
-			continue;
+	sc->encap_cookie6 = encap_attach_func(AF_INET6, -1,
+	    gif_encapcheck, (struct protosw *)&in6_gif_protosw, sc);
+	if (sc->encap_cookie6 == NULL) {
+		if (sc->encap_cookie4) {
+			encap_detach(sc->encap_cookie4);
+			sc->encap_cookie4 = NULL;
 		}
+		free(sc, M_GIF);
+		return (ENOMEM);
+	}
 #endif
 
-		sc->gif_if.if_mtu    = GIF_MTU;
-		sc->gif_if.if_flags  = IFF_POINTOPOINT | IFF_MULTICAST;
-		sc->gif_if.if_ioctl  = gif_ioctl;
-		sc->gif_if.if_output = gif_output;
-		sc->gif_if.if_type   = IFT_GIF;
-		sc->gif_if.if_snd.ifq_maxlen = IFQ_MAXLEN;
-		if_attach(&sc->gif_if);
+	sc->gif_if.if_mtu    = GIF_MTU;
+	sc->gif_if.if_flags  = IFF_POINTOPOINT | IFF_MULTICAST;
+	sc->gif_if.if_ioctl  = gif_ifioctl;
+	sc->gif_if.if_output = gif_output;
+	sc->gif_if.if_type   = IFT_GIF;
+	sc->gif_if.if_snd.ifq_maxlen = IFQ_MAXLEN;
+	if_attach(&sc->gif_if);
 #if NBPFILTER > 0
 #ifdef HAVE_OLD_BPF
-		bpfattach(&sc->gif_if, DLT_NULL, sizeof(u_int));
+	bpfattach(&sc->gif_if, DLT_NULL, sizeof(u_int));
 #else
-		bpfattach(&sc->gif_if.if_bpf, &sc->gif_if, DLT_NULL, sizeof(u_int));
+	bpfattach(&sc->gif_if.if_bpf, &sc->gif_if, DLT_NULL, sizeof(u_int));
+#endif
+#endif
+
+	TAILQ_INSERT_TAIL(&gifs, sc, gif_link);
+
+	return (0);
+}
+
+static int
+gifdelete(unit)
+	int unit;
+{
+	int err;
+	struct gif_softc *sc;
+
+	sc = gifunit2sc(unit);
+	if (sc == NULL)
+		return (ENXIO);
+
+	bpfdetach(&sc->gif_if);
+	if_detach(&sc->gif_if);
+
+	if (sc->encap_cookie4 != NULL) {
+		err = encap_detach(sc->encap_cookie4);
+		KASSERT(err == 0, ("Unexpected error detaching encap_cookie4"));
+	}
+	if (sc->encap_cookie6 != NULL) {
+		err = encap_detach(sc->encap_cookie6);
+		KASSERT(err == 0, ("Unexpected error detaching encap_cookie6"));
+	}
+
+	if (sc->gif_psrc)
+		free((caddr_t)sc->gif_psrc, M_IFADDR);
+	if (sc->gif_pdst)
+		free((caddr_t)sc->gif_pdst, M_IFADDR);
+
+	err = rman_release_resource(sc->r_unit);
+	KASSERT(err == 0, ("Unexpected error freeing resource"));
+
+	TAILQ_REMOVE(&gifs, sc, gif_link);
+	free(sc, M_GIF);
+
+	return 0;
+}
+
+static int
+gifmodevent(mod, type, data)
+	module_t mod;
+	int type;
+	void *data;
+{
+	static dev_t dev;
+	int err;
+
+	switch (type) {
+	case MOD_LOAD:
+		if (!devfs_present) {
+			err = cdevsw_add(&gif_cdevsw);
+			if (err != 0) {
+				return (err);
+			}
+		}
+		gifunits->rm_type = RMAN_ARRAY;
+		gifunits->rm_descr = "configurable if_gif units";
+		err = rman_init(gifunits);
+		if (err != 0) {
+			if (!devfs_present)
+				cdevsw_remove(&gif_cdevsw);
+			return (err);
+		}
+		err = rman_manage_region(gifunits, 0, GIF_MAXUNIT);
+		if (err != 0) {
+			printf("%s: gifunits: rman_manage_region: Failed %d\n",
+			    GIFNAME, err);
+			rman_fini(gifunits);
+			if (!devfs_present)
+				cdevsw_remove(&gif_cdevsw);
+			return (err);
+		}
+		dev = make_dev(&gif_cdevsw, unit2minor(0),
+		    UID_ROOT, GID_WHEEL, 0600, GIFDEV, 0);
+
+#ifdef INET6
+		ip6_gif_hlim = GIF_HLIM;
 #endif
+
+		break;
+	case MOD_UNLOAD:
+		destroy_dev(dev);
+
+		while (!TAILQ_EMPTY(&gifs))
+			gifdelete(TAILQ_FIRST(&gifs)->gif_if.if_unit);
+
+		err = rman_fini(gifunits);
+		if (err != 0)
+			return (err);
+
+		if (!devfs_present)
+			cdevsw_remove(&gif_cdevsw);
+
+#ifdef INET6
+		ip6_gif_hlim = 0;
 #endif
+		break;
 	}
+	return 0;
 }
+
+static moduledata_t gif_mod = {
+	"if_gif",
+	gifmodevent,
+	0
+};
 
-PSEUDO_SET(gifattach, if_gif);
+DECLARE_MODULE(if_gif, gif_mod, SI_SUB_PSEUDO, SI_ORDER_ANY);
 
 static int
+gifioctl(dev, cmd, data, flag, p)
+	dev_t dev;
+	u_long cmd;
+	caddr_t data;
+	int flag;
+	struct proc *p;
+{
+	int err;
+	struct if_manage *ifman;
+	struct gif_softc *sc;
+
+	/* all actions require root, so check now. */
+	err = suser(p);
+	if (err != 0)
+		return (err);
+
+	switch (cmd) {
+	case IOCIFMANAGE:
+		ifman = (void*)data;
+		switch (ifman->ifman_action) {
+		case IFMAN_CREATE:
+			if (strcmp(GIFNAME, ifman->ifman_name) != 0)
+				return (EINVAL);
+			err = gifcreate(&ifman->ifman_unit);
+			if (err != 0)
+				return (err);
+			break;
+		case IFMAN_DELETE:
+			sc = gifunit2sc(ifman->ifman_unit);
+			if (sc == NULL)
+				return (ENXIO);
+			if (sc->gif_if.if_flags & IFF_UP)
+				return (EBUSY);
+			err = gifdelete(ifman->ifman_unit);
+			if(err != 0)
+				return (err);
+			break;
+		default:
+			return (EINVAL);
+		}
+		break;
+	default:
+		return (ENOTTY);
+	}
+
+	return (0);
+}
+
+static int
 gif_encapcheck(m, off, proto, arg)
 	const struct mbuf *m;
 	int off;
@@ -390,7 +625,7 @@
 
 /* XXX how should we handle IPv6 scope on SIOC[GS]IFPHYADDR? */
 int
-gif_ioctl(ifp, cmd, data)
+gif_ifioctl(ifp, cmd, data)
 	struct ifnet *ifp;
 	u_long cmd;
 	caddr_t data;
@@ -400,8 +635,8 @@
 	int error = 0, size;
 	struct sockaddr *dst, *src;
 	struct sockaddr *sa;
-	int i;
 	int s;
+	struct ifnet *ifp2;
 	struct gif_softc *sc2;
 		
 	switch (cmd) {
@@ -451,9 +686,12 @@
 			break;
 #endif
 		}
+
+		TAILQ_FOREACH(ifp2, &ifnet, if_link) {
+			if (strcmp(ifp2->if_name, GIFNAME) != 0)
+				continue;
+			sc2 = ifp2->if_softc;
 
-		for (i = 0; i < ngif; i++) {
-			sc2 = gif + i;
 			if (sc2 == sc)
 				continue;
 			if (!sc2->gif_pdst || !sc2->gif_psrc)
@@ -623,4 +861,3 @@
  bad:
 	return error;
 }
-#endif /*NGIF > 0*/
Index: sys/net/if_gif.h
===================================================================
RCS file: /home/ncvs/src/sys/net/if_gif.h,v
retrieving revision 1.3
diff -u -u -r1.3 if_gif.h
--- sys/net/if_gif.h	2000/07/04 16:35:04	1.3
+++ sys/net/if_gif.h	2001/06/08 17:20:27
@@ -62,6 +62,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 */
 };
 
 #define gif_ro gifsc_gifscr.gifscr_ro
@@ -77,6 +79,6 @@
 void gif_input __P((struct mbuf *, int, struct ifnet *));
 int gif_output __P((struct ifnet *, struct mbuf *,
 		    struct sockaddr *, struct rtentry *));
-int gif_ioctl __P((struct ifnet *, u_long, caddr_t));
+int gif_ifioctl __P((struct ifnet *, u_long, caddr_t));
 
 #endif /* _NET_IF_GIF_H_ */
Index: sys/net/if.h
===================================================================
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/08 02:01:44
@@ -241,6 +241,18 @@
 	struct	sockaddr_storage dstaddr; /* out */
 };
 
+/*
+ * Structure and definiation for IOCIFMANAGE
+ */
+struct if_manage {
+	int	ifman_action;
+#define IFMAN_CREATE	0
+#define IFMAN_DELETE	1
+	char	ifman_name[IFNAMSIZ];
+	int	ifman_unit;
+};
+#define IOCIFMANAGE	_IOWR('i', 190, struct if_manage)
+
 #ifdef _KERNEL
 #ifdef MALLOC_DECLARE
 MALLOC_DECLARE(M_IFADDR);
Index: sys/net/if_stf.c
===================================================================
RCS file: /home/ncvs/src/sys/net/if_stf.c,v
retrieving revision 1.6
diff -u -u -r1.6 if_stf.c
--- sys/net/if_stf.c	2001/02/03 11:46:35	1.6
+++ sys/net/if_stf.c	2001/06/08 19:41:26
@@ -102,7 +102,6 @@
 
 #include <netinet/ip6.h>
 #include <netinet6/ip6_var.h>
-#include <netinet6/in6_gif.h>
 #include <netinet6/in6_var.h>
 #include <netinet/ip_ecn.h>
 
@@ -115,16 +114,11 @@
 #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 != 1
 # error only single stf interface allowed
@@ -146,11 +140,7 @@
 static struct stf_softc *stf;
 static int nstf;
 
-#if NGIF > 0
-extern int ip_gif_ttl;	/*XXX*/
-#else
-static int ip_gif_ttl = 40;	/*XXX*/
-#endif
+static int ip_stf_ttl = 40;
 
 extern struct protosw in_stf_protosw;
 
@@ -364,7 +354,7 @@
 	    &ip->ip_src, sizeof(ip->ip_src));
 	bcopy(GET_V4(&dst6->sin6_addr), &ip->ip_dst, sizeof(ip->ip_dst));
 	ip->ip_p = IPPROTO_IPV6;
-	ip->ip_ttl = ip_gif_ttl;	/*XXX*/
+	ip->ip_ttl = ip_stf_ttl;
 	ip->ip_len = m->m_pkthdr.len;	/*host order*/
 	if (ifp->if_flags & IFF_LINK1)
 		ip_ecn_ingress(ECN_ALLOWED, &ip->ip_tos, &tos);
Index: sys/netinet/in.c
===================================================================
RCS file: /home/ncvs/src/sys/netinet/in.c,v
retrieving revision 1.53
diff -u -u -r1.53 in.c
--- sys/netinet/in.c	2001/05/11 14:37:34	1.53
+++ sys/netinet/in.c	2001/06/08 19:47:09
@@ -51,11 +51,6 @@
 
 #include <netinet/igmp_var.h>
 
-#include "gif.h"
-#if NGIF > 0
-#include <net/if_gif.h>
-#endif
-
 static MALLOC_DEFINE(M_IPMADDR, "in_multi", "internet multicast address");
 
 static int in_mask2len __P((struct in_addr *));
@@ -200,7 +195,6 @@
 	int error, hostIsNew, maskIsNew, s;
 	u_long i;
 
-#if NGIF > 0
         if (ifp && ifp->if_type == IFT_GIF) {
                 switch (cmd) {
                 case SIOCSIFPHYADDR:
@@ -210,10 +204,9 @@
         			return(error);
                 case SIOCGIFPSRCADDR:
                 case SIOCGIFPDSTADDR:
-                        return gif_ioctl(ifp, cmd, data);
+                        return ifp->if_ioctl(ifp, cmd, data);
                 }
         }
-#endif
 
 	switch (cmd) {
 	case SIOCALIFADDR:
Index: sys/netinet/in_gif.c
===================================================================
RCS file: /home/ncvs/src/sys/netinet/in_gif.c,v
retrieving revision 1.9
diff -u -u -r1.9 in_gif.c
--- sys/netinet/in_gif.c	2001/02/04 16:08:12	1.9
+++ sys/netinet/in_gif.c	2001/06/08 19:53:37
@@ -67,17 +67,11 @@
 
 #include <net/if_gif.h>	
 
-#include "gif.h"
-
 #include <machine/stdarg.h>
 
 #include <net/net_osdep.h>
 
-#if NGIF > 0
 int ip_gif_ttl = GIF_TTL;
-#else
-int ip_gif_ttl = 0;
-#endif
 SYSCTL_INT(_net_inet_ip, IPCTL_GIF_TTL, gifttl, CTLFLAG_RW,
 	&ip_gif_ttl,	0, "");
 
Index: sys/netinet/in_proto.c
===================================================================
RCS file: /home/ncvs/src/sys/netinet/in_proto.c,v
retrieving revision 1.55
diff -u -u -r1.55 in_proto.c
--- sys/netinet/in_proto.c	2000/08/03 14:09:52	1.55
+++ sys/netinet/in_proto.c	2001/06/08 19:36:40
@@ -77,11 +77,6 @@
 #endif
 #endif /* IPSEC */
 
-#include "gif.h"
-#if NGIF > 0
-#include <netinet/in_gif.h>
-#endif
-
 #include "stf.h"
 #if NSTF > 0
 #include <net/if_stf.h>
@@ -205,16 +200,6 @@
   &rip_usrreqs
 },
 };
-
-#if NGIF > 0
-struct ipprotosw in_gif_protosw =
-{ 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 =
Index: sys/netinet6/in6.c
===================================================================
RCS file: /home/ncvs/src/sys/netinet6/in6.c,v
retrieving revision 1.11
diff -u -u -r1.11 in6.c
--- sys/netinet6/in6.c	2001/01/18 06:07:53	1.11
+++ sys/netinet6/in6.c	2001/06/09 00:01:41
@@ -97,11 +97,6 @@
 #include <netinet6/in6_ifattach.h>
 #include <netinet6/scope6_var.h>
 
-#include "gif.h"
-#if NGIF > 0
-#include <net/if_gif.h>
-#endif
-
 #include <net/net_osdep.h>
 
 MALLOC_DEFINE(M_IPMADDR, "in6_multi", "internet multicast address");
@@ -343,7 +338,6 @@
 	/*
 	 * xxx should prevent processes for link-local addresses?
 	 */
-#if NGIF > 0
 	if (ifp && ifp->if_type == IFT_GIF) {
 		switch (cmd) {
 		case SIOCSIFPHYADDR_IN6:
@@ -352,10 +346,10 @@
 			/*fall through*/
 		case SIOCGIFPSRCADDR_IN6:
 		case SIOCGIFPDSTADDR_IN6:
-			return gif_ioctl(ifp, cmd, data);
+			return ifp->if_ioctl(ifp, cmd, data);
 		}
 	}
-#endif
+
 	switch (cmd) {
 	case SIOCGETSGCNT_IN6:
 	case SIOCGETMIFCNT_IN6:
Index: sys/netinet6/in6_proto.c
===================================================================
RCS file: /home/ncvs/src/sys/netinet6/in6_proto.c,v
retrieving revision 1.12
diff -u -u -r1.12 in6_proto.c
--- sys/netinet6/in6_proto.c	2001/06/01 09:51:14	1.12
+++ sys/netinet6/in6_proto.c	2001/06/08 23:31:49
@@ -122,11 +122,6 @@
 
 #include <netinet6/ip6protosw.h>
 
-#include "gif.h"
-#if NGIF > 0
-#include <netinet6/in6_gif.h>
-#endif
-
 #include <net/net_osdep.h>
 
 /*
@@ -244,16 +239,6 @@
 },
 };
 
-#if NGIF > 0
-struct ip6protosw in6_gif_protosw =
-{ 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));
 
 struct domain inet6domain =
@@ -292,11 +277,7 @@
 int	ip6_dad_count = 1;	/* DupAddrDetectionTransmits */
 u_int32_t ip6_flow_seq;
 int	ip6_auto_flowlabel = 1;
-#if NGIF > 0
-int	ip6_gif_hlim = GIF_HLIM;
-#else
 int	ip6_gif_hlim = 0;
-#endif
 int	ip6_use_deprecated = 1;	/* allow deprecated addr (RFC2462 5.5.4) */
 int	ip6_rr_prune = 5;	/* router renumbering prefix
 				 * walk list every 5 sec.    */
Index: sys/netinet6/ip6_input.c
===================================================================
RCS file: /home/ncvs/src/sys/netinet6/ip6_input.c,v
retrieving revision 1.26
diff -u -u -r1.26 ip6_input.c
--- sys/netinet6/ip6_input.c	2001/05/22 17:32:02	1.26
+++ sys/netinet6/ip6_input.c	2001/06/08 23:41:41
@@ -113,7 +113,6 @@
 #include <netinet6/ip6protosw.h>
 
 #include "faith.h"
-#include "gif.h"
 
 #include <net/net_osdep.h>
 
Index: sys/modules/Makefile
===================================================================
RCS file: /home/ncvs/src/sys/modules/Makefile,v
retrieving revision 1.183
diff -u -u -r1.183 Makefile
--- sys/modules/Makefile	2001/05/31 21:44:19	1.183
+++ sys/modules/Makefile	2001/06/09 01:04:54
@@ -8,6 +8,7 @@
 
 SUBDIR=	3dfx accf_data accf_http agp aha amr an aue \
 	cam ccd cd9660 coda cue dc de dgm digi ed fdescfs fxp if_disc if_ef \
+	if_gif \
 	if_ppp if_sl 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}  \
--- 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}/../../netinet6
+
+KMOD=	if_gif
+SRCS=	if_gif.c in_gif.c in6_gif.c opt_inet.h opt_inet6.h opt_mrouting.h
+NOMAN=
+
+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>
>Release-Note:
>Audit-Trail:
>Unformatted:

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




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