From owner-freebsd-bugs Fri Jun 8 19:20:49 2001 Delivered-To: freebsd-bugs@hub.freebsd.org Received: from freefall.freebsd.org (freefall.freebsd.org [216.136.204.21]) by hub.freebsd.org (Postfix) with ESMTP id CD79137B406 for ; Fri, 8 Jun 2001 19:20:01 -0700 (PDT) (envelope-from gnats@FreeBSD.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.11.3/8.11.3) id f592K1S89504; Fri, 8 Jun 2001 19:20:01 -0700 (PDT) (envelope-from gnats) Received: from minya.sea.one-eyed-alien.net (minya.sea.one-eyed-alien.net [216.39.168.226]) by hub.freebsd.org (Postfix) with ESMTP id 8E6A037B401 for ; Fri, 8 Jun 2001 19:18:37 -0700 (PDT) (envelope-from brooks@minya.sea.one-eyed-alien.net) Received: by minya.sea.one-eyed-alien.net (Postfix, from userid 1001) id DE1CE24D1F; Fri, 8 Jun 2001 19:20:51 -0700 (PDT) Message-Id: <20010609022051.DE1CE24D1F@minya.sea.one-eyed-alien.net> Date: Fri, 8 Jun 2001 19:20:51 -0700 (PDT) From: Brooks Davis Reply-To: Brooks Davis To: FreeBSD-gnats-submit@freebsd.org X-Send-Pr-Version: 3.113 Subject: kern/27983: [PATCH] make gif fully dynamic Sender: owner-freebsd-bugs@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.org >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 #include #include +#include +#include /* XXX: Shouldn't really be required! */ +#include #include #include @@ -58,6 +61,8 @@ #include #include #include +#include +#include #endif /* INET */ #ifdef INET6 @@ -74,28 +79,68 @@ #include #include -#include "gif.h" +#if defined(__FreeBSD__) +#define NBPFILTER 1 +#else #include "bpf.h" #define NBPFILTER NBPF +#endif #include - -#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 #include -#include #include #include @@ -115,16 +114,11 @@ #include "bpf.h" #define NBPFILTER NBPF #include "stf.h" -#include "gif.h" /*XXX*/ #if NBPFILTER > 0 #include #endif -#if NGIF > 0 -#include -#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 -#include "gif.h" -#if NGIF > 0 -#include -#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 -#include "gif.h" - #include #include -#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 -#endif - #include "stf.h" #if NSTF > 0 #include @@ -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 #include -#include "gif.h" -#if NGIF > 0 -#include -#endif - #include 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 -#include "gif.h" -#if NGIF > 0 -#include -#endif - #include /* @@ -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 #include "faith.h" -#include "gif.h" #include 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 >Release-Note: >Audit-Trail: >Unformatted: To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-bugs" in the body of the message