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>
