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