if_tap.c revision 236725
1139823Simp/*-
263670Snsayer * Copyright (C) 1999-2000 by Maksim Yevmenkin <m_evmenkin@yahoo.com>
363670Snsayer * All rights reserved.
463670Snsayer *
563670Snsayer * Redistribution and use in source and binary forms, with or without
663670Snsayer * modification, are permitted provided that the following conditions
763670Snsayer * are met:
863670Snsayer * 1. Redistributions of source code must retain the above copyright
963670Snsayer *    notice, this list of conditions and the following disclaimer.
1063670Snsayer * 2. Redistributions in binary form must reproduce the above copyright
1163670Snsayer *    notice, this list of conditions and the following disclaimer in the
1263670Snsayer *    documentation and/or other materials provided with the distribution.
1363670Snsayer *
1463670Snsayer * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1563670Snsayer * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1663670Snsayer * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1763670Snsayer * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1863670Snsayer * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1963670Snsayer * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2063670Snsayer * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2163670Snsayer * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2263670Snsayer * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2363670Snsayer * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2463670Snsayer * SUCH DAMAGE.
2563670Snsayer *
2663670Snsayer * BASED ON:
2763670Snsayer * -------------------------------------------------------------------------
2863670Snsayer *
2963670Snsayer * Copyright (c) 1988, Julian Onions <jpo@cs.nott.ac.uk>
3063670Snsayer * Nottingham University 1987.
3163670Snsayer */
3263670Snsayer
3363670Snsayer/*
3463670Snsayer * $FreeBSD: head/sys/net/if_tap.c 236725 2012-06-07 19:48:45Z trociny $
3563803Snsayer * $Id: if_tap.c,v 0.21 2000/07/23 21:46:02 max Exp $
3663670Snsayer */
3763670Snsayer
38162711Sru#include "opt_compat.h"
3963670Snsayer#include "opt_inet.h"
4063670Snsayer
4163670Snsayer#include <sys/param.h>
4263670Snsayer#include <sys/conf.h>
43139207Sphk#include <sys/fcntl.h>
4463670Snsayer#include <sys/filio.h>
45236724Strociny#include <sys/jail.h>
4663670Snsayer#include <sys/kernel.h>
4763670Snsayer#include <sys/malloc.h>
4863670Snsayer#include <sys/mbuf.h>
49129880Sphk#include <sys/module.h>
5063670Snsayer#include <sys/poll.h>
51164033Srwatson#include <sys/priv.h>
5263670Snsayer#include <sys/proc.h>
53139207Sphk#include <sys/selinfo.h>
5463670Snsayer#include <sys/signalvar.h>
5563670Snsayer#include <sys/socket.h>
5663670Snsayer#include <sys/sockio.h>
5763670Snsayer#include <sys/sysctl.h>
5863670Snsayer#include <sys/systm.h>
5963670Snsayer#include <sys/ttycom.h>
6063670Snsayer#include <sys/uio.h>
6183043Sbrooks#include <sys/queue.h>
6263670Snsayer
6363670Snsayer#include <net/bpf.h>
6463670Snsayer#include <net/ethernet.h>
6563670Snsayer#include <net/if.h>
66166497Sbms#include <net/if_clone.h>
67152315Sru#include <net/if_dl.h>
68236725Strociny#include <net/if_types.h>
6963670Snsayer#include <net/route.h>
70236724Strociny#include <net/vnet.h>
7163670Snsayer
7263670Snsayer#include <netinet/in.h>
7363670Snsayer
7463670Snsayer#include <net/if_tapvar.h>
7563670Snsayer#include <net/if_tap.h>
7663670Snsayer
7763670Snsayer
7863670Snsayer#define CDEV_NAME	"tap"
7963670Snsayer#define TAPDEBUG	if (tapdebug) printf
8063670Snsayer
8163670Snsayer#define TAP		"tap"
8263670Snsayer#define VMNET		"vmnet"
8383043Sbrooks#define TAPMAXUNIT	0x7fff
84126077Sphk#define VMNET_DEV_MASK	CLONE_FLAG0
8563670Snsayer
8663670Snsayer/* module */
87111742Sdesstatic int		tapmodevent(module_t, int, void *);
8863670Snsayer
8963670Snsayer/* device */
90148868Srwatsonstatic void		tapclone(void *, struct ucred *, char *, int,
91148868Srwatson			    struct cdev **);
92130585Sphkstatic void		tapcreate(struct cdev *);
9363670Snsayer
9463670Snsayer/* network interface */
9593084Sbdestatic void		tapifstart(struct ifnet *);
9693084Sbdestatic int		tapifioctl(struct ifnet *, u_long, caddr_t);
9793084Sbdestatic void		tapifinit(void *);
9863670Snsayer
99166497Sbmsstatic int		tap_clone_create(struct if_clone *, int, caddr_t);
100166497Sbmsstatic void		tap_clone_destroy(struct ifnet *);
101166497Sbmsstatic int		vmnet_clone_create(struct if_clone *, int, caddr_t);
102166497Sbmsstatic void		vmnet_clone_destroy(struct ifnet *);
103166497Sbms
104166497SbmsIFC_SIMPLE_DECLARE(tap, 0);
105166497SbmsIFC_SIMPLE_DECLARE(vmnet, 0);
106166497Sbms
10763670Snsayer/* character device */
10863670Snsayerstatic d_open_t		tapopen;
10963670Snsayerstatic d_close_t	tapclose;
11063670Snsayerstatic d_read_t		tapread;
11163670Snsayerstatic d_write_t	tapwrite;
11263670Snsayerstatic d_ioctl_t	tapioctl;
11363670Snsayerstatic d_poll_t		tappoll;
114156783Semaxstatic d_kqfilter_t	tapkqfilter;
11563670Snsayer
116156783Semax/* kqueue(2) */
117156783Semaxstatic int		tapkqread(struct knote *, long);
118156783Semaxstatic int		tapkqwrite(struct knote *, long);
119156783Semaxstatic void		tapkqdetach(struct knote *);
120156783Semax
121156783Semaxstatic struct filterops	tap_read_filterops = {
122156783Semax	.f_isfd =	1,
123156783Semax	.f_attach =	NULL,
124156783Semax	.f_detach =	tapkqdetach,
125156783Semax	.f_event =	tapkqread,
126156783Semax};
127156783Semax
128156783Semaxstatic struct filterops	tap_write_filterops = {
129156783Semax	.f_isfd =	1,
130156783Semax	.f_attach =	NULL,
131156783Semax	.f_detach =	tapkqdetach,
132156783Semax	.f_event =	tapkqwrite,
133156783Semax};
134156783Semax
13563670Snsayerstatic struct cdevsw	tap_cdevsw = {
136126080Sphk	.d_version =	D_VERSION,
137226500Sed	.d_flags =	D_NEEDMINOR,
138111815Sphk	.d_open =	tapopen,
139111815Sphk	.d_close =	tapclose,
140111815Sphk	.d_read =	tapread,
141111815Sphk	.d_write =	tapwrite,
142111815Sphk	.d_ioctl =	tapioctl,
143111815Sphk	.d_poll =	tappoll,
144111815Sphk	.d_name =	CDEV_NAME,
145156783Semax	.d_kqfilter =	tapkqfilter,
14663670Snsayer};
14763670Snsayer
148127003Srwatson/*
149127003Srwatson * All global variables in if_tap.c are locked with tapmtx, with the
150127003Srwatson * exception of tapdebug, which is accessed unlocked; tapclones is
151127003Srwatson * static at runtime.
152127003Srwatson */
153127003Srwatsonstatic struct mtx		tapmtx;
15483043Sbrooksstatic int			tapdebug = 0;        /* debug flag   */
155167713Sbmsstatic int			tapuopen = 0;        /* allow user open() */
156167713Sbmsstatic int			tapuponopen = 0;    /* IFF_UP on open() */
157166497Sbmsstatic int			tapdclone = 1;	/* enable devfs cloning */
15883043Sbrooksstatic SLIST_HEAD(, tap_softc)	taphead;             /* first device */
159126077Sphkstatic struct clonedevs 	*tapclones;
16063670Snsayer
16163670SnsayerMALLOC_DECLARE(M_TAP);
16263670SnsayerMALLOC_DEFINE(M_TAP, CDEV_NAME, "Ethernet tunnel interface");
16363670SnsayerSYSCTL_INT(_debug, OID_AUTO, if_tap_debug, CTLFLAG_RW, &tapdebug, 0, "");
164144979Smdodd
165144979SmdoddSYSCTL_DECL(_net_link);
166227309Sedstatic SYSCTL_NODE(_net_link, OID_AUTO, tap, CTLFLAG_RW, 0,
167144979Smdodd    "Ethernet tunnel software network interface");
168144979SmdoddSYSCTL_INT(_net_link_tap, OID_AUTO, user_open, CTLFLAG_RW, &tapuopen, 0,
169144979Smdodd	"Allow user to open /dev/tap (based on node permissions)");
170167713SbmsSYSCTL_INT(_net_link_tap, OID_AUTO, up_on_open, CTLFLAG_RW, &tapuponopen, 0,
171167713Sbms	"Bring interface up when /dev/tap is opened");
172166497SbmsSYSCTL_INT(_net_link_tap, OID_AUTO, devfs_cloning, CTLFLAG_RW, &tapdclone, 0,
173166497Sbms	"Enably legacy devfs interface creation");
174144979SmdoddSYSCTL_INT(_net_link_tap, OID_AUTO, debug, CTLFLAG_RW, &tapdebug, 0, "");
175144979Smdodd
176166497SbmsTUNABLE_INT("net.link.tap.devfs_cloning", &tapdclone);
177166497Sbms
17863670SnsayerDEV_MODULE(if_tap, tapmodevent, NULL);
17963670Snsayer
180166497Sbmsstatic int
181166497Sbmstap_clone_create(struct if_clone *ifc, int unit, caddr_t params)
182166497Sbms{
183166497Sbms	struct cdev *dev;
184166497Sbms	int i;
185166497Sbms	int extra;
186166497Sbms
187166497Sbms	if (strcmp(ifc->ifc_name, VMNET) == 0)
188166497Sbms		extra = VMNET_DEV_MASK;
189166497Sbms	else
190166497Sbms		extra = 0;
191166497Sbms
192166497Sbms	/* find any existing device, or allocate new unit number */
193166497Sbms	i = clone_create(&tapclones, &tap_cdevsw, &unit, &dev, extra);
194166497Sbms	if (i) {
195183381Sed		dev = make_dev(&tap_cdevsw, unit | extra,
196166497Sbms		     UID_ROOT, GID_WHEEL, 0600, "%s%d", ifc->ifc_name, unit);
197166497Sbms	}
198166497Sbms
199166497Sbms	tapcreate(dev);
200166497Sbms	return (0);
201166497Sbms}
202166497Sbms
203166497Sbms/* vmnet devices are tap devices in disguise */
204166497Sbmsstatic int
205166497Sbmsvmnet_clone_create(struct if_clone *ifc, int unit, caddr_t params)
206166497Sbms{
207166497Sbms	return tap_clone_create(ifc, unit, params);
208166497Sbms}
209166497Sbms
210166497Sbmsstatic void
211166497Sbmstap_destroy(struct tap_softc *tp)
212166497Sbms{
213166497Sbms	struct ifnet *ifp = tp->tap_ifp;
214166497Sbms
215166497Sbms	/* Unlocked read. */
216166497Sbms	KASSERT(!(tp->tap_flags & TAP_OPEN),
217166497Sbms		("%s flags is out of sync", ifp->if_xname));
218166497Sbms
219236724Strociny	CURVNET_SET(ifp->if_vnet);
220225177Sattilio	seldrain(&tp->tap_rsel);
221166497Sbms	knlist_destroy(&tp->tap_rsel.si_note);
222166497Sbms	destroy_dev(tp->tap_dev);
223166497Sbms	ether_ifdetach(ifp);
224227459Sbrooks	if_free(ifp);
225166497Sbms
226166497Sbms	mtx_destroy(&tp->tap_mtx);
227166497Sbms	free(tp, M_TAP);
228236724Strociny	CURVNET_RESTORE();
229166497Sbms}
230166497Sbms
231166497Sbmsstatic void
232166497Sbmstap_clone_destroy(struct ifnet *ifp)
233166497Sbms{
234166497Sbms	struct tap_softc *tp = ifp->if_softc;
235166497Sbms
236166497Sbms	mtx_lock(&tapmtx);
237166497Sbms	SLIST_REMOVE(&taphead, tp, tap_softc, tap_next);
238166497Sbms	mtx_unlock(&tapmtx);
239166497Sbms	tap_destroy(tp);
240166497Sbms}
241166497Sbms
242166497Sbms/* vmnet devices are tap devices in disguise */
243166497Sbmsstatic void
244166497Sbmsvmnet_clone_destroy(struct ifnet *ifp)
245166497Sbms{
246166497Sbms	tap_clone_destroy(ifp);
247166497Sbms}
248166497Sbms
24963670Snsayer/*
25063670Snsayer * tapmodevent
25163670Snsayer *
25263670Snsayer * module event handler
25363670Snsayer */
25463670Snsayerstatic int
255156783Semaxtapmodevent(module_t mod, int type, void *data)
25663670Snsayer{
25783043Sbrooks	static eventhandler_tag	 eh_tag = NULL;
25883043Sbrooks	struct tap_softc	*tp = NULL;
25983043Sbrooks	struct ifnet		*ifp = NULL;
26063670Snsayer
26163670Snsayer	switch (type) {
26263670Snsayer	case MOD_LOAD:
26363670Snsayer
26483043Sbrooks		/* intitialize device */
26583043Sbrooks
266127003Srwatson		mtx_init(&tapmtx, "tapmtx", NULL, MTX_DEF);
26783043Sbrooks		SLIST_INIT(&taphead);
26883043Sbrooks
269126845Sphk		clone_setup(&tapclones);
27071602Sphk		eh_tag = EVENTHANDLER_REGISTER(dev_clone, tapclone, 0, 1000);
271127003Srwatson		if (eh_tag == NULL) {
272127170Srwatson			clone_cleanup(&tapclones);
273127003Srwatson			mtx_destroy(&tapmtx);
274126077Sphk			return (ENOMEM);
275127003Srwatson		}
276166497Sbms		if_clone_attach(&tap_cloner);
277166497Sbms		if_clone_attach(&vmnet_cloner);
27883043Sbrooks		return (0);
27963670Snsayer
28083043Sbrooks	case MOD_UNLOAD:
281127003Srwatson		/*
282127003Srwatson		 * The EBUSY algorithm here can't quite atomically
283127003Srwatson		 * guarantee that this is race-free since we have to
284127003Srwatson		 * release the tap mtx to deregister the clone handler.
285127003Srwatson		 */
286127003Srwatson		mtx_lock(&tapmtx);
287127003Srwatson		SLIST_FOREACH(tp, &taphead, tap_next) {
288127098Srwatson			mtx_lock(&tp->tap_mtx);
289127003Srwatson			if (tp->tap_flags & TAP_OPEN) {
290127098Srwatson				mtx_unlock(&tp->tap_mtx);
291127003Srwatson				mtx_unlock(&tapmtx);
29283043Sbrooks				return (EBUSY);
293127003Srwatson			}
294127098Srwatson			mtx_unlock(&tp->tap_mtx);
295127003Srwatson		}
296127003Srwatson		mtx_unlock(&tapmtx);
29783043Sbrooks
29871602Sphk		EVENTHANDLER_DEREGISTER(dev_clone, eh_tag);
299166497Sbms		if_clone_detach(&tap_cloner);
300166497Sbms		if_clone_detach(&vmnet_cloner);
301204464Skib		drain_dev_clone_events();
30263670Snsayer
303127003Srwatson		mtx_lock(&tapmtx);
30483043Sbrooks		while ((tp = SLIST_FIRST(&taphead)) != NULL) {
30583043Sbrooks			SLIST_REMOVE_HEAD(&taphead, tap_next);
306127003Srwatson			mtx_unlock(&tapmtx);
30783043Sbrooks
308147256Sbrooks			ifp = tp->tap_ifp;
30983043Sbrooks
310121816Sbrooks			TAPDEBUG("detaching %s\n", ifp->if_xname);
31183043Sbrooks
312166497Sbms			tap_destroy(tp);
313127003Srwatson			mtx_lock(&tapmtx);
31483043Sbrooks		}
315127003Srwatson		mtx_unlock(&tapmtx);
316126077Sphk		clone_cleanup(&tapclones);
31763670Snsayer
318135354Srwatson		mtx_destroy(&tapmtx);
319135354Srwatson
32083043Sbrooks		break;
32163670Snsayer
32263670Snsayer	default:
32363670Snsayer		return (EOPNOTSUPP);
32463670Snsayer	}
32563670Snsayer
32663670Snsayer	return (0);
32763670Snsayer} /* tapmodevent */
32863670Snsayer
32963670Snsayer
33063670Snsayer/*
33171602Sphk * DEVFS handler
33271602Sphk *
33371602Sphk * We need to support two kind of devices - tap and vmnet
33471602Sphk */
33571602Sphkstatic void
336156783Semaxtapclone(void *arg, struct ucred *cred, char *name, int namelen, struct cdev **dev)
33771602Sphk{
338166497Sbms	char		devname[SPECNAMELEN + 1];
339166497Sbms	int		i, unit, append_unit;
340166438Sbms	int		extra;
34171602Sphk
342130640Sphk	if (*dev != NULL)
34371602Sphk		return;
34471602Sphk
345166514Sbms	if (!tapdclone ||
346166514Sbms	    (!tapuopen && priv_check_cred(cred, PRIV_NET_IFCREATE, 0) != 0))
347166497Sbms		return;
348166497Sbms
349166497Sbms	unit = 0;
350166497Sbms	append_unit = 0;
351126077Sphk	extra = 0;
352166497Sbms
353166497Sbms	/* We're interested in only tap/vmnet devices. */
354126077Sphk	if (strcmp(name, TAP) == 0) {
355126077Sphk		unit = -1;
356126077Sphk	} else if (strcmp(name, VMNET) == 0) {
357126077Sphk		unit = -1;
358126077Sphk		extra = VMNET_DEV_MASK;
359166497Sbms	} else if (dev_stdclone(name, NULL, TAP, &unit) != 1) {
360166497Sbms		if (dev_stdclone(name, NULL, VMNET, &unit) != 1) {
361126077Sphk			return;
362166497Sbms		} else {
363166497Sbms			extra = VMNET_DEV_MASK;
364166497Sbms		}
36583043Sbrooks	}
36671602Sphk
367166497Sbms	if (unit == -1)
368166497Sbms		append_unit = 1;
369166497Sbms
370236724Strociny	CURVNET_SET(CRED_TO_VNET(cred));
371126077Sphk	/* find any existing device, or allocate new unit number */
372126077Sphk	i = clone_create(&tapclones, &tap_cdevsw, &unit, dev, extra);
373126077Sphk	if (i) {
374166497Sbms		if (append_unit) {
375166497Sbms			/*
376166497Sbms			 * We were passed 'tun' or 'tap', with no unit specified
377166497Sbms			 * so we'll need to append it now.
378166497Sbms			 */
379166497Sbms			namelen = snprintf(devname, sizeof(devname), "%s%d", name,
380166497Sbms			    unit);
381166497Sbms			name = devname;
382166497Sbms		}
383166497Sbms
384204464Skib		*dev = make_dev_credf(MAKEDEV_REF, &tap_cdevsw, unit | extra,
385204464Skib		     cred, UID_ROOT, GID_WHEEL, 0600, "%s", name);
38671602Sphk	}
387166497Sbms
388166497Sbms	if_clone_create(name, namelen, NULL);
389236724Strociny	CURVNET_RESTORE();
39071602Sphk} /* tapclone */
39171602Sphk
39271602Sphk
39371602Sphk/*
39463670Snsayer * tapcreate
39563670Snsayer *
39663670Snsayer * to create interface
39763670Snsayer */
39863670Snsayerstatic void
399156783Semaxtapcreate(struct cdev *dev)
40063670Snsayer{
40163670Snsayer	struct ifnet		*ifp = NULL;
40263670Snsayer	struct tap_softc	*tp = NULL;
40363670Snsayer	unsigned short		 macaddr_hi;
404178221Semax	uint32_t		 macaddr_mid;
405213028Sjhb	int			 unit;
40663670Snsayer	char			*name = NULL;
407147256Sbrooks	u_char			eaddr[6];
40863670Snsayer
409126077Sphk	dev->si_flags &= ~SI_CHEAPCLONE;
410126077Sphk
41163670Snsayer	/* allocate driver storage and create device */
412184205Sdes	tp = malloc(sizeof(*tp), M_TAP, M_WAITOK | M_ZERO);
413127098Srwatson	mtx_init(&tp->tap_mtx, "tap_mtx", NULL, MTX_DEF);
414127003Srwatson	mtx_lock(&tapmtx);
41583043Sbrooks	SLIST_INSERT_HEAD(&taphead, tp, tap_next);
416127003Srwatson	mtx_unlock(&tapmtx);
41763670Snsayer
418126796Sphk	unit = dev2unit(dev);
41983043Sbrooks
42063670Snsayer	/* select device: tap or vmnet */
421126796Sphk	if (unit & VMNET_DEV_MASK) {
42263670Snsayer		name = VMNET;
42363803Snsayer		tp->tap_flags |= TAP_VMNET;
42483043Sbrooks	} else
42563670Snsayer		name = TAP;
42663670Snsayer
427126796Sphk	unit &= TAPMAXUNIT;
428126796Sphk
429183397Sed	TAPDEBUG("tapcreate(%s%d). minor = %#x\n", name, unit, dev2unit(dev));
43083043Sbrooks
43163670Snsayer	/* generate fake MAC address: 00 bd xx xx xx unit_no */
43263670Snsayer	macaddr_hi = htons(0x00bd);
433178221Semax	macaddr_mid = (uint32_t) ticks;
434147256Sbrooks	bcopy(&macaddr_hi, eaddr, sizeof(short));
435178221Semax	bcopy(&macaddr_mid, &eaddr[2], sizeof(uint32_t));
436147256Sbrooks	eaddr[5] = (u_char)unit;
43763670Snsayer
438111742Sdes	/* fill the rest and attach interface */
439147256Sbrooks	ifp = tp->tap_ifp = if_alloc(IFT_ETHER);
440147256Sbrooks	if (ifp == NULL)
441147256Sbrooks		panic("%s%d: can not if_alloc()", name, unit);
44263670Snsayer	ifp->if_softc = tp;
443121816Sbrooks	if_initname(ifp, name, unit);
44463670Snsayer	ifp->if_init = tapifinit;
44563670Snsayer	ifp->if_start = tapifstart;
44663670Snsayer	ifp->if_ioctl = tapifioctl;
44763670Snsayer	ifp->if_mtu = ETHERMTU;
44863670Snsayer	ifp->if_flags = (IFF_BROADCAST|IFF_SIMPLEX|IFF_MULTICAST);
449213028Sjhb	IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
450205222Sqingli	ifp->if_capabilities |= IFCAP_LINKSTATE;
451205222Sqingli	ifp->if_capenable |= IFCAP_LINKSTATE;
45263670Snsayer
45383043Sbrooks	dev->si_drv1 = tp;
454126077Sphk	tp->tap_dev = dev;
45583043Sbrooks
456147256Sbrooks	ether_ifattach(ifp, eaddr);
45763670Snsayer
458127098Srwatson	mtx_lock(&tp->tap_mtx);
45963803Snsayer	tp->tap_flags |= TAP_INITED;
460127098Srwatson	mtx_unlock(&tp->tap_mtx);
46163803Snsayer
462213028Sjhb	knlist_init_mtx(&tp->tap_rsel.si_note, &tp->tap_mtx);
463158697Semax
464121816Sbrooks	TAPDEBUG("interface %s is created. minor = %#x\n",
465183397Sed		ifp->if_xname, dev2unit(dev));
46663670Snsayer} /* tapcreate */
46763670Snsayer
46863670Snsayer
46963670Snsayer/*
470111742Sdes * tapopen
47163670Snsayer *
47263670Snsayer * to open tunnel. must be superuser
47363670Snsayer */
47463670Snsayerstatic int
475156783Semaxtapopen(struct cdev *dev, int flag, int mode, struct thread *td)
47663670Snsayer{
47763670Snsayer	struct tap_softc	*tp = NULL;
478133460Semax	struct ifnet		*ifp = NULL;
479213028Sjhb	int			 error;
48063670Snsayer
481164033Srwatson	if (tapuopen == 0) {
482164033Srwatson		error = priv_check(td, PRIV_NET_TAP);
483164033Srwatson		if (error)
484164033Srwatson			return (error);
485164033Srwatson	}
48663670Snsayer
487126796Sphk	if ((dev2unit(dev) & CLONE_UNITMASK) > TAPMAXUNIT)
488126796Sphk		return (ENXIO);
48983043Sbrooks
49063670Snsayer	tp = dev->si_drv1;
49163670Snsayer
492127165Srwatson	mtx_lock(&tp->tap_mtx);
493127165Srwatson	if (tp->tap_flags & TAP_OPEN) {
494127165Srwatson		mtx_unlock(&tp->tap_mtx);
495127165Srwatson		return (EBUSY);
496127165Srwatson	}
49763670Snsayer
498152315Sru	bcopy(IF_LLADDR(tp->tap_ifp), tp->ether_addr, sizeof(tp->ether_addr));
49983366Sjulian	tp->tap_pid = td->td_proc->p_pid;
50063670Snsayer	tp->tap_flags |= TAP_OPEN;
501147256Sbrooks	ifp = tp->tap_ifp;
50263670Snsayer
503148887Srwatson	ifp->if_drv_flags |= IFF_DRV_RUNNING;
504148887Srwatson	ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
505167713Sbms	if (tapuponopen)
506167713Sbms		ifp->if_flags |= IFF_UP;
507205024Sqingli	if_link_state_change(ifp, LINK_STATE_UP);
508213028Sjhb	mtx_unlock(&tp->tap_mtx);
50963670Snsayer
510183397Sed	TAPDEBUG("%s is open. minor = %#x\n", ifp->if_xname, dev2unit(dev));
511133460Semax
51263670Snsayer	return (0);
51363670Snsayer} /* tapopen */
51463670Snsayer
51563670Snsayer
51663670Snsayer/*
51763670Snsayer * tapclose
51863670Snsayer *
51963670Snsayer * close the device - mark i/f down & delete routing info
52063670Snsayer */
52163670Snsayerstatic int
522156783Semaxtapclose(struct cdev *dev, int foo, int bar, struct thread *td)
52363670Snsayer{
524156783Semax	struct ifaddr		*ifa;
52563670Snsayer	struct tap_softc	*tp = dev->si_drv1;
526147256Sbrooks	struct ifnet		*ifp = tp->tap_ifp;
52763670Snsayer
52863670Snsayer	/* junk all pending output */
529213028Sjhb	mtx_lock(&tp->tap_mtx);
530236724Strociny	CURVNET_SET(ifp->if_vnet);
53183043Sbrooks	IF_DRAIN(&ifp->if_snd);
53263670Snsayer
53363803Snsayer	/*
53463803Snsayer	 * do not bring the interface down, and do not anything with
53563803Snsayer	 * interface, if we are in VMnet mode. just close the device.
53663803Snsayer	 */
53763803Snsayer
53863803Snsayer	if (((tp->tap_flags & TAP_VMNET) == 0) && (ifp->if_flags & IFF_UP)) {
539127098Srwatson		mtx_unlock(&tp->tap_mtx);
54063670Snsayer		if_down(ifp);
541213028Sjhb		mtx_lock(&tp->tap_mtx);
542148887Srwatson		if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
543213028Sjhb			ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
544213028Sjhb			mtx_unlock(&tp->tap_mtx);
54563803Snsayer			TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
546146620Speadar				rtinit(ifa, (int)RTM_DELETE, 0);
54763670Snsayer			}
548146620Speadar			if_purgeaddrs(ifp);
549213028Sjhb			mtx_lock(&tp->tap_mtx);
55063670Snsayer		}
551213028Sjhb	}
55263670Snsayer
553205024Sqingli	if_link_state_change(ifp, LINK_STATE_DOWN);
554236724Strociny	CURVNET_RESTORE();
555236724Strociny
55696122Salfred	funsetown(&tp->tap_sigio);
557122352Stanimura	selwakeuppri(&tp->tap_rsel, PZERO+1);
558213028Sjhb	KNOTE_LOCKED(&tp->tap_rsel.si_note, 0);
55963670Snsayer
56063670Snsayer	tp->tap_flags &= ~TAP_OPEN;
56163670Snsayer	tp->tap_pid = 0;
562127098Srwatson	mtx_unlock(&tp->tap_mtx);
56363670Snsayer
564121816Sbrooks	TAPDEBUG("%s is closed. minor = %#x\n",
565183397Sed		ifp->if_xname, dev2unit(dev));
56663670Snsayer
56763670Snsayer	return (0);
56863670Snsayer} /* tapclose */
56963670Snsayer
57063670Snsayer
57163670Snsayer/*
57263670Snsayer * tapifinit
57363670Snsayer *
57463670Snsayer * network interface initialization function
57563670Snsayer */
57663670Snsayerstatic void
577156783Semaxtapifinit(void *xtp)
57863670Snsayer{
57963670Snsayer	struct tap_softc	*tp = (struct tap_softc *)xtp;
580147256Sbrooks	struct ifnet		*ifp = tp->tap_ifp;
58163670Snsayer
582121816Sbrooks	TAPDEBUG("initializing %s\n", ifp->if_xname);
58363670Snsayer
584213028Sjhb	mtx_lock(&tp->tap_mtx);
585148887Srwatson	ifp->if_drv_flags |= IFF_DRV_RUNNING;
586148887Srwatson	ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
587213028Sjhb	mtx_unlock(&tp->tap_mtx);
58863670Snsayer
58963670Snsayer	/* attempt to start output */
59063670Snsayer	tapifstart(ifp);
59163670Snsayer} /* tapifinit */
59263670Snsayer
59363670Snsayer
59463670Snsayer/*
59563670Snsayer * tapifioctl
59663670Snsayer *
59763670Snsayer * Process an ioctl request on network interface
59863670Snsayer */
599105228Sphkstatic int
600156783Semaxtapifioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
60163670Snsayer{
602160376Sbrooks	struct tap_softc	*tp = ifp->if_softc;
603189866Sscf	struct ifreq		*ifr = (struct ifreq *)data;
60463670Snsayer	struct ifstat		*ifs = NULL;
605213028Sjhb	int			 dummy;
60663670Snsayer
60763670Snsayer	switch (cmd) {
60863670Snsayer		case SIOCSIFFLAGS: /* XXX -- just like vmnet does */
60963670Snsayer		case SIOCADDMULTI:
61063670Snsayer		case SIOCDELMULTI:
61183043Sbrooks			break;
61263670Snsayer
613189866Sscf		case SIOCSIFMTU:
614189866Sscf			ifp->if_mtu = ifr->ifr_mtu;
615189866Sscf			break;
616189866Sscf
61763670Snsayer		case SIOCGIFSTATUS:
61863670Snsayer			ifs = (struct ifstat *)data;
61963670Snsayer			dummy = strlen(ifs->ascii);
620127098Srwatson			mtx_lock(&tp->tap_mtx);
62163670Snsayer			if (tp->tap_pid != 0 && dummy < sizeof(ifs->ascii))
62263670Snsayer				snprintf(ifs->ascii + dummy,
62363670Snsayer					sizeof(ifs->ascii) - dummy,
62463670Snsayer					"\tOpened by PID %d\n", tp->tap_pid);
625127098Srwatson			mtx_unlock(&tp->tap_mtx);
62683043Sbrooks			break;
62763670Snsayer
62863670Snsayer		default:
629213028Sjhb			return (ether_ioctl(ifp, cmd, data));
630156783Semax			/* NOT REACHED */
63163670Snsayer	}
63263670Snsayer
63363670Snsayer	return (0);
63463670Snsayer} /* tapifioctl */
63563670Snsayer
63663670Snsayer
63763670Snsayer/*
638111742Sdes * tapifstart
639111742Sdes *
64063670Snsayer * queue packets from higher level ready to put out
64163670Snsayer */
64263670Snsayerstatic void
643156783Semaxtapifstart(struct ifnet *ifp)
64463670Snsayer{
64563670Snsayer	struct tap_softc	*tp = ifp->if_softc;
64663670Snsayer
647121816Sbrooks	TAPDEBUG("%s starting\n", ifp->if_xname);
64863670Snsayer
64963803Snsayer	/*
65063803Snsayer	 * do not junk pending output if we are in VMnet mode.
65163803Snsayer	 * XXX: can this do any harm because of queue overflow?
65263803Snsayer	 */
65363803Snsayer
654127098Srwatson	mtx_lock(&tp->tap_mtx);
655111742Sdes	if (((tp->tap_flags & TAP_VMNET) == 0) &&
65663803Snsayer	    ((tp->tap_flags & TAP_READY) != TAP_READY)) {
657213028Sjhb		struct mbuf *m;
65863670Snsayer
659127098Srwatson		/* Unlocked read. */
660121816Sbrooks		TAPDEBUG("%s not ready, tap_flags = 0x%x\n", ifp->if_xname,
661121816Sbrooks		    tp->tap_flags);
66263670Snsayer
663213028Sjhb		for (;;) {
66463670Snsayer			IF_DEQUEUE(&ifp->if_snd, m);
665213028Sjhb			if (m != NULL) {
66663670Snsayer				m_freem(m);
667213028Sjhb				ifp->if_oerrors++;
668213028Sjhb			} else
669213028Sjhb				break;
670213028Sjhb		}
671213028Sjhb		mtx_unlock(&tp->tap_mtx);
67263670Snsayer
67363670Snsayer		return;
67463670Snsayer	}
67563670Snsayer
676148887Srwatson	ifp->if_drv_flags |= IFF_DRV_OACTIVE;
67763670Snsayer
678213028Sjhb	if (!IFQ_IS_EMPTY(&ifp->if_snd)) {
67963670Snsayer		if (tp->tap_flags & TAP_RWAIT) {
68063670Snsayer			tp->tap_flags &= ~TAP_RWAIT;
681111748Sdes			wakeup(tp);
68263670Snsayer		}
68363670Snsayer
684127098Srwatson		if ((tp->tap_flags & TAP_ASYNC) && (tp->tap_sigio != NULL)) {
685127098Srwatson			mtx_unlock(&tp->tap_mtx);
68695883Salfred			pgsigio(&tp->tap_sigio, SIGIO, 0);
687213028Sjhb			mtx_lock(&tp->tap_mtx);
688213028Sjhb		}
68963670Snsayer
690122352Stanimura		selwakeuppri(&tp->tap_rsel, PZERO+1);
691213028Sjhb		KNOTE_LOCKED(&tp->tap_rsel.si_note, 0);
69263670Snsayer		ifp->if_opackets ++; /* obytes are counted in ether_output */
69363670Snsayer	}
69463670Snsayer
695148887Srwatson	ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
696213028Sjhb	mtx_unlock(&tp->tap_mtx);
69763670Snsayer} /* tapifstart */
69863670Snsayer
69963670Snsayer
70063670Snsayer/*
70163670Snsayer * tapioctl
70263670Snsayer *
70363670Snsayer * the cdevsw interface is now pretty minimal
70463670Snsayer */
70563670Snsayerstatic int
706156783Semaxtapioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td)
70763670Snsayer{
70863670Snsayer	struct tap_softc	*tp = dev->si_drv1;
709147256Sbrooks	struct ifnet		*ifp = tp->tap_ifp;
710111742Sdes	struct tapinfo		*tapp = NULL;
711102052Ssobomax	int			 f;
712162711Sru#if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5) || \
713162711Sru    defined(COMPAT_FREEBSD4)
714162711Sru	int			 ival;
715162711Sru#endif
71663670Snsayer
71763670Snsayer	switch (cmd) {
718111742Sdes		case TAPSIFINFO:
719111742Sdes			tapp = (struct tapinfo *)data;
720213028Sjhb			mtx_lock(&tp->tap_mtx);
721111742Sdes			ifp->if_mtu = tapp->mtu;
722111742Sdes			ifp->if_type = tapp->type;
723111742Sdes			ifp->if_baudrate = tapp->baudrate;
724213028Sjhb			mtx_unlock(&tp->tap_mtx);
725111742Sdes			break;
72663670Snsayer
727111742Sdes		case TAPGIFINFO:
728111742Sdes			tapp = (struct tapinfo *)data;
729213028Sjhb			mtx_lock(&tp->tap_mtx);
730111742Sdes			tapp->mtu = ifp->if_mtu;
731111742Sdes			tapp->type = ifp->if_type;
732111742Sdes			tapp->baudrate = ifp->if_baudrate;
733213028Sjhb			mtx_unlock(&tp->tap_mtx);
734111742Sdes			break;
73563670Snsayer
73663670Snsayer		case TAPSDEBUG:
737159079Smarius			tapdebug = *(int *)data;
73883043Sbrooks			break;
73963670Snsayer
74063670Snsayer		case TAPGDEBUG:
741159079Smarius			*(int *)data = tapdebug;
74283043Sbrooks			break;
74363670Snsayer
744182880Semax		case TAPGIFNAME: {
745182880Semax			struct ifreq	*ifr = (struct ifreq *) data;
746182880Semax
747182880Semax			strlcpy(ifr->ifr_name, ifp->if_xname, IFNAMSIZ);
748182880Semax			} break;
749182880Semax
75063670Snsayer		case FIONBIO:
75183043Sbrooks			break;
75263670Snsayer
75363670Snsayer		case FIOASYNC:
754127098Srwatson			mtx_lock(&tp->tap_mtx);
755159079Smarius			if (*(int *)data)
75663670Snsayer				tp->tap_flags |= TAP_ASYNC;
75763670Snsayer			else
75863670Snsayer				tp->tap_flags &= ~TAP_ASYNC;
759127098Srwatson			mtx_unlock(&tp->tap_mtx);
76083043Sbrooks			break;
76163670Snsayer
76263670Snsayer		case FIONREAD:
763213028Sjhb			if (!IFQ_IS_EMPTY(&ifp->if_snd)) {
764213028Sjhb				struct mbuf *mb;
76563670Snsayer
766213028Sjhb				IFQ_LOCK(&ifp->if_snd);
767213028Sjhb				IFQ_POLL_NOLOCK(&ifp->if_snd, mb);
768213028Sjhb				for (*(int *)data = 0; mb != NULL;
769213028Sjhb				     mb = mb->m_next)
770159079Smarius					*(int *)data += mb->m_len;
771213028Sjhb				IFQ_UNLOCK(&ifp->if_snd);
77283043Sbrooks			} else
773159079Smarius				*(int *)data = 0;
77483043Sbrooks			break;
77563670Snsayer
77663670Snsayer		case FIOSETOWN:
777159079Smarius			return (fsetown(*(int *)data, &tp->tap_sigio));
77863670Snsayer
77963670Snsayer		case FIOGETOWN:
780159079Smarius			*(int *)data = fgetown(&tp->tap_sigio);
78163670Snsayer			return (0);
78263670Snsayer
78363670Snsayer		/* this is deprecated, FIOSETOWN should be used instead */
78463670Snsayer		case TIOCSPGRP:
785159079Smarius			return (fsetown(-(*(int *)data), &tp->tap_sigio));
78663670Snsayer
78763670Snsayer		/* this is deprecated, FIOGETOWN should be used instead */
78863670Snsayer		case TIOCGPGRP:
789159079Smarius			*(int *)data = -fgetown(&tp->tap_sigio);
79063670Snsayer			return (0);
79163670Snsayer
79263670Snsayer		/* VMware/VMnet port ioctl's */
79363670Snsayer
794162711Sru#if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5) || \
795162711Sru    defined(COMPAT_FREEBSD4)
796162711Sru		case _IO('V', 0):
797162711Sru			ival = IOCPARM_IVAL(data);
798162711Sru			data = (caddr_t)&ival;
799162711Sru			/* FALLTHROUGH */
800162711Sru#endif
80183043Sbrooks		case VMIO_SIOCSIFFLAGS: /* VMware/VMnet SIOCSIFFLAGS */
802162711Sru			f = *(int *)data;
80363670Snsayer			f &= 0x0fff;
80463670Snsayer			f &= ~IFF_CANTCHANGE;
80563670Snsayer			f |= IFF_UP;
80663670Snsayer
807213028Sjhb			mtx_lock(&tp->tap_mtx);
80863670Snsayer			ifp->if_flags = f | (ifp->if_flags & IFF_CANTCHANGE);
809213028Sjhb			mtx_unlock(&tp->tap_mtx);
81083043Sbrooks			break;
81163670Snsayer
81263861Snsayer		case OSIOCGIFADDR:	/* get MAC address of the remote side */
81363670Snsayer		case SIOCGIFADDR:
814127165Srwatson			mtx_lock(&tp->tap_mtx);
81563861Snsayer			bcopy(tp->ether_addr, data, sizeof(tp->ether_addr));
816127165Srwatson			mtx_unlock(&tp->tap_mtx);
81783043Sbrooks			break;
81863670Snsayer
81963861Snsayer		case SIOCSIFADDR:	/* set MAC address of the remote side */
820127165Srwatson			mtx_lock(&tp->tap_mtx);
82163861Snsayer			bcopy(data, tp->ether_addr, sizeof(tp->ether_addr));
822127165Srwatson			mtx_unlock(&tp->tap_mtx);
82383043Sbrooks			break;
82463670Snsayer
82563670Snsayer		default:
82663670Snsayer			return (ENOTTY);
82763670Snsayer	}
82863670Snsayer	return (0);
82963670Snsayer} /* tapioctl */
83063670Snsayer
83163670Snsayer
83263670Snsayer/*
83363670Snsayer * tapread
83463670Snsayer *
83563670Snsayer * the cdevsw read interface - reads a packet at a time, or at
83663670Snsayer * least as much of a packet as can be read
83763670Snsayer */
83863670Snsayerstatic int
839156783Semaxtapread(struct cdev *dev, struct uio *uio, int flag)
84063670Snsayer{
84163670Snsayer	struct tap_softc	*tp = dev->si_drv1;
842147256Sbrooks	struct ifnet		*ifp = tp->tap_ifp;
84390227Sdillon	struct mbuf		*m = NULL;
844213028Sjhb	int			 error = 0, len;
84563670Snsayer
846183397Sed	TAPDEBUG("%s reading, minor = %#x\n", ifp->if_xname, dev2unit(dev));
84763670Snsayer
848127098Srwatson	mtx_lock(&tp->tap_mtx);
84963670Snsayer	if ((tp->tap_flags & TAP_READY) != TAP_READY) {
850127098Srwatson		mtx_unlock(&tp->tap_mtx);
851127098Srwatson
852127098Srwatson		/* Unlocked read. */
853121816Sbrooks		TAPDEBUG("%s not ready. minor = %#x, tap_flags = 0x%x\n",
854183397Sed			ifp->if_xname, dev2unit(dev), tp->tap_flags);
85563803Snsayer
85663670Snsayer		return (EHOSTDOWN);
85763670Snsayer	}
85863670Snsayer
85963670Snsayer	tp->tap_flags &= ~TAP_RWAIT;
86063670Snsayer
86163670Snsayer	/* sleep until we get a packet */
86263670Snsayer	do {
86390227Sdillon		IF_DEQUEUE(&ifp->if_snd, m);
86463670Snsayer
86590227Sdillon		if (m == NULL) {
866213028Sjhb			if (flag & O_NONBLOCK) {
867213028Sjhb				mtx_unlock(&tp->tap_mtx);
86863670Snsayer				return (EWOULDBLOCK);
869213028Sjhb			}
870111742Sdes
87163670Snsayer			tp->tap_flags |= TAP_RWAIT;
872213028Sjhb			error = mtx_sleep(tp, &tp->tap_mtx, PCATCH | (PZERO + 1),
873213028Sjhb			    "taprd", 0);
874213028Sjhb			if (error) {
875213028Sjhb				mtx_unlock(&tp->tap_mtx);
87663670Snsayer				return (error);
877213028Sjhb			}
87863670Snsayer		}
87990227Sdillon	} while (m == NULL);
880213028Sjhb	mtx_unlock(&tp->tap_mtx);
88163670Snsayer
88263670Snsayer	/* feed packet to bpf */
883106939Ssam	BPF_MTAP(ifp, m);
88463670Snsayer
88563670Snsayer	/* xfer packet to user space */
88690227Sdillon	while ((m != NULL) && (uio->uio_resid > 0) && (error == 0)) {
88790227Sdillon		len = min(uio->uio_resid, m->m_len);
88863670Snsayer		if (len == 0)
88963670Snsayer			break;
89063670Snsayer
891111741Sdes		error = uiomove(mtod(m, void *), len, uio);
89290227Sdillon		m = m_free(m);
89363670Snsayer	}
89463670Snsayer
89590227Sdillon	if (m != NULL) {
896121816Sbrooks		TAPDEBUG("%s dropping mbuf, minor = %#x\n", ifp->if_xname,
897183397Sed			dev2unit(dev));
89890227Sdillon		m_freem(m);
89963670Snsayer	}
90063670Snsayer
90163670Snsayer	return (error);
90263670Snsayer} /* tapread */
90363670Snsayer
90463670Snsayer
90563670Snsayer/*
90663670Snsayer * tapwrite
90763670Snsayer *
90863670Snsayer * the cdevsw write interface - an atomic write is a packet - or else!
90963670Snsayer */
91063670Snsayerstatic int
911156783Semaxtapwrite(struct cdev *dev, struct uio *uio, int flag)
91263670Snsayer{
913166443Sbms	struct ether_header	*eh;
91463670Snsayer	struct tap_softc	*tp = dev->si_drv1;
915147256Sbrooks	struct ifnet		*ifp = tp->tap_ifp;
916137101Sglebius	struct mbuf		*m;
91763670Snsayer
918121816Sbrooks	TAPDEBUG("%s writting, minor = %#x\n",
919183397Sed		ifp->if_xname, dev2unit(dev));
92063670Snsayer
92163670Snsayer	if (uio->uio_resid == 0)
92263670Snsayer		return (0);
92363670Snsayer
92463670Snsayer	if ((uio->uio_resid < 0) || (uio->uio_resid > TAPMRU)) {
925194990Skib		TAPDEBUG("%s invalid packet len = %zd, minor = %#x\n",
926183397Sed			ifp->if_xname, uio->uio_resid, dev2unit(dev));
92763803Snsayer
92863670Snsayer		return (EIO);
92963670Snsayer	}
93063670Snsayer
931163915Sandre	if ((m = m_uiotombuf(uio, M_DONTWAIT, 0, ETHER_ALIGN,
932163915Sandre	    M_PKTHDR)) == NULL) {
93363670Snsayer		ifp->if_ierrors ++;
934163986Scsjp		return (ENOBUFS);
93563670Snsayer	}
93663670Snsayer
937137101Sglebius	m->m_pkthdr.rcvif = ifp;
938111742Sdes
939166443Sbms	/*
940166443Sbms	 * Only pass a unicast frame to ether_input(), if it would actually
941166443Sbms	 * have been received by non-virtual hardware.
942166443Sbms	 */
943166443Sbms	if (m->m_len < sizeof(struct ether_header)) {
944166443Sbms		m_freem(m);
945166443Sbms		return (0);
946166443Sbms	}
947166443Sbms	eh = mtod(m, struct ether_header *);
948166443Sbms
949166443Sbms	if (eh && (ifp->if_flags & IFF_PROMISC) == 0 &&
950166443Sbms	    !ETHER_IS_MULTICAST(eh->ether_dhost) &&
951166443Sbms	    bcmp(eh->ether_dhost, IF_LLADDR(ifp), ETHER_ADDR_LEN) != 0) {
952166443Sbms		m_freem(m);
953166443Sbms		return (0);
954166443Sbms	}
955166443Sbms
956106939Ssam	/* Pass packet up to parent. */
957236724Strociny	CURVNET_SET(ifp->if_vnet);
958137101Sglebius	(*ifp->if_input)(ifp, m);
959236724Strociny	CURVNET_RESTORE();
960106939Ssam	ifp->if_ipackets ++; /* ibytes are counted in parent */
96163670Snsayer
96263670Snsayer	return (0);
96363670Snsayer} /* tapwrite */
96463670Snsayer
96563670Snsayer
96663670Snsayer/*
96763670Snsayer * tappoll
96863670Snsayer *
96963670Snsayer * the poll interface, this is only useful on reads
97063670Snsayer * really. the write detect always returns true, write never blocks
97163670Snsayer * anyway, it either accepts the packet or drops it
97263670Snsayer */
97363670Snsayerstatic int
974156783Semaxtappoll(struct cdev *dev, int events, struct thread *td)
97563670Snsayer{
97663670Snsayer	struct tap_softc	*tp = dev->si_drv1;
977147256Sbrooks	struct ifnet		*ifp = tp->tap_ifp;
978213028Sjhb	int			 revents = 0;
97963670Snsayer
980121816Sbrooks	TAPDEBUG("%s polling, minor = %#x\n",
981183397Sed		ifp->if_xname, dev2unit(dev));
98263670Snsayer
98363670Snsayer	if (events & (POLLIN | POLLRDNORM)) {
984213028Sjhb		IFQ_LOCK(&ifp->if_snd);
985213028Sjhb		if (!IFQ_IS_EMPTY(&ifp->if_snd)) {
986121816Sbrooks			TAPDEBUG("%s have data in queue. len = %d, " \
987121816Sbrooks				"minor = %#x\n", ifp->if_xname,
988183397Sed				ifp->if_snd.ifq_len, dev2unit(dev));
98963803Snsayer
99063670Snsayer			revents |= (events & (POLLIN | POLLRDNORM));
99183043Sbrooks		} else {
992121816Sbrooks			TAPDEBUG("%s waiting for data, minor = %#x\n",
993183397Sed				ifp->if_xname, dev2unit(dev));
99463803Snsayer
99583805Sjhb			selrecord(td, &tp->tap_rsel);
99663670Snsayer		}
997213028Sjhb		IFQ_UNLOCK(&ifp->if_snd);
99863670Snsayer	}
99963670Snsayer
100063670Snsayer	if (events & (POLLOUT | POLLWRNORM))
100163670Snsayer		revents |= (events & (POLLOUT | POLLWRNORM));
100263670Snsayer
100363670Snsayer	return (revents);
100463670Snsayer} /* tappoll */
1005156783Semax
1006156783Semax
1007156783Semax/*
1008156783Semax * tap_kqfilter
1009156783Semax *
1010156783Semax * support for kevent() system call
1011156783Semax */
1012156783Semaxstatic int
1013156783Semaxtapkqfilter(struct cdev *dev, struct knote *kn)
1014156783Semax{
1015156783Semax	struct tap_softc	*tp = dev->si_drv1;
1016156783Semax	struct ifnet		*ifp = tp->tap_ifp;
1017156783Semax
1018156783Semax	switch (kn->kn_filter) {
1019156783Semax	case EVFILT_READ:
1020156783Semax		TAPDEBUG("%s kqfilter: EVFILT_READ, minor = %#x\n",
1021183397Sed			ifp->if_xname, dev2unit(dev));
1022156783Semax		kn->kn_fop = &tap_read_filterops;
1023156783Semax		break;
1024156783Semax
1025156783Semax	case EVFILT_WRITE:
1026156783Semax		TAPDEBUG("%s kqfilter: EVFILT_WRITE, minor = %#x\n",
1027183397Sed			ifp->if_xname, dev2unit(dev));
1028156783Semax		kn->kn_fop = &tap_write_filterops;
1029156783Semax		break;
1030156783Semax
1031156783Semax	default:
1032156783Semax		TAPDEBUG("%s kqfilter: invalid filter, minor = %#x\n",
1033183397Sed			ifp->if_xname, dev2unit(dev));
1034156783Semax		return (EINVAL);
1035156783Semax		/* NOT REACHED */
1036156783Semax	}
1037156783Semax
1038213028Sjhb	kn->kn_hook = tp;
1039156783Semax	knlist_add(&tp->tap_rsel.si_note, kn, 0);
1040156783Semax
1041156783Semax	return (0);
1042156783Semax} /* tapkqfilter */
1043156783Semax
1044156783Semax
1045156783Semax/*
1046156783Semax * tap_kqread
1047156783Semax *
1048156783Semax * Return true if there is data in the interface queue
1049156783Semax */
1050156783Semaxstatic int
1051156783Semaxtapkqread(struct knote *kn, long hint)
1052156783Semax{
1053213028Sjhb	int			 ret;
1054213028Sjhb	struct tap_softc	*tp = kn->kn_hook;
1055213028Sjhb	struct cdev		*dev = tp->tap_dev;
1056156783Semax	struct ifnet		*ifp = tp->tap_ifp;
1057156783Semax
1058156783Semax	if ((kn->kn_data = ifp->if_snd.ifq_len) > 0) {
1059156783Semax		TAPDEBUG("%s have data in queue. len = %d, minor = %#x\n",
1060183397Sed			ifp->if_xname, ifp->if_snd.ifq_len, dev2unit(dev));
1061156783Semax		ret = 1;
1062156783Semax	} else {
1063156783Semax		TAPDEBUG("%s waiting for data, minor = %#x\n",
1064183397Sed			ifp->if_xname, dev2unit(dev));
1065156783Semax		ret = 0;
1066156783Semax	}
1067156783Semax
1068156783Semax	return (ret);
1069156783Semax} /* tapkqread */
1070156783Semax
1071156783Semax
1072156783Semax/*
1073156783Semax * tap_kqwrite
1074156783Semax *
1075156783Semax * Always can write. Return the MTU in kn->data
1076156783Semax */
1077156783Semaxstatic int
1078156783Semaxtapkqwrite(struct knote *kn, long hint)
1079156783Semax{
1080213028Sjhb	struct tap_softc	*tp = kn->kn_hook;
1081156783Semax	struct ifnet		*ifp = tp->tap_ifp;
1082156783Semax
1083156783Semax	kn->kn_data = ifp->if_mtu;
1084156783Semax
1085156783Semax	return (1);
1086156783Semax} /* tapkqwrite */
1087156783Semax
1088156783Semax
1089156783Semaxstatic void
1090156783Semaxtapkqdetach(struct knote *kn)
1091156783Semax{
1092213028Sjhb	struct tap_softc	*tp = kn->kn_hook;
1093156783Semax
1094156783Semax	knlist_remove(&tp->tap_rsel.si_note, kn, 0);
1095156783Semax} /* tapkqdetach */
1096156783Semax
1097