Home | History | Annotate | Line # | Download | only in net
if_srt.c revision 1.5.24.1
      1  1.5.24.1        ad /* $NetBSD: if_srt.c,v 1.5.24.1 2007/12/26 19:57:33 ad Exp $ */
      2       1.1     mouse /* This file is in the public domain. */
      3       1.1     mouse 
      4  1.5.24.1        ad #include <sys/cdefs.h>
      5  1.5.24.1        ad __KERNEL_RCSID(0, "$NetBSD: if_srt.c,v 1.5.24.1 2007/12/26 19:57:33 ad Exp $");
      6  1.5.24.1        ad 
      7       1.1     mouse #include "opt_inet.h"
      8       1.1     mouse 
      9       1.1     mouse #if !defined(INET) && !defined(INET6)
     10       1.1     mouse #error "srt without INET/INET6?"
     11       1.1     mouse #endif
     12       1.1     mouse 
     13       1.1     mouse #ifndef SRT_MAXUNIT
     14       1.1     mouse #define SRT_MAXUNIT 255
     15       1.1     mouse #endif
     16       1.1     mouse 
     17       1.3     mouse /* include-file bug workarounds */
     18       1.3     mouse #include <sys/types.h> /* sys/conf.h */
     19       1.3     mouse #include <sys/resource.h> /* sys/resourcevar.h (uvm/uvm_param.h, sys/mbuf.h) */
     20       1.3     mouse #include <netinet/in.h> /* netinet/ip.h */
     21       1.3     mouse #include <sys/param.h> /* sys/mbuf.h */
     22       1.3     mouse #include <netinet/in_systm.h> /* netinet/ip.h */
     23       1.3     mouse 
     24       1.1     mouse #include <sys/conf.h>
     25       1.1     mouse #include <sys/mbuf.h>
     26       1.1     mouse #include <sys/errno.h>
     27       1.1     mouse #include <sys/fcntl.h>
     28       1.1     mouse #include <sys/param.h>
     29       1.1     mouse #include <sys/ioctl.h>
     30       1.1     mouse #include <netinet/ip.h>
     31       1.1     mouse #include <netinet/ip6.h>
     32       1.1     mouse #include <net/if_types.h>
     33       1.1     mouse #include <machine/stdarg.h>
     34       1.1     mouse 
     35       1.1     mouse #include "if_srt.h"
     36       1.1     mouse #include "bpfilter.h"
     37       1.1     mouse 
     38       1.1     mouse /* until we know what to pass to bpfattach.... */
     39       1.1     mouse #undef NBPFILTER
     40       1.1     mouse #define NBPFILTER 0
     41       1.1     mouse 
     42       1.1     mouse typedef struct srt_rt RT;
     43       1.1     mouse typedef struct softc SOFTC;
     44       1.1     mouse 
     45       1.1     mouse struct softc {
     46       1.1     mouse   struct ifnet intf;	/* XXX interface botch */
     47       1.1     mouse   int unit;
     48       1.1     mouse   int nrt;
     49       1.1     mouse   RT **rts;
     50       1.1     mouse   unsigned int flags;	/* SSF_* values from if_srt.h */
     51       1.1     mouse #define SSF_UCHG (SSF_MTULOCK) /* userland-changeable bits */
     52       1.1     mouse   unsigned int kflags;	/* bits private to this file */
     53       1.1     mouse #define SKF_CDEVOPEN 0x00000001
     54       1.1     mouse   } ;
     55       1.1     mouse 
     56       1.1     mouse static SOFTC *softcv[SRT_MAXUNIT+1];
     57       1.1     mouse static unsigned int global_flags;
     58       1.1     mouse 
     59       1.1     mouse /* Internal routines. */
     60       1.1     mouse 
     61       1.1     mouse static unsigned int ipv4_masks[33]
     62       1.1     mouse  = { 0x00000000, /* /0 */
     63       1.1     mouse      0x80000000, 0xc0000000, 0xe0000000, 0xf0000000, /* /1 - /4 */
     64       1.1     mouse      0xf8000000, 0xfc000000, 0xfe000000, 0xff000000, /* /5 - /8 */
     65       1.1     mouse      0xff800000, 0xffc00000, 0xffe00000, 0xfff00000, /* /9 - /12 */
     66       1.1     mouse      0xfff80000, 0xfffc0000, 0xfffe0000, 0xffff0000, /* /13 - /16 */
     67       1.1     mouse      0xffff8000, 0xffffc000, 0xffffe000, 0xfffff000, /* /17 - /20 */
     68       1.1     mouse      0xfffff800, 0xfffffc00, 0xfffffe00, 0xffffff00, /* /21 - /24 */
     69       1.1     mouse      0xffffff80, 0xffffffc0, 0xffffffe0, 0xfffffff0, /* /25 - /28 */
     70       1.1     mouse      0xfffffff8, 0xfffffffc, 0xfffffffe, 0xffffffff  /* /29 - /32 */ };
     71       1.1     mouse 
     72       1.1     mouse static void update_mtu(SOFTC *sc)
     73       1.1     mouse {
     74       1.1     mouse  int mtu;
     75       1.1     mouse  int i;
     76       1.1     mouse  RT *r;
     77       1.1     mouse 
     78       1.1     mouse  if (sc->flags & SSF_MTULOCK) return;
     79       1.1     mouse  mtu = 65535;
     80       1.1     mouse  for (i=sc->nrt-1;i>=0;i--)
     81       1.1     mouse   { r = sc->rts[i];
     82       1.1     mouse     if (r->u.dstifp->if_mtu < mtu) mtu = r->u.dstifp->if_mtu;
     83       1.1     mouse   }
     84       1.1     mouse  sc->intf.if_mtu = mtu;
     85       1.1     mouse }
     86       1.1     mouse 
     87       1.1     mouse static RT *find_rt(SOFTC *sc, int af, ...)
     88       1.1     mouse {
     89       1.1     mouse  int i;
     90       1.1     mouse  RT *r;
     91       1.1     mouse  struct in_addr ia;
     92       1.1     mouse  struct in6_addr ia6;
     93       1.1     mouse  va_list ap;
     94       1.1     mouse 
     95       1.1     mouse  ia.s_addr = 0; ia6.s6_addr[0] = 0; /* shut up incorrect -Wuninitialized */
     96       1.1     mouse  va_start(ap,af);
     97       1.1     mouse  switch (af)
     98       1.1     mouse   { case AF_INET:
     99       1.1     mouse        ia = va_arg(ap,struct in_addr);
    100       1.1     mouse        break;
    101       1.1     mouse     case AF_INET6:
    102       1.1     mouse        ia6 = va_arg(ap,struct in6_addr);
    103       1.1     mouse        break;
    104       1.1     mouse     default:
    105       1.1     mouse        panic("if_srt find_rt: impossible address family");
    106       1.1     mouse        break;
    107       1.1     mouse   }
    108       1.1     mouse  va_end(ap);
    109       1.1     mouse  for (i=0;i<sc->nrt;i++)
    110       1.1     mouse   { r = sc->rts[i];
    111       1.1     mouse     if (r->af != af) continue;
    112       1.1     mouse     switch (af)
    113       1.1     mouse      { case AF_INET:
    114       1.1     mouse 	  if ((ia.s_addr & ipv4_masks[r->srcmask]) == r->srcmatch.v4.s_addr) return(r);
    115       1.1     mouse 	  break;
    116       1.1     mouse        case AF_INET6:
    117       1.1     mouse 	  if ((r->srcmask >= 8) && bcmp(&ia6,&r->srcmatch.v6,r->srcmask/8)) continue;
    118       1.1     mouse 	  if ( (r->srcmask % 8) &&
    119       1.1     mouse 	       ( ( ia6.s6_addr[r->srcmask/8] ^
    120       1.1     mouse 		   r->srcmatch.v6.s6_addr[r->srcmask/8] ) &
    121       1.1     mouse 		 0xff & (0xff00 >> (r->srcmask%8)) ) ) continue;
    122       1.1     mouse 	  return(r);
    123       1.1     mouse 	  break;
    124       1.1     mouse        default:
    125       1.1     mouse 	  panic("if_srt find_rt: impossible address family 2");
    126       1.1     mouse 	  break;
    127       1.1     mouse      }
    128       1.1     mouse   }
    129       1.1     mouse  return(0);
    130       1.1     mouse }
    131       1.1     mouse 
    132       1.1     mouse /* Network device interface. */
    133       1.1     mouse 
    134       1.5  christos static int srt_if_ioctl(struct ifnet *intf, u_long cmd, void *data)
    135       1.1     mouse {
    136       1.1     mouse  struct ifaddr *ifa;
    137       1.1     mouse  struct ifreq *ifr;
    138       1.1     mouse  int s;
    139       1.1     mouse  int err;
    140       1.1     mouse 
    141       1.1     mouse  err = 0;
    142       1.1     mouse  s = splnet();
    143       1.1     mouse  switch (cmd)
    144       1.1     mouse   { case SIOCSIFADDR:
    145       1.1     mouse     case SIOCSIFDSTADDR:
    146       1.1     mouse        ifa = (void *) data;
    147       1.1     mouse        switch (ifa->ifa_addr->sa_family)
    148       1.1     mouse 	{
    149       1.1     mouse #ifdef INET
    150       1.1     mouse 	  case AF_INET:
    151       1.1     mouse #endif
    152       1.1     mouse #ifdef INET6
    153       1.1     mouse 	  case AF_INET6:
    154       1.1     mouse #endif
    155       1.1     mouse 	     break;
    156       1.1     mouse 	  default:
    157       1.1     mouse 	     err = EAFNOSUPPORT;
    158       1.1     mouse 	     break;
    159       1.1     mouse 	}
    160       1.1     mouse        /* XXX do we need to do more here for either of these? */
    161       1.1     mouse        break;
    162       1.1     mouse     case SIOCSIFMTU:
    163       1.1     mouse        ifr = (void *) data;
    164       1.1     mouse        ((SOFTC *)intf->if_softc)->intf.if_mtu = ifr->ifr_mtu;
    165       1.1     mouse        break;
    166       1.1     mouse     case SIOCGIFMTU:
    167       1.1     mouse        ifr = (void *) data;
    168       1.1     mouse        ifr->ifr_mtu = intf->if_mtu;
    169       1.1     mouse        break;
    170       1.1     mouse     default:
    171       1.1     mouse        err = EINVAL;
    172       1.1     mouse        break;
    173       1.1     mouse   }
    174       1.1     mouse  splx(s);
    175       1.1     mouse  return(err);
    176       1.1     mouse }
    177       1.1     mouse 
    178       1.1     mouse static int srt_if_output(
    179       1.1     mouse 	struct ifnet *intf,
    180       1.1     mouse 	struct mbuf *m,
    181       1.4    dyoung 	const struct sockaddr *to,
    182       1.1     mouse 	struct rtentry *rtp )
    183       1.1     mouse {
    184       1.1     mouse  SOFTC *sc;
    185       1.1     mouse  RT *r;
    186       1.1     mouse 
    187       1.1     mouse  sc = intf->if_softc;
    188       1.1     mouse  if (! (intf->if_flags & IFF_UP))
    189       1.1     mouse   { m_freem(m);
    190       1.1     mouse     return(ENETDOWN);
    191       1.1     mouse   }
    192       1.1     mouse  switch (to->sa_family)
    193       1.1     mouse   {
    194       1.1     mouse #ifdef INET
    195       1.1     mouse     case AF_INET:
    196       1.1     mouse #endif
    197       1.1     mouse 	{ struct ip *ip;
    198       1.1     mouse 	  ip = mtod(m,struct ip *);
    199       1.1     mouse 	  r = find_rt(sc,AF_INET,ip->ip_src);
    200       1.1     mouse 	}
    201       1.1     mouse        break;
    202       1.1     mouse #ifdef INET6
    203       1.1     mouse     case AF_INET6:
    204       1.1     mouse #endif
    205       1.1     mouse 	{ struct ip6_hdr *ip;
    206       1.1     mouse 	  ip = mtod(m,struct ip6_hdr *);
    207       1.1     mouse 	  r = find_rt(sc,AF_INET6,ip->ip6_src);
    208       1.1     mouse 	}
    209       1.1     mouse        break;
    210       1.1     mouse     default:
    211       1.1     mouse        IF_DROP(&intf->if_snd);
    212       1.1     mouse        m_freem(m);
    213       1.1     mouse        return(EAFNOSUPPORT);
    214       1.1     mouse        break;
    215       1.1     mouse   }
    216       1.1     mouse  /* XXX Do we need to bpf_tap?  Or do higher layers now handle that? */
    217       1.1     mouse  /* if_gif.c seems to imply the latter. */
    218       1.1     mouse  intf->if_opackets ++;
    219       1.1     mouse  if (! r)
    220       1.1     mouse   { intf->if_oerrors ++;
    221       1.1     mouse     m_freem(m);
    222       1.1     mouse     return(0);
    223       1.1     mouse   }
    224       1.1     mouse  if (! (m->m_flags & M_PKTHDR))
    225       1.1     mouse   { printf("srt_if_output no PKTHDR\n");
    226       1.1     mouse     m_freem(m);
    227       1.1     mouse     return(0);
    228       1.1     mouse   }
    229       1.1     mouse  intf->if_obytes += m->m_pkthdr.len;
    230       1.1     mouse  if (! (r->u.dstifp->if_flags & IFF_UP))
    231       1.1     mouse   { m_freem(m);
    232       1.1     mouse     return(0); /* XXX ENETDOWN? */
    233       1.1     mouse   }
    234       1.1     mouse  /* XXX is 0 the right last arg here? */
    235       1.1     mouse  return((*r->u.dstifp->if_output)(r->u.dstifp,m,&r->dst.sa,0));
    236       1.1     mouse }
    237       1.1     mouse 
    238       1.1     mouse static int srt_clone_create(struct if_clone *cl, int unit)
    239       1.1     mouse {
    240       1.1     mouse  SOFTC *sc;
    241       1.1     mouse 
    242       1.1     mouse  if ((unit < 0) || (unit > SRT_MAXUNIT)) return(ENXIO);
    243       1.1     mouse  if (softcv[unit]) return(EBUSY);
    244       1.1     mouse  sc = malloc(sizeof(SOFTC),M_DEVBUF,M_WAIT);
    245       1.1     mouse  bzero(&sc->intf,sizeof(sc->intf)); /* XXX */
    246       1.1     mouse  sc->unit = unit;
    247       1.1     mouse  sc->nrt = 0;
    248       1.1     mouse  sc->rts = 0;
    249       1.1     mouse  sc->flags = 0;
    250       1.1     mouse  sc->kflags = 0;
    251       1.1     mouse  snprintf(&sc->intf.if_xname[0],sizeof(sc->intf.if_xname),"%s%d",cl->ifc_name,unit);
    252       1.1     mouse  sc->intf.if_softc = sc;
    253       1.1     mouse  sc->intf.if_mtu = 65535;
    254       1.1     mouse  sc->intf.if_flags = IFF_POINTOPOINT;
    255       1.1     mouse  sc->intf.if_type = IFT_OTHER;
    256       1.1     mouse  sc->intf.if_ioctl = &srt_if_ioctl;
    257       1.1     mouse  sc->intf.if_output = &srt_if_output;
    258       1.1     mouse  sc->intf.if_dlt = DLT_RAW;
    259       1.1     mouse  if_attach(&sc->intf);
    260       1.1     mouse  if_alloc_sadl(&sc->intf);
    261       1.1     mouse #if NBPFILTER > 0 /* see comment near top */
    262       1.1     mouse  bpfattach(&sc->intf,0/*???*/,0/*???*/);
    263       1.1     mouse #endif
    264       1.1     mouse  softcv[unit] = sc;
    265       1.1     mouse  return(0);
    266       1.1     mouse }
    267       1.1     mouse 
    268       1.1     mouse static int srt_clone_destroy(struct ifnet *intf)
    269       1.1     mouse {
    270       1.1     mouse  SOFTC *sc;
    271       1.1     mouse 
    272       1.1     mouse  sc = intf->if_softc;
    273       1.1     mouse  if ((intf->if_flags & IFF_UP) || (sc->kflags & SKF_CDEVOPEN)) return(EBUSY);
    274       1.1     mouse #if NBPFILTER > 0
    275       1.1     mouse  bpfdetach(intf);
    276       1.1     mouse #endif
    277       1.1     mouse  if_detach(intf);
    278       1.1     mouse  if ((sc->unit < 0) || (sc->unit > SRT_MAXUNIT))
    279       1.1     mouse   { panic("srt_clone_destroy: impossible unit %d\n",sc->unit);
    280       1.1     mouse   }
    281       1.1     mouse  if (softcv[sc->unit] != sc)
    282       1.1     mouse   { panic("srt_clone_destroy: bad backpointer ([%d]=%p not %p)\n",
    283       1.1     mouse 			sc->unit,(void *)softcv[sc->unit],(void *)sc);
    284       1.1     mouse   }
    285       1.1     mouse  softcv[sc->unit] = 0;
    286       1.1     mouse  free(sc,M_DEVBUF);
    287       1.1     mouse  return(0);
    288       1.1     mouse }
    289       1.1     mouse 
    290       1.1     mouse struct if_clone srt_clone =
    291       1.1     mouse     IF_CLONE_INITIALIZER("srt",&srt_clone_create,&srt_clone_destroy);
    292       1.1     mouse 
    293       1.1     mouse extern void srtattach(void);
    294       1.1     mouse void srtattach(void)
    295       1.1     mouse {
    296       1.1     mouse  int i;
    297       1.1     mouse 
    298       1.1     mouse  for (i=SRT_MAXUNIT;i>=0;i--) softcv[i] = 0;
    299       1.1     mouse  global_flags = 0;
    300       1.1     mouse  if_clone_attach(&srt_clone);
    301       1.1     mouse }
    302       1.1     mouse 
    303       1.1     mouse /* Special-device interface. */
    304       1.1     mouse 
    305       1.1     mouse static int srt_open(dev_t dev, int flag, int mode, struct lwp *l)
    306       1.1     mouse {
    307       1.1     mouse  int unit;
    308       1.1     mouse  SOFTC *sc;
    309       1.1     mouse 
    310       1.1     mouse  unit = minor(dev);
    311       1.1     mouse  if ((unit < 0) || (unit > SRT_MAXUNIT)) return(ENXIO);
    312       1.1     mouse  sc = softcv[unit];
    313       1.1     mouse  if (! sc) return(ENXIO);
    314       1.1     mouse  sc->kflags |= SKF_CDEVOPEN;
    315       1.1     mouse  return(0);
    316       1.1     mouse }
    317       1.1     mouse 
    318       1.1     mouse static int srt_close(dev_t dev, int flag, int mode, struct lwp *l)
    319       1.1     mouse {
    320       1.1     mouse  int unit;
    321       1.1     mouse  SOFTC *sc;
    322       1.1     mouse 
    323       1.1     mouse  unit = minor(dev);
    324       1.1     mouse  if ((unit < 0) || (unit > SRT_MAXUNIT)) return(ENXIO);
    325       1.1     mouse  sc = softcv[unit];
    326       1.1     mouse  if (! sc) return(ENXIO);
    327       1.1     mouse  sc->kflags &= ~SKF_CDEVOPEN;
    328       1.1     mouse  return(0);
    329       1.1     mouse }
    330       1.1     mouse 
    331       1.1     mouse static int srt_ioctl(
    332       1.1     mouse 	dev_t dev,
    333       1.1     mouse 	u_long cmd,
    334       1.5  christos 	void *data,
    335       1.1     mouse 	int flag,
    336       1.1     mouse 	struct lwp *l )
    337       1.1     mouse {
    338       1.1     mouse  SOFTC *sc;
    339       1.1     mouse  RT *dr;
    340       1.1     mouse  RT *scr;
    341       1.1     mouse  struct ifnet *intf;
    342       1.1     mouse  char nbuf[IFNAMSIZ];
    343       1.1     mouse 
    344       1.1     mouse  sc = softcv[minor(dev)];
    345       1.1     mouse  if (! sc) panic("srt_ioctl: softc disappeared");
    346       1.1     mouse  switch (cmd)
    347       1.1     mouse   { case SRT_GETNRT:
    348       1.1     mouse        if (! (flag & FREAD)) return(EBADF);
    349       1.1     mouse        *(unsigned int *)data = sc->nrt;
    350       1.1     mouse        return(0);
    351       1.1     mouse        break;
    352       1.1     mouse     case SRT_GETRT:
    353       1.1     mouse        if (! (flag & FREAD)) return(EBADF);
    354       1.1     mouse        dr = (RT *) data;
    355       1.1     mouse        if (dr->inx >= sc->nrt) return(EDOM);
    356       1.1     mouse        scr = sc->rts[dr->inx];
    357       1.1     mouse        dr->af = scr->af;
    358       1.1     mouse        dr->srcmatch = scr->srcmatch;
    359       1.1     mouse        dr->srcmask = scr->srcmask;
    360       1.1     mouse        strncpy(&dr->u.dstifn[0],&scr->u.dstifp->if_xname[0],IFNAMSIZ);
    361       1.1     mouse        memcpy(&dr->dst,&scr->dst,scr->dst.sa.sa_len);
    362       1.1     mouse        return(0);
    363       1.1     mouse        break;
    364       1.1     mouse     case SRT_SETRT:
    365       1.1     mouse        if (! (flag & FWRITE)) return(EBADF);
    366       1.1     mouse        dr = (RT *) data;
    367       1.1     mouse        if (dr->inx > sc->nrt) return(EDOM);
    368       1.1     mouse        strncpy(&nbuf[0],&dr->u.dstifn[0],IFNAMSIZ);
    369       1.1     mouse        nbuf[IFNAMSIZ-1] = '\0';
    370       1.1     mouse        if (dr->dst.sa.sa_family != dr->af) return(EIO);
    371       1.1     mouse        switch (dr->af)
    372       1.1     mouse 	{
    373       1.1     mouse #ifdef INET
    374       1.1     mouse 	  case AF_INET:
    375       1.1     mouse 	     if (dr->dst.sa.sa_len != sizeof(dr->dst.sin)) return(EIO);
    376       1.1     mouse 	     if (dr->srcmask > 32) return(EIO);
    377       1.1     mouse 	     break;
    378       1.1     mouse #endif
    379       1.1     mouse #ifdef INET6
    380       1.1     mouse 	  case AF_INET6:
    381       1.1     mouse 	     if (dr->dst.sa.sa_len != sizeof(dr->dst.sin6)) return(EIO);
    382       1.1     mouse 	     if (dr->srcmask > 128) return(EIO);
    383       1.1     mouse 	     break;
    384       1.1     mouse #endif
    385       1.1     mouse 	     break;
    386       1.1     mouse 	  default:
    387       1.1     mouse 	     return(EAFNOSUPPORT);
    388       1.1     mouse 	     break;
    389       1.1     mouse 	}
    390       1.1     mouse        intf = ifunit(&nbuf[0]);
    391       1.1     mouse        if (intf == 0) return(ENXIO); /* needs translation */
    392       1.1     mouse        if (dr->inx == sc->nrt)
    393       1.1     mouse 	{ RT **tmp;
    394       1.1     mouse 	  tmp = malloc((sc->nrt+1)*sizeof(*tmp),M_DEVBUF,M_WAITOK);
    395       1.1     mouse 	  if (tmp == 0) return(ENOBUFS);
    396       1.1     mouse 	  tmp[sc->nrt] = 0;
    397       1.1     mouse 	  if (sc->nrt > 0)
    398       1.1     mouse 	   { memcpy(tmp,sc->rts,sc->nrt*sizeof(*tmp));
    399       1.1     mouse 	     free(sc->rts,M_DEVBUF);
    400       1.1     mouse 	   }
    401       1.1     mouse 	  sc->rts = tmp;
    402       1.1     mouse 	  sc->nrt ++;
    403       1.1     mouse 	}
    404       1.1     mouse        scr = sc->rts[dr->inx];
    405       1.1     mouse        if (scr == 0)
    406       1.1     mouse 	{ scr = malloc(sizeof(RT),M_DEVBUF,M_WAITOK);
    407       1.1     mouse 	  if (scr == 0) return(ENOBUFS);
    408       1.1     mouse 	  scr->inx = dr->inx;
    409       1.1     mouse 	  scr->af = AF_UNSPEC;
    410       1.1     mouse 	  sc->rts[dr->inx] = scr;
    411       1.1     mouse 	}
    412       1.1     mouse        scr->af = dr->af;
    413       1.1     mouse        scr->srcmatch = dr->srcmatch;
    414       1.1     mouse        scr->srcmask = dr->srcmask;
    415       1.1     mouse        scr->u.dstifp = intf;
    416       1.1     mouse        memcpy(&scr->dst,&dr->dst,dr->dst.sa.sa_len);
    417       1.1     mouse        update_mtu(sc);
    418       1.1     mouse        return(0);
    419       1.1     mouse        break;
    420       1.1     mouse     case SRT_DELRT:
    421       1.1     mouse 	{ unsigned int i;
    422       1.1     mouse 	  if (! (flag & FWRITE)) return(EBADF);
    423       1.1     mouse 	  i = *(unsigned int *)data;
    424       1.1     mouse 	  if (i >= sc->nrt) return(EDOM);
    425       1.1     mouse 	  scr = sc->rts[i];
    426       1.1     mouse 	  sc->rts[i] = 0;
    427       1.1     mouse 	  free(scr,M_DEVBUF);
    428       1.1     mouse 	  sc->nrt --;
    429       1.1     mouse 	  if (i < sc->nrt) memcpy(sc->rts+i,sc->rts+i+1,(sc->nrt-i)*sizeof(*sc->rts));
    430       1.1     mouse 	  if (sc->nrt == 0)
    431       1.1     mouse 	   { free(sc->rts,M_DEVBUF);
    432       1.1     mouse 	     sc->rts = 0;
    433       1.1     mouse 	     sc->intf.if_flags &= ~IFF_UP;
    434       1.1     mouse 	   }
    435       1.1     mouse 	}
    436       1.1     mouse        update_mtu(sc);
    437       1.1     mouse        return(0);
    438       1.1     mouse        break;
    439       1.1     mouse     case SRT_SFLAGS:
    440       1.1     mouse 	{ unsigned int f;
    441       1.1     mouse 	  if (! (flag & FWRITE)) return(EBADF);
    442       1.1     mouse 	  f = *(unsigned int *)data & SSF_UCHG;
    443       1.1     mouse 	  global_flags = (global_flags & ~SSF_UCHG) | (f & SSF_GLOBAL);
    444       1.1     mouse 	  sc->flags = (sc->flags & ~SSF_UCHG) | (f & ~SSF_GLOBAL);
    445       1.1     mouse 	}
    446       1.1     mouse        return(0);
    447       1.1     mouse        break;
    448       1.1     mouse     case SRT_GFLAGS:
    449       1.1     mouse        if (! (flag & FREAD)) return(EBADF);
    450       1.1     mouse        *(unsigned int *)data = sc->flags | global_flags;
    451       1.1     mouse        return(0);
    452       1.1     mouse        break;
    453       1.1     mouse     case SRT_SGFLAGS:
    454       1.1     mouse 	{ unsigned int o;
    455       1.1     mouse 	  unsigned int n;
    456       1.1     mouse 	  if ((flag & (FWRITE|FREAD)) != (FWRITE|FREAD)) return(EBADF);
    457       1.1     mouse 	  o = sc->flags | global_flags;
    458       1.1     mouse 	  n = *(unsigned int *)data & SSF_UCHG;
    459       1.1     mouse 	  global_flags = (global_flags & ~SSF_UCHG) | (n & SSF_GLOBAL);
    460       1.1     mouse 	  sc->flags = (sc->flags & ~SSF_UCHG) | (n & ~SSF_GLOBAL);
    461       1.1     mouse 	  *(unsigned int *)data = o;
    462       1.1     mouse 	}
    463       1.1     mouse        return(0);
    464       1.1     mouse        break;
    465       1.1     mouse     case SRT_DEBUG:
    466       1.1     mouse        return(0);
    467       1.1     mouse        break;
    468       1.1     mouse   }
    469       1.1     mouse  return(ENOTTY);
    470       1.1     mouse }
    471       1.1     mouse 
    472       1.1     mouse const struct cdevsw srt_cdevsw
    473       1.1     mouse  = { &srt_open,
    474       1.1     mouse      &srt_close,
    475       1.1     mouse      nullread,
    476       1.1     mouse      nullwrite,
    477       1.1     mouse      &srt_ioctl,
    478       1.1     mouse      nullstop,
    479       1.1     mouse      notty,
    480       1.1     mouse      nullpoll,
    481       1.1     mouse      nommap,
    482       1.1     mouse      nullkqfilter,
    483       1.1     mouse      D_OTHER };
    484