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