if_tun.c revision 83805
1190688Sweongyo/*	$NetBSD: if_tun.c,v 1.14 1994/06/29 06:36:25 cgd Exp $	*/
2190688Sweongyo
3190688Sweongyo/*
4190688Sweongyo * Copyright (c) 1988, Julian Onions <jpo@cs.nott.ac.uk>
5190688Sweongyo * Nottingham University 1987.
6190688Sweongyo *
7190688Sweongyo * This source may be freely distributed, however I would be interested
8190688Sweongyo * in any changes that are made.
9190688Sweongyo *
10190688Sweongyo * This driver takes packets off the IP i/f and hands them up to a
11190688Sweongyo * user process to have its wicked way with. This driver has it's
12190688Sweongyo * roots in a similar driver written by Phil Cockcroft (formerly) at
13190688Sweongyo * UCL. This driver is based much more on read/write/poll mode of
14190688Sweongyo * operation though.
15190688Sweongyo *
16190688Sweongyo * $FreeBSD: head/sys/net/if_tun.c 83805 2001-09-21 22:46:54Z jhb $
17190688Sweongyo */
18190688Sweongyo
19190688Sweongyo#include "opt_inet.h"
20190688Sweongyo
21190688Sweongyo#include <sys/param.h>
22190688Sweongyo#include <sys/proc.h>
23190688Sweongyo#include <sys/systm.h>
24190688Sweongyo#include <sys/mbuf.h>
25190688Sweongyo#include <sys/module.h>
26190688Sweongyo#include <sys/socket.h>
27190688Sweongyo#include <sys/filio.h>
28190688Sweongyo#include <sys/sockio.h>
29190688Sweongyo#include <sys/ttycom.h>
30190688Sweongyo#include <sys/poll.h>
31190688Sweongyo#include <sys/signalvar.h>
32190688Sweongyo#include <sys/filedesc.h>
33190688Sweongyo#include <sys/kernel.h>
34190688Sweongyo#include <sys/sysctl.h>
35190688Sweongyo#include <sys/conf.h>
36190688Sweongyo#include <sys/uio.h>
37190688Sweongyo#include <sys/vnode.h>
38190688Sweongyo#include <sys/malloc.h>
39190688Sweongyo#include <machine/bus.h>	/* XXX Shouldn't really be required ! */
40190688Sweongyo#include <sys/rman.h>
41190688Sweongyo
42190688Sweongyo#include <net/if.h>
43190688Sweongyo#include <net/if_types.h>
44190688Sweongyo#include <net/route.h>
45190688Sweongyo#include <net/intrq.h>
46190688Sweongyo#ifdef INET
47190688Sweongyo#include <netinet/in.h>
48190688Sweongyo#endif
49190688Sweongyo#include <net/bpf.h>
50190688Sweongyo#include <net/if_tunvar.h>
51190688Sweongyo#include <net/if_tun.h>
52190688Sweongyo
53190688Sweongyo#define TUNDEBUG	if (tundebug) printf
54190688Sweongyo#define	TUNNAME		"tun"
55190688Sweongyo#define	TUN_MAXUNIT	0x7fff	/* ifp->if_unit is only 15 bits */
56190688Sweongyo
57190688Sweongyostatic MALLOC_DEFINE(M_TUN, TUNNAME, "Tunnel Interface");
58190688Sweongyostatic int tundebug = 0;
59190688Sweongyostatic struct tun_softc *tunhead = NULL;
60190688Sweongyostatic struct rman tununits[1];
61190688Sweongyostatic udev_t tunbasedev = NOUDEV;
62190688SweongyoSYSCTL_INT(_debug, OID_AUTO, if_tun_debug, CTLFLAG_RW, &tundebug, 0, "");
63190688Sweongyo
64190688Sweongyostatic void	tunclone(void *arg, char *name, int namelen, dev_t *dev);
65190688Sweongyostatic void	tuncreate(dev_t dev);
66190688Sweongyostatic int	tunifioctl(struct ifnet *, u_long, caddr_t);
67190688Sweongyostatic int	tuninit(struct ifnet *);
68190688Sweongyostatic int	tunmodevent(module_t, int, void *);
69190688Sweongyostatic int	tunoutput(struct ifnet *, struct mbuf *, struct sockaddr *,
70190688Sweongyo		    struct rtentry *rt);
71190688Sweongyostatic void	tunstart(struct ifnet *);
72190688Sweongyo
73190688Sweongyostatic d_open_t		tunopen;
74190688Sweongyostatic d_close_t	tunclose;
75190688Sweongyostatic d_read_t		tunread;
76190688Sweongyostatic d_write_t	tunwrite;
77190688Sweongyostatic d_ioctl_t	tunioctl;
78190688Sweongyostatic d_poll_t		tunpoll;
79190688Sweongyo
80190688Sweongyo#define CDEV_MAJOR 52
81190688Sweongyostatic struct cdevsw tun_cdevsw = {
82190688Sweongyo	/* open */	tunopen,
83190688Sweongyo	/* close */	tunclose,
84190688Sweongyo	/* read */	tunread,
85190688Sweongyo	/* write */	tunwrite,
86190688Sweongyo	/* ioctl */	tunioctl,
87190688Sweongyo	/* poll */	tunpoll,
88190688Sweongyo	/* mmap */	nommap,
89190688Sweongyo	/* strategy */	nostrategy,
90190688Sweongyo	/* name */	TUNNAME,
91190688Sweongyo	/* maj */	CDEV_MAJOR,
92190688Sweongyo	/* dump */	nodump,
93190688Sweongyo	/* psize */	nopsize,
94190688Sweongyo	/* flags */	0,
95190688Sweongyo};
96190688Sweongyo
97190688Sweongyostatic void
98190688Sweongyotunclone(void *arg, char *name, int namelen, dev_t *dev)
99190688Sweongyo{
100190688Sweongyo	struct resource *r;
101190688Sweongyo	int err;
102190688Sweongyo	int u;
103190688Sweongyo
104190688Sweongyo	if (*dev != NODEV)
105190688Sweongyo		return;
106190688Sweongyo
107190688Sweongyo	if (strcmp(name, TUNNAME) == 0) {
108190688Sweongyo		r = rman_reserve_resource(tununits, 0, TUN_MAXUNIT, 1,
109190688Sweongyo		    RF_ALLOCATED | RF_ACTIVE, NULL);
110190688Sweongyo		u = rman_get_start(r);
111190688Sweongyo		err = rman_release_resource(r);
112190688Sweongyo		KASSERT(err == 0, ("Unexpected failure releasing resource"));
113190688Sweongyo		*dev = makedev(CDEV_MAJOR, unit2minor(u));
114190688Sweongyo		if ((*dev)->si_flags & SI_NAMED)
115190688Sweongyo			return;	/* Already make_dev()d */
116190688Sweongyo	} else if (dev_stdclone(name, NULL, TUNNAME, &u) != 1)
117190688Sweongyo		return;	/* Don't recognise the name */
118190688Sweongyo
119192502Sthompsa	*dev = make_dev(&tun_cdevsw, unit2minor(u),
120190688Sweongyo	    UID_ROOT, GID_WHEEL, 0600, "tun%d", u);
121190688Sweongyo
122192502Sthompsa	/*
123190688Sweongyo	 * All devices depend on tunbasedev so that we can simply
124192502Sthompsa	 * destroy_dev() this device at module unload time to get
125190688Sweongyo	 * rid of all our make_dev()d resources.
126192502Sthompsa	 */
127190688Sweongyo	if (tunbasedev == NOUDEV)
128190688Sweongyo		tunbasedev = (*dev)->si_udev;
129190688Sweongyo	else {
130190688Sweongyo		(*dev)->si_flags |= SI_CHEAPCLONE;
131192502Sthompsa		dev_depends(udev2dev(tunbasedev, 0), *dev);
132190688Sweongyo	}
133190688Sweongyo}
134190688Sweongyo
135190688Sweongyostatic int
136190688Sweongyotunmodevent(module_t mod, int type, void *data)
137190688Sweongyo{
138190688Sweongyo	static eventhandler_tag tag;
139190688Sweongyo	struct tun_softc *tp;
140190688Sweongyo	dev_t dev;
141190688Sweongyo	int err;
142190688Sweongyo
143190688Sweongyo	switch (type) {
144190688Sweongyo	case MOD_LOAD:
145190688Sweongyo		tag = EVENTHANDLER_REGISTER(dev_clone, tunclone, 0, 1000);
146190688Sweongyo		if (tag == NULL)
147190688Sweongyo			return (ENOMEM);
148190688Sweongyo		if (!devfs_present) {
149190688Sweongyo			err = cdevsw_add(&tun_cdevsw);
150190688Sweongyo			if (err != 0) {
151190688Sweongyo				EVENTHANDLER_DEREGISTER(dev_clone, tag);
152190688Sweongyo				return (err);
153190688Sweongyo			}
154190688Sweongyo		}
155190688Sweongyo		tununits->rm_type = RMAN_ARRAY;
156190688Sweongyo		tununits->rm_descr = "open if_tun units";
157190688Sweongyo		err = rman_init(tununits);
158190688Sweongyo		if (err != 0) {
159190688Sweongyo			cdevsw_remove(&tun_cdevsw);
160190688Sweongyo			EVENTHANDLER_DEREGISTER(dev_clone, tag);
161190688Sweongyo			return (err);
162190688Sweongyo		}
163190688Sweongyo		err = rman_manage_region(tununits, 0, TUN_MAXUNIT);
164190688Sweongyo		if (err != 0) {
165190688Sweongyo			printf("%s: tununits: rman_manage_region: Failed %d\n",
166190688Sweongyo			    TUNNAME, err);
167190688Sweongyo			rman_fini(tununits);
168190688Sweongyo			cdevsw_remove(&tun_cdevsw);
169190688Sweongyo			EVENTHANDLER_DEREGISTER(dev_clone, tag);
170190688Sweongyo			return (err);
171190688Sweongyo		}
172190688Sweongyo		break;
173190688Sweongyo	case MOD_UNLOAD:
174190688Sweongyo		err = rman_fini(tununits);
175192984Sthompsa		if (err != 0)
176190688Sweongyo			return (err);
177190688Sweongyo		EVENTHANDLER_DEREGISTER(dev_clone, tag);
178190688Sweongyo
179190688Sweongyo		while (tunhead != NULL) {
180190688Sweongyo			KASSERT((tunhead->tun_flags & TUN_OPEN) == 0,
181190688Sweongyo			    ("tununits is out of sync - unit %d",
182190688Sweongyo			    tunhead->tun_if.if_unit));
183190688Sweongyo			tp = tunhead;
184190688Sweongyo			dev = makedev(tun_cdevsw.d_maj,
185190688Sweongyo			    unit2minor(tp->tun_if.if_unit));
186190688Sweongyo			KASSERT(dev->si_drv1 == tp, ("Bad makedev result"));
187190688Sweongyo			tunhead = tp->next;
188190688Sweongyo			bpfdetach(&tp->tun_if);
189190688Sweongyo			if_detach(&tp->tun_if);
190190688Sweongyo			KASSERT(dev->si_flags & SI_NAMED, ("Missing make_dev"));
191190688Sweongyo			FREE(tp, M_TUN);
192190688Sweongyo		}
193190688Sweongyo
194190688Sweongyo		/*
195192258Ssam		 * Destroying tunbasedev results in all of our make_dev()s
196190688Sweongyo		 * conveniently going away.
197190688Sweongyo		 */
198190688Sweongyo		if (tunbasedev != NOUDEV)
199190688Sweongyo			destroy_dev(udev2dev(tunbasedev, 0));
200190688Sweongyo
201190688Sweongyo		if (!devfs_present)
202190688Sweongyo			cdevsw_remove(&tun_cdevsw);
203190688Sweongyo		break;
204190688Sweongyo	}
205190688Sweongyo	return 0;
206190688Sweongyo}
207192984Sthompsa
208190688Sweongyostatic moduledata_t tun_mod = {
209190688Sweongyo	"if_tun",
210190688Sweongyo	tunmodevent,
211190688Sweongyo	0
212190744Sthompsa};
213190744Sthompsa
214190688SweongyoDECLARE_MODULE(if_tun, tun_mod, SI_SUB_PSEUDO, SI_ORDER_ANY);
215190688Sweongyo
216190688Sweongyostatic void
217190744Sthompsatunstart(struct ifnet *ifp)
218190688Sweongyo{
219190688Sweongyo	struct tun_softc *tp = ifp->if_softc;
220190688Sweongyo
221190688Sweongyo	if (tp->tun_flags & TUN_RWAIT) {
222190688Sweongyo		tp->tun_flags &= ~TUN_RWAIT;
223190744Sthompsa		wakeup((caddr_t)tp);
224190744Sthompsa	}
225190688Sweongyo	if (tp->tun_flags & TUN_ASYNC && tp->tun_sigio)
226190688Sweongyo		pgsigio(tp->tun_sigio, SIGIO, 0);
227190688Sweongyo	selwakeup(&tp->tun_rsel);
228190688Sweongyo}
229190744Sthompsa
230190744Sthompsastatic void
231190688Sweongyotuncreate(dev_t dev)
232190688Sweongyo{
233190688Sweongyo	struct tun_softc *sc;
234190688Sweongyo	struct ifnet *ifp;
235190688Sweongyo
236190744Sthompsa	if (!(dev->si_flags & SI_NAMED))
237190744Sthompsa		dev = make_dev(&tun_cdevsw, minor(dev),
238190688Sweongyo		    UID_UUCP, GID_DIALER, 0600, "tun%d", dev2unit(dev));
239190688Sweongyo
240190688Sweongyo	MALLOC(sc, struct tun_softc *, sizeof(*sc), M_TUN, M_WAITOK | M_ZERO);
241190688Sweongyo	sc->tun_flags = TUN_INITED;
242190744Sthompsa	sc->next = tunhead;
243190688Sweongyo	tunhead = sc;
244190688Sweongyo
245190688Sweongyo	ifp = &sc->tun_if;
246190688Sweongyo	ifp->if_unit = dev2unit(dev);
247190688Sweongyo	ifp->if_name = TUNNAME;
248190744Sthompsa	ifp->if_mtu = TUNMTU;
249190744Sthompsa	ifp->if_ioctl = tunifioctl;
250190688Sweongyo	ifp->if_output = tunoutput;
251190688Sweongyo	ifp->if_start = tunstart;
252190688Sweongyo	ifp->if_flags = IFF_POINTOPOINT | IFF_MULTICAST;
253190688Sweongyo	ifp->if_type = IFT_PPP;
254190744Sthompsa	ifp->if_snd.ifq_maxlen = ifqmaxlen;
255190744Sthompsa	ifp->if_softc = sc;
256190688Sweongyo	if_attach(ifp);
257190688Sweongyo	bpfattach(ifp, DLT_NULL, sizeof(u_int));
258190688Sweongyo	dev->si_drv1 = sc;
259190688Sweongyo}
260190688Sweongyo
261190688Sweongyostatic int
262190688Sweongyotunopen(dev_t dev, int flag, int mode, struct thread *td)
263190688Sweongyo{
264190688Sweongyo	struct resource *r;
265190688Sweongyo	struct ifnet	*ifp;
266190688Sweongyo	struct tun_softc *tp;
267190688Sweongyo	int unit;
268190688Sweongyo
269190688Sweongyo	unit = dev2unit(dev);
270190688Sweongyo	if (unit > TUN_MAXUNIT)
271190688Sweongyo		return (ENXIO);
272190688Sweongyo
273190688Sweongyo	r = rman_reserve_resource(tununits, unit, unit, 1,
274190688Sweongyo	    RF_ALLOCATED | RF_ACTIVE, NULL);
275190688Sweongyo	if (r == NULL)
276190688Sweongyo		return (EBUSY);
277190688Sweongyo
278190688Sweongyo	dev->si_flags &= ~SI_CHEAPCLONE;
279190688Sweongyo
280190688Sweongyo	tp = dev->si_drv1;
281190688Sweongyo	if (!tp) {
282190688Sweongyo		tuncreate(dev);
283190688Sweongyo		tp = dev->si_drv1;
284190688Sweongyo	}
285190688Sweongyo	KASSERT(!(tp->tun_flags & TUN_OPEN), ("Resource & flags out-of-sync"));
286190688Sweongyo	tp->r_unit = r;
287190688Sweongyo	tp->tun_pid = td->td_proc->p_pid;
288190688Sweongyo	ifp = &tp->tun_if;
289190688Sweongyo	tp->tun_flags |= TUN_OPEN;
290190688Sweongyo	TUNDEBUG("%s%d: open\n", ifp->if_name, ifp->if_unit);
291190688Sweongyo
292190688Sweongyo	return (0);
293190688Sweongyo}
294190688Sweongyo
295190688Sweongyo/*
296190688Sweongyo * tunclose - close the device - mark i/f down & delete
297190688Sweongyo * routing info
298190688Sweongyo */
299190688Sweongyostatic	int
300190688Sweongyotunclose(dev_t dev, int foo, int bar, struct thread *td)
301190688Sweongyo{
302190688Sweongyo	struct tun_softc *tp;
303190688Sweongyo	struct ifnet *ifp;
304190688Sweongyo	int s;
305190688Sweongyo	int err;
306190688Sweongyo
307190688Sweongyo	tp = dev->si_drv1;
308190688Sweongyo	ifp = &tp->tun_if;
309190688Sweongyo
310190688Sweongyo	KASSERT(tp->r_unit, ("Unit %d not marked open", ifp->if_unit));
311190688Sweongyo	tp->tun_flags &= ~TUN_OPEN;
312190688Sweongyo	tp->tun_pid = 0;
313190688Sweongyo
314190688Sweongyo	/*
315190688Sweongyo	 * junk all pending output
316190688Sweongyo	 */
317190688Sweongyo	IF_DRAIN(&ifp->if_snd);
318190688Sweongyo
319190688Sweongyo	if (ifp->if_flags & IFF_UP) {
320190688Sweongyo		s = splimp();
321190688Sweongyo		if_down(ifp);
322190688Sweongyo		splx(s);
323190688Sweongyo	}
324190688Sweongyo
325190688Sweongyo	if (ifp->if_flags & IFF_RUNNING) {
326190688Sweongyo		register struct ifaddr *ifa;
327190688Sweongyo
328190688Sweongyo		s = splimp();
329190688Sweongyo		/* find internet addresses and delete routes */
330192984Sthompsa		TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link)
331190688Sweongyo			if (ifa->ifa_addr->sa_family == AF_INET)
332192499Sthompsa				rtinit(ifa, (int)RTM_DELETE,
333190688Sweongyo				    tp->tun_flags & TUN_DSTADDR ? RTF_HOST : 0);
334190688Sweongyo		ifp->if_flags &= ~IFF_RUNNING;
335190688Sweongyo		splx(s);
336190688Sweongyo	}
337190688Sweongyo
338190688Sweongyo	funsetown(tp->tun_sigio);
339190688Sweongyo	selwakeup(&tp->tun_rsel);
340190688Sweongyo
341190688Sweongyo	TUNDEBUG ("%s%d: closed\n", ifp->if_name, ifp->if_unit);
342190688Sweongyo	err = rman_release_resource(tp->r_unit);
343190688Sweongyo	KASSERT(err == 0, ("Unit %d failed to release", ifp->if_unit));
344190688Sweongyo
345190688Sweongyo	return (0);
346192984Sthompsa}
347190688Sweongyo
348190688Sweongyostatic int
349190688Sweongyotuninit(struct ifnet *ifp)
350190688Sweongyo{
351190688Sweongyo	struct tun_softc *tp = ifp->if_softc;
352190688Sweongyo	register struct ifaddr *ifa;
353190688Sweongyo	int error = 0;
354190688Sweongyo
355190688Sweongyo	TUNDEBUG("%s%d: tuninit\n", ifp->if_name, ifp->if_unit);
356190688Sweongyo
357190688Sweongyo	ifp->if_flags |= IFF_UP | IFF_RUNNING;
358192511Sthompsa	getmicrotime(&ifp->if_lastchange);
359190688Sweongyo
360190688Sweongyo	for (ifa = TAILQ_FIRST(&ifp->if_addrhead); ifa;
361190688Sweongyo	     ifa = TAILQ_NEXT(ifa, ifa_link)) {
362190688Sweongyo		if (ifa->ifa_addr == NULL)
363190688Sweongyo			error = EFAULT;
364190688Sweongyo			/* XXX: Should maybe return straight off? */
365190688Sweongyo		else {
366190688Sweongyo#ifdef INET
367190688Sweongyo			if (ifa->ifa_addr->sa_family == AF_INET) {
368190688Sweongyo			    struct sockaddr_in *si;
369190688Sweongyo
370190688Sweongyo			    si = (struct sockaddr_in *)ifa->ifa_addr;
371190688Sweongyo			    if (si->sin_addr.s_addr)
372190688Sweongyo				    tp->tun_flags |= TUN_IASET;
373190688Sweongyo
374190688Sweongyo			    si = (struct sockaddr_in *)ifa->ifa_dstaddr;
375190688Sweongyo			    if (si && si->sin_addr.s_addr)
376190688Sweongyo				    tp->tun_flags |= TUN_DSTADDR;
377190688Sweongyo			}
378190688Sweongyo#endif
379190688Sweongyo		}
380190688Sweongyo	}
381190688Sweongyo	return (error);
382190688Sweongyo}
383190688Sweongyo
384190688Sweongyo/*
385190688Sweongyo * Process an ioctl request.
386190688Sweongyo */
387190688Sweongyoint
388190688Sweongyotunifioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
389190688Sweongyo{
390190688Sweongyo	struct ifreq *ifr = (struct ifreq *)data;
391190688Sweongyo	struct tun_softc *tp = ifp->if_softc;
392190688Sweongyo	struct ifstat *ifs;
393190688Sweongyo	int		error = 0, s;
394190688Sweongyo
395190688Sweongyo	s = splimp();
396190688Sweongyo	switch(cmd) {
397190688Sweongyo	case SIOCGIFSTATUS:
398190688Sweongyo		ifs = (struct ifstat *)data;
399190688Sweongyo		if (tp->tun_pid)
400190688Sweongyo			sprintf(ifs->ascii + strlen(ifs->ascii),
401190688Sweongyo			    "\tOpened by PID %d\n", tp->tun_pid);
402190688Sweongyo		break;
403190688Sweongyo	case SIOCSIFADDR:
404190688Sweongyo		error = tuninit(ifp);
405190688Sweongyo		TUNDEBUG("%s%d: address set, error=%d\n",
406190688Sweongyo			 ifp->if_name, ifp->if_unit, error);
407190688Sweongyo		break;
408190688Sweongyo	case SIOCSIFDSTADDR:
409190688Sweongyo		error = tuninit(ifp);
410190688Sweongyo		TUNDEBUG("%s%d: destination address set, error=%d\n",
411190688Sweongyo			 ifp->if_name, ifp->if_unit, error);
412190688Sweongyo		break;
413190688Sweongyo	case SIOCSIFMTU:
414190688Sweongyo		ifp->if_mtu = ifr->ifr_mtu;
415190688Sweongyo		TUNDEBUG("%s%d: mtu set\n", ifp->if_name, ifp->if_unit);
416190688Sweongyo		break;
417190688Sweongyo	case SIOCSIFFLAGS:
418190688Sweongyo	case SIOCADDMULTI:
419190688Sweongyo	case SIOCDELMULTI:
420190688Sweongyo		break;
421190688Sweongyo	default:
422190688Sweongyo		error = EINVAL;
423190688Sweongyo	}
424190688Sweongyo	splx(s);
425190688Sweongyo	return (error);
426190688Sweongyo}
427190688Sweongyo
428190688Sweongyo/*
429190688Sweongyo * tunoutput - queue packets from higher level ready to put out.
430190688Sweongyo */
431190688Sweongyoint
432190688Sweongyotunoutput(
433190688Sweongyo	struct ifnet *ifp,
434190688Sweongyo	struct mbuf *m0,
435190688Sweongyo	struct sockaddr *dst,
436190688Sweongyo	struct rtentry *rt)
437190688Sweongyo{
438190688Sweongyo	struct tun_softc *tp = ifp->if_softc;
439190688Sweongyo
440190688Sweongyo	TUNDEBUG ("%s%d: tunoutput\n", ifp->if_name, ifp->if_unit);
441190688Sweongyo
442190688Sweongyo	if ((tp->tun_flags & TUN_READY) != TUN_READY) {
443190688Sweongyo		TUNDEBUG ("%s%d: not ready 0%o\n", ifp->if_name,
444190688Sweongyo			  ifp->if_unit, tp->tun_flags);
445190688Sweongyo		m_freem (m0);
446190688Sweongyo		return EHOSTDOWN;
447190688Sweongyo	}
448190688Sweongyo
449190688Sweongyo	/* BPF write needs to be handled specially */
450190688Sweongyo	if (dst->sa_family == AF_UNSPEC) {
451190688Sweongyo		dst->sa_family = *(mtod(m0, int *));
452190688Sweongyo		m0->m_len -= sizeof(int);
453190688Sweongyo		m0->m_pkthdr.len -= sizeof(int);
454190688Sweongyo		m0->m_data += sizeof(int);
455190688Sweongyo	}
456190688Sweongyo
457190688Sweongyo	if (ifp->if_bpf) {
458190688Sweongyo		/*
459190688Sweongyo		 * We need to prepend the address family as
460190688Sweongyo		 * a four byte field.  Cons up a dummy header
461190688Sweongyo		 * to pacify bpf.  This is safe because bpf
462190688Sweongyo		 * will only read from the mbuf (i.e., it won't
463190688Sweongyo		 * try to free it or keep a pointer to it).
464190688Sweongyo		 */
465190688Sweongyo		struct mbuf m;
466190688Sweongyo		uint32_t af = dst->sa_family;
467190688Sweongyo
468190688Sweongyo		m.m_next = m0;
469190688Sweongyo		m.m_len = 4;
470190688Sweongyo		m.m_data = (char *)&af;
471190688Sweongyo
472190688Sweongyo		bpf_mtap(ifp, &m);
473190688Sweongyo	}
474190688Sweongyo
475190688Sweongyo	/* prepend sockaddr? this may abort if the mbuf allocation fails */
476190688Sweongyo	if (tp->tun_flags & TUN_LMODE) {
477190688Sweongyo		/* allocate space for sockaddr */
478190688Sweongyo		M_PREPEND(m0, dst->sa_len, M_DONTWAIT);
479190688Sweongyo
480190688Sweongyo		/* if allocation failed drop packet */
481190688Sweongyo		if (m0 == NULL) {
482190688Sweongyo			ifp->if_iqdrops++;
483190688Sweongyo			ifp->if_oerrors++;
484190688Sweongyo			return (ENOBUFS);
485192468Ssam		} else {
486192468Ssam			bcopy(dst, m0->m_data, dst->sa_len);
487192468Ssam		}
488192468Ssam	}
489192468Ssam
490190688Sweongyo	if (tp->tun_flags & TUN_IFHEAD) {
491190688Sweongyo		/* Prepend the address family */
492190688Sweongyo		M_PREPEND(m0, 4, M_DONTWAIT);
493190688Sweongyo
494190688Sweongyo		/* if allocation failed drop packet */
495190688Sweongyo		if (m0 == NULL) {
496190688Sweongyo			ifp->if_iqdrops++;
497190688Sweongyo			ifp->if_oerrors++;
498190688Sweongyo			return ENOBUFS;
499190688Sweongyo		} else
500190688Sweongyo			*(u_int32_t *)m0->m_data = htonl(dst->sa_family);
501190688Sweongyo	} else {
502190688Sweongyo#ifdef INET
503190688Sweongyo		if (dst->sa_family != AF_INET)
504190688Sweongyo#endif
505190688Sweongyo		{
506190688Sweongyo			m_freem(m0);
507190688Sweongyo			return EAFNOSUPPORT;
508190688Sweongyo		}
509190688Sweongyo	}
510190688Sweongyo
511190688Sweongyo	if (! IF_HANDOFF(&ifp->if_snd, m0, ifp)) {
512190688Sweongyo		ifp->if_collisions++;
513190688Sweongyo		return ENOBUFS;
514190688Sweongyo	}
515190688Sweongyo	ifp->if_opackets++;
516190688Sweongyo	return 0;
517190688Sweongyo}
518190688Sweongyo
519190688Sweongyo/*
520190688Sweongyo * the cdevsw interface is now pretty minimal.
521192419Sweongyo */
522190688Sweongyostatic	int
523190688Sweongyotunioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct thread *td)
524190688Sweongyo{
525190688Sweongyo	int		s;
526190688Sweongyo	int		error;
527190688Sweongyo	struct tun_softc *tp = dev->si_drv1;
528190688Sweongyo 	struct tuninfo *tunp;
529190688Sweongyo
530190688Sweongyo	switch (cmd) {
531190688Sweongyo 	case TUNSIFINFO:
532190688Sweongyo 		tunp = (struct tuninfo *)data;
533190688Sweongyo		if (tunp->mtu < IF_MINMTU)
534190688Sweongyo			return (EINVAL);
535190688Sweongyo 		if (tp->tun_if.if_mtu != tunp->mtu
536190688Sweongyo		&& (error = suser_td(td)) != 0)
537190688Sweongyo			return (error);
538190688Sweongyo 		tp->tun_if.if_mtu = tunp->mtu;
539190688Sweongyo 		tp->tun_if.if_type = tunp->type;
540190688Sweongyo 		tp->tun_if.if_baudrate = tunp->baudrate;
541190688Sweongyo 		break;
542190688Sweongyo 	case TUNGIFINFO:
543190688Sweongyo 		tunp = (struct tuninfo *)data;
544190688Sweongyo 		tunp->mtu = tp->tun_if.if_mtu;
545190688Sweongyo 		tunp->type = tp->tun_if.if_type;
546190688Sweongyo 		tunp->baudrate = tp->tun_if.if_baudrate;
547190688Sweongyo 		break;
548190688Sweongyo	case TUNSDEBUG:
549190688Sweongyo		tundebug = *(int *)data;
550190688Sweongyo		break;
551190688Sweongyo	case TUNGDEBUG:
552190688Sweongyo		*(int *)data = tundebug;
553190688Sweongyo		break;
554190688Sweongyo	case TUNSLMODE:
555190688Sweongyo		if (*(int *)data) {
556190688Sweongyo			tp->tun_flags |= TUN_LMODE;
557190688Sweongyo			tp->tun_flags &= ~TUN_IFHEAD;
558190688Sweongyo		} else
559190688Sweongyo			tp->tun_flags &= ~TUN_LMODE;
560190688Sweongyo		break;
561190688Sweongyo	case TUNSIFHEAD:
562190688Sweongyo		if (*(int *)data) {
563190688Sweongyo			tp->tun_flags |= TUN_IFHEAD;
564190688Sweongyo			tp->tun_flags &= ~TUN_LMODE;
565190688Sweongyo		} else
566190688Sweongyo			tp->tun_flags &= ~TUN_IFHEAD;
567190688Sweongyo		break;
568190688Sweongyo	case TUNGIFHEAD:
569190688Sweongyo		*(int *)data = (tp->tun_flags & TUN_IFHEAD) ? 1 : 0;
570190688Sweongyo		break;
571190688Sweongyo	case TUNSIFMODE:
572190688Sweongyo		/* deny this if UP */
573190688Sweongyo		if (tp->tun_if.if_flags & IFF_UP)
574190688Sweongyo			return(EBUSY);
575190688Sweongyo
576190688Sweongyo		switch (*(int *)data & ~IFF_MULTICAST) {
577190688Sweongyo		case IFF_POINTOPOINT:
578190688Sweongyo		case IFF_BROADCAST:
579190688Sweongyo			tp->tun_if.if_flags &=
580190688Sweongyo			    ~(IFF_BROADCAST|IFF_POINTOPOINT|IFF_MULTICAST);
581190688Sweongyo			tp->tun_if.if_flags |= *(int *)data;
582190688Sweongyo			break;
583190688Sweongyo		default:
584190688Sweongyo			return(EINVAL);
585190688Sweongyo		}
586190688Sweongyo		break;
587190688Sweongyo	case TUNSIFPID:
588190688Sweongyo		tp->tun_pid = curthread->td_proc->p_pid;
589190688Sweongyo		break;
590190688Sweongyo	case FIONBIO:
591190688Sweongyo		break;
592190688Sweongyo	case FIOASYNC:
593190688Sweongyo		if (*(int *)data)
594190688Sweongyo			tp->tun_flags |= TUN_ASYNC;
595190688Sweongyo		else
596190688Sweongyo			tp->tun_flags &= ~TUN_ASYNC;
597190688Sweongyo		break;
598190688Sweongyo	case FIONREAD:
599190688Sweongyo		s = splimp();
600190688Sweongyo		if (tp->tun_if.if_snd.ifq_head) {
601190688Sweongyo			struct mbuf *mb = tp->tun_if.if_snd.ifq_head;
602190688Sweongyo			for( *(int *)data = 0; mb != 0; mb = mb->m_next)
603190688Sweongyo				*(int *)data += mb->m_len;
604190688Sweongyo		} else
605190688Sweongyo			*(int *)data = 0;
606190688Sweongyo		splx(s);
607190688Sweongyo		break;
608190688Sweongyo	case FIOSETOWN:
609190688Sweongyo		return (fsetown(*(int *)data, &tp->tun_sigio));
610190688Sweongyo
611190688Sweongyo	case FIOGETOWN:
612190688Sweongyo		*(int *)data = fgetown(tp->tun_sigio);
613190688Sweongyo		return (0);
614190688Sweongyo
615190688Sweongyo	/* This is deprecated, FIOSETOWN should be used instead. */
616190688Sweongyo	case TIOCSPGRP:
617190688Sweongyo		return (fsetown(-(*(int *)data), &tp->tun_sigio));
618190688Sweongyo
619190688Sweongyo	/* This is deprecated, FIOGETOWN should be used instead. */
620190688Sweongyo	case TIOCGPGRP:
621190688Sweongyo		*(int *)data = -fgetown(tp->tun_sigio);
622190688Sweongyo		return (0);
623190688Sweongyo
624190688Sweongyo	default:
625190688Sweongyo		return (ENOTTY);
626190688Sweongyo	}
627190688Sweongyo	return (0);
628190688Sweongyo}
629190688Sweongyo
630190688Sweongyo/*
631190688Sweongyo * The cdevsw read interface - reads a packet at a time, or at
632190688Sweongyo * least as much of a packet as can be read.
633190688Sweongyo */
634190688Sweongyostatic	int
635190688Sweongyotunread(dev_t dev, struct uio *uio, int flag)
636190688Sweongyo{
637190688Sweongyo	struct tun_softc *tp = dev->si_drv1;
638190688Sweongyo	struct ifnet	*ifp = &tp->tun_if;
639190688Sweongyo	struct mbuf	*m, *m0;
640190688Sweongyo	int		error=0, len, s;
641190688Sweongyo
642190688Sweongyo	TUNDEBUG ("%s%d: read\n", ifp->if_name, ifp->if_unit);
643190688Sweongyo	if ((tp->tun_flags & TUN_READY) != TUN_READY) {
644190688Sweongyo		TUNDEBUG ("%s%d: not ready 0%o\n", ifp->if_name,
645190688Sweongyo			  ifp->if_unit, tp->tun_flags);
646190688Sweongyo		return EHOSTDOWN;
647190688Sweongyo	}
648190688Sweongyo
649190688Sweongyo	tp->tun_flags &= ~TUN_RWAIT;
650190688Sweongyo
651190688Sweongyo	s = splimp();
652190688Sweongyo	do {
653190688Sweongyo		IF_DEQUEUE(&ifp->if_snd, m0);
654190688Sweongyo		if (m0 == 0) {
655190688Sweongyo			if (flag & IO_NDELAY) {
656190688Sweongyo				splx(s);
657190688Sweongyo				return EWOULDBLOCK;
658190688Sweongyo			}
659190688Sweongyo			tp->tun_flags |= TUN_RWAIT;
660190688Sweongyo			if((error = tsleep((caddr_t)tp, PCATCH | (PZERO + 1),
661190688Sweongyo					"tunread", 0)) != 0) {
662190688Sweongyo				splx(s);
663190688Sweongyo				return error;
664190688Sweongyo			}
665190688Sweongyo		}
666190688Sweongyo	} while (m0 == 0);
667190688Sweongyo	splx(s);
668190688Sweongyo
669190688Sweongyo	while (m0 && uio->uio_resid > 0 && error == 0) {
670190688Sweongyo		len = min(uio->uio_resid, m0->m_len);
671190688Sweongyo		if (len != 0)
672190688Sweongyo			error = uiomove(mtod(m0, caddr_t), len, uio);
673190688Sweongyo		MFREE(m0, m);
674190688Sweongyo		m0 = m;
675190688Sweongyo	}
676190688Sweongyo
677190688Sweongyo	if (m0) {
678190688Sweongyo		TUNDEBUG("%s%d: Dropping mbuf\n", ifp->if_name, ifp->if_unit);
679190688Sweongyo		m_freem(m0);
680190688Sweongyo	}
681190688Sweongyo	return error;
682190688Sweongyo}
683190688Sweongyo
684190688Sweongyo/*
685190688Sweongyo * the cdevsw write interface - an atomic write is a packet - or else!
686190688Sweongyo */
687190688Sweongyostatic	int
688190688Sweongyotunwrite(dev_t dev, struct uio *uio, int flag)
689190688Sweongyo{
690190688Sweongyo	struct tun_softc *tp = dev->si_drv1;
691190688Sweongyo	struct ifnet	*ifp = &tp->tun_if;
692190688Sweongyo	struct mbuf	*top, **mp, *m;
693190688Sweongyo	int		error=0, tlen, mlen;
694190688Sweongyo	uint32_t	family;
695190688Sweongyo
696190688Sweongyo	TUNDEBUG("%s%d: tunwrite\n", ifp->if_name, ifp->if_unit);
697190688Sweongyo
698190688Sweongyo	if (uio->uio_resid == 0)
699190688Sweongyo		return 0;
700190688Sweongyo
701190688Sweongyo	if (uio->uio_resid < 0 || uio->uio_resid > TUNMRU) {
702190688Sweongyo		TUNDEBUG("%s%d: len=%d!\n", ifp->if_name, ifp->if_unit,
703190688Sweongyo		    uio->uio_resid);
704190688Sweongyo		return EIO;
705190688Sweongyo	}
706190688Sweongyo	tlen = uio->uio_resid;
707190688Sweongyo
708190688Sweongyo	/* get a header mbuf */
709190688Sweongyo	MGETHDR(m, M_DONTWAIT, MT_DATA);
710190688Sweongyo	if (m == NULL)
711190688Sweongyo		return ENOBUFS;
712190688Sweongyo	mlen = MHLEN;
713190688Sweongyo
714190688Sweongyo	top = 0;
715190688Sweongyo	mp = &top;
716190688Sweongyo	while (error == 0 && uio->uio_resid > 0) {
717190688Sweongyo		m->m_len = min(mlen, uio->uio_resid);
718190688Sweongyo		error = uiomove(mtod (m, caddr_t), m->m_len, uio);
719190688Sweongyo		*mp = m;
720190688Sweongyo		mp = &m->m_next;
721190688Sweongyo		if (uio->uio_resid > 0) {
722190688Sweongyo			MGET (m, M_DONTWAIT, MT_DATA);
723190688Sweongyo			if (m == 0) {
724190688Sweongyo				error = ENOBUFS;
725190688Sweongyo				break;
726190688Sweongyo			}
727190688Sweongyo			mlen = MLEN;
728190688Sweongyo		}
729190688Sweongyo	}
730190688Sweongyo	if (error) {
731190688Sweongyo		if (top)
732190688Sweongyo			m_freem (top);
733190688Sweongyo		ifp->if_ierrors++;
734190688Sweongyo		return error;
735190688Sweongyo	}
736190688Sweongyo
737190688Sweongyo	top->m_pkthdr.len = tlen;
738190688Sweongyo	top->m_pkthdr.rcvif = ifp;
739190688Sweongyo
740190688Sweongyo	if (ifp->if_bpf) {
741190688Sweongyo		if (tp->tun_flags & TUN_IFHEAD) {
742190688Sweongyo			/*
743190688Sweongyo			 * Conveniently, we already have a 4-byte address
744190688Sweongyo			 * family prepended to our packet !
745190688Sweongyo			 * Inconveniently, it's in the wrong byte order !
746190688Sweongyo			 */
747190688Sweongyo			if ((top = m_pullup(top, sizeof(family))) == NULL)
748190688Sweongyo				return ENOBUFS;
749190688Sweongyo			*mtod(top, u_int32_t *) =
750190688Sweongyo			    ntohl(*mtod(top, u_int32_t *));
751190688Sweongyo			bpf_mtap(ifp, top);
752190688Sweongyo			*mtod(top, u_int32_t *) =
753190688Sweongyo			    htonl(*mtod(top, u_int32_t *));
754190688Sweongyo		} else {
755190688Sweongyo			/*
756190688Sweongyo			 * We need to prepend the address family as
757190688Sweongyo			 * a four byte field.  Cons up a dummy header
758190688Sweongyo			 * to pacify bpf.  This is safe because bpf
759190688Sweongyo			 * will only read from the mbuf (i.e., it won't
760190688Sweongyo			 * try to free it or keep a pointer to it).
761190688Sweongyo			 */
762190688Sweongyo			struct mbuf m;
763190688Sweongyo			uint32_t af = AF_INET;
764190688Sweongyo
765190688Sweongyo			m.m_next = top;
766190688Sweongyo			m.m_len = 4;
767190688Sweongyo			m.m_data = (char *)&af;
768190688Sweongyo
769190688Sweongyo			bpf_mtap(ifp, &m);
770190688Sweongyo		}
771190688Sweongyo	}
772190688Sweongyo
773190688Sweongyo	if (tp->tun_flags & TUN_IFHEAD) {
774190688Sweongyo		if (top->m_len < sizeof(family) &&
775190688Sweongyo		    (top = m_pullup(top, sizeof(family))) == NULL)
776190688Sweongyo				return ENOBUFS;
777190688Sweongyo		family = ntohl(*mtod(top, u_int32_t *));
778190688Sweongyo		m_adj(top, sizeof(family));
779190688Sweongyo	} else
780190688Sweongyo		family = AF_INET;
781190688Sweongyo
782190688Sweongyo	ifp->if_ibytes += top->m_pkthdr.len;
783190688Sweongyo	ifp->if_ipackets++;
784190688Sweongyo
785190688Sweongyo	return family_enqueue(family, top);
786190688Sweongyo}
787190688Sweongyo
788190688Sweongyo/*
789190688Sweongyo * tunpoll - the poll interface, this is only useful on reads
790190688Sweongyo * really. The write detect always returns true, write never blocks
791190688Sweongyo * anyway, it either accepts the packet or drops it.
792190688Sweongyo */
793190688Sweongyostatic	int
794190688Sweongyotunpoll(dev_t dev, int events, struct thread *td)
795190688Sweongyo{
796190688Sweongyo	int		s;
797190688Sweongyo	struct tun_softc *tp = dev->si_drv1;
798190688Sweongyo	struct ifnet	*ifp = &tp->tun_if;
799190688Sweongyo	int		revents = 0;
800190688Sweongyo
801190688Sweongyo	s = splimp();
802190688Sweongyo	TUNDEBUG("%s%d: tunpoll\n", ifp->if_name, ifp->if_unit);
803190688Sweongyo
804190688Sweongyo	if (events & (POLLIN | POLLRDNORM)) {
805190688Sweongyo		if (ifp->if_snd.ifq_len > 0) {
806190688Sweongyo			TUNDEBUG("%s%d: tunpoll q=%d\n", ifp->if_name,
807190688Sweongyo			    ifp->if_unit, ifp->if_snd.ifq_len);
808190688Sweongyo			revents |= events & (POLLIN | POLLRDNORM);
809190688Sweongyo		} else {
810190688Sweongyo			TUNDEBUG("%s%d: tunpoll waiting\n", ifp->if_name,
811190688Sweongyo			    ifp->if_unit);
812190688Sweongyo			selrecord(td, &tp->tun_rsel);
813190688Sweongyo		}
814190688Sweongyo	}
815190688Sweongyo	if (events & (POLLOUT | POLLWRNORM))
816190688Sweongyo		revents |= events & (POLLOUT | POLLWRNORM);
817190688Sweongyo
818190688Sweongyo	splx(s);
819190688Sweongyo	return (revents);
820190688Sweongyo}
821190688Sweongyo