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