if_tap.c revision 347376
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 347376 2019-05-09 01:16:03Z 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> 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> 66257176Sglebius#include <net/if_var.h> 67166497Sbms#include <net/if_clone.h> 68152315Sru#include <net/if_dl.h> 69238183Semaste#include <net/if_media.h> 70236725Strociny#include <net/if_types.h> 7163670Snsayer#include <net/route.h> 72236724Strociny#include <net/vnet.h> 7363670Snsayer 7463670Snsayer#include <netinet/in.h> 7563670Snsayer 7663670Snsayer#include <net/if_tapvar.h> 7763670Snsayer#include <net/if_tap.h> 7863670Snsayer 7963670Snsayer 8063670Snsayer#define CDEV_NAME "tap" 8163670Snsayer#define TAPDEBUG if (tapdebug) printf 8263670Snsayer 83241610Sglebiusstatic const char tapname[] = "tap"; 84241610Sglebiusstatic const char vmnetname[] = "vmnet"; 8583043Sbrooks#define TAPMAXUNIT 0x7fff 86126077Sphk#define VMNET_DEV_MASK CLONE_FLAG0 8763670Snsayer 8863670Snsayer/* module */ 89111742Sdesstatic int tapmodevent(module_t, int, void *); 9063670Snsayer 9163670Snsayer/* device */ 92148868Srwatsonstatic void tapclone(void *, struct ucred *, char *, int, 93148868Srwatson struct cdev **); 94130585Sphkstatic void tapcreate(struct cdev *); 9563670Snsayer 9663670Snsayer/* network interface */ 9793084Sbdestatic void tapifstart(struct ifnet *); 9893084Sbdestatic int tapifioctl(struct ifnet *, u_long, caddr_t); 9993084Sbdestatic void tapifinit(void *); 10063670Snsayer 101166497Sbmsstatic int tap_clone_create(struct if_clone *, int, caddr_t); 102166497Sbmsstatic void tap_clone_destroy(struct ifnet *); 103241610Sglebiusstatic struct if_clone *tap_cloner; 104166497Sbmsstatic int vmnet_clone_create(struct if_clone *, int, caddr_t); 105166497Sbmsstatic void vmnet_clone_destroy(struct ifnet *); 106241610Sglebiusstatic struct if_clone *vmnet_cloner; 107166497Sbms 10863670Snsayer/* character device */ 10963670Snsayerstatic d_open_t tapopen; 11063670Snsayerstatic d_close_t tapclose; 11163670Snsayerstatic d_read_t tapread; 11263670Snsayerstatic d_write_t tapwrite; 11363670Snsayerstatic d_ioctl_t tapioctl; 11463670Snsayerstatic d_poll_t tappoll; 115156783Semaxstatic d_kqfilter_t tapkqfilter; 11663670Snsayer 117156783Semax/* kqueue(2) */ 118156783Semaxstatic int tapkqread(struct knote *, long); 119156783Semaxstatic int tapkqwrite(struct knote *, long); 120156783Semaxstatic void tapkqdetach(struct knote *); 121156783Semax 122156783Semaxstatic struct filterops tap_read_filterops = { 123156783Semax .f_isfd = 1, 124156783Semax .f_attach = NULL, 125156783Semax .f_detach = tapkqdetach, 126156783Semax .f_event = tapkqread, 127156783Semax}; 128156783Semax 129156783Semaxstatic struct filterops tap_write_filterops = { 130156783Semax .f_isfd = 1, 131156783Semax .f_attach = NULL, 132156783Semax .f_detach = tapkqdetach, 133156783Semax .f_event = tapkqwrite, 134156783Semax}; 135156783Semax 13663670Snsayerstatic struct cdevsw tap_cdevsw = { 137126080Sphk .d_version = D_VERSION, 138226500Sed .d_flags = D_NEEDMINOR, 139111815Sphk .d_open = tapopen, 140111815Sphk .d_close = tapclose, 141111815Sphk .d_read = tapread, 142111815Sphk .d_write = tapwrite, 143111815Sphk .d_ioctl = tapioctl, 144111815Sphk .d_poll = tappoll, 145111815Sphk .d_name = CDEV_NAME, 146156783Semax .d_kqfilter = tapkqfilter, 14763670Snsayer}; 14863670Snsayer 149127003Srwatson/* 150127003Srwatson * All global variables in if_tap.c are locked with tapmtx, with the 151127003Srwatson * exception of tapdebug, which is accessed unlocked; tapclones is 152127003Srwatson * static at runtime. 153127003Srwatson */ 154127003Srwatsonstatic struct mtx tapmtx; 15583043Sbrooksstatic int tapdebug = 0; /* debug flag */ 156167713Sbmsstatic int tapuopen = 0; /* allow user open() */ 157167713Sbmsstatic int tapuponopen = 0; /* IFF_UP on open() */ 158166497Sbmsstatic int tapdclone = 1; /* enable devfs cloning */ 15983043Sbrooksstatic SLIST_HEAD(, tap_softc) taphead; /* first device */ 160126077Sphkstatic struct clonedevs *tapclones; 16163670Snsayer 16263670SnsayerMALLOC_DECLARE(M_TAP); 16363670SnsayerMALLOC_DEFINE(M_TAP, CDEV_NAME, "Ethernet tunnel interface"); 16463670SnsayerSYSCTL_INT(_debug, OID_AUTO, if_tap_debug, CTLFLAG_RW, &tapdebug, 0, ""); 165144979Smdodd 166144979SmdoddSYSCTL_DECL(_net_link); 167227309Sedstatic SYSCTL_NODE(_net_link, OID_AUTO, tap, CTLFLAG_RW, 0, 168144979Smdodd "Ethernet tunnel software network interface"); 169144979SmdoddSYSCTL_INT(_net_link_tap, OID_AUTO, user_open, CTLFLAG_RW, &tapuopen, 0, 170144979Smdodd "Allow user to open /dev/tap (based on node permissions)"); 171167713SbmsSYSCTL_INT(_net_link_tap, OID_AUTO, up_on_open, CTLFLAG_RW, &tapuponopen, 0, 172167713Sbms "Bring interface up when /dev/tap is opened"); 173267992ShselaskySYSCTL_INT(_net_link_tap, OID_AUTO, devfs_cloning, CTLFLAG_RWTUN, &tapdclone, 0, 174289718Semaste "Enable legacy devfs interface creation"); 175144979SmdoddSYSCTL_INT(_net_link_tap, OID_AUTO, debug, CTLFLAG_RW, &tapdebug, 0, ""); 176144979Smdodd 17763670SnsayerDEV_MODULE(if_tap, tapmodevent, NULL); 178346803SkevansMODULE_VERSION(if_tap, 1); 17963670Snsayer 180166497Sbmsstatic int 181166497Sbmstap_clone_create(struct if_clone *ifc, int unit, caddr_t params) 182166497Sbms{ 183166497Sbms struct cdev *dev; 184166497Sbms int i; 185166497Sbms 186241610Sglebius /* Find any existing device, or allocate new unit number. */ 187241610Sglebius i = clone_create(&tapclones, &tap_cdevsw, &unit, &dev, 0); 188166497Sbms if (i) { 189243615Sdavidxu dev = make_dev(&tap_cdevsw, unit, UID_ROOT, GID_WHEEL, 0600, 190241610Sglebius "%s%d", tapname, unit); 191166497Sbms } 192166497Sbms 193166497Sbms tapcreate(dev); 194166497Sbms return (0); 195166497Sbms} 196166497Sbms 197166497Sbms/* vmnet devices are tap devices in disguise */ 198166497Sbmsstatic int 199166497Sbmsvmnet_clone_create(struct if_clone *ifc, int unit, caddr_t params) 200166497Sbms{ 201241610Sglebius struct cdev *dev; 202241610Sglebius int i; 203241610Sglebius 204241610Sglebius /* Find any existing device, or allocate new unit number. */ 205241610Sglebius i = clone_create(&tapclones, &tap_cdevsw, &unit, &dev, VMNET_DEV_MASK); 206241610Sglebius if (i) { 207241610Sglebius dev = make_dev(&tap_cdevsw, unit | VMNET_DEV_MASK, UID_ROOT, 208257078Sgrehan GID_WHEEL, 0600, "%s%d", vmnetname, unit); 209241610Sglebius } 210241610Sglebius 211241610Sglebius tapcreate(dev); 212241610Sglebius return (0); 213166497Sbms} 214166497Sbms 215166497Sbmsstatic void 216166497Sbmstap_destroy(struct tap_softc *tp) 217166497Sbms{ 218166497Sbms struct ifnet *ifp = tp->tap_ifp; 219166497Sbms 220236724Strociny CURVNET_SET(ifp->if_vnet); 221240938Semaste destroy_dev(tp->tap_dev); 222225177Sattilio seldrain(&tp->tap_rsel); 223256008Sglebius knlist_clear(&tp->tap_rsel.si_note, 0); 224166497Sbms knlist_destroy(&tp->tap_rsel.si_note); 225166497Sbms ether_ifdetach(ifp); 226227459Sbrooks if_free(ifp); 227166497Sbms 228166497Sbms mtx_destroy(&tp->tap_mtx); 229166497Sbms free(tp, M_TAP); 230236724Strociny CURVNET_RESTORE(); 231166497Sbms} 232166497Sbms 233166497Sbmsstatic void 234166497Sbmstap_clone_destroy(struct ifnet *ifp) 235166497Sbms{ 236166497Sbms struct tap_softc *tp = ifp->if_softc; 237166497Sbms 238166497Sbms mtx_lock(&tapmtx); 239166497Sbms SLIST_REMOVE(&taphead, tp, tap_softc, tap_next); 240166497Sbms mtx_unlock(&tapmtx); 241166497Sbms tap_destroy(tp); 242166497Sbms} 243166497Sbms 244166497Sbms/* vmnet devices are tap devices in disguise */ 245166497Sbmsstatic void 246166497Sbmsvmnet_clone_destroy(struct ifnet *ifp) 247166497Sbms{ 248166497Sbms tap_clone_destroy(ifp); 249166497Sbms} 250166497Sbms 25163670Snsayer/* 25263670Snsayer * tapmodevent 25363670Snsayer * 25463670Snsayer * module event handler 25563670Snsayer */ 25663670Snsayerstatic int 257156783Semaxtapmodevent(module_t mod, int type, void *data) 25863670Snsayer{ 25983043Sbrooks static eventhandler_tag eh_tag = NULL; 26083043Sbrooks struct tap_softc *tp = NULL; 26183043Sbrooks struct ifnet *ifp = NULL; 26263670Snsayer 26363670Snsayer switch (type) { 26463670Snsayer case MOD_LOAD: 26563670Snsayer 26683043Sbrooks /* intitialize device */ 26783043Sbrooks 268127003Srwatson mtx_init(&tapmtx, "tapmtx", NULL, MTX_DEF); 26983043Sbrooks SLIST_INIT(&taphead); 27083043Sbrooks 271126845Sphk clone_setup(&tapclones); 27271602Sphk eh_tag = EVENTHANDLER_REGISTER(dev_clone, tapclone, 0, 1000); 273127003Srwatson if (eh_tag == NULL) { 274127170Srwatson clone_cleanup(&tapclones); 275127003Srwatson mtx_destroy(&tapmtx); 276126077Sphk return (ENOMEM); 277127003Srwatson } 278241610Sglebius tap_cloner = if_clone_simple(tapname, tap_clone_create, 279241610Sglebius tap_clone_destroy, 0); 280241610Sglebius vmnet_cloner = if_clone_simple(vmnetname, vmnet_clone_create, 281241610Sglebius vmnet_clone_destroy, 0); 28283043Sbrooks return (0); 28363670Snsayer 28483043Sbrooks case MOD_UNLOAD: 285127003Srwatson /* 286127003Srwatson * The EBUSY algorithm here can't quite atomically 287127003Srwatson * guarantee that this is race-free since we have to 288127003Srwatson * release the tap mtx to deregister the clone handler. 289127003Srwatson */ 290127003Srwatson mtx_lock(&tapmtx); 291127003Srwatson SLIST_FOREACH(tp, &taphead, tap_next) { 292127098Srwatson mtx_lock(&tp->tap_mtx); 293127003Srwatson if (tp->tap_flags & TAP_OPEN) { 294127098Srwatson mtx_unlock(&tp->tap_mtx); 295127003Srwatson mtx_unlock(&tapmtx); 29683043Sbrooks return (EBUSY); 297127003Srwatson } 298127098Srwatson mtx_unlock(&tp->tap_mtx); 299127003Srwatson } 300127003Srwatson mtx_unlock(&tapmtx); 30183043Sbrooks 30271602Sphk EVENTHANDLER_DEREGISTER(dev_clone, eh_tag); 303241610Sglebius if_clone_detach(tap_cloner); 304241610Sglebius if_clone_detach(vmnet_cloner); 305204464Skib drain_dev_clone_events(); 30663670Snsayer 307127003Srwatson mtx_lock(&tapmtx); 30883043Sbrooks while ((tp = SLIST_FIRST(&taphead)) != NULL) { 30983043Sbrooks SLIST_REMOVE_HEAD(&taphead, tap_next); 310127003Srwatson mtx_unlock(&tapmtx); 31183043Sbrooks 312147256Sbrooks ifp = tp->tap_ifp; 31383043Sbrooks 314121816Sbrooks TAPDEBUG("detaching %s\n", ifp->if_xname); 31583043Sbrooks 316166497Sbms tap_destroy(tp); 317127003Srwatson mtx_lock(&tapmtx); 31883043Sbrooks } 319127003Srwatson mtx_unlock(&tapmtx); 320126077Sphk clone_cleanup(&tapclones); 32163670Snsayer 322135354Srwatson mtx_destroy(&tapmtx); 323135354Srwatson 32483043Sbrooks break; 32563670Snsayer 32663670Snsayer default: 32763670Snsayer return (EOPNOTSUPP); 32863670Snsayer } 32963670Snsayer 33063670Snsayer return (0); 33163670Snsayer} /* tapmodevent */ 33263670Snsayer 33363670Snsayer 33463670Snsayer/* 33571602Sphk * DEVFS handler 33671602Sphk * 33771602Sphk * We need to support two kind of devices - tap and vmnet 33871602Sphk */ 33971602Sphkstatic void 340156783Semaxtapclone(void *arg, struct ucred *cred, char *name, int namelen, struct cdev **dev) 34171602Sphk{ 342166497Sbms char devname[SPECNAMELEN + 1]; 343166497Sbms int i, unit, append_unit; 344166438Sbms int extra; 34571602Sphk 346130640Sphk if (*dev != NULL) 34771602Sphk return; 34871602Sphk 349166514Sbms if (!tapdclone || 350166514Sbms (!tapuopen && priv_check_cred(cred, PRIV_NET_IFCREATE, 0) != 0)) 351166497Sbms return; 352166497Sbms 353166497Sbms unit = 0; 354166497Sbms append_unit = 0; 355126077Sphk extra = 0; 356166497Sbms 357166497Sbms /* We're interested in only tap/vmnet devices. */ 358241610Sglebius if (strcmp(name, tapname) == 0) { 359126077Sphk unit = -1; 360241610Sglebius } else if (strcmp(name, vmnetname) == 0) { 361126077Sphk unit = -1; 362126077Sphk extra = VMNET_DEV_MASK; 363241610Sglebius } else if (dev_stdclone(name, NULL, tapname, &unit) != 1) { 364241610Sglebius if (dev_stdclone(name, NULL, vmnetname, &unit) != 1) { 365126077Sphk return; 366166497Sbms } else { 367166497Sbms extra = VMNET_DEV_MASK; 368166497Sbms } 36983043Sbrooks } 37071602Sphk 371166497Sbms if (unit == -1) 372166497Sbms append_unit = 1; 373166497Sbms 374236724Strociny CURVNET_SET(CRED_TO_VNET(cred)); 375126077Sphk /* find any existing device, or allocate new unit number */ 376126077Sphk i = clone_create(&tapclones, &tap_cdevsw, &unit, dev, extra); 377126077Sphk if (i) { 378166497Sbms if (append_unit) { 379166497Sbms /* 380166497Sbms * We were passed 'tun' or 'tap', with no unit specified 381166497Sbms * so we'll need to append it now. 382166497Sbms */ 383166497Sbms namelen = snprintf(devname, sizeof(devname), "%s%d", name, 384166497Sbms unit); 385166497Sbms name = devname; 386166497Sbms } 387166497Sbms 388204464Skib *dev = make_dev_credf(MAKEDEV_REF, &tap_cdevsw, unit | extra, 389204464Skib cred, UID_ROOT, GID_WHEEL, 0600, "%s", name); 39071602Sphk } 391166497Sbms 392166497Sbms if_clone_create(name, namelen, NULL); 393236724Strociny CURVNET_RESTORE(); 39471602Sphk} /* tapclone */ 39571602Sphk 39671602Sphk 39771602Sphk/* 39863670Snsayer * tapcreate 39963670Snsayer * 40063670Snsayer * to create interface 40163670Snsayer */ 40263670Snsayerstatic void 403156783Semaxtapcreate(struct cdev *dev) 40463670Snsayer{ 40563670Snsayer struct ifnet *ifp = NULL; 40663670Snsayer struct tap_softc *tp = NULL; 40763670Snsayer unsigned short macaddr_hi; 408178221Semax uint32_t macaddr_mid; 409213028Sjhb int unit; 410241610Sglebius const char *name = NULL; 411147256Sbrooks u_char eaddr[6]; 41263670Snsayer 41363670Snsayer /* allocate driver storage and create device */ 414184205Sdes tp = malloc(sizeof(*tp), M_TAP, M_WAITOK | M_ZERO); 415127098Srwatson mtx_init(&tp->tap_mtx, "tap_mtx", NULL, MTX_DEF); 416127003Srwatson mtx_lock(&tapmtx); 41783043Sbrooks SLIST_INSERT_HEAD(&taphead, tp, tap_next); 418127003Srwatson mtx_unlock(&tapmtx); 41963670Snsayer 420126796Sphk unit = dev2unit(dev); 42183043Sbrooks 42263670Snsayer /* select device: tap or vmnet */ 423126796Sphk if (unit & VMNET_DEV_MASK) { 424241610Sglebius name = vmnetname; 42563803Snsayer tp->tap_flags |= TAP_VMNET; 42683043Sbrooks } else 427241610Sglebius name = tapname; 42863670Snsayer 429126796Sphk unit &= TAPMAXUNIT; 430126796Sphk 431183397Sed TAPDEBUG("tapcreate(%s%d). minor = %#x\n", name, unit, dev2unit(dev)); 43283043Sbrooks 43363670Snsayer /* generate fake MAC address: 00 bd xx xx xx unit_no */ 43463670Snsayer macaddr_hi = htons(0x00bd); 435178221Semax macaddr_mid = (uint32_t) ticks; 436147256Sbrooks bcopy(&macaddr_hi, eaddr, sizeof(short)); 437178221Semax bcopy(&macaddr_mid, &eaddr[2], sizeof(uint32_t)); 438147256Sbrooks eaddr[5] = (u_char)unit; 43963670Snsayer 440111742Sdes /* fill the rest and attach interface */ 441147256Sbrooks ifp = tp->tap_ifp = if_alloc(IFT_ETHER); 442147256Sbrooks if (ifp == NULL) 443147256Sbrooks panic("%s%d: can not if_alloc()", name, unit); 44463670Snsayer ifp->if_softc = tp; 445121816Sbrooks if_initname(ifp, name, unit); 44663670Snsayer ifp->if_init = tapifinit; 44763670Snsayer ifp->if_start = tapifstart; 44863670Snsayer ifp->if_ioctl = tapifioctl; 44963670Snsayer ifp->if_mtu = ETHERMTU; 45063670Snsayer ifp->if_flags = (IFF_BROADCAST|IFF_SIMPLEX|IFF_MULTICAST); 451213028Sjhb IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen); 452205222Sqingli ifp->if_capabilities |= IFCAP_LINKSTATE; 453205222Sqingli ifp->if_capenable |= IFCAP_LINKSTATE; 45463670Snsayer 45583043Sbrooks dev->si_drv1 = tp; 456126077Sphk tp->tap_dev = dev; 45783043Sbrooks 458147256Sbrooks ether_ifattach(ifp, eaddr); 45963670Snsayer 460127098Srwatson mtx_lock(&tp->tap_mtx); 46163803Snsayer tp->tap_flags |= TAP_INITED; 462127098Srwatson mtx_unlock(&tp->tap_mtx); 46363803Snsayer 464213028Sjhb knlist_init_mtx(&tp->tap_rsel.si_note, &tp->tap_mtx); 465158697Semax 466121816Sbrooks TAPDEBUG("interface %s is created. minor = %#x\n", 467183397Sed ifp->if_xname, dev2unit(dev)); 46863670Snsayer} /* tapcreate */ 46963670Snsayer 47063670Snsayer 47163670Snsayer/* 472111742Sdes * tapopen 47363670Snsayer * 47463670Snsayer * to open tunnel. must be superuser 47563670Snsayer */ 47663670Snsayerstatic int 477156783Semaxtapopen(struct cdev *dev, int flag, int mode, struct thread *td) 47863670Snsayer{ 47963670Snsayer struct tap_softc *tp = NULL; 480133460Semax struct ifnet *ifp = NULL; 481213028Sjhb int error; 48263670Snsayer 483164033Srwatson if (tapuopen == 0) { 484164033Srwatson error = priv_check(td, PRIV_NET_TAP); 485164033Srwatson if (error) 486164033Srwatson return (error); 487164033Srwatson } 48863670Snsayer 489126796Sphk if ((dev2unit(dev) & CLONE_UNITMASK) > TAPMAXUNIT) 490126796Sphk return (ENXIO); 49183043Sbrooks 49263670Snsayer tp = dev->si_drv1; 49363670Snsayer 494127165Srwatson mtx_lock(&tp->tap_mtx); 495127165Srwatson if (tp->tap_flags & TAP_OPEN) { 496127165Srwatson mtx_unlock(&tp->tap_mtx); 497127165Srwatson return (EBUSY); 498127165Srwatson } 49963670Snsayer 500152315Sru bcopy(IF_LLADDR(tp->tap_ifp), tp->ether_addr, sizeof(tp->ether_addr)); 50183366Sjulian tp->tap_pid = td->td_proc->p_pid; 50263670Snsayer tp->tap_flags |= TAP_OPEN; 503147256Sbrooks ifp = tp->tap_ifp; 50463670Snsayer 505148887Srwatson ifp->if_drv_flags |= IFF_DRV_RUNNING; 506148887Srwatson ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 507167713Sbms if (tapuponopen) 508167713Sbms ifp->if_flags |= IFF_UP; 509205024Sqingli if_link_state_change(ifp, LINK_STATE_UP); 510213028Sjhb mtx_unlock(&tp->tap_mtx); 51163670Snsayer 512183397Sed TAPDEBUG("%s is open. minor = %#x\n", ifp->if_xname, dev2unit(dev)); 513133460Semax 51463670Snsayer return (0); 51563670Snsayer} /* tapopen */ 51663670Snsayer 51763670Snsayer 51863670Snsayer/* 51963670Snsayer * tapclose 52063670Snsayer * 52163670Snsayer * close the device - mark i/f down & delete routing info 52263670Snsayer */ 52363670Snsayerstatic int 524156783Semaxtapclose(struct cdev *dev, int foo, int bar, struct thread *td) 52563670Snsayer{ 526156783Semax struct ifaddr *ifa; 52763670Snsayer struct tap_softc *tp = dev->si_drv1; 528147256Sbrooks struct ifnet *ifp = tp->tap_ifp; 52963670Snsayer 53063670Snsayer /* junk all pending output */ 531213028Sjhb mtx_lock(&tp->tap_mtx); 532236724Strociny CURVNET_SET(ifp->if_vnet); 53383043Sbrooks IF_DRAIN(&ifp->if_snd); 53463670Snsayer 53563803Snsayer /* 536281363Sglebius * Do not bring the interface down, and do not anything with 537281363Sglebius * interface, if we are in VMnet mode. Just close the device. 53863803Snsayer */ 539281363Sglebius if (((tp->tap_flags & TAP_VMNET) == 0) && 540281363Sglebius (ifp->if_flags & (IFF_UP | IFF_LINK0)) == IFF_UP) { 541127098Srwatson mtx_unlock(&tp->tap_mtx); 54263670Snsayer if_down(ifp); 543213028Sjhb mtx_lock(&tp->tap_mtx); 544148887Srwatson if (ifp->if_drv_flags & IFF_DRV_RUNNING) { 545213028Sjhb ifp->if_drv_flags &= ~IFF_DRV_RUNNING; 546213028Sjhb mtx_unlock(&tp->tap_mtx); 54763803Snsayer TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { 548146620Speadar rtinit(ifa, (int)RTM_DELETE, 0); 54963670Snsayer } 550146620Speadar if_purgeaddrs(ifp); 551213028Sjhb mtx_lock(&tp->tap_mtx); 55263670Snsayer } 553213028Sjhb } 55463670Snsayer 555205024Sqingli if_link_state_change(ifp, LINK_STATE_DOWN); 556236724Strociny CURVNET_RESTORE(); 557236724Strociny 55896122Salfred funsetown(&tp->tap_sigio); 559122352Stanimura selwakeuppri(&tp->tap_rsel, PZERO+1); 560213028Sjhb KNOTE_LOCKED(&tp->tap_rsel.si_note, 0); 56163670Snsayer 56263670Snsayer tp->tap_flags &= ~TAP_OPEN; 56363670Snsayer tp->tap_pid = 0; 564127098Srwatson mtx_unlock(&tp->tap_mtx); 56563670Snsayer 566121816Sbrooks TAPDEBUG("%s is closed. minor = %#x\n", 567183397Sed ifp->if_xname, dev2unit(dev)); 56863670Snsayer 56963670Snsayer return (0); 57063670Snsayer} /* tapclose */ 57163670Snsayer 57263670Snsayer 57363670Snsayer/* 57463670Snsayer * tapifinit 57563670Snsayer * 57663670Snsayer * network interface initialization function 57763670Snsayer */ 57863670Snsayerstatic void 579156783Semaxtapifinit(void *xtp) 58063670Snsayer{ 58163670Snsayer struct tap_softc *tp = (struct tap_softc *)xtp; 582147256Sbrooks struct ifnet *ifp = tp->tap_ifp; 58363670Snsayer 584121816Sbrooks TAPDEBUG("initializing %s\n", ifp->if_xname); 58563670Snsayer 586213028Sjhb mtx_lock(&tp->tap_mtx); 587148887Srwatson ifp->if_drv_flags |= IFF_DRV_RUNNING; 588148887Srwatson ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 589213028Sjhb mtx_unlock(&tp->tap_mtx); 59063670Snsayer 59163670Snsayer /* attempt to start output */ 59263670Snsayer tapifstart(ifp); 59363670Snsayer} /* tapifinit */ 59463670Snsayer 59563670Snsayer 59663670Snsayer/* 59763670Snsayer * tapifioctl 59863670Snsayer * 59963670Snsayer * Process an ioctl request on network interface 60063670Snsayer */ 601105228Sphkstatic int 602156783Semaxtapifioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 60363670Snsayer{ 604160376Sbrooks struct tap_softc *tp = ifp->if_softc; 605189866Sscf struct ifreq *ifr = (struct ifreq *)data; 60663670Snsayer struct ifstat *ifs = NULL; 607238183Semaste struct ifmediareq *ifmr = NULL; 608238183Semaste int dummy, error = 0; 60963670Snsayer 61063670Snsayer switch (cmd) { 61163670Snsayer case SIOCSIFFLAGS: /* XXX -- just like vmnet does */ 61263670Snsayer case SIOCADDMULTI: 61363670Snsayer case SIOCDELMULTI: 61483043Sbrooks break; 61563670Snsayer 616238183Semaste case SIOCGIFMEDIA: 617238183Semaste ifmr = (struct ifmediareq *)data; 618238183Semaste dummy = ifmr->ifm_count; 619238183Semaste ifmr->ifm_count = 1; 620238183Semaste ifmr->ifm_status = IFM_AVALID; 621238183Semaste ifmr->ifm_active = IFM_ETHER; 622238183Semaste if (tp->tap_flags & TAP_OPEN) 623238183Semaste ifmr->ifm_status |= IFM_ACTIVE; 624238183Semaste ifmr->ifm_current = ifmr->ifm_active; 625238183Semaste if (dummy >= 1) { 626238183Semaste int media = IFM_ETHER; 627238183Semaste error = copyout(&media, ifmr->ifm_ulist, 628238183Semaste sizeof(int)); 629238183Semaste } 630238183Semaste break; 631238183Semaste 632189866Sscf case SIOCSIFMTU: 633189866Sscf ifp->if_mtu = ifr->ifr_mtu; 634189866Sscf break; 635189866Sscf 63663670Snsayer case SIOCGIFSTATUS: 63763670Snsayer ifs = (struct ifstat *)data; 638127098Srwatson mtx_lock(&tp->tap_mtx); 639260394Smelifaro if (tp->tap_pid != 0) 640260394Smelifaro snprintf(ifs->ascii, sizeof(ifs->ascii), 64163670Snsayer "\tOpened by PID %d\n", tp->tap_pid); 642260394Smelifaro else 643260394Smelifaro ifs->ascii[0] = '\0'; 644127098Srwatson mtx_unlock(&tp->tap_mtx); 64583043Sbrooks break; 64663670Snsayer 64763670Snsayer default: 648238183Semaste error = ether_ioctl(ifp, cmd, data); 649238183Semaste break; 65063670Snsayer } 65163670Snsayer 652238183Semaste return (error); 65363670Snsayer} /* tapifioctl */ 65463670Snsayer 65563670Snsayer 65663670Snsayer/* 657111742Sdes * tapifstart 658111742Sdes * 65963670Snsayer * queue packets from higher level ready to put out 66063670Snsayer */ 66163670Snsayerstatic void 662156783Semaxtapifstart(struct ifnet *ifp) 66363670Snsayer{ 66463670Snsayer struct tap_softc *tp = ifp->if_softc; 66563670Snsayer 666121816Sbrooks TAPDEBUG("%s starting\n", ifp->if_xname); 66763670Snsayer 66863803Snsayer /* 66963803Snsayer * do not junk pending output if we are in VMnet mode. 67063803Snsayer * XXX: can this do any harm because of queue overflow? 67163803Snsayer */ 67263803Snsayer 673127098Srwatson mtx_lock(&tp->tap_mtx); 674111742Sdes if (((tp->tap_flags & TAP_VMNET) == 0) && 67563803Snsayer ((tp->tap_flags & TAP_READY) != TAP_READY)) { 676213028Sjhb struct mbuf *m; 67763670Snsayer 678127098Srwatson /* Unlocked read. */ 679121816Sbrooks TAPDEBUG("%s not ready, tap_flags = 0x%x\n", ifp->if_xname, 680121816Sbrooks tp->tap_flags); 68163670Snsayer 682213028Sjhb for (;;) { 68363670Snsayer IF_DEQUEUE(&ifp->if_snd, m); 684213028Sjhb if (m != NULL) { 68563670Snsayer m_freem(m); 686271867Sglebius if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); 687213028Sjhb } else 688213028Sjhb break; 689213028Sjhb } 690213028Sjhb mtx_unlock(&tp->tap_mtx); 69163670Snsayer 69263670Snsayer return; 69363670Snsayer } 69463670Snsayer 695148887Srwatson ifp->if_drv_flags |= IFF_DRV_OACTIVE; 69663670Snsayer 697213028Sjhb if (!IFQ_IS_EMPTY(&ifp->if_snd)) { 69863670Snsayer if (tp->tap_flags & TAP_RWAIT) { 69963670Snsayer tp->tap_flags &= ~TAP_RWAIT; 700111748Sdes wakeup(tp); 70163670Snsayer } 70263670Snsayer 703127098Srwatson if ((tp->tap_flags & TAP_ASYNC) && (tp->tap_sigio != NULL)) { 704127098Srwatson mtx_unlock(&tp->tap_mtx); 70595883Salfred pgsigio(&tp->tap_sigio, SIGIO, 0); 706213028Sjhb mtx_lock(&tp->tap_mtx); 707213028Sjhb } 70863670Snsayer 709122352Stanimura selwakeuppri(&tp->tap_rsel, PZERO+1); 710213028Sjhb KNOTE_LOCKED(&tp->tap_rsel.si_note, 0); 711271867Sglebius if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); /* obytes are counted in ether_output */ 71263670Snsayer } 71363670Snsayer 714148887Srwatson ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 715213028Sjhb mtx_unlock(&tp->tap_mtx); 71663670Snsayer} /* tapifstart */ 71763670Snsayer 71863670Snsayer 71963670Snsayer/* 72063670Snsayer * tapioctl 72163670Snsayer * 72263670Snsayer * the cdevsw interface is now pretty minimal 72363670Snsayer */ 72463670Snsayerstatic int 725156783Semaxtapioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td) 72663670Snsayer{ 727341884Shselasky struct ifreq ifr; 72863670Snsayer struct tap_softc *tp = dev->si_drv1; 729147256Sbrooks struct ifnet *ifp = tp->tap_ifp; 730111742Sdes struct tapinfo *tapp = NULL; 731102052Ssobomax int f; 732341884Shselasky int error; 733162711Sru#if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5) || \ 734162711Sru defined(COMPAT_FREEBSD4) 735162711Sru int ival; 736162711Sru#endif 73763670Snsayer 73863670Snsayer switch (cmd) { 739111742Sdes case TAPSIFINFO: 740111742Sdes tapp = (struct tapinfo *)data; 741326691Shselasky if (ifp->if_type != tapp->type) 742326691Shselasky return (EPROTOTYPE); 743213028Sjhb mtx_lock(&tp->tap_mtx); 744341884Shselasky if (ifp->if_mtu != tapp->mtu) { 745347376Skevans strlcpy(ifr.ifr_name, if_name(ifp), IFNAMSIZ); 746341884Shselasky ifr.ifr_mtu = tapp->mtu; 747341884Shselasky CURVNET_SET(ifp->if_vnet); 748341884Shselasky error = ifhwioctl(SIOCSIFMTU, ifp, 749341884Shselasky (caddr_t)&ifr, td); 750341884Shselasky CURVNET_RESTORE(); 751341884Shselasky if (error) { 752341884Shselasky mtx_unlock(&tp->tap_mtx); 753341884Shselasky return (error); 754341884Shselasky } 755341884Shselasky } 756111742Sdes ifp->if_baudrate = tapp->baudrate; 757213028Sjhb mtx_unlock(&tp->tap_mtx); 758111742Sdes break; 75963670Snsayer 760111742Sdes case TAPGIFINFO: 761111742Sdes tapp = (struct tapinfo *)data; 762213028Sjhb mtx_lock(&tp->tap_mtx); 763111742Sdes tapp->mtu = ifp->if_mtu; 764111742Sdes tapp->type = ifp->if_type; 765111742Sdes tapp->baudrate = ifp->if_baudrate; 766213028Sjhb mtx_unlock(&tp->tap_mtx); 767111742Sdes break; 76863670Snsayer 76963670Snsayer case TAPSDEBUG: 770159079Smarius tapdebug = *(int *)data; 77183043Sbrooks break; 77263670Snsayer 77363670Snsayer case TAPGDEBUG: 774159079Smarius *(int *)data = tapdebug; 77583043Sbrooks break; 77663670Snsayer 777182880Semax case TAPGIFNAME: { 778182880Semax struct ifreq *ifr = (struct ifreq *) data; 779182880Semax 780182880Semax strlcpy(ifr->ifr_name, ifp->if_xname, IFNAMSIZ); 781182880Semax } break; 782182880Semax 78363670Snsayer case FIONBIO: 78483043Sbrooks break; 78563670Snsayer 78663670Snsayer case FIOASYNC: 787127098Srwatson mtx_lock(&tp->tap_mtx); 788159079Smarius if (*(int *)data) 78963670Snsayer tp->tap_flags |= TAP_ASYNC; 79063670Snsayer else 79163670Snsayer tp->tap_flags &= ~TAP_ASYNC; 792127098Srwatson mtx_unlock(&tp->tap_mtx); 79383043Sbrooks break; 79463670Snsayer 79563670Snsayer case FIONREAD: 796213028Sjhb if (!IFQ_IS_EMPTY(&ifp->if_snd)) { 797213028Sjhb struct mbuf *mb; 79863670Snsayer 799213028Sjhb IFQ_LOCK(&ifp->if_snd); 800213028Sjhb IFQ_POLL_NOLOCK(&ifp->if_snd, mb); 801213028Sjhb for (*(int *)data = 0; mb != NULL; 802213028Sjhb mb = mb->m_next) 803159079Smarius *(int *)data += mb->m_len; 804213028Sjhb IFQ_UNLOCK(&ifp->if_snd); 80583043Sbrooks } else 806159079Smarius *(int *)data = 0; 80783043Sbrooks break; 80863670Snsayer 80963670Snsayer case FIOSETOWN: 810159079Smarius return (fsetown(*(int *)data, &tp->tap_sigio)); 81163670Snsayer 81263670Snsayer case FIOGETOWN: 813159079Smarius *(int *)data = fgetown(&tp->tap_sigio); 81463670Snsayer return (0); 81563670Snsayer 81663670Snsayer /* this is deprecated, FIOSETOWN should be used instead */ 81763670Snsayer case TIOCSPGRP: 818159079Smarius return (fsetown(-(*(int *)data), &tp->tap_sigio)); 81963670Snsayer 82063670Snsayer /* this is deprecated, FIOGETOWN should be used instead */ 82163670Snsayer case TIOCGPGRP: 822159079Smarius *(int *)data = -fgetown(&tp->tap_sigio); 82363670Snsayer return (0); 82463670Snsayer 82563670Snsayer /* VMware/VMnet port ioctl's */ 82663670Snsayer 827162711Sru#if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5) || \ 828162711Sru defined(COMPAT_FREEBSD4) 829162711Sru case _IO('V', 0): 830162711Sru ival = IOCPARM_IVAL(data); 831162711Sru data = (caddr_t)&ival; 832162711Sru /* FALLTHROUGH */ 833162711Sru#endif 83483043Sbrooks case VMIO_SIOCSIFFLAGS: /* VMware/VMnet SIOCSIFFLAGS */ 835162711Sru f = *(int *)data; 83663670Snsayer f &= 0x0fff; 83763670Snsayer f &= ~IFF_CANTCHANGE; 83863670Snsayer f |= IFF_UP; 83963670Snsayer 840213028Sjhb mtx_lock(&tp->tap_mtx); 84163670Snsayer ifp->if_flags = f | (ifp->if_flags & IFF_CANTCHANGE); 842213028Sjhb mtx_unlock(&tp->tap_mtx); 84383043Sbrooks break; 84463670Snsayer 845257696Sglebius case SIOCGIFADDR: /* get MAC address of the remote side */ 846127165Srwatson mtx_lock(&tp->tap_mtx); 84763861Snsayer bcopy(tp->ether_addr, data, sizeof(tp->ether_addr)); 848127165Srwatson mtx_unlock(&tp->tap_mtx); 84983043Sbrooks break; 85063670Snsayer 85163861Snsayer case SIOCSIFADDR: /* set MAC address of the remote side */ 852127165Srwatson mtx_lock(&tp->tap_mtx); 85363861Snsayer bcopy(data, tp->ether_addr, sizeof(tp->ether_addr)); 854127165Srwatson mtx_unlock(&tp->tap_mtx); 85583043Sbrooks break; 85663670Snsayer 85763670Snsayer default: 85863670Snsayer return (ENOTTY); 85963670Snsayer } 86063670Snsayer return (0); 86163670Snsayer} /* tapioctl */ 86263670Snsayer 86363670Snsayer 86463670Snsayer/* 86563670Snsayer * tapread 86663670Snsayer * 86763670Snsayer * the cdevsw read interface - reads a packet at a time, or at 86863670Snsayer * least as much of a packet as can be read 86963670Snsayer */ 87063670Snsayerstatic int 871156783Semaxtapread(struct cdev *dev, struct uio *uio, int flag) 87263670Snsayer{ 87363670Snsayer struct tap_softc *tp = dev->si_drv1; 874147256Sbrooks struct ifnet *ifp = tp->tap_ifp; 87590227Sdillon struct mbuf *m = NULL; 876213028Sjhb int error = 0, len; 87763670Snsayer 878183397Sed TAPDEBUG("%s reading, minor = %#x\n", ifp->if_xname, dev2unit(dev)); 87963670Snsayer 880127098Srwatson mtx_lock(&tp->tap_mtx); 88163670Snsayer if ((tp->tap_flags & TAP_READY) != TAP_READY) { 882127098Srwatson mtx_unlock(&tp->tap_mtx); 883127098Srwatson 884127098Srwatson /* Unlocked read. */ 885121816Sbrooks TAPDEBUG("%s not ready. minor = %#x, tap_flags = 0x%x\n", 886183397Sed ifp->if_xname, dev2unit(dev), tp->tap_flags); 88763803Snsayer 88863670Snsayer return (EHOSTDOWN); 88963670Snsayer } 89063670Snsayer 89163670Snsayer tp->tap_flags &= ~TAP_RWAIT; 89263670Snsayer 89363670Snsayer /* sleep until we get a packet */ 89463670Snsayer do { 89590227Sdillon IF_DEQUEUE(&ifp->if_snd, m); 89663670Snsayer 89790227Sdillon if (m == NULL) { 898213028Sjhb if (flag & O_NONBLOCK) { 899213028Sjhb mtx_unlock(&tp->tap_mtx); 90063670Snsayer return (EWOULDBLOCK); 901213028Sjhb } 902111742Sdes 90363670Snsayer tp->tap_flags |= TAP_RWAIT; 904213028Sjhb error = mtx_sleep(tp, &tp->tap_mtx, PCATCH | (PZERO + 1), 905213028Sjhb "taprd", 0); 906213028Sjhb if (error) { 907213028Sjhb mtx_unlock(&tp->tap_mtx); 90863670Snsayer return (error); 909213028Sjhb } 91063670Snsayer } 91190227Sdillon } while (m == NULL); 912213028Sjhb mtx_unlock(&tp->tap_mtx); 91363670Snsayer 91463670Snsayer /* feed packet to bpf */ 915106939Ssam BPF_MTAP(ifp, m); 91663670Snsayer 91763670Snsayer /* xfer packet to user space */ 91890227Sdillon while ((m != NULL) && (uio->uio_resid > 0) && (error == 0)) { 91990227Sdillon len = min(uio->uio_resid, m->m_len); 92063670Snsayer if (len == 0) 92163670Snsayer break; 92263670Snsayer 923111741Sdes error = uiomove(mtod(m, void *), len, uio); 92490227Sdillon m = m_free(m); 92563670Snsayer } 92663670Snsayer 92790227Sdillon if (m != NULL) { 928121816Sbrooks TAPDEBUG("%s dropping mbuf, minor = %#x\n", ifp->if_xname, 929183397Sed dev2unit(dev)); 93090227Sdillon m_freem(m); 93163670Snsayer } 93263670Snsayer 93363670Snsayer return (error); 93463670Snsayer} /* tapread */ 93563670Snsayer 93663670Snsayer 93763670Snsayer/* 93863670Snsayer * tapwrite 93963670Snsayer * 94063670Snsayer * the cdevsw write interface - an atomic write is a packet - or else! 94163670Snsayer */ 94263670Snsayerstatic int 943156783Semaxtapwrite(struct cdev *dev, struct uio *uio, int flag) 94463670Snsayer{ 945166443Sbms struct ether_header *eh; 94663670Snsayer struct tap_softc *tp = dev->si_drv1; 947147256Sbrooks struct ifnet *ifp = tp->tap_ifp; 948137101Sglebius struct mbuf *m; 94963670Snsayer 950240945Semaste TAPDEBUG("%s writing, minor = %#x\n", 951183397Sed ifp->if_xname, dev2unit(dev)); 95263670Snsayer 95363670Snsayer if (uio->uio_resid == 0) 95463670Snsayer return (0); 95563670Snsayer 95663670Snsayer if ((uio->uio_resid < 0) || (uio->uio_resid > TAPMRU)) { 957194990Skib TAPDEBUG("%s invalid packet len = %zd, minor = %#x\n", 958183397Sed ifp->if_xname, uio->uio_resid, dev2unit(dev)); 95963803Snsayer 96063670Snsayer return (EIO); 96163670Snsayer } 96263670Snsayer 963243882Sglebius if ((m = m_uiotombuf(uio, M_NOWAIT, 0, ETHER_ALIGN, 964163915Sandre M_PKTHDR)) == NULL) { 965271867Sglebius if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); 966163986Scsjp return (ENOBUFS); 96763670Snsayer } 96863670Snsayer 969137101Sglebius m->m_pkthdr.rcvif = ifp; 970111742Sdes 971166443Sbms /* 972166443Sbms * Only pass a unicast frame to ether_input(), if it would actually 973166443Sbms * have been received by non-virtual hardware. 974166443Sbms */ 975166443Sbms if (m->m_len < sizeof(struct ether_header)) { 976166443Sbms m_freem(m); 977166443Sbms return (0); 978166443Sbms } 979166443Sbms eh = mtod(m, struct ether_header *); 980166443Sbms 981166443Sbms if (eh && (ifp->if_flags & IFF_PROMISC) == 0 && 982166443Sbms !ETHER_IS_MULTICAST(eh->ether_dhost) && 983166443Sbms bcmp(eh->ether_dhost, IF_LLADDR(ifp), ETHER_ADDR_LEN) != 0) { 984166443Sbms m_freem(m); 985166443Sbms return (0); 986166443Sbms } 987166443Sbms 988106939Ssam /* Pass packet up to parent. */ 989236724Strociny CURVNET_SET(ifp->if_vnet); 990137101Sglebius (*ifp->if_input)(ifp, m); 991236724Strociny CURVNET_RESTORE(); 992271867Sglebius if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1); /* ibytes are counted in parent */ 99363670Snsayer 99463670Snsayer return (0); 99563670Snsayer} /* tapwrite */ 99663670Snsayer 99763670Snsayer 99863670Snsayer/* 99963670Snsayer * tappoll 100063670Snsayer * 100163670Snsayer * the poll interface, this is only useful on reads 100263670Snsayer * really. the write detect always returns true, write never blocks 100363670Snsayer * anyway, it either accepts the packet or drops it 100463670Snsayer */ 100563670Snsayerstatic int 1006156783Semaxtappoll(struct cdev *dev, int events, struct thread *td) 100763670Snsayer{ 100863670Snsayer struct tap_softc *tp = dev->si_drv1; 1009147256Sbrooks struct ifnet *ifp = tp->tap_ifp; 1010213028Sjhb int revents = 0; 101163670Snsayer 1012121816Sbrooks TAPDEBUG("%s polling, minor = %#x\n", 1013183397Sed ifp->if_xname, dev2unit(dev)); 101463670Snsayer 101563670Snsayer if (events & (POLLIN | POLLRDNORM)) { 1016213028Sjhb IFQ_LOCK(&ifp->if_snd); 1017213028Sjhb if (!IFQ_IS_EMPTY(&ifp->if_snd)) { 1018121816Sbrooks TAPDEBUG("%s have data in queue. len = %d, " \ 1019121816Sbrooks "minor = %#x\n", ifp->if_xname, 1020183397Sed ifp->if_snd.ifq_len, dev2unit(dev)); 102163803Snsayer 102263670Snsayer revents |= (events & (POLLIN | POLLRDNORM)); 102383043Sbrooks } else { 1024121816Sbrooks TAPDEBUG("%s waiting for data, minor = %#x\n", 1025183397Sed ifp->if_xname, dev2unit(dev)); 102663803Snsayer 102783805Sjhb selrecord(td, &tp->tap_rsel); 102863670Snsayer } 1029213028Sjhb IFQ_UNLOCK(&ifp->if_snd); 103063670Snsayer } 103163670Snsayer 103263670Snsayer if (events & (POLLOUT | POLLWRNORM)) 103363670Snsayer revents |= (events & (POLLOUT | POLLWRNORM)); 103463670Snsayer 103563670Snsayer return (revents); 103663670Snsayer} /* tappoll */ 1037156783Semax 1038156783Semax 1039156783Semax/* 1040156783Semax * tap_kqfilter 1041156783Semax * 1042156783Semax * support for kevent() system call 1043156783Semax */ 1044156783Semaxstatic int 1045156783Semaxtapkqfilter(struct cdev *dev, struct knote *kn) 1046156783Semax{ 1047156783Semax struct tap_softc *tp = dev->si_drv1; 1048156783Semax struct ifnet *ifp = tp->tap_ifp; 1049156783Semax 1050156783Semax switch (kn->kn_filter) { 1051156783Semax case EVFILT_READ: 1052156783Semax TAPDEBUG("%s kqfilter: EVFILT_READ, minor = %#x\n", 1053183397Sed ifp->if_xname, dev2unit(dev)); 1054156783Semax kn->kn_fop = &tap_read_filterops; 1055156783Semax break; 1056156783Semax 1057156783Semax case EVFILT_WRITE: 1058156783Semax TAPDEBUG("%s kqfilter: EVFILT_WRITE, minor = %#x\n", 1059183397Sed ifp->if_xname, dev2unit(dev)); 1060156783Semax kn->kn_fop = &tap_write_filterops; 1061156783Semax break; 1062156783Semax 1063156783Semax default: 1064156783Semax TAPDEBUG("%s kqfilter: invalid filter, minor = %#x\n", 1065183397Sed ifp->if_xname, dev2unit(dev)); 1066156783Semax return (EINVAL); 1067156783Semax /* NOT REACHED */ 1068156783Semax } 1069156783Semax 1070213028Sjhb kn->kn_hook = tp; 1071156783Semax knlist_add(&tp->tap_rsel.si_note, kn, 0); 1072156783Semax 1073156783Semax return (0); 1074156783Semax} /* tapkqfilter */ 1075156783Semax 1076156783Semax 1077156783Semax/* 1078156783Semax * tap_kqread 1079156783Semax * 1080156783Semax * Return true if there is data in the interface queue 1081156783Semax */ 1082156783Semaxstatic int 1083156783Semaxtapkqread(struct knote *kn, long hint) 1084156783Semax{ 1085213028Sjhb int ret; 1086213028Sjhb struct tap_softc *tp = kn->kn_hook; 1087213028Sjhb struct cdev *dev = tp->tap_dev; 1088156783Semax struct ifnet *ifp = tp->tap_ifp; 1089156783Semax 1090156783Semax if ((kn->kn_data = ifp->if_snd.ifq_len) > 0) { 1091156783Semax TAPDEBUG("%s have data in queue. len = %d, minor = %#x\n", 1092183397Sed ifp->if_xname, ifp->if_snd.ifq_len, dev2unit(dev)); 1093156783Semax ret = 1; 1094156783Semax } else { 1095156783Semax TAPDEBUG("%s waiting for data, minor = %#x\n", 1096183397Sed ifp->if_xname, dev2unit(dev)); 1097156783Semax ret = 0; 1098156783Semax } 1099156783Semax 1100156783Semax return (ret); 1101156783Semax} /* tapkqread */ 1102156783Semax 1103156783Semax 1104156783Semax/* 1105156783Semax * tap_kqwrite 1106156783Semax * 1107156783Semax * Always can write. Return the MTU in kn->data 1108156783Semax */ 1109156783Semaxstatic int 1110156783Semaxtapkqwrite(struct knote *kn, long hint) 1111156783Semax{ 1112213028Sjhb struct tap_softc *tp = kn->kn_hook; 1113156783Semax struct ifnet *ifp = tp->tap_ifp; 1114156783Semax 1115156783Semax kn->kn_data = ifp->if_mtu; 1116156783Semax 1117156783Semax return (1); 1118156783Semax} /* tapkqwrite */ 1119156783Semax 1120156783Semax 1121156783Semaxstatic void 1122156783Semaxtapkqdetach(struct knote *kn) 1123156783Semax{ 1124213028Sjhb struct tap_softc *tp = kn->kn_hook; 1125156783Semax 1126156783Semax knlist_remove(&tp->tap_rsel.si_note, kn, 0); 1127156783Semax} /* tapkqdetach */ 1128156783Semax 1129