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 --- |