if_tun.c (347376) | if_tun.c (347378) |
---|---|
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 its 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/poll mode of 14 * operation though. 15 * | 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 its 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/poll mode of 14 * operation though. 15 * |
16 * $FreeBSD: stable/11/sys/net/if_tun.c 347376 2019-05-09 01:16:03Z kevans $ | 16 * $FreeBSD: stable/11/sys/net/if_tun.c 347378 2019-05-09 03:51:34Z kevans $ |
17 */ 18 19#include "opt_inet.h" 20#include "opt_inet6.h" 21 22#include <sys/param.h> | 17 */ 18 19#include "opt_inet.h" 20#include "opt_inet6.h" 21 22#include <sys/param.h> |
23#include <sys/lock.h> |
|
23#include <sys/priv.h> 24#include <sys/proc.h> 25#include <sys/systm.h> 26#include <sys/jail.h> 27#include <sys/mbuf.h> 28#include <sys/module.h> 29#include <sys/socket.h> 30#include <sys/fcntl.h> 31#include <sys/filio.h> 32#include <sys/sockio.h> | 24#include <sys/priv.h> 25#include <sys/proc.h> 26#include <sys/systm.h> 27#include <sys/jail.h> 28#include <sys/mbuf.h> 29#include <sys/module.h> 30#include <sys/socket.h> 31#include <sys/fcntl.h> 32#include <sys/filio.h> 33#include <sys/sockio.h> |
34#include <sys/sx.h> |
|
33#include <sys/ttycom.h> 34#include <sys/poll.h> 35#include <sys/selinfo.h> 36#include <sys/signalvar.h> 37#include <sys/filedesc.h> 38#include <sys/kernel.h> 39#include <sys/sysctl.h> 40#include <sys/conf.h> --- 33 unchanged lines hidden (view full) --- 74#define TUN_INITED 0x0002 75#define TUN_RCOLL 0x0004 76#define TUN_IASET 0x0008 77#define TUN_DSTADDR 0x0010 78#define TUN_LMODE 0x0020 79#define TUN_RWAIT 0x0040 80#define TUN_ASYNC 0x0080 81#define TUN_IFHEAD 0x0100 | 35#include <sys/ttycom.h> 36#include <sys/poll.h> 37#include <sys/selinfo.h> 38#include <sys/signalvar.h> 39#include <sys/filedesc.h> 40#include <sys/kernel.h> 41#include <sys/sysctl.h> 42#include <sys/conf.h> --- 33 unchanged lines hidden (view full) --- 76#define TUN_INITED 0x0002 77#define TUN_RCOLL 0x0004 78#define TUN_IASET 0x0008 79#define TUN_DSTADDR 0x0010 80#define TUN_LMODE 0x0020 81#define TUN_RWAIT 0x0040 82#define TUN_ASYNC 0x0080 83#define TUN_IFHEAD 0x0100 |
84#define TUN_DYING 0x0200 |
|
82 83#define TUN_READY (TUN_OPEN | TUN_INITED) 84 | 85 86#define TUN_READY (TUN_OPEN | TUN_INITED) 87 |
85 /* 86 * XXXRW: tun_pid is used to exclusively lock /dev/tun. Is this 87 * actually needed? Can we just return EBUSY if already open? 88 * Problem is that this involved inherent races when a tun device 89 * is handed off from one process to another, as opposed to just 90 * being slightly stale informationally. 91 */ | |
92 pid_t tun_pid; /* owning pid */ 93 struct ifnet *tun_ifp; /* the interface */ 94 struct sigio *tun_sigio; /* information for async I/O */ 95 struct selinfo tun_rsel; /* read select */ 96 struct mtx tun_mtx; /* protect mutable softc fields */ 97 struct cv tun_cv; /* protect against ref'd dev destroy */ 98}; 99#define TUN2IFP(sc) ((sc)->tun_ifp) --- 10 unchanged lines hidden (view full) --- 110static const char tunname[] = "tun"; 111static MALLOC_DEFINE(M_TUN, tunname, "Tunnel Interface"); 112static int tundebug = 0; 113static int tundclone = 1; 114static struct clonedevs *tunclones; 115static TAILQ_HEAD(,tun_softc) tunhead = TAILQ_HEAD_INITIALIZER(tunhead); 116SYSCTL_INT(_debug, OID_AUTO, if_tun_debug, CTLFLAG_RW, &tundebug, 0, ""); 117 | 88 pid_t tun_pid; /* owning pid */ 89 struct ifnet *tun_ifp; /* the interface */ 90 struct sigio *tun_sigio; /* information for async I/O */ 91 struct selinfo tun_rsel; /* read select */ 92 struct mtx tun_mtx; /* protect mutable softc fields */ 93 struct cv tun_cv; /* protect against ref'd dev destroy */ 94}; 95#define TUN2IFP(sc) ((sc)->tun_ifp) --- 10 unchanged lines hidden (view full) --- 106static const char tunname[] = "tun"; 107static MALLOC_DEFINE(M_TUN, tunname, "Tunnel Interface"); 108static int tundebug = 0; 109static int tundclone = 1; 110static struct clonedevs *tunclones; 111static TAILQ_HEAD(,tun_softc) tunhead = TAILQ_HEAD_INITIALIZER(tunhead); 112SYSCTL_INT(_debug, OID_AUTO, if_tun_debug, CTLFLAG_RW, &tundebug, 0, ""); 113 |
114static struct sx tun_ioctl_sx; 115SX_SYSINIT(tun_ioctl_sx, &tun_ioctl_sx, "tun_ioctl"); 116 |
|
118SYSCTL_DECL(_net_link); 119static SYSCTL_NODE(_net_link, OID_AUTO, tun, CTLFLAG_RW, 0, 120 "IP tunnel software network interface."); 121SYSCTL_INT(_net_link_tun, OID_AUTO, devfs_cloning, CTLFLAG_RWTUN, &tundclone, 0, 122 "Enable legacy devfs interface creation."); 123 124static void tunclone(void *arg, struct ucred *cred, char *name, 125 int namelen, struct cdev **dev); --- 141 unchanged lines hidden (view full) --- 267} 268 269static void 270tun_destroy(struct tun_softc *tp) 271{ 272 struct cdev *dev; 273 274 mtx_lock(&tp->tun_mtx); | 117SYSCTL_DECL(_net_link); 118static SYSCTL_NODE(_net_link, OID_AUTO, tun, CTLFLAG_RW, 0, 119 "IP tunnel software network interface."); 120SYSCTL_INT(_net_link_tun, OID_AUTO, devfs_cloning, CTLFLAG_RWTUN, &tundclone, 0, 121 "Enable legacy devfs interface creation."); 122 123static void tunclone(void *arg, struct ucred *cred, char *name, 124 int namelen, struct cdev **dev); --- 141 unchanged lines hidden (view full) --- 266} 267 268static void 269tun_destroy(struct tun_softc *tp) 270{ 271 struct cdev *dev; 272 273 mtx_lock(&tp->tun_mtx); |
274 tp->tun_flags |= TUN_DYING; |
|
275 if ((tp->tun_flags & TUN_OPEN) != 0) 276 cv_wait_unlock(&tp->tun_cv, &tp->tun_mtx); 277 else 278 mtx_unlock(&tp->tun_mtx); 279 280 CURVNET_SET(TUN2IFP(tp)->if_vnet); | 275 if ((tp->tun_flags & TUN_OPEN) != 0) 276 cv_wait_unlock(&tp->tun_cv, &tp->tun_mtx); 277 else 278 mtx_unlock(&tp->tun_mtx); 279 280 CURVNET_SET(TUN2IFP(tp)->if_vnet); |
281 sx_xlock(&tun_ioctl_sx); 282 TUN2IFP(tp)->if_softc = NULL; 283 sx_xunlock(&tun_ioctl_sx); 284 |
|
281 dev = tp->tun_dev; 282 bpfdetach(TUN2IFP(tp)); 283 if_detach(TUN2IFP(tp)); 284 free_unr(tun_unrhdr, TUN2IFP(tp)->if_dunit); 285 if_free(TUN2IFP(tp)); 286 destroy_dev(dev); 287 seldrain(&tp->tun_rsel); 288 knlist_clear(&tp->tun_rsel.si_note, 0); --- 170 unchanged lines hidden (view full) --- 459 * synchronization. 460 */ 461 tp = dev->si_drv1; 462 if (!tp) { 463 tuncreate(tunname, dev); 464 tp = dev->si_drv1; 465 } 466 | 285 dev = tp->tun_dev; 286 bpfdetach(TUN2IFP(tp)); 287 if_detach(TUN2IFP(tp)); 288 free_unr(tun_unrhdr, TUN2IFP(tp)->if_dunit); 289 if_free(TUN2IFP(tp)); 290 destroy_dev(dev); 291 seldrain(&tp->tun_rsel); 292 knlist_clear(&tp->tun_rsel.si_note, 0); --- 170 unchanged lines hidden (view full) --- 463 * synchronization. 464 */ 465 tp = dev->si_drv1; 466 if (!tp) { 467 tuncreate(tunname, dev); 468 tp = dev->si_drv1; 469 } 470 |
467 /* 468 * XXXRW: This use of tun_pid is subject to error due to the 469 * fact that a reference to the tunnel can live beyond the 470 * death of the process that created it. Can we replace this 471 * with a simple busy flag? 472 */ | |
473 mtx_lock(&tp->tun_mtx); | 471 mtx_lock(&tp->tun_mtx); |
474 if (tp->tun_pid != 0 && tp->tun_pid != td->td_proc->p_pid) { | 472 if ((tp->tun_flags & (TUN_OPEN | TUN_DYING)) != 0) { |
475 mtx_unlock(&tp->tun_mtx); 476 return (EBUSY); 477 } | 473 mtx_unlock(&tp->tun_mtx); 474 return (EBUSY); 475 } |
478 tp->tun_pid = td->td_proc->p_pid; | |
479 | 476 |
477 tp->tun_pid = td->td_proc->p_pid; |
|
480 tp->tun_flags |= TUN_OPEN; 481 ifp = TUN2IFP(tp); 482 if_link_state_change(ifp, LINK_STATE_UP); 483 TUNDEBUG(ifp, "open\n"); 484 mtx_unlock(&tp->tun_mtx); 485 486 return (0); 487} --- 7 unchanged lines hidden (view full) --- 495{ 496 struct tun_softc *tp; 497 struct ifnet *ifp; 498 499 tp = dev->si_drv1; 500 ifp = TUN2IFP(tp); 501 502 mtx_lock(&tp->tun_mtx); | 478 tp->tun_flags |= TUN_OPEN; 479 ifp = TUN2IFP(tp); 480 if_link_state_change(ifp, LINK_STATE_UP); 481 TUNDEBUG(ifp, "open\n"); 482 mtx_unlock(&tp->tun_mtx); 483 484 return (0); 485} --- 7 unchanged lines hidden (view full) --- 493{ 494 struct tun_softc *tp; 495 struct ifnet *ifp; 496 497 tp = dev->si_drv1; 498 ifp = TUN2IFP(tp); 499 500 mtx_lock(&tp->tun_mtx); |
503 tp->tun_flags &= ~TUN_OPEN; 504 tp->tun_pid = 0; | 501 /* 502 * Simply close the device if this isn't the controlling process. This 503 * may happen if, for instance, the tunnel has been handed off to 504 * another process. The original controller should be able to close it 505 * without putting us into an inconsistent state. 506 */ 507 if (td->td_proc->p_pid != tp->tun_pid) { 508 mtx_unlock(&tp->tun_mtx); 509 return (0); 510 } |
505 506 /* 507 * junk all pending output 508 */ 509 CURVNET_SET(ifp->if_vnet); 510 IFQ_PURGE(&ifp->if_snd); 511 512 if (ifp->if_flags & IFF_UP) { --- 22 unchanged lines hidden (view full) --- 535 } 536 if_link_state_change(ifp, LINK_STATE_DOWN); 537 CURVNET_RESTORE(); 538 539 funsetown(&tp->tun_sigio); 540 selwakeuppri(&tp->tun_rsel, PZERO + 1); 541 KNOTE_LOCKED(&tp->tun_rsel.si_note, 0); 542 TUNDEBUG (ifp, "closed\n"); | 511 512 /* 513 * junk all pending output 514 */ 515 CURVNET_SET(ifp->if_vnet); 516 IFQ_PURGE(&ifp->if_snd); 517 518 if (ifp->if_flags & IFF_UP) { --- 22 unchanged lines hidden (view full) --- 541 } 542 if_link_state_change(ifp, LINK_STATE_DOWN); 543 CURVNET_RESTORE(); 544 545 funsetown(&tp->tun_sigio); 546 selwakeuppri(&tp->tun_rsel, PZERO + 1); 547 KNOTE_LOCKED(&tp->tun_rsel.si_note, 0); 548 TUNDEBUG (ifp, "closed\n"); |
549 tp->tun_flags &= ~TUN_OPEN; 550 tp->tun_pid = 0; |
|
543 544 cv_broadcast(&tp->tun_cv); 545 mtx_unlock(&tp->tun_mtx); 546 return (0); 547} 548 549static void 550tuninit(struct ifnet *ifp) --- 32 unchanged lines hidden (view full) --- 583 584/* 585 * Process an ioctl request. 586 */ 587static int 588tunifioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 589{ 590 struct ifreq *ifr = (struct ifreq *)data; | 551 552 cv_broadcast(&tp->tun_cv); 553 mtx_unlock(&tp->tun_mtx); 554 return (0); 555} 556 557static void 558tuninit(struct ifnet *ifp) --- 32 unchanged lines hidden (view full) --- 591 592/* 593 * Process an ioctl request. 594 */ 595static int 596tunifioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 597{ 598 struct ifreq *ifr = (struct ifreq *)data; |
591 struct tun_softc *tp = ifp->if_softc; | 599 struct tun_softc *tp; |
592 struct ifstat *ifs; 593 int error = 0; 594 | 600 struct ifstat *ifs; 601 int error = 0; 602 |
603 sx_xlock(&tun_ioctl_sx); 604 tp = ifp->if_softc; 605 if (tp == NULL) { 606 error = ENXIO; 607 goto bad; 608 } |
|
595 switch(cmd) { 596 case SIOCGIFSTATUS: 597 ifs = (struct ifstat *)data; 598 mtx_lock(&tp->tun_mtx); 599 if (tp->tun_pid) 600 snprintf(ifs->ascii, sizeof(ifs->ascii), 601 "\tOpened by PID %d\n", tp->tun_pid); 602 else --- 10 unchanged lines hidden (view full) --- 613 break; 614 case SIOCSIFFLAGS: 615 case SIOCADDMULTI: 616 case SIOCDELMULTI: 617 break; 618 default: 619 error = EINVAL; 620 } | 609 switch(cmd) { 610 case SIOCGIFSTATUS: 611 ifs = (struct ifstat *)data; 612 mtx_lock(&tp->tun_mtx); 613 if (tp->tun_pid) 614 snprintf(ifs->ascii, sizeof(ifs->ascii), 615 "\tOpened by PID %d\n", tp->tun_pid); 616 else --- 10 unchanged lines hidden (view full) --- 627 break; 628 case SIOCSIFFLAGS: 629 case SIOCADDMULTI: 630 case SIOCDELMULTI: 631 break; 632 default: 633 error = EINVAL; 634 } |
635bad: 636 sx_xunlock(&tun_ioctl_sx); |
|
621 return (error); 622} 623 624/* 625 * tunoutput - queue packets from higher level ready to put out. 626 */ 627static int 628tunoutput(struct ifnet *ifp, struct mbuf *m0, const struct sockaddr *dst, --- 468 unchanged lines hidden --- | 637 return (error); 638} 639 640/* 641 * tunoutput - queue packets from higher level ready to put out. 642 */ 643static int 644tunoutput(struct ifnet *ifp, struct mbuf *m0, const struct sockaddr *dst, --- 468 unchanged lines hidden --- |