if_tun.c revision 121778
1133251Simp/* $NetBSD: if_tun.c,v 1.14 1994/06/29 06:36:25 cgd Exp $ */ 241967Sdillon 3133251Simp/* 4133251Simp * Copyright (c) 1988, Julian Onions <jpo@cs.nott.ac.uk> 5133251Simp * Nottingham University 1987. 6133251Simp * 7133251Simp * This source may be freely distributed, however I would be interested 8133251Simp * in any changes that are made. 9133251Simp * 10133251Simp * This driver takes packets off the IP i/f and hands them up to a 11133251Simp * user process to have its wicked way with. This driver has it's 12133251Simp * roots in a similar driver written by Phil Cockcroft (formerly) at 13133251Simp * UCL. This driver is based much more on read/write/poll mode of 14133251Simp * operation though. 15133251Simp * 16133251Simp * $FreeBSD: head/sys/net/if_tun.c 121778 2003-10-31 02:48:12Z brooks $ 17133251Simp */ 18133251Simp 19133251Simp#include "opt_atalk.h" 20133251Simp#include "opt_inet.h" 21133251Simp#include "opt_inet6.h" 22133251Simp#include "opt_ipx.h" 23133251Simp#include "opt_mac.h" 2450476Speter 2541967Sdillon#include <sys/param.h> 26260084Spluknet#include <sys/proc.h> 2741967Sdillon#include <sys/systm.h> 2879538Sru#include <sys/mac.h> 2941967Sdillon#include <sys/mbuf.h> 3041967Sdillon#include <sys/module.h> 31158489Skeramida#include <sys/socket.h> 3241967Sdillon#include <sys/filio.h> 3341967Sdillon#include <sys/sockio.h> 3441967Sdillon#include <sys/ttycom.h> 3541967Sdillon#include <sys/poll.h> 3651372Sdillon#include <sys/signalvar.h> 3790814Srwatson#include <sys/filedesc.h> 38130524Sru#include <sys/kernel.h> 3944389Sghelmer#include <sys/sysctl.h> 40130524Sru#include <sys/conf.h> 41130524Sru#include <sys/uio.h> 4241967Sdillon#include <sys/vnode.h> 4379727Sschweikh#include <sys/malloc.h> 4444389Sghelmer#include <machine/bus.h> /* XXX Shouldn't really be required ! */ 4544389Sghelmer#include <sys/random.h> 4642062Sobrien#include <sys/rman.h> 47130524Sru 48130524Sru#include <net/if.h> 49130524Sru#include <net/if_types.h> 5041967Sdillon#include <net/netisr.h> 5141967Sdillon#include <net/route.h> 5241967Sdillon#ifdef INET 53130524Sru#include <netinet/in.h> 54130524Sru#endif 5551372Sdillon#include <net/bpf.h> 56130524Sru#include <net/if_tunvar.h> 5751372Sdillon#include <net/if_tun.h> 58130524Sru 5951372Sdillon#define TUNDEBUG if (tundebug) if_printf 60130524Sru#define TUNNAME "tun" 61130524Sru 6251372Sdillonstatic MALLOC_DEFINE(M_TUN, TUNNAME, "Tunnel Interface"); 6341967Sdillonstatic int tundebug = 0; 6441967Sdillonstatic struct tun_softc *tunhead = NULL; 65130524Srustatic struct rman tununits; 6641967Sdillonstatic udev_t tunbasedev = NOUDEV; 6741967SdillonSYSCTL_INT(_debug, OID_AUTO, if_tun_debug, CTLFLAG_RW, &tundebug, 0, ""); 6841967Sdillon 6942062Sobrienstatic void tunclone(void *arg, char *name, int namelen, dev_t *dev); 7041967Sdillonstatic void tuncreate(dev_t dev); 7142062Sobrienstatic int tunifioctl(struct ifnet *, u_long, caddr_t); 7251372Sdillonstatic int tuninit(struct ifnet *); 7351372Sdillonstatic int tunmodevent(module_t, int, void *); 7441967Sdillonstatic int tunoutput(struct ifnet *, struct mbuf *, struct sockaddr *, 7541967Sdillon struct rtentry *rt); 7641967Sdillonstatic void tunstart(struct ifnet *); 77130524Sru 78130524Srustatic d_open_t tunopen; 7941967Sdillonstatic d_close_t tunclose; 80130524Srustatic d_read_t tunread; 81130524Srustatic d_write_t tunwrite; 82130524Srustatic d_ioctl_t tunioctl; 83130524Srustatic d_poll_t tunpoll; 84130524Sru 85130524Sru#define CDEV_MAJOR 52 8651372Sdillonstatic struct cdevsw tun_cdevsw = { 87130524Sru .d_open = tunopen, 88130524Sru .d_close = tunclose, 89130524Sru .d_read = tunread, 9089127Smpp .d_write = tunwrite, 91201539Sbrueffer .d_ioctl = tunioctl, 9251372Sdillon .d_poll = tunpoll, 9341967Sdillon .d_name = TUNNAME, 94130524Sru .d_maj = CDEV_MAJOR, 95130524Sru}; 96130524Sru 97130524Srustatic void 98130524Srutunclone(void *arg, char *name, int namelen, dev_t *dev) 99130524Sru{ 100130524Sru struct resource *r; 101130524Sru int err; 102130524Sru int u; 103130524Sru 104130524Sru if (*dev != NODEV) 105130524Sru return; 10641967Sdillon 107130524Sru if (strcmp(name, TUNNAME) == 0) { 108130524Sru r = rman_reserve_resource(&tununits, 0, IF_MAXUNIT, 1, 109130524Sru RF_ALLOCATED | RF_ACTIVE, NULL); 11051372Sdillon u = rman_get_start(r); 11141967Sdillon err = rman_release_resource(r); 11241967Sdillon KASSERT(err == 0, ("Unexpected failure releasing resource")); 11341967Sdillon *dev = makedev(CDEV_MAJOR, unit2minor(u)); 114130524Sru if ((*dev)->si_flags & SI_NAMED) 115130524Sru return; /* Already make_dev()d */ 11641967Sdillon } else if (dev_stdclone(name, NULL, TUNNAME, &u) != 1) 117130524Sru return; /* Don't recognise the name */ 118130524Sru 11941967Sdillon *dev = make_dev(&tun_cdevsw, unit2minor(u), 12086875Sdd UID_ROOT, GID_WHEEL, 0600, "tun%d", u); 12151372Sdillon 12289127Smpp /* 12341967Sdillon * All devices depend on tunbasedev so that we can simply 12479727Sschweikh * destroy_dev() this device at module unload time to get 125130524Sru * rid of all our make_dev()d resources. 126130524Sru */ 12751372Sdillon if (tunbasedev == NOUDEV) 12841967Sdillon tunbasedev = (*dev)->si_udev; 129130524Sru else { 13079727Sschweikh (*dev)->si_flags |= SI_CHEAPCLONE; 131130524Sru dev_depends(udev2dev(tunbasedev, 0), *dev); 132130524Sru } 13360258Ssheldonh} 13451372Sdillon 135130524Srustatic int 136130524Srutunmodevent(module_t mod, int type, void *data) 137130524Sru{ 138130524Sru static eventhandler_tag tag; 139129397Sdannyboy struct tun_softc *tp; 140129400Sdannyboy dev_t dev; 141219126Sbrucec int err; 14241967Sdillon 14351372Sdillon switch (type) { 144130524Sru case MOD_LOAD: 14541967Sdillon tag = EVENTHANDLER_REGISTER(dev_clone, tunclone, 0, 1000); 14641967Sdillon if (tag == NULL) 14741967Sdillon return (ENOMEM); 14841967Sdillon tununits.rm_type = RMAN_ARRAY; 14941967Sdillon tununits.rm_descr = "open if_tun units"; 150130524Sru err = rman_init(&tununits); 15141967Sdillon if (err != 0) { 15241967Sdillon EVENTHANDLER_DEREGISTER(dev_clone, tag); 15341967Sdillon return (err); 15479727Sschweikh } 15541967Sdillon err = rman_manage_region(&tununits, 0, IF_MAXUNIT); 156107788Sru if (err != 0) { 15741967Sdillon printf("%s: tununits: rman_manage_region: Failed %d\n", 15851372Sdillon TUNNAME, err); 15941967Sdillon rman_fini(&tununits); 16041967Sdillon EVENTHANDLER_DEREGISTER(dev_clone, tag); 16141967Sdillon return (err); 16241967Sdillon } 163130524Sru break; 164130524Sru case MOD_UNLOAD: 165130524Sru err = rman_fini(&tununits); 166130524Sru if (err != 0) 16744389Sghelmer return (err); 168130524Sru EVENTHANDLER_DEREGISTER(dev_clone, tag); 169130524Sru 170130524Sru while (tunhead != NULL) { 171130524Sru KASSERT((tunhead->tun_flags & TUN_OPEN) == 0, 17251372Sdillon ("tununits is out of sync - unit %d", 17351372Sdillon tunhead->tun_if.if_unit)); 17451372Sdillon tp = tunhead; 17551372Sdillon dev = makedev(tun_cdevsw.d_maj, 176130524Sru unit2minor(tp->tun_if.if_unit)); 177130524Sru KASSERT(dev->si_drv1 == tp, ("Bad makedev result")); 178201736Sdanger tunhead = tp->next; 17979727Sschweikh bpfdetach(&tp->tun_if); 180130524Sru if_detach(&tp->tun_if); 18151372Sdillon KASSERT(dev->si_flags & SI_NAMED, ("Missing make_dev")); 182130524Sru free(tp, M_TUN); 183130524Sru } 184130524Sru 185130524Sru /* 186130524Sru * Destroying tunbasedev results in all of our make_dev()s 187130524Sru * conveniently going away. 188130524Sru */ 189130524Sru if (tunbasedev != NOUDEV) 190130524Sru destroy_dev(udev2dev(tunbasedev, 0)); 191130524Sru 192130524Sru break; 193130524Sru } 194130524Sru return 0; 195130524Sru} 19651372Sdillon 19741967Sdillonstatic moduledata_t tun_mod = { 19842015Sdillon "if_tun", 199130524Sru tunmodevent, 200130524Sru 0 201130524Sru}; 202130524Sru 203130524SruDECLARE_MODULE(if_tun, tun_mod, SI_SUB_PSEUDO, SI_ORDER_ANY); 204130524Sru 205130524Srustatic void 20681251Srutunstart(struct ifnet *ifp) 207130524Sru{ 208130524Sru struct tun_softc *tp = ifp->if_softc; 209130524Sru 210130524Sru if (tp->tun_flags & TUN_RWAIT) { 211130524Sru tp->tun_flags &= ~TUN_RWAIT; 212130524Sru wakeup(tp); 213130524Sru } 214130524Sru if (tp->tun_flags & TUN_ASYNC && tp->tun_sigio) 215130524Sru pgsigio(&tp->tun_sigio, SIGIO, 0); 216130524Sru selwakeup(&tp->tun_rsel); 217130524Sru} 218130524Sru 219130524Srustatic void 220130524Srutuncreate(dev_t dev) 221130524Sru{ 222130524Sru struct tun_softc *sc; 223130524Sru struct ifnet *ifp; 224130524Sru 225130524Sru if (!(dev->si_flags & SI_NAMED)) 226130524Sru dev = make_dev(&tun_cdevsw, minor(dev), 227130524Sru UID_UUCP, GID_DIALER, 0600, "tun%d", dev2unit(dev)); 228130524Sru 229130524Sru MALLOC(sc, struct tun_softc *, sizeof(*sc), M_TUN, M_WAITOK | M_ZERO); 230130524Sru sc->tun_flags = TUN_INITED; 231130524Sru sc->next = tunhead; 23251372Sdillon tunhead = sc; 23351372Sdillon 234130524Sru ifp = &sc->tun_if; 235130524Sru ifp->if_unit = dev2unit(dev); 236130524Sru ifp->if_name = TUNNAME; 237130524Sru ifp->if_mtu = TUNMTU; 238130524Sru ifp->if_ioctl = tunifioctl; 239130524Sru ifp->if_output = tunoutput; 240130524Sru ifp->if_start = tunstart; 24151372Sdillon ifp->if_flags = IFF_POINTOPOINT | IFF_MULTICAST; 242130524Sru ifp->if_type = IFT_PPP; 243130524Sru ifp->if_snd.ifq_maxlen = ifqmaxlen; 244130524Sru ifp->if_softc = sc; 245130524Sru if_attach(ifp); 246130524Sru bpfattach(ifp, DLT_NULL, sizeof(u_int)); 24751372Sdillon dev->si_drv1 = sc; 24841967Sdillon} 24941967Sdillon 25041967Sdillonstatic int 251130524Srutunopen(dev_t dev, int flag, int mode, struct thread *td) 252130524Sru{ 253129397Sdannyboy struct resource *r; 254129397Sdannyboy struct ifnet *ifp; 255130524Sru struct tun_softc *tp; 256130524Sru int unit; 25779727Sschweikh 258140573Sru unit = dev2unit(dev); 25944389Sghelmer if (unit > IF_MAXUNIT) 26044389Sghelmer return (ENXIO); 26144389Sghelmer 262130524Sru r = rman_reserve_resource(&tununits, unit, unit, 1, 263130524Sru RF_ALLOCATED | RF_ACTIVE, NULL); 264130524Sru if (r == NULL) 265130524Sru return (EBUSY); 266130524Sru 267130524Sru dev->si_flags &= ~SI_CHEAPCLONE; 26881251Sru 26944389Sghelmer tp = dev->si_drv1; 27079727Sschweikh if (!tp) { 27144389Sghelmer tuncreate(dev); 27244389Sghelmer tp = dev->si_drv1; 27344389Sghelmer } 27442062Sobrien KASSERT(!(tp->tun_flags & TUN_OPEN), ("Resource & flags out-of-sync")); 275130524Sru tp->tun_unit = r; 276130524Sru tp->tun_pid = td->td_proc->p_pid; 27741967Sdillon ifp = &tp->tun_if; 278130524Sru tp->tun_flags |= TUN_OPEN; 27941967Sdillon TUNDEBUG(ifp, "open\n"); 28041967Sdillon 28141967Sdillon return (0); 282130524Sru} 283130524Sru 284130524Sru/* 285130524Sru * tunclose - close the device - mark i/f down & delete 286130524Sru * routing info 28779727Sschweikh */ 28844389Sghelmerstatic int 28944389Sghelmertunclose(dev_t dev, int foo, int bar, struct thread *td) 290130524Sru{ 29141967Sdillon struct tun_softc *tp; 29242062Sobrien struct ifnet *ifp; 29342015Sdillon int s; 29441967Sdillon int err; 29541967Sdillon 296130524Sru tp = dev->si_drv1; 29741967Sdillon ifp = &tp->tun_if; 298130524Sru 299130524Sru KASSERT(tp->tun_unit, ("Unit %d not marked open", ifp->if_unit)); 30079727Sschweikh tp->tun_flags &= ~TUN_OPEN; 301130524Sru tp->tun_pid = 0; 302130524Sru 303130524Sru /* 304130524Sru * junk all pending output 305130524Sru */ 30644389Sghelmer IF_DRAIN(&ifp->if_snd); 30781251Sru 308130524Sru if (ifp->if_flags & IFF_UP) { 309130524Sru s = splimp(); 310130524Sru if_down(ifp); 311130524Sru splx(s); 312130524Sru } 313130524Sru 314130524Sru if (ifp->if_flags & IFF_RUNNING) { 315148011Sbrueffer struct ifaddr *ifa; 316130524Sru 317130524Sru s = splimp(); 318130524Sru /* find internet addresses and delete routes */ 319130524Sru TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) 320130524Sru if (ifa->ifa_addr->sa_family == AF_INET) 321130524Sru rtinit(ifa, (int)RTM_DELETE, 322130524Sru tp->tun_flags & TUN_DSTADDR ? RTF_HOST : 0); 323130524Sru ifp->if_flags &= ~IFF_RUNNING; 324130524Sru splx(s); 325130524Sru } 326130524Sru 327130524Sru funsetown(&tp->tun_sigio); 328130524Sru selwakeup(&tp->tun_rsel); 329130524Sru 330130524Sru TUNDEBUG (ifp, "closed\n"); 33141967Sdillon err = rman_release_resource(tp->tun_unit); 332130524Sru KASSERT(err == 0, ("Unit %d failed to release", ifp->if_unit)); 333130524Sru 334130524Sru return (0); 335130524Sru} 33641967Sdillon 337130524Srustatic int 338130524Srutuninit(struct ifnet *ifp) 339130524Sru{ 340130524Sru struct tun_softc *tp = ifp->if_softc; 341130524Sru struct ifaddr *ifa; 342130524Sru int error = 0; 343130524Sru 344130524Sru TUNDEBUG(ifp, "tuninit\n"); 34541967Sdillon 34650911Sphantom ifp->if_flags |= IFF_UP | IFF_RUNNING; 347130524Sru getmicrotime(&ifp->if_lastchange); 348130524Sru 349130524Sru for (ifa = TAILQ_FIRST(&ifp->if_addrhead); ifa; 350130524Sru ifa = TAILQ_NEXT(ifa, ifa_link)) { 351130524Sru if (ifa->ifa_addr == NULL) 352130524Sru error = EFAULT; 353130524Sru /* XXX: Should maybe return straight off? */ 35441967Sdillon else { 355130524Sru#ifdef INET 356130524Sru if (ifa->ifa_addr->sa_family == AF_INET) { 35742015Sdillon struct sockaddr_in *si; 35841967Sdillon 35941967Sdillon si = (struct sockaddr_in *)ifa->ifa_addr; 360130524Sru if (si->sin_addr.s_addr) 361130524Sru tp->tun_flags |= TUN_IASET; 362130524Sru 363130524Sru si = (struct sockaddr_in *)ifa->ifa_dstaddr; 364130524Sru if (si && si->sin_addr.s_addr) 365130524Sru tp->tun_flags |= TUN_DSTADDR; 366148140Sschweikh } 36744389Sghelmer#endif 36881251Sru } 36944389Sghelmer } 37042062Sobrien return (error); 37141967Sdillon} 37241967Sdillon 373130524Sru/* 374130524Sru * Process an ioctl request. 375130524Sru */ 376130524Srustatic int 37744389Sghelmertunifioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 378130524Sru{ 37944389Sghelmer struct ifreq *ifr = (struct ifreq *)data; 38044389Sghelmer struct tun_softc *tp = ifp->if_softc; 38144389Sghelmer struct ifstat *ifs; 382130524Sru int error = 0, s; 383130524Sru 384130524Sru s = splimp(); 385130524Sru switch(cmd) { 386148011Sbrueffer case SIOCGIFSTATUS: 387130524Sru ifs = (struct ifstat *)data; 38844389Sghelmer if (tp->tun_pid) 389130524Sru sprintf(ifs->ascii + strlen(ifs->ascii), 39041967Sdillon "\tOpened by PID %d\n", tp->tun_pid); 39144389Sghelmer break; 392130524Sru case SIOCSIFADDR: 393130524Sru error = tuninit(ifp); 394130524Sru TUNDEBUG(ifp, "address set, error=%d\n", error); 395130524Sru break; 396130524Sru case SIOCSIFDSTADDR: 397130524Sru error = tuninit(ifp); 398130524Sru TUNDEBUG(ifp, "destination address set, error=%d\n", error); 39944389Sghelmer break; 40044389Sghelmer case SIOCSIFMTU: 40144389Sghelmer ifp->if_mtu = ifr->ifr_mtu; 402130524Sru TUNDEBUG(ifp, "mtu set\n"); 403130524Sru break; 404130524Sru case SIOCSIFFLAGS: 405130524Sru case SIOCADDMULTI: 406130524Sru case SIOCDELMULTI: 407130524Sru break; 408130524Sru default: 409130524Sru error = EINVAL; 410130524Sru } 411130524Sru splx(s); 412130524Sru return (error); 41351372Sdillon} 41479727Sschweikh 41579727Sschweikh/* 41641967Sdillon * tunoutput - queue packets from higher level ready to put out. 41741967Sdillon */ 41841967Sdillonstatic int 419130524Srutunoutput( 420130524Sru struct ifnet *ifp, 421130524Sru struct mbuf *m0, 422130524Sru struct sockaddr *dst, 423130524Sru struct rtentry *rt) 42441967Sdillon{ 425130524Sru struct tun_softc *tp = ifp->if_softc; 426130524Sru#ifdef MAC 427130524Sru int error; 428130524Sru#endif 42979727Sschweikh 43051372Sdillon TUNDEBUG (ifp, "tunoutput\n"); 43151372Sdillon 43241967Sdillon#ifdef MAC 43379727Sschweikh error = mac_check_ifnet_transmit(ifp, m0); 434130524Sru if (error) { 435130524Sru m_freem(m0); 43644389Sghelmer return (error); 43744389Sghelmer } 43844389Sghelmer#endif 43979727Sschweikh 44041967Sdillon if ((tp->tun_flags & TUN_READY) != TUN_READY) { 44141967Sdillon TUNDEBUG (ifp, "not ready 0%o\n", tp->tun_flags); 44279727Sschweikh m_freem (m0); 44344389Sghelmer return (EHOSTDOWN); 44481251Sru } 445130524Sru 44681251Sru if ((ifp->if_flags & IFF_UP) != IFF_UP) { 447107788Sru m_freem (m0); 44841967Sdillon return (EHOSTDOWN); 449130524Sru } 450130524Sru 451130524Sru /* BPF write needs to be handled specially */ 45250911Sphantom if (dst->sa_family == AF_UNSPEC) { 45344389Sghelmer dst->sa_family = *(mtod(m0, int *)); 45444389Sghelmer m0->m_len -= sizeof(int); 455130524Sru m0->m_pkthdr.len -= sizeof(int); 456130524Sru m0->m_data += sizeof(int); 457130524Sru } 458130524Sru 459130524Sru if (ifp->if_bpf) { 460130524Sru /* 461130524Sru * We need to prepend the address family as 462130524Sru * a four byte field. Cons up a dummy header 46341967Sdillon * to pacify bpf. This is safe because bpf 464130524Sru * will only read from the mbuf (i.e., it won't 465130524Sru * try to free it or keep a pointer to it). 466130524Sru */ 46744389Sghelmer struct mbuf m; 46844389Sghelmer uint32_t af = dst->sa_family; 46944389Sghelmer 470130524Sru m.m_next = m0; 471130524Sru m.m_len = 4; 47251372Sdillon m.m_data = (char *)⁡ 47351372Sdillon 47444389Sghelmer BPF_MTAP(ifp, &m); 47579727Sschweikh } 476130524Sru 477130524Sru /* prepend sockaddr? this may abort if the mbuf allocation fails */ 478130524Sru if (tp->tun_flags & TUN_LMODE) { 47944389Sghelmer /* allocate space for sockaddr */ 480149766Sgarys M_PREPEND(m0, dst->sa_len, M_DONTWAIT); 481149766Sgarys 482130524Sru /* if allocation failed drop packet */ 483130524Sru if (m0 == NULL) { 484130524Sru ifp->if_iqdrops++; 485130524Sru ifp->if_oerrors++; 486130524Sru return (ENOBUFS); 487149766Sgarys } else { 488130524Sru bcopy(dst, m0->m_data, dst->sa_len); 489130524Sru } 490130524Sru } 491130524Sru 492130524Sru if (tp->tun_flags & TUN_IFHEAD) { 493130524Sru /* Prepend the address family */ 49444389Sghelmer M_PREPEND(m0, 4, M_DONTWAIT); 495130524Sru 49644389Sghelmer /* if allocation failed drop packet */ 497149766Sgarys if (m0 == NULL) { 498149766Sgarys ifp->if_iqdrops++; 499130524Sru ifp->if_oerrors++; 500149766Sgarys return (ENOBUFS); 501130524Sru } else 502149766Sgarys *(u_int32_t *)m0->m_data = htonl(dst->sa_family); 503130524Sru } else { 504130524Sru#ifdef INET 505130524Sru if (dst->sa_family != AF_INET) 506130524Sru#endif 507130524Sru { 508130524Sru m_freem(m0); 509130524Sru return (EAFNOSUPPORT); 510130524Sru } 511130524Sru } 512130524Sru 51351372Sdillon if (! IF_HANDOFF(&ifp->if_snd, m0, ifp)) { 51451372Sdillon ifp->if_collisions++; 515149766Sgarys return (ENOBUFS); 516149766Sgarys } 517149766Sgarys ifp->if_opackets++; 518149766Sgarys return (0); 519149766Sgarys} 520149766Sgarys 521149766Sgarys/* 522149766Sgarys * the cdevsw interface is now pretty minimal. 523149766Sgarys */ 524149766Sgarysstatic int 525149766Sgarystunioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct thread *td) 526149766Sgarys{ 527149766Sgarys int s; 528149766Sgarys int error; 529149766Sgarys struct tun_softc *tp = dev->si_drv1; 530149766Sgarys struct tuninfo *tunp; 531160306Skeramida 532160306Skeramida switch (cmd) { 533149766Sgarys case TUNSIFINFO: 534160306Skeramida tunp = (struct tuninfo *)data; 535149766Sgarys if (tunp->mtu < IF_MINMTU) 536160306Skeramida return (EINVAL); 537149766Sgarys if (tp->tun_if.if_mtu != tunp->mtu 538149766Sgarys && (error = suser(td)) != 0) 539149766Sgarys return (error); 540226089Sobrien tp->tun_if.if_mtu = tunp->mtu; 541226089Sobrien tp->tun_if.if_type = tunp->type; 542226089Sobrien tp->tun_if.if_baudrate = tunp->baudrate; 543226089Sobrien break; 544226089Sobrien case TUNGIFINFO: 545226089Sobrien tunp = (struct tuninfo *)data; 546149766Sgarys tunp->mtu = tp->tun_if.if_mtu; 547149766Sgarys tunp->type = tp->tun_if.if_type; 548149766Sgarys tunp->baudrate = tp->tun_if.if_baudrate; 549149766Sgarys break; 550149766Sgarys case TUNSDEBUG: 551149766Sgarys tundebug = *(int *)data; 552149766Sgarys break; 553149766Sgarys case TUNGDEBUG: 554149766Sgarys *(int *)data = tundebug; 555149766Sgarys break; 556149766Sgarys case TUNSLMODE: 557149766Sgarys if (*(int *)data) { 558149766Sgarys tp->tun_flags |= TUN_LMODE; 559149766Sgarys tp->tun_flags &= ~TUN_IFHEAD; 560149766Sgarys } else 561149766Sgarys tp->tun_flags &= ~TUN_LMODE; 562149766Sgarys break; 563149766Sgarys case TUNSIFHEAD: 564149766Sgarys if (*(int *)data) { 565149766Sgarys tp->tun_flags |= TUN_IFHEAD; 566149766Sgarys tp->tun_flags &= ~TUN_LMODE; 567149766Sgarys } else 568149766Sgarys tp->tun_flags &= ~TUN_IFHEAD; 569149766Sgarys break; 570149766Sgarys case TUNGIFHEAD: 571149766Sgarys *(int *)data = (tp->tun_flags & TUN_IFHEAD) ? 1 : 0; 572149766Sgarys break; 573149766Sgarys case TUNSIFMODE: 574154558Sceri /* deny this if UP */ 575231244Sgjb if (tp->tun_if.if_flags & IFF_UP) 57641967Sdillon return(EBUSY); 57741967Sdillon 57841967Sdillon switch (*(int *)data & ~IFF_MULTICAST) { 579130524Sru case IFF_POINTOPOINT: 580130524Sru case IFF_BROADCAST: 581130524Sru tp->tun_if.if_flags &= 582130524Sru ~(IFF_BROADCAST|IFF_POINTOPOINT|IFF_MULTICAST); 583130524Sru tp->tun_if.if_flags |= *(int *)data; 584130524Sru break; 585130524Sru default: 586130524Sru return(EINVAL); 587130524Sru } 588130524Sru break; 589130524Sru case TUNSIFPID: 590130524Sru tp->tun_pid = curthread->td_proc->p_pid; 591129397Sdannyboy break; 59251372Sdillon case FIONBIO: 593130524Sru break; 594130524Sru case FIOASYNC: 595108260Sru if (*(int *)data) 596129400Sdannyboy tp->tun_flags |= TUN_ASYNC; 59751372Sdillon else 59841967Sdillon tp->tun_flags &= ~TUN_ASYNC; 59951372Sdillon break; 600130524Sru case FIONREAD: 601130524Sru s = splimp(); 60251372Sdillon if (tp->tun_if.if_snd.ifq_head) { 60351372Sdillon struct mbuf *mb = tp->tun_if.if_snd.ifq_head; 60479727Sschweikh for( *(int *)data = 0; mb != 0; mb = mb->m_next) 605129397Sdannyboy *(int *)data += mb->m_len; 60651372Sdillon } else 60751372Sdillon *(int *)data = 0; 60851372Sdillon splx(s); 609130524Sru break; 610130524Sru case FIOSETOWN: 611130524Sru return (fsetown(*(int *)data, &tp->tun_sigio)); 612129397Sdannyboy 613130524Sru case FIOGETOWN: 614130524Sru *(int *)data = fgetown(&tp->tun_sigio); 61551372Sdillon return (0); 616130524Sru 617130524Sru /* This is deprecated, FIOSETOWN should be used instead. */ 61851372Sdillon case TIOCSPGRP: 619130524Sru return (fsetown(-(*(int *)data), &tp->tun_sigio)); 620130524Sru 62151372Sdillon /* This is deprecated, FIOGETOWN should be used instead. */ 62251372Sdillon case TIOCGPGRP: 62379727Sschweikh *(int *)data = -fgetown(&tp->tun_sigio); 624130524Sru return (0); 625130524Sru 62651372Sdillon default: 62751372Sdillon return (ENOTTY); 62844389Sghelmer } 629130524Sru return (0); 630130524Sru} 63151372Sdillon 632130524Sru/* 63351382Sdillon * The cdevsw read interface - reads a packet at a time, or at 63451382Sdillon * least as much of a packet as can be read. 63551382Sdillon */ 63651382Sdillonstatic int 637130524Srutunread(dev_t dev, struct uio *uio, int flag) 638130524Sru{ 63951372Sdillon struct tun_softc *tp = dev->si_drv1; 640130524Sru struct ifnet *ifp = &tp->tun_if; 641130524Sru struct mbuf *m; 642130524Sru int error=0, len, s; 64351372Sdillon 64451372Sdillon TUNDEBUG (ifp, "read\n"); 64551372Sdillon if ((tp->tun_flags & TUN_READY) != TUN_READY) { 646130524Sru TUNDEBUG (ifp, "not ready 0%o\n", tp->tun_flags); 64741967Sdillon return (EHOSTDOWN); 648130524Sru } 649130524Sru 650130524Sru tp->tun_flags &= ~TUN_RWAIT; 651130524Sru 65251372Sdillon s = splimp(); 653130524Sru do { 654130524Sru IF_DEQUEUE(&ifp->if_snd, m); 655130524Sru if (m == NULL) { 656130524Sru if (flag & IO_NDELAY) { 657130524Sru splx(s); 658130524Sru return (EWOULDBLOCK); 659130524Sru } 660130524Sru tp->tun_flags |= TUN_RWAIT; 661130524Sru if((error = tsleep(tp, PCATCH | (PZERO + 1), 662130524Sru "tunread", 0)) != 0) { 66351372Sdillon splx(s); 66441967Sdillon return (error); 66541967Sdillon } 66651382Sdillon } 667130524Sru } while (m == NULL); 668131530Sru splx(s); 66941967Sdillon 67051372Sdillon while (m && uio->uio_resid > 0 && error == 0) { 671130524Sru len = min(uio->uio_resid, m->m_len); 672130524Sru if (len != 0) 673138188Sru error = uiomove(mtod(m, void *), len, uio); 674130524Sru m = m_free(m); 675130524Sru } 676130524Sru 677138188Sru if (m) { 67881251Sru TUNDEBUG(ifp, "Dropping mbuf\n"); 67981251Sru m_freem(m); 680138188Sru } 681130524Sru return (error); 68251372Sdillon} 683125973Sceri 68441967Sdillon/* 68544389Sghelmer * the cdevsw write interface - an atomic write is a packet - or else! 68681251Sru */ 68781251Srustatic int 68844389Sghelmertunwrite(dev_t dev, struct uio *uio, int flag) 68942062Sobrien{ 690130524Sru struct tun_softc *tp = dev->si_drv1; 691130524Sru struct ifnet *ifp = &tp->tun_if; 69251372Sdillon struct mbuf *top, **mp, *m; 69342062Sobrien int error=0, tlen, mlen; 69441967Sdillon uint32_t family; 69541967Sdillon int isr; 696129397Sdannyboy 697130524Sru TUNDEBUG(ifp, "tunwrite\n"); 698130524Sru 69979727Sschweikh if ((ifp->if_flags & IFF_UP) != IFF_UP) 700130524Sru /* ignore silently */ 701130524Sru return (0); 70251372Sdillon 70351372Sdillon if (uio->uio_resid == 0) 70441967Sdillon return (0); 705130524Sru 706130524Sru if (uio->uio_resid < 0 || uio->uio_resid > TUNMRU) { 707129397Sdannyboy TUNDEBUG(ifp, "len=%d!\n", uio->uio_resid); 708129397Sdannyboy return (EIO); 709130524Sru } 710130524Sru tlen = uio->uio_resid; 711129397Sdannyboy 71251372Sdillon /* get a header mbuf */ 713129397Sdannyboy MGETHDR(m, M_DONTWAIT, MT_DATA); 714130524Sru if (m == NULL) 715130524Sru return (ENOBUFS); 716130524Sru mlen = MHLEN; 717130524Sru 71841967Sdillon top = 0; 71979727Sschweikh mp = ⊤ 72041967Sdillon while (error == 0 && uio->uio_resid > 0) { 72141967Sdillon m->m_len = min(mlen, uio->uio_resid); 72241967Sdillon error = uiomove(mtod(m, void *), m->m_len, uio); 72341967Sdillon *mp = m; 724130524Sru mp = &m->m_next; 72541967Sdillon if (uio->uio_resid > 0) { 72641967Sdillon MGET (m, M_DONTWAIT, MT_DATA); 72741967Sdillon if (m == 0) { 72841967Sdillon error = ENOBUFS; 729130524Sru break; 73042062Sobrien } 731130524Sru mlen = MLEN; 732130524Sru } 733130524Sru } 734130524Sru if (error) { 73544389Sghelmer if (top) 73641967Sdillon m_freem (top); 73779727Sschweikh ifp->if_ierrors++; 738130524Sru return (error); 739130524Sru } 740130524Sru 741130524Sru top->m_pkthdr.len = tlen; 74244389Sghelmer top->m_pkthdr.rcvif = ifp; 743130524Sru#ifdef MAC 74444389Sghelmer mac_create_mbuf_from_ifnet(ifp, top); 74544389Sghelmer#endif 746130524Sru 747130524Sru if (ifp->if_bpf) { 74844389Sghelmer if (tp->tun_flags & TUN_IFHEAD) { 74944389Sghelmer /* 750130524Sru * Conveniently, we already have a 4-byte address 751130524Sru * family prepended to our packet ! 752130524Sru * Inconveniently, it's in the wrong byte order ! 75379727Sschweikh */ 75441967Sdillon if ((top = m_pullup(top, sizeof(family))) == NULL) 755130524Sru return (ENOBUFS); 756130524Sru *mtod(top, u_int32_t *) = 757130524Sru ntohl(*mtod(top, u_int32_t *)); 75844389Sghelmer BPF_MTAP(ifp, top); 75944389Sghelmer *mtod(top, u_int32_t *) = 760130524Sru htonl(*mtod(top, u_int32_t *)); 761130524Sru } else { 762130524Sru /* 763130524Sru * We need to prepend the address family as 764130524Sru * a four byte field. Cons up a dummy header 765130524Sru * to pacify bpf. This is safe because bpf 76644389Sghelmer * will only read from the mbuf (i.e., it won't 767130524Sru * try to free it or keep a pointer to it). 768130524Sru */ 769130524Sru struct mbuf m; 770130524Sru uint32_t af = AF_INET; 771130524Sru 772130524Sru m.m_next = top; 773130524Sru m.m_len = 4; 774130524Sru m.m_data = (char *)⁡ 775130524Sru 776130524Sru BPF_MTAP(ifp, &m); 77744389Sghelmer } 77879727Sschweikh } 779130524Sru 78044389Sghelmer if (tp->tun_flags & TUN_IFHEAD) { 781130524Sru if (top->m_len < sizeof(family) && 782130524Sru (top = m_pullup(top, sizeof(family))) == NULL) 78344389Sghelmer return (ENOBUFS); 78444389Sghelmer family = ntohl(*mtod(top, u_int32_t *)); 78544389Sghelmer m_adj(top, sizeof(family)); 786130524Sru } else 787130524Sru family = AF_INET; 788130524Sru 789130524Sru switch (family) { 79041967Sdillon#ifdef INET 791130524Sru case AF_INET: 792130524Sru isr = NETISR_IP; 793130524Sru break; 79479727Sschweikh#endif 79544389Sghelmer#ifdef INET6 79644389Sghelmer case AF_INET6: 79744389Sghelmer isr = NETISR_IPV6; 79844389Sghelmer break; 79941967Sdillon#endif 80041967Sdillon#ifdef IPX 80179727Sschweikh case AF_IPX: 802130524Sru isr = NETISR_IPX; 803130524Sru break; 80441967Sdillon#endif 80541967Sdillon#ifdef NETATALK 80641967Sdillon case AF_APPLETALK: 807130524Sru isr = NETISR_ATALK2; 808130524Sru break; 80979727Sschweikh#endif 810130524Sru default: 811130524Sru m_freem(m); 812130524Sru return (EAFNOSUPPORT); 81344389Sghelmer } 814129397Sdannyboy /* First chunk of an mbuf contains good junk */ 815129397Sdannyboy if (harvest.point_to_point) 816129397Sdannyboy random_harvest(m, 16, 3, 0, RANDOM_NET); 81744389Sghelmer ifp->if_ibytes += top->m_pkthdr.len; 81844389Sghelmer ifp->if_ipackets++; 81941967Sdillon netisr_dispatch(isr, top); 820130524Sru return (0); 821130524Sru} 822130524Sru 82341967Sdillon/* 82441967Sdillon * tunpoll - the poll interface, this is only useful on reads 825129397Sdannyboy * really. The write detect always returns true, write never blocks 82679727Sschweikh * anyway, it either accepts the packet or drops it. 827130524Sru */ 82844389Sghelmerstatic int 829130524Srutunpoll(dev_t dev, int events, struct thread *td) 830130524Sru{ 83141967Sdillon int s; 832130524Sru struct tun_softc *tp = dev->si_drv1; 833130524Sru struct ifnet *ifp = &tp->tun_if; 83450911Sphantom int revents = 0; 83544389Sghelmer 83641967Sdillon s = splimp(); 837130524Sru TUNDEBUG(ifp, "tunpoll\n"); 838130524Sru 839130524Sru if (events & (POLLIN | POLLRDNORM)) { 84044389Sghelmer if (ifp->if_snd.ifq_len > 0) { 841130524Sru TUNDEBUG(ifp, "tunpoll q=%d\n", ifp->if_snd.ifq_len); 842130524Sru revents |= events & (POLLIN | POLLRDNORM); 84341967Sdillon } else { 84444389Sghelmer TUNDEBUG(ifp, "tunpoll waiting\n"); 84581251Sru selrecord(td, &tp->tun_rsel); 84681251Sru } 84741967Sdillon } 848130524Sru if (events & (POLLOUT | POLLWRNORM)) 84941967Sdillon revents |= events & (POLLOUT | POLLWRNORM); 850130524Sru 851130524Sru splx(s); 852130524Sru return (revents); 853130524Sru} 85441967Sdillon