if_tun.c revision 126908
1/*	$NetBSD: if_tun.c,v 1.14 1994/06/29 06:36:25 cgd Exp $	*/
2
3/*
4 * Copyright (c) 1988, Julian Onions <jpo@cs.nott.ac.uk>
5 * Nottingham University 1987.
6 *
7 * This source may be freely distributed, however I would be interested
8 * in any changes that are made.
9 *
10 * This driver takes packets off the IP i/f and hands them up to a
11 * user process to have its wicked way with. This driver has it's
12 * roots in a similar driver written by Phil Cockcroft (formerly) at
13 * UCL. This driver is based much more on read/write/poll mode of
14 * operation though.
15 *
16 * $FreeBSD: head/sys/net/if_tun.c 126908 2004-03-13 05:51:06Z rwatson $
17 */
18
19#include "opt_atalk.h"
20#include "opt_inet.h"
21#include "opt_inet6.h"
22#include "opt_ipx.h"
23#include "opt_mac.h"
24
25#include <sys/param.h>
26#include <sys/proc.h>
27#include <sys/systm.h>
28#include <sys/mac.h>
29#include <sys/mbuf.h>
30#include <sys/module.h>
31#include <sys/socket.h>
32#include <sys/filio.h>
33#include <sys/sockio.h>
34#include <sys/ttycom.h>
35#include <sys/poll.h>
36#include <sys/signalvar.h>
37#include <sys/filedesc.h>
38#include <sys/kernel.h>
39#include <sys/sysctl.h>
40#include <sys/conf.h>
41#include <sys/uio.h>
42#include <sys/vnode.h>
43#include <sys/malloc.h>
44#include <sys/random.h>
45
46#include <net/if.h>
47#include <net/if_types.h>
48#include <net/netisr.h>
49#include <net/route.h>
50#ifdef INET
51#include <netinet/in.h>
52#endif
53#include <net/bpf.h>
54#include <net/if_tun.h>
55
56#include <sys/queue.h>
57
58struct tun_softc {
59	TAILQ_ENTRY(tun_softc)	tun_list;
60	dev_t			tun_dev;
61	u_short	tun_flags;		/* misc flags */
62#define	TUN_OPEN	0x0001
63#define	TUN_INITED	0x0002
64#define	TUN_RCOLL	0x0004
65#define	TUN_IASET	0x0008
66#define	TUN_DSTADDR	0x0010
67#define	TUN_LMODE	0x0020
68#define	TUN_RWAIT	0x0040
69#define	TUN_ASYNC	0x0080
70#define	TUN_IFHEAD	0x0100
71
72#define TUN_READY       (TUN_OPEN | TUN_INITED)
73
74	struct proc		*tun_proc;	/* Owning process */
75	struct	ifnet tun_if;		/* the interface */
76	struct  sigio *tun_sigio;	/* information for async I/O */
77	struct	selinfo	tun_rsel;	/* read select */
78};
79
80#define TUNDEBUG	if (tundebug) if_printf
81#define	TUNNAME		"tun"
82
83static MALLOC_DEFINE(M_TUN, TUNNAME, "Tunnel Interface");
84static int tundebug = 0;
85static struct clonedevs *tunclones;
86static TAILQ_HEAD(,tun_softc)	tunhead = TAILQ_HEAD_INITIALIZER(tunhead);
87SYSCTL_INT(_debug, OID_AUTO, if_tun_debug, CTLFLAG_RW, &tundebug, 0, "");
88
89static void	tunclone(void *arg, char *name, int namelen, dev_t *dev);
90static void	tuncreate(dev_t dev);
91static int	tunifioctl(struct ifnet *, u_long, caddr_t);
92static int	tuninit(struct ifnet *);
93static int	tunmodevent(module_t, int, void *);
94static int	tunoutput(struct ifnet *, struct mbuf *, struct sockaddr *,
95		    struct rtentry *rt);
96static void	tunstart(struct ifnet *);
97
98static d_open_t		tunopen;
99static d_close_t	tunclose;
100static d_read_t		tunread;
101static d_write_t	tunwrite;
102static d_ioctl_t	tunioctl;
103static d_poll_t		tunpoll;
104
105static struct cdevsw tun_cdevsw = {
106	.d_version =	D_VERSION,
107	.d_flags =	D_PSEUDO | D_NEEDGIANT,
108	.d_open =	tunopen,
109	.d_close =	tunclose,
110	.d_read =	tunread,
111	.d_write =	tunwrite,
112	.d_ioctl =	tunioctl,
113	.d_poll =	tunpoll,
114	.d_name =	TUNNAME,
115};
116
117static void
118tunclone(void *arg, char *name, int namelen, dev_t *dev)
119{
120	int u, i;
121
122	if (*dev != NODEV)
123		return;
124
125	if (strcmp(name, TUNNAME) == 0) {
126		u = -1;
127	} else if (dev_stdclone(name, NULL, TUNNAME, &u) != 1)
128		return;	/* Don't recognise the name */
129	if (u != -1 && u > IF_MAXUNIT)
130		return;	/* Unit number too high */
131
132	/* find any existing device, or allocate new unit number */
133	i = clone_create(&tunclones, &tun_cdevsw, &u, dev, 0);
134	if (i) {
135		/* No preexisting dev_t, create one */
136		*dev = make_dev(&tun_cdevsw, unit2minor(u),
137		    UID_UUCP, GID_DIALER, 0600, "tun%d", u);
138		if (*dev != NULL)
139			(*dev)->si_flags |= SI_CHEAPCLONE;
140	}
141}
142
143static int
144tunmodevent(module_t mod, int type, void *data)
145{
146	static eventhandler_tag tag;
147	struct tun_softc *tp;
148	dev_t dev;
149
150	switch (type) {
151	case MOD_LOAD:
152		clone_setup(&tunclones);
153		tag = EVENTHANDLER_REGISTER(dev_clone, tunclone, 0, 1000);
154		if (tag == NULL)
155			return (ENOMEM);
156		break;
157	case MOD_UNLOAD:
158		EVENTHANDLER_DEREGISTER(dev_clone, tag);
159
160		while (!TAILQ_EMPTY(&tunhead)) {
161			tp = TAILQ_FIRST(&tunhead);
162			KASSERT((tp->tun_flags & TUN_OPEN) == 0,
163			    ("tununits is out of sync - unit %d",
164			    tp->tun_if.if_dunit));
165			TAILQ_REMOVE(&tunhead, tp, tun_list);
166			dev = tp->tun_dev;
167			bpfdetach(&tp->tun_if);
168			if_detach(&tp->tun_if);
169			destroy_dev(dev);
170			free(tp, M_TUN);
171		}
172		clone_cleanup(&tunclones);
173		break;
174	}
175	return 0;
176}
177
178static moduledata_t tun_mod = {
179	"if_tun",
180	tunmodevent,
181	0
182};
183
184DECLARE_MODULE(if_tun, tun_mod, SI_SUB_PSEUDO, SI_ORDER_ANY);
185
186static void
187tunstart(struct ifnet *ifp)
188{
189	struct tun_softc *tp = ifp->if_softc;
190
191	if (tp->tun_flags & TUN_RWAIT) {
192		tp->tun_flags &= ~TUN_RWAIT;
193		wakeup(tp);
194	}
195	if (tp->tun_flags & TUN_ASYNC && tp->tun_sigio)
196		pgsigio(&tp->tun_sigio, SIGIO, 0);
197	selwakeuppri(&tp->tun_rsel, PZERO + 1);
198}
199
200static void
201tuncreate(dev_t dev)
202{
203	struct tun_softc *sc;
204	struct ifnet *ifp;
205
206	dev->si_flags &= ~SI_CHEAPCLONE;
207
208	MALLOC(sc, struct tun_softc *, sizeof(*sc), M_TUN, M_WAITOK | M_ZERO);
209	sc->tun_flags = TUN_INITED;
210	sc->tun_dev = dev;
211	TAILQ_INSERT_TAIL(&tunhead, sc, tun_list);
212
213	ifp = &sc->tun_if;
214	if_initname(ifp, TUNNAME, dev2unit(dev));
215	ifp->if_mtu = TUNMTU;
216	ifp->if_ioctl = tunifioctl;
217	ifp->if_output = tunoutput;
218	ifp->if_start = tunstart;
219	ifp->if_flags = IFF_POINTOPOINT | IFF_MULTICAST;
220	ifp->if_type = IFT_PPP;
221	ifp->if_snd.ifq_maxlen = ifqmaxlen;
222	ifp->if_softc = sc;
223	if_attach(ifp);
224	bpfattach(ifp, DLT_NULL, sizeof(u_int));
225	dev->si_drv1 = sc;
226}
227
228static int
229tunopen(dev_t dev, int flag, int mode, struct thread *td)
230{
231	struct ifnet	*ifp;
232	struct tun_softc *tp;
233
234	tp = dev->si_drv1;
235	if (!tp) {
236		tuncreate(dev);
237		tp = dev->si_drv1;
238	}
239
240	if (tp->tun_proc != NULL && tp->tun_proc != td->td_proc)
241		return (EBUSY);
242	tp->tun_proc = td->td_proc;
243
244	tp->tun_flags |= TUN_OPEN;
245	ifp = &tp->tun_if;
246	TUNDEBUG(ifp, "open\n");
247
248	return (0);
249}
250
251/*
252 * tunclose - close the device - mark i/f down & delete
253 * routing info
254 */
255static	int
256tunclose(dev_t dev, int foo, int bar, struct thread *td)
257{
258	struct tun_softc *tp;
259	struct ifnet *ifp;
260	int s;
261
262	tp = dev->si_drv1;
263	ifp = &tp->tun_if;
264
265	tp->tun_flags &= ~TUN_OPEN;
266	tp->tun_proc = NULL;
267
268	/*
269	 * junk all pending output
270	 */
271	IF_DRAIN(&ifp->if_snd);
272
273	if (ifp->if_flags & IFF_UP) {
274		s = splimp();
275		if_down(ifp);
276		splx(s);
277	}
278
279	if (ifp->if_flags & IFF_RUNNING) {
280		struct ifaddr *ifa;
281
282		s = splimp();
283		/* find internet addresses and delete routes */
284		TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link)
285			if (ifa->ifa_addr->sa_family == AF_INET)
286				rtinit(ifa, (int)RTM_DELETE,
287				    tp->tun_flags & TUN_DSTADDR ? RTF_HOST : 0);
288		ifp->if_flags &= ~IFF_RUNNING;
289		splx(s);
290	}
291
292	funsetown(&tp->tun_sigio);
293	selwakeuppri(&tp->tun_rsel, PZERO + 1);
294	TUNDEBUG (ifp, "closed\n");
295	return (0);
296}
297
298static int
299tuninit(struct ifnet *ifp)
300{
301	struct tun_softc *tp = ifp->if_softc;
302	struct ifaddr *ifa;
303	int error = 0;
304
305	TUNDEBUG(ifp, "tuninit\n");
306
307	ifp->if_flags |= IFF_UP | IFF_RUNNING;
308	getmicrotime(&ifp->if_lastchange);
309
310	for (ifa = TAILQ_FIRST(&ifp->if_addrhead); ifa;
311	     ifa = TAILQ_NEXT(ifa, ifa_link)) {
312		if (ifa->ifa_addr == NULL)
313			error = EFAULT;
314			/* XXX: Should maybe return straight off? */
315		else {
316#ifdef INET
317			if (ifa->ifa_addr->sa_family == AF_INET) {
318			    struct sockaddr_in *si;
319
320			    si = (struct sockaddr_in *)ifa->ifa_addr;
321			    if (si->sin_addr.s_addr)
322				    tp->tun_flags |= TUN_IASET;
323
324			    si = (struct sockaddr_in *)ifa->ifa_dstaddr;
325			    if (si && si->sin_addr.s_addr)
326				    tp->tun_flags |= TUN_DSTADDR;
327			}
328#endif
329		}
330	}
331	return (error);
332}
333
334/*
335 * Process an ioctl request.
336 */
337static int
338tunifioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
339{
340	struct ifreq *ifr = (struct ifreq *)data;
341	struct tun_softc *tp = ifp->if_softc;
342	struct ifstat *ifs;
343	int		error = 0, s;
344
345	s = splimp();
346	switch(cmd) {
347	case SIOCGIFSTATUS:
348		ifs = (struct ifstat *)data;
349		if (tp->tun_proc)
350			sprintf(ifs->ascii + strlen(ifs->ascii),
351			    "\tOpened by PID %d\n", tp->tun_proc->p_pid);
352		break;
353	case SIOCSIFADDR:
354		error = tuninit(ifp);
355		TUNDEBUG(ifp, "address set, error=%d\n", error);
356		break;
357	case SIOCSIFDSTADDR:
358		error = tuninit(ifp);
359		TUNDEBUG(ifp, "destination address set, error=%d\n", error);
360		break;
361	case SIOCSIFMTU:
362		ifp->if_mtu = ifr->ifr_mtu;
363		TUNDEBUG(ifp, "mtu set\n");
364		break;
365	case SIOCSIFFLAGS:
366	case SIOCADDMULTI:
367	case SIOCDELMULTI:
368		break;
369	default:
370		error = EINVAL;
371	}
372	splx(s);
373	return (error);
374}
375
376/*
377 * tunoutput - queue packets from higher level ready to put out.
378 */
379static int
380tunoutput(
381	struct ifnet *ifp,
382	struct mbuf *m0,
383	struct sockaddr *dst,
384	struct rtentry *rt)
385{
386	struct tun_softc *tp = ifp->if_softc;
387#ifdef MAC
388	int error;
389#endif
390
391	TUNDEBUG (ifp, "tunoutput\n");
392
393#ifdef MAC
394	error = mac_check_ifnet_transmit(ifp, m0);
395	if (error) {
396		m_freem(m0);
397		return (error);
398	}
399#endif
400
401	if ((tp->tun_flags & TUN_READY) != TUN_READY) {
402		TUNDEBUG (ifp, "not ready 0%o\n", tp->tun_flags);
403		m_freem (m0);
404		return (EHOSTDOWN);
405	}
406
407	if ((ifp->if_flags & IFF_UP) != IFF_UP) {
408		m_freem (m0);
409		return (EHOSTDOWN);
410	}
411
412	/* BPF write needs to be handled specially */
413	if (dst->sa_family == AF_UNSPEC) {
414		dst->sa_family = *(mtod(m0, int *));
415		m0->m_len -= sizeof(int);
416		m0->m_pkthdr.len -= sizeof(int);
417		m0->m_data += sizeof(int);
418	}
419
420	if (ifp->if_bpf) {
421		uint32_t af = dst->sa_family;
422		bpf_mtap2(ifp->if_bpf, &af, sizeof(af), m0);
423	}
424
425	/* prepend sockaddr? this may abort if the mbuf allocation fails */
426	if (tp->tun_flags & TUN_LMODE) {
427		/* allocate space for sockaddr */
428		M_PREPEND(m0, dst->sa_len, M_DONTWAIT);
429
430		/* if allocation failed drop packet */
431		if (m0 == NULL) {
432			ifp->if_iqdrops++;
433			ifp->if_oerrors++;
434			return (ENOBUFS);
435		} else {
436			bcopy(dst, m0->m_data, dst->sa_len);
437		}
438	}
439
440	if (tp->tun_flags & TUN_IFHEAD) {
441		/* Prepend the address family */
442		M_PREPEND(m0, 4, M_DONTWAIT);
443
444		/* if allocation failed drop packet */
445		if (m0 == NULL) {
446			ifp->if_iqdrops++;
447			ifp->if_oerrors++;
448			return (ENOBUFS);
449		} else
450			*(u_int32_t *)m0->m_data = htonl(dst->sa_family);
451	} else {
452#ifdef INET
453		if (dst->sa_family != AF_INET)
454#endif
455		{
456			m_freem(m0);
457			return (EAFNOSUPPORT);
458		}
459	}
460
461	if (! IF_HANDOFF(&ifp->if_snd, m0, ifp)) {
462		ifp->if_collisions++;
463		return (ENOBUFS);
464	}
465	ifp->if_opackets++;
466	return (0);
467}
468
469/*
470 * the cdevsw interface is now pretty minimal.
471 */
472static	int
473tunioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct thread *td)
474{
475	int		s;
476	int		error;
477	struct tun_softc *tp = dev->si_drv1;
478	struct tuninfo *tunp;
479
480	switch (cmd) {
481	case TUNSIFINFO:
482		tunp = (struct tuninfo *)data;
483		if (tunp->mtu < IF_MINMTU)
484			return (EINVAL);
485		if (tp->tun_if.if_mtu != tunp->mtu
486		&& (error = suser(td)) != 0)
487			return (error);
488		tp->tun_if.if_mtu = tunp->mtu;
489		tp->tun_if.if_type = tunp->type;
490		tp->tun_if.if_baudrate = tunp->baudrate;
491		break;
492	case TUNGIFINFO:
493		tunp = (struct tuninfo *)data;
494		tunp->mtu = tp->tun_if.if_mtu;
495		tunp->type = tp->tun_if.if_type;
496		tunp->baudrate = tp->tun_if.if_baudrate;
497		break;
498	case TUNSDEBUG:
499		tundebug = *(int *)data;
500		break;
501	case TUNGDEBUG:
502		*(int *)data = tundebug;
503		break;
504	case TUNSLMODE:
505		if (*(int *)data) {
506			tp->tun_flags |= TUN_LMODE;
507			tp->tun_flags &= ~TUN_IFHEAD;
508		} else
509			tp->tun_flags &= ~TUN_LMODE;
510		break;
511	case TUNSIFHEAD:
512		if (*(int *)data) {
513			tp->tun_flags |= TUN_IFHEAD;
514			tp->tun_flags &= ~TUN_LMODE;
515		} else
516			tp->tun_flags &= ~TUN_IFHEAD;
517		break;
518	case TUNGIFHEAD:
519		*(int *)data = (tp->tun_flags & TUN_IFHEAD) ? 1 : 0;
520		break;
521	case TUNSIFMODE:
522		/* deny this if UP */
523		if (tp->tun_if.if_flags & IFF_UP)
524			return(EBUSY);
525
526		switch (*(int *)data & ~IFF_MULTICAST) {
527		case IFF_POINTOPOINT:
528		case IFF_BROADCAST:
529			tp->tun_if.if_flags &=
530			    ~(IFF_BROADCAST|IFF_POINTOPOINT|IFF_MULTICAST);
531			tp->tun_if.if_flags |= *(int *)data;
532			break;
533		default:
534			return(EINVAL);
535		}
536		break;
537	case TUNSIFPID:
538		tp->tun_proc = curthread->td_proc;
539		break;
540	case FIONBIO:
541		break;
542	case FIOASYNC:
543		if (*(int *)data)
544			tp->tun_flags |= TUN_ASYNC;
545		else
546			tp->tun_flags &= ~TUN_ASYNC;
547		break;
548	case FIONREAD:
549		s = splimp();
550		if (tp->tun_if.if_snd.ifq_head) {
551			struct mbuf *mb = tp->tun_if.if_snd.ifq_head;
552			for( *(int *)data = 0; mb != 0; mb = mb->m_next)
553				*(int *)data += mb->m_len;
554		} else
555			*(int *)data = 0;
556		splx(s);
557		break;
558	case FIOSETOWN:
559		return (fsetown(*(int *)data, &tp->tun_sigio));
560
561	case FIOGETOWN:
562		*(int *)data = fgetown(&tp->tun_sigio);
563		return (0);
564
565	/* This is deprecated, FIOSETOWN should be used instead. */
566	case TIOCSPGRP:
567		return (fsetown(-(*(int *)data), &tp->tun_sigio));
568
569	/* This is deprecated, FIOGETOWN should be used instead. */
570	case TIOCGPGRP:
571		*(int *)data = -fgetown(&tp->tun_sigio);
572		return (0);
573
574	default:
575		return (ENOTTY);
576	}
577	return (0);
578}
579
580/*
581 * The cdevsw read interface - reads a packet at a time, or at
582 * least as much of a packet as can be read.
583 */
584static	int
585tunread(dev_t dev, struct uio *uio, int flag)
586{
587	struct tun_softc *tp = dev->si_drv1;
588	struct ifnet	*ifp = &tp->tun_if;
589	struct mbuf	*m;
590	int		error=0, len, s;
591
592	TUNDEBUG (ifp, "read\n");
593	if ((tp->tun_flags & TUN_READY) != TUN_READY) {
594		TUNDEBUG (ifp, "not ready 0%o\n", tp->tun_flags);
595		return (EHOSTDOWN);
596	}
597
598	tp->tun_flags &= ~TUN_RWAIT;
599
600	s = splimp();
601	do {
602		IF_DEQUEUE(&ifp->if_snd, m);
603		if (m == NULL) {
604			if (flag & IO_NDELAY) {
605				splx(s);
606				return (EWOULDBLOCK);
607			}
608			tp->tun_flags |= TUN_RWAIT;
609			if((error = tsleep(tp, PCATCH | (PZERO + 1),
610					"tunread", 0)) != 0) {
611				splx(s);
612				return (error);
613			}
614		}
615	} while (m == NULL);
616	splx(s);
617
618	while (m && uio->uio_resid > 0 && error == 0) {
619		len = min(uio->uio_resid, m->m_len);
620		if (len != 0)
621			error = uiomove(mtod(m, void *), len, uio);
622		m = m_free(m);
623	}
624
625	if (m) {
626		TUNDEBUG(ifp, "Dropping mbuf\n");
627		m_freem(m);
628	}
629	return (error);
630}
631
632/*
633 * the cdevsw write interface - an atomic write is a packet - or else!
634 */
635static	int
636tunwrite(dev_t dev, struct uio *uio, int flag)
637{
638	struct tun_softc *tp = dev->si_drv1;
639	struct ifnet	*ifp = &tp->tun_if;
640	struct mbuf	*top, **mp, *m;
641	int		error=0, tlen, mlen;
642	uint32_t	family;
643	int 		isr;
644
645	TUNDEBUG(ifp, "tunwrite\n");
646
647	if ((ifp->if_flags & IFF_UP) != IFF_UP)
648		/* ignore silently */
649		return (0);
650
651	if (uio->uio_resid == 0)
652		return (0);
653
654	if (uio->uio_resid < 0 || uio->uio_resid > TUNMRU) {
655		TUNDEBUG(ifp, "len=%d!\n", uio->uio_resid);
656		return (EIO);
657	}
658	tlen = uio->uio_resid;
659
660	/* get a header mbuf */
661	MGETHDR(m, M_DONTWAIT, MT_DATA);
662	if (m == NULL)
663		return (ENOBUFS);
664	mlen = MHLEN;
665
666	top = 0;
667	mp = &top;
668	while (error == 0 && uio->uio_resid > 0) {
669		m->m_len = min(mlen, uio->uio_resid);
670		error = uiomove(mtod(m, void *), m->m_len, uio);
671		*mp = m;
672		mp = &m->m_next;
673		if (uio->uio_resid > 0) {
674			MGET (m, M_DONTWAIT, MT_DATA);
675			if (m == 0) {
676				error = ENOBUFS;
677				break;
678			}
679			mlen = MLEN;
680		}
681	}
682	if (error) {
683		if (top)
684			m_freem (top);
685		ifp->if_ierrors++;
686		return (error);
687	}
688
689	top->m_pkthdr.len = tlen;
690	top->m_pkthdr.rcvif = ifp;
691#ifdef MAC
692	mac_create_mbuf_from_ifnet(ifp, top);
693#endif
694
695	if (tp->tun_flags & TUN_IFHEAD) {
696		if (top->m_len < sizeof(family) &&
697		    (top = m_pullup(top, sizeof(family))) == NULL)
698			return (ENOBUFS);
699		family = ntohl(*mtod(top, u_int32_t *));
700		m_adj(top, sizeof(family));
701	} else
702		family = AF_INET;
703
704	BPF_MTAP2(ifp, &family, sizeof(family), top);
705
706	switch (family) {
707#ifdef INET
708	case AF_INET:
709		isr = NETISR_IP;
710		break;
711#endif
712#ifdef INET6
713	case AF_INET6:
714		isr = NETISR_IPV6;
715		break;
716#endif
717#ifdef IPX
718	case AF_IPX:
719		isr = NETISR_IPX;
720		break;
721#endif
722#ifdef NETATALK
723	case AF_APPLETALK:
724		isr = NETISR_ATALK2;
725		break;
726#endif
727	default:
728		m_freem(m);
729		return (EAFNOSUPPORT);
730	}
731	/* First chunk of an mbuf contains good junk */
732	if (harvest.point_to_point)
733		random_harvest(m, 16, 3, 0, RANDOM_NET);
734	ifp->if_ibytes += top->m_pkthdr.len;
735	ifp->if_ipackets++;
736	netisr_dispatch(isr, top);
737	return (0);
738}
739
740/*
741 * tunpoll - the poll interface, this is only useful on reads
742 * really. The write detect always returns true, write never blocks
743 * anyway, it either accepts the packet or drops it.
744 */
745static	int
746tunpoll(dev_t dev, int events, struct thread *td)
747{
748	int		s;
749	struct tun_softc *tp = dev->si_drv1;
750	struct ifnet	*ifp = &tp->tun_if;
751	int		revents = 0;
752
753	s = splimp();
754	TUNDEBUG(ifp, "tunpoll\n");
755
756	if (events & (POLLIN | POLLRDNORM)) {
757		if (ifp->if_snd.ifq_len > 0) {
758			TUNDEBUG(ifp, "tunpoll q=%d\n", ifp->if_snd.ifq_len);
759			revents |= events & (POLLIN | POLLRDNORM);
760		} else {
761			TUNDEBUG(ifp, "tunpoll waiting\n");
762			selrecord(td, &tp->tun_rsel);
763		}
764	}
765	if (events & (POLLOUT | POLLWRNORM))
766		revents |= events & (POLLOUT | POLLWRNORM);
767
768	splx(s);
769	return (revents);
770}
771