if_tun.c revision 26566
1/* $NetBSD: if_tun.c,v 1.14 1994/06/29 06:36:25 cgd Exp $ */ 2 3/* 4 * Copyright (c) 1988, Julian Onions <jpo@cs.nott.ac.uk> 5 * Nottingham University 1987. 6 * 7 * This source may be freely distributed, however I would be interested 8 * in any changes that are made. 9 * 10 * This driver takes packets off the IP i/f and hands them up to a 11 * user process to have it's wicked way with. This driver has it's 12 * roots in a similar driver written by Phil Cockcroft (formerly) at 13 * UCL. This driver is based much more on read/write/select mode of 14 * operation though. 15 */ 16 17#include "tun.h" 18#if NTUN > 0 19 20#include <sys/param.h> 21#include <sys/proc.h> 22#include <sys/systm.h> 23#include <sys/mbuf.h> 24#include <sys/buf.h> 25#include <sys/protosw.h> 26#include <sys/socket.h> 27#include <sys/filio.h> 28#include <sys/sockio.h> 29#include <sys/ttycom.h> 30#include <sys/errno.h> 31#include <sys/syslog.h> 32#include <sys/select.h> 33#include <sys/fcntl.h> 34#include <sys/signalvar.h> 35#include <sys/kernel.h> 36#include <sys/sysctl.h> 37#ifdef DEVFS 38#include <sys/devfsext.h> 39#endif /*DEVFS*/ 40#include <sys/conf.h> 41 42#include <net/if.h> 43#include <net/netisr.h> 44#include <net/route.h> 45 46#ifdef INET 47#include <netinet/in.h> 48#include <netinet/in_systm.h> 49#include <netinet/in_var.h> 50#include <netinet/ip.h> 51#include <netinet/if_ether.h> 52#endif 53 54#ifdef NS 55#include <netns/ns.h> 56#include <netns/ns_if.h> 57#endif 58 59#include "bpfilter.h" 60#if NBPFILTER > 0 61#include <sys/time.h> 62#include <net/bpf.h> 63#endif 64 65#include <net/if_tun.h> 66 67static void tunattach __P((void *)); 68PSEUDO_SET(tunattach, if_tun); 69 70#define TUNDEBUG if (tundebug) printf 71static int tundebug = 0; 72SYSCTL_INT(_debug, OID_AUTO, if_tun_debug, CTLFLAG_RW, &tundebug, 0, ""); 73 74static struct tun_softc tunctl[NTUN]; 75 76static int tunoutput __P((struct ifnet *, struct mbuf *, struct sockaddr *, 77 struct rtentry *rt)); 78static int tunifioctl __P((struct ifnet *, int, caddr_t)); 79static int tuninit __P((int)); 80 81static d_open_t tunopen; 82static d_close_t tunclose; 83static d_read_t tunread; 84static d_write_t tunwrite; 85static d_ioctl_t tunioctl; 86static d_select_t tunselect; 87 88#define CDEV_MAJOR 52 89static struct cdevsw tun_cdevsw = { 90 tunopen, tunclose, tunread, tunwrite, 91 tunioctl, nullstop, noreset, nodevtotty, 92 tunselect, nommap, nostrategy, "tun", NULL, -1 93}; 94 95 96static tun_devsw_installed = 0; 97#ifdef DEVFS 98static void *tun_devfs_token[NTUN]; 99#endif 100 101static void 102tunattach(dummy) 103 void *dummy; 104{ 105 register int i; 106 struct ifnet *ifp; 107 dev_t dev; 108 109 if ( tun_devsw_installed ) 110 return; 111 dev = makedev(CDEV_MAJOR, 0); 112 cdevsw_add(&dev, &tun_cdevsw, NULL); 113 tun_devsw_installed = 1; 114 for ( i = 0; i < NTUN; i++ ) { 115#ifdef DEVFS 116 tun_devfs_token[i] = devfs_add_devswf(&tun_cdevsw, i, DV_CHR, 117 UID_UUCP, GID_DIALER, 118 0600, "tun%d", i); 119#endif 120 tunctl[i].tun_flags = TUN_INITED; 121 122 ifp = &tunctl[i].tun_if; 123 ifp->if_unit = i; 124 ifp->if_name = "tun"; 125 ifp->if_mtu = TUNMTU; 126 ifp->if_ioctl = tunifioctl; 127 ifp->if_output = tunoutput; 128 ifp->if_flags = IFF_POINTOPOINT | IFF_MULTICAST; 129 ifp->if_snd.ifq_maxlen = ifqmaxlen; 130 ifp->if_collisions = 0; 131 ifp->if_ierrors = 0; 132 ifp->if_oerrors = 0; 133 ifp->if_ipackets = 0; 134 ifp->if_opackets = 0; 135 if_attach(ifp); 136#if NBPFILTER > 0 137 bpfattach(ifp, DLT_NULL, sizeof(u_int)); 138#endif 139 } 140} 141 142/* 143 * tunnel open - must be superuser & the device must be 144 * configured in 145 */ 146static int 147tunopen(dev, flag, mode, p) 148 dev_t dev; 149 int flag, mode; 150 struct proc *p; 151{ 152 struct ifnet *ifp; 153 struct tun_softc *tp; 154 register int unit, error; 155 156 error = suser(p->p_ucred, &p->p_acflag); 157 if (error) 158 return (error); 159 160 if ((unit = minor(dev)) >= NTUN) 161 return (ENXIO); 162 tp = &tunctl[unit]; 163 if (tp->tun_flags & TUN_OPEN) 164 return EBUSY; 165 ifp = &tp->tun_if; 166 tp->tun_flags |= TUN_OPEN; 167 TUNDEBUG("%s%d: open\n", ifp->if_name, ifp->if_unit); 168 return (0); 169} 170 171/* 172 * tunclose - close the device - mark i/f down & delete 173 * routing info 174 */ 175static int 176tunclose(dev_t dev, int foo, int bar, struct proc *p) 177{ 178 register int unit = minor(dev), s; 179 struct tun_softc *tp = &tunctl[unit]; 180 struct ifnet *ifp = &tp->tun_if; 181 struct mbuf *m; 182 183 tp->tun_flags &= ~TUN_OPEN; 184 185 /* 186 * junk all pending output 187 */ 188 do { 189 s = splimp(); 190 IF_DEQUEUE(&ifp->if_snd, m); 191 splx(s); 192 if (m) 193 m_freem(m); 194 } while (m); 195 196 if (ifp->if_flags & IFF_UP) { 197 s = splimp(); 198 if_down(ifp); 199 if (ifp->if_flags & IFF_RUNNING) { 200 /* find internet addresses and delete routes */ 201 register struct ifaddr *ifa; 202 for (ifa = ifp->if_addrhead.tqh_first; ifa; 203 ifa = ifa->ifa_link.tqe_next) { 204 if (ifa->ifa_addr->sa_family == AF_INET) { 205 rtinit(ifa, (int)RTM_DELETE, 206 tp->tun_flags & TUN_DSTADDR ? RTF_HOST : 0); 207 } 208 } 209 } 210 splx(s); 211 } 212 tp->tun_pgrp = 0; 213 selwakeup(&tp->tun_rsel); 214 215 TUNDEBUG ("%s%d: closed\n", ifp->if_name, ifp->if_unit); 216 return (0); 217} 218 219static int 220tuninit(unit) 221 int unit; 222{ 223 struct tun_softc *tp = &tunctl[unit]; 224 struct ifnet *ifp = &tp->tun_if; 225 register struct ifaddr *ifa; 226 227 TUNDEBUG("%s%d: tuninit\n", ifp->if_name, ifp->if_unit); 228 229 ifp->if_flags |= IFF_UP | IFF_RUNNING; 230 microtime(&ifp->if_lastchange); 231 232 for (ifa = ifp->if_addrhead.tqh_first; ifa; 233 ifa = ifa->ifa_link.tqe_next) 234 if (ifa->ifa_addr->sa_family == AF_INET) { 235 struct sockaddr_in *si; 236 237 si = (struct sockaddr_in *)ifa->ifa_addr; 238 if (si && si->sin_addr.s_addr) 239 tp->tun_flags |= TUN_IASET; 240 241 si = (struct sockaddr_in *)ifa->ifa_dstaddr; 242 if (si && si->sin_addr.s_addr) 243 tp->tun_flags |= TUN_DSTADDR; 244 } 245 246 return 0; 247} 248 249/* 250 * Process an ioctl request. 251 */ 252int 253tunifioctl(ifp, cmd, data) 254 struct ifnet *ifp; 255 int cmd; 256 caddr_t data; 257{ 258 register struct ifreq *ifr = (struct ifreq *)data; 259 int error = 0, s; 260 261 s = splimp(); 262 switch(cmd) { 263 case SIOCSIFADDR: 264 tuninit(ifp->if_unit); 265 TUNDEBUG("%s%d: address set\n", 266 ifp->if_name, ifp->if_unit); 267 break; 268 case SIOCSIFDSTADDR: 269 tuninit(ifp->if_unit); 270 TUNDEBUG("%s%d: destination address set\n", 271 ifp->if_name, ifp->if_unit); 272 break; 273 case SIOCSIFMTU: 274 ifp->if_mtu = ifr->ifr_mtu; 275 TUNDEBUG("%s%d: mtu set\n", 276 ifp->if_name, ifp->if_unit); 277 break; 278 case SIOCADDMULTI: 279 case SIOCDELMULTI: 280 break; 281 282 283 default: 284 error = EINVAL; 285 } 286 splx(s); 287 return (error); 288} 289 290/* 291 * tunoutput - queue packets from higher level ready to put out. 292 */ 293int 294tunoutput(ifp, m0, dst, rt) 295 struct ifnet *ifp; 296 struct mbuf *m0; 297 struct sockaddr *dst; 298 struct rtentry *rt; 299{ 300 struct tun_softc *tp = &tunctl[ifp->if_unit]; 301 struct proc *p; 302 int s; 303 304 TUNDEBUG ("%s%d: tunoutput\n", ifp->if_name, ifp->if_unit); 305 306 if ((tp->tun_flags & TUN_READY) != TUN_READY) { 307 TUNDEBUG ("%s%d: not ready 0%o\n", ifp->if_name, 308 ifp->if_unit, tp->tun_flags); 309 m_freem (m0); 310 return EHOSTDOWN; 311 } 312 313#if NBPFILTER > 0 314 /* BPF write needs to be handled specially */ 315 if (dst->sa_family == AF_UNSPEC) { 316 dst->sa_family = *(mtod(m0, int *)); 317 m0->m_len -= sizeof(int); 318 m0->m_pkthdr.len -= sizeof(int); 319 m0->m_data += sizeof(int); 320 } 321 322 if (ifp->if_bpf) { 323 /* 324 * We need to prepend the address family as 325 * a four byte field. Cons up a dummy header 326 * to pacify bpf. This is safe because bpf 327 * will only read from the mbuf (i.e., it won't 328 * try to free it or keep a pointer to it). 329 */ 330 struct mbuf m; 331 u_int af = dst->sa_family; 332 333 m.m_next = m0; 334 m.m_len = 4; 335 m.m_data = (char *)⁡ 336 337 bpf_mtap(ifp, &m); 338 } 339#endif 340 341 switch(dst->sa_family) { 342#ifdef INET 343 case AF_INET: 344 s = splimp(); 345 if (IF_QFULL(&ifp->if_snd)) { 346 IF_DROP(&ifp->if_snd); 347 m_freem(m0); 348 splx(s); 349 ifp->if_collisions++; 350 return (ENOBUFS); 351 } 352 ifp->if_obytes += m0->m_pkthdr.len; 353 IF_ENQUEUE(&ifp->if_snd, m0); 354 splx(s); 355 ifp->if_opackets++; 356 break; 357#endif 358 default: 359 m_freem(m0); 360 return EAFNOSUPPORT; 361 } 362 363 if (tp->tun_flags & TUN_RWAIT) { 364 tp->tun_flags &= ~TUN_RWAIT; 365 wakeup((caddr_t)tp); 366 } 367 if (tp->tun_flags & TUN_ASYNC && tp->tun_pgrp) { 368 if (tp->tun_pgrp > 0) 369 gsignal(tp->tun_pgrp, SIGIO); 370 else if ((p = pfind(-tp->tun_pgrp)) != 0) 371 psignal(p, SIGIO); 372 } 373 selwakeup(&tp->tun_rsel); 374 return 0; 375} 376 377/* 378 * the cdevsw interface is now pretty minimal. 379 */ 380static int 381tunioctl(dev, cmd, data, flag, p) 382 dev_t dev; 383 int cmd; 384 caddr_t data; 385 int flag; 386 struct proc *p; 387{ 388 int unit = minor(dev), s; 389 struct tun_softc *tp = &tunctl[unit]; 390 struct tuninfo *tunp; 391 392 switch (cmd) { 393 case TUNSIFINFO: 394 tunp = (struct tuninfo *)data; 395 tp->tun_if.if_mtu = tunp->mtu; 396 tp->tun_if.if_type = tunp->type; 397 tp->tun_if.if_baudrate = tunp->baudrate; 398 break; 399 case TUNGIFINFO: 400 tunp = (struct tuninfo *)data; 401 tunp->mtu = tp->tun_if.if_mtu; 402 tunp->type = tp->tun_if.if_type; 403 tunp->baudrate = tp->tun_if.if_baudrate; 404 break; 405 case TUNSDEBUG: 406 tundebug = *(int *)data; 407 break; 408 case TUNGDEBUG: 409 *(int *)data = tundebug; 410 break; 411 case FIONBIO: 412 if (*(int *)data) 413 tp->tun_flags |= TUN_NBIO; 414 else 415 tp->tun_flags &= ~TUN_NBIO; 416 break; 417 case FIOASYNC: 418 if (*(int *)data) 419 tp->tun_flags |= TUN_ASYNC; 420 else 421 tp->tun_flags &= ~TUN_ASYNC; 422 break; 423 case FIONREAD: 424 s = splimp(); 425 if (tp->tun_if.if_snd.ifq_head) { 426 struct mbuf *mb = tp->tun_if.if_snd.ifq_head; 427 for( *(int *)data = 0; mb != 0; mb = mb->m_next) 428 *(int *)data += mb->m_len; 429 } else 430 *(int *)data = 0; 431 splx(s); 432 break; 433 case TIOCSPGRP: 434 tp->tun_pgrp = *(int *)data; 435 break; 436 case TIOCGPGRP: 437 *(int *)data = tp->tun_pgrp; 438 break; 439 default: 440 return (ENOTTY); 441 } 442 return (0); 443} 444 445/* 446 * The cdevsw read interface - reads a packet at a time, or at 447 * least as much of a packet as can be read. 448 */ 449static int 450tunread(dev_t dev, struct uio *uio, int flag) 451{ 452 int unit = minor(dev); 453 struct tun_softc *tp = &tunctl[unit]; 454 struct ifnet *ifp = &tp->tun_if; 455 struct mbuf *m, *m0; 456 int error=0, len, s; 457 458 TUNDEBUG ("%s%d: read\n", ifp->if_name, ifp->if_unit); 459 if ((tp->tun_flags & TUN_READY) != TUN_READY) { 460 TUNDEBUG ("%s%d: not ready 0%o\n", ifp->if_name, 461 ifp->if_unit, tp->tun_flags); 462 return EHOSTDOWN; 463 } 464 465 tp->tun_flags &= ~TUN_RWAIT; 466 467 s = splimp(); 468 do { 469 IF_DEQUEUE(&ifp->if_snd, m0); 470 if (m0 == 0) { 471 if (tp->tun_flags & TUN_NBIO) { 472 splx(s); 473 return EWOULDBLOCK; 474 } 475 tp->tun_flags |= TUN_RWAIT; 476 if( error = tsleep((caddr_t)tp, PCATCH | (PZERO + 1), 477 "tunread", 0)) { 478 splx(s); 479 return error; 480 } 481 } 482 } while (m0 == 0); 483 splx(s); 484 485 while (m0 && uio->uio_resid > 0 && error == 0) { 486 len = min(uio->uio_resid, m0->m_len); 487 if (len == 0) 488 break; 489 error = uiomove(mtod(m0, caddr_t), len, uio); 490 MFREE(m0, m); 491 m0 = m; 492 } 493 494 if (m0) { 495 TUNDEBUG("Dropping mbuf\n"); 496 m_freem(m0); 497 } 498 return error; 499} 500 501/* 502 * the cdevsw write interface - an atomic write is a packet - or else! 503 */ 504static int 505tunwrite(dev_t dev, struct uio *uio, int flag) 506{ 507 int unit = minor (dev); 508 struct ifnet *ifp = &tunctl[unit].tun_if; 509 struct mbuf *top, **mp, *m; 510 int error=0, s, tlen, mlen; 511 512 TUNDEBUG("%s%d: tunwrite\n", ifp->if_name, ifp->if_unit); 513 514 if (uio->uio_resid < 0 || uio->uio_resid > TUNMRU) { 515 TUNDEBUG("%s%d: len=%d!\n", ifp->if_name, ifp->if_unit, 516 uio->uio_resid); 517 return EIO; 518 } 519 tlen = uio->uio_resid; 520 521 /* get a header mbuf */ 522 MGETHDR(m, M_DONTWAIT, MT_DATA); 523 if (m == NULL) 524 return ENOBUFS; 525 mlen = MHLEN; 526 527 top = 0; 528 mp = ⊤ 529 while (error == 0 && uio->uio_resid > 0) { 530 m->m_len = min(mlen, uio->uio_resid); 531 error = uiomove(mtod (m, caddr_t), m->m_len, uio); 532 *mp = m; 533 mp = &m->m_next; 534 if (uio->uio_resid > 0) { 535 MGET (m, M_DONTWAIT, MT_DATA); 536 if (m == 0) { 537 error = ENOBUFS; 538 break; 539 } 540 mlen = MLEN; 541 } 542 } 543 if (error) { 544 if (top) 545 m_freem (top); 546 return error; 547 } 548 549 top->m_pkthdr.len = tlen; 550 top->m_pkthdr.rcvif = ifp; 551 552#if NBPFILTER > 0 553 if (ifp->if_bpf) { 554 /* 555 * We need to prepend the address family as 556 * a four byte field. Cons up a dummy header 557 * to pacify bpf. This is safe because bpf 558 * will only read from the mbuf (i.e., it won't 559 * try to free it or keep a pointer to it). 560 */ 561 struct mbuf m; 562 u_int af = AF_INET; 563 564 m.m_next = top; 565 m.m_len = 4; 566 m.m_data = (char *)⁡ 567 568 bpf_mtap(ifp, &m); 569 } 570#endif 571 572 s = splimp(); 573 if (IF_QFULL (&ipintrq)) { 574 IF_DROP(&ipintrq); 575 splx(s); 576 ifp->if_collisions++; 577 m_freem(top); 578 return ENOBUFS; 579 } 580 IF_ENQUEUE(&ipintrq, top); 581 splx(s); 582 ifp->if_ibytes += tlen; 583 ifp->if_ipackets++; 584 schednetisr(NETISR_IP); 585 return error; 586} 587 588/* 589 * tunselect - the select interface, this is only useful on reads 590 * really. The write detect always returns true, write never blocks 591 * anyway, it either accepts the packet or drops it. 592 */ 593static int 594tunselect(dev_t dev, int rw, struct proc *p) 595{ 596 int unit = minor(dev), s; 597 struct tun_softc *tp = &tunctl[unit]; 598 struct ifnet *ifp = &tp->tun_if; 599 600 s = splimp(); 601 TUNDEBUG("%s%d: tunselect\n", ifp->if_name, ifp->if_unit); 602 603 switch (rw) { 604 case FREAD: 605 if (ifp->if_snd.ifq_len > 0) { 606 splx(s); 607 TUNDEBUG("%s%d: tunselect q=%d\n", ifp->if_name, 608 ifp->if_unit, ifp->if_snd.ifq_len); 609 return 1; 610 } 611 selrecord(p, &tp->tun_rsel); 612 break; 613 case FWRITE: 614 splx(s); 615 return 1; 616 } 617 splx(s); 618 TUNDEBUG("%s%d: tunselect waiting\n", ifp->if_name, ifp->if_unit); 619 return 0; 620} 621 622 623#endif /* NTUN */ 624