if_tun.c revision 205222
161560Sn_hibma/* $NetBSD: if_tun.c,v 1.14 1994/06/29 06:36:25 cgd Exp $ */ 261560Sn_hibma 361560Sn_hibma/*- 461560Sn_hibma * Copyright (c) 1988, Julian Onions <jpo@cs.nott.ac.uk> 561560Sn_hibma * Nottingham University 1987. 661560Sn_hibma * 761560Sn_hibma * This source may be freely distributed, however I would be interested 861560Sn_hibma * in any changes that are made. 961560Sn_hibma * 1061560Sn_hibma * This driver takes packets off the IP i/f and hands them up to a 1161560Sn_hibma * user process to have its wicked way with. This driver has it's 1261560Sn_hibma * roots in a similar driver written by Phil Cockcroft (formerly) at 1361560Sn_hibma * UCL. This driver is based much more on read/write/poll mode of 1461560Sn_hibma * operation though. 1561560Sn_hibma * 1661560Sn_hibma * $FreeBSD: head/sys/net/if_tun.c 205222 2010-03-16 17:59:12Z qingli $ 1761560Sn_hibma */ 1861560Sn_hibma 1961560Sn_hibma#include "opt_atalk.h" 2061560Sn_hibma#include "opt_inet.h" 2161560Sn_hibma#include "opt_inet6.h" 22163675Smarkus#include "opt_ipx.h" 2361560Sn_hibma 2461560Sn_hibma#include <sys/param.h> 2561560Sn_hibma#include <sys/priv.h> 2661560Sn_hibma#include <sys/proc.h> 2761560Sn_hibma#include <sys/systm.h> 2861560Sn_hibma#include <sys/jail.h> 2961560Sn_hibma#include <sys/mbuf.h> 3061560Sn_hibma#include <sys/module.h> 3161560Sn_hibma#include <sys/socket.h> 3261560Sn_hibma#include <sys/fcntl.h> 3361560Sn_hibma#include <sys/filio.h> 3461560Sn_hibma#include <sys/sockio.h> 3561560Sn_hibma#include <sys/ttycom.h> 36163675Smarkus#include <sys/poll.h> 37163675Smarkus#include <sys/selinfo.h> 3861560Sn_hibma#include <sys/signalvar.h> 3961560Sn_hibma#include <sys/filedesc.h> 4061560Sn_hibma#include <sys/kernel.h> 4161560Sn_hibma#include <sys/sysctl.h> 4261560Sn_hibma#include <sys/conf.h> 4361560Sn_hibma#include <sys/uio.h> 4461560Sn_hibma#include <sys/malloc.h> 45163675Smarkus#include <sys/random.h> 46163675Smarkus 4761560Sn_hibma#include <net/if.h> 4861560Sn_hibma#include <net/if_clone.h> 4961560Sn_hibma#include <net/if_types.h> 5061560Sn_hibma#include <net/netisr.h> 5161560Sn_hibma#include <net/route.h> 5261560Sn_hibma#include <net/vnet.h> 5361560Sn_hibma#ifdef INET 5461560Sn_hibma#include <netinet/in.h> 5561560Sn_hibma#endif 5661560Sn_hibma#include <net/bpf.h> 5761560Sn_hibma#include <net/if_tun.h> 5861560Sn_hibma 5961560Sn_hibma#include <sys/queue.h> 6061560Sn_hibma#include <sys/condvar.h> 61163675Smarkus 62163675Smarkus#include <security/mac/mac_framework.h> 6361560Sn_hibma 6461560Sn_hibma/* 6561560Sn_hibma * tun_list is protected by global tunmtx. Other mutable fields are 6661560Sn_hibma * protected by tun->tun_mtx, or by their owning subsystem. tun_dev is 67163675Smarkus * static for the duration of a tunnel interface. 68163675Smarkus */ 69163675Smarkusstruct tun_softc { 70163675Smarkus TAILQ_ENTRY(tun_softc) tun_list; 71163675Smarkus struct cdev *tun_dev; 72163675Smarkus u_short tun_flags; /* misc flags */ 73163675Smarkus#define TUN_OPEN 0x0001 74163675Smarkus#define TUN_INITED 0x0002 75163675Smarkus#define TUN_RCOLL 0x0004 76163675Smarkus#define TUN_IASET 0x0008 77163675Smarkus#define TUN_DSTADDR 0x0010 78163675Smarkus#define TUN_LMODE 0x0020 79163675Smarkus#define TUN_RWAIT 0x0040 80163675Smarkus#define TUN_ASYNC 0x0080 81163675Smarkus#define TUN_IFHEAD 0x0100 82163675Smarkus 83163675Smarkus#define TUN_READY (TUN_OPEN | TUN_INITED) 8461560Sn_hibma 8561560Sn_hibma /* 8661560Sn_hibma * XXXRW: tun_pid is used to exclusively lock /dev/tun. Is this 8761560Sn_hibma * actually needed? Can we just return EBUSY if already open? 8861560Sn_hibma * Problem is that this involved inherent races when a tun device 8961560Sn_hibma * is handed off from one process to another, as opposed to just 9061560Sn_hibma * being slightly stale informationally. 9161560Sn_hibma */ 9261560Sn_hibma pid_t tun_pid; /* owning pid */ 9361560Sn_hibma struct ifnet *tun_ifp; /* the interface */ 9461560Sn_hibma struct sigio *tun_sigio; /* information for async I/O */ 9561560Sn_hibma struct selinfo tun_rsel; /* read select */ 9661560Sn_hibma struct mtx tun_mtx; /* protect mutable softc fields */ 9761560Sn_hibma struct cv tun_cv; /* protect against ref'd dev destroy */ 98163675Smarkus}; 9961560Sn_hibma#define TUN2IFP(sc) ((sc)->tun_ifp) 10061560Sn_hibma 10161560Sn_hibma#define TUNDEBUG if (tundebug) if_printf 10261560Sn_hibma#define TUNNAME "tun" 10361560Sn_hibma 10461560Sn_hibma/* 105163675Smarkus * All mutable global variables in if_tun are locked using tunmtx, with 10661560Sn_hibma * the exception of tundebug, which is used unlocked, and tunclones, 10761560Sn_hibma * which is static after setup. 10861560Sn_hibma */ 109163675Smarkusstatic struct mtx tunmtx; 11061560Sn_hibmastatic MALLOC_DEFINE(M_TUN, TUNNAME, "Tunnel Interface"); 11161560Sn_hibmastatic int tundebug = 0; 11261560Sn_hibmastatic int tundclone = 1; 113163675Smarkusstatic struct clonedevs *tunclones; 11461560Sn_hibmastatic TAILQ_HEAD(,tun_softc) tunhead = TAILQ_HEAD_INITIALIZER(tunhead); 11561560Sn_hibmaSYSCTL_INT(_debug, OID_AUTO, if_tun_debug, CTLFLAG_RW, &tundebug, 0, ""); 11661560Sn_hibma 11761560Sn_hibmaSYSCTL_DECL(_net_link); 11861560Sn_hibmaSYSCTL_NODE(_net_link, OID_AUTO, tun, CTLFLAG_RW, 0, 11961560Sn_hibma "IP tunnel software network interface."); 12061560Sn_hibmaSYSCTL_INT(_net_link_tun, OID_AUTO, devfs_cloning, CTLFLAG_RW, &tundclone, 0, 12161560Sn_hibma "Enable legacy devfs interface creation."); 12261560Sn_hibma 12361560Sn_hibmaTUNABLE_INT("net.link.tun.devfs_cloning", &tundclone); 12461560Sn_hibma 12561560Sn_hibmastatic void tunclone(void *arg, struct ucred *cred, char *name, 12661560Sn_hibma int namelen, struct cdev **dev); 12761560Sn_hibmastatic void tuncreate(const char *name, struct cdev *dev); 12861560Sn_hibmastatic int tunifioctl(struct ifnet *, u_long, caddr_t); 12961560Sn_hibmastatic int tuninit(struct ifnet *); 13061560Sn_hibmastatic int tunmodevent(module_t, int, void *); 13161560Sn_hibmastatic int tunoutput(struct ifnet *, struct mbuf *, struct sockaddr *, 13261560Sn_hibma struct route *ro); 13361560Sn_hibmastatic void tunstart(struct ifnet *); 13461560Sn_hibma 13561560Sn_hibmastatic int tun_clone_create(struct if_clone *, int, caddr_t); 13661560Sn_hibmastatic void tun_clone_destroy(struct ifnet *); 13761560Sn_hibma 13861560Sn_hibmaIFC_SIMPLE_DECLARE(tun, 0); 13961560Sn_hibma 14061560Sn_hibmastatic d_open_t tunopen; 14161560Sn_hibmastatic d_close_t tunclose; 14261560Sn_hibmastatic d_read_t tunread; 14361560Sn_hibmastatic d_write_t tunwrite; 14461560Sn_hibmastatic d_ioctl_t tunioctl; 14561560Sn_hibmastatic d_poll_t tunpoll; 14661560Sn_hibmastatic d_kqfilter_t tunkqfilter; 14761560Sn_hibma 14861560Sn_hibmastatic int tunkqread(struct knote *, long); 14961560Sn_hibmastatic int tunkqwrite(struct knote *, long); 15061560Sn_hibmastatic void tunkqdetach(struct knote *); 15161560Sn_hibma 15261560Sn_hibmastatic struct filterops tun_read_filterops = { 15361560Sn_hibma .f_isfd = 1, 15461560Sn_hibma .f_attach = NULL, 15561560Sn_hibma .f_detach = tunkqdetach, 15661560Sn_hibma .f_event = tunkqread, 15761560Sn_hibma}; 15861560Sn_hibma 15961560Sn_hibmastatic struct filterops tun_write_filterops = { 16061560Sn_hibma .f_isfd = 1, 16161560Sn_hibma .f_attach = NULL, 16261560Sn_hibma .f_detach = tunkqdetach, 16361560Sn_hibma .f_event = tunkqwrite, 16461560Sn_hibma}; 16561560Sn_hibma 16661560Sn_hibmastatic struct cdevsw tun_cdevsw = { 16761560Sn_hibma .d_version = D_VERSION, 16861560Sn_hibma .d_flags = D_PSEUDO | D_NEEDGIANT | D_NEEDMINOR, 16961560Sn_hibma .d_open = tunopen, 17061560Sn_hibma .d_close = tunclose, 17161560Sn_hibma .d_read = tunread, 17261560Sn_hibma .d_write = tunwrite, 17361560Sn_hibma .d_ioctl = tunioctl, 17461560Sn_hibma .d_poll = tunpoll, 17561560Sn_hibma .d_kqfilter = tunkqfilter, 17661560Sn_hibma .d_name = TUNNAME, 17761560Sn_hibma}; 17861560Sn_hibma 17961560Sn_hibmastatic int 18061560Sn_hibmatun_clone_create(struct if_clone *ifc, int unit, caddr_t params) 18161560Sn_hibma{ 18261560Sn_hibma struct cdev *dev; 18361560Sn_hibma int i; 18461560Sn_hibma 18561560Sn_hibma /* find any existing device, or allocate new unit number */ 18661560Sn_hibma i = clone_create(&tunclones, &tun_cdevsw, &unit, &dev, 0); 18761560Sn_hibma if (i) { 18861560Sn_hibma /* No preexisting struct cdev *, create one */ 18961560Sn_hibma dev = make_dev(&tun_cdevsw, unit, 19061560Sn_hibma UID_UUCP, GID_DIALER, 0600, "%s%d", ifc->ifc_name, unit); 19161560Sn_hibma } 19261560Sn_hibma tuncreate(ifc->ifc_name, dev); 19361560Sn_hibma 19461560Sn_hibma return (0); 19561560Sn_hibma} 19661560Sn_hibma 19761560Sn_hibmastatic void 19861560Sn_hibmatunclone(void *arg, struct ucred *cred, char *name, int namelen, 199163675Smarkus struct cdev **dev) 200163675Smarkus{ 20161560Sn_hibma char devname[SPECNAMELEN + 1]; 20261560Sn_hibma int u, i, append_unit; 20361560Sn_hibma 20461560Sn_hibma if (*dev != NULL) 20561560Sn_hibma return; 20661560Sn_hibma 20761560Sn_hibma /* 20861560Sn_hibma * If tun cloning is enabled, only the superuser can create an 20961560Sn_hibma * interface. 21061560Sn_hibma */ 21161560Sn_hibma if (!tundclone || priv_check_cred(cred, PRIV_NET_IFCREATE, 0) != 0) 21261560Sn_hibma return; 21361560Sn_hibma 21461560Sn_hibma if (strcmp(name, TUNNAME) == 0) { 21561560Sn_hibma u = -1; 21661560Sn_hibma } else if (dev_stdclone(name, NULL, TUNNAME, &u) != 1) 21761560Sn_hibma return; /* Don't recognise the name */ 21861560Sn_hibma if (u != -1 && u > IF_MAXUNIT) 21961560Sn_hibma return; /* Unit number too high */ 22061560Sn_hibma 22161560Sn_hibma if (u == -1) 22261560Sn_hibma append_unit = 1; 223163675Smarkus else 224163675Smarkus append_unit = 0; 225163675Smarkus 226163675Smarkus CURVNET_SET(CRED_TO_VNET(cred)); 227163675Smarkus /* find any existing device, or allocate new unit number */ 228163675Smarkus i = clone_create(&tunclones, &tun_cdevsw, &u, dev, 0); 229163675Smarkus if (i) { 230163675Smarkus if (append_unit) { 231163675Smarkus namelen = snprintf(devname, sizeof(devname), "%s%d", name, 232163675Smarkus u); 23361560Sn_hibma name = devname; 23461560Sn_hibma } 23561560Sn_hibma /* No preexisting struct cdev *, create one */ 23661560Sn_hibma *dev = make_dev_credf(MAKEDEV_REF, &tun_cdevsw, u, cred, 23761560Sn_hibma UID_UUCP, GID_DIALER, 0600, "%s", name); 23861560Sn_hibma } 23961560Sn_hibma 24061560Sn_hibma if_clone_create(name, namelen, NULL); 24161560Sn_hibma CURVNET_RESTORE(); 24261560Sn_hibma} 24361560Sn_hibma 24461560Sn_hibmastatic void 24561560Sn_hibmatun_destroy(struct tun_softc *tp) 24661560Sn_hibma{ 24761560Sn_hibma struct cdev *dev; 24861560Sn_hibma 24961560Sn_hibma /* Unlocked read. */ 25061560Sn_hibma mtx_lock(&tp->tun_mtx); 25161560Sn_hibma if ((tp->tun_flags & TUN_OPEN) != 0) 25261560Sn_hibma cv_wait_unlock(&tp->tun_cv, &tp->tun_mtx); 25361560Sn_hibma else 25461560Sn_hibma mtx_unlock(&tp->tun_mtx); 25561560Sn_hibma 25661560Sn_hibma CURVNET_SET(TUN2IFP(tp)->if_vnet); 25761560Sn_hibma dev = tp->tun_dev; 25861560Sn_hibma bpfdetach(TUN2IFP(tp)); 25961560Sn_hibma if_detach(TUN2IFP(tp)); 26061560Sn_hibma if_free(TUN2IFP(tp)); 26161560Sn_hibma destroy_dev(dev); 26261560Sn_hibma knlist_destroy(&tp->tun_rsel.si_note); 26361560Sn_hibma mtx_destroy(&tp->tun_mtx); 26461560Sn_hibma cv_destroy(&tp->tun_cv); 26561560Sn_hibma free(tp, M_TUN); 26661560Sn_hibma CURVNET_RESTORE(); 26761560Sn_hibma} 26861560Sn_hibma 26961560Sn_hibmastatic void 27061560Sn_hibmatun_clone_destroy(struct ifnet *ifp) 27161560Sn_hibma{ 27261560Sn_hibma struct tun_softc *tp = ifp->if_softc; 27361560Sn_hibma 27461560Sn_hibma mtx_lock(&tunmtx); 27561560Sn_hibma TAILQ_REMOVE(&tunhead, tp, tun_list); 27661560Sn_hibma mtx_unlock(&tunmtx); 27761560Sn_hibma tun_destroy(tp); 27861560Sn_hibma} 27961560Sn_hibma 28061560Sn_hibmastatic int 28161560Sn_hibmatunmodevent(module_t mod, int type, void *data) 28261560Sn_hibma{ 28361560Sn_hibma static eventhandler_tag tag; 28461560Sn_hibma struct tun_softc *tp; 28561560Sn_hibma 28661560Sn_hibma switch (type) { 28761560Sn_hibma case MOD_LOAD: 288163675Smarkus mtx_init(&tunmtx, "tunmtx", NULL, MTX_DEF); 28961560Sn_hibma clone_setup(&tunclones); 29061560Sn_hibma tag = EVENTHANDLER_REGISTER(dev_clone, tunclone, 0, 1000); 29161560Sn_hibma if (tag == NULL) 29261560Sn_hibma return (ENOMEM); 29361560Sn_hibma if_clone_attach(&tun_cloner); 29461560Sn_hibma break; 29561560Sn_hibma case MOD_UNLOAD: 29661560Sn_hibma if_clone_detach(&tun_cloner); 29761560Sn_hibma EVENTHANDLER_DEREGISTER(dev_clone, tag); 29861560Sn_hibma drain_dev_clone_events(); 29961560Sn_hibma 30061560Sn_hibma mtx_lock(&tunmtx); 30161560Sn_hibma while ((tp = TAILQ_FIRST(&tunhead)) != NULL) { 30261560Sn_hibma TAILQ_REMOVE(&tunhead, tp, tun_list); 30361560Sn_hibma mtx_unlock(&tunmtx); 30461560Sn_hibma tun_destroy(tp); 30561560Sn_hibma mtx_lock(&tunmtx); 30661560Sn_hibma } 30761560Sn_hibma mtx_unlock(&tunmtx); 30861560Sn_hibma clone_cleanup(&tunclones); 30961560Sn_hibma mtx_destroy(&tunmtx); 31061560Sn_hibma break; 31161560Sn_hibma default: 31261560Sn_hibma return EOPNOTSUPP; 31361560Sn_hibma } 31461560Sn_hibma return 0; 31561560Sn_hibma} 31661560Sn_hibma 31761560Sn_hibmastatic moduledata_t tun_mod = { 31861560Sn_hibma "if_tun", 31961560Sn_hibma tunmodevent, 32061560Sn_hibma 0 32161560Sn_hibma}; 32261560Sn_hibma 32361560Sn_hibmaDECLARE_MODULE(if_tun, tun_mod, SI_SUB_PSEUDO, SI_ORDER_ANY); 32461560Sn_hibma 32561560Sn_hibmastatic void 32661560Sn_hibmatunstart(struct ifnet *ifp) 32761560Sn_hibma{ 32861560Sn_hibma struct tun_softc *tp = ifp->if_softc; 32961560Sn_hibma struct mbuf *m; 33061560Sn_hibma 33161560Sn_hibma TUNDEBUG(ifp,"%s starting\n", ifp->if_xname); 33261560Sn_hibma if (ALTQ_IS_ENABLED(&ifp->if_snd)) { 33361560Sn_hibma IFQ_LOCK(&ifp->if_snd); 33461560Sn_hibma IFQ_POLL_NOLOCK(&ifp->if_snd, m); 33561560Sn_hibma if (m == NULL) { 33661560Sn_hibma IFQ_UNLOCK(&ifp->if_snd); 33761560Sn_hibma return; 33861560Sn_hibma } 33961560Sn_hibma IFQ_UNLOCK(&ifp->if_snd); 34061560Sn_hibma } 34161560Sn_hibma 34261560Sn_hibma mtx_lock(&tp->tun_mtx); 34361560Sn_hibma if (tp->tun_flags & TUN_RWAIT) { 34461560Sn_hibma tp->tun_flags &= ~TUN_RWAIT; 34561560Sn_hibma wakeup(tp); 34661560Sn_hibma } 34761560Sn_hibma if (tp->tun_flags & TUN_ASYNC && tp->tun_sigio) { 34861560Sn_hibma mtx_unlock(&tp->tun_mtx); 34961560Sn_hibma pgsigio(&tp->tun_sigio, SIGIO, 0); 35061560Sn_hibma } else 35161560Sn_hibma mtx_unlock(&tp->tun_mtx); 35261560Sn_hibma selwakeuppri(&tp->tun_rsel, PZERO + 1); 35361560Sn_hibma KNOTE_UNLOCKED(&tp->tun_rsel.si_note, 0); 35461560Sn_hibma} 35561560Sn_hibma 35661560Sn_hibma/* XXX: should return an error code so it can fail. */ 35761560Sn_hibmastatic void 35861560Sn_hibmatuncreate(const char *name, struct cdev *dev) 35961560Sn_hibma{ 36061560Sn_hibma struct tun_softc *sc; 36161560Sn_hibma struct ifnet *ifp; 36261560Sn_hibma 36361560Sn_hibma dev->si_flags &= ~SI_CHEAPCLONE; 36461560Sn_hibma 36561560Sn_hibma sc = malloc(sizeof(*sc), M_TUN, M_WAITOK | M_ZERO); 36661560Sn_hibma mtx_init(&sc->tun_mtx, "tun_mtx", NULL, MTX_DEF); 36761560Sn_hibma cv_init(&sc->tun_cv, "tun_condvar"); 36861560Sn_hibma sc->tun_flags = TUN_INITED; 36961560Sn_hibma sc->tun_dev = dev; 37061560Sn_hibma mtx_lock(&tunmtx); 37161560Sn_hibma TAILQ_INSERT_TAIL(&tunhead, sc, tun_list); 37261560Sn_hibma mtx_unlock(&tunmtx); 37361560Sn_hibma 37461560Sn_hibma ifp = sc->tun_ifp = if_alloc(IFT_PPP); 37561560Sn_hibma if (ifp == NULL) 37661560Sn_hibma panic("%s%d: failed to if_alloc() interface.\n", 37761560Sn_hibma name, dev2unit(dev)); 37861560Sn_hibma if_initname(ifp, name, dev2unit(dev)); 37961560Sn_hibma ifp->if_mtu = TUNMTU; 38061560Sn_hibma ifp->if_ioctl = tunifioctl; 38161560Sn_hibma ifp->if_output = tunoutput; 38261560Sn_hibma ifp->if_start = tunstart; 38361560Sn_hibma ifp->if_flags = IFF_POINTOPOINT | IFF_MULTICAST; 38461560Sn_hibma ifp->if_softc = sc; 38561560Sn_hibma IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen); 38661560Sn_hibma ifp->if_snd.ifq_drv_maxlen = 0; 38761560Sn_hibma IFQ_SET_READY(&ifp->if_snd); 38861560Sn_hibma knlist_init_mtx(&sc->tun_rsel.si_note, NULL); 38961560Sn_hibma ifp->if_capabilities |= IFCAP_LINKSTATE; 39061560Sn_hibma ifp->if_capenable |= IFCAP_LINKSTATE; 39161560Sn_hibma 39261560Sn_hibma if_attach(ifp); 39361560Sn_hibma bpfattach(ifp, DLT_NULL, sizeof(u_int32_t)); 39461560Sn_hibma dev->si_drv1 = sc; 39561560Sn_hibma TUNDEBUG(ifp, "interface %s is created, minor = %#x\n", 39661560Sn_hibma ifp->if_xname, dev2unit(dev)); 39761560Sn_hibma} 39861560Sn_hibma 399163675Smarkusstatic int 400163675Smarkustunopen(struct cdev *dev, int flag, int mode, struct thread *td) 401163675Smarkus{ 402163675Smarkus struct ifnet *ifp; 403163675Smarkus struct tun_softc *tp; 404163675Smarkus 405163675Smarkus /* 406163675Smarkus * XXXRW: Non-atomic test and set of dev->si_drv1 requires 407163675Smarkus * synchronization. 408163675Smarkus */ 409163675Smarkus tp = dev->si_drv1; 410163675Smarkus if (!tp) { 411163675Smarkus tuncreate(TUNNAME, dev); 412163675Smarkus tp = dev->si_drv1; 413163675Smarkus } 414163675Smarkus 415163675Smarkus /* 416163675Smarkus * XXXRW: This use of tun_pid is subject to error due to the 417163675Smarkus * fact that a reference to the tunnel can live beyond the 418163675Smarkus * death of the process that created it. Can we replace this 419163675Smarkus * with a simple busy flag? 420163675Smarkus */ 421163675Smarkus mtx_lock(&tp->tun_mtx); 422163675Smarkus if (tp->tun_pid != 0 && tp->tun_pid != td->td_proc->p_pid) { 423163675Smarkus mtx_unlock(&tp->tun_mtx); 424163675Smarkus return (EBUSY); 425163675Smarkus } 426163675Smarkus tp->tun_pid = td->td_proc->p_pid; 427163675Smarkus 428163675Smarkus tp->tun_flags |= TUN_OPEN; 429163675Smarkus mtx_unlock(&tp->tun_mtx); 430163675Smarkus ifp = TUN2IFP(tp); 431163675Smarkus if_link_state_change(ifp, LINK_STATE_UP); 432163675Smarkus TUNDEBUG(ifp, "open\n"); 433163675Smarkus 434163675Smarkus return (0); 435163675Smarkus} 436163675Smarkus 437163675Smarkus/* 438163675Smarkus * tunclose - close the device - mark i/f down & delete 439163675Smarkus * routing info 440163675Smarkus */ 441163675Smarkusstatic int 442163675Smarkustunclose(struct cdev *dev, int foo, int bar, struct thread *td) 443163675Smarkus{ 444163675Smarkus struct tun_softc *tp; 44561560Sn_hibma struct ifnet *ifp; 44661560Sn_hibma int s; 44761560Sn_hibma 44861560Sn_hibma tp = dev->si_drv1; 44961560Sn_hibma ifp = TUN2IFP(tp); 45061560Sn_hibma 45161560Sn_hibma mtx_lock(&tp->tun_mtx); 45261560Sn_hibma tp->tun_flags &= ~TUN_OPEN; 45361560Sn_hibma tp->tun_pid = 0; 45461560Sn_hibma mtx_unlock(&tp->tun_mtx); 45561560Sn_hibma 45661560Sn_hibma /* 45761560Sn_hibma * junk all pending output 45861560Sn_hibma */ 45961560Sn_hibma CURVNET_SET(ifp->if_vnet); 46061560Sn_hibma s = splimp(); 46161560Sn_hibma IFQ_PURGE(&ifp->if_snd); 46261560Sn_hibma splx(s); 46361560Sn_hibma 46461560Sn_hibma if (ifp->if_flags & IFF_UP) { 46561560Sn_hibma s = splimp(); 46661560Sn_hibma if_down(ifp); 46761560Sn_hibma splx(s); 46861560Sn_hibma } 46961560Sn_hibma 470163675Smarkus /* Delete all addresses and routes which reference this interface. */ 47161560Sn_hibma if (ifp->if_drv_flags & IFF_DRV_RUNNING) { 47261560Sn_hibma struct ifaddr *ifa; 47361560Sn_hibma 47461560Sn_hibma s = splimp(); 47561560Sn_hibma TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { 47661560Sn_hibma /* deal w/IPv4 PtP destination; unlocked read */ 47761560Sn_hibma if (ifa->ifa_addr->sa_family == AF_INET) { 47861560Sn_hibma rtinit(ifa, (int)RTM_DELETE, 47961560Sn_hibma tp->tun_flags & TUN_DSTADDR ? RTF_HOST : 0); 48061560Sn_hibma } else { 48161560Sn_hibma rtinit(ifa, (int)RTM_DELETE, 0); 48261560Sn_hibma } 48361560Sn_hibma } 48461560Sn_hibma if_purgeaddrs(ifp); 48561560Sn_hibma ifp->if_drv_flags &= ~IFF_DRV_RUNNING; 48661560Sn_hibma splx(s); 48761560Sn_hibma } 48861560Sn_hibma if_link_state_change(ifp, LINK_STATE_DOWN); 48961560Sn_hibma CURVNET_RESTORE(); 49061560Sn_hibma 49161560Sn_hibma mtx_lock(&tp->tun_mtx); 49261560Sn_hibma funsetown(&tp->tun_sigio); 49361560Sn_hibma selwakeuppri(&tp->tun_rsel, PZERO + 1); 49461560Sn_hibma KNOTE_UNLOCKED(&tp->tun_rsel.si_note, 0); 49561560Sn_hibma TUNDEBUG (ifp, "closed\n"); 49661560Sn_hibma 49761560Sn_hibma cv_broadcast(&tp->tun_cv); 49861560Sn_hibma mtx_unlock(&tp->tun_mtx); 49961560Sn_hibma return (0); 50061560Sn_hibma} 50161560Sn_hibma 50261560Sn_hibmastatic int 50361560Sn_hibmatuninit(struct ifnet *ifp) 50461560Sn_hibma{ 50561560Sn_hibma#ifdef INET 50661560Sn_hibma struct tun_softc *tp = ifp->if_softc; 50761560Sn_hibma struct ifaddr *ifa; 50861560Sn_hibma#endif 50961560Sn_hibma int error = 0; 51061560Sn_hibma 51161560Sn_hibma TUNDEBUG(ifp, "tuninit\n"); 51261560Sn_hibma 51361560Sn_hibma ifp->if_flags |= IFF_UP; 51461560Sn_hibma ifp->if_drv_flags |= IFF_DRV_RUNNING; 51561560Sn_hibma getmicrotime(&ifp->if_lastchange); 51661560Sn_hibma 51761560Sn_hibma#ifdef INET 51861560Sn_hibma if_addr_rlock(ifp); 51961560Sn_hibma TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { 52061560Sn_hibma if (ifa->ifa_addr->sa_family == AF_INET) { 52161560Sn_hibma struct sockaddr_in *si; 52261560Sn_hibma 52361560Sn_hibma si = (struct sockaddr_in *)ifa->ifa_addr; 52461560Sn_hibma mtx_lock(&tp->tun_mtx); 52561560Sn_hibma if (si->sin_addr.s_addr) 52661560Sn_hibma tp->tun_flags |= TUN_IASET; 527163675Smarkus 528163675Smarkus si = (struct sockaddr_in *)ifa->ifa_dstaddr; 529163675Smarkus if (si && si->sin_addr.s_addr) 53061560Sn_hibma tp->tun_flags |= TUN_DSTADDR; 53161560Sn_hibma mtx_unlock(&tp->tun_mtx); 53261560Sn_hibma } 53361560Sn_hibma } 53461560Sn_hibma if_addr_runlock(ifp); 53561560Sn_hibma#endif 53661560Sn_hibma return (error); 53761560Sn_hibma} 53861560Sn_hibma 539163675Smarkus/* 54061560Sn_hibma * Process an ioctl request. 54161560Sn_hibma */ 54261560Sn_hibmastatic int 54361560Sn_hibmatunifioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 54461560Sn_hibma{ 54561560Sn_hibma struct ifreq *ifr = (struct ifreq *)data; 54661560Sn_hibma struct tun_softc *tp = ifp->if_softc; 54761560Sn_hibma struct ifstat *ifs; 54861560Sn_hibma int error = 0, s; 54961560Sn_hibma 55061560Sn_hibma s = splimp(); 55161560Sn_hibma switch(cmd) { 55261560Sn_hibma case SIOCGIFSTATUS: 55361560Sn_hibma ifs = (struct ifstat *)data; 55461560Sn_hibma mtx_lock(&tp->tun_mtx); 55561560Sn_hibma if (tp->tun_pid) 55661560Sn_hibma sprintf(ifs->ascii + strlen(ifs->ascii), 55761560Sn_hibma "\tOpened by PID %d\n", tp->tun_pid); 55861560Sn_hibma mtx_unlock(&tp->tun_mtx); 55961560Sn_hibma break; 56061560Sn_hibma case SIOCSIFADDR: 56161560Sn_hibma error = tuninit(ifp); 56261560Sn_hibma TUNDEBUG(ifp, "address set, error=%d\n", error); 56361560Sn_hibma break; 56461560Sn_hibma case SIOCSIFDSTADDR: 56561560Sn_hibma error = tuninit(ifp); 56661560Sn_hibma TUNDEBUG(ifp, "destination address set, error=%d\n", error); 56761560Sn_hibma break; 568163675Smarkus case SIOCSIFMTU: 56961560Sn_hibma ifp->if_mtu = ifr->ifr_mtu; 57061560Sn_hibma TUNDEBUG(ifp, "mtu set\n"); 57161560Sn_hibma break; 57261560Sn_hibma case SIOCSIFFLAGS: 57361560Sn_hibma case SIOCADDMULTI: 57461560Sn_hibma case SIOCDELMULTI: 57561560Sn_hibma break; 57661560Sn_hibma default: 57761560Sn_hibma error = EINVAL; 57861560Sn_hibma } 57961560Sn_hibma splx(s); 58061560Sn_hibma return (error); 58161560Sn_hibma} 58261560Sn_hibma 58361560Sn_hibma/* 58461560Sn_hibma * tunoutput - queue packets from higher level ready to put out. 58561560Sn_hibma */ 58661560Sn_hibmastatic int 58761560Sn_hibmatunoutput( 58861560Sn_hibma struct ifnet *ifp, 58961560Sn_hibma struct mbuf *m0, 59061560Sn_hibma struct sockaddr *dst, 591163675Smarkus struct route *ro) 592163675Smarkus{ 59361560Sn_hibma struct tun_softc *tp = ifp->if_softc; 59461560Sn_hibma u_short cached_tun_flags; 59561560Sn_hibma int error; 59661560Sn_hibma u_int32_t af; 59761560Sn_hibma 59861560Sn_hibma TUNDEBUG (ifp, "tunoutput\n"); 59961560Sn_hibma 60061560Sn_hibma#ifdef MAC 60161560Sn_hibma error = mac_ifnet_check_transmit(ifp, m0); 60261560Sn_hibma if (error) { 60361560Sn_hibma m_freem(m0); 60461560Sn_hibma return (error); 60561560Sn_hibma } 60661560Sn_hibma#endif 60761560Sn_hibma 60861560Sn_hibma /* Could be unlocked read? */ 60961560Sn_hibma mtx_lock(&tp->tun_mtx); 61061560Sn_hibma cached_tun_flags = tp->tun_flags; 61161560Sn_hibma mtx_unlock(&tp->tun_mtx); 61261560Sn_hibma if ((cached_tun_flags & TUN_READY) != TUN_READY) { 61361560Sn_hibma TUNDEBUG (ifp, "not ready 0%o\n", tp->tun_flags); 61461560Sn_hibma m_freem (m0); 615163675Smarkus return (EHOSTDOWN); 616163675Smarkus } 617163675Smarkus 61861560Sn_hibma if ((ifp->if_flags & IFF_UP) != IFF_UP) { 61961560Sn_hibma m_freem (m0); 62061560Sn_hibma return (EHOSTDOWN); 62161560Sn_hibma } 62261560Sn_hibma 62361560Sn_hibma /* BPF writes need to be handled specially. */ 62461560Sn_hibma if (dst->sa_family == AF_UNSPEC) { 62561560Sn_hibma bcopy(dst->sa_data, &af, sizeof(af)); 62661560Sn_hibma dst->sa_family = af; 62761560Sn_hibma } 62861560Sn_hibma 629163675Smarkus if (bpf_peers_present(ifp->if_bpf)) { 63061560Sn_hibma af = dst->sa_family; 63161560Sn_hibma bpf_mtap2(ifp->if_bpf, &af, sizeof(af), m0); 63261560Sn_hibma } 63361560Sn_hibma 63461560Sn_hibma /* prepend sockaddr? this may abort if the mbuf allocation fails */ 63561560Sn_hibma if (cached_tun_flags & TUN_LMODE) { 63661560Sn_hibma /* allocate space for sockaddr */ 63761560Sn_hibma M_PREPEND(m0, dst->sa_len, M_DONTWAIT); 63861560Sn_hibma 63961560Sn_hibma /* if allocation failed drop packet */ 64061560Sn_hibma if (m0 == NULL) { 64161560Sn_hibma ifp->if_iqdrops++; 64261560Sn_hibma ifp->if_oerrors++; 64361560Sn_hibma return (ENOBUFS); 64461560Sn_hibma } else { 64561560Sn_hibma bcopy(dst, m0->m_data, dst->sa_len); 64661560Sn_hibma } 64761560Sn_hibma } 64861560Sn_hibma 64961560Sn_hibma if (cached_tun_flags & TUN_IFHEAD) { 65061560Sn_hibma /* Prepend the address family */ 65161560Sn_hibma M_PREPEND(m0, 4, M_DONTWAIT); 65261560Sn_hibma 65361560Sn_hibma /* if allocation failed drop packet */ 65461560Sn_hibma if (m0 == NULL) { 65561560Sn_hibma ifp->if_iqdrops++; 65661560Sn_hibma ifp->if_oerrors++; 65761560Sn_hibma return (ENOBUFS); 65861560Sn_hibma } else 65961560Sn_hibma *(u_int32_t *)m0->m_data = htonl(dst->sa_family); 66061560Sn_hibma } else { 66161560Sn_hibma#ifdef INET 66261560Sn_hibma if (dst->sa_family != AF_INET) 66361560Sn_hibma#endif 66461560Sn_hibma { 66561560Sn_hibma m_freem(m0); 66661560Sn_hibma return (EAFNOSUPPORT); 66761560Sn_hibma } 66861560Sn_hibma } 66961560Sn_hibma 67061560Sn_hibma error = (ifp->if_transmit)(ifp, m0); 67161560Sn_hibma if (error) { 67261560Sn_hibma ifp->if_collisions++; 67361560Sn_hibma return (ENOBUFS); 67461560Sn_hibma } 67561560Sn_hibma ifp->if_opackets++; 67661560Sn_hibma return (0); 67761560Sn_hibma} 67861560Sn_hibma 67961560Sn_hibma/* 68061560Sn_hibma * the cdevsw interface is now pretty minimal. 68161560Sn_hibma */ 68261560Sn_hibmastatic int 68361560Sn_hibmatunioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td) 68461560Sn_hibma{ 68561560Sn_hibma int s; 68661560Sn_hibma int error; 68761560Sn_hibma struct tun_softc *tp = dev->si_drv1; 68861560Sn_hibma struct tuninfo *tunp; 68961560Sn_hibma 69061560Sn_hibma switch (cmd) { 69161560Sn_hibma case TUNSIFINFO: 69261560Sn_hibma tunp = (struct tuninfo *)data; 69361560Sn_hibma if (tunp->mtu < IF_MINMTU) 69461560Sn_hibma return (EINVAL); 69561560Sn_hibma if (TUN2IFP(tp)->if_mtu != tunp->mtu) { 69661560Sn_hibma error = priv_check(td, PRIV_NET_SETIFMTU); 69761560Sn_hibma if (error) 69861560Sn_hibma return (error); 69961560Sn_hibma } 70061560Sn_hibma TUN2IFP(tp)->if_mtu = tunp->mtu; 70161560Sn_hibma TUN2IFP(tp)->if_type = tunp->type; 70261560Sn_hibma TUN2IFP(tp)->if_baudrate = tunp->baudrate; 70361560Sn_hibma break; 70461560Sn_hibma case TUNGIFINFO: 70561560Sn_hibma tunp = (struct tuninfo *)data; 70661560Sn_hibma tunp->mtu = TUN2IFP(tp)->if_mtu; 70761560Sn_hibma tunp->type = TUN2IFP(tp)->if_type; 708163675Smarkus tunp->baudrate = TUN2IFP(tp)->if_baudrate; 709163675Smarkus break; 710163675Smarkus case TUNSDEBUG: 71161560Sn_hibma tundebug = *(int *)data; 71261560Sn_hibma break; 71361560Sn_hibma case TUNGDEBUG: 71461560Sn_hibma *(int *)data = tundebug; 71561560Sn_hibma break; 71661560Sn_hibma case TUNSLMODE: 71761560Sn_hibma mtx_lock(&tp->tun_mtx); 71861560Sn_hibma if (*(int *)data) { 71961560Sn_hibma tp->tun_flags |= TUN_LMODE; 720163675Smarkus tp->tun_flags &= ~TUN_IFHEAD; 721163675Smarkus } else 72261560Sn_hibma tp->tun_flags &= ~TUN_LMODE; 72361560Sn_hibma mtx_unlock(&tp->tun_mtx); 72461560Sn_hibma break; 72561560Sn_hibma case TUNSIFHEAD: 72661560Sn_hibma mtx_lock(&tp->tun_mtx); 72761560Sn_hibma if (*(int *)data) { 72861560Sn_hibma tp->tun_flags |= TUN_IFHEAD; 72961560Sn_hibma tp->tun_flags &= ~TUN_LMODE; 730163675Smarkus } else 73161560Sn_hibma tp->tun_flags &= ~TUN_IFHEAD; 73261560Sn_hibma mtx_unlock(&tp->tun_mtx); 73361560Sn_hibma break; 73461560Sn_hibma case TUNGIFHEAD: 73561560Sn_hibma /* Could be unlocked read? */ 73661560Sn_hibma mtx_lock(&tp->tun_mtx); 737163675Smarkus *(int *)data = (tp->tun_flags & TUN_IFHEAD) ? 1 : 0; 738163675Smarkus mtx_unlock(&tp->tun_mtx); 739163675Smarkus break; 740163675Smarkus case TUNSIFMODE: 741163675Smarkus /* deny this if UP */ 74261560Sn_hibma if (TUN2IFP(tp)->if_flags & IFF_UP) 74361560Sn_hibma return(EBUSY); 74461560Sn_hibma 74561560Sn_hibma switch (*(int *)data & ~IFF_MULTICAST) { 74661560Sn_hibma case IFF_POINTOPOINT: 74761560Sn_hibma case IFF_BROADCAST: 74861560Sn_hibma TUN2IFP(tp)->if_flags &= 74961560Sn_hibma ~(IFF_BROADCAST|IFF_POINTOPOINT|IFF_MULTICAST); 75061560Sn_hibma TUN2IFP(tp)->if_flags |= *(int *)data; 75161560Sn_hibma break; 75261560Sn_hibma default: 75361560Sn_hibma return(EINVAL); 75461560Sn_hibma } 75561560Sn_hibma break; 75661560Sn_hibma case TUNSIFPID: 75761560Sn_hibma mtx_lock(&tp->tun_mtx); 75861560Sn_hibma tp->tun_pid = curthread->td_proc->p_pid; 75961560Sn_hibma mtx_unlock(&tp->tun_mtx); 76061560Sn_hibma break; 76161560Sn_hibma case FIONBIO: 76261560Sn_hibma break; 76361560Sn_hibma case FIOASYNC: 76461560Sn_hibma mtx_lock(&tp->tun_mtx); 76561560Sn_hibma if (*(int *)data) 76661560Sn_hibma tp->tun_flags |= TUN_ASYNC; 76761560Sn_hibma else 76861560Sn_hibma tp->tun_flags &= ~TUN_ASYNC; 76961560Sn_hibma mtx_unlock(&tp->tun_mtx); 77061560Sn_hibma break; 77161560Sn_hibma case FIONREAD: 77261560Sn_hibma s = splimp(); 77361560Sn_hibma if (!IFQ_IS_EMPTY(&TUN2IFP(tp)->if_snd)) { 77461560Sn_hibma struct mbuf *mb; 77561560Sn_hibma IFQ_LOCK(&TUN2IFP(tp)->if_snd); 77661560Sn_hibma IFQ_POLL_NOLOCK(&TUN2IFP(tp)->if_snd, mb); 77761560Sn_hibma for( *(int *)data = 0; mb != 0; mb = mb->m_next) 77861560Sn_hibma *(int *)data += mb->m_len; 77961560Sn_hibma IFQ_UNLOCK(&TUN2IFP(tp)->if_snd); 78061560Sn_hibma } else 78161560Sn_hibma *(int *)data = 0; 78261560Sn_hibma splx(s); 78361560Sn_hibma break; 78461560Sn_hibma case FIOSETOWN: 78561560Sn_hibma return (fsetown(*(int *)data, &tp->tun_sigio)); 78661560Sn_hibma 78761560Sn_hibma case FIOGETOWN: 78861560Sn_hibma *(int *)data = fgetown(&tp->tun_sigio); 78961560Sn_hibma return (0); 79061560Sn_hibma 79161560Sn_hibma /* This is deprecated, FIOSETOWN should be used instead. */ 79261560Sn_hibma case TIOCSPGRP: 79361560Sn_hibma return (fsetown(-(*(int *)data), &tp->tun_sigio)); 79461560Sn_hibma 79561560Sn_hibma /* This is deprecated, FIOGETOWN should be used instead. */ 79661560Sn_hibma case TIOCGPGRP: 79761560Sn_hibma *(int *)data = -fgetown(&tp->tun_sigio); 79861560Sn_hibma return (0); 79961560Sn_hibma 80061560Sn_hibma default: 80161560Sn_hibma return (ENOTTY); 802163675Smarkus } 803163675Smarkus return (0); 804163675Smarkus} 805163675Smarkus 806163675Smarkus/* 807163675Smarkus * The cdevsw read interface - reads a packet at a time, or at 808163675Smarkus * least as much of a packet as can be read. 809163675Smarkus */ 810163675Smarkusstatic int 811163675Smarkustunread(struct cdev *dev, struct uio *uio, int flag) 812163675Smarkus{ 813163675Smarkus struct tun_softc *tp = dev->si_drv1; 814163675Smarkus struct ifnet *ifp = TUN2IFP(tp); 815163675Smarkus struct mbuf *m; 816163675Smarkus int error=0, len, s; 817163675Smarkus 818163675Smarkus TUNDEBUG (ifp, "read\n"); 819163675Smarkus mtx_lock(&tp->tun_mtx); 820163675Smarkus if ((tp->tun_flags & TUN_READY) != TUN_READY) { 821163675Smarkus mtx_unlock(&tp->tun_mtx); 822163675Smarkus TUNDEBUG (ifp, "not ready 0%o\n", tp->tun_flags); 823163675Smarkus return (EHOSTDOWN); 824163675Smarkus } 825163675Smarkus 826163675Smarkus tp->tun_flags &= ~TUN_RWAIT; 827163675Smarkus mtx_unlock(&tp->tun_mtx); 828163675Smarkus 829163675Smarkus s = splimp(); 830163675Smarkus do { 831163675Smarkus IFQ_DEQUEUE(&ifp->if_snd, m); 832163675Smarkus if (m == NULL) { 833163675Smarkus if (flag & O_NONBLOCK) { 834163675Smarkus splx(s); 83561560Sn_hibma return (EWOULDBLOCK); 83661560Sn_hibma } 83761560Sn_hibma mtx_lock(&tp->tun_mtx); 83861560Sn_hibma tp->tun_flags |= TUN_RWAIT; 83961560Sn_hibma mtx_unlock(&tp->tun_mtx); 84061560Sn_hibma if ((error = tsleep(tp, PCATCH | (PZERO + 1), 84161560Sn_hibma "tunread", 0)) != 0) { 84261560Sn_hibma splx(s); 84361560Sn_hibma return (error); 84461560Sn_hibma } 84561560Sn_hibma } 84661560Sn_hibma } while (m == NULL); 84761560Sn_hibma splx(s); 84861560Sn_hibma 84961560Sn_hibma while (m && uio->uio_resid > 0 && error == 0) { 85061560Sn_hibma len = min(uio->uio_resid, m->m_len); 85161560Sn_hibma if (len != 0) 85261560Sn_hibma error = uiomove(mtod(m, void *), len, uio); 85361560Sn_hibma m = m_free(m); 85461560Sn_hibma } 85561560Sn_hibma 85661560Sn_hibma if (m) { 85761560Sn_hibma TUNDEBUG(ifp, "Dropping mbuf\n"); 85861560Sn_hibma m_freem(m); 85961560Sn_hibma } 86061560Sn_hibma return (error); 86161560Sn_hibma} 86261560Sn_hibma 86361560Sn_hibma/* 86461560Sn_hibma * the cdevsw write interface - an atomic write is a packet - or else! 86561560Sn_hibma */ 86661560Sn_hibmastatic int 86761560Sn_hibmatunwrite(struct cdev *dev, struct uio *uio, int flag) 86861560Sn_hibma{ 86961560Sn_hibma struct tun_softc *tp = dev->si_drv1; 87061560Sn_hibma struct ifnet *ifp = TUN2IFP(tp); 87161560Sn_hibma struct mbuf *m; 87261560Sn_hibma int error = 0; 87361560Sn_hibma uint32_t family; 87461560Sn_hibma int isr; 87561560Sn_hibma 87661560Sn_hibma TUNDEBUG(ifp, "tunwrite\n"); 87761560Sn_hibma 87861560Sn_hibma if ((ifp->if_flags & IFF_UP) != IFF_UP) 87961560Sn_hibma /* ignore silently */ 880163675Smarkus return (0); 881163675Smarkus 882163675Smarkus if (uio->uio_resid == 0) 883163675Smarkus return (0); 884163675Smarkus 885163675Smarkus if (uio->uio_resid < 0 || uio->uio_resid > TUNMRU) { 886163675Smarkus TUNDEBUG(ifp, "len=%zd!\n", uio->uio_resid); 887163675Smarkus return (EIO); 888163675Smarkus } 889163675Smarkus 890163675Smarkus if ((m = m_uiotombuf(uio, M_DONTWAIT, 0, 0, M_PKTHDR)) == NULL) { 891163675Smarkus ifp->if_ierrors++; 892163675Smarkus return (error); 893163675Smarkus } 894163675Smarkus 895163675Smarkus m->m_pkthdr.rcvif = ifp; 896163675Smarkus#ifdef MAC 897163675Smarkus mac_ifnet_create_mbuf(ifp, m); 898163675Smarkus#endif 899163675Smarkus 900163675Smarkus /* Could be unlocked read? */ 901163675Smarkus mtx_lock(&tp->tun_mtx); 902163675Smarkus if (tp->tun_flags & TUN_IFHEAD) { 903163675Smarkus mtx_unlock(&tp->tun_mtx); 904163675Smarkus if (m->m_len < sizeof(family) && 905163675Smarkus (m = m_pullup(m, sizeof(family))) == NULL) 906163675Smarkus return (ENOBUFS); 907163675Smarkus family = ntohl(*mtod(m, u_int32_t *)); 908163675Smarkus m_adj(m, sizeof(family)); 909163675Smarkus } else { 910163675Smarkus mtx_unlock(&tp->tun_mtx); 911163675Smarkus family = AF_INET; 912163675Smarkus } 913163675Smarkus 914163675Smarkus BPF_MTAP2(ifp, &family, sizeof(family), m); 915163675Smarkus 916163675Smarkus switch (family) { 917163675Smarkus#ifdef INET 918163675Smarkus case AF_INET: 919163675Smarkus isr = NETISR_IP; 920163675Smarkus break; 921163675Smarkus#endif 922163675Smarkus#ifdef INET6 923163675Smarkus case AF_INET6: 924163675Smarkus isr = NETISR_IPV6; 925163675Smarkus break; 926163675Smarkus#endif 927163675Smarkus#ifdef IPX 928163675Smarkus case AF_IPX: 929163675Smarkus isr = NETISR_IPX; 930163675Smarkus break; 931163675Smarkus#endif 932163675Smarkus#ifdef NETATALK 933163675Smarkus case AF_APPLETALK: 934163675Smarkus isr = NETISR_ATALK2; 935163675Smarkus break; 936163675Smarkus#endif 937163675Smarkus default: 938163675Smarkus m_freem(m); 939163675Smarkus return (EAFNOSUPPORT); 940163675Smarkus } 941163675Smarkus /* First chunk of an mbuf contains good junk */ 942163675Smarkus if (harvest.point_to_point) 943163675Smarkus random_harvest(m, 16, 3, 0, RANDOM_NET); 944163675Smarkus ifp->if_ibytes += m->m_pkthdr.len; 945163675Smarkus ifp->if_ipackets++; 946163675Smarkus CURVNET_SET(ifp->if_vnet); 947163675Smarkus netisr_dispatch(isr, m); 948163675Smarkus CURVNET_RESTORE(); 949163675Smarkus return (0); 950163675Smarkus} 951163675Smarkus 952163675Smarkus/* 953163675Smarkus * tunpoll - the poll interface, this is only useful on reads 954163675Smarkus * really. The write detect always returns true, write never blocks 955163675Smarkus * anyway, it either accepts the packet or drops it. 956163675Smarkus */ 957163675Smarkusstatic int 958163675Smarkustunpoll(struct cdev *dev, int events, struct thread *td) 959163675Smarkus{ 960163675Smarkus int s; 961163675Smarkus struct tun_softc *tp = dev->si_drv1; 962163675Smarkus struct ifnet *ifp = TUN2IFP(tp); 963163675Smarkus int revents = 0; 964163675Smarkus struct mbuf *m; 965163675Smarkus 966163675Smarkus s = splimp(); 967163675Smarkus TUNDEBUG(ifp, "tunpoll\n"); 968163675Smarkus 969163675Smarkus if (events & (POLLIN | POLLRDNORM)) { 970163675Smarkus IFQ_LOCK(&ifp->if_snd); 971163675Smarkus IFQ_POLL_NOLOCK(&ifp->if_snd, m); 972163675Smarkus if (m != NULL) { 973163675Smarkus TUNDEBUG(ifp, "tunpoll q=%d\n", ifp->if_snd.ifq_len); 974163675Smarkus revents |= events & (POLLIN | POLLRDNORM); 975163675Smarkus } else { 97661560Sn_hibma TUNDEBUG(ifp, "tunpoll waiting\n"); 97761560Sn_hibma selrecord(td, &tp->tun_rsel); 97861560Sn_hibma } 97961560Sn_hibma IFQ_UNLOCK(&ifp->if_snd); 98061560Sn_hibma } 98161560Sn_hibma if (events & (POLLOUT | POLLWRNORM)) 98261560Sn_hibma revents |= events & (POLLOUT | POLLWRNORM); 98361560Sn_hibma 98461560Sn_hibma splx(s); 98561560Sn_hibma return (revents); 986163675Smarkus} 98761560Sn_hibma 98861560Sn_hibma/* 98961560Sn_hibma * tunkqfilter - support for the kevent() system call. 99061560Sn_hibma */ 99161560Sn_hibmastatic int 992223153Smavtunkqfilter(struct cdev *dev, struct knote *kn) 99361560Sn_hibma{ 99461560Sn_hibma int s; 99561560Sn_hibma struct tun_softc *tp = dev->si_drv1; 996223153Smav struct ifnet *ifp = TUN2IFP(tp); 99761560Sn_hibma 99861560Sn_hibma s = splimp(); 99961560Sn_hibma switch(kn->kn_filter) { 100061560Sn_hibma case EVFILT_READ: 100161560Sn_hibma TUNDEBUG(ifp, "%s kqfilter: EVFILT_READ, minor = %#x\n", 100261560Sn_hibma ifp->if_xname, dev2unit(dev)); 100361560Sn_hibma kn->kn_fop = &tun_read_filterops; 100461560Sn_hibma break; 100561560Sn_hibma 100661560Sn_hibma case EVFILT_WRITE: 100761560Sn_hibma TUNDEBUG(ifp, "%s kqfilter: EVFILT_WRITE, minor = %#x\n", 100861560Sn_hibma ifp->if_xname, dev2unit(dev)); 100961560Sn_hibma kn->kn_fop = &tun_write_filterops; 101061560Sn_hibma break; 101161560Sn_hibma 101261560Sn_hibma default: 101361560Sn_hibma TUNDEBUG(ifp, "%s kqfilter: invalid filter, minor = %#x\n", 101461560Sn_hibma ifp->if_xname, dev2unit(dev)); 101561560Sn_hibma splx(s); 101661560Sn_hibma return(EINVAL); 101761560Sn_hibma } 101861560Sn_hibma splx(s); 101961560Sn_hibma 1020223153Smav kn->kn_hook = (caddr_t) dev; 1021223153Smav knlist_add(&tp->tun_rsel.si_note, kn, 0); 1022223153Smav 1023223153Smav return (0); 1024223153Smav} 1025223153Smav 1026223153Smav/* 1027223153Smav * Return true of there is data in the interface queue. 102861560Sn_hibma */ 102961560Sn_hibmastatic int 1030163675Smarkustunkqread(struct knote *kn, long hint) 1031163675Smarkus{ 1032163675Smarkus int ret, s; 1033163675Smarkus struct cdev *dev = (struct cdev *)(kn->kn_hook); 1034163675Smarkus struct tun_softc *tp = dev->si_drv1; 1035163675Smarkus struct ifnet *ifp = TUN2IFP(tp); 1036163675Smarkus 1037163675Smarkus s = splimp(); 1038163675Smarkus if ((kn->kn_data = ifp->if_snd.ifq_len) > 0) { 1039163675Smarkus TUNDEBUG(ifp, 1040163675Smarkus "%s have data in the queue. Len = %d, minor = %#x\n", 1041163675Smarkus ifp->if_xname, ifp->if_snd.ifq_len, dev2unit(dev)); 1042163675Smarkus ret = 1; 1043163675Smarkus } else { 1044163675Smarkus TUNDEBUG(ifp, 1045163675Smarkus "%s waiting for data, minor = %#x\n", ifp->if_xname, 1046163675Smarkus dev2unit(dev)); 1047163675Smarkus ret = 0; 1048163675Smarkus } 1049163675Smarkus splx(s); 1050163675Smarkus 1051163675Smarkus return (ret); 1052163675Smarkus} 1053163675Smarkus 1054163675Smarkus/* 1055163675Smarkus * Always can write, always return MTU in kn->data. 1056163675Smarkus */ 1057163675Smarkusstatic int 1058163675Smarkustunkqwrite(struct knote *kn, long hint) 1059163675Smarkus{ 1060163675Smarkus int s; 1061163675Smarkus struct tun_softc *tp = ((struct cdev *)kn->kn_hook)->si_drv1; 1062163675Smarkus struct ifnet *ifp = TUN2IFP(tp); 1063163675Smarkus 1064163675Smarkus s = splimp(); 1065163675Smarkus kn->kn_data = ifp->if_mtu; 1066163675Smarkus splx(s); 1067163675Smarkus 1068163675Smarkus return (1); 1069163675Smarkus} 1070163675Smarkus 1071163675Smarkusstatic void 1072163675Smarkustunkqdetach(struct knote *kn) 1073163675Smarkus{ 1074163675Smarkus struct tun_softc *tp = ((struct cdev *)kn->kn_hook)->si_drv1; 1075163675Smarkus 1076163675Smarkus knlist_remove(&tp->tun_rsel.si_note, kn, 0); 1077163675Smarkus} 1078163675Smarkus