xref: /illumos-gate/usr/src/uts/common/io/dls/dls_mgmt.c (revision 5328fc53d11d7151861fa272e4fb0248b8f0e145)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 /*
26  * Copyright (c) 2016 by Delphix. All rights reserved.
27  */
28 
29 /*
30  * Datalink management routines.
31  */
32 
33 #include <sys/types.h>
34 #include <sys/door.h>
35 #include <sys/zone.h>
36 #include <sys/modctl.h>
37 #include <sys/file.h>
38 #include <sys/modhash.h>
39 #include <sys/kstat.h>
40 #include <sys/vnode.h>
41 #include <sys/cmn_err.h>
42 #include <sys/softmac.h>
43 #include <sys/dls.h>
44 #include <sys/dls_impl.h>
45 #include <sys/stropts.h>
46 #include <sys/netstack.h>
47 #include <inet/iptun/iptun_impl.h>
48 
49 /*
50  * This vanity name management module is treated as part of the GLD framework
51  * and we don't hold any GLD framework lock across a call to any mac
52  * function that needs to acquire the mac perimeter. The hierarchy is
53  * mac perimeter -> framework locks
54  */
55 
56 typedef struct dls_stack {
57 	zoneid_t	dlss_zoneid;
58 } dls_stack_t;
59 
60 static kmem_cache_t	*i_dls_devnet_cachep;
61 static kmutex_t		i_dls_mgmt_lock;
62 static krwlock_t	i_dls_devnet_lock;
63 static mod_hash_t	*i_dls_devnet_id_hash;
64 static mod_hash_t	*i_dls_devnet_hash;
65 
66 boolean_t		devnet_need_rebuild;
67 
68 #define	VLAN_HASHSZ	67	/* prime */
69 
70 /*
71  * The following macros take a link name without the trailing PPA as input.
72  * Opening a /dev/net node with one of these names causes a tunnel link to be
73  * implicitly created in dls_devnet_hold_by_name() for backward compatibility
74  * with Solaris 10 and prior.
75  */
76 #define	IS_IPV4_TUN(name)	(strcmp((name), "ip.tun") == 0)
77 #define	IS_IPV6_TUN(name)	(strcmp((name), "ip6.tun") == 0)
78 #define	IS_6TO4_TUN(name)	(strcmp((name), "ip.6to4tun") == 0)
79 #define	IS_IPTUN_LINK(name)	(					\
80     IS_IPV4_TUN(name) || IS_IPV6_TUN(name) || IS_6TO4_TUN(name))
81 
82 /* Upcall door handle */
83 static door_handle_t	dls_mgmt_dh = NULL;
84 
85 /* dls_devnet_t dd_flags */
86 #define	DD_CONDEMNED		0x1
87 #define	DD_IMPLICIT_IPTUN	0x2 /* Implicitly-created ip*.*tun* tunnel */
88 
89 /*
90  * This structure is used to keep the <linkid, macname> mapping.
91  * This structure itself is not protected by the mac perimeter, but is
92  * protected by the dd_mutex and i_dls_devnet_lock. Thus most of the
93  * functions manipulating this structure such as dls_devnet_set/unset etc.
94  * may be called while not holding the mac perimeter.
95  */
96 typedef struct dls_devnet_s {
97 	datalink_id_t	dd_linkid;
98 	char		dd_linkname[MAXLINKNAMELEN];
99 	char		dd_mac[MAXNAMELEN];
100 	kstat_t		*dd_ksp;	/* kstat in owner_zid */
101 	kstat_t		*dd_zone_ksp;	/* in dd_zid if != owner_zid */
102 	uint32_t	dd_ref;
103 	kmutex_t	dd_mutex;
104 	kcondvar_t	dd_cv;
105 	uint32_t	dd_tref;
106 	uint_t		dd_flags;
107 	zoneid_t	dd_owner_zid;	/* zone where node was created */
108 	zoneid_t	dd_zid;		/* current zone */
109 	boolean_t	dd_prop_loaded;
110 	taskqid_t	dd_prop_taskid;
111 } dls_devnet_t;
112 
113 static int i_dls_devnet_create_iptun(const char *, const char *,
114     datalink_id_t *);
115 static int i_dls_devnet_destroy_iptun(datalink_id_t);
116 static int i_dls_devnet_setzid(dls_devnet_t *, zoneid_t, boolean_t);
117 static int dls_devnet_unset(const char *, datalink_id_t *, boolean_t);
118 
119 /*ARGSUSED*/
120 static int
121 i_dls_devnet_constructor(void *buf, void *arg, int kmflag)
122 {
123 	dls_devnet_t	*ddp = buf;
124 
125 	bzero(buf, sizeof (dls_devnet_t));
126 	mutex_init(&ddp->dd_mutex, NULL, MUTEX_DEFAULT, NULL);
127 	cv_init(&ddp->dd_cv, NULL, CV_DEFAULT, NULL);
128 	return (0);
129 }
130 
131 /*ARGSUSED*/
132 static void
133 i_dls_devnet_destructor(void *buf, void *arg)
134 {
135 	dls_devnet_t	*ddp = buf;
136 
137 	ASSERT(ddp->dd_ksp == NULL);
138 	ASSERT(ddp->dd_ref == 0);
139 	ASSERT(ddp->dd_tref == 0);
140 	mutex_destroy(&ddp->dd_mutex);
141 	cv_destroy(&ddp->dd_cv);
142 }
143 
144 /* ARGSUSED */
145 static int
146 dls_zone_remove(datalink_id_t linkid, void *arg)
147 {
148 	dls_devnet_t *ddp;
149 
150 	if (dls_devnet_hold_tmp(linkid, &ddp) == 0) {
151 		(void) dls_devnet_setzid(ddp, GLOBAL_ZONEID);
152 		dls_devnet_rele_tmp(ddp);
153 	}
154 	return (0);
155 }
156 
157 /* ARGSUSED */
158 static void *
159 dls_stack_init(netstackid_t stackid, netstack_t *ns)
160 {
161 	dls_stack_t *dlss;
162 
163 	dlss = kmem_zalloc(sizeof (*dlss), KM_SLEEP);
164 	dlss->dlss_zoneid = netstackid_to_zoneid(stackid);
165 	return (dlss);
166 }
167 
168 /* ARGSUSED */
169 static void
170 dls_stack_shutdown(netstackid_t stackid, void *arg)
171 {
172 	dls_stack_t	*dlss = (dls_stack_t *)arg;
173 
174 	/* Move remaining datalinks in this zone back to the global zone. */
175 	(void) zone_datalink_walk(dlss->dlss_zoneid, dls_zone_remove, NULL);
176 }
177 
178 /* ARGSUSED */
179 static void
180 dls_stack_fini(netstackid_t stackid, void *arg)
181 {
182 	dls_stack_t	*dlss = (dls_stack_t *)arg;
183 
184 	kmem_free(dlss, sizeof (*dlss));
185 }
186 
187 /*
188  * Module initialization and finalization functions.
189  */
190 void
191 dls_mgmt_init(void)
192 {
193 	mutex_init(&i_dls_mgmt_lock, NULL, MUTEX_DEFAULT, NULL);
194 	rw_init(&i_dls_devnet_lock, NULL, RW_DEFAULT, NULL);
195 
196 	/*
197 	 * Create a kmem_cache of dls_devnet_t structures.
198 	 */
199 	i_dls_devnet_cachep = kmem_cache_create("dls_devnet_cache",
200 	    sizeof (dls_devnet_t), 0, i_dls_devnet_constructor,
201 	    i_dls_devnet_destructor, NULL, NULL, NULL, 0);
202 	ASSERT(i_dls_devnet_cachep != NULL);
203 
204 	/*
205 	 * Create a hash table, keyed by dd_linkid, of dls_devnet_t.
206 	 */
207 	i_dls_devnet_id_hash = mod_hash_create_idhash("dls_devnet_id_hash",
208 	    VLAN_HASHSZ, mod_hash_null_valdtor);
209 
210 	/*
211 	 * Create a hash table, keyed by dd_mac
212 	 */
213 	i_dls_devnet_hash = mod_hash_create_extended("dls_devnet_hash",
214 	    VLAN_HASHSZ, mod_hash_null_keydtor, mod_hash_null_valdtor,
215 	    mod_hash_bystr, NULL, mod_hash_strkey_cmp, KM_SLEEP);
216 
217 	devnet_need_rebuild = B_FALSE;
218 
219 	netstack_register(NS_DLS, dls_stack_init, dls_stack_shutdown,
220 	    dls_stack_fini);
221 }
222 
223 void
224 dls_mgmt_fini(void)
225 {
226 	netstack_unregister(NS_DLS);
227 	mod_hash_destroy_hash(i_dls_devnet_hash);
228 	mod_hash_destroy_hash(i_dls_devnet_id_hash);
229 	kmem_cache_destroy(i_dls_devnet_cachep);
230 	rw_destroy(&i_dls_devnet_lock);
231 	mutex_destroy(&i_dls_mgmt_lock);
232 }
233 
234 int
235 dls_mgmt_door_set(boolean_t start)
236 {
237 	int	err;
238 
239 	/* handle daemon restart */
240 	mutex_enter(&i_dls_mgmt_lock);
241 	if (dls_mgmt_dh != NULL) {
242 		door_ki_rele(dls_mgmt_dh);
243 		dls_mgmt_dh = NULL;
244 	}
245 
246 	if (start && ((err = door_ki_open(DLMGMT_DOOR, &dls_mgmt_dh)) != 0)) {
247 		mutex_exit(&i_dls_mgmt_lock);
248 		return (err);
249 	}
250 
251 	mutex_exit(&i_dls_mgmt_lock);
252 
253 	/*
254 	 * Create and associate <link name, linkid> mapping for network devices
255 	 * which are already attached before the daemon is started.
256 	 */
257 	if (start)
258 		softmac_recreate();
259 	return (0);
260 }
261 
262 static boolean_t
263 i_dls_mgmt_door_revoked(door_handle_t dh)
264 {
265 	struct door_info info;
266 	extern int sys_shutdown;
267 
268 	ASSERT(dh != NULL);
269 
270 	if (sys_shutdown) {
271 		cmn_err(CE_NOTE, "dls_mgmt_door: shutdown observed\n");
272 		return (B_TRUE);
273 	}
274 
275 	if (door_ki_info(dh, &info) != 0)
276 		return (B_TRUE);
277 
278 	return ((info.di_attributes & DOOR_REVOKED) != 0);
279 }
280 
281 /*
282  * Upcall to the datalink management daemon (dlmgmtd).
283  */
284 static int
285 i_dls_mgmt_upcall(void *arg, size_t asize, void *rbuf, size_t rsize)
286 {
287 	door_arg_t			darg, save_arg;
288 	door_handle_t			dh;
289 	int				err;
290 	int				retry = 0;
291 
292 #define	MAXRETRYNUM	3
293 
294 	ASSERT(arg);
295 	darg.data_ptr = arg;
296 	darg.data_size = asize;
297 	darg.desc_ptr = NULL;
298 	darg.desc_num = 0;
299 	darg.rbuf = rbuf;
300 	darg.rsize = rsize;
301 	save_arg = darg;
302 
303 retry:
304 	mutex_enter(&i_dls_mgmt_lock);
305 	dh = dls_mgmt_dh;
306 	if ((dh == NULL) || i_dls_mgmt_door_revoked(dh)) {
307 		mutex_exit(&i_dls_mgmt_lock);
308 		return (EBADF);
309 	}
310 	door_ki_hold(dh);
311 	mutex_exit(&i_dls_mgmt_lock);
312 
313 	for (;;) {
314 		retry++;
315 		if ((err = door_ki_upcall_limited(dh, &darg, zone_kcred(),
316 		    SIZE_MAX, 0)) == 0)
317 			break;
318 
319 		/*
320 		 * handle door call errors
321 		 */
322 		darg = save_arg;
323 		switch (err) {
324 		case EINTR:
325 			/*
326 			 * If the operation which caused this door upcall gets
327 			 * interrupted, return directly.
328 			 */
329 			goto done;
330 		case EAGAIN:
331 			/*
332 			 * Repeat upcall if the maximum attempt limit has not
333 			 * been reached.
334 			 */
335 			if (retry < MAXRETRYNUM) {
336 				delay(2 * hz);
337 				break;
338 			}
339 			cmn_err(CE_WARN, "dls: dlmgmtd fatal error %d\n", err);
340 			goto done;
341 		default:
342 			/* A fatal door error */
343 			if (i_dls_mgmt_door_revoked(dh)) {
344 				cmn_err(CE_NOTE,
345 				    "dls: dlmgmtd door service revoked\n");
346 
347 				if (retry < MAXRETRYNUM) {
348 					door_ki_rele(dh);
349 					goto retry;
350 				}
351 			}
352 			cmn_err(CE_WARN, "dls: dlmgmtd fatal error %d\n", err);
353 			goto done;
354 		}
355 	}
356 
357 	if (darg.rbuf != rbuf) {
358 		/*
359 		 * The size of the input rbuf was not big enough, so the
360 		 * upcall allocated the rbuf itself.  If this happens, assume
361 		 * that this was an invalid door call request.
362 		 */
363 		kmem_free(darg.rbuf, darg.rsize);
364 		err = ENOSPC;
365 		goto done;
366 	}
367 
368 	if (darg.rsize != rsize) {
369 		err = EINVAL;
370 		goto done;
371 	}
372 
373 	err = ((dlmgmt_retval_t *)rbuf)->lr_err;
374 
375 done:
376 	door_ki_rele(dh);
377 	return (err);
378 }
379 
380 /*
381  * Request the datalink management daemon to create a link with the attributes
382  * below.  Upon success, zero is returned and linkidp contains the linkid for
383  * the new link; otherwise, an errno is returned.
384  *
385  *     - dev		physical dev_t.  required for all physical links,
386  *		        including GLDv3 links.  It will be used to force the
387  *		        attachment of a physical device, hence the
388  *		        registration of its mac
389  *     - class		datalink class
390  *     - media type	media type; DL_OTHER means unknown
391  *     - persist	whether to persist the datalink
392  */
393 int
394 dls_mgmt_create(const char *devname, dev_t dev, datalink_class_t class,
395     uint32_t media, boolean_t persist, datalink_id_t *linkidp)
396 {
397 	dlmgmt_upcall_arg_create_t	create;
398 	dlmgmt_create_retval_t		retval;
399 	int				err;
400 
401 	create.ld_cmd = DLMGMT_CMD_DLS_CREATE;
402 	create.ld_class = class;
403 	create.ld_media = media;
404 	create.ld_phymaj = getmajor(dev);
405 	create.ld_phyinst = getminor(dev);
406 	create.ld_persist = persist;
407 	if (strlcpy(create.ld_devname, devname, sizeof (create.ld_devname)) >=
408 	    sizeof (create.ld_devname))
409 		return (EINVAL);
410 
411 	if ((err = i_dls_mgmt_upcall(&create, sizeof (create), &retval,
412 	    sizeof (retval))) == 0) {
413 		*linkidp = retval.lr_linkid;
414 	}
415 	return (err);
416 }
417 
418 /*
419  * Request the datalink management daemon to destroy the specified link.
420  * Returns zero upon success, or an errno upon failure.
421  */
422 int
423 dls_mgmt_destroy(datalink_id_t linkid, boolean_t persist)
424 {
425 	dlmgmt_upcall_arg_destroy_t	destroy;
426 	dlmgmt_destroy_retval_t		retval;
427 
428 	destroy.ld_cmd = DLMGMT_CMD_DLS_DESTROY;
429 	destroy.ld_linkid = linkid;
430 	destroy.ld_persist = persist;
431 
432 	return (i_dls_mgmt_upcall(&destroy, sizeof (destroy),
433 	    &retval, sizeof (retval)));
434 }
435 
436 /*
437  * Request the datalink management daemon to verify/update the information
438  * for a physical link.  Upon success, get its linkid.
439  *
440  *     - media type	media type
441  *     - novanity	whether this physical datalink supports vanity naming.
442  *			physical links that do not use the GLDv3 MAC plugin
443  *			cannot suport vanity naming
444  *
445  * This function could fail with ENOENT or EEXIST.  Two cases return EEXIST:
446  *
447  * 1. A link with devname already exists, but the media type does not match.
448  *    In this case, mediap will bee set to the media type of the existing link.
449  * 2. A link with devname already exists, but its link name does not match
450  *    the device name, although this link does not support vanity naming.
451  */
452 int
453 dls_mgmt_update(const char *devname, uint32_t media, boolean_t novanity,
454     uint32_t *mediap, datalink_id_t *linkidp)
455 {
456 	dlmgmt_upcall_arg_update_t	update;
457 	dlmgmt_update_retval_t		retval;
458 	int				err;
459 
460 	update.ld_cmd = DLMGMT_CMD_DLS_UPDATE;
461 
462 	if (strlcpy(update.ld_devname, devname, sizeof (update.ld_devname)) >=
463 	    sizeof (update.ld_devname))
464 		return (EINVAL);
465 
466 	update.ld_media = media;
467 	update.ld_novanity = novanity;
468 
469 	if ((err = i_dls_mgmt_upcall(&update, sizeof (update), &retval,
470 	    sizeof (retval))) == EEXIST) {
471 		*linkidp = retval.lr_linkid;
472 		*mediap = retval.lr_media;
473 	} else if (err == 0) {
474 		*linkidp = retval.lr_linkid;
475 	}
476 
477 	return (err);
478 }
479 
480 /*
481  * Request the datalink management daemon to get the information for a link.
482  * Returns zero upon success, or an errno upon failure.
483  *
484  * Only fills in information for argument pointers that are non-NULL.
485  * Note that the link argument is expected to be MAXLINKNAMELEN bytes.
486  */
487 int
488 dls_mgmt_get_linkinfo(datalink_id_t linkid, char *link,
489     datalink_class_t *classp, uint32_t *mediap, uint32_t *flagsp)
490 {
491 	dlmgmt_door_getname_t	getname;
492 	dlmgmt_getname_retval_t	retval;
493 	int			err, len;
494 
495 	getname.ld_cmd = DLMGMT_CMD_GETNAME;
496 	getname.ld_linkid = linkid;
497 
498 	if ((err = i_dls_mgmt_upcall(&getname, sizeof (getname), &retval,
499 	    sizeof (retval))) != 0) {
500 		return (err);
501 	}
502 
503 	len = strlen(retval.lr_link);
504 	if (len <= 1 || len >= MAXLINKNAMELEN)
505 		return (EINVAL);
506 
507 	if (link != NULL)
508 		(void) strlcpy(link, retval.lr_link, MAXLINKNAMELEN);
509 	if (classp != NULL)
510 		*classp = retval.lr_class;
511 	if (mediap != NULL)
512 		*mediap = retval.lr_media;
513 	if (flagsp != NULL)
514 		*flagsp = retval.lr_flags;
515 	return (0);
516 }
517 
518 /*
519  * Request the datalink management daemon to get the linkid for a link.
520  * Returns a non-zero error code on failure.  The linkid argument is only
521  * set on success (when zero is returned.)
522  */
523 int
524 dls_mgmt_get_linkid(const char *link, datalink_id_t *linkid)
525 {
526 	dlmgmt_door_getlinkid_t		getlinkid;
527 	dlmgmt_getlinkid_retval_t	retval;
528 	int				err;
529 
530 	getlinkid.ld_cmd = DLMGMT_CMD_GETLINKID;
531 	(void) strlcpy(getlinkid.ld_link, link, MAXLINKNAMELEN);
532 
533 	if ((err = i_dls_mgmt_upcall(&getlinkid, sizeof (getlinkid), &retval,
534 	    sizeof (retval))) == 0) {
535 		*linkid = retval.lr_linkid;
536 	}
537 	return (err);
538 }
539 
540 datalink_id_t
541 dls_mgmt_get_next(datalink_id_t linkid, datalink_class_t class,
542     datalink_media_t dmedia, uint32_t flags)
543 {
544 	dlmgmt_door_getnext_t	getnext;
545 	dlmgmt_getnext_retval_t	retval;
546 
547 	getnext.ld_cmd = DLMGMT_CMD_GETNEXT;
548 	getnext.ld_class = class;
549 	getnext.ld_dmedia = dmedia;
550 	getnext.ld_flags = flags;
551 	getnext.ld_linkid = linkid;
552 
553 	if (i_dls_mgmt_upcall(&getnext, sizeof (getnext), &retval,
554 	    sizeof (retval)) != 0) {
555 		return (DATALINK_INVALID_LINKID);
556 	}
557 
558 	return (retval.lr_linkid);
559 }
560 
561 static int
562 i_dls_mgmt_get_linkattr(const datalink_id_t linkid, const char *attr,
563     void *attrval, size_t *attrszp)
564 {
565 	dlmgmt_upcall_arg_getattr_t	getattr;
566 	dlmgmt_getattr_retval_t		retval;
567 	int				err;
568 
569 	getattr.ld_cmd = DLMGMT_CMD_DLS_GETATTR;
570 	getattr.ld_linkid = linkid;
571 	(void) strlcpy(getattr.ld_attr, attr, MAXLINKATTRLEN);
572 
573 	if ((err = i_dls_mgmt_upcall(&getattr, sizeof (getattr), &retval,
574 	    sizeof (retval))) == 0) {
575 		if (*attrszp < retval.lr_attrsz)
576 			return (EINVAL);
577 		*attrszp = retval.lr_attrsz;
578 		bcopy(retval.lr_attrval, attrval, retval.lr_attrsz);
579 	}
580 
581 	return (err);
582 }
583 
584 /*
585  * Note that this function can only get devp successfully for non-VLAN link.
586  */
587 int
588 dls_mgmt_get_phydev(datalink_id_t linkid, dev_t *devp)
589 {
590 	uint64_t	maj, inst;
591 	size_t		attrsz = sizeof (uint64_t);
592 
593 	if (i_dls_mgmt_get_linkattr(linkid, FPHYMAJ, &maj, &attrsz) != 0 ||
594 	    attrsz != sizeof (uint64_t) ||
595 	    i_dls_mgmt_get_linkattr(linkid, FPHYINST, &inst, &attrsz) != 0 ||
596 	    attrsz != sizeof (uint64_t)) {
597 		return (EINVAL);
598 	}
599 
600 	*devp = makedevice((major_t)maj, (minor_t)inst);
601 	return (0);
602 }
603 
604 /*
605  * Request the datalink management daemon to push in
606  * all properties associated with the link.
607  * Returns a non-zero error code on failure.
608  */
609 int
610 dls_mgmt_linkprop_init(datalink_id_t linkid)
611 {
612 	dlmgmt_door_linkprop_init_t	li;
613 	dlmgmt_linkprop_init_retval_t	retval;
614 	int				err;
615 
616 	li.ld_cmd = DLMGMT_CMD_LINKPROP_INIT;
617 	li.ld_linkid = linkid;
618 
619 	err = i_dls_mgmt_upcall(&li, sizeof (li), &retval, sizeof (retval));
620 	return (err);
621 }
622 
623 static void
624 dls_devnet_prop_task(void *arg)
625 {
626 	dls_devnet_t		*ddp = arg;
627 
628 	(void) dls_mgmt_linkprop_init(ddp->dd_linkid);
629 
630 	mutex_enter(&ddp->dd_mutex);
631 	ddp->dd_prop_loaded = B_TRUE;
632 	ddp->dd_prop_taskid = 0;
633 	cv_broadcast(&ddp->dd_cv);
634 	mutex_exit(&ddp->dd_mutex);
635 }
636 
637 /*
638  * Ensure property loading task is completed.
639  */
640 void
641 dls_devnet_prop_task_wait(dls_dl_handle_t ddp)
642 {
643 	mutex_enter(&ddp->dd_mutex);
644 	while (ddp->dd_prop_taskid != 0)
645 		cv_wait(&ddp->dd_cv, &ddp->dd_mutex);
646 	mutex_exit(&ddp->dd_mutex);
647 }
648 
649 void
650 dls_devnet_rele_tmp(dls_dl_handle_t dlh)
651 {
652 	dls_devnet_t		*ddp = dlh;
653 
654 	mutex_enter(&ddp->dd_mutex);
655 	ASSERT(ddp->dd_tref != 0);
656 	if (--ddp->dd_tref == 0)
657 		cv_signal(&ddp->dd_cv);
658 	mutex_exit(&ddp->dd_mutex);
659 }
660 
661 int
662 dls_devnet_hold_link(datalink_id_t linkid, dls_dl_handle_t *ddhp,
663     dls_link_t **dlpp)
664 {
665 	dls_dl_handle_t	dlh;
666 	dls_link_t	*dlp;
667 	int		err;
668 
669 	if ((err = dls_devnet_hold_tmp(linkid, &dlh)) != 0)
670 		return (err);
671 
672 	if ((err = dls_link_hold(dls_devnet_mac(dlh), &dlp)) != 0) {
673 		dls_devnet_rele_tmp(dlh);
674 		return (err);
675 	}
676 
677 	ASSERT(MAC_PERIM_HELD(dlp->dl_mh));
678 
679 	*ddhp = dlh;
680 	*dlpp = dlp;
681 	return (0);
682 }
683 
684 void
685 dls_devnet_rele_link(dls_dl_handle_t dlh, dls_link_t *dlp)
686 {
687 	ASSERT(MAC_PERIM_HELD(dlp->dl_mh));
688 
689 	dls_link_rele(dlp);
690 	dls_devnet_rele_tmp(dlh);
691 }
692 
693 /*
694  * "link" kstats related functions.
695  */
696 
697 /*
698  * Query the "link" kstats.
699  *
700  * We may be called from the kstat subsystem in an arbitrary context.
701  * If the caller is the stack, the context could be an upcall data
702  * thread. Hence we can't acquire the mac perimeter in this function
703  * for fear of deadlock.
704  */
705 static int
706 dls_devnet_stat_update(kstat_t *ksp, int rw)
707 {
708 	datalink_id_t	linkid = (datalink_id_t)(uintptr_t)ksp->ks_private;
709 	dls_devnet_t	*ddp;
710 	dls_link_t	*dlp;
711 	int		err;
712 
713 	if ((err = dls_devnet_hold_tmp(linkid, &ddp)) != 0) {
714 		return (err);
715 	}
716 
717 	/*
718 	 * If a device detach happens at this time, it will block in
719 	 * dls_devnet_unset since the dd_tref has been bumped in
720 	 * dls_devnet_hold_tmp(). So the access to 'dlp' is safe even though
721 	 * we don't hold the mac perimeter.
722 	 */
723 	if (mod_hash_find(i_dls_link_hash, (mod_hash_key_t)ddp->dd_mac,
724 	    (mod_hash_val_t *)&dlp) != 0) {
725 		dls_devnet_rele_tmp(ddp);
726 		return (ENOENT);
727 	}
728 
729 	err = dls_stat_update(ksp, dlp, rw);
730 
731 	dls_devnet_rele_tmp(ddp);
732 	return (err);
733 }
734 
735 /*
736  * Create the "link" kstats.
737  */
738 static void
739 dls_devnet_stat_create(dls_devnet_t *ddp, zoneid_t zoneid)
740 {
741 	kstat_t	*ksp;
742 
743 	if (dls_stat_create("link", 0, ddp->dd_linkname, zoneid,
744 	    dls_devnet_stat_update, (void *)(uintptr_t)ddp->dd_linkid,
745 	    &ksp) == 0) {
746 		ASSERT(ksp != NULL);
747 		if (zoneid == ddp->dd_owner_zid) {
748 			ASSERT(ddp->dd_ksp == NULL);
749 			ddp->dd_ksp = ksp;
750 		} else {
751 			ASSERT(ddp->dd_zone_ksp == NULL);
752 			ddp->dd_zone_ksp = ksp;
753 		}
754 	}
755 }
756 
757 /*
758  * Destroy the "link" kstats.
759  */
760 static void
761 dls_devnet_stat_destroy(dls_devnet_t *ddp, zoneid_t zoneid)
762 {
763 	if (zoneid == ddp->dd_owner_zid) {
764 		if (ddp->dd_ksp != NULL) {
765 			kstat_delete(ddp->dd_ksp);
766 			ddp->dd_ksp = NULL;
767 		}
768 	} else {
769 		if (ddp->dd_zone_ksp != NULL) {
770 			kstat_delete(ddp->dd_zone_ksp);
771 			ddp->dd_zone_ksp = NULL;
772 		}
773 	}
774 }
775 
776 /*
777  * The link has been renamed. Destroy the old non-legacy kstats ("link kstats")
778  * and create the new set using the new name.
779  */
780 static void
781 dls_devnet_stat_rename(dls_devnet_t *ddp)
782 {
783 	if (ddp->dd_ksp != NULL) {
784 		kstat_delete(ddp->dd_ksp);
785 		ddp->dd_ksp = NULL;
786 	}
787 	/* We can't rename a link while it's assigned to a non-global zone. */
788 	ASSERT(ddp->dd_zone_ksp == NULL);
789 	dls_devnet_stat_create(ddp, ddp->dd_owner_zid);
790 }
791 
792 /*
793  * Associate a linkid with a given link (identified by macname)
794  */
795 static int
796 dls_devnet_set(const char *macname, datalink_id_t linkid, zoneid_t zoneid,
797     dls_devnet_t **ddpp)
798 {
799 	dls_devnet_t		*ddp = NULL;
800 	datalink_class_t	class;
801 	int			err;
802 	boolean_t		stat_create = B_FALSE;
803 	char			linkname[MAXLINKNAMELEN];
804 
805 	rw_enter(&i_dls_devnet_lock, RW_WRITER);
806 
807 	/*
808 	 * Don't allow callers to set a link name with a linkid that already
809 	 * has a name association (that's what rename is for).
810 	 */
811 	if (linkid != DATALINK_INVALID_LINKID) {
812 		if (mod_hash_find(i_dls_devnet_id_hash,
813 		    (mod_hash_key_t)(uintptr_t)linkid,
814 		    (mod_hash_val_t *)&ddp) == 0) {
815 			err = EEXIST;
816 			goto done;
817 		}
818 		if ((err = dls_mgmt_get_linkinfo(linkid, linkname, &class,
819 		    NULL, NULL)) != 0)
820 			goto done;
821 	}
822 
823 	if ((err = mod_hash_find(i_dls_devnet_hash,
824 	    (mod_hash_key_t)macname, (mod_hash_val_t *)&ddp)) == 0) {
825 		if (ddp->dd_linkid != DATALINK_INVALID_LINKID) {
826 			err = EEXIST;
827 			goto done;
828 		}
829 
830 		/*
831 		 * This might be a physical link that has already
832 		 * been created, but which does not have a linkid
833 		 * because dlmgmtd was not running when it was created.
834 		 */
835 		if (linkid == DATALINK_INVALID_LINKID ||
836 		    class != DATALINK_CLASS_PHYS) {
837 			err = EINVAL;
838 			goto done;
839 		}
840 	} else {
841 		ddp = kmem_cache_alloc(i_dls_devnet_cachep, KM_SLEEP);
842 		ddp->dd_tref = 0;
843 		ddp->dd_ref++;
844 		ddp->dd_owner_zid = zoneid;
845 		(void) strlcpy(ddp->dd_mac, macname, sizeof (ddp->dd_mac));
846 		VERIFY(mod_hash_insert(i_dls_devnet_hash,
847 		    (mod_hash_key_t)ddp->dd_mac, (mod_hash_val_t)ddp) == 0);
848 	}
849 
850 	if (linkid != DATALINK_INVALID_LINKID) {
851 		ddp->dd_linkid = linkid;
852 		(void) strlcpy(ddp->dd_linkname, linkname,
853 		    sizeof (ddp->dd_linkname));
854 		VERIFY(mod_hash_insert(i_dls_devnet_id_hash,
855 		    (mod_hash_key_t)(uintptr_t)linkid,
856 		    (mod_hash_val_t)ddp) == 0);
857 		devnet_need_rebuild = B_TRUE;
858 		stat_create = B_TRUE;
859 		mutex_enter(&ddp->dd_mutex);
860 		if (!ddp->dd_prop_loaded && (ddp->dd_prop_taskid == 0)) {
861 			ddp->dd_prop_taskid = taskq_dispatch(system_taskq,
862 			    dls_devnet_prop_task, ddp, TQ_SLEEP);
863 		}
864 		mutex_exit(&ddp->dd_mutex);
865 	}
866 	err = 0;
867 done:
868 	/*
869 	 * It is safe to drop the i_dls_devnet_lock at this point. In the case
870 	 * of physical devices, the softmac framework will fail the device
871 	 * detach based on the smac_state or smac_hold_cnt. Other cases like
872 	 * vnic and aggr use their own scheme to serialize creates and deletes
873 	 * and ensure that *ddp is valid.
874 	 */
875 	rw_exit(&i_dls_devnet_lock);
876 	if (err == 0) {
877 		if (zoneid != GLOBAL_ZONEID &&
878 		    (err = i_dls_devnet_setzid(ddp, zoneid, B_FALSE)) != 0)
879 			(void) dls_devnet_unset(macname, &linkid, B_TRUE);
880 		/*
881 		 * The kstat subsystem holds its own locks (rather perimeter)
882 		 * before calling the ks_update (dls_devnet_stat_update) entry
883 		 * point which in turn grabs the i_dls_devnet_lock. So the
884 		 * lock hierarchy is kstat locks -> i_dls_devnet_lock.
885 		 */
886 		if (stat_create)
887 			dls_devnet_stat_create(ddp, zoneid);
888 		if (ddpp != NULL)
889 			*ddpp = ddp;
890 	}
891 	return (err);
892 }
893 
894 /*
895  * Disassociate a linkid with a given link (identified by macname)
896  * This waits until temporary references to the dls_devnet_t are gone.
897  */
898 static int
899 dls_devnet_unset(const char *macname, datalink_id_t *id, boolean_t wait)
900 {
901 	dls_devnet_t	*ddp;
902 	int		err;
903 	mod_hash_val_t	val;
904 
905 	rw_enter(&i_dls_devnet_lock, RW_WRITER);
906 	if ((err = mod_hash_find(i_dls_devnet_hash,
907 	    (mod_hash_key_t)macname, (mod_hash_val_t *)&ddp)) != 0) {
908 		ASSERT(err == MH_ERR_NOTFOUND);
909 		rw_exit(&i_dls_devnet_lock);
910 		return (ENOENT);
911 	}
912 
913 	mutex_enter(&ddp->dd_mutex);
914 
915 	/*
916 	 * Make sure downcalls into softmac_create or softmac_destroy from
917 	 * devfs don't cv_wait on any devfs related condition for fear of
918 	 * deadlock. Return EBUSY if the asynchronous thread started for
919 	 * property loading as part of the post attach hasn't yet completed.
920 	 */
921 	ASSERT(ddp->dd_ref != 0);
922 	if ((ddp->dd_ref != 1) || (!wait &&
923 	    (ddp->dd_tref != 0 || ddp->dd_prop_taskid != 0))) {
924 		mutex_exit(&ddp->dd_mutex);
925 		rw_exit(&i_dls_devnet_lock);
926 		return (EBUSY);
927 	}
928 
929 	ddp->dd_flags |= DD_CONDEMNED;
930 	ddp->dd_ref--;
931 	*id = ddp->dd_linkid;
932 
933 	if (ddp->dd_zid != GLOBAL_ZONEID)
934 		(void) i_dls_devnet_setzid(ddp, GLOBAL_ZONEID, B_FALSE);
935 
936 	/*
937 	 * Remove this dls_devnet_t from the hash table.
938 	 */
939 	VERIFY(mod_hash_remove(i_dls_devnet_hash,
940 	    (mod_hash_key_t)ddp->dd_mac, &val) == 0);
941 
942 	if (ddp->dd_linkid != DATALINK_INVALID_LINKID) {
943 		VERIFY(mod_hash_remove(i_dls_devnet_id_hash,
944 		    (mod_hash_key_t)(uintptr_t)ddp->dd_linkid, &val) == 0);
945 
946 		devnet_need_rebuild = B_TRUE;
947 	}
948 	rw_exit(&i_dls_devnet_lock);
949 
950 	if (wait) {
951 		/*
952 		 * Wait until all temporary references are released.
953 		 */
954 		while ((ddp->dd_tref != 0) || (ddp->dd_prop_taskid != 0))
955 			cv_wait(&ddp->dd_cv, &ddp->dd_mutex);
956 	} else {
957 		ASSERT(ddp->dd_tref == 0 &&
958 		    ddp->dd_prop_taskid == (taskqid_t)NULL);
959 	}
960 
961 	if (ddp->dd_linkid != DATALINK_INVALID_LINKID)
962 		dls_devnet_stat_destroy(ddp, ddp->dd_owner_zid);
963 
964 	ddp->dd_prop_loaded = B_FALSE;
965 	ddp->dd_linkid = DATALINK_INVALID_LINKID;
966 	ddp->dd_flags = 0;
967 	mutex_exit(&ddp->dd_mutex);
968 	kmem_cache_free(i_dls_devnet_cachep, ddp);
969 
970 	return (0);
971 }
972 
973 /*
974  * This is a private hold routine used when we already have the dls_link_t, thus
975  * we know that it cannot go away.
976  */
977 int
978 dls_devnet_hold_tmp_by_link(dls_link_t *dlp, dls_dl_handle_t *ddhp)
979 {
980 	int err;
981 	dls_devnet_t *ddp = NULL;
982 
983 	rw_enter(&i_dls_devnet_lock, RW_WRITER);
984 	if ((err = mod_hash_find(i_dls_devnet_hash,
985 	    (mod_hash_key_t)dlp->dl_name, (mod_hash_val_t *)&ddp)) != 0) {
986 		ASSERT(err == MH_ERR_NOTFOUND);
987 		rw_exit(&i_dls_devnet_lock);
988 		return (ENOENT);
989 	}
990 
991 	mutex_enter(&ddp->dd_mutex);
992 	ASSERT(ddp->dd_ref > 0);
993 	if (ddp->dd_flags & DD_CONDEMNED) {
994 		mutex_exit(&ddp->dd_mutex);
995 		rw_exit(&i_dls_devnet_lock);
996 		return (ENOENT);
997 	}
998 	ddp->dd_tref++;
999 	mutex_exit(&ddp->dd_mutex);
1000 	rw_exit(&i_dls_devnet_lock);
1001 
1002 	*ddhp = ddp;
1003 	return (0);
1004 }
1005 
1006 static int
1007 dls_devnet_hold_common(datalink_id_t linkid, dls_devnet_t **ddpp,
1008     boolean_t tmp_hold)
1009 {
1010 	dls_devnet_t		*ddp;
1011 	int			err;
1012 
1013 	rw_enter(&i_dls_devnet_lock, RW_READER);
1014 	if ((err = mod_hash_find(i_dls_devnet_id_hash,
1015 	    (mod_hash_key_t)(uintptr_t)linkid, (mod_hash_val_t *)&ddp)) != 0) {
1016 		ASSERT(err == MH_ERR_NOTFOUND);
1017 		rw_exit(&i_dls_devnet_lock);
1018 		return (ENOENT);
1019 	}
1020 
1021 	mutex_enter(&ddp->dd_mutex);
1022 	ASSERT(ddp->dd_ref > 0);
1023 	if (ddp->dd_flags & DD_CONDEMNED) {
1024 		mutex_exit(&ddp->dd_mutex);
1025 		rw_exit(&i_dls_devnet_lock);
1026 		return (ENOENT);
1027 	}
1028 	if (tmp_hold)
1029 		ddp->dd_tref++;
1030 	else
1031 		ddp->dd_ref++;
1032 	mutex_exit(&ddp->dd_mutex);
1033 	rw_exit(&i_dls_devnet_lock);
1034 
1035 	*ddpp = ddp;
1036 	return (0);
1037 }
1038 
1039 int
1040 dls_devnet_hold(datalink_id_t linkid, dls_devnet_t **ddpp)
1041 {
1042 	return (dls_devnet_hold_common(linkid, ddpp, B_FALSE));
1043 }
1044 
1045 /*
1046  * Hold the vanity naming structure (dls_devnet_t) temporarily.  The request to
1047  * delete the dls_devnet_t will wait until the temporary reference is released.
1048  */
1049 int
1050 dls_devnet_hold_tmp(datalink_id_t linkid, dls_devnet_t **ddpp)
1051 {
1052 	return (dls_devnet_hold_common(linkid, ddpp, B_TRUE));
1053 }
1054 
1055 /*
1056  * This funtion is called when a DLS client tries to open a device node.
1057  * This dev_t could be a result of a /dev/net node access (returned by
1058  * devnet_create_rvp->dls_devnet_open()) or a direct /dev node access.
1059  * In both cases, this function bumps up the reference count of the
1060  * dls_devnet_t structure. The reference is held as long as the device node
1061  * is open. In the case of /dev/net while it is true that the initial reference
1062  * is held when the devnet_create_rvp->dls_devnet_open call happens, this
1063  * initial reference is released immediately in devnet_inactive_callback ->
1064  * dls_devnet_close(). (Note that devnet_inactive_callback() is called right
1065  * after dld_open completes, not when the /dev/net node is being closed).
1066  * To undo this function, call dls_devnet_rele()
1067  */
1068 int
1069 dls_devnet_hold_by_dev(dev_t dev, dls_dl_handle_t *ddhp)
1070 {
1071 	char			name[MAXNAMELEN];
1072 	char			*drv;
1073 	dls_devnet_t		*ddp;
1074 	int			err;
1075 
1076 	if ((drv = ddi_major_to_name(getmajor(dev))) == NULL)
1077 		return (EINVAL);
1078 
1079 	(void) snprintf(name, sizeof (name), "%s%d", drv,
1080 	    DLS_MINOR2INST(getminor(dev)));
1081 
1082 	rw_enter(&i_dls_devnet_lock, RW_READER);
1083 	if ((err = mod_hash_find(i_dls_devnet_hash,
1084 	    (mod_hash_key_t)name, (mod_hash_val_t *)&ddp)) != 0) {
1085 		ASSERT(err == MH_ERR_NOTFOUND);
1086 		rw_exit(&i_dls_devnet_lock);
1087 		return (ENOENT);
1088 	}
1089 	mutex_enter(&ddp->dd_mutex);
1090 	ASSERT(ddp->dd_ref > 0);
1091 	if (ddp->dd_flags & DD_CONDEMNED) {
1092 		mutex_exit(&ddp->dd_mutex);
1093 		rw_exit(&i_dls_devnet_lock);
1094 		return (ENOENT);
1095 	}
1096 	ddp->dd_ref++;
1097 	mutex_exit(&ddp->dd_mutex);
1098 	rw_exit(&i_dls_devnet_lock);
1099 
1100 	*ddhp = ddp;
1101 	return (0);
1102 }
1103 
1104 void
1105 dls_devnet_rele(dls_devnet_t *ddp)
1106 {
1107 	mutex_enter(&ddp->dd_mutex);
1108 	ASSERT(ddp->dd_ref > 1);
1109 	ddp->dd_ref--;
1110 	if ((ddp->dd_flags & DD_IMPLICIT_IPTUN) && ddp->dd_ref == 1) {
1111 		mutex_exit(&ddp->dd_mutex);
1112 		if (i_dls_devnet_destroy_iptun(ddp->dd_linkid) != 0)
1113 			ddp->dd_flags |= DD_IMPLICIT_IPTUN;
1114 		return;
1115 	}
1116 	mutex_exit(&ddp->dd_mutex);
1117 }
1118 
1119 static int
1120 dls_devnet_hold_by_name(const char *link, dls_devnet_t **ddpp)
1121 {
1122 	char			drv[MAXLINKNAMELEN];
1123 	uint_t			ppa;
1124 	major_t			major;
1125 	dev_t			phy_dev, tmp_dev;
1126 	datalink_id_t		linkid;
1127 	dls_dev_handle_t	ddh;
1128 	int			err;
1129 
1130 	if ((err = dls_mgmt_get_linkid(link, &linkid)) == 0)
1131 		return (dls_devnet_hold(linkid, ddpp));
1132 
1133 	/*
1134 	 * If we failed to get the link's linkid because the dlmgmtd daemon
1135 	 * has not been started, return ENOENT so that the application can
1136 	 * fallback to open the /dev node.
1137 	 */
1138 	if (err == EBADF)
1139 		return (ENOENT);
1140 
1141 	if (err != ENOENT)
1142 		return (err);
1143 
1144 	/*
1145 	 * If we reach this point it means dlmgmtd is up but has no
1146 	 * mapping for the link name.
1147 	 */
1148 	if (ddi_parse(link, drv, &ppa) != DDI_SUCCESS)
1149 		return (ENOENT);
1150 
1151 	if (IS_IPTUN_LINK(drv)) {
1152 		if ((err = i_dls_devnet_create_iptun(link, drv, &linkid)) != 0)
1153 			return (err);
1154 		/*
1155 		 * At this point, an IP tunnel MAC has registered, which
1156 		 * resulted in a link being created.
1157 		 */
1158 		err = dls_devnet_hold(linkid, ddpp);
1159 		if (err != 0) {
1160 			VERIFY(i_dls_devnet_destroy_iptun(linkid) == 0);
1161 			return (err);
1162 		}
1163 		/*
1164 		 * dls_devnet_rele() will know to destroy the implicit IP
1165 		 * tunnel on last reference release if DD_IMPLICIT_IPTUN is
1166 		 * set.
1167 		 */
1168 		(*ddpp)->dd_flags |= DD_IMPLICIT_IPTUN;
1169 		return (0);
1170 	}
1171 
1172 	/*
1173 	 * If this link:
1174 	 * (a) is a physical device, (b) this is the first boot, (c) the MAC
1175 	 * is not registered yet, and (d) we cannot find its linkid, then the
1176 	 * linkname is the same as the devname.
1177 	 *
1178 	 * First filter out invalid names.
1179 	 */
1180 	if ((major = ddi_name_to_major(drv)) == (major_t)-1)
1181 		return (ENOENT);
1182 
1183 	phy_dev = makedevice(major, DLS_PPA2MINOR(ppa));
1184 	if (softmac_hold_device(phy_dev, &ddh) != 0)
1185 		return (ENOENT);
1186 
1187 	/*
1188 	 * At this time, the MAC should be registered, check its phy_dev using
1189 	 * the given name.
1190 	 */
1191 	if ((err = dls_mgmt_get_linkid(link, &linkid)) != 0 ||
1192 	    (err = dls_mgmt_get_phydev(linkid, &tmp_dev)) != 0) {
1193 		softmac_rele_device(ddh);
1194 		return (err);
1195 	}
1196 	if (tmp_dev != phy_dev) {
1197 		softmac_rele_device(ddh);
1198 		return (ENOENT);
1199 	}
1200 
1201 	err = dls_devnet_hold(linkid, ddpp);
1202 	softmac_rele_device(ddh);
1203 	return (err);
1204 }
1205 
1206 int
1207 dls_devnet_macname2linkid(const char *macname, datalink_id_t *linkidp)
1208 {
1209 	dls_devnet_t	*ddp;
1210 
1211 	rw_enter(&i_dls_devnet_lock, RW_READER);
1212 	if (mod_hash_find(i_dls_devnet_hash, (mod_hash_key_t)macname,
1213 	    (mod_hash_val_t *)&ddp) != 0) {
1214 		rw_exit(&i_dls_devnet_lock);
1215 		return (ENOENT);
1216 	}
1217 
1218 	*linkidp = ddp->dd_linkid;
1219 	rw_exit(&i_dls_devnet_lock);
1220 	return (0);
1221 }
1222 
1223 /*
1224  * Get linkid for the given dev.
1225  */
1226 int
1227 dls_devnet_dev2linkid(dev_t dev, datalink_id_t *linkidp)
1228 {
1229 	char	macname[MAXNAMELEN];
1230 	char	*drv;
1231 
1232 	if ((drv = ddi_major_to_name(getmajor(dev))) == NULL)
1233 		return (EINVAL);
1234 
1235 	(void) snprintf(macname, sizeof (macname), "%s%d", drv,
1236 	    DLS_MINOR2INST(getminor(dev)));
1237 	return (dls_devnet_macname2linkid(macname, linkidp));
1238 }
1239 
1240 /*
1241  * Get the link's physical dev_t. It this is a VLAN, get the dev_t of the
1242  * link this VLAN is created on.
1243  */
1244 int
1245 dls_devnet_phydev(datalink_id_t vlanid, dev_t *devp)
1246 {
1247 	dls_devnet_t	*ddp;
1248 	int		err;
1249 
1250 	if ((err = dls_devnet_hold_tmp(vlanid, &ddp)) != 0)
1251 		return (err);
1252 
1253 	err = dls_mgmt_get_phydev(ddp->dd_linkid, devp);
1254 	dls_devnet_rele_tmp(ddp);
1255 	return (err);
1256 }
1257 
1258 /*
1259  * Handle the renaming requests.  There are two rename cases:
1260  *
1261  * 1. Request to rename a valid link (id1) to an non-existent link name
1262  *    (id2). In this case id2 is DATALINK_INVALID_LINKID.  Just check whether
1263  *    id1 is held by any applications.
1264  *
1265  *    In this case, the link's kstats need to be updated using the given name.
1266  *
1267  * 2. Request to rename a valid link (id1) to the name of a REMOVED
1268  *    physical link (id2). In this case, check that id1 and its associated
1269  *    mac is not held by any application, and update the link's linkid to id2.
1270  *
1271  *    This case does not change the <link name, linkid> mapping, so the link's
1272  *    kstats need to be updated with using name associated the given id2.
1273  */
1274 int
1275 dls_devnet_rename(datalink_id_t id1, datalink_id_t id2, const char *link)
1276 {
1277 	dls_dev_handle_t	ddh = NULL;
1278 	int			err = 0;
1279 	dev_t			phydev = 0;
1280 	dls_devnet_t		*ddp;
1281 	mac_perim_handle_t	mph = NULL;
1282 	mac_handle_t		mh;
1283 	mod_hash_val_t		val;
1284 
1285 	/*
1286 	 * In the second case, id2 must be a REMOVED physical link.
1287 	 */
1288 	if ((id2 != DATALINK_INVALID_LINKID) &&
1289 	    (dls_mgmt_get_phydev(id2, &phydev) == 0) &&
1290 	    softmac_hold_device(phydev, &ddh) == 0) {
1291 		softmac_rele_device(ddh);
1292 		return (EEXIST);
1293 	}
1294 
1295 	/*
1296 	 * Hold id1 to prevent it from being detached (if a physical link).
1297 	 */
1298 	if (dls_mgmt_get_phydev(id1, &phydev) == 0)
1299 		(void) softmac_hold_device(phydev, &ddh);
1300 
1301 	/*
1302 	 * The framework does not hold hold locks across calls to the
1303 	 * mac perimeter, hence enter the perimeter first. This also waits
1304 	 * for the property loading to finish.
1305 	 */
1306 	if ((err = mac_perim_enter_by_linkid(id1, &mph)) != 0) {
1307 		softmac_rele_device(ddh);
1308 		return (err);
1309 	}
1310 
1311 	rw_enter(&i_dls_devnet_lock, RW_WRITER);
1312 	if ((err = mod_hash_find(i_dls_devnet_id_hash,
1313 	    (mod_hash_key_t)(uintptr_t)id1, (mod_hash_val_t *)&ddp)) != 0) {
1314 		ASSERT(err == MH_ERR_NOTFOUND);
1315 		err = ENOENT;
1316 		goto done;
1317 	}
1318 
1319 	mutex_enter(&ddp->dd_mutex);
1320 	if (ddp->dd_ref > 1) {
1321 		mutex_exit(&ddp->dd_mutex);
1322 		err = EBUSY;
1323 		goto done;
1324 	}
1325 	mutex_exit(&ddp->dd_mutex);
1326 
1327 	if (id2 == DATALINK_INVALID_LINKID) {
1328 		(void) strlcpy(ddp->dd_linkname, link,
1329 		    sizeof (ddp->dd_linkname));
1330 
1331 		/* rename mac client name and its flow if exists */
1332 		if ((err = mac_open(ddp->dd_mac, &mh)) != 0)
1333 			goto done;
1334 		(void) mac_rename_primary(mh, link);
1335 		mac_close(mh);
1336 		goto done;
1337 	}
1338 
1339 	/*
1340 	 * The second case, check whether the MAC is used by any MAC
1341 	 * user.  This must be a physical link so ddh must not be NULL.
1342 	 */
1343 	if (ddh == NULL) {
1344 		err = EINVAL;
1345 		goto done;
1346 	}
1347 
1348 	if ((err = mac_open(ddp->dd_mac, &mh)) != 0)
1349 		goto done;
1350 
1351 	/*
1352 	 * We release the reference of the MAC which mac_open() is
1353 	 * holding. Note that this mac will not be unregistered
1354 	 * because the physical device is held.
1355 	 */
1356 	mac_close(mh);
1357 
1358 	/*
1359 	 * Check if there is any other MAC clients, if not, hold this mac
1360 	 * exclusively until we are done.
1361 	 */
1362 	if ((err = mac_mark_exclusive(mh)) != 0)
1363 		goto done;
1364 
1365 	/*
1366 	 * Update the link's linkid.
1367 	 */
1368 	if ((err = mod_hash_find(i_dls_devnet_id_hash,
1369 	    (mod_hash_key_t)(uintptr_t)id2, &val)) != MH_ERR_NOTFOUND) {
1370 		mac_unmark_exclusive(mh);
1371 		err = EEXIST;
1372 		goto done;
1373 	}
1374 
1375 	err = dls_mgmt_get_linkinfo(id2, ddp->dd_linkname, NULL, NULL, NULL);
1376 	if (err != 0) {
1377 		mac_unmark_exclusive(mh);
1378 		goto done;
1379 	}
1380 
1381 	(void) mod_hash_remove(i_dls_devnet_id_hash,
1382 	    (mod_hash_key_t)(uintptr_t)id1, &val);
1383 
1384 	ddp->dd_linkid = id2;
1385 	(void) mod_hash_insert(i_dls_devnet_id_hash,
1386 	    (mod_hash_key_t)(uintptr_t)ddp->dd_linkid, (mod_hash_val_t)ddp);
1387 
1388 	mac_unmark_exclusive(mh);
1389 
1390 	/* load properties for new id */
1391 	mutex_enter(&ddp->dd_mutex);
1392 	ddp->dd_prop_loaded = B_FALSE;
1393 	ddp->dd_prop_taskid = taskq_dispatch(system_taskq,
1394 	    dls_devnet_prop_task, ddp, TQ_SLEEP);
1395 	mutex_exit(&ddp->dd_mutex);
1396 
1397 done:
1398 	rw_exit(&i_dls_devnet_lock);
1399 
1400 	if (err == 0)
1401 		dls_devnet_stat_rename(ddp);
1402 
1403 	if (mph != NULL)
1404 		mac_perim_exit(mph);
1405 	softmac_rele_device(ddh);
1406 	return (err);
1407 }
1408 
1409 static int
1410 i_dls_devnet_setzid(dls_devnet_t *ddp, zoneid_t new_zoneid, boolean_t setprop)
1411 {
1412 	int			err;
1413 	mac_perim_handle_t	mph;
1414 	boolean_t		upcall_done = B_FALSE;
1415 	datalink_id_t		linkid = ddp->dd_linkid;
1416 	zoneid_t		old_zoneid = ddp->dd_zid;
1417 	dlmgmt_door_setzoneid_t	setzid;
1418 	dlmgmt_setzoneid_retval_t retval;
1419 
1420 	if (old_zoneid == new_zoneid)
1421 		return (0);
1422 
1423 	if ((err = mac_perim_enter_by_macname(ddp->dd_mac, &mph)) != 0)
1424 		return (err);
1425 
1426 	/*
1427 	 * When changing the zoneid of an existing link, we need to tell
1428 	 * dlmgmtd about it.  dlmgmtd already knows the zoneid associated with
1429 	 * newly created links.
1430 	 */
1431 	if (setprop) {
1432 		setzid.ld_cmd = DLMGMT_CMD_SETZONEID;
1433 		setzid.ld_linkid = linkid;
1434 		setzid.ld_zoneid = new_zoneid;
1435 		err = i_dls_mgmt_upcall(&setzid, sizeof (setzid), &retval,
1436 		    sizeof (retval));
1437 		if (err != 0)
1438 			goto done;
1439 		upcall_done = B_TRUE;
1440 	}
1441 	if ((err = dls_link_setzid(ddp->dd_mac, new_zoneid)) == 0) {
1442 		ddp->dd_zid = new_zoneid;
1443 		devnet_need_rebuild = B_TRUE;
1444 	}
1445 
1446 done:
1447 	if (err != 0 && upcall_done) {
1448 		setzid.ld_zoneid = old_zoneid;
1449 		(void) i_dls_mgmt_upcall(&setzid, sizeof (setzid), &retval,
1450 		    sizeof (retval));
1451 	}
1452 	mac_perim_exit(mph);
1453 	return (err);
1454 }
1455 
1456 int
1457 dls_devnet_setzid(dls_dl_handle_t ddh, zoneid_t new_zid)
1458 {
1459 	dls_devnet_t	*ddp;
1460 	int		err;
1461 	zoneid_t	old_zid;
1462 	boolean_t	refheld = B_FALSE;
1463 
1464 	old_zid = ddh->dd_zid;
1465 
1466 	if (old_zid == new_zid)
1467 		return (0);
1468 
1469 	/*
1470 	 * Acquire an additional reference to the link if it is being assigned
1471 	 * to a non-global zone from the global zone.
1472 	 */
1473 	if (old_zid == GLOBAL_ZONEID && new_zid != GLOBAL_ZONEID) {
1474 		if ((err = dls_devnet_hold(ddh->dd_linkid, &ddp)) != 0)
1475 			return (err);
1476 		refheld = B_TRUE;
1477 	}
1478 
1479 	if ((err = i_dls_devnet_setzid(ddh, new_zid, B_TRUE)) != 0) {
1480 		if (refheld)
1481 			dls_devnet_rele(ddp);
1482 		return (err);
1483 	}
1484 
1485 	/*
1486 	 * Release the additional reference if the link is returning to the
1487 	 * global zone from a non-global zone.
1488 	 */
1489 	if (old_zid != GLOBAL_ZONEID && new_zid == GLOBAL_ZONEID)
1490 		dls_devnet_rele(ddh);
1491 
1492 	/* Re-create kstats in the appropriate zones. */
1493 	if (old_zid != GLOBAL_ZONEID)
1494 		dls_devnet_stat_destroy(ddh, old_zid);
1495 	if (new_zid != GLOBAL_ZONEID)
1496 		dls_devnet_stat_create(ddh, new_zid);
1497 
1498 	return (0);
1499 }
1500 
1501 zoneid_t
1502 dls_devnet_getzid(dls_dl_handle_t ddh)
1503 {
1504 	return (((dls_devnet_t *)ddh)->dd_zid);
1505 }
1506 
1507 zoneid_t
1508 dls_devnet_getownerzid(dls_dl_handle_t ddh)
1509 {
1510 	return (((dls_devnet_t *)ddh)->dd_owner_zid);
1511 }
1512 
1513 /*
1514  * Is linkid visible from zoneid?  A link is visible if it was created in the
1515  * zone, or if it is currently assigned to the zone.
1516  */
1517 boolean_t
1518 dls_devnet_islinkvisible(datalink_id_t linkid, zoneid_t zoneid)
1519 {
1520 	dls_devnet_t	*ddp;
1521 	boolean_t	result;
1522 
1523 	if (dls_devnet_hold_tmp(linkid, &ddp) != 0)
1524 		return (B_FALSE);
1525 	result = (ddp->dd_owner_zid == zoneid || ddp->dd_zid == zoneid);
1526 	dls_devnet_rele_tmp(ddp);
1527 	return (result);
1528 }
1529 
1530 /*
1531  * Access a vanity naming node.
1532  */
1533 int
1534 dls_devnet_open(const char *link, dls_dl_handle_t *dhp, dev_t *devp)
1535 {
1536 	dls_devnet_t	*ddp;
1537 	dls_link_t	*dlp;
1538 	zoneid_t	zid = getzoneid();
1539 	int		err;
1540 	mac_perim_handle_t	mph;
1541 
1542 	if ((err = dls_devnet_hold_by_name(link, &ddp)) != 0)
1543 		return (err);
1544 
1545 	dls_devnet_prop_task_wait(ddp);
1546 
1547 	/*
1548 	 * Opening a link that does not belong to the current non-global zone
1549 	 * is not allowed.
1550 	 */
1551 	if (zid != GLOBAL_ZONEID && ddp->dd_zid != zid) {
1552 		dls_devnet_rele(ddp);
1553 		return (ENOENT);
1554 	}
1555 
1556 	err = mac_perim_enter_by_macname(ddp->dd_mac, &mph);
1557 	if (err != 0) {
1558 		dls_devnet_rele(ddp);
1559 		return (err);
1560 	}
1561 
1562 	err = dls_link_hold_create(ddp->dd_mac, &dlp);
1563 	mac_perim_exit(mph);
1564 
1565 	if (err != 0) {
1566 		dls_devnet_rele(ddp);
1567 		return (err);
1568 	}
1569 
1570 	*dhp = ddp;
1571 	*devp = dls_link_dev(dlp);
1572 	return (0);
1573 }
1574 
1575 /*
1576  * Close access to a vanity naming node.
1577  */
1578 void
1579 dls_devnet_close(dls_dl_handle_t dlh)
1580 {
1581 	dls_devnet_t	*ddp = dlh;
1582 	dls_link_t	*dlp;
1583 	mac_perim_handle_t	mph;
1584 
1585 	VERIFY(mac_perim_enter_by_macname(ddp->dd_mac, &mph) == 0);
1586 	VERIFY(dls_link_hold(ddp->dd_mac, &dlp) == 0);
1587 
1588 	/*
1589 	 * One rele for the hold placed in dls_devnet_open, another for
1590 	 * the hold done just above
1591 	 */
1592 	dls_link_rele(dlp);
1593 	dls_link_rele(dlp);
1594 	mac_perim_exit(mph);
1595 
1596 	dls_devnet_rele(ddp);
1597 }
1598 
1599 /*
1600  * This is used by /dev/net to rebuild the nodes for readdir().  It is not
1601  * critical and no protection is needed.
1602  */
1603 boolean_t
1604 dls_devnet_rebuild()
1605 {
1606 	boolean_t updated = devnet_need_rebuild;
1607 
1608 	devnet_need_rebuild = B_FALSE;
1609 	return (updated);
1610 }
1611 
1612 int
1613 dls_devnet_create(mac_handle_t mh, datalink_id_t linkid, zoneid_t zoneid)
1614 {
1615 	dls_link_t	*dlp;
1616 	dls_devnet_t	*ddp;
1617 	int		err;
1618 	mac_perim_handle_t mph;
1619 
1620 	/*
1621 	 * Holding the mac perimeter ensures that the downcall from the
1622 	 * dlmgmt daemon which does the property loading does not proceed
1623 	 * until we relinquish the perimeter.
1624 	 */
1625 	mac_perim_enter_by_mh(mh, &mph);
1626 	/*
1627 	 * Make this association before we call dls_link_hold_create as
1628 	 * we need to use the linkid to get the user name for the link
1629 	 * when we create the MAC client.
1630 	 */
1631 	if ((err = dls_devnet_set(mac_name(mh), linkid, zoneid, &ddp)) == 0) {
1632 		if ((err = dls_link_hold_create(mac_name(mh), &dlp)) != 0) {
1633 			mac_perim_exit(mph);
1634 			(void) dls_devnet_unset(mac_name(mh), &linkid, B_TRUE);
1635 			return (err);
1636 		}
1637 	}
1638 	mac_perim_exit(mph);
1639 	return (err);
1640 }
1641 
1642 /*
1643  * Set the linkid of the dls_devnet_t and add it into the i_dls_devnet_id_hash.
1644  * This is called in the case that the dlmgmtd daemon is started later than
1645  * the physical devices get attached, and the linkid is only known after the
1646  * daemon starts.
1647  */
1648 int
1649 dls_devnet_recreate(mac_handle_t mh, datalink_id_t linkid)
1650 {
1651 	ASSERT(linkid != DATALINK_INVALID_LINKID);
1652 	return (dls_devnet_set(mac_name(mh), linkid, GLOBAL_ZONEID, NULL));
1653 }
1654 
1655 int
1656 dls_devnet_destroy(mac_handle_t mh, datalink_id_t *idp, boolean_t wait)
1657 {
1658 	int			err;
1659 	mac_perim_handle_t	mph;
1660 
1661 	*idp = DATALINK_INVALID_LINKID;
1662 	err = dls_devnet_unset(mac_name(mh), idp, wait);
1663 	if (err != 0 && err != ENOENT)
1664 		return (err);
1665 
1666 	mac_perim_enter_by_mh(mh, &mph);
1667 	err = dls_link_rele_by_name(mac_name(mh));
1668 	mac_perim_exit(mph);
1669 
1670 	if (err != 0) {
1671 		/*
1672 		 * XXX It is a general GLDv3 bug that dls_devnet_set() has to
1673 		 * be called to re-set the link when destroy fails.  The
1674 		 * zoneid below will be incorrect if this function is ever
1675 		 * called from kernel context or from a zone other than that
1676 		 * which initially created the link.
1677 		 */
1678 		(void) dls_devnet_set(mac_name(mh), *idp, crgetzoneid(CRED()),
1679 		    NULL);
1680 	}
1681 	return (err);
1682 }
1683 
1684 /*
1685  * Implicitly create an IP tunnel link.
1686  */
1687 static int
1688 i_dls_devnet_create_iptun(const char *linkname, const char *drvname,
1689     datalink_id_t *linkid)
1690 {
1691 	int		err;
1692 	iptun_kparams_t	ik;
1693 	uint32_t	media;
1694 	netstack_t	*ns;
1695 	major_t		iptun_major;
1696 	dev_info_t	*iptun_dip;
1697 
1698 	/* First ensure that the iptun device is attached. */
1699 	if ((iptun_major = ddi_name_to_major(IPTUN_DRIVER_NAME)) == (major_t)-1)
1700 		return (EINVAL);
1701 	if ((iptun_dip = ddi_hold_devi_by_instance(iptun_major, 0, 0)) == NULL)
1702 		return (EINVAL);
1703 
1704 	if (IS_IPV4_TUN(drvname)) {
1705 		ik.iptun_kparam_type = IPTUN_TYPE_IPV4;
1706 		media = DL_IPV4;
1707 	} else if (IS_6TO4_TUN(drvname)) {
1708 		ik.iptun_kparam_type = IPTUN_TYPE_6TO4;
1709 		media = DL_6TO4;
1710 	} else if (IS_IPV6_TUN(drvname)) {
1711 		ik.iptun_kparam_type = IPTUN_TYPE_IPV6;
1712 		media = DL_IPV6;
1713 	}
1714 	ik.iptun_kparam_flags = (IPTUN_KPARAM_TYPE | IPTUN_KPARAM_IMPLICIT);
1715 
1716 	/* Obtain a datalink id for this tunnel. */
1717 	err = dls_mgmt_create((char *)linkname, 0, DATALINK_CLASS_IPTUN, media,
1718 	    B_FALSE, &ik.iptun_kparam_linkid);
1719 	if (err != 0) {
1720 		ddi_release_devi(iptun_dip);
1721 		return (err);
1722 	}
1723 
1724 	ns = netstack_get_current();
1725 	err = iptun_create(&ik, CRED());
1726 	netstack_rele(ns);
1727 
1728 	if (err != 0)
1729 		VERIFY(dls_mgmt_destroy(ik.iptun_kparam_linkid, B_FALSE) == 0);
1730 	else
1731 		*linkid = ik.iptun_kparam_linkid;
1732 
1733 	ddi_release_devi(iptun_dip);
1734 	return (err);
1735 }
1736 
1737 static int
1738 i_dls_devnet_destroy_iptun(datalink_id_t linkid)
1739 {
1740 	int err;
1741 
1742 	/*
1743 	 * Note the use of zone_kcred() here as opposed to CRED().  This is
1744 	 * because the process that does the last close of this /dev/net node
1745 	 * may not have necessary privileges to delete this IP tunnel, but the
1746 	 * tunnel must always be implicitly deleted on last close.
1747 	 */
1748 	if ((err = iptun_delete(linkid, zone_kcred())) == 0)
1749 		(void) dls_mgmt_destroy(linkid, B_FALSE);
1750 	return (err);
1751 }
1752 
1753 const char *
1754 dls_devnet_link(dls_dl_handle_t ddh)
1755 {
1756 	return (ddh->dd_linkname);
1757 }
1758 
1759 const char *
1760 dls_devnet_mac(dls_dl_handle_t ddh)
1761 {
1762 	return (ddh->dd_mac);
1763 }
1764 
1765 datalink_id_t
1766 dls_devnet_linkid(dls_dl_handle_t ddh)
1767 {
1768 	return (ddh->dd_linkid);
1769 }
1770