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