if_tun.c revision 64880
1185573Srwatson/* $NetBSD: if_tun.c,v 1.14 1994/06/29 06:36:25 cgd Exp $ */ 2191273Srwatson 3155131Srwatson/* 4155131Srwatson * Copyright (c) 1988, Julian Onions <jpo@cs.nott.ac.uk> 5155131Srwatson * Nottingham University 1987. 6155131Srwatson * 7155131Srwatson * This source may be freely distributed, however I would be interested 8155131Srwatson * in any changes that are made. 9155131Srwatson * 10155131Srwatson * This driver takes packets off the IP i/f and hands them up to a 11155131Srwatson * user process to have its wicked way with. This driver has it's 12155131Srwatson * roots in a similar driver written by Phil Cockcroft (formerly) at 13185573Srwatson * UCL. This driver is based much more on read/write/poll mode of 14155131Srwatson * operation though. 15155131Srwatson * 16155131Srwatson * $FreeBSD: head/sys/net/if_tun.c 64880 2000-08-20 21:34:39Z phk $ 17155131Srwatson */ 18155131Srwatson 19155131Srwatson#include "opt_inet.h" 20155131Srwatson#include "opt_devfs.h" 21155131Srwatson 22155131Srwatson#include <sys/param.h> 23155131Srwatson#include <sys/proc.h> 24155131Srwatson#include <sys/systm.h> 25155131Srwatson#include <sys/mbuf.h> 26155131Srwatson#include <sys/socket.h> 27155131Srwatson#include <sys/filio.h> 28155131Srwatson#include <sys/sockio.h> 29155131Srwatson#include <sys/ttycom.h> 30155518Srwatson#include <sys/poll.h> 31155518Srwatson#include <sys/signalvar.h> 32155518Srwatson#include <sys/filedesc.h> 33155518Srwatson#include <sys/kernel.h> 34155131Srwatson#include <sys/sysctl.h> 35155131Srwatson#include <sys/conf.h> 36156283Srwatson#include <sys/uio.h> 37156283Srwatson#include <sys/vnode.h> 38156283Srwatson#include <sys/malloc.h> 39156283Srwatson 40156283Srwatson#include <net/if.h> 41155131Srwatson#include <net/if_types.h> 42155131Srwatson#include <net/route.h> 43155131Srwatson#include <net/intrq.h> 44155131Srwatson 45155131Srwatson#ifdef INET 46155131Srwatson#include <netinet/in.h> 47159248Srwatson#endif 48155131Srwatson 49155131Srwatson#include <net/bpf.h> 50155131Srwatson 51155131Srwatson#include <net/if_tunvar.h> 52155131Srwatson#include <net/if_tun.h> 53155131Srwatson 54155131Srwatson#ifdef DEVFS 55159248Srwatson#include <sys/eventhandler.h> 56159248Srwatson#include <fs/devfs/devfs.h> 57159248Srwatson#endif 58155131Srwatson 59159248Srwatsonstatic MALLOC_DEFINE(M_TUN, "tun", "Tunnel Interface"); 60159248Srwatson 61159248Srwatsonstatic void tunattach __P((void *)); 62159248SrwatsonPSEUDO_SET(tunattach, if_tun); 63159248Srwatson 64191273Srwatsonstatic void tuncreate __P((dev_t dev)); 65159248Srwatson 66159248Srwatson#define TUNDEBUG if (tundebug) printf 67168777Srwatsonstatic int tundebug = 0; 68159248SrwatsonSYSCTL_INT(_debug, OID_AUTO, if_tun_debug, CTLFLAG_RW, &tundebug, 0, ""); 69168777Srwatson 70186647Srwatsonstatic int tunoutput __P((struct ifnet *, struct mbuf *, struct sockaddr *, 71159248Srwatson struct rtentry *rt)); 72191273Srwatsonstatic int tunifioctl __P((struct ifnet *, u_long, caddr_t)); 73159248Srwatsonstatic int tuninit __P((struct ifnet *)); 74159248Srwatson 75159248Srwatsonstatic d_open_t tunopen; 76159248Srwatsonstatic d_close_t tunclose; 77159248Srwatsonstatic d_read_t tunread; 78159248Srwatsonstatic d_write_t tunwrite; 79159248Srwatsonstatic d_ioctl_t tunioctl; 80159248Srwatsonstatic d_poll_t tunpoll; 81159248Srwatson 82159248Srwatson#define CDEV_MAJOR 52 83159248Srwatsonstatic struct cdevsw tun_cdevsw = { 84159248Srwatson /* open */ tunopen, 85159248Srwatson /* close */ tunclose, 86159248Srwatson /* read */ tunread, 87159248Srwatson /* write */ tunwrite, 88159248Srwatson /* ioctl */ tunioctl, 89159248Srwatson /* poll */ tunpoll, 90159248Srwatson /* mmap */ nommap, 91159248Srwatson /* strategy */ nostrategy, 92159248Srwatson /* name */ "tun", 93159248Srwatson /* maj */ CDEV_MAJOR, 94159248Srwatson /* dump */ nodump, 95168777Srwatson /* psize */ nopsize, 96186647Srwatson /* flags */ 0, 97186647Srwatson /* bmaj */ -1 98168777Srwatson}; 99168777Srwatson 100186647Srwatson#ifdef DEVFS 101186647Srwatsonstatic void tun_clone __P((void *arg, char *name, int namelen, dev_t *dev)); 102186647Srwatson 103186647Srwatsonstatic void 104186647Srwatsontun_clone(arg, name, namelen, dev) 105186647Srwatson void *arg; 106186647Srwatson char *name; 107186647Srwatson int namelen; 108186647Srwatson dev_t *dev; 109186647Srwatson{ 110186647Srwatson int u; 111186647Srwatson 112186647Srwatson if (*dev != NODEV) 113186647Srwatson return; 114186647Srwatson if (devfs_stdclone(name, NULL, "tun", &u) != 1) 115186647Srwatson return; 116186647Srwatson /* XXX: minor encoding if u > 255 */ 117186647Srwatson *dev = make_dev(&tun_cdevsw, u, 118186647Srwatson UID_UUCP, GID_DIALER, 0600, "tun%d", u); 119186647Srwatson 120186647Srwatson} 121186647Srwatson#endif 122159248Srwatson 123186647Srwatson 124159248Srwatsonstatic void 125159248Srwatsontunattach(dummy) 126159248Srwatson void *dummy; 127159248Srwatson{ 128186647Srwatson 129186647Srwatson#ifdef DEVFS 130186647Srwatson EVENTHANDLER_REGISTER(devfs_clone, tun_clone, 0, 1000); 131186647Srwatson#else 132186647Srwatson cdevsw_add(&tun_cdevsw); 133186647Srwatson#endif 134159248Srwatson} 135186647Srwatson 136186647Srwatsonstatic void 137186647Srwatsontuncreate(dev) 138168777Srwatson dev_t dev; 139186647Srwatson{ 140186647Srwatson struct tun_softc *sc; 141168777Srwatson struct ifnet *ifp; 142168777Srwatson 143159248Srwatson dev = make_dev(&tun_cdevsw, minor(dev), 144159248Srwatson UID_UUCP, GID_DIALER, 0600, "tun%d", lminor(dev)); 145159248Srwatson 146159248Srwatson MALLOC(sc, struct tun_softc *, sizeof(*sc), M_TUN, M_WAITOK); 147159248Srwatson bzero(sc, sizeof *sc); 148159248Srwatson sc->tun_flags = TUN_INITED; 149159248Srwatson 150159248Srwatson ifp = &sc->tun_if; 151159248Srwatson ifp->if_unit = lminor(dev); 152159248Srwatson ifp->if_name = "tun"; 153159248Srwatson ifp->if_mtu = TUNMTU; 154159248Srwatson ifp->if_ioctl = tunifioctl; 155159248Srwatson ifp->if_output = tunoutput; 156159248Srwatson ifp->if_flags = IFF_POINTOPOINT | IFF_MULTICAST; 157159248Srwatson ifp->if_type = IFT_PPP; 158159248Srwatson ifp->if_snd.ifq_maxlen = ifqmaxlen; 159159248Srwatson ifp->if_softc = sc; 160159248Srwatson if_attach(ifp); 161159248Srwatson bpfattach(ifp, DLT_NULL, sizeof(u_int)); 162159248Srwatson dev->si_drv1 = sc; 163159248Srwatson} 164159248Srwatson 165159248Srwatson/* 166159248Srwatson * tunnel open - must be superuser & the device must be 167159248Srwatson * configured in 168159248Srwatson */ 169159248Srwatsonstatic int 170159248Srwatsontunopen(dev, flag, mode, p) 171159248Srwatson dev_t dev; 172159248Srwatson int flag, mode; 173159248Srwatson struct proc *p; 174159248Srwatson{ 175159248Srwatson struct ifnet *ifp; 176159248Srwatson struct tun_softc *tp; 177159248Srwatson register int error; 178159248Srwatson 179191273Srwatson error = suser(p); 180159248Srwatson if (error) 181159248Srwatson return (error); 182243750Srwatson 183159248Srwatson tp = dev->si_drv1; 184159248Srwatson if (!tp) { 185159248Srwatson tuncreate(dev); 186159248Srwatson tp = dev->si_drv1; 187159248Srwatson } 188159248Srwatson if (tp->tun_flags & TUN_OPEN) 189159248Srwatson return EBUSY; 190159248Srwatson tp->tun_pid = p->p_pid; 191159248Srwatson ifp = &tp->tun_if; 192159248Srwatson tp->tun_flags |= TUN_OPEN; 193159248Srwatson TUNDEBUG("%s%d: open\n", ifp->if_name, ifp->if_unit); 194159248Srwatson return (0); 195159248Srwatson} 196159248Srwatson 197159248Srwatson/* 198159248Srwatson * tunclose - close the device - mark i/f down & delete 199159248Srwatson * routing info 200159248Srwatson */ 201159248Srwatsonstatic int 202159248Srwatsontunclose(dev, foo, bar, p) 203159248Srwatson dev_t dev; 204159248Srwatson int foo; 205155131Srwatson int bar; 206155131Srwatson struct proc *p; 207155131Srwatson{ 208155131Srwatson register int s; 209155131Srwatson struct tun_softc *tp; 210155131Srwatson struct ifnet *ifp; 211155131Srwatson struct mbuf *m; 212156283Srwatson 213155131Srwatson tp = dev->si_drv1; 214156283Srwatson ifp = &tp->tun_if; 215156283Srwatson 216156283Srwatson tp->tun_flags &= ~TUN_OPEN; 217155131Srwatson tp->tun_pid = 0; 218155131Srwatson 219155131Srwatson /* 220155131Srwatson * junk all pending output 221155131Srwatson */ 222155131Srwatson do { 223155131Srwatson s = splimp(); 224155131Srwatson IF_DEQUEUE(&ifp->if_snd, m); 225155131Srwatson splx(s); 226155131Srwatson if (m) 227155131Srwatson m_freem(m); 228155131Srwatson } while (m); 229155131Srwatson 230155131Srwatson if (ifp->if_flags & IFF_UP) { 231155131Srwatson s = splimp(); 232155131Srwatson if_down(ifp); 233155131Srwatson splx(s); 234155131Srwatson } 235155131Srwatson 236155131Srwatson if (ifp->if_flags & IFF_RUNNING) { 237155131Srwatson register struct ifaddr *ifa; 238156283Srwatson 239156283Srwatson s = splimp(); 240155131Srwatson /* find internet addresses and delete routes */ 241155131Srwatson for (ifa = ifp->if_addrhead.tqh_first; ifa; 242155131Srwatson ifa = ifa->ifa_link.tqe_next) 243155131Srwatson if (ifa->ifa_addr->sa_family == AF_INET) 244155131Srwatson rtinit(ifa, (int)RTM_DELETE, 245155131Srwatson tp->tun_flags & TUN_DSTADDR ? RTF_HOST : 0); 246155131Srwatson ifp->if_flags &= ~IFF_RUNNING; 247155131Srwatson splx(s); 248155131Srwatson } 249155131Srwatson 250155131Srwatson funsetown(tp->tun_sigio); 251155131Srwatson selwakeup(&tp->tun_rsel); 252156283Srwatson 253156283Srwatson TUNDEBUG ("%s%d: closed\n", ifp->if_name, ifp->if_unit); 254156283Srwatson return (0); 255156283Srwatson} 256155131Srwatson 257155131Srwatsonstatic int 258155131Srwatsontuninit(ifp) 259155131Srwatson struct ifnet *ifp; 260155131Srwatson{ 261155131Srwatson struct tun_softc *tp = ifp->if_softc; 262155131Srwatson register struct ifaddr *ifa; 263155131Srwatson 264155131Srwatson TUNDEBUG("%s%d: tuninit\n", ifp->if_name, ifp->if_unit); 265155131Srwatson 266155131Srwatson ifp->if_flags |= IFF_UP | IFF_RUNNING; 267155131Srwatson getmicrotime(&ifp->if_lastchange); 268155131Srwatson 269155131Srwatson for (ifa = ifp->if_addrhead.tqh_first; ifa; 270155131Srwatson ifa = ifa->ifa_link.tqe_next) { 271155131Srwatson#ifdef INET 272155131Srwatson if (ifa->ifa_addr->sa_family == AF_INET) { 273155131Srwatson struct sockaddr_in *si; 274155131Srwatson 275155131Srwatson si = (struct sockaddr_in *)ifa->ifa_addr; 276155131Srwatson if (si && si->sin_addr.s_addr) 277155131Srwatson tp->tun_flags |= TUN_IASET; 278155131Srwatson 279155131Srwatson si = (struct sockaddr_in *)ifa->ifa_dstaddr; 280155131Srwatson if (si && si->sin_addr.s_addr) 281159248Srwatson tp->tun_flags |= TUN_DSTADDR; 282155131Srwatson } 283155131Srwatson#endif 284155131Srwatson } 285155131Srwatson return 0; 286155131Srwatson} 287155131Srwatson 288155131Srwatson/* 289155131Srwatson * Process an ioctl request. 290155131Srwatson */ 291155131Srwatsonint 292155131Srwatsontunifioctl(ifp, cmd, data) 293155131Srwatson struct ifnet *ifp; 294155131Srwatson u_long cmd; 295155131Srwatson caddr_t data; 296155131Srwatson{ 297155131Srwatson struct ifreq *ifr = (struct ifreq *)data; 298155131Srwatson struct tun_softc *tp = ifp->if_softc; 299155131Srwatson struct ifstat *ifs; 300155131Srwatson int error = 0, s; 301155131Srwatson 302155131Srwatson s = splimp(); 303155131Srwatson switch(cmd) { 304155131Srwatson case SIOCGIFSTATUS: 305155131Srwatson ifs = (struct ifstat *)data; 306155131Srwatson if (tp->tun_pid) 307185573Srwatson sprintf(ifs->ascii + strlen(ifs->ascii), 308155131Srwatson "\tOpened by PID %d\n", tp->tun_pid); 309155131Srwatson return(0); 310155131Srwatson case SIOCSIFADDR: 311155131Srwatson tuninit(ifp); 312155131Srwatson TUNDEBUG("%s%d: address set\n", 313155131Srwatson ifp->if_name, ifp->if_unit); 314155131Srwatson break; 315159248Srwatson case SIOCSIFDSTADDR: 316155131Srwatson tuninit(ifp); 317155131Srwatson TUNDEBUG("%s%d: destination address set\n", 318155131Srwatson ifp->if_name, ifp->if_unit); 319155131Srwatson break; 320155131Srwatson case SIOCSIFMTU: 321155131Srwatson ifp->if_mtu = ifr->ifr_mtu; 322159248Srwatson TUNDEBUG("%s%d: mtu set\n", 323155131Srwatson ifp->if_name, ifp->if_unit); 324155131Srwatson break; 325155131Srwatson case SIOCADDMULTI: 326155131Srwatson case SIOCDELMULTI: 327155131Srwatson break; 328155131Srwatson 329159248Srwatson 330155131Srwatson default: 331155131Srwatson error = EINVAL; 332155131Srwatson } 333155131Srwatson splx(s); 334155131Srwatson return (error); 335159248Srwatson} 336155131Srwatson 337155131Srwatson/* 338159248Srwatson * tunoutput - queue packets from higher level ready to put out. 339155131Srwatson */ 340155131Srwatsonint 341155131Srwatsontunoutput(ifp, m0, dst, rt) 342155131Srwatson struct ifnet *ifp; 343155131Srwatson struct mbuf *m0; 344155131Srwatson struct sockaddr *dst; 345155131Srwatson struct rtentry *rt; 346155131Srwatson{ 347155131Srwatson struct tun_softc *tp = ifp->if_softc; 348155131Srwatson int s; 349155131Srwatson 350155131Srwatson TUNDEBUG ("%s%d: tunoutput\n", ifp->if_name, ifp->if_unit); 351155131Srwatson 352155131Srwatson if ((tp->tun_flags & TUN_READY) != TUN_READY) { 353155131Srwatson TUNDEBUG ("%s%d: not ready 0%o\n", ifp->if_name, 354155131Srwatson ifp->if_unit, tp->tun_flags); 355155131Srwatson m_freem (m0); 356155131Srwatson return EHOSTDOWN; 357155131Srwatson } 358155131Srwatson 359155131Srwatson /* BPF write needs to be handled specially */ 360155131Srwatson if (dst->sa_family == AF_UNSPEC) { 361155131Srwatson dst->sa_family = *(mtod(m0, int *)); 362155131Srwatson m0->m_len -= sizeof(int); 363155131Srwatson m0->m_pkthdr.len -= sizeof(int); 364155131Srwatson m0->m_data += sizeof(int); 365155131Srwatson } 366155131Srwatson 367155131Srwatson if (ifp->if_bpf) { 368155131Srwatson /* 369155131Srwatson * We need to prepend the address family as 370155131Srwatson * a four byte field. Cons up a dummy header 371155131Srwatson * to pacify bpf. This is safe because bpf 372155131Srwatson * will only read from the mbuf (i.e., it won't 373155131Srwatson * try to free it or keep a pointer to it). 374155131Srwatson */ 375155131Srwatson struct mbuf m; 376155131Srwatson u_int af = dst->sa_family; 377155131Srwatson 378155131Srwatson m.m_next = m0; 379155131Srwatson m.m_len = 4; 380155131Srwatson m.m_data = (char *)⁡ 381155131Srwatson 382155131Srwatson bpf_mtap(ifp, &m); 383155131Srwatson } 384155131Srwatson 385155131Srwatson /* prepend sockaddr? this may abort if the mbuf allocation fails */ 386155131Srwatson if (tp->tun_flags & TUN_LMODE) { 387155131Srwatson /* allocate space for sockaddr */ 388155131Srwatson M_PREPEND(m0, dst->sa_len, M_DONTWAIT); 389155131Srwatson 390155131Srwatson /* if allocation failed drop packet */ 391155131Srwatson if (m0 == NULL){ 392155131Srwatson s = splimp(); /* spl on queue manipulation */ 393155131Srwatson IF_DROP(&ifp->if_snd); 394155131Srwatson splx(s); 395155131Srwatson ifp->if_oerrors++; 396155131Srwatson return (ENOBUFS); 397155131Srwatson } else { 398155131Srwatson bcopy(dst, m0->m_data, dst->sa_len); 399155131Srwatson } 400155131Srwatson } 401155131Srwatson 402155131Srwatson if (tp->tun_flags & TUN_IFHEAD) { 403155131Srwatson /* Prepend the address family */ 404155131Srwatson M_PREPEND(m0, 4, M_DONTWAIT); 405155131Srwatson 406155131Srwatson /* if allocation failed drop packet */ 407155131Srwatson if (m0 == NULL){ 408155131Srwatson s = splimp(); /* spl on queue manipulation */ 409155131Srwatson IF_DROP(&ifp->if_snd); 410155131Srwatson splx(s); 411155131Srwatson ifp->if_oerrors++; 412155131Srwatson return ENOBUFS; 413155131Srwatson } else 414155131Srwatson *(u_int32_t *)m0->m_data = htonl(dst->sa_family); 415155131Srwatson } else { 416155131Srwatson#ifdef INET 417155131Srwatson if (dst->sa_family != AF_INET) 418155131Srwatson#endif 419155131Srwatson { 420155131Srwatson m_freem(m0); 421155131Srwatson return EAFNOSUPPORT; 422155131Srwatson } 423155131Srwatson } 424155131Srwatson 425155131Srwatson s = splimp(); 426155131Srwatson if (IF_QFULL(&ifp->if_snd)) { 427155131Srwatson IF_DROP(&ifp->if_snd); 428155131Srwatson m_freem(m0); 429155131Srwatson splx(s); 430155131Srwatson ifp->if_collisions++; 431155131Srwatson return ENOBUFS; 432155131Srwatson } 433155131Srwatson ifp->if_obytes += m0->m_pkthdr.len; 434155131Srwatson IF_ENQUEUE(&ifp->if_snd, m0); 435155131Srwatson splx(s); 436155131Srwatson ifp->if_opackets++; 437155131Srwatson 438155131Srwatson if (tp->tun_flags & TUN_RWAIT) { 439155131Srwatson tp->tun_flags &= ~TUN_RWAIT; 440155131Srwatson wakeup((caddr_t)tp); 441155131Srwatson } 442155131Srwatson if (tp->tun_flags & TUN_ASYNC && tp->tun_sigio) 443155131Srwatson pgsigio(tp->tun_sigio, SIGIO, 0); 444155131Srwatson selwakeup(&tp->tun_rsel); 445155131Srwatson return 0; 446155131Srwatson} 447155131Srwatson 448155131Srwatson/* 449155131Srwatson * the cdevsw interface is now pretty minimal. 450155131Srwatson */ 451155131Srwatsonstatic int 452155131Srwatsontunioctl(dev, cmd, data, flag, p) 453155131Srwatson dev_t dev; 454155131Srwatson u_long cmd; 455155131Srwatson caddr_t data; 456155131Srwatson int flag; 457155131Srwatson struct proc *p; 458155131Srwatson{ 459155131Srwatson int s; 460155131Srwatson struct tun_softc *tp = dev->si_drv1; 461155131Srwatson struct tuninfo *tunp; 462155131Srwatson 463155131Srwatson switch (cmd) { 464155131Srwatson case TUNSIFINFO: 465155131Srwatson tunp = (struct tuninfo *)data; 466155131Srwatson if (tunp->mtu < IF_MINMTU) 467155131Srwatson return (EINVAL); 468155131Srwatson tp->tun_if.if_mtu = tunp->mtu; 469155131Srwatson tp->tun_if.if_type = tunp->type; 470155131Srwatson tp->tun_if.if_baudrate = tunp->baudrate; 471155131Srwatson break; 472155131Srwatson case TUNGIFINFO: 473155131Srwatson tunp = (struct tuninfo *)data; 474155131Srwatson tunp->mtu = tp->tun_if.if_mtu; 475155131Srwatson tunp->type = tp->tun_if.if_type; 476155131Srwatson tunp->baudrate = tp->tun_if.if_baudrate; 477155131Srwatson break; 478155131Srwatson case TUNSDEBUG: 479155131Srwatson tundebug = *(int *)data; 480155131Srwatson break; 481155131Srwatson case TUNGDEBUG: 482155131Srwatson *(int *)data = tundebug; 483155131Srwatson break; 484155131Srwatson case TUNSLMODE: 485155131Srwatson if (*(int *)data) { 486155131Srwatson tp->tun_flags |= TUN_LMODE; 487155131Srwatson tp->tun_flags &= ~TUN_IFHEAD; 488155131Srwatson } else 489191273Srwatson tp->tun_flags &= ~TUN_LMODE; 490191273Srwatson break; 491191273Srwatson case TUNSIFHEAD: 492191273Srwatson if (*(int *)data) { 493191273Srwatson tp->tun_flags |= TUN_IFHEAD; 494191273Srwatson tp->tun_flags &= ~TUN_LMODE; 495191273Srwatson } else 496191273Srwatson tp->tun_flags &= ~TUN_IFHEAD; 497191273Srwatson break; 498191273Srwatson case TUNGIFHEAD: 499191273Srwatson *(int *)data = (tp->tun_flags & TUN_IFHEAD) ? 1 : 0; 500191273Srwatson break; 501191273Srwatson case TUNSIFMODE: 502191273Srwatson /* deny this if UP */ 503191273Srwatson if (tp->tun_if.if_flags & IFF_UP) 504191273Srwatson return(EBUSY); 505191273Srwatson 506191273Srwatson switch (*(int *)data) { 507191273Srwatson case IFF_POINTOPOINT: 508191273Srwatson tp->tun_if.if_flags |= IFF_POINTOPOINT; 509191273Srwatson tp->tun_if.if_flags &= ~IFF_BROADCAST; 510191273Srwatson break; 511191273Srwatson case IFF_BROADCAST: 512191273Srwatson tp->tun_if.if_flags &= ~IFF_POINTOPOINT; 513191273Srwatson tp->tun_if.if_flags |= IFF_BROADCAST; 514191273Srwatson break; 515191273Srwatson default: 516191273Srwatson return(EINVAL); 517191273Srwatson } 518191273Srwatson break; 519191273Srwatson case TUNSIFPID: 520191273Srwatson tp->tun_pid = curproc->p_pid; 521191273Srwatson break; 522191273Srwatson case FIONBIO: 523191273Srwatson break; 524191273Srwatson case FIOASYNC: 525191273Srwatson if (*(int *)data) 526191273Srwatson tp->tun_flags |= TUN_ASYNC; 527191273Srwatson else 528191273Srwatson tp->tun_flags &= ~TUN_ASYNC; 529191273Srwatson break; 530191273Srwatson case FIONREAD: 531191273Srwatson s = splimp(); 532191273Srwatson if (tp->tun_if.if_snd.ifq_head) { 533191273Srwatson struct mbuf *mb = tp->tun_if.if_snd.ifq_head; 534191273Srwatson for( *(int *)data = 0; mb != 0; mb = mb->m_next) 535191273Srwatson *(int *)data += mb->m_len; 536191273Srwatson } else 537191273Srwatson *(int *)data = 0; 538191273Srwatson splx(s); 539191273Srwatson break; 540191273Srwatson case FIOSETOWN: 541191273Srwatson return (fsetown(*(int *)data, &tp->tun_sigio)); 542191273Srwatson 543191273Srwatson case FIOGETOWN: 544191273Srwatson *(int *)data = fgetown(tp->tun_sigio); 545191273Srwatson return (0); 546191273Srwatson 547191273Srwatson /* This is deprecated, FIOSETOWN should be used instead. */ 548191273Srwatson case TIOCSPGRP: 549191273Srwatson return (fsetown(-(*(int *)data), &tp->tun_sigio)); 550191273Srwatson 551191273Srwatson /* This is deprecated, FIOGETOWN should be used instead. */ 552191273Srwatson case TIOCGPGRP: 553191273Srwatson *(int *)data = -fgetown(tp->tun_sigio); 554191273Srwatson return (0); 555191273Srwatson 556191273Srwatson default: 557191273Srwatson return (ENOTTY); 558191273Srwatson } 559191273Srwatson return (0); 560191273Srwatson} 561191273Srwatson 562191273Srwatson/* 563191273Srwatson * The cdevsw read interface - reads a packet at a time, or at 564191273Srwatson * least as much of a packet as can be read. 565191273Srwatson */ 566191273Srwatsonstatic int 567191273Srwatsontunread(dev, uio, flag) 568191273Srwatson dev_t dev; 569191273Srwatson struct uio *uio; 570191273Srwatson int flag; 571191273Srwatson{ 572191273Srwatson struct tun_softc *tp = dev->si_drv1; 573191273Srwatson struct ifnet *ifp = &tp->tun_if; 574191273Srwatson struct mbuf *m, *m0; 575191273Srwatson int error=0, len, s; 576191273Srwatson 577191273Srwatson TUNDEBUG ("%s%d: read\n", ifp->if_name, ifp->if_unit); 578191273Srwatson if ((tp->tun_flags & TUN_READY) != TUN_READY) { 579191273Srwatson TUNDEBUG ("%s%d: not ready 0%o\n", ifp->if_name, 580191273Srwatson ifp->if_unit, tp->tun_flags); 581191273Srwatson return EHOSTDOWN; 582191273Srwatson } 583191273Srwatson 584191273Srwatson tp->tun_flags &= ~TUN_RWAIT; 585191273Srwatson 586191273Srwatson s = splimp(); 587191273Srwatson do { 588191273Srwatson IF_DEQUEUE(&ifp->if_snd, m0); 589191273Srwatson if (m0 == 0) { 590191273Srwatson if (flag & IO_NDELAY) { 591191273Srwatson splx(s); 592191273Srwatson return EWOULDBLOCK; 593191273Srwatson } 594191273Srwatson tp->tun_flags |= TUN_RWAIT; 595191273Srwatson if((error = tsleep((caddr_t)tp, PCATCH | (PZERO + 1), 596191273Srwatson "tunread", 0)) != 0) { 597191273Srwatson splx(s); 598191273Srwatson return error; 599191273Srwatson } 600191273Srwatson } 601191273Srwatson } while (m0 == 0); 602191273Srwatson splx(s); 603191273Srwatson 604191273Srwatson while (m0 && uio->uio_resid > 0 && error == 0) { 605191273Srwatson len = min(uio->uio_resid, m0->m_len); 606191273Srwatson if (len == 0) 607191273Srwatson break; 608191273Srwatson error = uiomove(mtod(m0, caddr_t), len, uio); 609191273Srwatson MFREE(m0, m); 610191273Srwatson m0 = m; 611191273Srwatson } 612191273Srwatson 613191273Srwatson if (m0) { 614191273Srwatson TUNDEBUG("Dropping mbuf\n"); 615191273Srwatson m_freem(m0); 616191273Srwatson } 617191273Srwatson return error; 618191273Srwatson} 619191273Srwatson 620191273Srwatson/* 621191273Srwatson * the cdevsw write interface - an atomic write is a packet - or else! 622191273Srwatson */ 623191273Srwatsonstatic int 624191273Srwatsontunwrite(dev, uio, flag) 625191273Srwatson dev_t dev; 626191273Srwatson struct uio *uio; 627191273Srwatson int flag; 628191273Srwatson{ 629191273Srwatson struct tun_softc *tp = dev->si_drv1; 630191273Srwatson struct ifnet *ifp = &tp->tun_if; 631191273Srwatson struct mbuf *top, **mp, *m; 632191273Srwatson int error=0, tlen, mlen; 633191273Srwatson u_int32_t family; 634191273Srwatson 635191273Srwatson TUNDEBUG("%s%d: tunwrite\n", ifp->if_name, ifp->if_unit); 636191273Srwatson 637191273Srwatson if (uio->uio_resid == 0) 638191273Srwatson return 0; 639191273Srwatson 640191273Srwatson if (uio->uio_resid < 0 || uio->uio_resid > TUNMRU) { 641191273Srwatson TUNDEBUG("%s%d: len=%d!\n", ifp->if_name, ifp->if_unit, 642191273Srwatson uio->uio_resid); 643191273Srwatson return EIO; 644191273Srwatson } 645191273Srwatson tlen = uio->uio_resid; 646191273Srwatson 647191273Srwatson /* get a header mbuf */ 648191273Srwatson MGETHDR(m, M_DONTWAIT, MT_DATA); 649191273Srwatson if (m == NULL) 650191273Srwatson return ENOBUFS; 651191273Srwatson mlen = MHLEN; 652191273Srwatson 653191273Srwatson top = 0; 654191273Srwatson mp = ⊤ 655191273Srwatson while (error == 0 && uio->uio_resid > 0) { 656191273Srwatson m->m_len = min(mlen, uio->uio_resid); 657191273Srwatson error = uiomove(mtod (m, caddr_t), m->m_len, uio); 658191273Srwatson *mp = m; 659191273Srwatson mp = &m->m_next; 660191273Srwatson if (uio->uio_resid > 0) { 661191273Srwatson MGET (m, M_DONTWAIT, MT_DATA); 662191273Srwatson if (m == 0) { 663191273Srwatson error = ENOBUFS; 664191273Srwatson break; 665191273Srwatson } 666191273Srwatson mlen = MLEN; 667191273Srwatson } 668191273Srwatson } 669191273Srwatson if (error) { 670191273Srwatson if (top) 671191273Srwatson m_freem (top); 672191273Srwatson ifp->if_ierrors++; 673191273Srwatson return error; 674191273Srwatson } 675191273Srwatson 676191273Srwatson top->m_pkthdr.len = tlen; 677191273Srwatson top->m_pkthdr.rcvif = ifp; 678191273Srwatson 679191273Srwatson if (ifp->if_bpf) { 680191273Srwatson if (tp->tun_flags & TUN_IFHEAD) 681191273Srwatson /* 682191273Srwatson * Conveniently, we already have a 4-byte address 683191273Srwatson * family prepended to our packet ! 684191273Srwatson */ 685191273Srwatson bpf_mtap(ifp, top); 686191273Srwatson else { 687191273Srwatson /* 688191273Srwatson * We need to prepend the address family as 689191273Srwatson * a four byte field. Cons up a dummy header 690191273Srwatson * to pacify bpf. This is safe because bpf 691191273Srwatson * will only read from the mbuf (i.e., it won't 692191273Srwatson * try to free it or keep a pointer to it). 693191273Srwatson */ 694191273Srwatson struct mbuf m; 695191273Srwatson u_int af = AF_INET; 696191273Srwatson 697191273Srwatson m.m_next = top; 698191273Srwatson m.m_len = 4; 699191273Srwatson m.m_data = (char *)⁡ 700191273Srwatson 701191273Srwatson bpf_mtap(ifp, &m); 702191273Srwatson } 703191273Srwatson } 704191273Srwatson 705191273Srwatson if (tp->tun_flags & TUN_IFHEAD) { 706191273Srwatson if (top->m_len < sizeof(family) && 707191273Srwatson (top = m_pullup(top, sizeof(family))) == NULL) 708191273Srwatson return ENOBUFS; 709191273Srwatson family = ntohl(*mtod(top, u_int32_t *)); 710191273Srwatson m_adj(top, sizeof(family)); 711191273Srwatson } else 712191273Srwatson family = AF_INET; 713191273Srwatson 714191273Srwatson ifp->if_ibytes += top->m_pkthdr.len; 715191273Srwatson ifp->if_ipackets++; 716191273Srwatson 717191273Srwatson return family_enqueue(family, top); 718191273Srwatson} 719191273Srwatson 720191273Srwatson/* 721191273Srwatson * tunpoll - the poll interface, this is only useful on reads 722191273Srwatson * really. The write detect always returns true, write never blocks 723191273Srwatson * anyway, it either accepts the packet or drops it. 724191273Srwatson */ 725191273Srwatsonstatic int 726191273Srwatsontunpoll(dev, events, p) 727191273Srwatson dev_t dev; 728191273Srwatson int events; 729191273Srwatson struct proc *p; 730191273Srwatson{ 731191273Srwatson int s; 732191273Srwatson struct tun_softc *tp = dev->si_drv1; 733191273Srwatson struct ifnet *ifp = &tp->tun_if; 734191273Srwatson int revents = 0; 735191273Srwatson 736191273Srwatson s = splimp(); 737191273Srwatson TUNDEBUG("%s%d: tunpoll\n", ifp->if_name, ifp->if_unit); 738191273Srwatson 739191273Srwatson if (events & (POLLIN | POLLRDNORM)) { 740191273Srwatson if (ifp->if_snd.ifq_len > 0) { 741191273Srwatson TUNDEBUG("%s%d: tunpoll q=%d\n", ifp->if_name, 742191273Srwatson ifp->if_unit, ifp->if_snd.ifq_len); 743191273Srwatson revents |= events & (POLLIN | POLLRDNORM); 744191273Srwatson } else { 745191273Srwatson TUNDEBUG("%s%d: tunpoll waiting\n", ifp->if_name, 746191273Srwatson ifp->if_unit); 747191273Srwatson selrecord(p, &tp->tun_rsel); 748191273Srwatson } 749191273Srwatson } 750191273Srwatson if (events & (POLLOUT | POLLWRNORM)) 751191273Srwatson revents |= events & (POLLOUT | POLLWRNORM); 752191273Srwatson 753191273Srwatson splx(s); 754191273Srwatson return (revents); 755191273Srwatson} 756191273Srwatson