if_tun.c revision 11921
133965Sjdp/* $NetBSD: if_tun.c,v 1.14 1994/06/29 06:36:25 cgd Exp $ */ 2130561Sobrien 378828Sobrien/* 433965Sjdp * Copyright (c) 1988, Julian Onions <jpo@cs.nott.ac.uk> 533965Sjdp * Nottingham University 1987. 6130561Sobrien * 733965Sjdp * This source may be freely distributed, however I would be interested 8130561Sobrien * in any changes that are made. 9130561Sobrien * 10130561Sobrien * This driver takes packets off the IP i/f and hands them up to a 11130561Sobrien * user process to have it's wicked way with. This driver has it's 1233965Sjdp * roots in a similar driver written by Phil Cockcroft (formerly) at 13130561Sobrien * UCL. This driver is based much more on read/write/select mode of 14130561Sobrien * operation though. 15130561Sobrien */ 16130561Sobrien 1733965Sjdp#include "tun.h" 18130561Sobrien#if NTUN > 0 19130561Sobrien 20130561Sobrien#include <sys/param.h> 2133965Sjdp#include <sys/proc.h> 2233965Sjdp#include <sys/systm.h> 2333965Sjdp#include <sys/mbuf.h> 2433965Sjdp#include <sys/buf.h> 2533965Sjdp#include <sys/protosw.h> 2633965Sjdp#include <sys/socket.h> 2733965Sjdp#include <sys/ioctl.h> 2833965Sjdp#include <sys/errno.h> 2933965Sjdp#include <sys/syslog.h> 3033965Sjdp#include <sys/select.h> 3177298Sobrien#include <sys/file.h> 3277298Sobrien#include <sys/signalvar.h> 3377298Sobrien#ifdef __FreeBSD__ 3477298Sobrien#include <sys/kernel.h> 3577298Sobrien#endif 3633965Sjdp#include <sys/conf.h> 3733965Sjdp 3833965Sjdp#include <machine/cpu.h> 3933965Sjdp 4033965Sjdp#include <net/if.h> 4133965Sjdp#include <net/netisr.h> 4233965Sjdp#include <net/route.h> 4333965Sjdp 4433965Sjdp#ifdef INET 4533965Sjdp#include <netinet/in.h> 4633965Sjdp#include <netinet/in_systm.h> 4733965Sjdp#include <netinet/in_var.h> 4889857Sobrien#include <netinet/ip.h> 4989857Sobrien#include <netinet/if_ether.h> 5033965Sjdp#endif 5133965Sjdp 5289857Sobrien#ifdef NS 5389857Sobrien#include <netns/ns.h> 5433965Sjdp#include <netns/ns_if.h> 5577298Sobrien#endif 5689857Sobrien 5789857Sobrien#include "bpfilter.h" 5877298Sobrien#if NBPFILTER > 0 5977298Sobrien#include <sys/time.h> 6089857Sobrien#include <net/bpf.h> 6189857Sobrien#endif 6277298Sobrien 6333965Sjdp#include <net/if_tun.h> 6433965Sjdp 6533965Sjdp#ifdef __FreeBSD__ 6633965Sjdpstatic void tunattach __P((void *)); 6733965SjdpPSEUDO_SET(tunattach, if_tun); 6833965Sjdp#endif 6933965Sjdp 7033965Sjdp#define TUNDEBUG if (tundebug) printf 7133965Sjdpint tundebug = 0; 7233965Sjdp 7333965Sjdpstruct tun_softc tunctl[NTUN]; 7433965Sjdp 7533965Sjdpd_open_t tunopen; 7633965Sjdpd_close_t tunclose; 7733965Sjdpint tunoutput __P((struct ifnet *, struct mbuf *, struct sockaddr *, 7833965Sjdp struct rtentry *rt)); 7933965Sjdpd_rdwr_t tunread; 8033965Sjdpd_rdwr_t tunwrite; 8133965Sjdpd_ioctl_t tunioctl; 8233965Sjdpint tunifioctl __P((struct ifnet *, int, caddr_t)); 8333965Sjdpd_select_t tunselect; 8433965Sjdp 8533965Sjdpstatic struct cdevsw tuncdevsw = 8633965Sjdp{ tunopen, tunclose, tunread, tunwrite, 8733965Sjdp tunioctl, (d_stop_t *)enodev, (d_reset_t *)nullop, (d_ttycv_t *)enodev, 8833965Sjdp tunselect, (d_mmap_t *)enodev, NULL }; 8933965Sjdpextern dev_t tuncdev; 9033965Sjdp 9133965Sjdpstatic int tuninit __P((int)); 9233965Sjdp 9333965Sjdpstatic void 9433965Sjdptunattach(udata) 9533965Sjdp void *udata; 9633965Sjdp{ 9733965Sjdp register int i; 9833965Sjdp struct ifnet *ifp; 9933965Sjdp 10033965Sjdp /* 10133965Sjdp * In case we are an LKM, set up device switch. 10233965Sjdp */ 10333965Sjdp cdevsw[major(tuncdev)] = tuncdevsw; 10433965Sjdp 10533965Sjdp for (i = 0; i < NTUN; i++) { 10633965Sjdp tunctl[i].tun_flags = TUN_INITED; 10789857Sobrien 10889857Sobrien ifp = &tunctl[i].tun_if; 10989857Sobrien ifp->if_unit = i; 11089857Sobrien ifp->if_name = "tun"; 11189857Sobrien ifp->if_mtu = TUNMTU; 11289857Sobrien ifp->if_ioctl = tunifioctl; 11389857Sobrien ifp->if_output = tunoutput; 11489857Sobrien ifp->if_flags = IFF_POINTOPOINT | IFF_MULTICAST; 11589857Sobrien ifp->if_snd.ifq_maxlen = ifqmaxlen; 11689857Sobrien ifp->if_collisions = 0; 11789857Sobrien ifp->if_ierrors = 0; 11889857Sobrien ifp->if_oerrors = 0; 11989857Sobrien ifp->if_ipackets = 0; 12089857Sobrien ifp->if_opackets = 0; 12189857Sobrien if_attach(ifp); 12289857Sobrien#if NBPFILTER > 0 12389857Sobrien bpfattach(&tunctl[i].tun_bpf, ifp, DLT_NULL, sizeof(u_int)); 12489857Sobrien#endif 12589857Sobrien } 12689857Sobrien} 12789857Sobrien 12889857Sobrien/* 12989857Sobrien * tunnel open - must be superuser & the device must be 13089857Sobrien * configured in 13189857Sobrien */ 13233965Sjdpint 13333965Sjdptunopen(dev, flag, mode, p) 13433965Sjdp dev_t dev; 13577298Sobrien int flag, mode; 13633965Sjdp struct proc *p; 13733965Sjdp{ 13833965Sjdp struct ifnet *ifp; 13933965Sjdp struct tun_softc *tp; 14033965Sjdp register int unit, error; 14133965Sjdp 14233965Sjdp if (error = suser(p->p_ucred, &p->p_acflag)) 14333965Sjdp return (error); 14433965Sjdp 14533965Sjdp if ((unit = minor(dev)) >= NTUN) 14633965Sjdp return (ENXIO); 14733965Sjdp tp = &tunctl[unit]; 14833965Sjdp if (tp->tun_flags & TUN_OPEN) 14933965Sjdp return ENXIO; 15033965Sjdp ifp = &tp->tun_if; 15133965Sjdp tp->tun_flags |= TUN_OPEN; 15289857Sobrien TUNDEBUG("%s%d: open\n", ifp->if_name, ifp->if_unit); 15389857Sobrien return (0); 15489857Sobrien} 15589857Sobrien 15689857Sobrien/* 15789857Sobrien * tunclose - close the device - mark i/f down & delete 15889857Sobrien * routing info 15989857Sobrien */ 16089857Sobrienint 16189857Sobrientunclose(dev_t dev, int foo, int bar, struct proc *p) 16289857Sobrien{ 16389857Sobrien register int unit = minor(dev), s; 16489857Sobrien struct tun_softc *tp = &tunctl[unit]; 16589857Sobrien struct ifnet *ifp = &tp->tun_if; 16689857Sobrien struct mbuf *m; 16789857Sobrien 16889857Sobrien tp->tun_flags &= ~TUN_OPEN; 16989857Sobrien 17089857Sobrien /* 17189857Sobrien * junk all pending output 17289857Sobrien */ 17389857Sobrien do { 17489857Sobrien s = splimp(); 17589857Sobrien IF_DEQUEUE(&ifp->if_snd, m); 17689857Sobrien splx(s); 17733965Sjdp if (m) 17833965Sjdp m_freem(m); 17989857Sobrien } while (m); 18077298Sobrien 18133965Sjdp if (ifp->if_flags & IFF_UP) { 18233965Sjdp s = splimp(); 18333965Sjdp if_down(ifp); 18433965Sjdp if (ifp->if_flags & IFF_RUNNING) { 18533965Sjdp /* find internet addresses and delete routes */ 18633965Sjdp register struct ifaddr *ifa; 18733965Sjdp for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { 18833965Sjdp if (ifa->ifa_addr->sa_family == AF_INET) { 18933965Sjdp rtinit(ifa, (int)RTM_DELETE, 19033965Sjdp tp->tun_flags & TUN_DSTADDR ? RTF_HOST : 0); 19133965Sjdp } 19233965Sjdp } 19333965Sjdp } 19433965Sjdp splx(s); 19577298Sobrien } 19689857Sobrien tp->tun_pgrp = 0; 19789857Sobrien selwakeup(&tp->tun_rsel); 19877298Sobrien 19978828Sobrien TUNDEBUG ("%s%d: closed\n", ifp->if_name, ifp->if_unit); 20033965Sjdp return (0); 20133965Sjdp} 20289857Sobrien 20389857Sobrienstatic int 20489857Sobrientuninit(unit) 20589857Sobrien int unit; 20689857Sobrien{ 20789857Sobrien struct tun_softc *tp = &tunctl[unit]; 20889857Sobrien struct ifnet *ifp = &tp->tun_if; 20989857Sobrien register struct ifaddr *ifa; 21077298Sobrien 21189857Sobrien TUNDEBUG("%s%d: tuninit\n", ifp->if_name, ifp->if_unit); 21289857Sobrien 21333965Sjdp ifp->if_flags |= IFF_UP | IFF_RUNNING; 21477298Sobrien 21589857Sobrien for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) 21689857Sobrien if (ifa->ifa_addr->sa_family == AF_INET) { 21733965Sjdp struct sockaddr_in *si; 21889857Sobrien 21989857Sobrien si = (struct sockaddr_in *)ifa->ifa_addr; 22089857Sobrien if (si && si->sin_addr.s_addr) 22189857Sobrien tp->tun_flags |= TUN_IASET; 22233965Sjdp 223130561Sobrien si = (struct sockaddr_in *)ifa->ifa_dstaddr; 22489857Sobrien if (si && si->sin_addr.s_addr) 22589857Sobrien tp->tun_flags |= TUN_DSTADDR; 22689857Sobrien } 22789857Sobrien 22889857Sobrien return 0; 22989857Sobrien} 23089857Sobrien 23189857Sobrien/* 23289857Sobrien * Process an ioctl request. 23389857Sobrien */ 23489857Sobrienint 23589857Sobrientunifioctl(ifp, cmd, data) 23689857Sobrien struct ifnet *ifp; 23789857Sobrien int cmd; 23889857Sobrien caddr_t data; 23989857Sobrien{ 24089857Sobrien register struct ifreq *ifr = (struct ifreq *)data; 24189857Sobrien int error = 0, s; 24289857Sobrien 24389857Sobrien s = splimp(); 24433965Sjdp switch(cmd) { 24533965Sjdp case SIOCSIFADDR: 24689857Sobrien tuninit(ifp->if_unit); 24789857Sobrien TUNDEBUG("%s%d: address set\n", 24833965Sjdp ifp->if_name, ifp->if_unit); 24933965Sjdp break; 25033965Sjdp case SIOCSIFDSTADDR: 25177298Sobrien tuninit(ifp->if_unit); 25233965Sjdp TUNDEBUG("%s%d: destination address set\n", 25333965Sjdp ifp->if_name, ifp->if_unit); 25433965Sjdp break; 25533965Sjdp case SIOCADDMULTI: 25633965Sjdp case SIOCDELMULTI: 25733965Sjdp if (ifr == 0) { 25833965Sjdp error = EAFNOSUPPORT; /* XXX */ 25933965Sjdp break; 26033965Sjdp } 26133965Sjdp switch (ifr->ifr_addr.sa_family) { 26233965Sjdp 26333965Sjdp#ifdef INET 26433965Sjdp case AF_INET: 26533965Sjdp break; 266130561Sobrien#endif 267130561Sobrien 26877298Sobrien default: 26989857Sobrien error = EAFNOSUPPORT; 27089857Sobrien break; 27189857Sobrien } 27289857Sobrien break; 27389857Sobrien 27489857Sobrien 27589857Sobrien default: 27689857Sobrien error = EINVAL; 27789857Sobrien } 27889857Sobrien splx(s); 27977298Sobrien return (error); 28089857Sobrien} 28189857Sobrien 28233965Sjdp/* 28377298Sobrien * tunoutput - queue packets from higher level ready to put out. 28489857Sobrien */ 28589857Sobrienint 28633965Sjdptunoutput(ifp, m0, dst, rt) 28789857Sobrien struct ifnet *ifp; 28889857Sobrien struct mbuf *m0; 28989857Sobrien struct sockaddr *dst; 29089857Sobrien struct rtentry *rt; 29133965Sjdp{ 292130561Sobrien struct tun_softc *tp = &tunctl[ifp->if_unit]; 29389857Sobrien struct proc *p; 29489857Sobrien int s; 29589857Sobrien 29689857Sobrien TUNDEBUG ("%s%d: tunoutput\n", ifp->if_name, ifp->if_unit); 29789857Sobrien 29889857Sobrien if ((tp->tun_flags & TUN_READY) != TUN_READY) { 29989857Sobrien TUNDEBUG ("%s%d: not ready 0%o\n", ifp->if_name, 30089857Sobrien ifp->if_unit, tp->tun_flags); 30189857Sobrien m_freem (m0); 30289857Sobrien return EHOSTDOWN; 30389857Sobrien } 30489857Sobrien 30589857Sobrien#if NBPFILTER > 0 30689857Sobrien /* BPF write needs to be handled specially */ 30789857Sobrien if (dst->sa_family == AF_UNSPEC) { 30889857Sobrien dst->sa_family = *(mtod(m0, int *)); 30989857Sobrien m0->m_len -= sizeof(int); 31089857Sobrien m0->m_pkthdr.len -= sizeof(int); 31189857Sobrien m0->m_data += sizeof(int); 31289857Sobrien } 31389857Sobrien 31489857Sobrien if (tp->tun_bpf) { 31589857Sobrien /* 31689857Sobrien * We need to prepend the address family as 31733965Sjdp * a four byte field. Cons up a dummy header 31889857Sobrien * to pacify bpf. This is safe because bpf 31989857Sobrien * will only read from the mbuf (i.e., it won't 32033965Sjdp * try to free it or keep a pointer to it). 32133965Sjdp */ 32233965Sjdp struct mbuf m; 32377298Sobrien u_int af = dst->sa_family; 32433965Sjdp 32533965Sjdp m.m_next = m0; 32633965Sjdp m.m_len = 4; 32733965Sjdp m.m_data = (char *)⁡ 32833965Sjdp 32933965Sjdp bpf_mtap(tp->tun_bpf, &m); 33033965Sjdp } 33133965Sjdp#endif 33233965Sjdp 33333965Sjdp switch(dst->sa_family) { 33433965Sjdp#ifdef INET 33533965Sjdp case AF_INET: 33633965Sjdp s = splimp(); 33733965Sjdp if (IF_QFULL(&ifp->if_snd)) { 33833965Sjdp IF_DROP(&ifp->if_snd); 33933965Sjdp m_freem(m0); 34033965Sjdp splx(s); 34133965Sjdp ifp->if_collisions++; 34233965Sjdp return (ENOBUFS); 34389857Sobrien } 34489857Sobrien IF_ENQUEUE(&ifp->if_snd, m0); 34589857Sobrien splx(s); 34689857Sobrien ifp->if_opackets++; 34789857Sobrien break; 34889857Sobrien#endif 34989857Sobrien default: 35089857Sobrien m_freem(m0); 35189857Sobrien return EAFNOSUPPORT; 35289857Sobrien } 35389857Sobrien 35489857Sobrien if (tp->tun_flags & TUN_RWAIT) { 35589857Sobrien tp->tun_flags &= ~TUN_RWAIT; 35689857Sobrien wakeup((caddr_t)tp); 35733965Sjdp } 35877298Sobrien if (tp->tun_flags & TUN_ASYNC && tp->tun_pgrp) { 359130561Sobrien if (tp->tun_pgrp > 0) 360130561Sobrien gsignal(tp->tun_pgrp, SIGIO); 361130561Sobrien else if (p = pfind(-tp->tun_pgrp)) 362130561Sobrien psignal(p, SIGIO); 363130561Sobrien } 36489857Sobrien selwakeup(&tp->tun_rsel); 36533965Sjdp return 0; 36633965Sjdp} 36733965Sjdp 36833965Sjdp/* 36933965Sjdp * the cdevsw interface is now pretty minimal. 37033965Sjdp */ 37133965Sjdpint 37233965Sjdptunioctl(dev, cmd, data, flag, p) 37333965Sjdp dev_t dev; 37433965Sjdp int cmd; 37533965Sjdp caddr_t data; 37633965Sjdp int flag; 37733965Sjdp struct proc *p; 37833965Sjdp{ 37933965Sjdp int unit = minor(dev), s; 38033965Sjdp struct tun_softc *tp = &tunctl[unit]; 38133965Sjdp struct tuninfo *tunp; 38233965Sjdp 38333965Sjdp switch (cmd) { 38433965Sjdp case TUNSIFINFO: 38589857Sobrien tunp = (struct tuninfo *)data; 38677298Sobrien tp->tun_if.if_mtu = tunp->mtu; 38733965Sjdp tp->tun_if.if_type = tunp->type; 38833965Sjdp tp->tun_if.if_baudrate = tunp->baudrate; 38933965Sjdp break; 39077298Sobrien case TUNGIFINFO: 39133965Sjdp tunp = (struct tuninfo *)data; 39233965Sjdp tunp->mtu = tp->tun_if.if_mtu; 39333965Sjdp tunp->type = tp->tun_if.if_type; 39433965Sjdp tunp->baudrate = tp->tun_if.if_baudrate; 39533965Sjdp break; 39633965Sjdp case TUNSDEBUG: 39733965Sjdp tundebug = *(int *)data; 39833965Sjdp break; 39933965Sjdp case TUNGDEBUG: 40033965Sjdp *(int *)data = tundebug; 40133965Sjdp break; 40233965Sjdp case FIONBIO: 40333965Sjdp if (*(int *)data) 40433965Sjdp tp->tun_flags |= TUN_NBIO; 405130561Sobrien else 406130561Sobrien tp->tun_flags &= ~TUN_NBIO; 40777298Sobrien break; 40889857Sobrien case FIOASYNC: 40989857Sobrien if (*(int *)data) 41089857Sobrien tp->tun_flags |= TUN_ASYNC; 41189857Sobrien else 41289857Sobrien tp->tun_flags &= ~TUN_ASYNC; 41389857Sobrien break; 41489857Sobrien case FIONREAD: 41589857Sobrien s = splimp(); 41689857Sobrien if (tp->tun_if.if_snd.ifq_head) 41789857Sobrien *(int *)data = tp->tun_if.if_snd.ifq_head->m_len; 41889857Sobrien else 41989857Sobrien *(int *)data = 0; 42089857Sobrien splx(s); 42189857Sobrien break; 42233965Sjdp case TIOCSPGRP: 42377298Sobrien tp->tun_pgrp = *(int *)data; 42489857Sobrien break; 42589857Sobrien case TIOCGPGRP: 42633965Sjdp *(int *)data = tp->tun_pgrp; 42733965Sjdp break; 42833965Sjdp default: 42933965Sjdp return (ENOTTY); 43033965Sjdp } 43133965Sjdp return (0); 43233965Sjdp} 43333965Sjdp 43433965Sjdp/* 43533965Sjdp * The cdevsw read interface - reads a packet at a time, or at 43633965Sjdp * least as much of a packet as can be read. 43733965Sjdp */ 43833965Sjdpint 43933965Sjdptunread(dev_t dev, struct uio *uio, int flag) 44033965Sjdp{ 44133965Sjdp int unit = minor(dev); 44233965Sjdp struct tun_softc *tp = &tunctl[unit]; 44333965Sjdp struct ifnet *ifp = &tp->tun_if; 44433965Sjdp struct mbuf *m, *m0; 44533965Sjdp int error=0, len, s; 44633965Sjdp 44733965Sjdp TUNDEBUG ("%s%d: read\n", ifp->if_name, ifp->if_unit); 44889857Sobrien if ((tp->tun_flags & TUN_READY) != TUN_READY) { 44977298Sobrien TUNDEBUG ("%s%d: not ready 0%o\n", ifp->if_name, 45033965Sjdp ifp->if_unit, tp->tun_flags); 45133965Sjdp return EHOSTDOWN; 45233965Sjdp } 45377298Sobrien 45433965Sjdp tp->tun_flags &= ~TUN_RWAIT; 45533965Sjdp 45633965Sjdp s = splimp(); 45733965Sjdp do { 45833965Sjdp IF_DEQUEUE(&ifp->if_snd, m0); 45977298Sobrien if (m0 == 0) { 46033965Sjdp if (tp->tun_flags & TUN_NBIO) { 46133965Sjdp splx(s); 46233965Sjdp return EWOULDBLOCK; 46333965Sjdp } 46433965Sjdp tp->tun_flags |= TUN_RWAIT; 46533965Sjdp tsleep((caddr_t)tp, PZERO + 1, "tunread", 0); 46633965Sjdp } 46733965Sjdp } while (m0 == 0); 46833965Sjdp splx(s); 46933965Sjdp 47033965Sjdp while (m0 && uio->uio_resid > 0 && error == 0) { 47177298Sobrien len = min(uio->uio_resid, m0->m_len); 47289857Sobrien if (len == 0) 47389857Sobrien break; 47489857Sobrien error = uiomove(mtod(m0, caddr_t), len, uio); 47589857Sobrien MFREE(m0, m); 47689857Sobrien m0 = m; 47789857Sobrien } 47889857Sobrien 47989857Sobrien if (m0) { 48089857Sobrien TUNDEBUG("Dropping mbuf\n"); 48189857Sobrien m_freem(m0); 48289857Sobrien } 48389857Sobrien return error; 48489857Sobrien} 48589857Sobrien 48633965Sjdp/* 48733965Sjdp * the cdevsw write interface - an atomic write is a packet - or else! 48833965Sjdp */ 48977298Sobrienint 49033965Sjdptunwrite(dev_t dev, struct uio *uio, int flag) 49133965Sjdp{ 49233965Sjdp int unit = minor (dev); 49333965Sjdp struct ifnet *ifp = &tunctl[unit].tun_if; 49433965Sjdp struct mbuf *top, **mp, *m; 49533965Sjdp int error=0, s, tlen, mlen; 49633965Sjdp 49733965Sjdp TUNDEBUG("%s%d: tunwrite\n", ifp->if_name, ifp->if_unit); 49833965Sjdp 49933965Sjdp if (uio->uio_resid < 0 || uio->uio_resid > TUNMTU) { 50033965Sjdp TUNDEBUG("%s%d: len=%d!\n", ifp->if_name, ifp->if_unit, 50133965Sjdp uio->uio_resid); 50233965Sjdp return EIO; 50333965Sjdp } 504130561Sobrien tlen = uio->uio_resid; 505130561Sobrien 50677298Sobrien /* get a header mbuf */ 50789857Sobrien MGETHDR(m, M_DONTWAIT, MT_DATA); 50889857Sobrien if (m == NULL) 50989857Sobrien return ENOBUFS; 51089857Sobrien mlen = MHLEN; 51189857Sobrien 51289857Sobrien top = 0; 51389857Sobrien mp = ⊤ 51489857Sobrien while (error == 0 && uio->uio_resid > 0) { 51589857Sobrien m->m_len = min(mlen, uio->uio_resid); 51689857Sobrien error = uiomove(mtod (m, caddr_t), m->m_len, uio); 51789857Sobrien *mp = m; 51889857Sobrien mp = &m->m_next; 51989857Sobrien if (uio->uio_resid > 0) { 52089857Sobrien MGET (m, M_DONTWAIT, MT_DATA); 52133965Sjdp if (m == 0) { 52233965Sjdp error = ENOBUFS; 52333965Sjdp break; 52477298Sobrien } 52533965Sjdp mlen = MLEN; 52633965Sjdp } 52733965Sjdp } 52833965Sjdp if (error) { 52933965Sjdp if (top) 53033965Sjdp m_freem (top); 53133965Sjdp return error; 53233965Sjdp } 53333965Sjdp 53433965Sjdp top->m_pkthdr.len = tlen; 53533965Sjdp top->m_pkthdr.rcvif = ifp; 53633965Sjdp 53733965Sjdp#if NBPFILTER > 0 53833965Sjdp if (tunctl[unit].tun_bpf) { 53933965Sjdp /* 54077298Sobrien * We need to prepend the address family as 54189857Sobrien * a four byte field. Cons up a dummy header 54289857Sobrien * to pacify bpf. This is safe because bpf 54333965Sjdp * will only read from the mbuf (i.e., it won't 544130561Sobrien * try to free it or keep a pointer to it). 545130561Sobrien */ 546130561Sobrien struct mbuf m; 547130561Sobrien u_int af = AF_INET; 54833965Sjdp 549130561Sobrien m.m_next = top; 550130561Sobrien m.m_len = 4; 551130561Sobrien m.m_data = (char *)⁡ 552130561Sobrien 553130561Sobrien bpf_mtap(tunctl[unit].tun_bpf, &m); 554130561Sobrien } 555130561Sobrien#endif 556130561Sobrien 557130561Sobrien s = splimp(); 558130561Sobrien if (IF_QFULL (&ipintrq)) { 559130561Sobrien IF_DROP(&ipintrq); 560130561Sobrien splx(s); 561130561Sobrien ifp->if_collisions++; 562130561Sobrien m_freem(top); 563130561Sobrien return ENOBUFS; 564130561Sobrien } 565130561Sobrien IF_ENQUEUE(&ipintrq, top); 566130561Sobrien splx(s); 567130561Sobrien ifp->if_ipackets++; 568130561Sobrien schednetisr(NETISR_IP); 569130561Sobrien return error; 570130561Sobrien} 571130561Sobrien 572130561Sobrien/* 573130561Sobrien * tunselect - the select interface, this is only useful on reads 574130561Sobrien * really. The write detect always returns true, write never blocks 575130561Sobrien * anyway, it either accepts the packet or drops it. 576130561Sobrien */ 577130561Sobrienint 578130561Sobrientunselect(dev_t dev, int rw, struct proc *p) 579130561Sobrien{ 58033965Sjdp int unit = minor(dev), s; 58133965Sjdp struct tun_softc *tp = &tunctl[unit]; 58277298Sobrien struct ifnet *ifp = &tp->tun_if; 58333965Sjdp 58433965Sjdp s = splimp(); 58533965Sjdp TUNDEBUG("%s%d: tunselect\n", ifp->if_name, ifp->if_unit); 58633965Sjdp 58733965Sjdp switch (rw) { 58833965Sjdp case FREAD: 58933965Sjdp if (ifp->if_snd.ifq_len > 0) { 59033965Sjdp splx(s); 59133965Sjdp TUNDEBUG("%s%d: tunselect q=%d\n", ifp->if_name, 59233965Sjdp ifp->if_unit, ifp->if_snd.ifq_len); 59333965Sjdp return 1; 59433965Sjdp } 59533965Sjdp selrecord(p, &tp->tun_rsel); 59633965Sjdp break; 597130561Sobrien case FWRITE: 598130561Sobrien splx(s); 59977298Sobrien return 1; 60089857Sobrien } 60189857Sobrien splx(s); 60233965Sjdp TUNDEBUG("%s%d: tunselect waiting\n", ifp->if_name, ifp->if_unit); 603130561Sobrien return 0; 604130561Sobrien} 605130561Sobrien 606130561Sobrien#endif /* NTUN */ 607130561Sobrien