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