Home | History | Annotate | Line # | Download | only in net
if_tun.c revision 1.7
      1 /*
      2  * Copyright (c) 1988, Julian Onions.
      3  *
      4  * This source may be freely distributed, however I would be interested
      5  * in any changes that are made.
      6  *
      7  *  if_tun.c - tunnel interface module & driver
      8  *
      9  * $Id: if_tun.c,v 1.7 1993/11/14 20:33:26 deraadt Exp $
     10  */
     11 
     12 #include "tun.h"
     13 #if NTUN > 0
     14 
     15 /*
     16  * Tunnel driver.
     17  *
     18  * This driver takes packets off the IP i/f and hands them up to a
     19  * user process to have it's wicked way with. This driver has it's
     20  * roots in a similar driver written by Phil Cockcroft (formerly) at
     21  * UCL. This driver is based much more on read/write/select mode of
     22  * operation though.
     23  *
     24  * Julian Onions <jpo (at) cs.nott.ac.uk>
     25  * Nottingham University 1987.
     26  */
     27 
     28 #include <sys/param.h>
     29 #include <sys/systm.h>
     30 #include <sys/mbuf.h>
     31 #include <sys/buf.h>
     32 #include <sys/protosw.h>
     33 #include <sys/socket.h>
     34 #include <sys/ioctl.h>
     35 #include <sys/errno.h>
     36 #include <sys/syslog.h>
     37 #include <sys/select.h>
     38 
     39 #include <net/if.h>
     40 #include <net/if_tun.h>
     41 #include <net/netisr.h>
     42 #include <net/route.h>
     43 
     44 #ifdef INET
     45 #include <netinet/in.h>
     46 #include <netinet/in_systm.h>
     47 #include <netinet/in_var.h>
     48 #include <netinet/ip.h>
     49 #include <netinet/if_ether.h>
     50 #endif
     51 
     52 #ifdef NS
     53 #include <netns/ns.h>
     54 #include <netns/ns_if.h>
     55 #endif
     56 
     57 #define TUNDEBUG	if (tundebug) printf
     58 int	tundebug = 0;
     59 
     60 struct tun_softc tunctl[NTUN];
     61 extern int ifqmaxlen;
     62 
     63 int	tunoutput __P((dev_t, int, int, struct proc *));
     64 int	tunclose __P((dev_t, int));
     65 int	tunoutput __P((struct ifnet *, struct mbuf *, struct sockaddr *));
     66 int	tunread __P((dev_t, struct uio *));
     67 int	tunwrite __P((dev_t, struct uio *));
     68 int	tuncioctl __P((dev_t, int, caddr_t, data);
     69 int	tunioctl __P((struct ifnet *, int, caddr_t, int));
     70 int	tunselect __P((dev_t, int);
     71 
     72 static int tunattach __P((int));
     73 static int tuninit __P((int));
     74 
     75 /*
     76  * tunnel open - must be superuser & the device must be
     77  * configured in
     78  */
     79 int
     80 tunopen(dev, flag, mode, p)
     81 	dev_t	dev;
     82 	int	flag, mode;
     83 	struct proc *p;
     84 {
     85 	struct ifnet	*ifp;
     86 	struct tunctl	*tp;
     87 	register int	unit, error;
     88 
     89 	if (error = suser(p->p_ucred, &p->p_acflag))
     90 		return (error);
     91 
     92 	if ((unit = minor(dev)) >= NTUN)
     93 		return (ENXIO);
     94 	tp = &tunctl[unit];
     95 	if (tp->tun_flags & TUN_OPEN)
     96 		return ENXIO;
     97 	if ((tp->tun_flags & TUN_INITED) == 0) {
     98 		tp->tun_flags = TUN_INITED;
     99 		tunattach(unit);
    100 	}
    101 	ifp = &tp->tun_if;
    102 	tp->tun_flags |= TUN_OPEN;
    103 	TUNDEBUG("%s%d: open\n", ifp->if_name, ifp->if_unit);
    104 	return (0);
    105 }
    106 
    107 /*
    108  * tunclose - close the device - mark i/f down & delete
    109  * routing info
    110  */
    111 int
    112 tunclose(dev, flag)
    113 	dev_t	dev;
    114 	int	flag;
    115 {
    116 	struct tunctl	*tp = &tunctl[unit];
    117 	struct ifnet	*ifp = &tp->tun_if;
    118 	struct mbuf	*m;
    119 	register int	unit = minor(dev), s;
    120 
    121 	tp->tun_flags &= TUN_INITED;
    122 
    123 	/*
    124 	 * junk all pending output
    125 	 */
    126 	do {
    127 		s = splimp();
    128 		IF_DEQUEUE(&ifp->if_snd, m);
    129 		splx(s);
    130 		if (m)
    131 			m_freem(m);
    132 	} while (m);
    133 
    134 	if (ifp->if_flags & IFF_UP) {
    135 		s = splimp();
    136 		if_down(ifp);
    137 		if (ifp->if_flags & IFF_RUNNING)
    138 			rtinit(ifp->if_addrlist, (int)SIOCDELRT, RTF_HOST);
    139 		splx(s);
    140 	}
    141 	tp->tun_pgrp = 0;
    142 	selwakeup(&tp->tun_rsel);
    143 
    144 	TUNDEBUG ("%s%d: closed\n", ifp->if_name, ifp->if_unit);
    145 	return (0);
    146 }
    147 
    148 /*
    149  * attach an interface N.B. argument is not same as other drivers
    150  */
    151 static int
    152 tunattach(unit)
    153 	int	unit;
    154 {
    155 	struct ifnet	*ifp = &tunctl[unit].tun_if;
    156 	struct sockaddr_in *sin;
    157 
    158 	ifp->if_unit = unit;
    159 	ifp->if_name = "tun";
    160 	ifp->if_mtu = TUNMTU;
    161 	ifp->if_ioctl = tunioctl;
    162 	ifp->if_output = tunoutput;
    163 	ifp->if_flags = IFF_POINTOPOINT;
    164 	ifp->if_snd.ifq_maxlen = ifqmaxlen;
    165 	ifp->if_collisions = 0;
    166 	ifp->if_ierrors = 0;
    167 	ifp->if_oerrors = 0;
    168 	ifp->if_ipackets = 0;
    169 	ifp->if_opackets = 0;
    170 	if_attach(ifp);
    171 	TUNDEBUG("%s%d: tunattach\n", ifp->if_name, ifp->if_unit);
    172 	return 0;
    173 }
    174 
    175 static int
    176 tuninit(unit)
    177 	int	unit;
    178 {
    179 	struct tunctl	*tp = &tunctl[unit];
    180 	struct ifnet	*ifp = &tp->tun_if;
    181 
    182 	ifp->if_flags |= IFF_UP | IFF_RUNNING;
    183 	tp->tun_flags |= TUN_IASET;
    184 	TUNDEBUG("%s%d: tuninit\n", ifp->if_name, ifp->if_unit);
    185 	return 0;
    186 }
    187 
    188 /*
    189  * Process an ioctl request.
    190  */
    191 int
    192 tunioctl(ifp, cmd, data, flag)
    193 	struct ifnet *ifp;
    194 	int	cmd;
    195 	caddr_t	data;
    196 	int	flag;
    197 {
    198 	int		error = 0, s;
    199 	struct tunctl	*tp = &tunctl[ifp->if_unit];
    200 
    201 	s = splimp();
    202 	switch(cmd) {
    203 	case SIOCSIFADDR:
    204 		tuninit(ifp->if_unit);
    205 		break;
    206 	case SIOCSIFDSTADDR:
    207 		tp->tun_flags |= TUN_DSTADDR;
    208 		TUNDEBUG("%s%d: destination address set\n", ifp->if_name,
    209 		    ifp->if_unit);
    210 		break;
    211 	default:
    212 		error = EINVAL;
    213 	}
    214 	splx(s);
    215 	return (error);
    216 }
    217 
    218 /*
    219  * tunoutput - queue packets from higher level ready to put out.
    220  */
    221 int
    222 tunoutput(ifp, m0, dst)
    223 	struct ifnet   *ifp;
    224 	struct mbuf    *m0;
    225 	struct sockaddr *dst;
    226 {
    227 	struct tunctl	*tp = &tunctl[ifp->if_unit];
    228 	struct proc	*p;
    229 	int		s;
    230 
    231 	TUNDEBUG ("%s%d: tunoutput\n", ifp->if_name, ifp->if_unit);
    232 
    233 	switch(dst->sa_family) {
    234 #ifdef INET
    235 	case AF_INET:
    236 		s = splimp();
    237 		if (IF_QFULL(&ifp->if_snd)) {
    238 			IF_DROP(&ifp->if_snd);
    239 			m_freem(m0);
    240 			splx(s);
    241 			ifp->if_collisions++;
    242 			return (ENOBUFS);
    243 		}
    244 		IF_ENQUEUE(&ifp->if_snd, m0);
    245 		splx(s);
    246 		ifp->if_opackets++;
    247 		break;
    248 #endif
    249 	default:
    250 		m_freem(m0);
    251 		return EAFNOSUPPORT;
    252 	}
    253 
    254 	if (tp->tun_flags & TUN_RWAIT) {
    255 		tp->tun_flags &= ~TUN_RWAIT;
    256 		wakeup((caddr_t)tp);
    257 	}
    258 	if (tp->tun_flags & TUN_ASYNC && tp->tun_pgrp) {
    259 		if (tp->tun_pgrp > 0)
    260 			gsignal(tp->tun_pgrp, SIGIO);
    261 		else if (p = pfind(-tp->tun_pgrp))
    262 			psignal(p, SIGIO);
    263 	}
    264 	selwakeup(&tp->tun_rsel);
    265 	return 0;
    266 }
    267 
    268 /*
    269  * the cdevsw interface is now pretty minimal.
    270  */
    271 int
    272 tuncioctl(dev, cmd, data, flag)
    273 	dev_t		dev;
    274 	int		cmd;
    275 	caddr_t		data;
    276 	int		flag;
    277 {
    278 	int		unit = minor(dev), s;
    279 	struct tunctl	*tp = &tunctl[unit];
    280 
    281 	switch (cmd) {
    282 	case TUNSDEBUG:
    283 		tundebug = *(int *)data;
    284 		break;
    285 	case TUNGDEBUG:
    286 		*(int *)data = tundebug;
    287 		break;
    288 	case FIONBIO:
    289 		if (*(int *)data)
    290 			tp->tun_flags |= TUN_NBIO;
    291 		else
    292 			tp->tun_flags &= ~TUN_NBIO;
    293 		break;
    294 	case FIOASYNC:
    295 		if (*(int *)data)
    296 			tp->tun_flags |= TUN_ASYNC;
    297 		else
    298 			tp->tun_flags &= ~TUN_ASYNC;
    299 		break;
    300 	case FIONREAD:
    301 		s = splimp();
    302 		if (tp->tun_if.if_snd.ifq_head)
    303 			*(int *)data = tp->tun_if.if_snd.ifq_head->m_len;
    304 		else
    305 			*(int *)data = 0;
    306 		splx(s);
    307 		break;
    308 	case TIOCSPGRP:
    309 		tp->tun_pgrp = *(int *)data;
    310 		break;
    311 	case TIOCGPGRP:
    312 		*(int *)data = tp->tun_pgrp;
    313 		break;
    314 	default:
    315 		return (ENOTTY);
    316 	}
    317 	return (0);
    318 }
    319 
    320 /*
    321  * The cdevsw read interface - reads a packet at a time, or at
    322  * least as much of a packet as can be read.
    323  */
    324 int
    325 tunread(dev, uio)
    326 	dev_t		dev;
    327 	struct uio	*uio;
    328 {
    329 	struct ifnet	*ifp = &tp->tun_if;
    330 	struct mbuf	*m, *m0;
    331 	struct tunctl	*tp = &tunctl[unit];
    332 	int		unit = minor(dev);
    333 	int		error=0, len, s;
    334 
    335 	TUNDEBUG ("%s%d: read\n", ifp->if_name, ifp->if_unit);
    336 	tp->tun_flags &= ~TUN_RWAIT;
    337 
    338 	s = splimp();
    339 	do {
    340 		IF_DEQUEUE(&ifp->if_snd, m0);
    341 		if (m0 == 0) {
    342 			if (tp->tun_flags & TUN_NBIO) {
    343 				splx(s);
    344 				return EWOULDBLOCK;
    345 			}
    346 			tp->tun_flags |= TUN_RWAIT;
    347 			tsleep((caddr_t)tp, PZERO + 1, "tunread", 0);
    348 		}
    349 	} while (m0 == 0);
    350 	splx(s);
    351 
    352 	while (m0 && uio->uio_resid > 0 && error == 0) {
    353 		len = MIN(uio->uio_resid, m0->m_len);
    354 		if (len == 0)
    355 			break;
    356 		error = uiomove(mtod(m0, caddr_t), len,
    357 		    UIO_READ, uio);
    358 		MFREE(m0, m);
    359 		m0 = m;
    360 	}
    361 
    362 	if (m0) {
    363 		TUNDEBUG("Dropping mbuf\n");
    364 		m_freem(m0);
    365 	}
    366 	return error;
    367 }
    368 
    369 /*
    370  * the cdevsw write interface - an atomic write is a packet - or else!
    371  */
    372 int
    373 tunwrite(dev, uio)
    374 	int		dev;
    375 	struct uio	*uio;
    376 {
    377 	int		unit = minor (dev);
    378 	struct ifnet	*ifp = &(tunctl[unit].tun_if);
    379 	struct mbuf	*top, **mp, *m;
    380 	int		error=0, s;
    381 
    382 	TUNDEBUG("%s%d: tunwrite\n", ifp->if_name, ifp->if_unit);
    383 
    384 	if (uio->uio_resid < 0 || uio->uio_resid > TUNMTU) {
    385 		TUNDEBUG("%s%d: len=%d!\n", ifp->if_name, ifp->if_unit,
    386 		    uio->uio_resid);
    387 		return EIO;
    388 	}
    389 	top = 0;
    390 	mp = &top;
    391 	while (error == 0 && uio->uio_resid > 0) {
    392 		MGET(m, M_DONTWAIT, MT_DATA);
    393 		if (m == 0) {
    394 			error = ENOBUFS;
    395 			break;
    396 		}
    397 		m->m_len = MIN(MLEN, uio->uio_resid);
    398 		error = uiomove(mtod(m, caddr_t), m->m_len, UIO_WRITE, uio);
    399 		*mp = m;
    400 		mp = &m->m_next;
    401 	}
    402 	if (error) {
    403 		if (top)
    404 			m_freem(top);
    405 		return error;
    406 	}
    407 
    408 	/*
    409 	 * Place interface pointer before the data
    410 	 * for the receiving protocol.
    411 	 */
    412 	if (top->m_off <= MMAXOFF &&
    413 	    top->m_off >= MMINOFF + sizeof(struct ifnet *)) {
    414 		top->m_off -= sizeof(struct ifnet *);
    415 		top->m_len += sizeof(struct ifnet *);
    416 	} else {
    417 		MGET(m, M_DONTWAIT, MT_HEADER);
    418 		if (m == (struct mbuf *)0)
    419 			return (ENOBUFS);
    420 		m->m_len = sizeof(struct ifnet *);
    421 		m->m_next = top;
    422 		top = m;
    423 	}
    424 	*(mtod(top, struct ifnet **)) = ifp;
    425 
    426 	s = splimp();
    427 	if (IF_QFULL (&ipintrq)) {
    428 		IF_DROP(&ipintrq);
    429 		splx(s);
    430 		ifp->if_collisions++;
    431 		m_freem(top);
    432 		return ENOBUFS;
    433 	}
    434 	IF_ENQUEUE(&ipintrq, top);
    435 	splx(s);
    436 	ifp->if_ipackets++;
    437 	schednetisr(NETISR_IP);
    438 	return error;
    439 }
    440 
    441 /*
    442  * tunselect - the select interface, this is only useful on reads
    443  * really. The write detect always returns true, write never blocks
    444  * anyway, it either accepts the packet or drops it.
    445  */
    446 int
    447 tunselect(dev, rw, p)
    448 	dev_t		dev;
    449 	int		rw;
    450 	struct proc	*p;
    451 {
    452 	int		unit = minor(dev), s;
    453 	struct tunctl	*tp = &tunctl[unit];
    454 	struct ifnet	*ifp = &tp->tun_if;
    455 
    456 	s = splimp();
    457 	TUNDEBUG("%s%d: tunselect\n", ifp->if_name, ifp->if_unit);
    458 
    459 	switch (rw) {
    460 	case FREAD:
    461 		if (ifp->if_snd.ifq_len > 0) {
    462 			splx(s);
    463 			TUNDEBUG("%s%d: tunselect q=%d\n", ifp->if_name,
    464 			    ifp->if_unit, ifp->if_snd.ifq_len);
    465 			return 1;
    466 		}
    467 		selrecord(p, &tp->tun_rsel);
    468 		break;
    469 	case FWRITE:
    470 		splx(s);
    471 		return 1;
    472 	}
    473 	splx(s);
    474 	TUNDEBUG("%s%d: tunselect waiting\n", ifp->if_name, ifp->if_unit);
    475 	return 0;
    476 }
    477 #endif  NTUN
    478