if_tun.c revision 104393
1141240Snjl/*	$NetBSD: if_tun.c,v 1.14 1994/06/29 06:36:25 cgd Exp $	*/
2141240Snjl
3141240Snjl/*
4141240Snjl * Copyright (c) 1988, Julian Onions <jpo@cs.nott.ac.uk>
5141240Snjl * Nottingham University 1987.
6141240Snjl *
7141240Snjl * This source may be freely distributed, however I would be interested
8141240Snjl * in any changes that are made.
9141240Snjl *
10141240Snjl * This driver takes packets off the IP i/f and hands them up to a
11141240Snjl * user process to have its wicked way with. This driver has it's
12141240Snjl * roots in a similar driver written by Phil Cockcroft (formerly) at
13141240Snjl * UCL. This driver is based much more on read/write/poll mode of
14141240Snjl * operation though.
15141240Snjl *
16141240Snjl * $FreeBSD: head/sys/net/if_tun.c 104393 2002-10-03 02:13:00Z truckman $
17141240Snjl */
18141240Snjl
19141240Snjl#include "opt_inet.h"
20141240Snjl#include "opt_mac.h"
21141240Snjl
22141240Snjl#include <sys/param.h>
23141240Snjl#include <sys/proc.h>
24141240Snjl#include <sys/systm.h>
25141240Snjl#include <sys/mac.h>
26141240Snjl#include <sys/mbuf.h>
27141240Snjl#include <sys/module.h>
28141240Snjl#include <sys/socket.h>
29141240Snjl#include <sys/filio.h>
30141240Snjl#include <sys/sockio.h>
31141240Snjl#include <sys/ttycom.h>
32141240Snjl#include <sys/poll.h>
33141240Snjl#include <sys/signalvar.h>
34141240Snjl#include <sys/filedesc.h>
35141240Snjl#include <sys/kernel.h>
36141240Snjl#include <sys/sysctl.h>
37141240Snjl#include <sys/conf.h>
38141240Snjl#include <sys/uio.h>
39141240Snjl#include <sys/vnode.h>
40141240Snjl#include <sys/malloc.h>
41141240Snjl#include <machine/bus.h>	/* XXX Shouldn't really be required ! */
42141240Snjl#include <sys/rman.h>
43141814Snjl
44141240Snjl#include <net/if.h>
45141240Snjl#include <net/if_types.h>
46141240Snjl#include <net/route.h>
47141240Snjl#include <net/intrq.h>
48141240Snjl#ifdef INET
49141240Snjl#include <netinet/in.h>
50141240Snjl#endif
51141240Snjl#include <net/bpf.h>
52141240Snjl#include <net/if_tunvar.h>
53141240Snjl#include <net/if_tun.h>
54141240Snjl
55141240Snjl#define TUNDEBUG	if (tundebug) printf
56141240Snjl#define	TUNNAME		"tun"
57141240Snjl#define	TUN_MAXUNIT	0x7fff	/* ifp->if_unit is only 15 bits */
58141240Snjl
59141240Snjlstatic MALLOC_DEFINE(M_TUN, TUNNAME, "Tunnel Interface");
60141923Snjlstatic int tundebug = 0;
61141923Snjlstatic struct tun_softc *tunhead = NULL;
62141923Snjlstatic struct rman tununits[1];
63141923Snjlstatic udev_t tunbasedev = NOUDEV;
64141413SnjlSYSCTL_INT(_debug, OID_AUTO, if_tun_debug, CTLFLAG_RW, &tundebug, 0, "");
65141945Snjl
66141240Snjlstatic void	tunclone(void *arg, char *name, int namelen, dev_t *dev);
67141240Snjlstatic void	tuncreate(dev_t dev);
68141240Snjlstatic int	tunifioctl(struct ifnet *, u_long, caddr_t);
69141240Snjlstatic int	tuninit(struct ifnet *);
70141240Snjlstatic int	tunmodevent(module_t, int, void *);
71141240Snjlstatic int	tunoutput(struct ifnet *, struct mbuf *, struct sockaddr *,
72141240Snjl		    struct rtentry *rt);
73141240Snjlstatic void	tunstart(struct ifnet *);
74141240Snjl
75141240Snjlstatic d_open_t		tunopen;
76141240Snjlstatic d_close_t	tunclose;
77141240Snjlstatic d_read_t		tunread;
78141240Snjlstatic d_write_t	tunwrite;
79141240Snjlstatic d_ioctl_t	tunioctl;
80141240Snjlstatic d_poll_t		tunpoll;
81141240Snjl
82141240Snjl#define CDEV_MAJOR 52
83141240Snjlstatic struct cdevsw tun_cdevsw = {
84141240Snjl	/* open */	tunopen,
85141240Snjl	/* close */	tunclose,
86141413Snjl	/* read */	tunread,
87141240Snjl	/* write */	tunwrite,
88141413Snjl	/* ioctl */	tunioctl,
89141413Snjl	/* poll */	tunpoll,
90141413Snjl	/* mmap */	nommap,
91141413Snjl	/* strategy */	nostrategy,
92141240Snjl	/* name */	TUNNAME,
93141240Snjl	/* maj */	CDEV_MAJOR,
94141240Snjl	/* dump */	nodump,
95141240Snjl	/* psize */	nopsize,
96141240Snjl	/* flags */	0,
97141240Snjl};
98141240Snjl
99141240Snjlstatic void
100141240Snjltunclone(void *arg, char *name, int namelen, dev_t *dev)
101141240Snjl{
102141240Snjl	struct resource *r;
103141240Snjl	int err;
104141240Snjl	int u;
105141240Snjl
106141240Snjl	if (*dev != NODEV)
107141240Snjl		return;
108141240Snjl
109141240Snjl	if (strcmp(name, TUNNAME) == 0) {
110141240Snjl		r = rman_reserve_resource(tununits, 0, TUN_MAXUNIT, 1,
111141240Snjl		    RF_ALLOCATED | RF_ACTIVE, NULL);
112141240Snjl		u = rman_get_start(r);
113141240Snjl		err = rman_release_resource(r);
114141240Snjl		KASSERT(err == 0, ("Unexpected failure releasing resource"));
115141240Snjl		*dev = makedev(CDEV_MAJOR, unit2minor(u));
116141240Snjl		if ((*dev)->si_flags & SI_NAMED)
117141240Snjl			return;	/* Already make_dev()d */
118141240Snjl	} else if (dev_stdclone(name, NULL, TUNNAME, &u) != 1)
119141240Snjl		return;	/* Don't recognise the name */
120141240Snjl
121141240Snjl	*dev = make_dev(&tun_cdevsw, unit2minor(u),
122141240Snjl	    UID_ROOT, GID_WHEEL, 0600, "tun%d", u);
123141240Snjl
124141240Snjl	/*
125141240Snjl	 * All devices depend on tunbasedev so that we can simply
126141923Snjl	 * destroy_dev() this device at module unload time to get
127141945Snjl	 * rid of all our make_dev()d resources.
128141240Snjl	 */
129141240Snjl	if (tunbasedev == NOUDEV)
130141240Snjl		tunbasedev = (*dev)->si_udev;
131141240Snjl	else {
132141240Snjl		(*dev)->si_flags |= SI_CHEAPCLONE;
133141240Snjl		dev_depends(udev2dev(tunbasedev, 0), *dev);
134141240Snjl	}
135141240Snjl}
136141240Snjl
137141240Snjlstatic int
138141240Snjltunmodevent(module_t mod, int type, void *data)
139141240Snjl{
140141240Snjl	static eventhandler_tag tag;
141141240Snjl	struct tun_softc *tp;
142141240Snjl	dev_t dev;
143141240Snjl	int err;
144141240Snjl
145141240Snjl	switch (type) {
146141240Snjl	case MOD_LOAD:
147141240Snjl		tag = EVENTHANDLER_REGISTER(dev_clone, tunclone, 0, 1000);
148141240Snjl		if (tag == NULL)
149141240Snjl			return (ENOMEM);
150141240Snjl		if (!devfs_present) {
151141240Snjl			err = cdevsw_add(&tun_cdevsw);
152141240Snjl			if (err != 0) {
153141240Snjl				EVENTHANDLER_DEREGISTER(dev_clone, tag);
154141240Snjl				return (err);
155141240Snjl			}
156141240Snjl		}
157141240Snjl		tununits->rm_type = RMAN_ARRAY;
158141240Snjl		tununits->rm_descr = "open if_tun units";
159141240Snjl		err = rman_init(tununits);
160141240Snjl		if (err != 0) {
161141240Snjl			cdevsw_remove(&tun_cdevsw);
162141240Snjl			EVENTHANDLER_DEREGISTER(dev_clone, tag);
163141240Snjl			return (err);
164141240Snjl		}
165141240Snjl		err = rman_manage_region(tununits, 0, TUN_MAXUNIT);
166141240Snjl		if (err != 0) {
167141240Snjl			printf("%s: tununits: rman_manage_region: Failed %d\n",
168141240Snjl			    TUNNAME, err);
169141240Snjl			rman_fini(tununits);
170141240Snjl			cdevsw_remove(&tun_cdevsw);
171141240Snjl			EVENTHANDLER_DEREGISTER(dev_clone, tag);
172141240Snjl			return (err);
173141240Snjl		}
174141240Snjl		break;
175141240Snjl	case MOD_UNLOAD:
176141240Snjl		err = rman_fini(tununits);
177141240Snjl		if (err != 0)
178141240Snjl			return (err);
179141240Snjl		EVENTHANDLER_DEREGISTER(dev_clone, tag);
180141814Snjl
181141814Snjl		while (tunhead != NULL) {
182141240Snjl			KASSERT((tunhead->tun_flags & TUN_OPEN) == 0,
183141240Snjl			    ("tununits is out of sync - unit %d",
184141240Snjl			    tunhead->tun_if.if_unit));
185141814Snjl			tp = tunhead;
186141814Snjl			dev = makedev(tun_cdevsw.d_maj,
187141814Snjl			    unit2minor(tp->tun_if.if_unit));
188141814Snjl			KASSERT(dev->si_drv1 == tp, ("Bad makedev result"));
189141814Snjl			tunhead = tp->next;
190141814Snjl			bpfdetach(&tp->tun_if);
191141814Snjl			if_detach(&tp->tun_if);
192141814Snjl			KASSERT(dev->si_flags & SI_NAMED, ("Missing make_dev"));
193141923Snjl			free(tp, M_TUN);
194141923Snjl		}
195141923Snjl
196141923Snjl		/*
197141923Snjl		 * Destroying tunbasedev results in all of our make_dev()s
198141923Snjl		 * conveniently going away.
199141923Snjl		 */
200141923Snjl		if (tunbasedev != NOUDEV)
201141923Snjl			destroy_dev(udev2dev(tunbasedev, 0));
202141923Snjl
203141923Snjl		if (!devfs_present)
204141923Snjl			cdevsw_remove(&tun_cdevsw);
205141923Snjl		break;
206141923Snjl	}
207141923Snjl	return 0;
208141240Snjl}
209141240Snjl
210141240Snjlstatic moduledata_t tun_mod = {
211141240Snjl	"if_tun",
212141240Snjl	tunmodevent,
213141240Snjl	0
214141240Snjl};
215141240Snjl
216141240SnjlDECLARE_MODULE(if_tun, tun_mod, SI_SUB_PSEUDO, SI_ORDER_ANY);
217141240Snjl
218141240Snjlstatic void
219141943Snjltunstart(struct ifnet *ifp)
220141943Snjl{
221141943Snjl	struct tun_softc *tp = ifp->if_softc;
222141943Snjl
223141943Snjl	if (tp->tun_flags & TUN_RWAIT) {
224141943Snjl		tp->tun_flags &= ~TUN_RWAIT;
225141943Snjl		wakeup((caddr_t)tp);
226141943Snjl	}
227141943Snjl	if (tp->tun_flags & TUN_ASYNC && tp->tun_sigio)
228141240Snjl		pgsigio(&tp->tun_sigio, SIGIO, 0);
229141943Snjl	selwakeup(&tp->tun_rsel);
230141943Snjl}
231141943Snjl
232141943Snjlstatic void
233141943Snjltuncreate(dev_t dev)
234141240Snjl{
235141240Snjl	struct tun_softc *sc;
236141240Snjl	struct ifnet *ifp;
237141240Snjl
238141240Snjl	if (!(dev->si_flags & SI_NAMED))
239141413Snjl		dev = make_dev(&tun_cdevsw, minor(dev),
240141413Snjl		    UID_UUCP, GID_DIALER, 0600, "tun%d", dev2unit(dev));
241141413Snjl
242141413Snjl	MALLOC(sc, struct tun_softc *, sizeof(*sc), M_TUN, M_WAITOK | M_ZERO);
243141413Snjl	sc->tun_flags = TUN_INITED;
244141413Snjl	sc->next = tunhead;
245141413Snjl	tunhead = sc;
246141943Snjl
247141943Snjl	ifp = &sc->tun_if;
248141943Snjl	ifp->if_unit = dev2unit(dev);
249141943Snjl	ifp->if_name = TUNNAME;
250141943Snjl	ifp->if_mtu = TUNMTU;
251141943Snjl	ifp->if_ioctl = tunifioctl;
252141943Snjl	ifp->if_output = tunoutput;
253141943Snjl	ifp->if_start = tunstart;
254141943Snjl	ifp->if_flags = IFF_POINTOPOINT | IFF_MULTICAST;
255141413Snjl	ifp->if_type = IFT_PPP;
256141943Snjl	ifp->if_snd.ifq_maxlen = ifqmaxlen;
257141943Snjl	ifp->if_softc = sc;
258141943Snjl	if_attach(ifp);
259141943Snjl	bpfattach(ifp, DLT_NULL, sizeof(u_int));
260141943Snjl	dev->si_drv1 = sc;
261141413Snjl}
262141413Snjl
263141413Snjlstatic int
264141413Snjltunopen(dev_t dev, int flag, int mode, struct thread *td)
265141413Snjl{
266141240Snjl	struct resource *r;
267141923Snjl	struct ifnet	*ifp;
268141923Snjl	struct tun_softc *tp;
269141923Snjl	int unit;
270141923Snjl
271141923Snjl	unit = dev2unit(dev);
272141923Snjl	if (unit > TUN_MAXUNIT)
273141923Snjl		return (ENXIO);
274141923Snjl
275141923Snjl	r = rman_reserve_resource(tununits, unit, unit, 1,
276141923Snjl	    RF_ALLOCATED | RF_ACTIVE, NULL);
277141923Snjl	if (r == NULL)
278141923Snjl		return (EBUSY);
279141923Snjl
280141923Snjl	dev->si_flags &= ~SI_CHEAPCLONE;
281141923Snjl
282141923Snjl	tp = dev->si_drv1;
283141923Snjl	if (!tp) {
284141240Snjl		tuncreate(dev);
285141923Snjl		tp = dev->si_drv1;
286141240Snjl	}
287141240Snjl	KASSERT(!(tp->tun_flags & TUN_OPEN), ("Resource & flags out-of-sync"));
288141240Snjl	tp->r_unit = r;
289141240Snjl	tp->tun_pid = td->td_proc->p_pid;
290141240Snjl	ifp = &tp->tun_if;
291141240Snjl	tp->tun_flags |= TUN_OPEN;
292141240Snjl	TUNDEBUG("%s%d: open\n", ifp->if_name, ifp->if_unit);
293141240Snjl
294141240Snjl	return (0);
295141240Snjl}
296141240Snjl
297141240Snjl/*
298141240Snjl * tunclose - close the device - mark i/f down & delete
299141240Snjl * routing info
300141240Snjl */
301141240Snjlstatic	int
302141240Snjltunclose(dev_t dev, int foo, int bar, struct thread *td)
303141240Snjl{
304141240Snjl	struct tun_softc *tp;
305141240Snjl	struct ifnet *ifp;
306141240Snjl	int s;
307141240Snjl	int err;
308141240Snjl
309141240Snjl	tp = dev->si_drv1;
310141240Snjl	ifp = &tp->tun_if;
311141240Snjl
312141240Snjl	KASSERT(tp->r_unit, ("Unit %d not marked open", ifp->if_unit));
313141240Snjl	tp->tun_flags &= ~TUN_OPEN;
314141240Snjl	tp->tun_pid = 0;
315141240Snjl
316141240Snjl	/*
317141240Snjl	 * junk all pending output
318141240Snjl	 */
319141240Snjl	IF_DRAIN(&ifp->if_snd);
320141240Snjl
321141240Snjl	if (ifp->if_flags & IFF_UP) {
322141240Snjl		s = splimp();
323141240Snjl		if_down(ifp);
324141240Snjl		splx(s);
325141240Snjl	}
326141240Snjl
327141240Snjl	if (ifp->if_flags & IFF_RUNNING) {
328141240Snjl		register struct ifaddr *ifa;
329141240Snjl
330141240Snjl		s = splimp();
331141240Snjl		/* find internet addresses and delete routes */
332141240Snjl		TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link)
333141240Snjl			if (ifa->ifa_addr->sa_family == AF_INET)
334141240Snjl				rtinit(ifa, (int)RTM_DELETE,
335141413Snjl				    tp->tun_flags & TUN_DSTADDR ? RTF_HOST : 0);
336141240Snjl		ifp->if_flags &= ~IFF_RUNNING;
337141240Snjl		splx(s);
338141240Snjl	}
339141240Snjl
340141240Snjl	funsetown(&tp->tun_sigio);
341141240Snjl	selwakeup(&tp->tun_rsel);
342141240Snjl
343141240Snjl	TUNDEBUG ("%s%d: closed\n", ifp->if_name, ifp->if_unit);
344141240Snjl	err = rman_release_resource(tp->r_unit);
345141240Snjl	KASSERT(err == 0, ("Unit %d failed to release", ifp->if_unit));
346141240Snjl
347141240Snjl	return (0);
348141240Snjl}
349141240Snjl
350141240Snjlstatic int
351141240Snjltuninit(struct ifnet *ifp)
352141240Snjl{
353141240Snjl	struct tun_softc *tp = ifp->if_softc;
354141240Snjl	register struct ifaddr *ifa;
355141240Snjl	int error = 0;
356141240Snjl
357141240Snjl	TUNDEBUG("%s%d: tuninit\n", ifp->if_name, ifp->if_unit);
358141240Snjl
359141240Snjl	ifp->if_flags |= IFF_UP | IFF_RUNNING;
360141240Snjl	getmicrotime(&ifp->if_lastchange);
361141240Snjl
362141240Snjl	for (ifa = TAILQ_FIRST(&ifp->if_addrhead); ifa;
363141240Snjl	     ifa = TAILQ_NEXT(ifa, ifa_link)) {
364141240Snjl		if (ifa->ifa_addr == NULL)
365141240Snjl			error = EFAULT;
366141240Snjl			/* XXX: Should maybe return straight off? */
367141240Snjl		else {
368141240Snjl#ifdef INET
369141240Snjl			if (ifa->ifa_addr->sa_family == AF_INET) {
370141240Snjl			    struct sockaddr_in *si;
371141240Snjl
372141240Snjl			    si = (struct sockaddr_in *)ifa->ifa_addr;
373141413Snjl			    if (si->sin_addr.s_addr)
374141240Snjl				    tp->tun_flags |= TUN_IASET;
375141240Snjl
376141240Snjl			    si = (struct sockaddr_in *)ifa->ifa_dstaddr;
377141240Snjl			    if (si && si->sin_addr.s_addr)
378141240Snjl				    tp->tun_flags |= TUN_DSTADDR;
379141240Snjl			}
380141413Snjl#endif
381141240Snjl		}
382141240Snjl	}
383141240Snjl	return (error);
384141240Snjl}
385141240Snjl
386141240Snjl/*
387141240Snjl * Process an ioctl request.
388141240Snjl */
389141240Snjlint
390141240Snjltunifioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
391141240Snjl{
392141240Snjl	struct ifreq *ifr = (struct ifreq *)data;
393141240Snjl	struct tun_softc *tp = ifp->if_softc;
394141240Snjl	struct ifstat *ifs;
395141240Snjl	int		error = 0, s;
396141240Snjl
397141240Snjl	s = splimp();
398141240Snjl	switch(cmd) {
399141824Snjl	case SIOCGIFSTATUS:
400141240Snjl		ifs = (struct ifstat *)data;
401141240Snjl		if (tp->tun_pid)
402141824Snjl			sprintf(ifs->ascii + strlen(ifs->ascii),
403141824Snjl			    "\tOpened by PID %d\n", tp->tun_pid);
404141824Snjl		break;
405141824Snjl	case SIOCSIFADDR:
406141824Snjl		error = tuninit(ifp);
407142032Snjl		TUNDEBUG("%s%d: address set, error=%d\n",
408142032Snjl			 ifp->if_name, ifp->if_unit, error);
409142032Snjl		break;
410141240Snjl	case SIOCSIFDSTADDR:
411142032Snjl		error = tuninit(ifp);
412142032Snjl		TUNDEBUG("%s%d: destination address set, error=%d\n",
413141240Snjl			 ifp->if_name, ifp->if_unit, error);
414141413Snjl		break;
415141824Snjl	case SIOCSIFMTU:
416141814Snjl		ifp->if_mtu = ifr->ifr_mtu;
417141413Snjl		TUNDEBUG("%s%d: mtu set\n", ifp->if_name, ifp->if_unit);
418141413Snjl		break;
419141413Snjl	case SIOCSIFFLAGS:
420141413Snjl	case SIOCADDMULTI:
421141413Snjl	case SIOCDELMULTI:
422141413Snjl		break;
423141413Snjl	default:
424141413Snjl		error = EINVAL;
425141413Snjl	}
426141413Snjl	splx(s);
427141413Snjl	return (error);
428141413Snjl}
429141413Snjl
430141413Snjl/*
431141413Snjl * tunoutput - queue packets from higher level ready to put out.
432141413Snjl */
433141413Snjlint
434141240Snjltunoutput(
435141240Snjl	struct ifnet *ifp,
436141240Snjl	struct mbuf *m0,
437141240Snjl	struct sockaddr *dst,
438141945Snjl	struct rtentry *rt)
439141945Snjl{
440141945Snjl	struct tun_softc *tp = ifp->if_softc;
441141945Snjl#ifdef MAC
442141945Snjl	int error;
443141945Snjl#endif
444141945Snjl
445141240Snjl	TUNDEBUG ("%s%d: tunoutput\n", ifp->if_name, ifp->if_unit);
446141945Snjl
447141945Snjl#ifdef MAC
448141945Snjl	error = mac_check_ifnet_transmit(ifp, m0);
449141945Snjl	if (error) {
450141240Snjl		m_freem(m0);
451141945Snjl		return (error);
452141945Snjl	}
453141945Snjl#endif
454141413Snjl
455141240Snjl	if ((tp->tun_flags & TUN_READY) != TUN_READY) {
456141240Snjl		TUNDEBUG ("%s%d: not ready 0%o\n", ifp->if_name,
457141240Snjl			  ifp->if_unit, tp->tun_flags);
458141240Snjl		m_freem (m0);
459141413Snjl		return (EHOSTDOWN);
460141413Snjl	}
461141413Snjl
462141413Snjl	/* BPF write needs to be handled specially */
463141413Snjl	if (dst->sa_family == AF_UNSPEC) {
464141413Snjl		dst->sa_family = *(mtod(m0, int *));
465141413Snjl		m0->m_len -= sizeof(int);
466141413Snjl		m0->m_pkthdr.len -= sizeof(int);
467141413Snjl		m0->m_data += sizeof(int);
468141413Snjl	}
469141413Snjl
470141413Snjl	if (ifp->if_bpf) {
471141240Snjl		/*
472141240Snjl		 * We need to prepend the address family as
473141240Snjl		 * a four byte field.  Cons up a dummy header
474141240Snjl		 * to pacify bpf.  This is safe because bpf
475141240Snjl		 * will only read from the mbuf (i.e., it won't
476141413Snjl		 * try to free it or keep a pointer to it).
477141240Snjl		 */
478141240Snjl		struct mbuf m;
479141240Snjl		uint32_t af = dst->sa_family;
480141240Snjl
481141240Snjl		m.m_next = m0;
482141240Snjl		m.m_len = 4;
483141240Snjl		m.m_data = (char *)&af;
484141240Snjl
485141413Snjl		bpf_mtap(ifp, &m);
486141413Snjl	}
487141413Snjl
488141413Snjl	/* prepend sockaddr? this may abort if the mbuf allocation fails */
489141413Snjl	if (tp->tun_flags & TUN_LMODE) {
490141240Snjl		/* allocate space for sockaddr */
491141240Snjl		M_PREPEND(m0, dst->sa_len, M_DONTWAIT);
492141240Snjl
493141240Snjl		/* if allocation failed drop packet */
494141240Snjl		if (m0 == NULL) {
495141240Snjl			ifp->if_iqdrops++;
496141240Snjl			ifp->if_oerrors++;
497141240Snjl			return (ENOBUFS);
498141240Snjl		} else {
499141240Snjl			bcopy(dst, m0->m_data, dst->sa_len);
500141413Snjl		}
501141240Snjl	}
502141240Snjl
503141413Snjl	if (tp->tun_flags & TUN_IFHEAD) {
504141240Snjl		/* Prepend the address family */
505141240Snjl		M_PREPEND(m0, 4, M_DONTWAIT);
506141240Snjl
507141413Snjl		/* if allocation failed drop packet */
508141240Snjl		if (m0 == NULL) {
509141240Snjl			ifp->if_iqdrops++;
510141240Snjl			ifp->if_oerrors++;
511141240Snjl			return (ENOBUFS);
512141240Snjl		} else
513141413Snjl			*(u_int32_t *)m0->m_data = htonl(dst->sa_family);
514141413Snjl	} else {
515141413Snjl#ifdef INET
516141240Snjl		if (dst->sa_family != AF_INET)
517141240Snjl#endif
518141240Snjl		{
519141240Snjl			m_freem(m0);
520141240Snjl			return (EAFNOSUPPORT);
521141240Snjl		}
522141240Snjl	}
523141413Snjl
524141240Snjl	if (! IF_HANDOFF(&ifp->if_snd, m0, ifp)) {
525141240Snjl		ifp->if_collisions++;
526141240Snjl		return (ENOBUFS);
527141240Snjl	}
528141240Snjl	ifp->if_opackets++;
529141240Snjl	return (0);
530141240Snjl}
531141240Snjl
532141413Snjl/*
533141413Snjl * the cdevsw interface is now pretty minimal.
534141413Snjl */
535141240Snjlstatic	int
536141413Snjltunioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct thread *td)
537141413Snjl{
538141413Snjl	int		s;
539141413Snjl	int		error;
540141413Snjl	struct tun_softc *tp = dev->si_drv1;
541141413Snjl 	struct tuninfo *tunp;
542141413Snjl
543141413Snjl	switch (cmd) {
544141413Snjl 	case TUNSIFINFO:
545141413Snjl 		tunp = (struct tuninfo *)data;
546141413Snjl		if (tunp->mtu < IF_MINMTU)
547141413Snjl			return (EINVAL);
548141413Snjl 		if (tp->tun_if.if_mtu != tunp->mtu
549141413Snjl		&& (error = suser(td)) != 0)
550141413Snjl			return (error);
551141413Snjl 		tp->tun_if.if_mtu = tunp->mtu;
552141413Snjl 		tp->tun_if.if_type = tunp->type;
553141413Snjl 		tp->tun_if.if_baudrate = tunp->baudrate;
554141413Snjl 		break;
555141413Snjl 	case TUNGIFINFO:
556141413Snjl 		tunp = (struct tuninfo *)data;
557141413Snjl 		tunp->mtu = tp->tun_if.if_mtu;
558141413Snjl 		tunp->type = tp->tun_if.if_type;
559141413Snjl 		tunp->baudrate = tp->tun_if.if_baudrate;
560141413Snjl 		break;
561141413Snjl	case TUNSDEBUG:
562141413Snjl		tundebug = *(int *)data;
563141413Snjl		break;
564141413Snjl	case TUNGDEBUG:
565141413Snjl		*(int *)data = tundebug;
566141413Snjl		break;
567141413Snjl	case TUNSLMODE:
568141413Snjl		if (*(int *)data) {
569141413Snjl			tp->tun_flags |= TUN_LMODE;
570141413Snjl			tp->tun_flags &= ~TUN_IFHEAD;
571141413Snjl		} else
572141413Snjl			tp->tun_flags &= ~TUN_LMODE;
573141413Snjl		break;
574141413Snjl	case TUNSIFHEAD:
575141413Snjl		if (*(int *)data) {
576141413Snjl			tp->tun_flags |= TUN_IFHEAD;
577141413Snjl			tp->tun_flags &= ~TUN_LMODE;
578141413Snjl		} else
579141413Snjl			tp->tun_flags &= ~TUN_IFHEAD;
580141413Snjl		break;
581141413Snjl	case TUNGIFHEAD:
582141413Snjl		*(int *)data = (tp->tun_flags & TUN_IFHEAD) ? 1 : 0;
583141413Snjl		break;
584141413Snjl	case TUNSIFMODE:
585141413Snjl		/* deny this if UP */
586141413Snjl		if (tp->tun_if.if_flags & IFF_UP)
587141413Snjl			return(EBUSY);
588141413Snjl
589141413Snjl		switch (*(int *)data & ~IFF_MULTICAST) {
590141413Snjl		case IFF_POINTOPOINT:
591141413Snjl		case IFF_BROADCAST:
592141413Snjl			tp->tun_if.if_flags &=
593141413Snjl			    ~(IFF_BROADCAST|IFF_POINTOPOINT|IFF_MULTICAST);
594141413Snjl			tp->tun_if.if_flags |= *(int *)data;
595141413Snjl			break;
596141413Snjl		default:
597141413Snjl			return(EINVAL);
598141413Snjl		}
599141413Snjl		break;
600141413Snjl	case TUNSIFPID:
601141413Snjl		tp->tun_pid = curthread->td_proc->p_pid;
602141413Snjl		break;
603141413Snjl	case FIONBIO:
604141413Snjl		break;
605141413Snjl	case FIOASYNC:
606141413Snjl		if (*(int *)data)
607141413Snjl			tp->tun_flags |= TUN_ASYNC;
608141413Snjl		else
609141413Snjl			tp->tun_flags &= ~TUN_ASYNC;
610141413Snjl		break;
611141413Snjl	case FIONREAD:
612141413Snjl		s = splimp();
613141413Snjl		if (tp->tun_if.if_snd.ifq_head) {
614141413Snjl			struct mbuf *mb = tp->tun_if.if_snd.ifq_head;
615141413Snjl			for( *(int *)data = 0; mb != 0; mb = mb->m_next)
616141413Snjl				*(int *)data += mb->m_len;
617141413Snjl		} else
618141413Snjl			*(int *)data = 0;
619141413Snjl		splx(s);
620141413Snjl		break;
621141413Snjl	case FIOSETOWN:
622141413Snjl		return (fsetown(*(int *)data, &tp->tun_sigio));
623141413Snjl
624141413Snjl	case FIOGETOWN:
625141413Snjl		*(int *)data = fgetown(&tp->tun_sigio);
626141413Snjl		return (0);
627141413Snjl
628141413Snjl	/* This is deprecated, FIOSETOWN should be used instead. */
629141413Snjl	case TIOCSPGRP:
630141413Snjl		return (fsetown(-(*(int *)data), &tp->tun_sigio));
631141413Snjl
632141413Snjl	/* This is deprecated, FIOGETOWN should be used instead. */
633141413Snjl	case TIOCGPGRP:
634141413Snjl		*(int *)data = -fgetown(&tp->tun_sigio);
635141413Snjl		return (0);
636141413Snjl
637141413Snjl	default:
638141413Snjl		return (ENOTTY);
639141413Snjl	}
640141413Snjl	return (0);
641141413Snjl}
642141413Snjl
643141413Snjl/*
644141413Snjl * The cdevsw read interface - reads a packet at a time, or at
645141413Snjl * least as much of a packet as can be read.
646141413Snjl */
647141413Snjlstatic	int
648141413Snjltunread(dev_t dev, struct uio *uio, int flag)
649141413Snjl{
650141413Snjl	struct tun_softc *tp = dev->si_drv1;
651141413Snjl	struct ifnet	*ifp = &tp->tun_if;
652141413Snjl	struct mbuf	*m;
653141413Snjl	int		error=0, len, s;
654141413Snjl
655141413Snjl	TUNDEBUG ("%s%d: read\n", ifp->if_name, ifp->if_unit);
656141240Snjl	if ((tp->tun_flags & TUN_READY) != TUN_READY) {
657141240Snjl		TUNDEBUG ("%s%d: not ready 0%o\n", ifp->if_name,
658141240Snjl			  ifp->if_unit, tp->tun_flags);
659141240Snjl		return (EHOSTDOWN);
660141814Snjl	}
661141814Snjl
662141240Snjl	tp->tun_flags &= ~TUN_RWAIT;
663141814Snjl
664141240Snjl	s = splimp();
665141814Snjl	do {
666141240Snjl		IF_DEQUEUE(&ifp->if_snd, m);
667141240Snjl		if (m == NULL) {
668141240Snjl			if (flag & IO_NDELAY) {
669141240Snjl				splx(s);
670141240Snjl				return (EWOULDBLOCK);
671141240Snjl			}
672141240Snjl			tp->tun_flags |= TUN_RWAIT;
673141240Snjl			if((error = tsleep((caddr_t)tp, PCATCH | (PZERO + 1),
674141240Snjl					"tunread", 0)) != 0) {
675141240Snjl				splx(s);
676141240Snjl				return (error);
677141814Snjl			}
678141814Snjl		}
679141814Snjl	} while (m == NULL);
680141814Snjl	splx(s);
681141814Snjl
682141814Snjl	while (m && uio->uio_resid > 0 && error == 0) {
683141240Snjl		len = min(uio->uio_resid, m->m_len);
684141240Snjl		if (len != 0)
685141814Snjl			error = uiomove(mtod(m, caddr_t), len, uio);
686141814Snjl		m = m_free(m);
687141814Snjl	}
688141814Snjl
689141240Snjl	if (m) {
690141814Snjl		TUNDEBUG("%s%d: Dropping mbuf\n", ifp->if_name, ifp->if_unit);
691141814Snjl		m_freem(m);
692141814Snjl	}
693141814Snjl	return (error);
694141814Snjl}
695141814Snjl
696141240Snjl/*
697141814Snjl * the cdevsw write interface - an atomic write is a packet - or else!
698141814Snjl */
699141814Snjlstatic	int
700141814Snjltunwrite(dev_t dev, struct uio *uio, int flag)
701141240Snjl{
702141240Snjl	struct tun_softc *tp = dev->si_drv1;
703141240Snjl	struct ifnet	*ifp = &tp->tun_if;
704141814Snjl	struct mbuf	*top, **mp, *m;
705141814Snjl	int		error=0, tlen, mlen;
706141240Snjl	uint32_t	family;
707141240Snjl
708141240Snjl	TUNDEBUG("%s%d: tunwrite\n", ifp->if_name, ifp->if_unit);
709141240Snjl
710141240Snjl	if (uio->uio_resid == 0)
711141240Snjl		return (0);
712141240Snjl
713141240Snjl	if (uio->uio_resid < 0 || uio->uio_resid > TUNMRU) {
714141240Snjl		TUNDEBUG("%s%d: len=%d!\n", ifp->if_name, ifp->if_unit,
715141240Snjl		    uio->uio_resid);
716141240Snjl		return (EIO);
717141240Snjl	}
718141240Snjl	tlen = uio->uio_resid;
719141240Snjl
720141240Snjl	/* get a header mbuf */
721141240Snjl	MGETHDR(m, M_DONTWAIT, MT_DATA);
722141240Snjl	if (m == NULL)
723141240Snjl		return (ENOBUFS);
724141240Snjl	mlen = MHLEN;
725141240Snjl
726141240Snjl	top = 0;
727141240Snjl	mp = &top;
728141240Snjl	while (error == 0 && uio->uio_resid > 0) {
729141240Snjl		m->m_len = min(mlen, uio->uio_resid);
730141240Snjl		error = uiomove(mtod (m, caddr_t), m->m_len, uio);
731141240Snjl		*mp = m;
732141240Snjl		mp = &m->m_next;
733141240Snjl		if (uio->uio_resid > 0) {
734141240Snjl			MGET (m, M_DONTWAIT, MT_DATA);
735141240Snjl			if (m == 0) {
736141240Snjl				error = ENOBUFS;
737141240Snjl				break;
738141240Snjl			}
739141240Snjl			mlen = MLEN;
740141240Snjl		}
741141240Snjl	}
742141240Snjl	if (error) {
743141240Snjl		if (top)
744141240Snjl			m_freem (top);
745141240Snjl		ifp->if_ierrors++;
746141240Snjl		return (error);
747141240Snjl	}
748141240Snjl
749141240Snjl	top->m_pkthdr.len = tlen;
750141240Snjl	top->m_pkthdr.rcvif = ifp;
751141945Snjl#ifdef MAC
752141240Snjl	mac_create_mbuf_from_ifnet(ifp, top);
753141240Snjl#endif
754141240Snjl
755141814Snjl	if (ifp->if_bpf) {
756141814Snjl		if (tp->tun_flags & TUN_IFHEAD) {
757141240Snjl			/*
758141814Snjl			 * Conveniently, we already have a 4-byte address
759141945Snjl			 * family prepended to our packet !
760141945Snjl			 * Inconveniently, it's in the wrong byte order !
761141945Snjl			 */
762141240Snjl			if ((top = m_pullup(top, sizeof(family))) == NULL)
763141945Snjl				return (ENOBUFS);
764141240Snjl			*mtod(top, u_int32_t *) =
765141814Snjl			    ntohl(*mtod(top, u_int32_t *));
766141814Snjl			bpf_mtap(ifp, top);
767141240Snjl			*mtod(top, u_int32_t *) =
768141240Snjl			    htonl(*mtod(top, u_int32_t *));
769141240Snjl		} else {
770141240Snjl			/*
771141240Snjl			 * We need to prepend the address family as
772141240Snjl			 * a four byte field.  Cons up a dummy header
773141240Snjl			 * to pacify bpf.  This is safe because bpf
774141240Snjl			 * will only read from the mbuf (i.e., it won't
775141240Snjl			 * try to free it or keep a pointer to it).
776141240Snjl			 */
777141240Snjl			struct mbuf m;
778142032Snjl			uint32_t af = AF_INET;
779141240Snjl
780141240Snjl			m.m_next = top;
781141240Snjl			m.m_len = 4;
782141240Snjl			m.m_data = (char *)&af;
783141240Snjl
784141240Snjl			bpf_mtap(ifp, &m);
785141240Snjl		}
786141240Snjl	}
787141240Snjl
788141945Snjl	if (tp->tun_flags & TUN_IFHEAD) {
789141240Snjl		if (top->m_len < sizeof(family) &&
790141240Snjl		    (top = m_pullup(top, sizeof(family))) == NULL)
791141240Snjl			return (ENOBUFS);
792141240Snjl		family = ntohl(*mtod(top, u_int32_t *));
793142032Snjl		m_adj(top, sizeof(family));
794141240Snjl	} else
795141240Snjl		family = AF_INET;
796141814Snjl
797141240Snjl	ifp->if_ibytes += top->m_pkthdr.len;
798141240Snjl	ifp->if_ipackets++;
799141240Snjl
800141240Snjl	return (family_enqueue(family, top));
801141240Snjl}
802
803/*
804 * tunpoll - the poll interface, this is only useful on reads
805 * really. The write detect always returns true, write never blocks
806 * anyway, it either accepts the packet or drops it.
807 */
808static	int
809tunpoll(dev_t dev, int events, struct thread *td)
810{
811	int		s;
812	struct tun_softc *tp = dev->si_drv1;
813	struct ifnet	*ifp = &tp->tun_if;
814	int		revents = 0;
815
816	s = splimp();
817	TUNDEBUG("%s%d: tunpoll\n", ifp->if_name, ifp->if_unit);
818
819	if (events & (POLLIN | POLLRDNORM)) {
820		if (ifp->if_snd.ifq_len > 0) {
821			TUNDEBUG("%s%d: tunpoll q=%d\n", ifp->if_name,
822			    ifp->if_unit, ifp->if_snd.ifq_len);
823			revents |= events & (POLLIN | POLLRDNORM);
824		} else {
825			TUNDEBUG("%s%d: tunpoll waiting\n", ifp->if_name,
826			    ifp->if_unit);
827			selrecord(td, &tp->tun_rsel);
828		}
829	}
830	if (events & (POLLOUT | POLLWRNORM))
831		revents |= events & (POLLOUT | POLLWRNORM);
832
833	splx(s);
834	return (revents);
835}
836