if_tun.c revision 105804
1190688Sweongyo/* $NetBSD: if_tun.c,v 1.14 1994/06/29 06:36:25 cgd Exp $ */ 2190688Sweongyo 3190688Sweongyo/* 4190688Sweongyo * Copyright (c) 1988, Julian Onions <jpo@cs.nott.ac.uk> 5190688Sweongyo * Nottingham University 1987. 6190688Sweongyo * 7190688Sweongyo * This source may be freely distributed, however I would be interested 8190688Sweongyo * in any changes that are made. 9190688Sweongyo * 10190688Sweongyo * This driver takes packets off the IP i/f and hands them up to a 11190688Sweongyo * user process to have its wicked way with. This driver has it's 12190688Sweongyo * roots in a similar driver written by Phil Cockcroft (formerly) at 13190688Sweongyo * UCL. This driver is based much more on read/write/poll mode of 14190688Sweongyo * operation though. 15190688Sweongyo * 16190688Sweongyo * $FreeBSD: head/sys/net/if_tun.c 105804 2002-10-23 15:16:37Z simokawa $ 17190688Sweongyo */ 18190688Sweongyo 19190688Sweongyo#include "opt_inet.h" 20190688Sweongyo#include "opt_mac.h" 21190688Sweongyo 22190688Sweongyo#include <sys/param.h> 23190688Sweongyo#include <sys/proc.h> 24190688Sweongyo#include <sys/systm.h> 25190688Sweongyo#include <sys/mac.h> 26190688Sweongyo#include <sys/mbuf.h> 27190688Sweongyo#include <sys/module.h> 28190688Sweongyo#include <sys/socket.h> 29190688Sweongyo#include <sys/filio.h> 30190688Sweongyo#include <sys/sockio.h> 31190688Sweongyo#include <sys/ttycom.h> 32190688Sweongyo#include <sys/poll.h> 33190688Sweongyo#include <sys/signalvar.h> 34190688Sweongyo#include <sys/filedesc.h> 35190688Sweongyo#include <sys/kernel.h> 36190688Sweongyo#include <sys/sysctl.h> 37190688Sweongyo#include <sys/conf.h> 38190688Sweongyo#include <sys/uio.h> 39190688Sweongyo#include <sys/vnode.h> 40190688Sweongyo#include <sys/malloc.h> 41190688Sweongyo#include <machine/bus.h> /* XXX Shouldn't really be required ! */ 42190688Sweongyo#include <sys/rman.h> 43190688Sweongyo 44190688Sweongyo#include <net/if.h> 45190688Sweongyo#include <net/if_types.h> 46190688Sweongyo#include <net/route.h> 47190688Sweongyo#include <net/intrq.h> 48190688Sweongyo#ifdef INET 49190688Sweongyo#include <netinet/in.h> 50190688Sweongyo#endif 51190688Sweongyo#include <net/bpf.h> 52190688Sweongyo#include <net/if_tunvar.h> 53190688Sweongyo#include <net/if_tun.h> 54190688Sweongyo 55190688Sweongyo#define TUNDEBUG if (tundebug) printf 56190688Sweongyo#define TUNNAME "tun" 57190688Sweongyo#define TUN_MAXUNIT 0x7fff /* ifp->if_unit is only 15 bits */ 58190688Sweongyo 59190688Sweongyostatic MALLOC_DEFINE(M_TUN, TUNNAME, "Tunnel Interface"); 60190688Sweongyostatic int tundebug = 0; 61190688Sweongyostatic struct tun_softc *tunhead = NULL; 62190688Sweongyostatic struct rman tununits; 63190688Sweongyostatic udev_t tunbasedev = NOUDEV; 64190688SweongyoSYSCTL_INT(_debug, OID_AUTO, if_tun_debug, CTLFLAG_RW, &tundebug, 0, ""); 65190688Sweongyo 66190688Sweongyostatic void tunclone(void *arg, char *name, int namelen, dev_t *dev); 67190688Sweongyostatic void tuncreate(dev_t dev); 68190688Sweongyostatic int tunifioctl(struct ifnet *, u_long, caddr_t); 69190688Sweongyostatic int tuninit(struct ifnet *); 70190688Sweongyostatic int tunmodevent(module_t, int, void *); 71190688Sweongyostatic int tunoutput(struct ifnet *, struct mbuf *, struct sockaddr *, 72190688Sweongyo struct rtentry *rt); 73190688Sweongyostatic void tunstart(struct ifnet *); 74190688Sweongyo 75190688Sweongyostatic d_open_t tunopen; 76190688Sweongyostatic d_close_t tunclose; 77190688Sweongyostatic d_read_t tunread; 78190688Sweongyostatic d_write_t tunwrite; 79190688Sweongyostatic d_ioctl_t tunioctl; 80190688Sweongyostatic d_poll_t tunpoll; 81190688Sweongyo 82190688Sweongyo#define CDEV_MAJOR 52 83190688Sweongyostatic struct cdevsw tun_cdevsw = { 84190688Sweongyo /* open */ tunopen, 85190688Sweongyo /* close */ tunclose, 86190688Sweongyo /* read */ tunread, 87190688Sweongyo /* write */ tunwrite, 88190688Sweongyo /* ioctl */ tunioctl, 89190688Sweongyo /* poll */ tunpoll, 90190688Sweongyo /* mmap */ nommap, 91190688Sweongyo /* strategy */ nostrategy, 92190688Sweongyo /* name */ TUNNAME, 93190688Sweongyo /* maj */ CDEV_MAJOR, 94190688Sweongyo /* dump */ nodump, 95190688Sweongyo /* psize */ nopsize, 96190688Sweongyo /* flags */ 0, 97190688Sweongyo}; 98190688Sweongyo 99190688Sweongyostatic void 100190688Sweongyotunclone(void *arg, char *name, int namelen, dev_t *dev) 101190688Sweongyo{ 102190688Sweongyo struct resource *r; 103190688Sweongyo int err; 104190688Sweongyo int u; 105190688Sweongyo 106190688Sweongyo if (*dev != NODEV) 107190688Sweongyo return; 108190688Sweongyo 109190688Sweongyo if (strcmp(name, TUNNAME) == 0) { 110190688Sweongyo r = rman_reserve_resource(&tununits, 0, TUN_MAXUNIT, 1, 111190688Sweongyo RF_ALLOCATED | RF_ACTIVE, NULL); 112190688Sweongyo u = rman_get_start(r); 113190688Sweongyo err = rman_release_resource(r); 114190688Sweongyo KASSERT(err == 0, ("Unexpected failure releasing resource")); 115190688Sweongyo *dev = makedev(CDEV_MAJOR, unit2minor(u)); 116190688Sweongyo if ((*dev)->si_flags & SI_NAMED) 117190688Sweongyo return; /* Already make_dev()d */ 118190688Sweongyo } else if (dev_stdclone(name, NULL, TUNNAME, &u) != 1) 119190688Sweongyo return; /* Don't recognise the name */ 120190688Sweongyo 121190688Sweongyo *dev = make_dev(&tun_cdevsw, unit2minor(u), 122190688Sweongyo UID_ROOT, GID_WHEEL, 0600, "tun%d", u); 123190688Sweongyo 124190688Sweongyo /* 125190688Sweongyo * All devices depend on tunbasedev so that we can simply 126190688Sweongyo * destroy_dev() this device at module unload time to get 127190688Sweongyo * rid of all our make_dev()d resources. 128190688Sweongyo */ 129190688Sweongyo if (tunbasedev == NOUDEV) 130190688Sweongyo tunbasedev = (*dev)->si_udev; 131190688Sweongyo else { 132190688Sweongyo (*dev)->si_flags |= SI_CHEAPCLONE; 133190688Sweongyo dev_depends(udev2dev(tunbasedev, 0), *dev); 134190688Sweongyo } 135190688Sweongyo} 136190688Sweongyo 137190688Sweongyostatic int 138190688Sweongyotunmodevent(module_t mod, int type, void *data) 139190688Sweongyo{ 140190688Sweongyo static eventhandler_tag tag; 141190688Sweongyo struct tun_softc *tp; 142190688Sweongyo dev_t dev; 143190688Sweongyo int err; 144190688Sweongyo 145190688Sweongyo switch (type) { 146190688Sweongyo case MOD_LOAD: 147190688Sweongyo tag = EVENTHANDLER_REGISTER(dev_clone, tunclone, 0, 1000); 148190688Sweongyo if (tag == NULL) 149190688Sweongyo return (ENOMEM); 150190688Sweongyo if (!devfs_present) { 151190688Sweongyo err = cdevsw_add(&tun_cdevsw); 152190688Sweongyo if (err != 0) { 153190688Sweongyo EVENTHANDLER_DEREGISTER(dev_clone, tag); 154190688Sweongyo return (err); 155190688Sweongyo } 156190688Sweongyo } 157190688Sweongyo tununits.rm_type = RMAN_ARRAY; 158190688Sweongyo tununits.rm_descr = "open if_tun units"; 159190688Sweongyo err = rman_init(&tununits); 160190688Sweongyo if (err != 0) { 161190688Sweongyo cdevsw_remove(&tun_cdevsw); 162190688Sweongyo EVENTHANDLER_DEREGISTER(dev_clone, tag); 163190688Sweongyo return (err); 164190688Sweongyo } 165190688Sweongyo err = rman_manage_region(&tununits, 0, TUN_MAXUNIT); 166190688Sweongyo if (err != 0) { 167190688Sweongyo printf("%s: tununits: rman_manage_region: Failed %d\n", 168190688Sweongyo TUNNAME, err); 169190688Sweongyo rman_fini(&tununits); 170190688Sweongyo cdevsw_remove(&tun_cdevsw); 171190688Sweongyo EVENTHANDLER_DEREGISTER(dev_clone, tag); 172190688Sweongyo return (err); 173190688Sweongyo } 174190688Sweongyo break; 175190688Sweongyo case MOD_UNLOAD: 176190688Sweongyo err = rman_fini(&tununits); 177190688Sweongyo if (err != 0) 178190688Sweongyo return (err); 179190688Sweongyo EVENTHANDLER_DEREGISTER(dev_clone, tag); 180190688Sweongyo 181190688Sweongyo while (tunhead != NULL) { 182190688Sweongyo KASSERT((tunhead->tun_flags & TUN_OPEN) == 0, 183190688Sweongyo ("tununits is out of sync - unit %d", 184190688Sweongyo tunhead->tun_if.if_unit)); 185190688Sweongyo tp = tunhead; 186190688Sweongyo dev = makedev(tun_cdevsw.d_maj, 187190688Sweongyo unit2minor(tp->tun_if.if_unit)); 188190688Sweongyo KASSERT(dev->si_drv1 == tp, ("Bad makedev result")); 189190688Sweongyo tunhead = tp->next; 190190688Sweongyo bpfdetach(&tp->tun_if); 191190688Sweongyo if_detach(&tp->tun_if); 192190688Sweongyo KASSERT(dev->si_flags & SI_NAMED, ("Missing make_dev")); 193190688Sweongyo free(tp, M_TUN); 194190688Sweongyo } 195190688Sweongyo 196190688Sweongyo /* 197190688Sweongyo * Destroying tunbasedev results in all of our make_dev()s 198190688Sweongyo * conveniently going away. 199190688Sweongyo */ 200190688Sweongyo if (tunbasedev != NOUDEV) 201190688Sweongyo destroy_dev(udev2dev(tunbasedev, 0)); 202190688Sweongyo 203190688Sweongyo if (!devfs_present) 204190688Sweongyo cdevsw_remove(&tun_cdevsw); 205190688Sweongyo break; 206190688Sweongyo } 207190688Sweongyo return 0; 208190688Sweongyo} 209190688Sweongyo 210190688Sweongyostatic moduledata_t tun_mod = { 211190744Sthompsa "if_tun", 212190744Sthompsa tunmodevent, 213190688Sweongyo 0 214190688Sweongyo}; 215190688Sweongyo 216190744SthompsaDECLARE_MODULE(if_tun, tun_mod, SI_SUB_PSEUDO, SI_ORDER_ANY); 217190688Sweongyo 218190688Sweongyostatic void 219190688Sweongyotunstart(struct ifnet *ifp) 220190688Sweongyo{ 221190688Sweongyo struct tun_softc *tp = ifp->if_softc; 222190744Sthompsa 223190744Sthompsa if (tp->tun_flags & TUN_RWAIT) { 224190688Sweongyo tp->tun_flags &= ~TUN_RWAIT; 225190688Sweongyo wakeup((caddr_t)tp); 226190688Sweongyo } 227190688Sweongyo if (tp->tun_flags & TUN_ASYNC && tp->tun_sigio) 228190744Sthompsa pgsigio(&tp->tun_sigio, SIGIO, 0); 229190744Sthompsa selwakeup(&tp->tun_rsel); 230190688Sweongyo} 231190688Sweongyo 232190688Sweongyostatic void 233190688Sweongyotuncreate(dev_t dev) 234190688Sweongyo{ 235190744Sthompsa struct tun_softc *sc; 236190744Sthompsa struct ifnet *ifp; 237190688Sweongyo 238190688Sweongyo if (!(dev->si_flags & SI_NAMED)) 239190688Sweongyo dev = make_dev(&tun_cdevsw, minor(dev), 240190688Sweongyo UID_UUCP, GID_DIALER, 0600, "tun%d", dev2unit(dev)); 241190744Sthompsa 242190688Sweongyo MALLOC(sc, struct tun_softc *, sizeof(*sc), M_TUN, M_WAITOK | M_ZERO); 243190688Sweongyo sc->tun_flags = TUN_INITED; 244190688Sweongyo sc->next = tunhead; 245190688Sweongyo tunhead = sc; 246190688Sweongyo 247190744Sthompsa ifp = &sc->tun_if; 248190744Sthompsa ifp->if_unit = dev2unit(dev); 249190688Sweongyo ifp->if_name = TUNNAME; 250190688Sweongyo ifp->if_mtu = TUNMTU; 251190688Sweongyo ifp->if_ioctl = tunifioctl; 252190688Sweongyo ifp->if_output = tunoutput; 253190744Sthompsa ifp->if_start = tunstart; 254190744Sthompsa ifp->if_flags = IFF_POINTOPOINT | IFF_MULTICAST; 255190688Sweongyo ifp->if_type = IFT_PPP; 256190688Sweongyo ifp->if_snd.ifq_maxlen = ifqmaxlen; 257190688Sweongyo ifp->if_softc = sc; 258190688Sweongyo if_attach(ifp); 259190688Sweongyo bpfattach(ifp, DLT_NULL, sizeof(u_int)); 260190688Sweongyo dev->si_drv1 = sc; 261190688Sweongyo} 262190688Sweongyo 263190688Sweongyostatic int 264190688Sweongyotunopen(dev_t dev, int flag, int mode, struct thread *td) 265190688Sweongyo{ 266190688Sweongyo struct resource *r; 267190688Sweongyo struct ifnet *ifp; 268190688Sweongyo struct tun_softc *tp; 269190688Sweongyo int unit; 270190688Sweongyo 271190688Sweongyo unit = dev2unit(dev); 272190688Sweongyo if (unit > TUN_MAXUNIT) 273190688Sweongyo return (ENXIO); 274190688Sweongyo 275190688Sweongyo r = rman_reserve_resource(&tununits, unit, unit, 1, 276190688Sweongyo RF_ALLOCATED | RF_ACTIVE, NULL); 277190688Sweongyo if (r == NULL) 278190688Sweongyo return (EBUSY); 279190688Sweongyo 280190688Sweongyo dev->si_flags &= ~SI_CHEAPCLONE; 281190688Sweongyo 282190688Sweongyo tp = dev->si_drv1; 283190688Sweongyo if (!tp) { 284190688Sweongyo tuncreate(dev); 285190688Sweongyo tp = dev->si_drv1; 286190688Sweongyo } 287190688Sweongyo KASSERT(!(tp->tun_flags & TUN_OPEN), ("Resource & flags out-of-sync")); 288190688Sweongyo tp->r_unit = r; 289190688Sweongyo tp->tun_pid = td->td_proc->p_pid; 290190688Sweongyo ifp = &tp->tun_if; 291190688Sweongyo tp->tun_flags |= TUN_OPEN; 292190688Sweongyo TUNDEBUG("%s%d: open\n", ifp->if_name, ifp->if_unit); 293190688Sweongyo 294190688Sweongyo return (0); 295190688Sweongyo} 296190688Sweongyo 297190688Sweongyo/* 298190688Sweongyo * tunclose - close the device - mark i/f down & delete 299190688Sweongyo * routing info 300190688Sweongyo */ 301190688Sweongyostatic int 302190688Sweongyotunclose(dev_t dev, int foo, int bar, struct thread *td) 303190688Sweongyo{ 304190688Sweongyo struct tun_softc *tp; 305190688Sweongyo struct ifnet *ifp; 306190688Sweongyo int s; 307190688Sweongyo int err; 308190688Sweongyo 309190688Sweongyo tp = dev->si_drv1; 310190688Sweongyo ifp = &tp->tun_if; 311190688Sweongyo 312190688Sweongyo KASSERT(tp->r_unit, ("Unit %d not marked open", ifp->if_unit)); 313190688Sweongyo tp->tun_flags &= ~TUN_OPEN; 314190688Sweongyo tp->tun_pid = 0; 315190688Sweongyo 316190688Sweongyo /* 317190688Sweongyo * junk all pending output 318190688Sweongyo */ 319190688Sweongyo IF_DRAIN(&ifp->if_snd); 320190688Sweongyo 321190688Sweongyo if (ifp->if_flags & IFF_UP) { 322190688Sweongyo s = splimp(); 323190688Sweongyo if_down(ifp); 324190688Sweongyo splx(s); 325190688Sweongyo } 326190688Sweongyo 327190688Sweongyo if (ifp->if_flags & IFF_RUNNING) { 328190688Sweongyo register struct ifaddr *ifa; 329190688Sweongyo 330190688Sweongyo s = splimp(); 331190688Sweongyo /* find internet addresses and delete routes */ 332190688Sweongyo TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) 333190688Sweongyo if (ifa->ifa_addr->sa_family == AF_INET) 334190688Sweongyo rtinit(ifa, (int)RTM_DELETE, 335190688Sweongyo tp->tun_flags & TUN_DSTADDR ? RTF_HOST : 0); 336190688Sweongyo ifp->if_flags &= ~IFF_RUNNING; 337190688Sweongyo splx(s); 338190688Sweongyo } 339190688Sweongyo 340190688Sweongyo funsetown(&tp->tun_sigio); 341190688Sweongyo selwakeup(&tp->tun_rsel); 342190688Sweongyo 343190688Sweongyo TUNDEBUG ("%s%d: closed\n", ifp->if_name, ifp->if_unit); 344190688Sweongyo err = rman_release_resource(tp->r_unit); 345190688Sweongyo KASSERT(err == 0, ("Unit %d failed to release", ifp->if_unit)); 346190688Sweongyo 347190688Sweongyo return (0); 348190688Sweongyo} 349190688Sweongyo 350190688Sweongyostatic int 351190688Sweongyotuninit(struct ifnet *ifp) 352190688Sweongyo{ 353190688Sweongyo struct tun_softc *tp = ifp->if_softc; 354190688Sweongyo register struct ifaddr *ifa; 355190688Sweongyo int error = 0; 356190688Sweongyo 357190688Sweongyo TUNDEBUG("%s%d: tuninit\n", ifp->if_name, ifp->if_unit); 358190688Sweongyo 359190688Sweongyo ifp->if_flags |= IFF_UP | IFF_RUNNING; 360190688Sweongyo getmicrotime(&ifp->if_lastchange); 361190688Sweongyo 362190688Sweongyo for (ifa = TAILQ_FIRST(&ifp->if_addrhead); ifa; 363190688Sweongyo ifa = TAILQ_NEXT(ifa, ifa_link)) { 364190688Sweongyo if (ifa->ifa_addr == NULL) 365190688Sweongyo error = EFAULT; 366190688Sweongyo /* XXX: Should maybe return straight off? */ 367190688Sweongyo else { 368190688Sweongyo#ifdef INET 369190688Sweongyo if (ifa->ifa_addr->sa_family == AF_INET) { 370190688Sweongyo struct sockaddr_in *si; 371190688Sweongyo 372190688Sweongyo si = (struct sockaddr_in *)ifa->ifa_addr; 373190688Sweongyo if (si->sin_addr.s_addr) 374190688Sweongyo tp->tun_flags |= TUN_IASET; 375190688Sweongyo 376190688Sweongyo si = (struct sockaddr_in *)ifa->ifa_dstaddr; 377190688Sweongyo if (si && si->sin_addr.s_addr) 378190688Sweongyo tp->tun_flags |= TUN_DSTADDR; 379190688Sweongyo } 380190688Sweongyo#endif 381190688Sweongyo } 382190688Sweongyo } 383190688Sweongyo return (error); 384190688Sweongyo} 385190688Sweongyo 386190688Sweongyo/* 387190688Sweongyo * Process an ioctl request. 388190688Sweongyo */ 389190688Sweongyostatic int 390190688Sweongyotunifioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 391190688Sweongyo{ 392190688Sweongyo struct ifreq *ifr = (struct ifreq *)data; 393190688Sweongyo struct tun_softc *tp = ifp->if_softc; 394190688Sweongyo struct ifstat *ifs; 395190688Sweongyo int error = 0, s; 396190688Sweongyo 397190688Sweongyo s = splimp(); 398190688Sweongyo switch(cmd) { 399190688Sweongyo case SIOCGIFSTATUS: 400190688Sweongyo ifs = (struct ifstat *)data; 401190688Sweongyo if (tp->tun_pid) 402190688Sweongyo sprintf(ifs->ascii + strlen(ifs->ascii), 403190688Sweongyo "\tOpened by PID %d\n", tp->tun_pid); 404190688Sweongyo break; 405190688Sweongyo case SIOCSIFADDR: 406190688Sweongyo error = tuninit(ifp); 407190688Sweongyo TUNDEBUG("%s%d: address set, error=%d\n", 408190688Sweongyo ifp->if_name, ifp->if_unit, error); 409190688Sweongyo break; 410190688Sweongyo case SIOCSIFDSTADDR: 411190688Sweongyo error = tuninit(ifp); 412190688Sweongyo TUNDEBUG("%s%d: destination address set, error=%d\n", 413190688Sweongyo ifp->if_name, ifp->if_unit, error); 414190688Sweongyo break; 415190688Sweongyo case SIOCSIFMTU: 416190688Sweongyo ifp->if_mtu = ifr->ifr_mtu; 417190688Sweongyo TUNDEBUG("%s%d: mtu set\n", ifp->if_name, ifp->if_unit); 418190688Sweongyo break; 419190688Sweongyo case SIOCSIFFLAGS: 420190688Sweongyo case SIOCADDMULTI: 421190688Sweongyo case SIOCDELMULTI: 422190688Sweongyo break; 423190688Sweongyo default: 424190688Sweongyo error = EINVAL; 425190688Sweongyo } 426190688Sweongyo splx(s); 427190688Sweongyo return (error); 428190688Sweongyo} 429190688Sweongyo 430190688Sweongyo/* 431190688Sweongyo * tunoutput - queue packets from higher level ready to put out. 432190688Sweongyo */ 433190688Sweongyostatic int 434190688Sweongyotunoutput( 435190688Sweongyo struct ifnet *ifp, 436190688Sweongyo struct mbuf *m0, 437190688Sweongyo struct sockaddr *dst, 438190688Sweongyo struct rtentry *rt) 439190688Sweongyo{ 440190688Sweongyo struct tun_softc *tp = ifp->if_softc; 441190688Sweongyo#ifdef MAC 442190688Sweongyo int error; 443190688Sweongyo#endif 444190688Sweongyo 445190688Sweongyo TUNDEBUG ("%s%d: tunoutput\n", ifp->if_name, ifp->if_unit); 446190688Sweongyo 447190688Sweongyo#ifdef MAC 448190688Sweongyo error = mac_check_ifnet_transmit(ifp, m0); 449190688Sweongyo if (error) { 450190688Sweongyo m_freem(m0); 451190688Sweongyo return (error); 452190688Sweongyo } 453190688Sweongyo#endif 454190688Sweongyo 455190688Sweongyo if ((tp->tun_flags & TUN_READY) != TUN_READY) { 456190688Sweongyo TUNDEBUG ("%s%d: not ready 0%o\n", ifp->if_name, 457190688Sweongyo ifp->if_unit, tp->tun_flags); 458190688Sweongyo m_freem (m0); 459190688Sweongyo return (EHOSTDOWN); 460190688Sweongyo } 461190688Sweongyo 462190688Sweongyo if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) { 463190688Sweongyo m_freem (m0); 464190688Sweongyo return (EHOSTDOWN); 465190688Sweongyo } 466190688Sweongyo 467190688Sweongyo /* BPF write needs to be handled specially */ 468190688Sweongyo if (dst->sa_family == AF_UNSPEC) { 469190688Sweongyo dst->sa_family = *(mtod(m0, int *)); 470190688Sweongyo m0->m_len -= sizeof(int); 471190688Sweongyo m0->m_pkthdr.len -= sizeof(int); 472190688Sweongyo m0->m_data += sizeof(int); 473190688Sweongyo } 474190688Sweongyo 475190688Sweongyo if (ifp->if_bpf) { 476190688Sweongyo /* 477190688Sweongyo * We need to prepend the address family as 478190688Sweongyo * a four byte field. Cons up a dummy header 479190688Sweongyo * to pacify bpf. This is safe because bpf 480190688Sweongyo * will only read from the mbuf (i.e., it won't 481190688Sweongyo * try to free it or keep a pointer to it). 482190688Sweongyo */ 483190688Sweongyo struct mbuf m; 484190688Sweongyo uint32_t af = dst->sa_family; 485190688Sweongyo 486190688Sweongyo m.m_next = m0; 487190688Sweongyo m.m_len = 4; 488190688Sweongyo m.m_data = (char *)⁡ 489190688Sweongyo 490190688Sweongyo bpf_mtap(ifp, &m); 491190688Sweongyo } 492190688Sweongyo 493190688Sweongyo /* prepend sockaddr? this may abort if the mbuf allocation fails */ 494190688Sweongyo if (tp->tun_flags & TUN_LMODE) { 495190688Sweongyo /* allocate space for sockaddr */ 496190688Sweongyo M_PREPEND(m0, dst->sa_len, M_DONTWAIT); 497190688Sweongyo 498190688Sweongyo /* if allocation failed drop packet */ 499190688Sweongyo if (m0 == NULL) { 500190688Sweongyo ifp->if_iqdrops++; 501190688Sweongyo ifp->if_oerrors++; 502190688Sweongyo return (ENOBUFS); 503190688Sweongyo } else { 504190688Sweongyo bcopy(dst, m0->m_data, dst->sa_len); 505190688Sweongyo } 506190688Sweongyo } 507190688Sweongyo 508190688Sweongyo if (tp->tun_flags & TUN_IFHEAD) { 509190688Sweongyo /* Prepend the address family */ 510190688Sweongyo M_PREPEND(m0, 4, M_DONTWAIT); 511190688Sweongyo 512190688Sweongyo /* if allocation failed drop packet */ 513190688Sweongyo if (m0 == NULL) { 514190688Sweongyo ifp->if_iqdrops++; 515190688Sweongyo ifp->if_oerrors++; 516190688Sweongyo return (ENOBUFS); 517190688Sweongyo } else 518190688Sweongyo *(u_int32_t *)m0->m_data = htonl(dst->sa_family); 519190688Sweongyo } else { 520190688Sweongyo#ifdef INET 521190688Sweongyo if (dst->sa_family != AF_INET) 522190688Sweongyo#endif 523190688Sweongyo { 524190688Sweongyo m_freem(m0); 525190688Sweongyo return (EAFNOSUPPORT); 526190688Sweongyo } 527190688Sweongyo } 528190688Sweongyo 529190688Sweongyo if (! IF_HANDOFF(&ifp->if_snd, m0, ifp)) { 530190688Sweongyo ifp->if_collisions++; 531190688Sweongyo return (ENOBUFS); 532190688Sweongyo } 533190688Sweongyo ifp->if_opackets++; 534190688Sweongyo return (0); 535190688Sweongyo} 536190688Sweongyo 537190688Sweongyo/* 538190688Sweongyo * the cdevsw interface is now pretty minimal. 539190688Sweongyo */ 540190688Sweongyostatic int 541190688Sweongyotunioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct thread *td) 542190688Sweongyo{ 543190688Sweongyo int s; 544190688Sweongyo int error; 545190688Sweongyo struct tun_softc *tp = dev->si_drv1; 546190688Sweongyo struct tuninfo *tunp; 547190688Sweongyo 548190688Sweongyo switch (cmd) { 549190688Sweongyo case TUNSIFINFO: 550190688Sweongyo tunp = (struct tuninfo *)data; 551190688Sweongyo if (tunp->mtu < IF_MINMTU) 552190688Sweongyo return (EINVAL); 553190688Sweongyo if (tp->tun_if.if_mtu != tunp->mtu 554190688Sweongyo && (error = suser(td)) != 0) 555190688Sweongyo return (error); 556190688Sweongyo tp->tun_if.if_mtu = tunp->mtu; 557190688Sweongyo tp->tun_if.if_type = tunp->type; 558190688Sweongyo tp->tun_if.if_baudrate = tunp->baudrate; 559190688Sweongyo break; 560190688Sweongyo case TUNGIFINFO: 561190688Sweongyo tunp = (struct tuninfo *)data; 562190688Sweongyo tunp->mtu = tp->tun_if.if_mtu; 563190688Sweongyo tunp->type = tp->tun_if.if_type; 564190688Sweongyo tunp->baudrate = tp->tun_if.if_baudrate; 565190688Sweongyo break; 566190688Sweongyo case TUNSDEBUG: 567190688Sweongyo tundebug = *(int *)data; 568190688Sweongyo break; 569190688Sweongyo case TUNGDEBUG: 570190688Sweongyo *(int *)data = tundebug; 571190688Sweongyo break; 572190688Sweongyo case TUNSLMODE: 573190688Sweongyo if (*(int *)data) { 574190688Sweongyo tp->tun_flags |= TUN_LMODE; 575190688Sweongyo tp->tun_flags &= ~TUN_IFHEAD; 576190688Sweongyo } else 577190688Sweongyo tp->tun_flags &= ~TUN_LMODE; 578190688Sweongyo break; 579190688Sweongyo case TUNSIFHEAD: 580190688Sweongyo if (*(int *)data) { 581190688Sweongyo tp->tun_flags |= TUN_IFHEAD; 582190688Sweongyo tp->tun_flags &= ~TUN_LMODE; 583190688Sweongyo } else 584190688Sweongyo tp->tun_flags &= ~TUN_IFHEAD; 585190688Sweongyo break; 586190688Sweongyo case TUNGIFHEAD: 587190688Sweongyo *(int *)data = (tp->tun_flags & TUN_IFHEAD) ? 1 : 0; 588190688Sweongyo break; 589190688Sweongyo case TUNSIFMODE: 590190688Sweongyo /* deny this if UP */ 591190688Sweongyo if (tp->tun_if.if_flags & IFF_UP) 592190688Sweongyo return(EBUSY); 593190688Sweongyo 594190688Sweongyo switch (*(int *)data & ~IFF_MULTICAST) { 595190688Sweongyo case IFF_POINTOPOINT: 596190688Sweongyo case IFF_BROADCAST: 597190688Sweongyo tp->tun_if.if_flags &= 598190688Sweongyo ~(IFF_BROADCAST|IFF_POINTOPOINT|IFF_MULTICAST); 599190688Sweongyo tp->tun_if.if_flags |= *(int *)data; 600190688Sweongyo break; 601190688Sweongyo default: 602190688Sweongyo return(EINVAL); 603190688Sweongyo } 604190688Sweongyo break; 605190688Sweongyo case TUNSIFPID: 606190688Sweongyo tp->tun_pid = curthread->td_proc->p_pid; 607190688Sweongyo break; 608190688Sweongyo case FIONBIO: 609190688Sweongyo break; 610190688Sweongyo case FIOASYNC: 611190688Sweongyo if (*(int *)data) 612190688Sweongyo tp->tun_flags |= TUN_ASYNC; 613190688Sweongyo else 614190688Sweongyo tp->tun_flags &= ~TUN_ASYNC; 615190688Sweongyo break; 616190688Sweongyo case FIONREAD: 617190688Sweongyo s = splimp(); 618190688Sweongyo if (tp->tun_if.if_snd.ifq_head) { 619190688Sweongyo struct mbuf *mb = tp->tun_if.if_snd.ifq_head; 620190688Sweongyo for( *(int *)data = 0; mb != 0; mb = mb->m_next) 621190688Sweongyo *(int *)data += mb->m_len; 622190688Sweongyo } else 623190688Sweongyo *(int *)data = 0; 624190688Sweongyo splx(s); 625190688Sweongyo break; 626190688Sweongyo case FIOSETOWN: 627190688Sweongyo return (fsetown(*(int *)data, &tp->tun_sigio)); 628190688Sweongyo 629190688Sweongyo case FIOGETOWN: 630190688Sweongyo *(int *)data = fgetown(&tp->tun_sigio); 631190688Sweongyo return (0); 632190688Sweongyo 633190688Sweongyo /* This is deprecated, FIOSETOWN should be used instead. */ 634190688Sweongyo case TIOCSPGRP: 635190688Sweongyo return (fsetown(-(*(int *)data), &tp->tun_sigio)); 636190688Sweongyo 637190688Sweongyo /* This is deprecated, FIOGETOWN should be used instead. */ 638190688Sweongyo case TIOCGPGRP: 639190688Sweongyo *(int *)data = -fgetown(&tp->tun_sigio); 640190688Sweongyo return (0); 641190688Sweongyo 642190688Sweongyo default: 643190688Sweongyo return (ENOTTY); 644190688Sweongyo } 645190688Sweongyo return (0); 646190688Sweongyo} 647190688Sweongyo 648190688Sweongyo/* 649190688Sweongyo * The cdevsw read interface - reads a packet at a time, or at 650190688Sweongyo * least as much of a packet as can be read. 651190688Sweongyo */ 652190688Sweongyostatic int 653190688Sweongyotunread(dev_t dev, struct uio *uio, int flag) 654190688Sweongyo{ 655190688Sweongyo struct tun_softc *tp = dev->si_drv1; 656190688Sweongyo struct ifnet *ifp = &tp->tun_if; 657190688Sweongyo struct mbuf *m; 658190688Sweongyo int error=0, len, s; 659190688Sweongyo 660190688Sweongyo TUNDEBUG ("%s%d: read\n", ifp->if_name, ifp->if_unit); 661190688Sweongyo if ((tp->tun_flags & TUN_READY) != TUN_READY) { 662190688Sweongyo TUNDEBUG ("%s%d: not ready 0%o\n", ifp->if_name, 663190688Sweongyo ifp->if_unit, tp->tun_flags); 664190688Sweongyo return (EHOSTDOWN); 665190688Sweongyo } 666190688Sweongyo 667190688Sweongyo tp->tun_flags &= ~TUN_RWAIT; 668190688Sweongyo 669190688Sweongyo s = splimp(); 670190688Sweongyo do { 671190688Sweongyo IF_DEQUEUE(&ifp->if_snd, m); 672190688Sweongyo if (m == NULL) { 673190688Sweongyo if (flag & IO_NDELAY) { 674190688Sweongyo splx(s); 675190688Sweongyo return (EWOULDBLOCK); 676190688Sweongyo } 677190688Sweongyo tp->tun_flags |= TUN_RWAIT; 678190688Sweongyo if((error = tsleep((caddr_t)tp, PCATCH | (PZERO + 1), 679190688Sweongyo "tunread", 0)) != 0) { 680190688Sweongyo splx(s); 681190688Sweongyo return (error); 682190688Sweongyo } 683190688Sweongyo } 684190688Sweongyo } while (m == NULL); 685190688Sweongyo splx(s); 686190688Sweongyo 687190688Sweongyo while (m && uio->uio_resid > 0 && error == 0) { 688190688Sweongyo len = min(uio->uio_resid, m->m_len); 689190688Sweongyo if (len != 0) 690190688Sweongyo error = uiomove(mtod(m, caddr_t), len, uio); 691190688Sweongyo m = m_free(m); 692190688Sweongyo } 693190688Sweongyo 694190688Sweongyo if (m) { 695190688Sweongyo TUNDEBUG("%s%d: Dropping mbuf\n", ifp->if_name, ifp->if_unit); 696190688Sweongyo m_freem(m); 697190688Sweongyo } 698190688Sweongyo return (error); 699190688Sweongyo} 700190688Sweongyo 701190688Sweongyo/* 702190688Sweongyo * the cdevsw write interface - an atomic write is a packet - or else! 703190688Sweongyo */ 704190688Sweongyostatic int 705190688Sweongyotunwrite(dev_t dev, struct uio *uio, int flag) 706190688Sweongyo{ 707190688Sweongyo struct tun_softc *tp = dev->si_drv1; 708190688Sweongyo struct ifnet *ifp = &tp->tun_if; 709190688Sweongyo struct mbuf *top, **mp, *m; 710190688Sweongyo int error=0, tlen, mlen; 711190688Sweongyo uint32_t family; 712190688Sweongyo 713190688Sweongyo TUNDEBUG("%s%d: tunwrite\n", ifp->if_name, ifp->if_unit); 714190688Sweongyo 715190688Sweongyo if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) 716190688Sweongyo /* ignore silently */ 717190688Sweongyo return (0); 718190688Sweongyo 719190688Sweongyo if (uio->uio_resid == 0) 720190688Sweongyo return (0); 721190688Sweongyo 722190688Sweongyo if (uio->uio_resid < 0 || uio->uio_resid > TUNMRU) { 723190688Sweongyo TUNDEBUG("%s%d: len=%d!\n", ifp->if_name, ifp->if_unit, 724190688Sweongyo uio->uio_resid); 725190688Sweongyo return (EIO); 726190688Sweongyo } 727190688Sweongyo tlen = uio->uio_resid; 728190688Sweongyo 729190688Sweongyo /* get a header mbuf */ 730190688Sweongyo MGETHDR(m, M_DONTWAIT, MT_DATA); 731190688Sweongyo if (m == NULL) 732190688Sweongyo return (ENOBUFS); 733190688Sweongyo mlen = MHLEN; 734190688Sweongyo 735190688Sweongyo top = 0; 736190688Sweongyo mp = ⊤ 737190688Sweongyo while (error == 0 && uio->uio_resid > 0) { 738190688Sweongyo m->m_len = min(mlen, uio->uio_resid); 739190688Sweongyo error = uiomove(mtod (m, caddr_t), m->m_len, uio); 740190688Sweongyo *mp = m; 741190688Sweongyo mp = &m->m_next; 742190688Sweongyo if (uio->uio_resid > 0) { 743190688Sweongyo MGET (m, M_DONTWAIT, MT_DATA); 744190688Sweongyo if (m == 0) { 745190688Sweongyo error = ENOBUFS; 746190688Sweongyo break; 747190688Sweongyo } 748190688Sweongyo mlen = MLEN; 749190688Sweongyo } 750190688Sweongyo } 751190688Sweongyo if (error) { 752190688Sweongyo if (top) 753190688Sweongyo m_freem (top); 754190688Sweongyo ifp->if_ierrors++; 755190688Sweongyo return (error); 756190688Sweongyo } 757190688Sweongyo 758190688Sweongyo top->m_pkthdr.len = tlen; 759190688Sweongyo top->m_pkthdr.rcvif = ifp; 760190688Sweongyo#ifdef MAC 761190688Sweongyo mac_create_mbuf_from_ifnet(ifp, top); 762190688Sweongyo#endif 763190688Sweongyo 764190688Sweongyo if (ifp->if_bpf) { 765190688Sweongyo if (tp->tun_flags & TUN_IFHEAD) { 766190688Sweongyo /* 767190688Sweongyo * Conveniently, we already have a 4-byte address 768190688Sweongyo * family prepended to our packet ! 769190688Sweongyo * Inconveniently, it's in the wrong byte order ! 770190688Sweongyo */ 771190688Sweongyo if ((top = m_pullup(top, sizeof(family))) == NULL) 772190688Sweongyo return (ENOBUFS); 773190688Sweongyo *mtod(top, u_int32_t *) = 774190688Sweongyo ntohl(*mtod(top, u_int32_t *)); 775190688Sweongyo bpf_mtap(ifp, top); 776190688Sweongyo *mtod(top, u_int32_t *) = 777190688Sweongyo htonl(*mtod(top, u_int32_t *)); 778190688Sweongyo } else { 779190688Sweongyo /* 780190688Sweongyo * We need to prepend the address family as 781190688Sweongyo * a four byte field. Cons up a dummy header 782190688Sweongyo * to pacify bpf. This is safe because bpf 783190688Sweongyo * will only read from the mbuf (i.e., it won't 784190688Sweongyo * try to free it or keep a pointer to it). 785190688Sweongyo */ 786190688Sweongyo struct mbuf m; 787190688Sweongyo uint32_t af = AF_INET; 788190688Sweongyo 789190688Sweongyo m.m_next = top; 790190688Sweongyo m.m_len = 4; 791190688Sweongyo m.m_data = (char *)⁡ 792190688Sweongyo 793190688Sweongyo bpf_mtap(ifp, &m); 794190688Sweongyo } 795190688Sweongyo } 796190688Sweongyo 797190688Sweongyo if (tp->tun_flags & TUN_IFHEAD) { 798190688Sweongyo if (top->m_len < sizeof(family) && 799190688Sweongyo (top = m_pullup(top, sizeof(family))) == NULL) 800190688Sweongyo return (ENOBUFS); 801190688Sweongyo family = ntohl(*mtod(top, u_int32_t *)); 802190688Sweongyo m_adj(top, sizeof(family)); 803190688Sweongyo } else 804190688Sweongyo family = AF_INET; 805190688Sweongyo 806190688Sweongyo ifp->if_ibytes += top->m_pkthdr.len; 807190688Sweongyo ifp->if_ipackets++; 808190688Sweongyo 809190688Sweongyo return (family_enqueue(family, top)); 810190688Sweongyo} 811190688Sweongyo 812190688Sweongyo/* 813190688Sweongyo * tunpoll - the poll interface, this is only useful on reads 814190688Sweongyo * really. The write detect always returns true, write never blocks 815190688Sweongyo * anyway, it either accepts the packet or drops it. 816190688Sweongyo */ 817190688Sweongyostatic int 818190688Sweongyotunpoll(dev_t dev, int events, struct thread *td) 819190688Sweongyo{ 820190688Sweongyo int s; 821190688Sweongyo struct tun_softc *tp = dev->si_drv1; 822190688Sweongyo struct ifnet *ifp = &tp->tun_if; 823190688Sweongyo int revents = 0; 824190688Sweongyo 825190688Sweongyo s = splimp(); 826190688Sweongyo TUNDEBUG("%s%d: tunpoll\n", ifp->if_name, ifp->if_unit); 827190688Sweongyo 828190688Sweongyo if (events & (POLLIN | POLLRDNORM)) { 829190688Sweongyo if (ifp->if_snd.ifq_len > 0) { 830190688Sweongyo TUNDEBUG("%s%d: tunpoll q=%d\n", ifp->if_name, 831190688Sweongyo ifp->if_unit, ifp->if_snd.ifq_len); 832190688Sweongyo revents |= events & (POLLIN | POLLRDNORM); 833190688Sweongyo } else { 834190688Sweongyo TUNDEBUG("%s%d: tunpoll waiting\n", ifp->if_name, 835190688Sweongyo ifp->if_unit); 836190688Sweongyo selrecord(td, &tp->tun_rsel); 837190688Sweongyo } 838190688Sweongyo } 839190688Sweongyo if (events & (POLLOUT | POLLWRNORM)) 840190688Sweongyo revents |= events & (POLLOUT | POLLWRNORM); 841190688Sweongyo 842190688Sweongyo splx(s); 843190688Sweongyo return (revents); 844190688Sweongyo} 845190688Sweongyo