Deleted Added
full compact
if_tap.c (166443) if_tap.c (166497)
1/*-
2 * Copyright (C) 1999-2000 by Maksim Yevmenkin <m_evmenkin@yahoo.com>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 17 unchanged lines hidden (view full) ---

26 * BASED ON:
27 * -------------------------------------------------------------------------
28 *
29 * Copyright (c) 1988, Julian Onions <jpo@cs.nott.ac.uk>
30 * Nottingham University 1987.
31 */
32
33/*
1/*-
2 * Copyright (C) 1999-2000 by Maksim Yevmenkin <m_evmenkin@yahoo.com>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 17 unchanged lines hidden (view full) ---

26 * BASED ON:
27 * -------------------------------------------------------------------------
28 *
29 * Copyright (c) 1988, Julian Onions <jpo@cs.nott.ac.uk>
30 * Nottingham University 1987.
31 */
32
33/*
34 * $FreeBSD: head/sys/net/if_tap.c 166443 2007-02-03 02:57:45Z bms $
34 * $FreeBSD: head/sys/net/if_tap.c 166497 2007-02-04 16:32:46Z bms $
35 * $Id: if_tap.c,v 0.21 2000/07/23 21:46:02 max Exp $
36 */
37
38#include "opt_compat.h"
39#include "opt_inet.h"
40
41#include <sys/param.h>
42#include <sys/conf.h>

--- 14 unchanged lines hidden (view full) ---

57#include <sys/systm.h>
58#include <sys/ttycom.h>
59#include <sys/uio.h>
60#include <sys/queue.h>
61
62#include <net/bpf.h>
63#include <net/ethernet.h>
64#include <net/if.h>
35 * $Id: if_tap.c,v 0.21 2000/07/23 21:46:02 max Exp $
36 */
37
38#include "opt_compat.h"
39#include "opt_inet.h"
40
41#include <sys/param.h>
42#include <sys/conf.h>

--- 14 unchanged lines hidden (view full) ---

57#include <sys/systm.h>
58#include <sys/ttycom.h>
59#include <sys/uio.h>
60#include <sys/queue.h>
61
62#include <net/bpf.h>
63#include <net/ethernet.h>
64#include <net/if.h>
65#include <net/if_clone.h>
65#include <net/if_dl.h>
66#include <net/route.h>
67#include <net/if_types.h>
68
69#include <netinet/in.h>
70
71#include <net/if_tapvar.h>
72#include <net/if_tap.h>

--- 15 unchanged lines hidden (view full) ---

88 struct cdev **);
89static void tapcreate(struct cdev *);
90
91/* network interface */
92static void tapifstart(struct ifnet *);
93static int tapifioctl(struct ifnet *, u_long, caddr_t);
94static void tapifinit(void *);
95
66#include <net/if_dl.h>
67#include <net/route.h>
68#include <net/if_types.h>
69
70#include <netinet/in.h>
71
72#include <net/if_tapvar.h>
73#include <net/if_tap.h>

--- 15 unchanged lines hidden (view full) ---

89 struct cdev **);
90static void tapcreate(struct cdev *);
91
92/* network interface */
93static void tapifstart(struct ifnet *);
94static int tapifioctl(struct ifnet *, u_long, caddr_t);
95static void tapifinit(void *);
96
97static int tap_clone_create(struct if_clone *, int, caddr_t);
98static void tap_clone_destroy(struct ifnet *);
99static int vmnet_clone_create(struct if_clone *, int, caddr_t);
100static void vmnet_clone_destroy(struct ifnet *);
101
102IFC_SIMPLE_DECLARE(tap, 0);
103IFC_SIMPLE_DECLARE(vmnet, 0);
104
96/* character device */
97static d_open_t tapopen;
98static d_close_t tapclose;
99static d_read_t tapread;
100static d_write_t tapwrite;
101static d_ioctl_t tapioctl;
102static d_poll_t tappoll;
103static d_kqfilter_t tapkqfilter;

--- 33 unchanged lines hidden (view full) ---

137/*
138 * All global variables in if_tap.c are locked with tapmtx, with the
139 * exception of tapdebug, which is accessed unlocked; tapclones is
140 * static at runtime.
141 */
142static struct mtx tapmtx;
143static int tapdebug = 0; /* debug flag */
144static int tapuopen = 0; /* allow user open() */
105/* character device */
106static d_open_t tapopen;
107static d_close_t tapclose;
108static d_read_t tapread;
109static d_write_t tapwrite;
110static d_ioctl_t tapioctl;
111static d_poll_t tappoll;
112static d_kqfilter_t tapkqfilter;

--- 33 unchanged lines hidden (view full) ---

146/*
147 * All global variables in if_tap.c are locked with tapmtx, with the
148 * exception of tapdebug, which is accessed unlocked; tapclones is
149 * static at runtime.
150 */
151static struct mtx tapmtx;
152static int tapdebug = 0; /* debug flag */
153static int tapuopen = 0; /* allow user open() */
154static int tapdclone = 1; /* enable devfs cloning */
145static SLIST_HEAD(, tap_softc) taphead; /* first device */
146static struct clonedevs *tapclones;
147
148MALLOC_DECLARE(M_TAP);
149MALLOC_DEFINE(M_TAP, CDEV_NAME, "Ethernet tunnel interface");
150SYSCTL_INT(_debug, OID_AUTO, if_tap_debug, CTLFLAG_RW, &tapdebug, 0, "");
151
152SYSCTL_DECL(_net_link);
153SYSCTL_NODE(_net_link, OID_AUTO, tap, CTLFLAG_RW, 0,
154 "Ethernet tunnel software network interface");
155SYSCTL_INT(_net_link_tap, OID_AUTO, user_open, CTLFLAG_RW, &tapuopen, 0,
156 "Allow user to open /dev/tap (based on node permissions)");
155static SLIST_HEAD(, tap_softc) taphead; /* first device */
156static struct clonedevs *tapclones;
157
158MALLOC_DECLARE(M_TAP);
159MALLOC_DEFINE(M_TAP, CDEV_NAME, "Ethernet tunnel interface");
160SYSCTL_INT(_debug, OID_AUTO, if_tap_debug, CTLFLAG_RW, &tapdebug, 0, "");
161
162SYSCTL_DECL(_net_link);
163SYSCTL_NODE(_net_link, OID_AUTO, tap, CTLFLAG_RW, 0,
164 "Ethernet tunnel software network interface");
165SYSCTL_INT(_net_link_tap, OID_AUTO, user_open, CTLFLAG_RW, &tapuopen, 0,
166 "Allow user to open /dev/tap (based on node permissions)");
167SYSCTL_INT(_net_link_tap, OID_AUTO, devfs_cloning, CTLFLAG_RW, &tapdclone, 0,
168 "Enably legacy devfs interface creation");
157SYSCTL_INT(_net_link_tap, OID_AUTO, debug, CTLFLAG_RW, &tapdebug, 0, "");
158
169SYSCTL_INT(_net_link_tap, OID_AUTO, debug, CTLFLAG_RW, &tapdebug, 0, "");
170
171TUNABLE_INT("net.link.tap.devfs_cloning", &tapdclone);
172
159DEV_MODULE(if_tap, tapmodevent, NULL);
160
173DEV_MODULE(if_tap, tapmodevent, NULL);
174
175static int
176tap_clone_create(struct if_clone *ifc, int unit, caddr_t params)
177{
178 struct cdev *dev;
179 int i;
180 int extra;
181
182 if (strcmp(ifc->ifc_name, VMNET) == 0)
183 extra = VMNET_DEV_MASK;
184 else
185 extra = 0;
186
187 /* find any existing device, or allocate new unit number */
188 i = clone_create(&tapclones, &tap_cdevsw, &unit, &dev, extra);
189 if (i) {
190 dev = make_dev(&tap_cdevsw, unit2minor(unit | extra),
191 UID_ROOT, GID_WHEEL, 0600, "%s%d", ifc->ifc_name, unit);
192 if (dev != NULL) {
193 dev_ref(dev);
194 dev->si_flags |= SI_CHEAPCLONE;
195 }
196 }
197
198 tapcreate(dev);
199 return (0);
200}
201
202/* vmnet devices are tap devices in disguise */
203static int
204vmnet_clone_create(struct if_clone *ifc, int unit, caddr_t params)
205{
206 return tap_clone_create(ifc, unit, params);
207}
208
209static void
210tap_destroy(struct tap_softc *tp)
211{
212 struct ifnet *ifp = tp->tap_ifp;
213 int s;
214
215 /* Unlocked read. */
216 KASSERT(!(tp->tap_flags & TAP_OPEN),
217 ("%s flags is out of sync", ifp->if_xname));
218
219 knlist_destroy(&tp->tap_rsel.si_note);
220 destroy_dev(tp->tap_dev);
221 s = splimp();
222 ether_ifdetach(ifp);
223 if_free_type(ifp, IFT_ETHER);
224 splx(s);
225
226 mtx_destroy(&tp->tap_mtx);
227 free(tp, M_TAP);
228}
229
230static void
231tap_clone_destroy(struct ifnet *ifp)
232{
233 struct tap_softc *tp = ifp->if_softc;
234
235 mtx_lock(&tapmtx);
236 SLIST_REMOVE(&taphead, tp, tap_softc, tap_next);
237 mtx_unlock(&tapmtx);
238 tap_destroy(tp);
239}
240
241/* vmnet devices are tap devices in disguise */
242static void
243vmnet_clone_destroy(struct ifnet *ifp)
244{
245 tap_clone_destroy(ifp);
246}
247
161/*
162 * tapmodevent
163 *
164 * module event handler
165 */
166static int
167tapmodevent(module_t mod, int type, void *data)
168{
169 static eventhandler_tag eh_tag = NULL;
170 struct tap_softc *tp = NULL;
171 struct ifnet *ifp = NULL;
248/*
249 * tapmodevent
250 *
251 * module event handler
252 */
253static int
254tapmodevent(module_t mod, int type, void *data)
255{
256 static eventhandler_tag eh_tag = NULL;
257 struct tap_softc *tp = NULL;
258 struct ifnet *ifp = NULL;
172 int s;
173
174 switch (type) {
175 case MOD_LOAD:
176
177 /* intitialize device */
178
179 mtx_init(&tapmtx, "tapmtx", NULL, MTX_DEF);
180 SLIST_INIT(&taphead);
181
182 clone_setup(&tapclones);
183 eh_tag = EVENTHANDLER_REGISTER(dev_clone, tapclone, 0, 1000);
184 if (eh_tag == NULL) {
185 clone_cleanup(&tapclones);
186 mtx_destroy(&tapmtx);
187 return (ENOMEM);
188 }
259
260 switch (type) {
261 case MOD_LOAD:
262
263 /* intitialize device */
264
265 mtx_init(&tapmtx, "tapmtx", NULL, MTX_DEF);
266 SLIST_INIT(&taphead);
267
268 clone_setup(&tapclones);
269 eh_tag = EVENTHANDLER_REGISTER(dev_clone, tapclone, 0, 1000);
270 if (eh_tag == NULL) {
271 clone_cleanup(&tapclones);
272 mtx_destroy(&tapmtx);
273 return (ENOMEM);
274 }
275 if_clone_attach(&tap_cloner);
276 if_clone_attach(&vmnet_cloner);
189 return (0);
190
191 case MOD_UNLOAD:
192 /*
193 * The EBUSY algorithm here can't quite atomically
194 * guarantee that this is race-free since we have to
195 * release the tap mtx to deregister the clone handler.
196 */

--- 5 unchanged lines hidden (view full) ---

202 mtx_unlock(&tapmtx);
203 return (EBUSY);
204 }
205 mtx_unlock(&tp->tap_mtx);
206 }
207 mtx_unlock(&tapmtx);
208
209 EVENTHANDLER_DEREGISTER(dev_clone, eh_tag);
277 return (0);
278
279 case MOD_UNLOAD:
280 /*
281 * The EBUSY algorithm here can't quite atomically
282 * guarantee that this is race-free since we have to
283 * release the tap mtx to deregister the clone handler.
284 */

--- 5 unchanged lines hidden (view full) ---

290 mtx_unlock(&tapmtx);
291 return (EBUSY);
292 }
293 mtx_unlock(&tp->tap_mtx);
294 }
295 mtx_unlock(&tapmtx);
296
297 EVENTHANDLER_DEREGISTER(dev_clone, eh_tag);
298 if_clone_detach(&tap_cloner);
299 if_clone_detach(&vmnet_cloner);
210
211 mtx_lock(&tapmtx);
212 while ((tp = SLIST_FIRST(&taphead)) != NULL) {
213 SLIST_REMOVE_HEAD(&taphead, tap_next);
214 mtx_unlock(&tapmtx);
215
216 ifp = tp->tap_ifp;
217
218 TAPDEBUG("detaching %s\n", ifp->if_xname);
219
300
301 mtx_lock(&tapmtx);
302 while ((tp = SLIST_FIRST(&taphead)) != NULL) {
303 SLIST_REMOVE_HEAD(&taphead, tap_next);
304 mtx_unlock(&tapmtx);
305
306 ifp = tp->tap_ifp;
307
308 TAPDEBUG("detaching %s\n", ifp->if_xname);
309
220 /* Unlocked read. */
221 KASSERT(!(tp->tap_flags & TAP_OPEN),
222 ("%s flags is out of sync", ifp->if_xname));
223
224 knlist_destroy(&tp->tap_rsel.si_note);
225 destroy_dev(tp->tap_dev);
226 s = splimp();
227 ether_ifdetach(ifp);
228 if_free_type(ifp, IFT_ETHER);
229 splx(s);
230
231 mtx_destroy(&tp->tap_mtx);
232 free(tp, M_TAP);
310 tap_destroy(tp);
233 mtx_lock(&tapmtx);
234 }
235 mtx_unlock(&tapmtx);
236 clone_cleanup(&tapclones);
237
238 mtx_destroy(&tapmtx);
239
240 break;

--- 9 unchanged lines hidden (view full) ---

250/*
251 * DEVFS handler
252 *
253 * We need to support two kind of devices - tap and vmnet
254 */
255static void
256tapclone(void *arg, struct ucred *cred, char *name, int namelen, struct cdev **dev)
257{
311 mtx_lock(&tapmtx);
312 }
313 mtx_unlock(&tapmtx);
314 clone_cleanup(&tapclones);
315
316 mtx_destroy(&tapmtx);
317
318 break;

--- 9 unchanged lines hidden (view full) ---

328/*
329 * DEVFS handler
330 *
331 * We need to support two kind of devices - tap and vmnet
332 */
333static void
334tapclone(void *arg, struct ucred *cred, char *name, int namelen, struct cdev **dev)
335{
336 char devname[SPECNAMELEN + 1];
337 int i, unit, append_unit;
258 int extra;
338 int extra;
259 int i, unit;
260 char *device_name = name;
261
262 if (*dev != NULL)
263 return;
264
339
340 if (*dev != NULL)
341 return;
342
265 device_name = TAP;
343 /*
344 * If tap cloning is enabled, only the superuser can create
345 * an interface.
346 */
347 if (!tapdclone || priv_check_cred(cred, PRIV_NET_IFCREATE, 0) != 0)
348 return;
349
350 unit = 0;
351 append_unit = 0;
266 extra = 0;
352 extra = 0;
353
354 /* We're interested in only tap/vmnet devices. */
267 if (strcmp(name, TAP) == 0) {
268 unit = -1;
269 } else if (strcmp(name, VMNET) == 0) {
355 if (strcmp(name, TAP) == 0) {
356 unit = -1;
357 } else if (strcmp(name, VMNET) == 0) {
270 device_name = VMNET;
271 extra = VMNET_DEV_MASK;
272 unit = -1;
358 unit = -1;
273 } else if (dev_stdclone(name, NULL, device_name, &unit) != 1) {
274 device_name = VMNET;
275 extra = VMNET_DEV_MASK;
359 extra = VMNET_DEV_MASK;
276 if (dev_stdclone(name, NULL, device_name, &unit) != 1)
360 } else if (dev_stdclone(name, NULL, TAP, &unit) != 1) {
361 if (dev_stdclone(name, NULL, VMNET, &unit) != 1) {
277 return;
362 return;
363 } else {
364 extra = VMNET_DEV_MASK;
365 }
278 }
279
366 }
367
368 if (unit == -1)
369 append_unit = 1;
370
280 /* find any existing device, or allocate new unit number */
281 i = clone_create(&tapclones, &tap_cdevsw, &unit, dev, extra);
282 if (i) {
371 /* find any existing device, or allocate new unit number */
372 i = clone_create(&tapclones, &tap_cdevsw, &unit, dev, extra);
373 if (i) {
374 if (append_unit) {
375 /*
376 * We were passed 'tun' or 'tap', with no unit specified
377 * so we'll need to append it now.
378 */
379 namelen = snprintf(devname, sizeof(devname), "%s%d", name,
380 unit);
381 name = devname;
382 }
383
283 *dev = make_dev(&tap_cdevsw, unit2minor(unit | extra),
384 *dev = make_dev(&tap_cdevsw, unit2minor(unit | extra),
284 UID_ROOT, GID_WHEEL, 0600, "%s%d", device_name, unit);
385 UID_ROOT, GID_WHEEL, 0600, "%s", name);
285 if (*dev != NULL) {
286 dev_ref(*dev);
287 (*dev)->si_flags |= SI_CHEAPCLONE;
288 }
289 }
386 if (*dev != NULL) {
387 dev_ref(*dev);
388 (*dev)->si_flags |= SI_CHEAPCLONE;
389 }
390 }
391
392 if_clone_create(name, namelen, NULL);
290} /* tapclone */
291
292
293/*
294 * tapcreate
295 *
296 * to create interface
297 */

--- 82 unchanged lines hidden (view full) ---

380 error = priv_check(td, PRIV_NET_TAP);
381 if (error)
382 return (error);
383 }
384
385 if ((dev2unit(dev) & CLONE_UNITMASK) > TAPMAXUNIT)
386 return (ENXIO);
387
393} /* tapclone */
394
395
396/*
397 * tapcreate
398 *
399 * to create interface
400 */

--- 82 unchanged lines hidden (view full) ---

483 error = priv_check(td, PRIV_NET_TAP);
484 if (error)
485 return (error);
486 }
487
488 if ((dev2unit(dev) & CLONE_UNITMASK) > TAPMAXUNIT)
489 return (ENXIO);
490
388 /*
389 * XXXRW: Non-atomic test-and-set of si_drv1. Currently protected
390 * by Giant, but the race actually exists under memory pressure as
391 * well even when running with Giant, as malloc() may sleep.
392 */
393 tp = dev->si_drv1;
491 tp = dev->si_drv1;
394 if (tp == NULL) {
395 tapcreate(dev);
396 tp = dev->si_drv1;
397 }
398
399 mtx_lock(&tp->tap_mtx);
400 if (tp->tap_flags & TAP_OPEN) {
401 mtx_unlock(&tp->tap_mtx);
402 return (EBUSY);
403 }
404
405 bcopy(IF_LLADDR(tp->tap_ifp), tp->ether_addr, sizeof(tp->ether_addr));

--- 601 unchanged lines hidden ---
492
493 mtx_lock(&tp->tap_mtx);
494 if (tp->tap_flags & TAP_OPEN) {
495 mtx_unlock(&tp->tap_mtx);
496 return (EBUSY);
497 }
498
499 bcopy(IF_LLADDR(tp->tap_ifp), tp->ether_addr, sizeof(tp->ether_addr));

--- 601 unchanged lines hidden ---