2 * ip tunnel/ethertap device for MacOSX.
4 * tuntap_manager definition.
7 * Copyright (c) 2004, 2005, 2006, 2007 Mattias Nissler <mattias.nissler@gmx.de>
9 * Redistribution and use in source and binary forms, with or without modification, are permitted
10 * provided that the following conditions are met:
12 * 1. Redistributions of source code must retain the above copyright notice, this list of
13 * conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright notice, this list of
15 * conditions and the following disclaimer in the documentation and/or other materials provided
16 * with the distribution.
17 * 3. The name of the author may not be used to endorse or promote products derived from this
18 * software without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
21 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
22 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
23 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
24 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 #include <sys/param.h>
36 #include <sys/syslog.h>
37 #include <sys/systm.h>
38 #include <sys/malloc.h>
40 #include <vm/vm_kern.h>
42 #include <miscfs/devfs/devfs.h>
47 #define dprintf(...) log(LOG_INFO, __VA_ARGS__)
52 /* cdevsw for tuntap_manager */
53 static struct cdevsw mgr_cdevsw
=
55 tuntap_manager::cdev_open
,
56 tuntap_manager::cdev_close
,
57 tuntap_manager::cdev_read
,
58 tuntap_manager::cdev_write
,
59 tuntap_manager::cdev_ioctl
,
63 tuntap_manager::cdev_select
,
71 /* tuntap_manager members */
72 tuntap_manager
*tuntap_manager::mgr_map
[MAX_CDEV
];
74 bool tuntap_manager::statics_initialized
= false;
76 /* static initializer */
78 tuntap_manager::initialize_statics()
80 dprintf("initializing mgr_map\n");
82 /* initialize the major-to-manager map */
83 for (int i
= 0; i
< MAX_CDEV
; i
++)
86 statics_initialized
= true;
90 tuntap_manager::initialize(unsigned int count
, char *family
)
93 this->family
= family
;
96 if (!statics_initialized
)
99 /* make sure noone can access the character devices until we are done */
100 auto_lock
l(&cdev_gate
);
102 /* register the switch for the tap character devices */
103 dev_major
= cdevsw_add(-1, &mgr_cdevsw
);
104 if (dev_major
== -1) {
105 log(LOG_ERR
, "%s: could not register character device switch.\n", family
);
109 /* allocate memory for the interface instance table */
110 tuntaps
= (tuntap_interface
**) kalloc(count
* sizeof(tuntap_interface
*));
112 if (tuntaps
== NULL
) {
113 log(LOG_ERR
, "%s: no memory!\n", family
);
117 bzero(tuntaps
, count
* sizeof(tuntap_interface
*));
119 /* Create the interfaces. This will only add the character devices. The network devices will
120 * be created upon open()ing the corresponding character devices.
122 for (int i
= 0; i
< (int) count
; i
++)
124 tuntaps
[i
] = create_interface();
126 if (tuntaps
[i
] != NULL
)
128 if (tuntaps
[i
]->initialize(dev_major
, i
))
133 /* error here. current interface needs to be shut down */
137 /* something went wrong. clean up. */
140 tuntaps
[i
]->shutdown();
147 /* register the new family in the mgr switch */
148 mgr_map
[dev_major
] = this;
150 log(LOG_INFO
, "%s kernel extension version %s <mattias.nissler@gmx.de>\n",
151 family
, TUNTAP_VERSION
);
157 tuntap_manager::shutdown()
161 /* we halt the whole thing while we check whether we can shutdown */
162 auto_lock
l(&cdev_gate
);
165 if (cdev_gate
.is_anyone_in()) {
166 dprintf("tuntap_mgr: won't shutdown, threads still behind the gate.");
169 /* query the interfaces to see if shutting down is ok */
170 if (tuntaps
!= NULL
) {
171 for (unsigned int i
= 0; i
< count
; i
++) {
172 if (tuntaps
[i
] != NULL
)
173 ok
&= tuntaps
[i
]->idle();
176 /* if yes, do it now */
178 for (unsigned int i
= 0; i
< count
; i
++) {
179 if (tuntaps
[i
] != NULL
) {
180 tuntaps
[i
]->shutdown();
189 /* unregister the character device switch */
191 if (dev_major
!= -1 && cdevsw_remove(dev_major
, &mgr_cdevsw
) == -1) {
193 "%s: character device switch got lost. strange.\n", family
);
195 mgr_map
[dev_major
] = NULL
;
198 /* at this point there is still a chance that some thread hangs at the cdev_gate in
199 * one of the cdev service functions. I can't imagine any way that would aviod this.
200 * So lets unblock the gate such that they fail.
202 unsigned int old_number
;
204 old_number
= cdev_gate
.get_ticket_number();
207 dprintf("tuntap_manager: waiting for other threads to give up.\n");
209 /* wait one second */
212 } while (cdev_gate
.get_ticket_number() != old_number
);
214 /* I hope it is safe to unload now. */
217 log(LOG_WARNING
, "%s: won't unload, at least one interface is busy.\n", family
);
220 dprintf("tuntap manager: shutdown %s\n", ok
? "ok" : "failed");
225 tuntap_manager::~tuntap_manager()
227 dprintf("freeing interface table\n");
231 kfree(tuntaps
, count
* sizeof(tuntap_interface
*));
234 /* service method dispatchers */
236 tuntap_manager::cdev_open(dev_t dev
, int flags
, int devtype
, proc_t p
)
238 return (mgr_map
[major(dev
)] == NULL
? ENOENT
239 : mgr_map
[major(dev
)]->do_cdev_open(dev
, flags
, devtype
, p
));
243 tuntap_manager::cdev_close(dev_t dev
, int flags
, int devtype
, proc_t p
)
245 return (mgr_map
[major(dev
)] == NULL
? EBADF
246 : mgr_map
[major(dev
)]->do_cdev_close(dev
, flags
, devtype
, p
));
250 tuntap_manager::cdev_read(dev_t dev
, uio_t uio
, int ioflag
)
252 return (mgr_map
[major(dev
)] == NULL
? EBADF
253 : mgr_map
[major(dev
)]->do_cdev_read(dev
, uio
, ioflag
));
257 tuntap_manager::cdev_write(dev_t dev
, uio_t uio
, int ioflag
)
259 return (mgr_map
[major(dev
)] == NULL
? EBADF
260 : mgr_map
[major(dev
)]->do_cdev_write(dev
, uio
, ioflag
));
264 tuntap_manager::cdev_ioctl(dev_t dev
, u_long cmd
, caddr_t data
, int fflag
, proc_t p
)
266 return (mgr_map
[major(dev
)] == NULL
? EBADF
267 : mgr_map
[major(dev
)]->do_cdev_ioctl(dev
, cmd
, data
, fflag
, p
));
271 tuntap_manager::cdev_select(dev_t dev
, int which
, void *wql
, proc_t p
)
273 return (mgr_map
[major(dev
)] == NULL
? EBADF
274 : mgr_map
[major(dev
)]->do_cdev_select(dev
, which
, wql
, p
));
277 /* character device service methods */
279 tuntap_manager::do_cdev_open(dev_t dev
, int flags
, int devtype
, proc_t p
)
281 int dmin
= minor(dev
);
286 if (dmin
< (int) count
&& dmin
>= 0 && tuntaps
[dmin
] != NULL
)
287 error
= tuntaps
[dmin
]->cdev_open(flags
, devtype
, p
);
295 tuntap_manager::do_cdev_close(dev_t dev
, int flags
, int devtype
, proc_t p
)
297 int dmin
= minor(dev
);
302 if (dmin
< (int) count
&& dmin
>= 0 && tuntaps
[dmin
] != NULL
)
303 error
= tuntaps
[dmin
]->cdev_close(flags
, devtype
, p
);
311 tuntap_manager::do_cdev_read(dev_t dev
, uio_t uio
, int ioflag
)
313 int dmin
= minor(dev
);
318 if (dmin
< (int) count
&& dmin
>= 0 && tuntaps
[dmin
] != NULL
)
319 error
= tuntaps
[dmin
]->cdev_read(uio
, ioflag
);
327 tuntap_manager::do_cdev_write(dev_t dev
, uio_t uio
, int ioflag
)
329 int dmin
= minor(dev
);
334 if (dmin
< (int) count
&& dmin
>= 0 && tuntaps
[dmin
] != NULL
)
335 error
= tuntaps
[dmin
]->cdev_write(uio
, ioflag
);
343 tuntap_manager::do_cdev_ioctl(dev_t dev
, u_long cmd
, caddr_t data
, int fflag
, proc_t p
)
345 int dmin
= minor(dev
);
350 if (dmin
< (int) count
&& dmin
>= 0 && tuntaps
[dmin
] != NULL
)
351 error
= tuntaps
[dmin
]->cdev_ioctl(cmd
, data
, fflag
, p
);
359 tuntap_manager::do_cdev_select(dev_t dev
, int which
, void *wql
, proc_t p
)
361 int dmin
= minor(dev
);
366 if (dmin
< (int) count
&& dmin
>= 0 && tuntaps
[dmin
] != NULL
)
367 error
= tuntaps
[dmin
]->cdev_select(which
, wql
, p
);