|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights ! 7: * Reserved. This file contains Original Code and/or Modifications of ! 8: * Original Code as defined in and that are subject to the Apple Public ! 9: * Source License Version 1.1 (the "License"). You may not use this file ! 10: * except in compliance with the License. Please obtain a copy of the ! 11: * License at http://www.apple.com/publicsource and read it before using ! 12: * this file. ! 13: * ! 14: * The Original Code and all software distributed under the License are ! 15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 19: * License for the specific language governing rights and limitations ! 20: * under the License. ! 21: * ! 22: * @APPLE_LICENSE_HEADER_END@ ! 23: */ ! 24: ! 25: /* Copyright (c) 1997 Apple Computer, Inc. All Rights Reserved */ ! 26: /* ! 27: * Copyright (c) 1988, Julian Onions <[email protected]> ! 28: * Nottingham University 1987. ! 29: * ! 30: * This source may be freely distributed, however I would be interested ! 31: * in any changes that are made. ! 32: * ! 33: * This driver takes packets off the IP i/f and hands them up to a ! 34: * user process to have it's wicked way with. This driver has it's ! 35: * roots in a similar driver written by Phil Cockcroft (formerly) at ! 36: * UCL. This driver is based much more on read/write/select mode of ! 37: * operation though. ! 38: * ! 39: */ ! 40: ! 41: #include "tun.h" ! 42: #if NTUN > 0 ! 43: ! 44: #include <sys/param.h> ! 45: #include <sys/proc.h> ! 46: #include <sys/systm.h> ! 47: #include <sys/mbuf.h> ! 48: #include <sys/buf.h> ! 49: #include <sys/protosw.h> ! 50: #include <sys/socket.h> ! 51: #include <sys/ioctl.h> ! 52: #include <sys/errno.h> ! 53: #include <sys/syslog.h> ! 54: #include <sys/select.h> ! 55: #include <sys/file.h> ! 56: ! 57: #include <machine/cpu.h> ! 58: ! 59: #include <net/if.h> ! 60: #include <net/netisr.h> ! 61: #include <net/route.h> ! 62: ! 63: #if INET ! 64: #include <netinet/in.h> ! 65: #include <netinet/in_systm.h> ! 66: #include <netinet/in_var.h> ! 67: #include <netinet/ip.h> ! 68: #include <netinet/if_ether.h> ! 69: #endif ! 70: ! 71: #if NS ! 72: #include <netns/ns.h> ! 73: #include <netns/ns_if.h> ! 74: #endif ! 75: ! 76: #include "bpfilter.h" ! 77: #if NBPFILTER > 0 ! 78: #include <sys/time.h> ! 79: #include <net/bpf.h> ! 80: #endif ! 81: ! 82: #include <net/if_tun.h> ! 83: ! 84: #define TUNDEBUG if (tundebug) printf ! 85: int tundebug = 0; ! 86: ! 87: struct tun_softc tunctl[NTUN]; ! 88: extern int ifqmaxlen; ! 89: ! 90: int tunopen __P((dev_t, int, int, struct proc *)); ! 91: int tunclose __P((dev_t, int)); ! 92: int tunoutput __P((struct ifnet *, struct mbuf *, struct sockaddr *, ! 93: struct rtentry *rt)); ! 94: int tunread __P((dev_t, struct uio *)); ! 95: int tunwrite __P((dev_t, struct uio *)); ! 96: int tuncioctl __P((dev_t, u_long, caddr_t, int, struct proc *)); ! 97: int tunioctl __P((struct ifnet *, u_long, caddr_t)); ! 98: int tunselect __P((dev_t, int)); ! 99: void tunattach __P((int)); ! 100: ! 101: static int tuninit __P((int)); ! 102: ! 103: void ! 104: tunattach(unused) ! 105: int unused; ! 106: { ! 107: register int i; ! 108: struct ifnet *ifp; ! 109: struct sockaddr_in *sin; ! 110: ! 111: for (i = 0; i < NTUN; i++) { ! 112: tunctl[i].tun_flags = TUN_INITED; ! 113: ! 114: ifp = &tunctl[i].tun_if; ! 115: ifp->if_unit = i; ! 116: ifp->if_name = "tun"; ! 117: ifp->if_mtu = TUNMTU; ! 118: ifp->if_ioctl = tunioctl; ! 119: ifp->if_output = tunoutput; ! 120: ifp->if_flags = IFF_POINTOPOINT; ! 121: ifp->if_snd.ifq_maxlen = ifqmaxlen; ! 122: ifp->if_collisions = 0; ! 123: ifp->if_ierrors = 0; ! 124: ifp->if_oerrors = 0; ! 125: ifp->if_ipackets = 0; ! 126: ifp->if_opackets = 0; ! 127: if_attach(ifp); ! 128: #if NBPFILTER > 0 ! 129: bpfattach(&tunctl[i].tun_bpf, ifp, DLT_NULL, sizeof(u_int32_t)); ! 130: #endif ! 131: } ! 132: } ! 133: ! 134: /* ! 135: * tunnel open - must be superuser & the device must be ! 136: * configured in ! 137: */ ! 138: int ! 139: tunopen(dev, flag, mode, p) ! 140: dev_t dev; ! 141: int flag, mode; ! 142: struct proc *p; ! 143: { ! 144: struct ifnet *ifp; ! 145: struct tun_softc *tp; ! 146: register int unit, error; ! 147: ! 148: if (error = suser(p->p_ucred, &p->p_acflag)) ! 149: return (error); ! 150: ! 151: if ((unit = minor(dev)) >= NTUN) ! 152: return (ENXIO); ! 153: tp = &tunctl[unit]; ! 154: if (tp->tun_flags & TUN_OPEN) ! 155: return ENXIO; ! 156: ifp = &tp->tun_if; ! 157: tp->tun_flags |= TUN_OPEN; ! 158: TUNDEBUG("%s%d: open\n", ifp->if_name, ifp->if_unit); ! 159: return (0); ! 160: } ! 161: ! 162: /* ! 163: * tunclose - close the device - mark i/f down & delete ! 164: * routing info ! 165: */ ! 166: int ! 167: tunclose(dev, flag) ! 168: dev_t dev; ! 169: int flag; ! 170: { ! 171: register int unit = minor(dev), s; ! 172: struct tun_softc *tp = &tunctl[unit]; ! 173: struct ifnet *ifp = &tp->tun_if; ! 174: struct mbuf *m; ! 175: ! 176: tp->tun_flags &= ~TUN_OPEN; ! 177: ! 178: /* ! 179: * junk all pending output ! 180: */ ! 181: do { ! 182: s = splimp(); ! 183: IF_DEQUEUE(&ifp->if_snd, m); ! 184: splx(s); ! 185: if (m) ! 186: m_freem(m); ! 187: } while (m); ! 188: ! 189: if (ifp->if_flags & IFF_UP) { ! 190: s = splimp(); ! 191: if_down(ifp); ! 192: if (ifp->if_flags & IFF_RUNNING) { ! 193: /* find internet addresses and delete routes */ ! 194: register struct ifaddr *ifa; ! 195: for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { ! 196: if (ifa->ifa_addr->sa_family == AF_INET) { ! 197: rtinit(ifa, (int)RTM_DELETE, ! 198: tp->tun_flags & TUN_DSTADDR ? RTF_HOST : 0); ! 199: } ! 200: } ! 201: } ! 202: splx(s); ! 203: } ! 204: tp->tun_pgrp = 0; ! 205: selwakeup(&tp->tun_rsel); ! 206: ! 207: TUNDEBUG ("%s%d: closed\n", ifp->if_name, ifp->if_unit); ! 208: return (0); ! 209: } ! 210: ! 211: static int ! 212: tuninit(unit) ! 213: int unit; ! 214: { ! 215: struct tun_softc *tp = &tunctl[unit]; ! 216: struct ifnet *ifp = &tp->tun_if; ! 217: register struct ifaddr *ifa; ! 218: ! 219: TUNDEBUG("%s%d: tuninit\n", ifp->if_name, ifp->if_unit); ! 220: ! 221: ifp->if_flags |= IFF_UP | IFF_RUNNING; ! 222: ! 223: for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) ! 224: if (ifa->ifa_addr->sa_family == AF_INET) { ! 225: struct sockaddr_in *si; ! 226: ! 227: si = (struct sockaddr_in *)ifa->ifa_addr; ! 228: if (si && si->sin_addr.s_addr) ! 229: tp->tun_flags |= TUN_IASET; ! 230: ! 231: si = (struct sockaddr_in *)ifa->ifa_dstaddr; ! 232: if (si && si->sin_addr.s_addr) ! 233: tp->tun_flags |= TUN_DSTADDR; ! 234: } ! 235: ! 236: return 0; ! 237: } ! 238: ! 239: /* ! 240: * Process an ioctl request. ! 241: */ ! 242: int ! 243: tunioctl(ifp, cmd, data) ! 244: struct ifnet *ifp; ! 245: u_long cmd; ! 246: caddr_t data; ! 247: { ! 248: struct tun_softc *tp = &tunctl[ifp->if_unit]; ! 249: int error = 0, s; ! 250: ! 251: s = splimp(); ! 252: switch(cmd) { ! 253: case SIOCSIFADDR: ! 254: tuninit(ifp->if_unit); ! 255: TUNDEBUG("%s%d: address set\n", ! 256: ifp->if_name, ifp->if_unit); ! 257: break; ! 258: case SIOCSIFDSTADDR: ! 259: tuninit(ifp->if_unit); ! 260: TUNDEBUG("%s%d: destination address set\n", ! 261: ifp->if_name, ifp->if_unit); ! 262: break; ! 263: default: ! 264: error = EINVAL; ! 265: } ! 266: splx(s); ! 267: return (error); ! 268: } ! 269: ! 270: /* ! 271: * tunoutput - queue packets from higher level ready to put out. ! 272: */ ! 273: int ! 274: tunoutput(ifp, m0, dst, rt) ! 275: struct ifnet *ifp; ! 276: struct mbuf *m0; ! 277: struct sockaddr *dst; ! 278: struct rtentry *rt; ! 279: { ! 280: struct tun_softc *tp = &tunctl[ifp->if_unit]; ! 281: struct proc *p; ! 282: int s; ! 283: ! 284: TUNDEBUG ("%s%d: tunoutput\n", ifp->if_name, ifp->if_unit); ! 285: ! 286: if ((tp->tun_flags & TUN_READY) != TUN_READY) { ! 287: TUNDEBUG ("%s%d: not ready 0%o\n", ifp->if_name, ! 288: ifp->if_unit, tp->tun_flags); ! 289: m_freem (m0); ! 290: return EHOSTDOWN; ! 291: } ! 292: ! 293: #if NBPFILTER > 0 ! 294: if (tp->tun_bpf) { ! 295: /* ! 296: * We need to prepend the address family as ! 297: * a four byte field. Cons up a dummy header ! 298: * to pacify bpf. This is safe because bpf ! 299: * will only read from the mbuf (i.e., it won't ! 300: * try to free it or keep a pointer to it). ! 301: */ ! 302: struct mbuf m; ! 303: u_int32_t af = dst->sa_family; ! 304: ! 305: m.m_next = m0; ! 306: m.m_len = sizeof(af); ! 307: m.m_data = (char *)⁡ ! 308: ! 309: BPF_MTAP(tp->tun_bpf, &m); ! 310: } ! 311: #endif ! 312: ! 313: switch(dst->sa_family) { ! 314: #if INET ! 315: case AF_INET: ! 316: s = splimp(); ! 317: if (IF_QFULL(&ifp->if_snd)) { ! 318: IF_DROP(&ifp->if_snd); ! 319: m_freem(m0); ! 320: splx(s); ! 321: ifp->if_collisions++; ! 322: return (ENOBUFS); ! 323: } ! 324: IF_ENQUEUE(&ifp->if_snd, m0); ! 325: splx(s); ! 326: ifp->if_opackets++; ! 327: break; ! 328: #endif ! 329: default: ! 330: m_freem(m0); ! 331: return EAFNOSUPPORT; ! 332: } ! 333: ! 334: if (tp->tun_flags & TUN_RWAIT) { ! 335: tp->tun_flags &= ~TUN_RWAIT; ! 336: wakeup((caddr_t)tp); ! 337: } ! 338: if (tp->tun_flags & TUN_ASYNC && tp->tun_pgrp) { ! 339: if (tp->tun_pgrp > 0) ! 340: gsignal(tp->tun_pgrp, SIGIO); ! 341: else if (p = pfind(-tp->tun_pgrp)) ! 342: psignal(p, SIGIO); ! 343: } ! 344: selwakeup(&tp->tun_rsel); ! 345: return 0; ! 346: } ! 347: ! 348: /* ! 349: * the cdevsw interface is now pretty minimal. ! 350: */ ! 351: int ! 352: tuncioctl(dev, cmd, data, flag, p) ! 353: dev_t dev; ! 354: u_long cmd; ! 355: caddr_t data; ! 356: int flag; ! 357: struct proc *p; ! 358: { ! 359: int unit = minor(dev), s; ! 360: struct tun_softc *tp = &tunctl[unit]; ! 361: ! 362: switch (cmd) { ! 363: case TUNSDEBUG: ! 364: tundebug = *(int *)data; ! 365: break; ! 366: case TUNGDEBUG: ! 367: *(int *)data = tundebug; ! 368: break; ! 369: case FIONBIO: ! 370: if (*(int *)data) ! 371: tp->tun_flags |= TUN_NBIO; ! 372: else ! 373: tp->tun_flags &= ~TUN_NBIO; ! 374: break; ! 375: case FIOASYNC: ! 376: if (*(int *)data) ! 377: tp->tun_flags |= TUN_ASYNC; ! 378: else ! 379: tp->tun_flags &= ~TUN_ASYNC; ! 380: break; ! 381: case FIONREAD: ! 382: s = splimp(); ! 383: if (tp->tun_if.if_snd.ifq_head) ! 384: *(int *)data = tp->tun_if.if_snd.ifq_head->m_len; ! 385: else ! 386: *(int *)data = 0; ! 387: splx(s); ! 388: break; ! 389: case TIOCSPGRP: ! 390: tp->tun_pgrp = *(int *)data; ! 391: break; ! 392: case TIOCGPGRP: ! 393: *(int *)data = tp->tun_pgrp; ! 394: break; ! 395: default: ! 396: return (ENOTTY); ! 397: } ! 398: return (0); ! 399: } ! 400: ! 401: /* ! 402: * The cdevsw read interface - reads a packet at a time, or at ! 403: * least as much of a packet as can be read. ! 404: */ ! 405: int ! 406: tunread(dev, uio) ! 407: dev_t dev; ! 408: struct uio *uio; ! 409: { ! 410: int unit = minor(dev); ! 411: struct tun_softc *tp = &tunctl[unit]; ! 412: struct ifnet *ifp = &tp->tun_if; ! 413: struct mbuf *m, *m0; ! 414: int error=0, len, s; ! 415: ! 416: TUNDEBUG ("%s%d: read\n", ifp->if_name, ifp->if_unit); ! 417: if ((tp->tun_flags & TUN_READY) != TUN_READY) { ! 418: TUNDEBUG ("%s%d: not ready 0%o\n", ifp->if_name, ! 419: ifp->if_unit, tp->tun_flags); ! 420: return EHOSTDOWN; ! 421: } ! 422: ! 423: tp->tun_flags &= ~TUN_RWAIT; ! 424: ! 425: s = splimp(); ! 426: do { ! 427: IF_DEQUEUE(&ifp->if_snd, m0); ! 428: if (m0 == 0) { ! 429: if (tp->tun_flags & TUN_NBIO) { ! 430: splx(s); ! 431: return EWOULDBLOCK; ! 432: } ! 433: tp->tun_flags |= TUN_RWAIT; ! 434: tsleep((caddr_t)tp, PZERO + 1, "tunread", 0); ! 435: } ! 436: } while (m0 == 0); ! 437: splx(s); ! 438: ! 439: while (m0 && uio->uio_resid > 0 && error == 0) { ! 440: len = min(uio->uio_resid, m0->m_len); ! 441: if (len == 0) ! 442: break; ! 443: error = uiomove(mtod(m0, caddr_t), len, uio); ! 444: MFREE(m0, m); ! 445: m0 = m; ! 446: } ! 447: ! 448: if (m0) { ! 449: TUNDEBUG("Dropping mbuf\n"); ! 450: m_freem(m0); ! 451: } ! 452: return error; ! 453: } ! 454: ! 455: /* ! 456: * the cdevsw write interface - an atomic write is a packet - or else! ! 457: */ ! 458: int ! 459: tunwrite(dev, uio) ! 460: dev_t dev; ! 461: struct uio *uio; ! 462: { ! 463: int unit = minor (dev); ! 464: struct ifnet *ifp = &tunctl[unit].tun_if; ! 465: struct mbuf *top, **mp, *m; ! 466: int error=0, s, tlen, mlen; ! 467: ! 468: TUNDEBUG("%s%d: tunwrite\n", ifp->if_name, ifp->if_unit); ! 469: ! 470: if (uio->uio_resid < 0 || uio->uio_resid > TUNMTU) { ! 471: TUNDEBUG("%s%d: len=%d!\n", ifp->if_name, ifp->if_unit, ! 472: uio->uio_resid); ! 473: return EIO; ! 474: } ! 475: tlen = uio->uio_resid; ! 476: ! 477: /* get a header mbuf */ ! 478: MGETHDR(m, M_DONTWAIT, MT_DATA); ! 479: if (m == NULL) ! 480: return ENOBUFS; ! 481: mlen = MHLEN; ! 482: ! 483: top = 0; ! 484: mp = ⊤ ! 485: while (error == 0 && uio->uio_resid > 0) { ! 486: m->m_len = min(mlen, uio->uio_resid); ! 487: error = uiomove(mtod (m, caddr_t), m->m_len, uio); ! 488: *mp = m; ! 489: mp = &m->m_next; ! 490: if (uio->uio_resid > 0) { ! 491: MGET (m, M_DONTWAIT, MT_DATA); ! 492: if (m == 0) { ! 493: error = ENOBUFS; ! 494: break; ! 495: } ! 496: mlen = MLEN; ! 497: } ! 498: } ! 499: if (error) { ! 500: if (top) ! 501: m_freem (top); ! 502: return error; ! 503: } ! 504: ! 505: top->m_pkthdr.len = tlen; ! 506: top->m_pkthdr.rcvif = ifp; ! 507: ! 508: #if NBPFILTER > 0 ! 509: if (tunctl[unit].tun_bpf) { ! 510: /* ! 511: * We need to prepend the address family as ! 512: * a four byte field. Cons up a dummy header ! 513: * to pacify bpf. This is safe because bpf ! 514: * will only read from the mbuf (i.e., it won't ! 515: * try to free it or keep a pointer to it). ! 516: */ ! 517: struct mbuf m; ! 518: u_int32_t af = AF_INET; ! 519: ! 520: m.m_next = top; ! 521: m.m_len = sizeof(af); ! 522: m.m_data = (char *)⁡ ! 523: ! 524: BPF_MTAP(tunctl[unit].tun_bpf, &m); ! 525: } ! 526: #endif ! 527: ! 528: s = splimp(); ! 529: if (IF_QFULL (&ipintrq)) { ! 530: IF_DROP(&ipintrq); ! 531: splx(s); ! 532: ifp->if_collisions++; ! 533: m_freem(top); ! 534: return ENOBUFS; ! 535: } ! 536: IF_ENQUEUE(&ipintrq, top); ! 537: splx(s); ! 538: ifp->if_ipackets++; ! 539: schednetisr(NETISR_IP); ! 540: return error; ! 541: } ! 542: ! 543: /* ! 544: * tunselect - the select interface, this is only useful on reads ! 545: * really. The write detect always returns true, write never blocks ! 546: * anyway, it either accepts the packet or drops it. ! 547: */ ! 548: int ! 549: tunselect(dev, rw) ! 550: dev_t dev; ! 551: int rw; ! 552: { ! 553: int unit = minor(dev), s; ! 554: struct tun_softc *tp = &tunctl[unit]; ! 555: struct ifnet *ifp = &tp->tun_if; ! 556: ! 557: s = splimp(); ! 558: TUNDEBUG("%s%d: tunselect\n", ifp->if_name, ifp->if_unit); ! 559: ! 560: switch (rw) { ! 561: case FREAD: ! 562: if (ifp->if_snd.ifq_len > 0) { ! 563: splx(s); ! 564: TUNDEBUG("%s%d: tunselect q=%d\n", ifp->if_name, ! 565: ifp->if_unit, ifp->if_snd.ifq_len); ! 566: return 1; ! 567: } ! 568: selrecord(curproc, &tp->tun_rsel); ! 569: break; ! 570: case FWRITE: ! 571: splx(s); ! 572: return 1; ! 573: } ! 574: splx(s); ! 575: TUNDEBUG("%s%d: tunselect waiting\n", ifp->if_name, ifp->if_unit); ! 576: return 0; ! 577: } ! 578: ! 579: #endif /* NTUN */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.