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: stable/11/sys/net/if_tap.c 348126 2019-05-22 22:56:05Z kevans $
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>
43347378Skevans#include <sys/lock.h>
44139207Sphk#include <sys/fcntl.h>
4563670Snsayer#include <sys/filio.h>
46236724Strociny#include <sys/jail.h>
4763670Snsayer#include <sys/kernel.h>
4863670Snsayer#include <sys/malloc.h>
4963670Snsayer#include <sys/mbuf.h>
50129880Sphk#include <sys/module.h>
5163670Snsayer#include <sys/poll.h>
52164033Srwatson#include <sys/priv.h>
5363670Snsayer#include <sys/proc.h>
54139207Sphk#include <sys/selinfo.h>
5563670Snsayer#include <sys/signalvar.h>
5663670Snsayer#include <sys/socket.h>
5763670Snsayer#include <sys/sockio.h>
58347378Skevans#include <sys/sx.h>
5963670Snsayer#include <sys/sysctl.h>
6063670Snsayer#include <sys/systm.h>
6163670Snsayer#include <sys/ttycom.h>
6263670Snsayer#include <sys/uio.h>
6383043Sbrooks#include <sys/queue.h>
6463670Snsayer
6563670Snsayer#include <net/bpf.h>
6663670Snsayer#include <net/ethernet.h>
6763670Snsayer#include <net/if.h>
68257176Sglebius#include <net/if_var.h>
69166497Sbms#include <net/if_clone.h>
70152315Sru#include <net/if_dl.h>
71238183Semaste#include <net/if_media.h>
72236725Strociny#include <net/if_types.h>
7363670Snsayer#include <net/route.h>
74236724Strociny#include <net/vnet.h>
7563670Snsayer
7663670Snsayer#include <netinet/in.h>
7763670Snsayer
7863670Snsayer#include <net/if_tapvar.h>
7963670Snsayer#include <net/if_tap.h>
8063670Snsayer
8163670Snsayer
8263670Snsayer#define CDEV_NAME	"tap"
8363670Snsayer#define TAPDEBUG	if (tapdebug) printf
8463670Snsayer
85241610Sglebiusstatic const char tapname[] = "tap";
86241610Sglebiusstatic const char vmnetname[] = "vmnet";
8783043Sbrooks#define TAPMAXUNIT	0x7fff
88126077Sphk#define VMNET_DEV_MASK	CLONE_FLAG0
8963670Snsayer
9063670Snsayer/* module */
91111742Sdesstatic int		tapmodevent(module_t, int, void *);
9263670Snsayer
9363670Snsayer/* device */
94148868Srwatsonstatic void		tapclone(void *, struct ucred *, char *, int,
95148868Srwatson			    struct cdev **);
96130585Sphkstatic void		tapcreate(struct cdev *);
9763670Snsayer
9863670Snsayer/* network interface */
9993084Sbdestatic void		tapifstart(struct ifnet *);
10093084Sbdestatic int		tapifioctl(struct ifnet *, u_long, caddr_t);
10193084Sbdestatic void		tapifinit(void *);
10263670Snsayer
103166497Sbmsstatic int		tap_clone_create(struct if_clone *, int, caddr_t);
104166497Sbmsstatic void		tap_clone_destroy(struct ifnet *);
105241610Sglebiusstatic struct if_clone *tap_cloner;
106166497Sbmsstatic int		vmnet_clone_create(struct if_clone *, int, caddr_t);
107166497Sbmsstatic void		vmnet_clone_destroy(struct ifnet *);
108241610Sglebiusstatic struct if_clone *vmnet_cloner;
109166497Sbms
11063670Snsayer/* character device */
11163670Snsayerstatic d_open_t		tapopen;
11263670Snsayerstatic d_close_t	tapclose;
11363670Snsayerstatic d_read_t		tapread;
11463670Snsayerstatic d_write_t	tapwrite;
11563670Snsayerstatic d_ioctl_t	tapioctl;
11663670Snsayerstatic d_poll_t		tappoll;
117156783Semaxstatic d_kqfilter_t	tapkqfilter;
11863670Snsayer
119156783Semax/* kqueue(2) */
120156783Semaxstatic int		tapkqread(struct knote *, long);
121156783Semaxstatic int		tapkqwrite(struct knote *, long);
122156783Semaxstatic void		tapkqdetach(struct knote *);
123156783Semax
124156783Semaxstatic struct filterops	tap_read_filterops = {
125156783Semax	.f_isfd =	1,
126156783Semax	.f_attach =	NULL,
127156783Semax	.f_detach =	tapkqdetach,
128156783Semax	.f_event =	tapkqread,
129156783Semax};
130156783Semax
131156783Semaxstatic struct filterops	tap_write_filterops = {
132156783Semax	.f_isfd =	1,
133156783Semax	.f_attach =	NULL,
134156783Semax	.f_detach =	tapkqdetach,
135156783Semax	.f_event =	tapkqwrite,
136156783Semax};
137156783Semax
13863670Snsayerstatic struct cdevsw	tap_cdevsw = {
139126080Sphk	.d_version =	D_VERSION,
140226500Sed	.d_flags =	D_NEEDMINOR,
141111815Sphk	.d_open =	tapopen,
142111815Sphk	.d_close =	tapclose,
143111815Sphk	.d_read =	tapread,
144111815Sphk	.d_write =	tapwrite,
145111815Sphk	.d_ioctl =	tapioctl,
146111815Sphk	.d_poll =	tappoll,
147111815Sphk	.d_name =	CDEV_NAME,
148156783Semax	.d_kqfilter =	tapkqfilter,
14963670Snsayer};
15063670Snsayer
151127003Srwatson/*
152127003Srwatson * All global variables in if_tap.c are locked with tapmtx, with the
153127003Srwatson * exception of tapdebug, which is accessed unlocked; tapclones is
154127003Srwatson * static at runtime.
155127003Srwatson */
156127003Srwatsonstatic struct mtx		tapmtx;
15783043Sbrooksstatic int			tapdebug = 0;        /* debug flag   */
158167713Sbmsstatic int			tapuopen = 0;        /* allow user open() */
159167713Sbmsstatic int			tapuponopen = 0;    /* IFF_UP on open() */
160166497Sbmsstatic int			tapdclone = 1;	/* enable devfs cloning */
16183043Sbrooksstatic SLIST_HEAD(, tap_softc)	taphead;             /* first device */
162126077Sphkstatic struct clonedevs 	*tapclones;
16363670Snsayer
16463670SnsayerMALLOC_DECLARE(M_TAP);
16563670SnsayerMALLOC_DEFINE(M_TAP, CDEV_NAME, "Ethernet tunnel interface");
16663670SnsayerSYSCTL_INT(_debug, OID_AUTO, if_tap_debug, CTLFLAG_RW, &tapdebug, 0, "");
167144979Smdodd
168347378Skevansstatic struct sx tap_ioctl_sx;
169347378SkevansSX_SYSINIT(tap_ioctl_sx, &tap_ioctl_sx, "tap_ioctl");
170347378Skevans
171144979SmdoddSYSCTL_DECL(_net_link);
172227309Sedstatic SYSCTL_NODE(_net_link, OID_AUTO, tap, CTLFLAG_RW, 0,
173144979Smdodd    "Ethernet tunnel software network interface");
174144979SmdoddSYSCTL_INT(_net_link_tap, OID_AUTO, user_open, CTLFLAG_RW, &tapuopen, 0,
175144979Smdodd	"Allow user to open /dev/tap (based on node permissions)");
176167713SbmsSYSCTL_INT(_net_link_tap, OID_AUTO, up_on_open, CTLFLAG_RW, &tapuponopen, 0,
177167713Sbms	"Bring interface up when /dev/tap is opened");
178267992ShselaskySYSCTL_INT(_net_link_tap, OID_AUTO, devfs_cloning, CTLFLAG_RWTUN, &tapdclone, 0,
179289718Semaste	"Enable legacy devfs interface creation");
180144979SmdoddSYSCTL_INT(_net_link_tap, OID_AUTO, debug, CTLFLAG_RW, &tapdebug, 0, "");
181144979Smdodd
18263670SnsayerDEV_MODULE(if_tap, tapmodevent, NULL);
183346803SkevansMODULE_VERSION(if_tap, 1);
18463670Snsayer
185166497Sbmsstatic int
186166497Sbmstap_clone_create(struct if_clone *ifc, int unit, caddr_t params)
187166497Sbms{
188166497Sbms	struct cdev *dev;
189166497Sbms	int i;
190166497Sbms
191241610Sglebius	/* Find any existing device, or allocate new unit number. */
192241610Sglebius	i = clone_create(&tapclones, &tap_cdevsw, &unit, &dev, 0);
193166497Sbms	if (i) {
194243615Sdavidxu		dev = make_dev(&tap_cdevsw, unit, UID_ROOT, GID_WHEEL, 0600,
195241610Sglebius		    "%s%d", tapname, unit);
196166497Sbms	}
197166497Sbms
198166497Sbms	tapcreate(dev);
199166497Sbms	return (0);
200166497Sbms}
201166497Sbms
202166497Sbms/* vmnet devices are tap devices in disguise */
203166497Sbmsstatic int
204166497Sbmsvmnet_clone_create(struct if_clone *ifc, int unit, caddr_t params)
205166497Sbms{
206241610Sglebius	struct cdev *dev;
207241610Sglebius	int i;
208241610Sglebius
209241610Sglebius	/* Find any existing device, or allocate new unit number. */
210241610Sglebius	i = clone_create(&tapclones, &tap_cdevsw, &unit, &dev, VMNET_DEV_MASK);
211241610Sglebius	if (i) {
212241610Sglebius		dev = make_dev(&tap_cdevsw, unit | VMNET_DEV_MASK, UID_ROOT,
213257078Sgrehan		    GID_WHEEL, 0600, "%s%d", vmnetname, unit);
214241610Sglebius	}
215241610Sglebius
216241610Sglebius	tapcreate(dev);
217241610Sglebius	return (0);
218166497Sbms}
219166497Sbms
220166497Sbmsstatic void
221166497Sbmstap_destroy(struct tap_softc *tp)
222166497Sbms{
223166497Sbms	struct ifnet *ifp = tp->tap_ifp;
224166497Sbms
225236724Strociny	CURVNET_SET(ifp->if_vnet);
226347378Skevans
227240938Semaste	destroy_dev(tp->tap_dev);
228225177Sattilio	seldrain(&tp->tap_rsel);
229256008Sglebius	knlist_clear(&tp->tap_rsel.si_note, 0);
230166497Sbms	knlist_destroy(&tp->tap_rsel.si_note);
231166497Sbms	ether_ifdetach(ifp);
232348126Skevans
233348126Skevans	sx_xlock(&tap_ioctl_sx);
234348126Skevans	ifp->if_softc = NULL;
235348126Skevans	sx_xunlock(&tap_ioctl_sx);
236348126Skevans
237227459Sbrooks	if_free(ifp);
238166497Sbms
239166497Sbms	mtx_destroy(&tp->tap_mtx);
240166497Sbms	free(tp, M_TAP);
241236724Strociny	CURVNET_RESTORE();
242166497Sbms}
243166497Sbms
244166497Sbmsstatic void
245166497Sbmstap_clone_destroy(struct ifnet *ifp)
246166497Sbms{
247166497Sbms	struct tap_softc *tp = ifp->if_softc;
248166497Sbms
249166497Sbms	mtx_lock(&tapmtx);
250166497Sbms	SLIST_REMOVE(&taphead, tp, tap_softc, tap_next);
251166497Sbms	mtx_unlock(&tapmtx);
252166497Sbms	tap_destroy(tp);
253166497Sbms}
254166497Sbms
255166497Sbms/* vmnet devices are tap devices in disguise */
256166497Sbmsstatic void
257166497Sbmsvmnet_clone_destroy(struct ifnet *ifp)
258166497Sbms{
259166497Sbms	tap_clone_destroy(ifp);
260166497Sbms}
261166497Sbms
26263670Snsayer/*
26363670Snsayer * tapmodevent
26463670Snsayer *
26563670Snsayer * module event handler
26663670Snsayer */
26763670Snsayerstatic int
268156783Semaxtapmodevent(module_t mod, int type, void *data)
26963670Snsayer{
27083043Sbrooks	static eventhandler_tag	 eh_tag = NULL;
27183043Sbrooks	struct tap_softc	*tp = NULL;
27283043Sbrooks	struct ifnet		*ifp = NULL;
27363670Snsayer
27463670Snsayer	switch (type) {
27563670Snsayer	case MOD_LOAD:
27663670Snsayer
27783043Sbrooks		/* intitialize device */
27883043Sbrooks
279127003Srwatson		mtx_init(&tapmtx, "tapmtx", NULL, MTX_DEF);
28083043Sbrooks		SLIST_INIT(&taphead);
28183043Sbrooks
282126845Sphk		clone_setup(&tapclones);
28371602Sphk		eh_tag = EVENTHANDLER_REGISTER(dev_clone, tapclone, 0, 1000);
284127003Srwatson		if (eh_tag == NULL) {
285127170Srwatson			clone_cleanup(&tapclones);
286127003Srwatson			mtx_destroy(&tapmtx);
287126077Sphk			return (ENOMEM);
288127003Srwatson		}
289241610Sglebius		tap_cloner = if_clone_simple(tapname, tap_clone_create,
290241610Sglebius		    tap_clone_destroy, 0);
291241610Sglebius		vmnet_cloner = if_clone_simple(vmnetname, vmnet_clone_create,
292241610Sglebius		    vmnet_clone_destroy, 0);
29383043Sbrooks		return (0);
29463670Snsayer
29583043Sbrooks	case MOD_UNLOAD:
296127003Srwatson		/*
297127003Srwatson		 * The EBUSY algorithm here can't quite atomically
298127003Srwatson		 * guarantee that this is race-free since we have to
299127003Srwatson		 * release the tap mtx to deregister the clone handler.
300127003Srwatson		 */
301127003Srwatson		mtx_lock(&tapmtx);
302127003Srwatson		SLIST_FOREACH(tp, &taphead, tap_next) {
303127098Srwatson			mtx_lock(&tp->tap_mtx);
304127003Srwatson			if (tp->tap_flags & TAP_OPEN) {
305127098Srwatson				mtx_unlock(&tp->tap_mtx);
306127003Srwatson				mtx_unlock(&tapmtx);
30783043Sbrooks				return (EBUSY);
308127003Srwatson			}
309127098Srwatson			mtx_unlock(&tp->tap_mtx);
310127003Srwatson		}
311127003Srwatson		mtx_unlock(&tapmtx);
31283043Sbrooks
31371602Sphk		EVENTHANDLER_DEREGISTER(dev_clone, eh_tag);
314241610Sglebius		if_clone_detach(tap_cloner);
315241610Sglebius		if_clone_detach(vmnet_cloner);
316204464Skib		drain_dev_clone_events();
31763670Snsayer
318127003Srwatson		mtx_lock(&tapmtx);
31983043Sbrooks		while ((tp = SLIST_FIRST(&taphead)) != NULL) {
32083043Sbrooks			SLIST_REMOVE_HEAD(&taphead, tap_next);
321127003Srwatson			mtx_unlock(&tapmtx);
32283043Sbrooks
323147256Sbrooks			ifp = tp->tap_ifp;
32483043Sbrooks
325121816Sbrooks			TAPDEBUG("detaching %s\n", ifp->if_xname);
32683043Sbrooks
327166497Sbms			tap_destroy(tp);
328127003Srwatson			mtx_lock(&tapmtx);
32983043Sbrooks		}
330127003Srwatson		mtx_unlock(&tapmtx);
331126077Sphk		clone_cleanup(&tapclones);
33263670Snsayer
333135354Srwatson		mtx_destroy(&tapmtx);
334135354Srwatson
33583043Sbrooks		break;
33663670Snsayer
33763670Snsayer	default:
33863670Snsayer		return (EOPNOTSUPP);
33963670Snsayer	}
34063670Snsayer
34163670Snsayer	return (0);
34263670Snsayer} /* tapmodevent */
34363670Snsayer
34463670Snsayer
34563670Snsayer/*
34671602Sphk * DEVFS handler
34771602Sphk *
34871602Sphk * We need to support two kind of devices - tap and vmnet
34971602Sphk */
35071602Sphkstatic void
351156783Semaxtapclone(void *arg, struct ucred *cred, char *name, int namelen, struct cdev **dev)
35271602Sphk{
353166497Sbms	char		devname[SPECNAMELEN + 1];
354166497Sbms	int		i, unit, append_unit;
355166438Sbms	int		extra;
35671602Sphk
357130640Sphk	if (*dev != NULL)
35871602Sphk		return;
35971602Sphk
360166514Sbms	if (!tapdclone ||
361166514Sbms	    (!tapuopen && priv_check_cred(cred, PRIV_NET_IFCREATE, 0) != 0))
362166497Sbms		return;
363166497Sbms
364166497Sbms	unit = 0;
365166497Sbms	append_unit = 0;
366126077Sphk	extra = 0;
367166497Sbms
368166497Sbms	/* We're interested in only tap/vmnet devices. */
369241610Sglebius	if (strcmp(name, tapname) == 0) {
370126077Sphk		unit = -1;
371241610Sglebius	} else if (strcmp(name, vmnetname) == 0) {
372126077Sphk		unit = -1;
373126077Sphk		extra = VMNET_DEV_MASK;
374241610Sglebius	} else if (dev_stdclone(name, NULL, tapname, &unit) != 1) {
375241610Sglebius		if (dev_stdclone(name, NULL, vmnetname, &unit) != 1) {
376126077Sphk			return;
377166497Sbms		} else {
378166497Sbms			extra = VMNET_DEV_MASK;
379166497Sbms		}
38083043Sbrooks	}
38171602Sphk
382166497Sbms	if (unit == -1)
383166497Sbms		append_unit = 1;
384166497Sbms
385236724Strociny	CURVNET_SET(CRED_TO_VNET(cred));
386126077Sphk	/* find any existing device, or allocate new unit number */
387126077Sphk	i = clone_create(&tapclones, &tap_cdevsw, &unit, dev, extra);
388126077Sphk	if (i) {
389166497Sbms		if (append_unit) {
390166497Sbms			/*
391166497Sbms			 * We were passed 'tun' or 'tap', with no unit specified
392166497Sbms			 * so we'll need to append it now.
393166497Sbms			 */
394166497Sbms			namelen = snprintf(devname, sizeof(devname), "%s%d", name,
395166497Sbms			    unit);
396166497Sbms			name = devname;
397166497Sbms		}
398166497Sbms
399204464Skib		*dev = make_dev_credf(MAKEDEV_REF, &tap_cdevsw, unit | extra,
400204464Skib		     cred, UID_ROOT, GID_WHEEL, 0600, "%s", name);
40171602Sphk	}
402166497Sbms
403166497Sbms	if_clone_create(name, namelen, NULL);
404236724Strociny	CURVNET_RESTORE();
40571602Sphk} /* tapclone */
40671602Sphk
40771602Sphk
40871602Sphk/*
40963670Snsayer * tapcreate
41063670Snsayer *
41163670Snsayer * to create interface
41263670Snsayer */
41363670Snsayerstatic void
414156783Semaxtapcreate(struct cdev *dev)
41563670Snsayer{
41663670Snsayer	struct ifnet		*ifp = NULL;
41763670Snsayer	struct tap_softc	*tp = NULL;
41863670Snsayer	unsigned short		 macaddr_hi;
419178221Semax	uint32_t		 macaddr_mid;
420213028Sjhb	int			 unit;
421241610Sglebius	const char		*name = NULL;
422147256Sbrooks	u_char			eaddr[6];
42363670Snsayer
42463670Snsayer	/* allocate driver storage and create device */
425184205Sdes	tp = malloc(sizeof(*tp), M_TAP, M_WAITOK | M_ZERO);
426127098Srwatson	mtx_init(&tp->tap_mtx, "tap_mtx", NULL, MTX_DEF);
427127003Srwatson	mtx_lock(&tapmtx);
42883043Sbrooks	SLIST_INSERT_HEAD(&taphead, tp, tap_next);
429127003Srwatson	mtx_unlock(&tapmtx);
43063670Snsayer
431126796Sphk	unit = dev2unit(dev);
43283043Sbrooks
43363670Snsayer	/* select device: tap or vmnet */
434126796Sphk	if (unit & VMNET_DEV_MASK) {
435241610Sglebius		name = vmnetname;
43663803Snsayer		tp->tap_flags |= TAP_VMNET;
43783043Sbrooks	} else
438241610Sglebius		name = tapname;
43963670Snsayer
440126796Sphk	unit &= TAPMAXUNIT;
441126796Sphk
442183397Sed	TAPDEBUG("tapcreate(%s%d). minor = %#x\n", name, unit, dev2unit(dev));
44383043Sbrooks
44463670Snsayer	/* generate fake MAC address: 00 bd xx xx xx unit_no */
44563670Snsayer	macaddr_hi = htons(0x00bd);
446178221Semax	macaddr_mid = (uint32_t) ticks;
447147256Sbrooks	bcopy(&macaddr_hi, eaddr, sizeof(short));
448178221Semax	bcopy(&macaddr_mid, &eaddr[2], sizeof(uint32_t));
449147256Sbrooks	eaddr[5] = (u_char)unit;
45063670Snsayer
451111742Sdes	/* fill the rest and attach interface */
452147256Sbrooks	ifp = tp->tap_ifp = if_alloc(IFT_ETHER);
453147256Sbrooks	if (ifp == NULL)
454147256Sbrooks		panic("%s%d: can not if_alloc()", name, unit);
45563670Snsayer	ifp->if_softc = tp;
456121816Sbrooks	if_initname(ifp, name, unit);
45763670Snsayer	ifp->if_init = tapifinit;
45863670Snsayer	ifp->if_start = tapifstart;
45963670Snsayer	ifp->if_ioctl = tapifioctl;
46063670Snsayer	ifp->if_mtu = ETHERMTU;
46163670Snsayer	ifp->if_flags = (IFF_BROADCAST|IFF_SIMPLEX|IFF_MULTICAST);
462213028Sjhb	IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
463205222Sqingli	ifp->if_capabilities |= IFCAP_LINKSTATE;
464205222Sqingli	ifp->if_capenable |= IFCAP_LINKSTATE;
46563670Snsayer
46683043Sbrooks	dev->si_drv1 = tp;
467126077Sphk	tp->tap_dev = dev;
46883043Sbrooks
469147256Sbrooks	ether_ifattach(ifp, eaddr);
47063670Snsayer
471127098Srwatson	mtx_lock(&tp->tap_mtx);
47263803Snsayer	tp->tap_flags |= TAP_INITED;
473127098Srwatson	mtx_unlock(&tp->tap_mtx);
47463803Snsayer
475213028Sjhb	knlist_init_mtx(&tp->tap_rsel.si_note, &tp->tap_mtx);
476158697Semax
477121816Sbrooks	TAPDEBUG("interface %s is created. minor = %#x\n",
478183397Sed		ifp->if_xname, dev2unit(dev));
47963670Snsayer} /* tapcreate */
48063670Snsayer
48163670Snsayer
48263670Snsayer/*
483111742Sdes * tapopen
48463670Snsayer *
48563670Snsayer * to open tunnel. must be superuser
48663670Snsayer */
48763670Snsayerstatic int
488156783Semaxtapopen(struct cdev *dev, int flag, int mode, struct thread *td)
48963670Snsayer{
49063670Snsayer	struct tap_softc	*tp = NULL;
491133460Semax	struct ifnet		*ifp = NULL;
492213028Sjhb	int			 error;
49363670Snsayer
494164033Srwatson	if (tapuopen == 0) {
495164033Srwatson		error = priv_check(td, PRIV_NET_TAP);
496164033Srwatson		if (error)
497164033Srwatson			return (error);
498164033Srwatson	}
49963670Snsayer
500126796Sphk	if ((dev2unit(dev) & CLONE_UNITMASK) > TAPMAXUNIT)
501126796Sphk		return (ENXIO);
50283043Sbrooks
50363670Snsayer	tp = dev->si_drv1;
50463670Snsayer
505127165Srwatson	mtx_lock(&tp->tap_mtx);
506127165Srwatson	if (tp->tap_flags & TAP_OPEN) {
507127165Srwatson		mtx_unlock(&tp->tap_mtx);
508127165Srwatson		return (EBUSY);
509127165Srwatson	}
51063670Snsayer
511152315Sru	bcopy(IF_LLADDR(tp->tap_ifp), tp->ether_addr, sizeof(tp->ether_addr));
51283366Sjulian	tp->tap_pid = td->td_proc->p_pid;
51363670Snsayer	tp->tap_flags |= TAP_OPEN;
514147256Sbrooks	ifp = tp->tap_ifp;
51563670Snsayer
516148887Srwatson	ifp->if_drv_flags |= IFF_DRV_RUNNING;
517148887Srwatson	ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
518167713Sbms	if (tapuponopen)
519167713Sbms		ifp->if_flags |= IFF_UP;
520205024Sqingli	if_link_state_change(ifp, LINK_STATE_UP);
521213028Sjhb	mtx_unlock(&tp->tap_mtx);
52263670Snsayer
523183397Sed	TAPDEBUG("%s is open. minor = %#x\n", ifp->if_xname, dev2unit(dev));
524133460Semax
52563670Snsayer	return (0);
52663670Snsayer} /* tapopen */
52763670Snsayer
52863670Snsayer
52963670Snsayer/*
53063670Snsayer * tapclose
53163670Snsayer *
53263670Snsayer * close the device - mark i/f down & delete routing info
53363670Snsayer */
53463670Snsayerstatic int
535156783Semaxtapclose(struct cdev *dev, int foo, int bar, struct thread *td)
53663670Snsayer{
537156783Semax	struct ifaddr		*ifa;
53863670Snsayer	struct tap_softc	*tp = dev->si_drv1;
539147256Sbrooks	struct ifnet		*ifp = tp->tap_ifp;
54063670Snsayer
54163670Snsayer	/* junk all pending output */
542213028Sjhb	mtx_lock(&tp->tap_mtx);
543236724Strociny	CURVNET_SET(ifp->if_vnet);
54483043Sbrooks	IF_DRAIN(&ifp->if_snd);
54563670Snsayer
54663803Snsayer	/*
547281363Sglebius	 * Do not bring the interface down, and do not anything with
548281363Sglebius	 * interface, if we are in VMnet mode. Just close the device.
54963803Snsayer	 */
550281363Sglebius	if (((tp->tap_flags & TAP_VMNET) == 0) &&
551281363Sglebius	    (ifp->if_flags & (IFF_UP | IFF_LINK0)) == IFF_UP) {
552127098Srwatson		mtx_unlock(&tp->tap_mtx);
55363670Snsayer		if_down(ifp);
554213028Sjhb		mtx_lock(&tp->tap_mtx);
555148887Srwatson		if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
556213028Sjhb			ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
557213028Sjhb			mtx_unlock(&tp->tap_mtx);
55863803Snsayer			TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
559146620Speadar				rtinit(ifa, (int)RTM_DELETE, 0);
56063670Snsayer			}
561146620Speadar			if_purgeaddrs(ifp);
562213028Sjhb			mtx_lock(&tp->tap_mtx);
56363670Snsayer		}
564213028Sjhb	}
56563670Snsayer
566205024Sqingli	if_link_state_change(ifp, LINK_STATE_DOWN);
567236724Strociny	CURVNET_RESTORE();
568236724Strociny
56996122Salfred	funsetown(&tp->tap_sigio);
570122352Stanimura	selwakeuppri(&tp->tap_rsel, PZERO+1);
571213028Sjhb	KNOTE_LOCKED(&tp->tap_rsel.si_note, 0);
57263670Snsayer
57363670Snsayer	tp->tap_flags &= ~TAP_OPEN;
57463670Snsayer	tp->tap_pid = 0;
575127098Srwatson	mtx_unlock(&tp->tap_mtx);
57663670Snsayer
577121816Sbrooks	TAPDEBUG("%s is closed. minor = %#x\n",
578183397Sed		ifp->if_xname, dev2unit(dev));
57963670Snsayer
58063670Snsayer	return (0);
58163670Snsayer} /* tapclose */
58263670Snsayer
58363670Snsayer
58463670Snsayer/*
58563670Snsayer * tapifinit
58663670Snsayer *
58763670Snsayer * network interface initialization function
58863670Snsayer */
58963670Snsayerstatic void
590156783Semaxtapifinit(void *xtp)
59163670Snsayer{
59263670Snsayer	struct tap_softc	*tp = (struct tap_softc *)xtp;
593147256Sbrooks	struct ifnet		*ifp = tp->tap_ifp;
59463670Snsayer
595121816Sbrooks	TAPDEBUG("initializing %s\n", ifp->if_xname);
59663670Snsayer
597213028Sjhb	mtx_lock(&tp->tap_mtx);
598148887Srwatson	ifp->if_drv_flags |= IFF_DRV_RUNNING;
599148887Srwatson	ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
600213028Sjhb	mtx_unlock(&tp->tap_mtx);
60163670Snsayer
60263670Snsayer	/* attempt to start output */
60363670Snsayer	tapifstart(ifp);
60463670Snsayer} /* tapifinit */
60563670Snsayer
60663670Snsayer
60763670Snsayer/*
60863670Snsayer * tapifioctl
60963670Snsayer *
61063670Snsayer * Process an ioctl request on network interface
61163670Snsayer */
612105228Sphkstatic int
613156783Semaxtapifioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
61463670Snsayer{
615347378Skevans	struct tap_softc	*tp;
616189866Sscf	struct ifreq		*ifr = (struct ifreq *)data;
61763670Snsayer	struct ifstat		*ifs = NULL;
618238183Semaste	struct ifmediareq	*ifmr = NULL;
619238183Semaste	int			 dummy, error = 0;
62063670Snsayer
621347378Skevans	sx_xlock(&tap_ioctl_sx);
622347378Skevans	tp = ifp->if_softc;
623347378Skevans	if (tp == NULL) {
624347378Skevans		error = ENXIO;
625347378Skevans		goto bad;
626347378Skevans	}
62763670Snsayer	switch (cmd) {
62863670Snsayer		case SIOCSIFFLAGS: /* XXX -- just like vmnet does */
62963670Snsayer		case SIOCADDMULTI:
63063670Snsayer		case SIOCDELMULTI:
63183043Sbrooks			break;
63263670Snsayer
633238183Semaste		case SIOCGIFMEDIA:
634238183Semaste			ifmr = (struct ifmediareq *)data;
635238183Semaste			dummy = ifmr->ifm_count;
636238183Semaste			ifmr->ifm_count = 1;
637238183Semaste			ifmr->ifm_status = IFM_AVALID;
638238183Semaste			ifmr->ifm_active = IFM_ETHER;
639238183Semaste			if (tp->tap_flags & TAP_OPEN)
640238183Semaste				ifmr->ifm_status |= IFM_ACTIVE;
641238183Semaste			ifmr->ifm_current = ifmr->ifm_active;
642238183Semaste			if (dummy >= 1) {
643238183Semaste				int media = IFM_ETHER;
644238183Semaste				error = copyout(&media, ifmr->ifm_ulist,
645238183Semaste				    sizeof(int));
646238183Semaste			}
647238183Semaste			break;
648238183Semaste
649189866Sscf		case SIOCSIFMTU:
650189866Sscf			ifp->if_mtu = ifr->ifr_mtu;
651189866Sscf			break;
652189866Sscf
65363670Snsayer		case SIOCGIFSTATUS:
65463670Snsayer			ifs = (struct ifstat *)data;
655127098Srwatson			mtx_lock(&tp->tap_mtx);
656260394Smelifaro			if (tp->tap_pid != 0)
657260394Smelifaro				snprintf(ifs->ascii, sizeof(ifs->ascii),
65863670Snsayer					"\tOpened by PID %d\n", tp->tap_pid);
659260394Smelifaro			else
660260394Smelifaro				ifs->ascii[0] = '\0';
661127098Srwatson			mtx_unlock(&tp->tap_mtx);
66283043Sbrooks			break;
66363670Snsayer
66463670Snsayer		default:
665238183Semaste			error = ether_ioctl(ifp, cmd, data);
666238183Semaste			break;
66763670Snsayer	}
66863670Snsayer
669347378Skevansbad:
670347378Skevans	sx_xunlock(&tap_ioctl_sx);
671238183Semaste	return (error);
67263670Snsayer} /* tapifioctl */
67363670Snsayer
67463670Snsayer
67563670Snsayer/*
676111742Sdes * tapifstart
677111742Sdes *
67863670Snsayer * queue packets from higher level ready to put out
67963670Snsayer */
68063670Snsayerstatic void
681156783Semaxtapifstart(struct ifnet *ifp)
68263670Snsayer{
68363670Snsayer	struct tap_softc	*tp = ifp->if_softc;
68463670Snsayer
685121816Sbrooks	TAPDEBUG("%s starting\n", ifp->if_xname);
68663670Snsayer
68763803Snsayer	/*
68863803Snsayer	 * do not junk pending output if we are in VMnet mode.
68963803Snsayer	 * XXX: can this do any harm because of queue overflow?
69063803Snsayer	 */
69163803Snsayer
692127098Srwatson	mtx_lock(&tp->tap_mtx);
693111742Sdes	if (((tp->tap_flags & TAP_VMNET) == 0) &&
69463803Snsayer	    ((tp->tap_flags & TAP_READY) != TAP_READY)) {
695213028Sjhb		struct mbuf *m;
69663670Snsayer
697127098Srwatson		/* Unlocked read. */
698121816Sbrooks		TAPDEBUG("%s not ready, tap_flags = 0x%x\n", ifp->if_xname,
699121816Sbrooks		    tp->tap_flags);
70063670Snsayer
701213028Sjhb		for (;;) {
70263670Snsayer			IF_DEQUEUE(&ifp->if_snd, m);
703213028Sjhb			if (m != NULL) {
70463670Snsayer				m_freem(m);
705271867Sglebius				if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
706213028Sjhb			} else
707213028Sjhb				break;
708213028Sjhb		}
709213028Sjhb		mtx_unlock(&tp->tap_mtx);
71063670Snsayer
71163670Snsayer		return;
71263670Snsayer	}
71363670Snsayer
714148887Srwatson	ifp->if_drv_flags |= IFF_DRV_OACTIVE;
71563670Snsayer
716213028Sjhb	if (!IFQ_IS_EMPTY(&ifp->if_snd)) {
71763670Snsayer		if (tp->tap_flags & TAP_RWAIT) {
71863670Snsayer			tp->tap_flags &= ~TAP_RWAIT;
719111748Sdes			wakeup(tp);
72063670Snsayer		}
72163670Snsayer
722127098Srwatson		if ((tp->tap_flags & TAP_ASYNC) && (tp->tap_sigio != NULL)) {
723127098Srwatson			mtx_unlock(&tp->tap_mtx);
72495883Salfred			pgsigio(&tp->tap_sigio, SIGIO, 0);
725213028Sjhb			mtx_lock(&tp->tap_mtx);
726213028Sjhb		}
72763670Snsayer
728122352Stanimura		selwakeuppri(&tp->tap_rsel, PZERO+1);
729213028Sjhb		KNOTE_LOCKED(&tp->tap_rsel.si_note, 0);
730271867Sglebius		if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); /* obytes are counted in ether_output */
73163670Snsayer	}
73263670Snsayer
733148887Srwatson	ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
734213028Sjhb	mtx_unlock(&tp->tap_mtx);
73563670Snsayer} /* tapifstart */
73663670Snsayer
73763670Snsayer
73863670Snsayer/*
73963670Snsayer * tapioctl
74063670Snsayer *
74163670Snsayer * the cdevsw interface is now pretty minimal
74263670Snsayer */
74363670Snsayerstatic int
744156783Semaxtapioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td)
74563670Snsayer{
746341884Shselasky	struct ifreq		 ifr;
74763670Snsayer	struct tap_softc	*tp = dev->si_drv1;
748147256Sbrooks	struct ifnet		*ifp = tp->tap_ifp;
749111742Sdes	struct tapinfo		*tapp = NULL;
750102052Ssobomax	int			 f;
751341884Shselasky	int			 error;
752162711Sru#if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5) || \
753162711Sru    defined(COMPAT_FREEBSD4)
754162711Sru	int			 ival;
755162711Sru#endif
75663670Snsayer
75763670Snsayer	switch (cmd) {
758111742Sdes		case TAPSIFINFO:
759111742Sdes			tapp = (struct tapinfo *)data;
760326691Shselasky			if (ifp->if_type != tapp->type)
761326691Shselasky				return (EPROTOTYPE);
762213028Sjhb			mtx_lock(&tp->tap_mtx);
763341884Shselasky			if (ifp->if_mtu != tapp->mtu) {
764347376Skevans				strlcpy(ifr.ifr_name, if_name(ifp), IFNAMSIZ);
765341884Shselasky				ifr.ifr_mtu = tapp->mtu;
766341884Shselasky				CURVNET_SET(ifp->if_vnet);
767341884Shselasky				error = ifhwioctl(SIOCSIFMTU, ifp,
768341884Shselasky				    (caddr_t)&ifr, td);
769341884Shselasky				CURVNET_RESTORE();
770341884Shselasky				if (error) {
771341884Shselasky					mtx_unlock(&tp->tap_mtx);
772341884Shselasky					return (error);
773341884Shselasky				}
774341884Shselasky			}
775111742Sdes			ifp->if_baudrate = tapp->baudrate;
776213028Sjhb			mtx_unlock(&tp->tap_mtx);
777111742Sdes			break;
77863670Snsayer
779111742Sdes		case TAPGIFINFO:
780111742Sdes			tapp = (struct tapinfo *)data;
781213028Sjhb			mtx_lock(&tp->tap_mtx);
782111742Sdes			tapp->mtu = ifp->if_mtu;
783111742Sdes			tapp->type = ifp->if_type;
784111742Sdes			tapp->baudrate = ifp->if_baudrate;
785213028Sjhb			mtx_unlock(&tp->tap_mtx);
786111742Sdes			break;
78763670Snsayer
78863670Snsayer		case TAPSDEBUG:
789159079Smarius			tapdebug = *(int *)data;
79083043Sbrooks			break;
79163670Snsayer
79263670Snsayer		case TAPGDEBUG:
793159079Smarius			*(int *)data = tapdebug;
79483043Sbrooks			break;
79563670Snsayer
796182880Semax		case TAPGIFNAME: {
797182880Semax			struct ifreq	*ifr = (struct ifreq *) data;
798182880Semax
799182880Semax			strlcpy(ifr->ifr_name, ifp->if_xname, IFNAMSIZ);
800182880Semax			} break;
801182880Semax
80263670Snsayer		case FIONBIO:
80383043Sbrooks			break;
80463670Snsayer
80563670Snsayer		case FIOASYNC:
806127098Srwatson			mtx_lock(&tp->tap_mtx);
807159079Smarius			if (*(int *)data)
80863670Snsayer				tp->tap_flags |= TAP_ASYNC;
80963670Snsayer			else
81063670Snsayer				tp->tap_flags &= ~TAP_ASYNC;
811127098Srwatson			mtx_unlock(&tp->tap_mtx);
81283043Sbrooks			break;
81363670Snsayer
81463670Snsayer		case FIONREAD:
815213028Sjhb			if (!IFQ_IS_EMPTY(&ifp->if_snd)) {
816213028Sjhb				struct mbuf *mb;
81763670Snsayer
818213028Sjhb				IFQ_LOCK(&ifp->if_snd);
819213028Sjhb				IFQ_POLL_NOLOCK(&ifp->if_snd, mb);
820213028Sjhb				for (*(int *)data = 0; mb != NULL;
821213028Sjhb				     mb = mb->m_next)
822159079Smarius					*(int *)data += mb->m_len;
823213028Sjhb				IFQ_UNLOCK(&ifp->if_snd);
82483043Sbrooks			} else
825159079Smarius				*(int *)data = 0;
82683043Sbrooks			break;
82763670Snsayer
82863670Snsayer		case FIOSETOWN:
829159079Smarius			return (fsetown(*(int *)data, &tp->tap_sigio));
83063670Snsayer
83163670Snsayer		case FIOGETOWN:
832159079Smarius			*(int *)data = fgetown(&tp->tap_sigio);
83363670Snsayer			return (0);
83463670Snsayer
83563670Snsayer		/* this is deprecated, FIOSETOWN should be used instead */
83663670Snsayer		case TIOCSPGRP:
837159079Smarius			return (fsetown(-(*(int *)data), &tp->tap_sigio));
83863670Snsayer
83963670Snsayer		/* this is deprecated, FIOGETOWN should be used instead */
84063670Snsayer		case TIOCGPGRP:
841159079Smarius			*(int *)data = -fgetown(&tp->tap_sigio);
84263670Snsayer			return (0);
84363670Snsayer
84463670Snsayer		/* VMware/VMnet port ioctl's */
84563670Snsayer
846162711Sru#if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5) || \
847162711Sru    defined(COMPAT_FREEBSD4)
848162711Sru		case _IO('V', 0):
849162711Sru			ival = IOCPARM_IVAL(data);
850162711Sru			data = (caddr_t)&ival;
851162711Sru			/* FALLTHROUGH */
852162711Sru#endif
85383043Sbrooks		case VMIO_SIOCSIFFLAGS: /* VMware/VMnet SIOCSIFFLAGS */
854162711Sru			f = *(int *)data;
85563670Snsayer			f &= 0x0fff;
85663670Snsayer			f &= ~IFF_CANTCHANGE;
85763670Snsayer			f |= IFF_UP;
85863670Snsayer
859213028Sjhb			mtx_lock(&tp->tap_mtx);
86063670Snsayer			ifp->if_flags = f | (ifp->if_flags & IFF_CANTCHANGE);
861213028Sjhb			mtx_unlock(&tp->tap_mtx);
86283043Sbrooks			break;
86363670Snsayer
864257696Sglebius		case SIOCGIFADDR:	/* get MAC address of the remote side */
865127165Srwatson			mtx_lock(&tp->tap_mtx);
86663861Snsayer			bcopy(tp->ether_addr, data, sizeof(tp->ether_addr));
867127165Srwatson			mtx_unlock(&tp->tap_mtx);
86883043Sbrooks			break;
86963670Snsayer
87063861Snsayer		case SIOCSIFADDR:	/* set MAC address of the remote side */
871127165Srwatson			mtx_lock(&tp->tap_mtx);
87263861Snsayer			bcopy(data, tp->ether_addr, sizeof(tp->ether_addr));
873127165Srwatson			mtx_unlock(&tp->tap_mtx);
87483043Sbrooks			break;
87563670Snsayer
87663670Snsayer		default:
87763670Snsayer			return (ENOTTY);
87863670Snsayer	}
87963670Snsayer	return (0);
88063670Snsayer} /* tapioctl */
88163670Snsayer
88263670Snsayer
88363670Snsayer/*
88463670Snsayer * tapread
88563670Snsayer *
88663670Snsayer * the cdevsw read interface - reads a packet at a time, or at
88763670Snsayer * least as much of a packet as can be read
88863670Snsayer */
88963670Snsayerstatic int
890156783Semaxtapread(struct cdev *dev, struct uio *uio, int flag)
89163670Snsayer{
89263670Snsayer	struct tap_softc	*tp = dev->si_drv1;
893147256Sbrooks	struct ifnet		*ifp = tp->tap_ifp;
89490227Sdillon	struct mbuf		*m = NULL;
895213028Sjhb	int			 error = 0, len;
89663670Snsayer
897183397Sed	TAPDEBUG("%s reading, minor = %#x\n", ifp->if_xname, dev2unit(dev));
89863670Snsayer
899127098Srwatson	mtx_lock(&tp->tap_mtx);
90063670Snsayer	if ((tp->tap_flags & TAP_READY) != TAP_READY) {
901127098Srwatson		mtx_unlock(&tp->tap_mtx);
902127098Srwatson
903127098Srwatson		/* Unlocked read. */
904121816Sbrooks		TAPDEBUG("%s not ready. minor = %#x, tap_flags = 0x%x\n",
905183397Sed			ifp->if_xname, dev2unit(dev), tp->tap_flags);
90663803Snsayer
90763670Snsayer		return (EHOSTDOWN);
90863670Snsayer	}
90963670Snsayer
91063670Snsayer	tp->tap_flags &= ~TAP_RWAIT;
91163670Snsayer
91263670Snsayer	/* sleep until we get a packet */
91363670Snsayer	do {
91490227Sdillon		IF_DEQUEUE(&ifp->if_snd, m);
91563670Snsayer
91690227Sdillon		if (m == NULL) {
917213028Sjhb			if (flag & O_NONBLOCK) {
918213028Sjhb				mtx_unlock(&tp->tap_mtx);
91963670Snsayer				return (EWOULDBLOCK);
920213028Sjhb			}
921111742Sdes
92263670Snsayer			tp->tap_flags |= TAP_RWAIT;
923213028Sjhb			error = mtx_sleep(tp, &tp->tap_mtx, PCATCH | (PZERO + 1),
924213028Sjhb			    "taprd", 0);
925213028Sjhb			if (error) {
926213028Sjhb				mtx_unlock(&tp->tap_mtx);
92763670Snsayer				return (error);
928213028Sjhb			}
92963670Snsayer		}
93090227Sdillon	} while (m == NULL);
931213028Sjhb	mtx_unlock(&tp->tap_mtx);
93263670Snsayer
93363670Snsayer	/* feed packet to bpf */
934106939Ssam	BPF_MTAP(ifp, m);
93563670Snsayer
93663670Snsayer	/* xfer packet to user space */
93790227Sdillon	while ((m != NULL) && (uio->uio_resid > 0) && (error == 0)) {
93890227Sdillon		len = min(uio->uio_resid, m->m_len);
93963670Snsayer		if (len == 0)
94063670Snsayer			break;
94163670Snsayer
942111741Sdes		error = uiomove(mtod(m, void *), len, uio);
94390227Sdillon		m = m_free(m);
94463670Snsayer	}
94563670Snsayer
94690227Sdillon	if (m != NULL) {
947121816Sbrooks		TAPDEBUG("%s dropping mbuf, minor = %#x\n", ifp->if_xname,
948183397Sed			dev2unit(dev));
94990227Sdillon		m_freem(m);
95063670Snsayer	}
95163670Snsayer
95263670Snsayer	return (error);
95363670Snsayer} /* tapread */
95463670Snsayer
95563670Snsayer
95663670Snsayer/*
95763670Snsayer * tapwrite
95863670Snsayer *
95963670Snsayer * the cdevsw write interface - an atomic write is a packet - or else!
96063670Snsayer */
96163670Snsayerstatic int
962156783Semaxtapwrite(struct cdev *dev, struct uio *uio, int flag)
96363670Snsayer{
964166443Sbms	struct ether_header	*eh;
96563670Snsayer	struct tap_softc	*tp = dev->si_drv1;
966147256Sbrooks	struct ifnet		*ifp = tp->tap_ifp;
967137101Sglebius	struct mbuf		*m;
96863670Snsayer
969240945Semaste	TAPDEBUG("%s writing, minor = %#x\n",
970183397Sed		ifp->if_xname, dev2unit(dev));
97163670Snsayer
97263670Snsayer	if (uio->uio_resid == 0)
97363670Snsayer		return (0);
97463670Snsayer
97563670Snsayer	if ((uio->uio_resid < 0) || (uio->uio_resid > TAPMRU)) {
976194990Skib		TAPDEBUG("%s invalid packet len = %zd, minor = %#x\n",
977183397Sed			ifp->if_xname, uio->uio_resid, dev2unit(dev));
97863803Snsayer
97963670Snsayer		return (EIO);
98063670Snsayer	}
98163670Snsayer
982243882Sglebius	if ((m = m_uiotombuf(uio, M_NOWAIT, 0, ETHER_ALIGN,
983163915Sandre	    M_PKTHDR)) == NULL) {
984271867Sglebius		if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
985163986Scsjp		return (ENOBUFS);
98663670Snsayer	}
98763670Snsayer
988137101Sglebius	m->m_pkthdr.rcvif = ifp;
989111742Sdes
990166443Sbms	/*
991166443Sbms	 * Only pass a unicast frame to ether_input(), if it would actually
992166443Sbms	 * have been received by non-virtual hardware.
993166443Sbms	 */
994166443Sbms	if (m->m_len < sizeof(struct ether_header)) {
995166443Sbms		m_freem(m);
996166443Sbms		return (0);
997166443Sbms	}
998166443Sbms	eh = mtod(m, struct ether_header *);
999166443Sbms
1000166443Sbms	if (eh && (ifp->if_flags & IFF_PROMISC) == 0 &&
1001166443Sbms	    !ETHER_IS_MULTICAST(eh->ether_dhost) &&
1002166443Sbms	    bcmp(eh->ether_dhost, IF_LLADDR(ifp), ETHER_ADDR_LEN) != 0) {
1003166443Sbms		m_freem(m);
1004166443Sbms		return (0);
1005166443Sbms	}
1006166443Sbms
1007106939Ssam	/* Pass packet up to parent. */
1008236724Strociny	CURVNET_SET(ifp->if_vnet);
1009137101Sglebius	(*ifp->if_input)(ifp, m);
1010236724Strociny	CURVNET_RESTORE();
1011271867Sglebius	if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1); /* ibytes are counted in parent */
101263670Snsayer
101363670Snsayer	return (0);
101463670Snsayer} /* tapwrite */
101563670Snsayer
101663670Snsayer
101763670Snsayer/*
101863670Snsayer * tappoll
101963670Snsayer *
102063670Snsayer * the poll interface, this is only useful on reads
102163670Snsayer * really. the write detect always returns true, write never blocks
102263670Snsayer * anyway, it either accepts the packet or drops it
102363670Snsayer */
102463670Snsayerstatic int
1025156783Semaxtappoll(struct cdev *dev, int events, struct thread *td)
102663670Snsayer{
102763670Snsayer	struct tap_softc	*tp = dev->si_drv1;
1028147256Sbrooks	struct ifnet		*ifp = tp->tap_ifp;
1029213028Sjhb	int			 revents = 0;
103063670Snsayer
1031121816Sbrooks	TAPDEBUG("%s polling, minor = %#x\n",
1032183397Sed		ifp->if_xname, dev2unit(dev));
103363670Snsayer
103463670Snsayer	if (events & (POLLIN | POLLRDNORM)) {
1035213028Sjhb		IFQ_LOCK(&ifp->if_snd);
1036213028Sjhb		if (!IFQ_IS_EMPTY(&ifp->if_snd)) {
1037121816Sbrooks			TAPDEBUG("%s have data in queue. len = %d, " \
1038121816Sbrooks				"minor = %#x\n", ifp->if_xname,
1039183397Sed				ifp->if_snd.ifq_len, dev2unit(dev));
104063803Snsayer
104163670Snsayer			revents |= (events & (POLLIN | POLLRDNORM));
104283043Sbrooks		} else {
1043121816Sbrooks			TAPDEBUG("%s waiting for data, minor = %#x\n",
1044183397Sed				ifp->if_xname, dev2unit(dev));
104563803Snsayer
104683805Sjhb			selrecord(td, &tp->tap_rsel);
104763670Snsayer		}
1048213028Sjhb		IFQ_UNLOCK(&ifp->if_snd);
104963670Snsayer	}
105063670Snsayer
105163670Snsayer	if (events & (POLLOUT | POLLWRNORM))
105263670Snsayer		revents |= (events & (POLLOUT | POLLWRNORM));
105363670Snsayer
105463670Snsayer	return (revents);
105563670Snsayer} /* tappoll */
1056156783Semax
1057156783Semax
1058156783Semax/*
1059156783Semax * tap_kqfilter
1060156783Semax *
1061156783Semax * support for kevent() system call
1062156783Semax */
1063156783Semaxstatic int
1064156783Semaxtapkqfilter(struct cdev *dev, struct knote *kn)
1065156783Semax{
1066156783Semax	struct tap_softc	*tp = dev->si_drv1;
1067156783Semax	struct ifnet		*ifp = tp->tap_ifp;
1068156783Semax
1069156783Semax	switch (kn->kn_filter) {
1070156783Semax	case EVFILT_READ:
1071156783Semax		TAPDEBUG("%s kqfilter: EVFILT_READ, minor = %#x\n",
1072183397Sed			ifp->if_xname, dev2unit(dev));
1073156783Semax		kn->kn_fop = &tap_read_filterops;
1074156783Semax		break;
1075156783Semax
1076156783Semax	case EVFILT_WRITE:
1077156783Semax		TAPDEBUG("%s kqfilter: EVFILT_WRITE, minor = %#x\n",
1078183397Sed			ifp->if_xname, dev2unit(dev));
1079156783Semax		kn->kn_fop = &tap_write_filterops;
1080156783Semax		break;
1081156783Semax
1082156783Semax	default:
1083156783Semax		TAPDEBUG("%s kqfilter: invalid filter, minor = %#x\n",
1084183397Sed			ifp->if_xname, dev2unit(dev));
1085156783Semax		return (EINVAL);
1086156783Semax		/* NOT REACHED */
1087156783Semax	}
1088156783Semax
1089213028Sjhb	kn->kn_hook = tp;
1090156783Semax	knlist_add(&tp->tap_rsel.si_note, kn, 0);
1091156783Semax
1092156783Semax	return (0);
1093156783Semax} /* tapkqfilter */
1094156783Semax
1095156783Semax
1096156783Semax/*
1097156783Semax * tap_kqread
1098156783Semax *
1099156783Semax * Return true if there is data in the interface queue
1100156783Semax */
1101156783Semaxstatic int
1102156783Semaxtapkqread(struct knote *kn, long hint)
1103156783Semax{
1104213028Sjhb	int			 ret;
1105213028Sjhb	struct tap_softc	*tp = kn->kn_hook;
1106213028Sjhb	struct cdev		*dev = tp->tap_dev;
1107156783Semax	struct ifnet		*ifp = tp->tap_ifp;
1108156783Semax
1109156783Semax	if ((kn->kn_data = ifp->if_snd.ifq_len) > 0) {
1110156783Semax		TAPDEBUG("%s have data in queue. len = %d, minor = %#x\n",
1111183397Sed			ifp->if_xname, ifp->if_snd.ifq_len, dev2unit(dev));
1112156783Semax		ret = 1;
1113156783Semax	} else {
1114156783Semax		TAPDEBUG("%s waiting for data, minor = %#x\n",
1115183397Sed			ifp->if_xname, dev2unit(dev));
1116156783Semax		ret = 0;
1117156783Semax	}
1118156783Semax
1119156783Semax	return (ret);
1120156783Semax} /* tapkqread */
1121156783Semax
1122156783Semax
1123156783Semax/*
1124156783Semax * tap_kqwrite
1125156783Semax *
1126156783Semax * Always can write. Return the MTU in kn->data
1127156783Semax */
1128156783Semaxstatic int
1129156783Semaxtapkqwrite(struct knote *kn, long hint)
1130156783Semax{
1131213028Sjhb	struct tap_softc	*tp = kn->kn_hook;
1132156783Semax	struct ifnet		*ifp = tp->tap_ifp;
1133156783Semax
1134156783Semax	kn->kn_data = ifp->if_mtu;
1135156783Semax
1136156783Semax	return (1);
1137156783Semax} /* tapkqwrite */
1138156783Semax
1139156783Semax
1140156783Semaxstatic void
1141156783Semaxtapkqdetach(struct knote *kn)
1142156783Semax{
1143213028Sjhb	struct tap_softc	*tp = kn->kn_hook;
1144156783Semax
1145156783Semax	knlist_remove(&tp->tap_rsel.si_note, kn, 0);
1146156783Semax} /* tapkqdetach */
1147156783Semax
1148