if_tun.c revision 11921
133965Sjdp/*	$NetBSD: if_tun.c,v 1.14 1994/06/29 06:36:25 cgd Exp $	*/
2130561Sobrien
378828Sobrien/*
433965Sjdp * Copyright (c) 1988, Julian Onions <jpo@cs.nott.ac.uk>
533965Sjdp * Nottingham University 1987.
6130561Sobrien *
733965Sjdp * This source may be freely distributed, however I would be interested
8130561Sobrien * in any changes that are made.
9130561Sobrien *
10130561Sobrien * This driver takes packets off the IP i/f and hands them up to a
11130561Sobrien * user process to have it's wicked way with. This driver has it's
1233965Sjdp * roots in a similar driver written by Phil Cockcroft (formerly) at
13130561Sobrien * UCL. This driver is based much more on read/write/select mode of
14130561Sobrien * operation though.
15130561Sobrien */
16130561Sobrien
1733965Sjdp#include "tun.h"
18130561Sobrien#if NTUN > 0
19130561Sobrien
20130561Sobrien#include <sys/param.h>
2133965Sjdp#include <sys/proc.h>
2233965Sjdp#include <sys/systm.h>
2333965Sjdp#include <sys/mbuf.h>
2433965Sjdp#include <sys/buf.h>
2533965Sjdp#include <sys/protosw.h>
2633965Sjdp#include <sys/socket.h>
2733965Sjdp#include <sys/ioctl.h>
2833965Sjdp#include <sys/errno.h>
2933965Sjdp#include <sys/syslog.h>
3033965Sjdp#include <sys/select.h>
3177298Sobrien#include <sys/file.h>
3277298Sobrien#include <sys/signalvar.h>
3377298Sobrien#ifdef __FreeBSD__
3477298Sobrien#include <sys/kernel.h>
3577298Sobrien#endif
3633965Sjdp#include <sys/conf.h>
3733965Sjdp
3833965Sjdp#include <machine/cpu.h>
3933965Sjdp
4033965Sjdp#include <net/if.h>
4133965Sjdp#include <net/netisr.h>
4233965Sjdp#include <net/route.h>
4333965Sjdp
4433965Sjdp#ifdef INET
4533965Sjdp#include <netinet/in.h>
4633965Sjdp#include <netinet/in_systm.h>
4733965Sjdp#include <netinet/in_var.h>
4889857Sobrien#include <netinet/ip.h>
4989857Sobrien#include <netinet/if_ether.h>
5033965Sjdp#endif
5133965Sjdp
5289857Sobrien#ifdef NS
5389857Sobrien#include <netns/ns.h>
5433965Sjdp#include <netns/ns_if.h>
5577298Sobrien#endif
5689857Sobrien
5789857Sobrien#include "bpfilter.h"
5877298Sobrien#if NBPFILTER > 0
5977298Sobrien#include <sys/time.h>
6089857Sobrien#include <net/bpf.h>
6189857Sobrien#endif
6277298Sobrien
6333965Sjdp#include <net/if_tun.h>
6433965Sjdp
6533965Sjdp#ifdef __FreeBSD__
6633965Sjdpstatic void tunattach __P((void *));
6733965SjdpPSEUDO_SET(tunattach, if_tun);
6833965Sjdp#endif
6933965Sjdp
7033965Sjdp#define TUNDEBUG	if (tundebug) printf
7133965Sjdpint	tundebug = 0;
7233965Sjdp
7333965Sjdpstruct tun_softc tunctl[NTUN];
7433965Sjdp
7533965Sjdpd_open_t tunopen;
7633965Sjdpd_close_t tunclose;
7733965Sjdpint	tunoutput __P((struct ifnet *, struct mbuf *, struct sockaddr *,
7833965Sjdp	    struct rtentry *rt));
7933965Sjdpd_rdwr_t tunread;
8033965Sjdpd_rdwr_t tunwrite;
8133965Sjdpd_ioctl_t tunioctl;
8233965Sjdpint	tunifioctl __P((struct ifnet *, int, caddr_t));
8333965Sjdpd_select_t tunselect;
8433965Sjdp
8533965Sjdpstatic struct cdevsw tuncdevsw =
8633965Sjdp{ tunopen,      tunclose,       tunread,        tunwrite,
8733965Sjdp  tunioctl,     (d_stop_t *)enodev, (d_reset_t *)nullop, (d_ttycv_t *)enodev,
8833965Sjdp  tunselect,    (d_mmap_t *)enodev,         NULL };
8933965Sjdpextern dev_t tuncdev;
9033965Sjdp
9133965Sjdpstatic int tuninit __P((int));
9233965Sjdp
9333965Sjdpstatic void
9433965Sjdptunattach(udata)
9533965Sjdp	void *udata;
9633965Sjdp{
9733965Sjdp	register int i;
9833965Sjdp	struct ifnet *ifp;
9933965Sjdp
10033965Sjdp	/*
10133965Sjdp	 * In case we are an LKM, set up device switch.
10233965Sjdp	 */
10333965Sjdp	cdevsw[major(tuncdev)] = tuncdevsw;
10433965Sjdp
10533965Sjdp	for (i = 0; i < NTUN; i++) {
10633965Sjdp		tunctl[i].tun_flags = TUN_INITED;
10789857Sobrien
10889857Sobrien		ifp = &tunctl[i].tun_if;
10989857Sobrien		ifp->if_unit = i;
11089857Sobrien		ifp->if_name = "tun";
11189857Sobrien		ifp->if_mtu = TUNMTU;
11289857Sobrien		ifp->if_ioctl = tunifioctl;
11389857Sobrien		ifp->if_output = tunoutput;
11489857Sobrien		ifp->if_flags = IFF_POINTOPOINT | IFF_MULTICAST;
11589857Sobrien		ifp->if_snd.ifq_maxlen = ifqmaxlen;
11689857Sobrien		ifp->if_collisions = 0;
11789857Sobrien		ifp->if_ierrors = 0;
11889857Sobrien		ifp->if_oerrors = 0;
11989857Sobrien		ifp->if_ipackets = 0;
12089857Sobrien		ifp->if_opackets = 0;
12189857Sobrien		if_attach(ifp);
12289857Sobrien#if NBPFILTER > 0
12389857Sobrien		bpfattach(&tunctl[i].tun_bpf, ifp, DLT_NULL, sizeof(u_int));
12489857Sobrien#endif
12589857Sobrien	}
12689857Sobrien}
12789857Sobrien
12889857Sobrien/*
12989857Sobrien * tunnel open - must be superuser & the device must be
13089857Sobrien * configured in
13189857Sobrien */
13233965Sjdpint
13333965Sjdptunopen(dev, flag, mode, p)
13433965Sjdp	dev_t	dev;
13577298Sobrien	int	flag, mode;
13633965Sjdp	struct proc *p;
13733965Sjdp{
13833965Sjdp	struct ifnet	*ifp;
13933965Sjdp	struct tun_softc *tp;
14033965Sjdp	register int	unit, error;
14133965Sjdp
14233965Sjdp	if (error = suser(p->p_ucred, &p->p_acflag))
14333965Sjdp		return (error);
14433965Sjdp
14533965Sjdp	if ((unit = minor(dev)) >= NTUN)
14633965Sjdp		return (ENXIO);
14733965Sjdp	tp = &tunctl[unit];
14833965Sjdp	if (tp->tun_flags & TUN_OPEN)
14933965Sjdp		return ENXIO;
15033965Sjdp	ifp = &tp->tun_if;
15133965Sjdp	tp->tun_flags |= TUN_OPEN;
15289857Sobrien	TUNDEBUG("%s%d: open\n", ifp->if_name, ifp->if_unit);
15389857Sobrien	return (0);
15489857Sobrien}
15589857Sobrien
15689857Sobrien/*
15789857Sobrien * tunclose - close the device - mark i/f down & delete
15889857Sobrien * routing info
15989857Sobrien */
16089857Sobrienint
16189857Sobrientunclose(dev_t dev, int foo, int bar, struct proc *p)
16289857Sobrien{
16389857Sobrien	register int	unit = minor(dev), s;
16489857Sobrien	struct tun_softc *tp = &tunctl[unit];
16589857Sobrien	struct ifnet	*ifp = &tp->tun_if;
16689857Sobrien	struct mbuf	*m;
16789857Sobrien
16889857Sobrien	tp->tun_flags &= ~TUN_OPEN;
16989857Sobrien
17089857Sobrien	/*
17189857Sobrien	 * junk all pending output
17289857Sobrien	 */
17389857Sobrien	do {
17489857Sobrien		s = splimp();
17589857Sobrien		IF_DEQUEUE(&ifp->if_snd, m);
17689857Sobrien		splx(s);
17733965Sjdp		if (m)
17833965Sjdp			m_freem(m);
17989857Sobrien	} while (m);
18077298Sobrien
18133965Sjdp	if (ifp->if_flags & IFF_UP) {
18233965Sjdp		s = splimp();
18333965Sjdp		if_down(ifp);
18433965Sjdp		if (ifp->if_flags & IFF_RUNNING) {
18533965Sjdp		    /* find internet addresses and delete routes */
18633965Sjdp		    register struct ifaddr *ifa;
18733965Sjdp		    for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) {
18833965Sjdp			if (ifa->ifa_addr->sa_family == AF_INET) {
18933965Sjdp			    rtinit(ifa, (int)RTM_DELETE,
19033965Sjdp				   tp->tun_flags & TUN_DSTADDR ? RTF_HOST : 0);
19133965Sjdp			}
19233965Sjdp		    }
19333965Sjdp		}
19433965Sjdp		splx(s);
19577298Sobrien	}
19689857Sobrien	tp->tun_pgrp = 0;
19789857Sobrien	selwakeup(&tp->tun_rsel);
19877298Sobrien
19978828Sobrien	TUNDEBUG ("%s%d: closed\n", ifp->if_name, ifp->if_unit);
20033965Sjdp	return (0);
20133965Sjdp}
20289857Sobrien
20389857Sobrienstatic int
20489857Sobrientuninit(unit)
20589857Sobrien	int	unit;
20689857Sobrien{
20789857Sobrien	struct tun_softc *tp = &tunctl[unit];
20889857Sobrien	struct ifnet	*ifp = &tp->tun_if;
20989857Sobrien	register struct ifaddr *ifa;
21077298Sobrien
21189857Sobrien	TUNDEBUG("%s%d: tuninit\n", ifp->if_name, ifp->if_unit);
21289857Sobrien
21333965Sjdp	ifp->if_flags |= IFF_UP | IFF_RUNNING;
21477298Sobrien
21589857Sobrien	for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
21689857Sobrien		if (ifa->ifa_addr->sa_family == AF_INET) {
21733965Sjdp		    struct sockaddr_in *si;
21889857Sobrien
21989857Sobrien		    si = (struct sockaddr_in *)ifa->ifa_addr;
22089857Sobrien		    if (si && si->sin_addr.s_addr)
22189857Sobrien			    tp->tun_flags |= TUN_IASET;
22233965Sjdp
223130561Sobrien		    si = (struct sockaddr_in *)ifa->ifa_dstaddr;
22489857Sobrien		    if (si && si->sin_addr.s_addr)
22589857Sobrien			    tp->tun_flags |= TUN_DSTADDR;
22689857Sobrien		}
22789857Sobrien
22889857Sobrien	return 0;
22989857Sobrien}
23089857Sobrien
23189857Sobrien/*
23289857Sobrien * Process an ioctl request.
23389857Sobrien */
23489857Sobrienint
23589857Sobrientunifioctl(ifp, cmd, data)
23689857Sobrien	struct ifnet *ifp;
23789857Sobrien	int	cmd;
23889857Sobrien	caddr_t	data;
23989857Sobrien{
24089857Sobrien	register struct ifreq *ifr = (struct ifreq *)data;
24189857Sobrien	int		error = 0, s;
24289857Sobrien
24389857Sobrien	s = splimp();
24433965Sjdp	switch(cmd) {
24533965Sjdp	case SIOCSIFADDR:
24689857Sobrien		tuninit(ifp->if_unit);
24789857Sobrien		TUNDEBUG("%s%d: address set\n",
24833965Sjdp			 ifp->if_name, ifp->if_unit);
24933965Sjdp		break;
25033965Sjdp	case SIOCSIFDSTADDR:
25177298Sobrien		tuninit(ifp->if_unit);
25233965Sjdp		TUNDEBUG("%s%d: destination address set\n",
25333965Sjdp			 ifp->if_name, ifp->if_unit);
25433965Sjdp		break;
25533965Sjdp	case SIOCADDMULTI:
25633965Sjdp	case SIOCDELMULTI:
25733965Sjdp		if (ifr == 0) {
25833965Sjdp			error = EAFNOSUPPORT;		/* XXX */
25933965Sjdp			break;
26033965Sjdp		}
26133965Sjdp		switch (ifr->ifr_addr.sa_family) {
26233965Sjdp
26333965Sjdp#ifdef INET
26433965Sjdp		case AF_INET:
26533965Sjdp			break;
266130561Sobrien#endif
267130561Sobrien
26877298Sobrien		default:
26989857Sobrien			error = EAFNOSUPPORT;
27089857Sobrien			break;
27189857Sobrien		}
27289857Sobrien		break;
27389857Sobrien
27489857Sobrien
27589857Sobrien	default:
27689857Sobrien		error = EINVAL;
27789857Sobrien	}
27889857Sobrien	splx(s);
27977298Sobrien	return (error);
28089857Sobrien}
28189857Sobrien
28233965Sjdp/*
28377298Sobrien * tunoutput - queue packets from higher level ready to put out.
28489857Sobrien */
28589857Sobrienint
28633965Sjdptunoutput(ifp, m0, dst, rt)
28789857Sobrien	struct ifnet   *ifp;
28889857Sobrien	struct mbuf    *m0;
28989857Sobrien	struct sockaddr *dst;
29089857Sobrien	struct rtentry *rt;
29133965Sjdp{
292130561Sobrien	struct tun_softc *tp = &tunctl[ifp->if_unit];
29389857Sobrien	struct proc	*p;
29489857Sobrien	int		s;
29589857Sobrien
29689857Sobrien	TUNDEBUG ("%s%d: tunoutput\n", ifp->if_name, ifp->if_unit);
29789857Sobrien
29889857Sobrien	if ((tp->tun_flags & TUN_READY) != TUN_READY) {
29989857Sobrien		TUNDEBUG ("%s%d: not ready 0%o\n", ifp->if_name,
30089857Sobrien			  ifp->if_unit, tp->tun_flags);
30189857Sobrien		m_freem (m0);
30289857Sobrien		return EHOSTDOWN;
30389857Sobrien	}
30489857Sobrien
30589857Sobrien#if NBPFILTER > 0
30689857Sobrien	/* BPF write needs to be handled specially */
30789857Sobrien	if (dst->sa_family == AF_UNSPEC) {
30889857Sobrien		dst->sa_family = *(mtod(m0, int *));
30989857Sobrien		m0->m_len -= sizeof(int);
31089857Sobrien		m0->m_pkthdr.len -= sizeof(int);
31189857Sobrien		m0->m_data += sizeof(int);
31289857Sobrien	}
31389857Sobrien
31489857Sobrien	if (tp->tun_bpf) {
31589857Sobrien		/*
31689857Sobrien		 * We need to prepend the address family as
31733965Sjdp		 * a four byte field.  Cons up a dummy header
31889857Sobrien		 * to pacify bpf.  This is safe because bpf
31989857Sobrien		 * will only read from the mbuf (i.e., it won't
32033965Sjdp		 * try to free it or keep a pointer to it).
32133965Sjdp		 */
32233965Sjdp		struct mbuf m;
32377298Sobrien		u_int af = dst->sa_family;
32433965Sjdp
32533965Sjdp		m.m_next = m0;
32633965Sjdp		m.m_len = 4;
32733965Sjdp		m.m_data = (char *)&af;
32833965Sjdp
32933965Sjdp		bpf_mtap(tp->tun_bpf, &m);
33033965Sjdp	}
33133965Sjdp#endif
33233965Sjdp
33333965Sjdp	switch(dst->sa_family) {
33433965Sjdp#ifdef INET
33533965Sjdp	case AF_INET:
33633965Sjdp		s = splimp();
33733965Sjdp		if (IF_QFULL(&ifp->if_snd)) {
33833965Sjdp			IF_DROP(&ifp->if_snd);
33933965Sjdp			m_freem(m0);
34033965Sjdp			splx(s);
34133965Sjdp			ifp->if_collisions++;
34233965Sjdp			return (ENOBUFS);
34389857Sobrien		}
34489857Sobrien		IF_ENQUEUE(&ifp->if_snd, m0);
34589857Sobrien		splx(s);
34689857Sobrien		ifp->if_opackets++;
34789857Sobrien		break;
34889857Sobrien#endif
34989857Sobrien	default:
35089857Sobrien		m_freem(m0);
35189857Sobrien		return EAFNOSUPPORT;
35289857Sobrien	}
35389857Sobrien
35489857Sobrien	if (tp->tun_flags & TUN_RWAIT) {
35589857Sobrien		tp->tun_flags &= ~TUN_RWAIT;
35689857Sobrien		wakeup((caddr_t)tp);
35733965Sjdp	}
35877298Sobrien	if (tp->tun_flags & TUN_ASYNC && tp->tun_pgrp) {
359130561Sobrien		if (tp->tun_pgrp > 0)
360130561Sobrien			gsignal(tp->tun_pgrp, SIGIO);
361130561Sobrien		else if (p = pfind(-tp->tun_pgrp))
362130561Sobrien			psignal(p, SIGIO);
363130561Sobrien	}
36489857Sobrien	selwakeup(&tp->tun_rsel);
36533965Sjdp	return 0;
36633965Sjdp}
36733965Sjdp
36833965Sjdp/*
36933965Sjdp * the cdevsw interface is now pretty minimal.
37033965Sjdp */
37133965Sjdpint
37233965Sjdptunioctl(dev, cmd, data, flag, p)
37333965Sjdp	dev_t		dev;
37433965Sjdp	int		cmd;
37533965Sjdp	caddr_t		data;
37633965Sjdp	int		flag;
37733965Sjdp	struct proc	*p;
37833965Sjdp{
37933965Sjdp	int		unit = minor(dev), s;
38033965Sjdp	struct tun_softc *tp = &tunctl[unit];
38133965Sjdp 	struct tuninfo *tunp;
38233965Sjdp
38333965Sjdp	switch (cmd) {
38433965Sjdp 	case TUNSIFINFO:
38589857Sobrien 	        tunp = (struct tuninfo *)data;
38677298Sobrien 		tp->tun_if.if_mtu = tunp->mtu;
38733965Sjdp 		tp->tun_if.if_type = tunp->type;
38833965Sjdp 		tp->tun_if.if_baudrate = tunp->baudrate;
38933965Sjdp 		break;
39077298Sobrien 	case TUNGIFINFO:
39133965Sjdp 		tunp = (struct tuninfo *)data;
39233965Sjdp 		tunp->mtu = tp->tun_if.if_mtu;
39333965Sjdp 		tunp->type = tp->tun_if.if_type;
39433965Sjdp 		tunp->baudrate = tp->tun_if.if_baudrate;
39533965Sjdp 		break;
39633965Sjdp	case TUNSDEBUG:
39733965Sjdp		tundebug = *(int *)data;
39833965Sjdp		break;
39933965Sjdp	case TUNGDEBUG:
40033965Sjdp		*(int *)data = tundebug;
40133965Sjdp		break;
40233965Sjdp	case FIONBIO:
40333965Sjdp		if (*(int *)data)
40433965Sjdp			tp->tun_flags |= TUN_NBIO;
405130561Sobrien		else
406130561Sobrien			tp->tun_flags &= ~TUN_NBIO;
40777298Sobrien		break;
40889857Sobrien	case FIOASYNC:
40989857Sobrien		if (*(int *)data)
41089857Sobrien			tp->tun_flags |= TUN_ASYNC;
41189857Sobrien		else
41289857Sobrien			tp->tun_flags &= ~TUN_ASYNC;
41389857Sobrien		break;
41489857Sobrien	case FIONREAD:
41589857Sobrien		s = splimp();
41689857Sobrien		if (tp->tun_if.if_snd.ifq_head)
41789857Sobrien			*(int *)data = tp->tun_if.if_snd.ifq_head->m_len;
41889857Sobrien		else
41989857Sobrien			*(int *)data = 0;
42089857Sobrien		splx(s);
42189857Sobrien		break;
42233965Sjdp	case TIOCSPGRP:
42377298Sobrien		tp->tun_pgrp = *(int *)data;
42489857Sobrien		break;
42589857Sobrien	case TIOCGPGRP:
42633965Sjdp		*(int *)data = tp->tun_pgrp;
42733965Sjdp		break;
42833965Sjdp	default:
42933965Sjdp		return (ENOTTY);
43033965Sjdp	}
43133965Sjdp	return (0);
43233965Sjdp}
43333965Sjdp
43433965Sjdp/*
43533965Sjdp * The cdevsw read interface - reads a packet at a time, or at
43633965Sjdp * least as much of a packet as can be read.
43733965Sjdp */
43833965Sjdpint
43933965Sjdptunread(dev_t dev, struct uio *uio, int flag)
44033965Sjdp{
44133965Sjdp	int		unit = minor(dev);
44233965Sjdp	struct tun_softc *tp = &tunctl[unit];
44333965Sjdp	struct ifnet	*ifp = &tp->tun_if;
44433965Sjdp	struct mbuf	*m, *m0;
44533965Sjdp	int		error=0, len, s;
44633965Sjdp
44733965Sjdp	TUNDEBUG ("%s%d: read\n", ifp->if_name, ifp->if_unit);
44889857Sobrien	if ((tp->tun_flags & TUN_READY) != TUN_READY) {
44977298Sobrien		TUNDEBUG ("%s%d: not ready 0%o\n", ifp->if_name,
45033965Sjdp			  ifp->if_unit, tp->tun_flags);
45133965Sjdp		return EHOSTDOWN;
45233965Sjdp	}
45377298Sobrien
45433965Sjdp	tp->tun_flags &= ~TUN_RWAIT;
45533965Sjdp
45633965Sjdp	s = splimp();
45733965Sjdp	do {
45833965Sjdp		IF_DEQUEUE(&ifp->if_snd, m0);
45977298Sobrien		if (m0 == 0) {
46033965Sjdp			if (tp->tun_flags & TUN_NBIO) {
46133965Sjdp				splx(s);
46233965Sjdp				return EWOULDBLOCK;
46333965Sjdp			}
46433965Sjdp			tp->tun_flags |= TUN_RWAIT;
46533965Sjdp			tsleep((caddr_t)tp, PZERO + 1, "tunread", 0);
46633965Sjdp		}
46733965Sjdp	} while (m0 == 0);
46833965Sjdp	splx(s);
46933965Sjdp
47033965Sjdp	while (m0 && uio->uio_resid > 0 && error == 0) {
47177298Sobrien		len = min(uio->uio_resid, m0->m_len);
47289857Sobrien		if (len == 0)
47389857Sobrien			break;
47489857Sobrien		error = uiomove(mtod(m0, caddr_t), len, uio);
47589857Sobrien		MFREE(m0, m);
47689857Sobrien		m0 = m;
47789857Sobrien	}
47889857Sobrien
47989857Sobrien	if (m0) {
48089857Sobrien		TUNDEBUG("Dropping mbuf\n");
48189857Sobrien		m_freem(m0);
48289857Sobrien	}
48389857Sobrien	return error;
48489857Sobrien}
48589857Sobrien
48633965Sjdp/*
48733965Sjdp * the cdevsw write interface - an atomic write is a packet - or else!
48833965Sjdp */
48977298Sobrienint
49033965Sjdptunwrite(dev_t dev, struct uio *uio, int flag)
49133965Sjdp{
49233965Sjdp	int		unit = minor (dev);
49333965Sjdp	struct ifnet	*ifp = &tunctl[unit].tun_if;
49433965Sjdp	struct mbuf	*top, **mp, *m;
49533965Sjdp	int		error=0, s, tlen, mlen;
49633965Sjdp
49733965Sjdp	TUNDEBUG("%s%d: tunwrite\n", ifp->if_name, ifp->if_unit);
49833965Sjdp
49933965Sjdp	if (uio->uio_resid < 0 || uio->uio_resid > TUNMTU) {
50033965Sjdp		TUNDEBUG("%s%d: len=%d!\n", ifp->if_name, ifp->if_unit,
50133965Sjdp		    uio->uio_resid);
50233965Sjdp		return EIO;
50333965Sjdp	}
504130561Sobrien	tlen = uio->uio_resid;
505130561Sobrien
50677298Sobrien	/* get a header mbuf */
50789857Sobrien	MGETHDR(m, M_DONTWAIT, MT_DATA);
50889857Sobrien	if (m == NULL)
50989857Sobrien		return ENOBUFS;
51089857Sobrien	mlen = MHLEN;
51189857Sobrien
51289857Sobrien	top = 0;
51389857Sobrien	mp = &top;
51489857Sobrien	while (error == 0 && uio->uio_resid > 0) {
51589857Sobrien		m->m_len = min(mlen, uio->uio_resid);
51689857Sobrien		error = uiomove(mtod (m, caddr_t), m->m_len, uio);
51789857Sobrien		*mp = m;
51889857Sobrien		mp = &m->m_next;
51989857Sobrien		if (uio->uio_resid > 0) {
52089857Sobrien			MGET (m, M_DONTWAIT, MT_DATA);
52133965Sjdp			if (m == 0) {
52233965Sjdp				error = ENOBUFS;
52333965Sjdp				break;
52477298Sobrien			}
52533965Sjdp			mlen = MLEN;
52633965Sjdp		}
52733965Sjdp	}
52833965Sjdp	if (error) {
52933965Sjdp		if (top)
53033965Sjdp			m_freem (top);
53133965Sjdp		return error;
53233965Sjdp	}
53333965Sjdp
53433965Sjdp	top->m_pkthdr.len = tlen;
53533965Sjdp	top->m_pkthdr.rcvif = ifp;
53633965Sjdp
53733965Sjdp#if NBPFILTER > 0
53833965Sjdp	if (tunctl[unit].tun_bpf) {
53933965Sjdp		/*
54077298Sobrien		 * We need to prepend the address family as
54189857Sobrien		 * a four byte field.  Cons up a dummy header
54289857Sobrien		 * to pacify bpf.  This is safe because bpf
54333965Sjdp		 * will only read from the mbuf (i.e., it won't
544130561Sobrien		 * try to free it or keep a pointer to it).
545130561Sobrien		 */
546130561Sobrien		struct mbuf m;
547130561Sobrien		u_int af = AF_INET;
54833965Sjdp
549130561Sobrien		m.m_next = top;
550130561Sobrien		m.m_len = 4;
551130561Sobrien		m.m_data = (char *)&af;
552130561Sobrien
553130561Sobrien		bpf_mtap(tunctl[unit].tun_bpf, &m);
554130561Sobrien	}
555130561Sobrien#endif
556130561Sobrien
557130561Sobrien	s = splimp();
558130561Sobrien	if (IF_QFULL (&ipintrq)) {
559130561Sobrien		IF_DROP(&ipintrq);
560130561Sobrien		splx(s);
561130561Sobrien		ifp->if_collisions++;
562130561Sobrien		m_freem(top);
563130561Sobrien		return ENOBUFS;
564130561Sobrien	}
565130561Sobrien	IF_ENQUEUE(&ipintrq, top);
566130561Sobrien	splx(s);
567130561Sobrien	ifp->if_ipackets++;
568130561Sobrien	schednetisr(NETISR_IP);
569130561Sobrien	return error;
570130561Sobrien}
571130561Sobrien
572130561Sobrien/*
573130561Sobrien * tunselect - the select interface, this is only useful on reads
574130561Sobrien * really. The write detect always returns true, write never blocks
575130561Sobrien * anyway, it either accepts the packet or drops it.
576130561Sobrien */
577130561Sobrienint
578130561Sobrientunselect(dev_t dev, int rw, struct proc *p)
579130561Sobrien{
58033965Sjdp	int		unit = minor(dev), s;
58133965Sjdp	struct tun_softc *tp = &tunctl[unit];
58277298Sobrien	struct ifnet	*ifp = &tp->tun_if;
58333965Sjdp
58433965Sjdp	s = splimp();
58533965Sjdp	TUNDEBUG("%s%d: tunselect\n", ifp->if_name, ifp->if_unit);
58633965Sjdp
58733965Sjdp	switch (rw) {
58833965Sjdp	case FREAD:
58933965Sjdp		if (ifp->if_snd.ifq_len > 0) {
59033965Sjdp			splx(s);
59133965Sjdp			TUNDEBUG("%s%d: tunselect q=%d\n", ifp->if_name,
59233965Sjdp			    ifp->if_unit, ifp->if_snd.ifq_len);
59333965Sjdp			return 1;
59433965Sjdp		}
59533965Sjdp		selrecord(p, &tp->tun_rsel);
59633965Sjdp		break;
597130561Sobrien	case FWRITE:
598130561Sobrien		splx(s);
59977298Sobrien		return 1;
60089857Sobrien	}
60189857Sobrien	splx(s);
60233965Sjdp	TUNDEBUG("%s%d: tunselect waiting\n", ifp->if_name, ifp->if_unit);
603130561Sobrien	return 0;
604130561Sobrien}
605130561Sobrien
606130561Sobrien#endif  /* NTUN */
607130561Sobrien