1 /* UNFINISHED CONVERSION TO 386BSD -wfj */ 2 3 /* if_tun.c - tunnel interface module & driver */ 4 5 /* 6 * Copyright (c) 1988, Julian Onions. 7 * 8 * This source may be freely distributed, however I would be interested 9 * in any changes that are made. 10 */ 11 12 /* 13 * 90/02/06 15:03 - Fixed a bug in where TIOCGPGRP and TIOCSPGRP were 14 * mixed up. Anders Klemets - klemets@sics.se 15 * 16 * $Id: if_tun.c,v 1.3 1993/05/22 11:42:13 cgd Exp $ 17 * 18 * $Log: if_tun.c,v $ 19 * Revision 1.3 1993/05/22 11:42:13 cgd 20 * add include of select.h if necessary for protos, or delete if extraneous 21 * 22 * Revision 1.2 1993/05/18 18:19:58 cgd 23 * make kernel select interface be one-stop shopping & clean it all up. 24 * 25 * Revision 1.1.1.1 1993/03/21 09:46:06 cgd 26 * initial import of 386bsd-0.1 sources 27 * 28 * Revision 1.13 88/07/11 08:28:51 jpo 29 * Some tidying up 30 * 31 * Revision 1.12 87/12/10 09:16:29 jpo 32 * Decided the vax/mtpr was unnecessay. 33 * 34 * Revision 1.11 87/12/10 09:10:36 jpo 35 * Fixed some minor things & 1 major bug. 36 * 37 * Revision 1.10 87/11/04 14:27:41 jpo 38 * A few sanity checks added. 39 * 40 * Revision 1.9 87/11/04 14:13:45 jpo 41 * Added some ioctls for non-blocking & async I/O 42 * 43 * Revision 1.8 87/10/19 10:28:14 jpo 44 * Another touch up (sigh) 45 * 46 * Revision 1.7 87/10/19 10:25:48 jpo 47 * Touch up. 48 * 49 * Revision 1.6 87/10/19 09:15:14 jpo 50 * Touch up. 51 * 52 * Revision 1.5 87/10/19 08:34:51 jpo 53 * General clean up - plus sun specific fixes 54 * 55 * Revision 1.4 87/10/16 17:10:12 jpo 56 * Purged all ioctl read/writes and non-standard routing stuff. 57 * 58 * Revision 1.3 87/10/05 11:57:09 jpo 59 * More debugging - in error mainly. 60 * 61 * Revision 1.2 87/10/04 18:29:45 jpo 62 * Select & read/write working. 63 */ 64 65 #include "tun.h" 66 #if NTUN > 0 67 68 /* 69 * Tunnel driver. 70 * 71 * This driver takes packets off the IP i/f and hands them up to a 72 * user process to have it's wicked way with. This driver has it's 73 * roots in a similar driver written by Phil Cockcroft (formerly) at 74 * UCL. This driver is based much more on read/write/select mode of 75 * operation though. 76 * 77 * Julian Onions <jpo@cs.nott.ac.uk> 78 * Nottingham University 1987. 79 */ 80 81 #include "param.h" 82 #include "systm.h" 83 #include "mbuf.h" 84 #include "buf.h" 85 #include "protosw.h" 86 #include "socket.h" 87 #include "ioctl.h" 88 #include "errno.h" 89 #include "syslog.h" 90 #include "select.h" 91 92 #include "net/if.h" 93 #include "net/netisr.h" 94 #include "net/route.h" 95 96 #ifdef INET 97 #include "netinet/in.h" 98 #include "netinet/in_systm.h" 99 #include "netinet/in_var.h" 100 #include "netinet/ip.h" 101 #include "netinet/if_ether.h" 102 #endif 103 104 #ifdef NS 105 #include "netns/ns.h" 106 #include "netns/ns_if.h" 107 #endif 108 109 #define TUNDEBUG if (tundebug) printf 110 111 int tundebug = 0; 112 struct tunctl 113 { 114 u_short tun_flags; /* misc flags */ 115 struct ifnet tun_if; /* the interface */ 116 int tun_pgrp; /* the process group - if any */ 117 struct selinfo tun_rsel; /* read select */ 118 struct selinfo tun_wsel; /* write select (not used) */ 119 } tunctl[NTUN]; 120 121 extern int ifqmaxlen; 122 123 int tunoutput (), tunioctl (), tuninit (); 124 125 /* tunnel open - must be superuser & the device must be configured in */ 126 tunopen (dev, flag) 127 dev_t dev; 128 { 129 register int unit; 130 struct tunctl *tp; 131 register struct ifnet *ifp; 132 133 if (!suser ()) 134 return EACCES; 135 if ((unit = minor (dev)) >= NTUN) 136 return (ENXIO); 137 tp = &tunctl[unit]; 138 if (tp->tun_flags & TUN_OPEN) 139 return ENXIO; 140 if ((tp->tun_flags & TUN_INITED) == 0) { 141 tp->tun_flags = TUN_INITED; 142 tunattach (unit); 143 } 144 ifp = &tp->tun_if; 145 tp->tun_flags |= TUN_OPEN; 146 TUNDEBUG ("%s%d: open\n", ifp->if_name, ifp->if_unit); 147 return (0); 148 } 149 150 /* tunclose - close the device - mark i/f down & delete routing info */ 151 tunclose (dev, flag) 152 dev_t dev; 153 { 154 int s; 155 register int unit = minor (dev); 156 register struct tunctl *tp = &tunctl[unit]; 157 register struct ifnet *ifp = &tp->tun_if; 158 register struct mbuf *m; 159 160 tp->tun_flags &= TUN_INITED; 161 162 /* 163 * junk all pending output 164 */ 165 do { 166 s = splimp (); 167 IF_DEQUEUE (&ifp->if_snd, m); 168 splx (s); 169 if (m) /* actually - m_freem checks this - but what the hell */ 170 m_freem (m); 171 } while (m != 0); 172 if (ifp->if_flags & IFF_UP) { 173 s = splimp (); 174 if_down (ifp); 175 if (ifp->if_flags & IFF_RUNNING) 176 rtinit (ifp->if_addrlist, (int)SIOCDELRT, RTF_HOST); 177 splx (s); 178 } 179 tp -> tun_pgrp = 0; 180 if (tp -> tun_rsel) 181 selwakeup (&tp->tun_rsel); 182 183 tp -> tun_rsel = tp -> tun_wsel = (struct proc *)0; 184 185 TUNDEBUG ("%s%d: closed\n", ifp->if_name, ifp->if_unit); 186 return (0); 187 } 188 189 /* 190 * attach an interface N.B. argument is not same as other drivers 191 */ 192 int 193 tunattach (unit) 194 int unit; 195 { 196 register struct ifnet *ifp = &tunctl[unit].tun_if; 197 register struct sockaddr_in *sin; 198 199 ifp->if_unit = unit; 200 ifp->if_name = "tun"; 201 ifp->if_mtu = TUNMTU; 202 ifp->if_ioctl = tunioctl; 203 ifp->if_output = tunoutput; 204 ifp->if_init = tuninit; 205 #ifndef BSD4_3 206 sin = (struct sockaddr_in *) & ifp->if_addr; 207 sin->sin_family = AF_INET; 208 #endif 209 ifp->if_flags = IFF_POINTOPOINT; 210 ifp->if_snd.ifq_maxlen = ifqmaxlen; 211 ifp->if_collisions = ifp->if_ierrors = ifp->if_oerrors = 0; 212 ifp->if_ipackets = ifp->if_opackets = 0; 213 if_attach (ifp); 214 TUNDEBUG ("%s%d: tunattach\n", ifp->if_name, ifp->if_unit); 215 return 0; 216 } 217 218 int 219 tuninit (unit) 220 int unit; 221 { 222 register struct tunctl *tp = &tunctl[unit]; 223 register struct ifnet *ifp = &tp->tun_if; 224 #ifndef BSD4_3 225 register struct sockaddr_in *sin; 226 227 sin = (struct sockaddr_in *) & ifp->if_addr; 228 if (sin->sin_addr.s_addr == 0) /* if address still unknown */ 229 return; 230 if_rtinit (ifp, RTF_UP); 231 #endif 232 ifp->if_flags |= IFF_UP | IFF_RUNNING; 233 tp->tun_flags |= TUN_IASET; 234 TUNDEBUG ("%s%d: tuninit\n", ifp->if_name, ifp->if_unit); 235 return 0; 236 } 237 238 /* 239 * Process an ioctl request. 240 * The problem here is 4.2 pass a struct ifreq * to this routine, 241 * sun only passes a struct sockaddr * since 3.2 at least. This is 242 * rather upsetting! Also, sun doesn't pass the SIOCDSTADDR ioctl through 243 * so we can't detect this being set directly. This is the reason for 244 * tuncheckready. 245 * Under 4.3 and SunOs 4.0 we now get the SIOCSIFDSTADDR ioctl, and we get a 246 * struct in_ifaddr * for data. (tte) 247 */ 248 249 #if !defined(BSD4_3) && defined(sun) 250 251 /* 252 * workaround for not being able to detect DSTADDR being set. 253 */ 254 255 tuncheckready (ifp) 256 struct ifnet *ifp; 257 { 258 struct tunctl *tp = &tunctl[ifp->if_unit]; 259 struct sockaddr_in *sin; 260 261 sin = (struct sockaddr_in *) &ifp->if_dstaddr; 262 if (sin->sin_addr.s_addr == 0) 263 return 0; 264 tp -> tun_flags |= TUN_DSTADDR; 265 return 1; 266 } 267 #else 268 #define tuncheckready(dummy) 1 269 #endif /* !defined(BSD4_3) && defined(sun) */ 270 271 int 272 tunioctl (ifp, cmd, data) 273 register struct ifnet *ifp; 274 int cmd; 275 caddr_t data; 276 { 277 #ifndef BSD4_3 278 #ifdef sun 279 struct sockaddr_in *sin = (struct sockaddr_in *) data; 280 #else 281 struct sockaddr_in *sin; 282 struct ifreq *ifr = (struct ifreq *) data; 283 #endif 284 #endif /* BSD4_3 */ 285 286 int s = splimp (), error = 0; 287 struct tunctl *tp = &tunctl[ifp->if_unit]; 288 289 switch (cmd) 290 { 291 case SIOCSIFADDR: 292 #ifndef BSD4_3 293 if (ifp->if_flags & IFF_RUNNING) 294 if_rtinit (ifp, -1); /* delete previous route */ 295 #ifndef sun 296 sin = (struct sockaddr_in *)&ifr -> ifr_addr; 297 #endif 298 ifp->if_addr = *((struct sockaddr *) sin); 299 ifp->if_net = in_netof (sin->sin_addr); 300 ifp->if_host[0] = in_lnaof (sin->sin_addr); 301 #endif 302 tuninit (ifp->if_unit); 303 break; 304 case SIOCSIFDSTADDR: 305 tp->tun_flags |= TUN_DSTADDR; 306 #ifndef BSD4_3 307 #ifndef sun 308 sin = (struct sockaddr_in *)&ifr -> ifr_addr; 309 #endif 310 ifp->if_dstaddr = *((struct sockaddr *)sin); 311 #endif BSD4_3 312 TUNDEBUG ("%s%d: destination addres set\n", ifp->if_name, 313 ifp -> if_unit); 314 break; 315 default: 316 error = EINVAL; 317 } 318 splx (s); 319 return (error); 320 } 321 322 /* 323 * tunoutput - queue packets from higher level ready to put out. 324 */ 325 tunoutput (ifp, m0, dst) 326 struct ifnet *ifp; 327 struct mbuf *m0; 328 struct sockaddr *dst; 329 { 330 struct tunctl *tp; 331 struct proc *p; 332 int s; 333 334 TUNDEBUG ("%s%d: tunoutput\n", ifp->if_name, ifp->if_unit); 335 tp = &tunctl[ifp->if_unit]; 336 if ((tp->tun_flags & TUN_READY) != TUN_READY) { 337 if(tuncheckready(ifp) == 0) { 338 TUNDEBUG ("%s%d: not ready 0%o\n", ifp->if_name, 339 ifp->if_unit, tp->tun_flags); 340 m_freem (m0); 341 return EHOSTDOWN; 342 } 343 } 344 345 switch (dst->sa_family) { 346 #ifdef INET 347 case AF_INET: 348 s = splimp (); 349 if (IF_QFULL (&ifp->if_snd)) 350 { 351 IF_DROP (&ifp->if_snd); 352 m_freem (m0); 353 splx (s); 354 ifp->if_collisions++; 355 return (ENOBUFS); 356 } 357 IF_ENQUEUE (&ifp->if_snd, m0); 358 splx (s); 359 ifp->if_opackets++; 360 break; 361 #endif 362 default: 363 m_freem (m0); 364 return EAFNOSUPPORT; 365 } 366 367 if (tp->tun_flags & TUN_RWAIT) { 368 tp->tun_flags &= ~TUN_RWAIT; 369 wakeup ((caddr_t) tp); 370 } 371 if (tp->tun_flags & TUN_ASYNC && tp -> tun_pgrp != 0) { 372 if (tp->tun_pgrp > 0) 373 gsignal (tp->tun_pgrp, SIGIO); 374 else if ((p = pfind (-tp->tun_pgrp)) != 0) 375 psignal (p, SIGIO); 376 } 377 selwakeup (&tp->tun_rsel); 378 return 0; 379 } 380 381 /* 382 * the cdevsw interface is now pretty minimal. 383 */ 384 385 tuncioctl (dev, cmd, data, flag) 386 dev_t dev; 387 caddr_t data; 388 { 389 int unit = minor(dev); 390 struct tunctl *tp = &tunctl[unit]; 391 int s; 392 393 switch (cmd) { 394 case TUNSDEBUG: 395 tundebug = *(int *)data; 396 break; 397 398 case TUNGDEBUG: 399 *(int *)data = tundebug; 400 break; 401 402 case FIONBIO: 403 if (*(int *)data) 404 tp->tun_flags |= TUN_NBIO; 405 else 406 tp->tun_flags &= ~TUN_NBIO; 407 break; 408 409 case FIOASYNC: 410 if (*(int *)data) 411 tp->tun_flags |= TUN_ASYNC; 412 else 413 tp->tun_flags &= ~TUN_ASYNC; 414 break; 415 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 *(int *)data = 0; 421 splx (s); 422 break; 423 424 case TIOCSPGRP: 425 tp->tun_pgrp = *(int *)data; 426 break; 427 428 case TIOCGPGRP: 429 *(int *)data = tp->tun_pgrp; 430 break; 431 432 default: 433 return (ENOTTY); 434 } 435 return (0); 436 } 437 438 /* 439 * The cdevsw read interface - reads a packet at a time, or at least as much 440 * of a packet as can be read. 441 */ 442 tunread (dev, uio) 443 dev_t dev; 444 struct uio *uio; 445 { 446 register struct ifnet *ifp; 447 register struct mbuf *m, *m0; 448 int unit = minor (dev); 449 int len, s; 450 int error = 0; 451 struct tunctl *tp; 452 453 tp = &tunctl[unit]; 454 ifp = &tp->tun_if; 455 TUNDEBUG ("%s%d: read\n", ifp->if_name, ifp->if_unit); 456 if ((tp->tun_flags & TUN_READY) != TUN_READY) { 457 if(tuncheckready(ifp) == 0) { 458 TUNDEBUG ("%s%d: not ready 0%o\n", ifp->if_name, 459 ifp->if_unit, tp->tun_flags); 460 return EHOSTDOWN; 461 } 462 } 463 464 tp->tun_flags &= ~TUN_RWAIT; 465 466 s = splimp (); 467 do { 468 IF_DEQUEUE (&ifp->if_snd, m0); 469 if (m0 == 0) { 470 if (tp -> tun_flags & TUN_NBIO) { 471 splx (s); 472 return EWOULDBLOCK; 473 } 474 tp->tun_flags |= TUN_RWAIT; 475 sleep ((caddr_t) tp, PZERO + 1); 476 } 477 } while (m0 == 0); 478 splx (s); 479 480 while (m0 && uio->uio_resid > 0 && error == 0) { 481 len = MIN (uio->uio_resid, m0->m_len); 482 if (len == 0) 483 break; 484 error = uiomove (mtod (m0, caddr_t), len, 485 UIO_READ, uio); 486 MFREE (m0, m); 487 m0 = m; 488 } 489 490 if (m0 != 0) { 491 TUNDEBUG ("Dropping mbuf\n"); 492 m_freem (m0); 493 } 494 return error; 495 } 496 497 /* 498 * the cdevsw write interface - an atomic write is a packet - or else! 499 */ 500 501 tunwrite (dev, uio) 502 int dev; 503 struct uio *uio; 504 { 505 int error = 0; 506 int unit = minor (dev); 507 struct mbuf *top, **mp, *m; 508 struct ifnet *ifp = &(tunctl[unit].tun_if); 509 int s; 510 511 TUNDEBUG ("%s%d: tunwrite\n", ifp->if_name, ifp->if_unit); 512 513 if (uio->uio_resid < 0 || uio->uio_resid > TUNMTU) { 514 TUNDEBUG ("%s%d: len=%d!\n", ifp->if_name, ifp->if_unit, 515 uio->uio_resid); 516 return EIO; 517 } 518 top = 0; 519 mp = ⊤ 520 while (error == 0 && uio->uio_resid > 0) { 521 MGET (m, M_DONTWAIT, MT_DATA); 522 if (m == 0) { 523 error = ENOBUFS; 524 break; 525 } 526 m->m_len = MIN (MLEN, uio->uio_resid); 527 error = uiomove (mtod (m, caddr_t), m->m_len, UIO_WRITE, uio); 528 *mp = m; 529 mp = &m->m_next; 530 } 531 if (error) { 532 if (top) 533 m_freem (top); 534 return error; 535 } 536 537 #ifdef BSD4_3 538 /* 539 * Place interface pointer before the data 540 * for the receiving protocol. 541 */ 542 if (top->m_off <= MMAXOFF && 543 top->m_off >= MMINOFF + sizeof(struct ifnet *)) { 544 top->m_off -= sizeof(struct ifnet *); 545 top->m_len += sizeof(struct ifnet *); 546 } else { 547 MGET(m, M_DONTWAIT, MT_HEADER); 548 if (m == (struct mbuf *)0) 549 return (ENOBUFS); 550 m->m_len = sizeof(struct ifnet *); 551 m->m_next = top; 552 top = m; 553 } 554 *(mtod(top, struct ifnet **)) = ifp; 555 #endif /* BSD4_3 */ 556 557 s = splimp (); 558 if (IF_QFULL (&ipintrq)) { 559 IF_DROP (&ipintrq); 560 splx (s); 561 ifp->if_collisions++; 562 m_freem (top); 563 return ENOBUFS; 564 } 565 IF_ENQUEUE (&ipintrq, top); 566 splx (s); 567 ifp->if_ipackets++; 568 schednetisr (NETISR_IP); 569 return error; 570 } 571 572 /* 573 * tunselect - the select interface, this is only useful on reads really. 574 * The write detect always returns true, write never blocks anyway, it either 575 * accepts the packet or drops it. 576 */ 577 tunselect (dev, rw) 578 dev_t dev; 579 int rw; 580 { 581 int unit = minor (dev); 582 register struct tunctl *tp = &tunctl[unit]; 583 struct ifnet *ifp = &tp->tun_if; 584 int s = splimp (); 585 586 TUNDEBUG ("%s%d: tunselect\n", ifp->if_name, ifp->if_unit); 587 switch (rw) { 588 case FREAD: 589 if (ifp->if_snd.ifq_len > 0) { 590 splx (s); 591 TUNDEBUG ("%s%d: tunselect q=%d\n", ifp->if_name, 592 ifp->if_unit, ifp->if_snd.ifq_len); 593 return 1; 594 } 595 selrecord(p, &tp->tun_rsel); 596 break; 597 case FWRITE: 598 splx (s); 599 return 1; 600 } 601 splx (s); 602 TUNDEBUG ("%s%d: tunselect waiting\n", ifp->if_name, ifp->if_unit); 603 return 0; 604 } 605 #endif NTUN 606