if_tun.c revision 104393
1141240Snjl/* $NetBSD: if_tun.c,v 1.14 1994/06/29 06:36:25 cgd Exp $ */ 2141240Snjl 3141240Snjl/* 4141240Snjl * Copyright (c) 1988, Julian Onions <jpo@cs.nott.ac.uk> 5141240Snjl * Nottingham University 1987. 6141240Snjl * 7141240Snjl * This source may be freely distributed, however I would be interested 8141240Snjl * in any changes that are made. 9141240Snjl * 10141240Snjl * This driver takes packets off the IP i/f and hands them up to a 11141240Snjl * user process to have its wicked way with. This driver has it's 12141240Snjl * roots in a similar driver written by Phil Cockcroft (formerly) at 13141240Snjl * UCL. This driver is based much more on read/write/poll mode of 14141240Snjl * operation though. 15141240Snjl * 16141240Snjl * $FreeBSD: head/sys/net/if_tun.c 104393 2002-10-03 02:13:00Z truckman $ 17141240Snjl */ 18141240Snjl 19141240Snjl#include "opt_inet.h" 20141240Snjl#include "opt_mac.h" 21141240Snjl 22141240Snjl#include <sys/param.h> 23141240Snjl#include <sys/proc.h> 24141240Snjl#include <sys/systm.h> 25141240Snjl#include <sys/mac.h> 26141240Snjl#include <sys/mbuf.h> 27141240Snjl#include <sys/module.h> 28141240Snjl#include <sys/socket.h> 29141240Snjl#include <sys/filio.h> 30141240Snjl#include <sys/sockio.h> 31141240Snjl#include <sys/ttycom.h> 32141240Snjl#include <sys/poll.h> 33141240Snjl#include <sys/signalvar.h> 34141240Snjl#include <sys/filedesc.h> 35141240Snjl#include <sys/kernel.h> 36141240Snjl#include <sys/sysctl.h> 37141240Snjl#include <sys/conf.h> 38141240Snjl#include <sys/uio.h> 39141240Snjl#include <sys/vnode.h> 40141240Snjl#include <sys/malloc.h> 41141240Snjl#include <machine/bus.h> /* XXX Shouldn't really be required ! */ 42141240Snjl#include <sys/rman.h> 43141814Snjl 44141240Snjl#include <net/if.h> 45141240Snjl#include <net/if_types.h> 46141240Snjl#include <net/route.h> 47141240Snjl#include <net/intrq.h> 48141240Snjl#ifdef INET 49141240Snjl#include <netinet/in.h> 50141240Snjl#endif 51141240Snjl#include <net/bpf.h> 52141240Snjl#include <net/if_tunvar.h> 53141240Snjl#include <net/if_tun.h> 54141240Snjl 55141240Snjl#define TUNDEBUG if (tundebug) printf 56141240Snjl#define TUNNAME "tun" 57141240Snjl#define TUN_MAXUNIT 0x7fff /* ifp->if_unit is only 15 bits */ 58141240Snjl 59141240Snjlstatic MALLOC_DEFINE(M_TUN, TUNNAME, "Tunnel Interface"); 60141923Snjlstatic int tundebug = 0; 61141923Snjlstatic struct tun_softc *tunhead = NULL; 62141923Snjlstatic struct rman tununits[1]; 63141923Snjlstatic udev_t tunbasedev = NOUDEV; 64141413SnjlSYSCTL_INT(_debug, OID_AUTO, if_tun_debug, CTLFLAG_RW, &tundebug, 0, ""); 65141945Snjl 66141240Snjlstatic void tunclone(void *arg, char *name, int namelen, dev_t *dev); 67141240Snjlstatic void tuncreate(dev_t dev); 68141240Snjlstatic int tunifioctl(struct ifnet *, u_long, caddr_t); 69141240Snjlstatic int tuninit(struct ifnet *); 70141240Snjlstatic int tunmodevent(module_t, int, void *); 71141240Snjlstatic int tunoutput(struct ifnet *, struct mbuf *, struct sockaddr *, 72141240Snjl struct rtentry *rt); 73141240Snjlstatic void tunstart(struct ifnet *); 74141240Snjl 75141240Snjlstatic d_open_t tunopen; 76141240Snjlstatic d_close_t tunclose; 77141240Snjlstatic d_read_t tunread; 78141240Snjlstatic d_write_t tunwrite; 79141240Snjlstatic d_ioctl_t tunioctl; 80141240Snjlstatic d_poll_t tunpoll; 81141240Snjl 82141240Snjl#define CDEV_MAJOR 52 83141240Snjlstatic struct cdevsw tun_cdevsw = { 84141240Snjl /* open */ tunopen, 85141240Snjl /* close */ tunclose, 86141413Snjl /* read */ tunread, 87141240Snjl /* write */ tunwrite, 88141413Snjl /* ioctl */ tunioctl, 89141413Snjl /* poll */ tunpoll, 90141413Snjl /* mmap */ nommap, 91141413Snjl /* strategy */ nostrategy, 92141240Snjl /* name */ TUNNAME, 93141240Snjl /* maj */ CDEV_MAJOR, 94141240Snjl /* dump */ nodump, 95141240Snjl /* psize */ nopsize, 96141240Snjl /* flags */ 0, 97141240Snjl}; 98141240Snjl 99141240Snjlstatic void 100141240Snjltunclone(void *arg, char *name, int namelen, dev_t *dev) 101141240Snjl{ 102141240Snjl struct resource *r; 103141240Snjl int err; 104141240Snjl int u; 105141240Snjl 106141240Snjl if (*dev != NODEV) 107141240Snjl return; 108141240Snjl 109141240Snjl if (strcmp(name, TUNNAME) == 0) { 110141240Snjl r = rman_reserve_resource(tununits, 0, TUN_MAXUNIT, 1, 111141240Snjl RF_ALLOCATED | RF_ACTIVE, NULL); 112141240Snjl u = rman_get_start(r); 113141240Snjl err = rman_release_resource(r); 114141240Snjl KASSERT(err == 0, ("Unexpected failure releasing resource")); 115141240Snjl *dev = makedev(CDEV_MAJOR, unit2minor(u)); 116141240Snjl if ((*dev)->si_flags & SI_NAMED) 117141240Snjl return; /* Already make_dev()d */ 118141240Snjl } else if (dev_stdclone(name, NULL, TUNNAME, &u) != 1) 119141240Snjl return; /* Don't recognise the name */ 120141240Snjl 121141240Snjl *dev = make_dev(&tun_cdevsw, unit2minor(u), 122141240Snjl UID_ROOT, GID_WHEEL, 0600, "tun%d", u); 123141240Snjl 124141240Snjl /* 125141240Snjl * All devices depend on tunbasedev so that we can simply 126141923Snjl * destroy_dev() this device at module unload time to get 127141945Snjl * rid of all our make_dev()d resources. 128141240Snjl */ 129141240Snjl if (tunbasedev == NOUDEV) 130141240Snjl tunbasedev = (*dev)->si_udev; 131141240Snjl else { 132141240Snjl (*dev)->si_flags |= SI_CHEAPCLONE; 133141240Snjl dev_depends(udev2dev(tunbasedev, 0), *dev); 134141240Snjl } 135141240Snjl} 136141240Snjl 137141240Snjlstatic int 138141240Snjltunmodevent(module_t mod, int type, void *data) 139141240Snjl{ 140141240Snjl static eventhandler_tag tag; 141141240Snjl struct tun_softc *tp; 142141240Snjl dev_t dev; 143141240Snjl int err; 144141240Snjl 145141240Snjl switch (type) { 146141240Snjl case MOD_LOAD: 147141240Snjl tag = EVENTHANDLER_REGISTER(dev_clone, tunclone, 0, 1000); 148141240Snjl if (tag == NULL) 149141240Snjl return (ENOMEM); 150141240Snjl if (!devfs_present) { 151141240Snjl err = cdevsw_add(&tun_cdevsw); 152141240Snjl if (err != 0) { 153141240Snjl EVENTHANDLER_DEREGISTER(dev_clone, tag); 154141240Snjl return (err); 155141240Snjl } 156141240Snjl } 157141240Snjl tununits->rm_type = RMAN_ARRAY; 158141240Snjl tununits->rm_descr = "open if_tun units"; 159141240Snjl err = rman_init(tununits); 160141240Snjl if (err != 0) { 161141240Snjl cdevsw_remove(&tun_cdevsw); 162141240Snjl EVENTHANDLER_DEREGISTER(dev_clone, tag); 163141240Snjl return (err); 164141240Snjl } 165141240Snjl err = rman_manage_region(tununits, 0, TUN_MAXUNIT); 166141240Snjl if (err != 0) { 167141240Snjl printf("%s: tununits: rman_manage_region: Failed %d\n", 168141240Snjl TUNNAME, err); 169141240Snjl rman_fini(tununits); 170141240Snjl cdevsw_remove(&tun_cdevsw); 171141240Snjl EVENTHANDLER_DEREGISTER(dev_clone, tag); 172141240Snjl return (err); 173141240Snjl } 174141240Snjl break; 175141240Snjl case MOD_UNLOAD: 176141240Snjl err = rman_fini(tununits); 177141240Snjl if (err != 0) 178141240Snjl return (err); 179141240Snjl EVENTHANDLER_DEREGISTER(dev_clone, tag); 180141814Snjl 181141814Snjl while (tunhead != NULL) { 182141240Snjl KASSERT((tunhead->tun_flags & TUN_OPEN) == 0, 183141240Snjl ("tununits is out of sync - unit %d", 184141240Snjl tunhead->tun_if.if_unit)); 185141814Snjl tp = tunhead; 186141814Snjl dev = makedev(tun_cdevsw.d_maj, 187141814Snjl unit2minor(tp->tun_if.if_unit)); 188141814Snjl KASSERT(dev->si_drv1 == tp, ("Bad makedev result")); 189141814Snjl tunhead = tp->next; 190141814Snjl bpfdetach(&tp->tun_if); 191141814Snjl if_detach(&tp->tun_if); 192141814Snjl KASSERT(dev->si_flags & SI_NAMED, ("Missing make_dev")); 193141923Snjl free(tp, M_TUN); 194141923Snjl } 195141923Snjl 196141923Snjl /* 197141923Snjl * Destroying tunbasedev results in all of our make_dev()s 198141923Snjl * conveniently going away. 199141923Snjl */ 200141923Snjl if (tunbasedev != NOUDEV) 201141923Snjl destroy_dev(udev2dev(tunbasedev, 0)); 202141923Snjl 203141923Snjl if (!devfs_present) 204141923Snjl cdevsw_remove(&tun_cdevsw); 205141923Snjl break; 206141923Snjl } 207141923Snjl return 0; 208141240Snjl} 209141240Snjl 210141240Snjlstatic moduledata_t tun_mod = { 211141240Snjl "if_tun", 212141240Snjl tunmodevent, 213141240Snjl 0 214141240Snjl}; 215141240Snjl 216141240SnjlDECLARE_MODULE(if_tun, tun_mod, SI_SUB_PSEUDO, SI_ORDER_ANY); 217141240Snjl 218141240Snjlstatic void 219141943Snjltunstart(struct ifnet *ifp) 220141943Snjl{ 221141943Snjl struct tun_softc *tp = ifp->if_softc; 222141943Snjl 223141943Snjl if (tp->tun_flags & TUN_RWAIT) { 224141943Snjl tp->tun_flags &= ~TUN_RWAIT; 225141943Snjl wakeup((caddr_t)tp); 226141943Snjl } 227141943Snjl if (tp->tun_flags & TUN_ASYNC && tp->tun_sigio) 228141240Snjl pgsigio(&tp->tun_sigio, SIGIO, 0); 229141943Snjl selwakeup(&tp->tun_rsel); 230141943Snjl} 231141943Snjl 232141943Snjlstatic void 233141943Snjltuncreate(dev_t dev) 234141240Snjl{ 235141240Snjl struct tun_softc *sc; 236141240Snjl struct ifnet *ifp; 237141240Snjl 238141240Snjl if (!(dev->si_flags & SI_NAMED)) 239141413Snjl dev = make_dev(&tun_cdevsw, minor(dev), 240141413Snjl UID_UUCP, GID_DIALER, 0600, "tun%d", dev2unit(dev)); 241141413Snjl 242141413Snjl MALLOC(sc, struct tun_softc *, sizeof(*sc), M_TUN, M_WAITOK | M_ZERO); 243141413Snjl sc->tun_flags = TUN_INITED; 244141413Snjl sc->next = tunhead; 245141413Snjl tunhead = sc; 246141943Snjl 247141943Snjl ifp = &sc->tun_if; 248141943Snjl ifp->if_unit = dev2unit(dev); 249141943Snjl ifp->if_name = TUNNAME; 250141943Snjl ifp->if_mtu = TUNMTU; 251141943Snjl ifp->if_ioctl = tunifioctl; 252141943Snjl ifp->if_output = tunoutput; 253141943Snjl ifp->if_start = tunstart; 254141943Snjl ifp->if_flags = IFF_POINTOPOINT | IFF_MULTICAST; 255141413Snjl ifp->if_type = IFT_PPP; 256141943Snjl ifp->if_snd.ifq_maxlen = ifqmaxlen; 257141943Snjl ifp->if_softc = sc; 258141943Snjl if_attach(ifp); 259141943Snjl bpfattach(ifp, DLT_NULL, sizeof(u_int)); 260141943Snjl dev->si_drv1 = sc; 261141413Snjl} 262141413Snjl 263141413Snjlstatic int 264141413Snjltunopen(dev_t dev, int flag, int mode, struct thread *td) 265141413Snjl{ 266141240Snjl struct resource *r; 267141923Snjl struct ifnet *ifp; 268141923Snjl struct tun_softc *tp; 269141923Snjl int unit; 270141923Snjl 271141923Snjl unit = dev2unit(dev); 272141923Snjl if (unit > TUN_MAXUNIT) 273141923Snjl return (ENXIO); 274141923Snjl 275141923Snjl r = rman_reserve_resource(tununits, unit, unit, 1, 276141923Snjl RF_ALLOCATED | RF_ACTIVE, NULL); 277141923Snjl if (r == NULL) 278141923Snjl return (EBUSY); 279141923Snjl 280141923Snjl dev->si_flags &= ~SI_CHEAPCLONE; 281141923Snjl 282141923Snjl tp = dev->si_drv1; 283141923Snjl if (!tp) { 284141240Snjl tuncreate(dev); 285141923Snjl tp = dev->si_drv1; 286141240Snjl } 287141240Snjl KASSERT(!(tp->tun_flags & TUN_OPEN), ("Resource & flags out-of-sync")); 288141240Snjl tp->r_unit = r; 289141240Snjl tp->tun_pid = td->td_proc->p_pid; 290141240Snjl ifp = &tp->tun_if; 291141240Snjl tp->tun_flags |= TUN_OPEN; 292141240Snjl TUNDEBUG("%s%d: open\n", ifp->if_name, ifp->if_unit); 293141240Snjl 294141240Snjl return (0); 295141240Snjl} 296141240Snjl 297141240Snjl/* 298141240Snjl * tunclose - close the device - mark i/f down & delete 299141240Snjl * routing info 300141240Snjl */ 301141240Snjlstatic int 302141240Snjltunclose(dev_t dev, int foo, int bar, struct thread *td) 303141240Snjl{ 304141240Snjl struct tun_softc *tp; 305141240Snjl struct ifnet *ifp; 306141240Snjl int s; 307141240Snjl int err; 308141240Snjl 309141240Snjl tp = dev->si_drv1; 310141240Snjl ifp = &tp->tun_if; 311141240Snjl 312141240Snjl KASSERT(tp->r_unit, ("Unit %d not marked open", ifp->if_unit)); 313141240Snjl tp->tun_flags &= ~TUN_OPEN; 314141240Snjl tp->tun_pid = 0; 315141240Snjl 316141240Snjl /* 317141240Snjl * junk all pending output 318141240Snjl */ 319141240Snjl IF_DRAIN(&ifp->if_snd); 320141240Snjl 321141240Snjl if (ifp->if_flags & IFF_UP) { 322141240Snjl s = splimp(); 323141240Snjl if_down(ifp); 324141240Snjl splx(s); 325141240Snjl } 326141240Snjl 327141240Snjl if (ifp->if_flags & IFF_RUNNING) { 328141240Snjl register struct ifaddr *ifa; 329141240Snjl 330141240Snjl s = splimp(); 331141240Snjl /* find internet addresses and delete routes */ 332141240Snjl TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) 333141240Snjl if (ifa->ifa_addr->sa_family == AF_INET) 334141240Snjl rtinit(ifa, (int)RTM_DELETE, 335141413Snjl tp->tun_flags & TUN_DSTADDR ? RTF_HOST : 0); 336141240Snjl ifp->if_flags &= ~IFF_RUNNING; 337141240Snjl splx(s); 338141240Snjl } 339141240Snjl 340141240Snjl funsetown(&tp->tun_sigio); 341141240Snjl selwakeup(&tp->tun_rsel); 342141240Snjl 343141240Snjl TUNDEBUG ("%s%d: closed\n", ifp->if_name, ifp->if_unit); 344141240Snjl err = rman_release_resource(tp->r_unit); 345141240Snjl KASSERT(err == 0, ("Unit %d failed to release", ifp->if_unit)); 346141240Snjl 347141240Snjl return (0); 348141240Snjl} 349141240Snjl 350141240Snjlstatic int 351141240Snjltuninit(struct ifnet *ifp) 352141240Snjl{ 353141240Snjl struct tun_softc *tp = ifp->if_softc; 354141240Snjl register struct ifaddr *ifa; 355141240Snjl int error = 0; 356141240Snjl 357141240Snjl TUNDEBUG("%s%d: tuninit\n", ifp->if_name, ifp->if_unit); 358141240Snjl 359141240Snjl ifp->if_flags |= IFF_UP | IFF_RUNNING; 360141240Snjl getmicrotime(&ifp->if_lastchange); 361141240Snjl 362141240Snjl for (ifa = TAILQ_FIRST(&ifp->if_addrhead); ifa; 363141240Snjl ifa = TAILQ_NEXT(ifa, ifa_link)) { 364141240Snjl if (ifa->ifa_addr == NULL) 365141240Snjl error = EFAULT; 366141240Snjl /* XXX: Should maybe return straight off? */ 367141240Snjl else { 368141240Snjl#ifdef INET 369141240Snjl if (ifa->ifa_addr->sa_family == AF_INET) { 370141240Snjl struct sockaddr_in *si; 371141240Snjl 372141240Snjl si = (struct sockaddr_in *)ifa->ifa_addr; 373141413Snjl if (si->sin_addr.s_addr) 374141240Snjl tp->tun_flags |= TUN_IASET; 375141240Snjl 376141240Snjl si = (struct sockaddr_in *)ifa->ifa_dstaddr; 377141240Snjl if (si && si->sin_addr.s_addr) 378141240Snjl tp->tun_flags |= TUN_DSTADDR; 379141240Snjl } 380141413Snjl#endif 381141240Snjl } 382141240Snjl } 383141240Snjl return (error); 384141240Snjl} 385141240Snjl 386141240Snjl/* 387141240Snjl * Process an ioctl request. 388141240Snjl */ 389141240Snjlint 390141240Snjltunifioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 391141240Snjl{ 392141240Snjl struct ifreq *ifr = (struct ifreq *)data; 393141240Snjl struct tun_softc *tp = ifp->if_softc; 394141240Snjl struct ifstat *ifs; 395141240Snjl int error = 0, s; 396141240Snjl 397141240Snjl s = splimp(); 398141240Snjl switch(cmd) { 399141824Snjl case SIOCGIFSTATUS: 400141240Snjl ifs = (struct ifstat *)data; 401141240Snjl if (tp->tun_pid) 402141824Snjl sprintf(ifs->ascii + strlen(ifs->ascii), 403141824Snjl "\tOpened by PID %d\n", tp->tun_pid); 404141824Snjl break; 405141824Snjl case SIOCSIFADDR: 406141824Snjl error = tuninit(ifp); 407142032Snjl TUNDEBUG("%s%d: address set, error=%d\n", 408142032Snjl ifp->if_name, ifp->if_unit, error); 409142032Snjl break; 410141240Snjl case SIOCSIFDSTADDR: 411142032Snjl error = tuninit(ifp); 412142032Snjl TUNDEBUG("%s%d: destination address set, error=%d\n", 413141240Snjl ifp->if_name, ifp->if_unit, error); 414141413Snjl break; 415141824Snjl case SIOCSIFMTU: 416141814Snjl ifp->if_mtu = ifr->ifr_mtu; 417141413Snjl TUNDEBUG("%s%d: mtu set\n", ifp->if_name, ifp->if_unit); 418141413Snjl break; 419141413Snjl case SIOCSIFFLAGS: 420141413Snjl case SIOCADDMULTI: 421141413Snjl case SIOCDELMULTI: 422141413Snjl break; 423141413Snjl default: 424141413Snjl error = EINVAL; 425141413Snjl } 426141413Snjl splx(s); 427141413Snjl return (error); 428141413Snjl} 429141413Snjl 430141413Snjl/* 431141413Snjl * tunoutput - queue packets from higher level ready to put out. 432141413Snjl */ 433141413Snjlint 434141240Snjltunoutput( 435141240Snjl struct ifnet *ifp, 436141240Snjl struct mbuf *m0, 437141240Snjl struct sockaddr *dst, 438141945Snjl struct rtentry *rt) 439141945Snjl{ 440141945Snjl struct tun_softc *tp = ifp->if_softc; 441141945Snjl#ifdef MAC 442141945Snjl int error; 443141945Snjl#endif 444141945Snjl 445141240Snjl TUNDEBUG ("%s%d: tunoutput\n", ifp->if_name, ifp->if_unit); 446141945Snjl 447141945Snjl#ifdef MAC 448141945Snjl error = mac_check_ifnet_transmit(ifp, m0); 449141945Snjl if (error) { 450141240Snjl m_freem(m0); 451141945Snjl return (error); 452141945Snjl } 453141945Snjl#endif 454141413Snjl 455141240Snjl if ((tp->tun_flags & TUN_READY) != TUN_READY) { 456141240Snjl TUNDEBUG ("%s%d: not ready 0%o\n", ifp->if_name, 457141240Snjl ifp->if_unit, tp->tun_flags); 458141240Snjl m_freem (m0); 459141413Snjl return (EHOSTDOWN); 460141413Snjl } 461141413Snjl 462141413Snjl /* BPF write needs to be handled specially */ 463141413Snjl if (dst->sa_family == AF_UNSPEC) { 464141413Snjl dst->sa_family = *(mtod(m0, int *)); 465141413Snjl m0->m_len -= sizeof(int); 466141413Snjl m0->m_pkthdr.len -= sizeof(int); 467141413Snjl m0->m_data += sizeof(int); 468141413Snjl } 469141413Snjl 470141413Snjl if (ifp->if_bpf) { 471141240Snjl /* 472141240Snjl * We need to prepend the address family as 473141240Snjl * a four byte field. Cons up a dummy header 474141240Snjl * to pacify bpf. This is safe because bpf 475141240Snjl * will only read from the mbuf (i.e., it won't 476141413Snjl * try to free it or keep a pointer to it). 477141240Snjl */ 478141240Snjl struct mbuf m; 479141240Snjl uint32_t af = dst->sa_family; 480141240Snjl 481141240Snjl m.m_next = m0; 482141240Snjl m.m_len = 4; 483141240Snjl m.m_data = (char *)⁡ 484141240Snjl 485141413Snjl bpf_mtap(ifp, &m); 486141413Snjl } 487141413Snjl 488141413Snjl /* prepend sockaddr? this may abort if the mbuf allocation fails */ 489141413Snjl if (tp->tun_flags & TUN_LMODE) { 490141240Snjl /* allocate space for sockaddr */ 491141240Snjl M_PREPEND(m0, dst->sa_len, M_DONTWAIT); 492141240Snjl 493141240Snjl /* if allocation failed drop packet */ 494141240Snjl if (m0 == NULL) { 495141240Snjl ifp->if_iqdrops++; 496141240Snjl ifp->if_oerrors++; 497141240Snjl return (ENOBUFS); 498141240Snjl } else { 499141240Snjl bcopy(dst, m0->m_data, dst->sa_len); 500141413Snjl } 501141240Snjl } 502141240Snjl 503141413Snjl if (tp->tun_flags & TUN_IFHEAD) { 504141240Snjl /* Prepend the address family */ 505141240Snjl M_PREPEND(m0, 4, M_DONTWAIT); 506141240Snjl 507141413Snjl /* if allocation failed drop packet */ 508141240Snjl if (m0 == NULL) { 509141240Snjl ifp->if_iqdrops++; 510141240Snjl ifp->if_oerrors++; 511141240Snjl return (ENOBUFS); 512141240Snjl } else 513141413Snjl *(u_int32_t *)m0->m_data = htonl(dst->sa_family); 514141413Snjl } else { 515141413Snjl#ifdef INET 516141240Snjl if (dst->sa_family != AF_INET) 517141240Snjl#endif 518141240Snjl { 519141240Snjl m_freem(m0); 520141240Snjl return (EAFNOSUPPORT); 521141240Snjl } 522141240Snjl } 523141413Snjl 524141240Snjl if (! IF_HANDOFF(&ifp->if_snd, m0, ifp)) { 525141240Snjl ifp->if_collisions++; 526141240Snjl return (ENOBUFS); 527141240Snjl } 528141240Snjl ifp->if_opackets++; 529141240Snjl return (0); 530141240Snjl} 531141240Snjl 532141413Snjl/* 533141413Snjl * the cdevsw interface is now pretty minimal. 534141413Snjl */ 535141240Snjlstatic int 536141413Snjltunioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct thread *td) 537141413Snjl{ 538141413Snjl int s; 539141413Snjl int error; 540141413Snjl struct tun_softc *tp = dev->si_drv1; 541141413Snjl struct tuninfo *tunp; 542141413Snjl 543141413Snjl switch (cmd) { 544141413Snjl case TUNSIFINFO: 545141413Snjl tunp = (struct tuninfo *)data; 546141413Snjl if (tunp->mtu < IF_MINMTU) 547141413Snjl return (EINVAL); 548141413Snjl if (tp->tun_if.if_mtu != tunp->mtu 549141413Snjl && (error = suser(td)) != 0) 550141413Snjl return (error); 551141413Snjl tp->tun_if.if_mtu = tunp->mtu; 552141413Snjl tp->tun_if.if_type = tunp->type; 553141413Snjl tp->tun_if.if_baudrate = tunp->baudrate; 554141413Snjl break; 555141413Snjl case TUNGIFINFO: 556141413Snjl tunp = (struct tuninfo *)data; 557141413Snjl tunp->mtu = tp->tun_if.if_mtu; 558141413Snjl tunp->type = tp->tun_if.if_type; 559141413Snjl tunp->baudrate = tp->tun_if.if_baudrate; 560141413Snjl break; 561141413Snjl case TUNSDEBUG: 562141413Snjl tundebug = *(int *)data; 563141413Snjl break; 564141413Snjl case TUNGDEBUG: 565141413Snjl *(int *)data = tundebug; 566141413Snjl break; 567141413Snjl case TUNSLMODE: 568141413Snjl if (*(int *)data) { 569141413Snjl tp->tun_flags |= TUN_LMODE; 570141413Snjl tp->tun_flags &= ~TUN_IFHEAD; 571141413Snjl } else 572141413Snjl tp->tun_flags &= ~TUN_LMODE; 573141413Snjl break; 574141413Snjl case TUNSIFHEAD: 575141413Snjl if (*(int *)data) { 576141413Snjl tp->tun_flags |= TUN_IFHEAD; 577141413Snjl tp->tun_flags &= ~TUN_LMODE; 578141413Snjl } else 579141413Snjl tp->tun_flags &= ~TUN_IFHEAD; 580141413Snjl break; 581141413Snjl case TUNGIFHEAD: 582141413Snjl *(int *)data = (tp->tun_flags & TUN_IFHEAD) ? 1 : 0; 583141413Snjl break; 584141413Snjl case TUNSIFMODE: 585141413Snjl /* deny this if UP */ 586141413Snjl if (tp->tun_if.if_flags & IFF_UP) 587141413Snjl return(EBUSY); 588141413Snjl 589141413Snjl switch (*(int *)data & ~IFF_MULTICAST) { 590141413Snjl case IFF_POINTOPOINT: 591141413Snjl case IFF_BROADCAST: 592141413Snjl tp->tun_if.if_flags &= 593141413Snjl ~(IFF_BROADCAST|IFF_POINTOPOINT|IFF_MULTICAST); 594141413Snjl tp->tun_if.if_flags |= *(int *)data; 595141413Snjl break; 596141413Snjl default: 597141413Snjl return(EINVAL); 598141413Snjl } 599141413Snjl break; 600141413Snjl case TUNSIFPID: 601141413Snjl tp->tun_pid = curthread->td_proc->p_pid; 602141413Snjl break; 603141413Snjl case FIONBIO: 604141413Snjl break; 605141413Snjl case FIOASYNC: 606141413Snjl if (*(int *)data) 607141413Snjl tp->tun_flags |= TUN_ASYNC; 608141413Snjl else 609141413Snjl tp->tun_flags &= ~TUN_ASYNC; 610141413Snjl break; 611141413Snjl case FIONREAD: 612141413Snjl s = splimp(); 613141413Snjl if (tp->tun_if.if_snd.ifq_head) { 614141413Snjl struct mbuf *mb = tp->tun_if.if_snd.ifq_head; 615141413Snjl for( *(int *)data = 0; mb != 0; mb = mb->m_next) 616141413Snjl *(int *)data += mb->m_len; 617141413Snjl } else 618141413Snjl *(int *)data = 0; 619141413Snjl splx(s); 620141413Snjl break; 621141413Snjl case FIOSETOWN: 622141413Snjl return (fsetown(*(int *)data, &tp->tun_sigio)); 623141413Snjl 624141413Snjl case FIOGETOWN: 625141413Snjl *(int *)data = fgetown(&tp->tun_sigio); 626141413Snjl return (0); 627141413Snjl 628141413Snjl /* This is deprecated, FIOSETOWN should be used instead. */ 629141413Snjl case TIOCSPGRP: 630141413Snjl return (fsetown(-(*(int *)data), &tp->tun_sigio)); 631141413Snjl 632141413Snjl /* This is deprecated, FIOGETOWN should be used instead. */ 633141413Snjl case TIOCGPGRP: 634141413Snjl *(int *)data = -fgetown(&tp->tun_sigio); 635141413Snjl return (0); 636141413Snjl 637141413Snjl default: 638141413Snjl return (ENOTTY); 639141413Snjl } 640141413Snjl return (0); 641141413Snjl} 642141413Snjl 643141413Snjl/* 644141413Snjl * The cdevsw read interface - reads a packet at a time, or at 645141413Snjl * least as much of a packet as can be read. 646141413Snjl */ 647141413Snjlstatic int 648141413Snjltunread(dev_t dev, struct uio *uio, int flag) 649141413Snjl{ 650141413Snjl struct tun_softc *tp = dev->si_drv1; 651141413Snjl struct ifnet *ifp = &tp->tun_if; 652141413Snjl struct mbuf *m; 653141413Snjl int error=0, len, s; 654141413Snjl 655141413Snjl TUNDEBUG ("%s%d: read\n", ifp->if_name, ifp->if_unit); 656141240Snjl if ((tp->tun_flags & TUN_READY) != TUN_READY) { 657141240Snjl TUNDEBUG ("%s%d: not ready 0%o\n", ifp->if_name, 658141240Snjl ifp->if_unit, tp->tun_flags); 659141240Snjl return (EHOSTDOWN); 660141814Snjl } 661141814Snjl 662141240Snjl tp->tun_flags &= ~TUN_RWAIT; 663141814Snjl 664141240Snjl s = splimp(); 665141814Snjl do { 666141240Snjl IF_DEQUEUE(&ifp->if_snd, m); 667141240Snjl if (m == NULL) { 668141240Snjl if (flag & IO_NDELAY) { 669141240Snjl splx(s); 670141240Snjl return (EWOULDBLOCK); 671141240Snjl } 672141240Snjl tp->tun_flags |= TUN_RWAIT; 673141240Snjl if((error = tsleep((caddr_t)tp, PCATCH | (PZERO + 1), 674141240Snjl "tunread", 0)) != 0) { 675141240Snjl splx(s); 676141240Snjl return (error); 677141814Snjl } 678141814Snjl } 679141814Snjl } while (m == NULL); 680141814Snjl splx(s); 681141814Snjl 682141814Snjl while (m && uio->uio_resid > 0 && error == 0) { 683141240Snjl len = min(uio->uio_resid, m->m_len); 684141240Snjl if (len != 0) 685141814Snjl error = uiomove(mtod(m, caddr_t), len, uio); 686141814Snjl m = m_free(m); 687141814Snjl } 688141814Snjl 689141240Snjl if (m) { 690141814Snjl TUNDEBUG("%s%d: Dropping mbuf\n", ifp->if_name, ifp->if_unit); 691141814Snjl m_freem(m); 692141814Snjl } 693141814Snjl return (error); 694141814Snjl} 695141814Snjl 696141240Snjl/* 697141814Snjl * the cdevsw write interface - an atomic write is a packet - or else! 698141814Snjl */ 699141814Snjlstatic int 700141814Snjltunwrite(dev_t dev, struct uio *uio, int flag) 701141240Snjl{ 702141240Snjl struct tun_softc *tp = dev->si_drv1; 703141240Snjl struct ifnet *ifp = &tp->tun_if; 704141814Snjl struct mbuf *top, **mp, *m; 705141814Snjl int error=0, tlen, mlen; 706141240Snjl uint32_t family; 707141240Snjl 708141240Snjl TUNDEBUG("%s%d: tunwrite\n", ifp->if_name, ifp->if_unit); 709141240Snjl 710141240Snjl if (uio->uio_resid == 0) 711141240Snjl return (0); 712141240Snjl 713141240Snjl if (uio->uio_resid < 0 || uio->uio_resid > TUNMRU) { 714141240Snjl TUNDEBUG("%s%d: len=%d!\n", ifp->if_name, ifp->if_unit, 715141240Snjl uio->uio_resid); 716141240Snjl return (EIO); 717141240Snjl } 718141240Snjl tlen = uio->uio_resid; 719141240Snjl 720141240Snjl /* get a header mbuf */ 721141240Snjl MGETHDR(m, M_DONTWAIT, MT_DATA); 722141240Snjl if (m == NULL) 723141240Snjl return (ENOBUFS); 724141240Snjl mlen = MHLEN; 725141240Snjl 726141240Snjl top = 0; 727141240Snjl mp = ⊤ 728141240Snjl while (error == 0 && uio->uio_resid > 0) { 729141240Snjl m->m_len = min(mlen, uio->uio_resid); 730141240Snjl error = uiomove(mtod (m, caddr_t), m->m_len, uio); 731141240Snjl *mp = m; 732141240Snjl mp = &m->m_next; 733141240Snjl if (uio->uio_resid > 0) { 734141240Snjl MGET (m, M_DONTWAIT, MT_DATA); 735141240Snjl if (m == 0) { 736141240Snjl error = ENOBUFS; 737141240Snjl break; 738141240Snjl } 739141240Snjl mlen = MLEN; 740141240Snjl } 741141240Snjl } 742141240Snjl if (error) { 743141240Snjl if (top) 744141240Snjl m_freem (top); 745141240Snjl ifp->if_ierrors++; 746141240Snjl return (error); 747141240Snjl } 748141240Snjl 749141240Snjl top->m_pkthdr.len = tlen; 750141240Snjl top->m_pkthdr.rcvif = ifp; 751141945Snjl#ifdef MAC 752141240Snjl mac_create_mbuf_from_ifnet(ifp, top); 753141240Snjl#endif 754141240Snjl 755141814Snjl if (ifp->if_bpf) { 756141814Snjl if (tp->tun_flags & TUN_IFHEAD) { 757141240Snjl /* 758141814Snjl * Conveniently, we already have a 4-byte address 759141945Snjl * family prepended to our packet ! 760141945Snjl * Inconveniently, it's in the wrong byte order ! 761141945Snjl */ 762141240Snjl if ((top = m_pullup(top, sizeof(family))) == NULL) 763141945Snjl return (ENOBUFS); 764141240Snjl *mtod(top, u_int32_t *) = 765141814Snjl ntohl(*mtod(top, u_int32_t *)); 766141814Snjl bpf_mtap(ifp, top); 767141240Snjl *mtod(top, u_int32_t *) = 768141240Snjl htonl(*mtod(top, u_int32_t *)); 769141240Snjl } else { 770141240Snjl /* 771141240Snjl * We need to prepend the address family as 772141240Snjl * a four byte field. Cons up a dummy header 773141240Snjl * to pacify bpf. This is safe because bpf 774141240Snjl * will only read from the mbuf (i.e., it won't 775141240Snjl * try to free it or keep a pointer to it). 776141240Snjl */ 777141240Snjl struct mbuf m; 778142032Snjl uint32_t af = AF_INET; 779141240Snjl 780141240Snjl m.m_next = top; 781141240Snjl m.m_len = 4; 782141240Snjl m.m_data = (char *)⁡ 783141240Snjl 784141240Snjl bpf_mtap(ifp, &m); 785141240Snjl } 786141240Snjl } 787141240Snjl 788141945Snjl if (tp->tun_flags & TUN_IFHEAD) { 789141240Snjl if (top->m_len < sizeof(family) && 790141240Snjl (top = m_pullup(top, sizeof(family))) == NULL) 791141240Snjl return (ENOBUFS); 792141240Snjl family = ntohl(*mtod(top, u_int32_t *)); 793142032Snjl m_adj(top, sizeof(family)); 794141240Snjl } else 795141240Snjl family = AF_INET; 796141814Snjl 797141240Snjl ifp->if_ibytes += top->m_pkthdr.len; 798141240Snjl ifp->if_ipackets++; 799141240Snjl 800141240Snjl return (family_enqueue(family, top)); 801141240Snjl} 802 803/* 804 * tunpoll - the poll interface, this is only useful on reads 805 * really. The write detect always returns true, write never blocks 806 * anyway, it either accepts the packet or drops it. 807 */ 808static int 809tunpoll(dev_t dev, int events, struct thread *td) 810{ 811 int s; 812 struct tun_softc *tp = dev->si_drv1; 813 struct ifnet *ifp = &tp->tun_if; 814 int revents = 0; 815 816 s = splimp(); 817 TUNDEBUG("%s%d: tunpoll\n", ifp->if_name, ifp->if_unit); 818 819 if (events & (POLLIN | POLLRDNORM)) { 820 if (ifp->if_snd.ifq_len > 0) { 821 TUNDEBUG("%s%d: tunpoll q=%d\n", ifp->if_name, 822 ifp->if_unit, ifp->if_snd.ifq_len); 823 revents |= events & (POLLIN | POLLRDNORM); 824 } else { 825 TUNDEBUG("%s%d: tunpoll waiting\n", ifp->if_name, 826 ifp->if_unit); 827 selrecord(td, &tp->tun_rsel); 828 } 829 } 830 if (events & (POLLOUT | POLLWRNORM)) 831 revents |= events & (POLLOUT | POLLWRNORM); 832 833 splx(s); 834 return (revents); 835} 836