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 2019 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
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
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
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, B_FALSE);
167 dls_devnet_rele_tmp(ddp);
168 }
169 return (0);
170 }
171
172 /* ARGSUSED */
173 static void *
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
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
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
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
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
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
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
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
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
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
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
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
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 getlinkid.ld_zoneid = getzoneid();
548
549 if ((err = i_dls_mgmt_upcall(&getlinkid, sizeof (getlinkid), &retval,
550 sizeof (retval))) == 0) {
551 *linkid = retval.lr_linkid;
552 }
553 return (err);
554 }
555
556 int
557 dls_mgmt_get_linkid_in_zone(const char *link, datalink_id_t *linkid,
558 zoneid_t zid)
559 {
560 dlmgmt_door_getlinkid_t getlinkid;
561 dlmgmt_getlinkid_retval_t retval;
562 int err;
563
564 ASSERT(getzoneid() == GLOBAL_ZONEID || zid == getzoneid());
565 getlinkid.ld_cmd = DLMGMT_CMD_GETLINKID;
566 (void) strlcpy(getlinkid.ld_link, link, MAXLINKNAMELEN);
567 getlinkid.ld_zoneid = zid;
568
569 if ((err = i_dls_mgmt_upcall(&getlinkid, sizeof (getlinkid), &retval,
570 sizeof (retval))) == 0) {
571 *linkid = retval.lr_linkid;
572 }
573 return (err);
574 }
575
576
577 datalink_id_t
578 dls_mgmt_get_next(datalink_id_t linkid, datalink_class_t class,
579 datalink_media_t dmedia, uint32_t flags)
580 {
581 dlmgmt_door_getnext_t getnext;
582 dlmgmt_getnext_retval_t retval;
583
584 getnext.ld_cmd = DLMGMT_CMD_GETNEXT;
585 getnext.ld_class = class;
586 getnext.ld_dmedia = dmedia;
587 getnext.ld_flags = flags;
588 getnext.ld_linkid = linkid;
589
590 if (i_dls_mgmt_upcall(&getnext, sizeof (getnext), &retval,
591 sizeof (retval)) != 0) {
592 return (DATALINK_INVALID_LINKID);
593 }
594
595 return (retval.lr_linkid);
596 }
597
598 static int
599 i_dls_mgmt_get_linkattr(const datalink_id_t linkid, const char *attr,
600 void *attrval, size_t *attrszp)
601 {
602 dlmgmt_upcall_arg_getattr_t getattr;
603 dlmgmt_getattr_retval_t retval;
604 int err;
605
606 getattr.ld_cmd = DLMGMT_CMD_DLS_GETATTR;
607 getattr.ld_linkid = linkid;
608 (void) strlcpy(getattr.ld_attr, attr, MAXLINKATTRLEN);
609
610 if ((err = i_dls_mgmt_upcall(&getattr, sizeof (getattr), &retval,
611 sizeof (retval))) == 0) {
612 if (*attrszp < retval.lr_attrsz)
613 return (EINVAL);
614 *attrszp = retval.lr_attrsz;
615 bcopy(retval.lr_attrval, attrval, retval.lr_attrsz);
616 }
617
618 return (err);
619 }
620
621 /*
622 * Note that this function can only get devp successfully for non-VLAN link.
623 */
624 int
625 dls_mgmt_get_phydev(datalink_id_t linkid, dev_t *devp)
626 {
627 uint64_t maj, inst;
628 size_t attrsz = sizeof (uint64_t);
629
630 if (i_dls_mgmt_get_linkattr(linkid, FPHYMAJ, &maj, &attrsz) != 0 ||
631 attrsz != sizeof (uint64_t) ||
632 i_dls_mgmt_get_linkattr(linkid, FPHYINST, &inst, &attrsz) != 0 ||
633 attrsz != sizeof (uint64_t)) {
634 return (EINVAL);
635 }
636
637 *devp = makedevice((major_t)maj, (minor_t)inst);
638 return (0);
639 }
640
641 /*
642 * Request the datalink management daemon to push in
643 * all properties associated with the link.
644 * Returns a non-zero error code on failure.
645 */
646 int
647 dls_mgmt_linkprop_init(datalink_id_t linkid)
648 {
649 dlmgmt_door_linkprop_init_t li;
650 dlmgmt_linkprop_init_retval_t retval;
651 int err;
652
653 li.ld_cmd = DLMGMT_CMD_LINKPROP_INIT;
654 li.ld_linkid = linkid;
655
656 err = i_dls_mgmt_upcall(&li, sizeof (li), &retval, sizeof (retval));
657 return (err);
658 }
659
660 static void
661 dls_devnet_prop_task(void *arg)
662 {
663 dls_devnet_t *ddp = arg;
664
665 (void) dls_mgmt_linkprop_init(ddp->dd_linkid);
666
667 mutex_enter(&ddp->dd_mutex);
668 ddp->dd_prop_loaded = B_TRUE;
669 ddp->dd_prop_taskid = 0;
670 cv_broadcast(&ddp->dd_cv);
671 mutex_exit(&ddp->dd_mutex);
672 }
673
674 /*
675 * Ensure property loading task is completed.
676 */
677 void
678 dls_devnet_prop_task_wait(dls_dl_handle_t ddp)
679 {
680 mutex_enter(&ddp->dd_mutex);
681 while (ddp->dd_prop_taskid != 0)
682 cv_wait(&ddp->dd_cv, &ddp->dd_mutex);
683 mutex_exit(&ddp->dd_mutex);
684 }
685
686 void
687 dls_devnet_rele_tmp(dls_dl_handle_t dlh)
688 {
689 dls_devnet_t *ddp = dlh;
690
691 mutex_enter(&ddp->dd_mutex);
692 ASSERT(ddp->dd_tref != 0);
693 if (--ddp->dd_tref == 0)
694 cv_signal(&ddp->dd_cv);
695 mutex_exit(&ddp->dd_mutex);
696 }
697
698 int
699 dls_devnet_hold_link(datalink_id_t linkid, dls_dl_handle_t *ddhp,
700 dls_link_t **dlpp)
701 {
702 dls_dl_handle_t dlh;
703 dls_link_t *dlp;
704 int err;
705
706 if ((err = dls_devnet_hold_tmp(linkid, &dlh)) != 0)
707 return (err);
708
709 if ((err = dls_link_hold(dls_devnet_mac(dlh), &dlp)) != 0) {
710 dls_devnet_rele_tmp(dlh);
711 return (err);
712 }
713
714 ASSERT(MAC_PERIM_HELD(dlp->dl_mh));
715
716 *ddhp = dlh;
717 *dlpp = dlp;
718 return (0);
719 }
720
721 void
722 dls_devnet_rele_link(dls_dl_handle_t dlh, dls_link_t *dlp)
723 {
724 ASSERT(MAC_PERIM_HELD(dlp->dl_mh));
725
726 dls_link_rele(dlp);
727 dls_devnet_rele_tmp(dlh);
728 }
729
730 /*
731 * "link" kstats related functions.
732 */
733
734 /*
735 * Query the "link" kstats.
736 *
737 * We may be called from the kstat subsystem in an arbitrary context.
738 * If the caller is the stack, the context could be an upcall data
739 * thread. Hence we can't acquire the mac perimeter in this function
740 * for fear of deadlock.
741 */
742 static int
743 dls_devnet_stat_update(kstat_t *ksp, int rw)
744 {
745 datalink_id_t linkid = (datalink_id_t)(uintptr_t)ksp->ks_private;
746 dls_devnet_t *ddp;
747 dls_link_t *dlp;
748 int err;
749
750 if ((err = dls_devnet_hold_tmp(linkid, &ddp)) != 0) {
751 return (err);
752 }
753
754 /*
755 * If a device detach happens at this time, it will block in
756 * dls_devnet_unset since the dd_tref has been bumped in
757 * dls_devnet_hold_tmp(). So the access to 'dlp' is safe even though
758 * we don't hold the mac perimeter.
759 */
760 if (mod_hash_find(i_dls_link_hash, (mod_hash_key_t)ddp->dd_mac,
761 (mod_hash_val_t *)&dlp) != 0) {
762 dls_devnet_rele_tmp(ddp);
763 return (ENOENT);
764 }
765
766 err = dls_stat_update(ksp, dlp, rw);
767
768 dls_devnet_rele_tmp(ddp);
769 return (err);
770 }
771
772 /*
773 * Create the "link" kstats.
774 */
775 static void
776 dls_devnet_stat_create(dls_devnet_t *ddp, zoneid_t zoneid, zoneid_t newzoneid)
777 {
778 kstat_t *ksp;
779 char *nm;
780 char kname[MAXLINKNAMELEN];
781
782 if (zoneid != newzoneid) {
783 ASSERT(zoneid == GLOBAL_ZONEID);
784 (void) snprintf(kname, sizeof (kname), "z%d_%s", newzoneid,
785 ddp->dd_linkname);
786 nm = kname;
787 } else {
788 nm = ddp->dd_linkname;
789 }
790
791 if (dls_stat_create("link", 0, nm, zoneid,
792 dls_devnet_stat_update, (void *)(uintptr_t)ddp->dd_linkid,
793 &ksp, newzoneid) == 0) {
794 ASSERT(ksp != NULL);
795 if (zoneid == ddp->dd_owner_zid) {
796 ASSERT(ddp->dd_ksp == NULL);
797 ddp->dd_ksp = ksp;
798 } else {
799 ASSERT(ddp->dd_zone_ksp == NULL);
800 ddp->dd_zone_ksp = ksp;
801 }
802 }
803 }
804
805 /*
806 * Destroy the "link" kstats.
807 */
808 static void
809 dls_devnet_stat_destroy(dls_devnet_t *ddp, zoneid_t zoneid)
810 {
811 if (zoneid == ddp->dd_owner_zid) {
812 if (ddp->dd_ksp != NULL) {
813 dls_stat_delete(ddp->dd_ksp);
814 ddp->dd_ksp = NULL;
815 }
816 } else {
817 if (ddp->dd_zone_ksp != NULL) {
818 dls_stat_delete(ddp->dd_zone_ksp);
819 ddp->dd_zone_ksp = NULL;
820 }
821 }
822 }
823
824 /*
825 * The link has been renamed. Destroy the old non-legacy kstats ("link kstats")
826 * and create the new set using the new name.
827 */
828 static void
829 dls_devnet_stat_rename(dls_devnet_t *ddp, boolean_t zoneinit)
830 {
831 if (ddp->dd_ksp != NULL) {
832 dls_stat_delete(ddp->dd_ksp);
833 ddp->dd_ksp = NULL;
834 }
835 if (zoneinit && ddp->dd_zone_ksp != NULL) {
836 dls_stat_delete(ddp->dd_zone_ksp);
837 ddp->dd_zone_ksp = NULL;
838 }
839 /*
840 * We can't rename a link while it's assigned to a non-global zone
841 * unless we're first initializing the zone while readying it.
842 */
843 ASSERT(ddp->dd_zone_ksp == NULL);
844 dls_devnet_stat_create(ddp, ddp->dd_owner_zid,
845 (zoneinit ? ddp->dd_zid : ddp->dd_owner_zid));
846 if (zoneinit)
847 dls_devnet_stat_create(ddp, ddp->dd_zid, ddp->dd_zid);
848 }
849
850 /*
851 * Associate the linkid with the link identified by macname. If this
852 * is called on behalf of a physical link then linkid may be
853 * DATALINK_INVALID_LINKID. Otherwise, if called on behalf of a
854 * virtual link, linkid must have a value.
855 */
856 static int
857 dls_devnet_set(mac_handle_t mh, datalink_id_t linkid, zoneid_t zoneid,
858 dls_devnet_t **ddpp)
859 {
860 const char *macname = mac_name(mh);
861 dls_devnet_t *ddp = NULL;
862 datalink_class_t class;
863 int err;
864 boolean_t stat_create = B_FALSE;
865 char linkname[MAXLINKNAMELEN];
866
867 rw_enter(&i_dls_devnet_lock, RW_WRITER);
868
869 /*
870 * Don't allow callers to set a link name with a linkid that already
871 * has a name association (that's what rename is for).
872 */
873 if (linkid != DATALINK_INVALID_LINKID) {
874 if (mod_hash_find(i_dls_devnet_id_hash,
875 (mod_hash_key_t)(uintptr_t)linkid,
876 (mod_hash_val_t *)&ddp) == 0) {
877 err = EEXIST;
878 goto done;
879 }
880 if ((err = dls_mgmt_get_linkinfo(linkid, linkname, &class,
881 NULL, NULL)) != 0)
882 goto done;
883 }
884
885 if ((err = mod_hash_find(i_dls_devnet_hash,
886 (mod_hash_key_t)macname, (mod_hash_val_t *)&ddp)) == 0) {
887 if (ddp->dd_linkid != DATALINK_INVALID_LINKID) {
888 err = EEXIST;
889 goto done;
890 }
891
892 /*
893 * If we arrive here we know we are attempting to set
894 * the linkid on a physical link. A virtual link
895 * should never arrive here because it should never
896 * call this function without a linkid. Virtual links
897 * are created through dlgmtmd and thus we know
898 * dlmgmtd is alive to assign it a linkid (search for
899 * uses of dladm_create_datalink_id() to prove this to
900 * yourself); we don't have the same guarantee for a
901 * physical link which may perform an upcall for a
902 * linkid while dlmgmtd is down but will continue
903 * creating a devnet without the linkid (see
904 * softmac_create_datalink() to see how physical link
905 * creation works). That is why there is no entry in
906 * the id hash but there is one in the macname hash --
907 * softmac couldn't acquire a linkid the first time it
908 * called this function.
909 *
910 * Because of the check above, we also know that
911 * ddp->dd_linkid is not set. Following this, the link
912 * must still be in the DD_INITIALIZING state because
913 * that flag is removed IFF dd_linkid is set. This is
914 * why we can ASSERT the DD_INITIALIZING flag below if
915 * the call to i_dls_devnet_setzid() fails.
916 */
917 if (linkid == DATALINK_INVALID_LINKID ||
918 class != DATALINK_CLASS_PHYS) {
919 err = EINVAL;
920 goto done;
921 }
922
923 ASSERT(ddp->dd_flags & DD_INITIALIZING);
924
925 } else {
926 ddp = kmem_cache_alloc(i_dls_devnet_cachep, KM_SLEEP);
927 ddp->dd_flags = DD_INITIALIZING;
928 ddp->dd_tref = 0;
929 ddp->dd_ref++;
930 ddp->dd_owner_zid = zoneid;
931 (void) strlcpy(ddp->dd_mac, macname, sizeof (ddp->dd_mac));
932 VERIFY(mod_hash_insert(i_dls_devnet_hash,
933 (mod_hash_key_t)ddp->dd_mac, (mod_hash_val_t)ddp) == 0);
934 }
935
936 if (linkid != DATALINK_INVALID_LINKID) {
937 ddp->dd_linkid = linkid;
938 (void) strlcpy(ddp->dd_linkname, linkname,
939 sizeof (ddp->dd_linkname));
940 VERIFY(mod_hash_insert(i_dls_devnet_id_hash,
941 (mod_hash_key_t)(uintptr_t)linkid,
942 (mod_hash_val_t)ddp) == 0);
943 devnet_need_rebuild = B_TRUE;
944 stat_create = B_TRUE;
945 mutex_enter(&ddp->dd_mutex);
946 if (!ddp->dd_prop_loaded && (ddp->dd_prop_taskid == 0)) {
947 ddp->dd_prop_taskid = taskq_dispatch(system_taskq,
948 dls_devnet_prop_task, ddp, TQ_SLEEP);
949 }
950 mutex_exit(&ddp->dd_mutex);
951 }
952 err = 0;
953 done:
954 /*
955 * It is safe to drop the i_dls_devnet_lock at this point. In the case
956 * of physical devices, the softmac framework will fail the device
957 * detach based on the smac_state or smac_hold_cnt. Other cases like
958 * vnic and aggr use their own scheme to serialize creates and deletes
959 * and ensure that *ddp is valid.
960 */
961 rw_exit(&i_dls_devnet_lock);
962 if (err == 0) {
963 if (zoneid != GLOBAL_ZONEID &&
964 (err = i_dls_devnet_setzid(ddp, zoneid, B_FALSE,
965 B_FALSE)) != 0) {
966 /*
967 * At this point the link is marked as
968 * DD_INITIALIZING -- there can be no
969 * outstanding temp refs and therefore no need
970 * to wait for them.
971 */
972 ASSERT(ddp->dd_flags & DD_INITIALIZING);
973 (void) dls_devnet_unset(mh, &linkid, B_FALSE);
974 return (err);
975 }
976
977 /*
978 * The kstat subsystem holds its own locks (rather perimeter)
979 * before calling the ks_update (dls_devnet_stat_update) entry
980 * point which in turn grabs the i_dls_devnet_lock. So the
981 * lock hierarchy is kstat locks -> i_dls_devnet_lock.
982 */
983 if (stat_create)
984 dls_devnet_stat_create(ddp, zoneid, zoneid);
985 if (ddpp != NULL)
986 *ddpp = ddp;
987
988 mutex_enter(&ddp->dd_mutex);
989 if (linkid != DATALINK_INVALID_LINKID && !ddp->dd_prop_loaded &&
990 ddp->dd_prop_taskid == TASKQID_INVALID) {
991 ddp->dd_prop_taskid = taskq_dispatch(system_taskq,
992 dls_devnet_prop_task, ddp, TQ_SLEEP);
993 }
994 mutex_exit(&ddp->dd_mutex);
995
996 }
997 return (err);
998 }
999
1000 /*
1001 * Disassociate the linkid from the link identified by macname. If
1002 * wait is B_TRUE, wait until all temporary refs are released and the
1003 * prop task is finished.
1004 *
1005 * If waiting then you SHOULD NOT call this from inside the MAC perim
1006 * as deadlock will ensue. Otherwise, this function is safe to call
1007 * from inside or outside the MAC perim.
1008 */
1009 static int
1010 dls_devnet_unset(mac_handle_t mh, datalink_id_t *id, boolean_t wait)
1011 {
1012 const char *macname = mac_name(mh);
1013 dls_devnet_t *ddp;
1014 int err;
1015 mod_hash_val_t val;
1016
1017 rw_enter(&i_dls_devnet_lock, RW_WRITER);
1018 if ((err = mod_hash_find(i_dls_devnet_hash,
1019 (mod_hash_key_t)macname, (mod_hash_val_t *)&ddp)) != 0) {
1020 ASSERT(err == MH_ERR_NOTFOUND);
1021 rw_exit(&i_dls_devnet_lock);
1022 return (ENOENT);
1023 }
1024
1025 mutex_enter(&ddp->dd_mutex);
1026
1027 /*
1028 * Make sure downcalls into softmac_create or softmac_destroy from
1029 * devfs don't cv_wait on any devfs related condition for fear of
1030 * deadlock. Return EBUSY if the asynchronous thread started for
1031 * property loading as part of the post attach hasn't yet completed.
1032 */
1033 VERIFY(ddp->dd_ref != 0);
1034 if ((ddp->dd_ref != 1) || (!wait &&
1035 (ddp->dd_tref != 0 || ddp->dd_prop_taskid != 0))) {
1036 int zstatus = 0;
1037
1038 /*
1039 * There are a couple of alternatives that might be going on
1040 * here; a) the zone is shutting down and it has a transient
1041 * link assigned, in which case we want to clean it up instead
1042 * of moving it back to the global zone, or b) its possible
1043 * that we're trying to clean up an orphaned vnic that was
1044 * delegated to a zone and which wasn't cleaned up properly
1045 * when the zone went away. Check for either of these cases
1046 * before we simply return EBUSY.
1047 *
1048 * zstatus indicates which situation we are dealing with:
1049 * 0 - means return EBUSY
1050 * 1 - means case (a), cleanup transient link
1051 * -1 - means case (b), orphained VNIC
1052 */
1053 if (ddp->dd_ref > 1 && ddp->dd_zid != GLOBAL_ZONEID) {
1054 zone_t *zp;
1055
1056 if ((zp = zone_find_by_id(ddp->dd_zid)) == NULL) {
1057 zstatus = -1;
1058 } else {
1059 if (ddp->dd_transient) {
1060 zone_status_t s = zone_status_get(zp);
1061
1062 if (s >= ZONE_IS_SHUTTING_DOWN)
1063 zstatus = 1;
1064 }
1065 zone_rele(zp);
1066 }
1067 }
1068
1069 if (zstatus == 0) {
1070 mutex_exit(&ddp->dd_mutex);
1071 rw_exit(&i_dls_devnet_lock);
1072 return (EBUSY);
1073 }
1074
1075 /*
1076 * We want to delete the link, reset ref to 1;
1077 */
1078 if (zstatus == -1)
1079 /* Log a warning, but continue in this case */
1080 cmn_err(CE_WARN, "clear orphaned datalink: %s\n",
1081 ddp->dd_linkname);
1082 ddp->dd_ref = 1;
1083 }
1084
1085 ddp->dd_flags |= DD_CONDEMNED;
1086 ddp->dd_ref--;
1087 *id = ddp->dd_linkid;
1088
1089 /*
1090 * Remove this dls_devnet_t from the hash table.
1091 */
1092 VERIFY(mod_hash_remove(i_dls_devnet_hash,
1093 (mod_hash_key_t)ddp->dd_mac, &val) == 0);
1094
1095 if (ddp->dd_linkid != DATALINK_INVALID_LINKID) {
1096 VERIFY(mod_hash_remove(i_dls_devnet_id_hash,
1097 (mod_hash_key_t)(uintptr_t)ddp->dd_linkid, &val) == 0);
1098
1099 devnet_need_rebuild = B_TRUE;
1100 }
1101 rw_exit(&i_dls_devnet_lock);
1102
1103 /*
1104 * It is important to call i_dls_devnet_setzid() WITHOUT the
1105 * i_dls_devnet_lock held. The setzid call grabs the MAC
1106 * perim; thus causing DLS -> MAC lock ordering if performed
1107 * with the i_dls_devnet_lock held. This forces consumers to
1108 * grab the MAC perim before calling dls_devnet_unset() (the
1109 * locking rules state MAC -> DLS order). By performing the
1110 * setzid outside of the i_dls_devnet_lock consumers can
1111 * safely call dls_devnet_unset() outside the MAC perim.
1112 */
1113 if (ddp->dd_zid != GLOBAL_ZONEID) {
1114 dls_devnet_stat_destroy(ddp, ddp->dd_zid);
1115 (void) i_dls_devnet_setzid(ddp, GLOBAL_ZONEID, B_FALSE,
1116 B_FALSE);
1117 }
1118
1119 if (wait) {
1120 /*
1121 * Wait until all temporary references are released.
1122 * The holders of the tref need the MAC perim to
1123 * perform their work and release the tref. To avoid
1124 * deadlock, assert that the perim is never held here.
1125 */
1126 ASSERT0(MAC_PERIM_HELD(mh));
1127 while ((ddp->dd_tref != 0) || (ddp->dd_prop_taskid != 0))
1128 cv_wait(&ddp->dd_cv, &ddp->dd_mutex);
1129 } else {
1130 VERIFY(ddp->dd_tref == 0);
1131 VERIFY(ddp->dd_prop_taskid == (taskqid_t)NULL);
1132 }
1133
1134 if (ddp->dd_linkid != DATALINK_INVALID_LINKID) {
1135 dls_devnet_stat_destroy(ddp, ddp->dd_owner_zid);
1136 }
1137
1138 ddp->dd_prop_loaded = B_FALSE;
1139 ddp->dd_linkid = DATALINK_INVALID_LINKID;
1140 ddp->dd_flags = 0;
1141 mutex_exit(&ddp->dd_mutex);
1142 kmem_cache_free(i_dls_devnet_cachep, ddp);
1143
1144 return (0);
1145 }
1146
1147 /*
1148 * This is a private hold routine used when we already have the dls_link_t, thus
1149 * we know that it cannot go away.
1150 */
1151 int
1152 dls_devnet_hold_tmp_by_link(dls_link_t *dlp, dls_dl_handle_t *ddhp)
1153 {
1154 int err;
1155 dls_devnet_t *ddp = NULL;
1156
1157 rw_enter(&i_dls_devnet_lock, RW_WRITER);
1158 if ((err = mod_hash_find(i_dls_devnet_hash,
1159 (mod_hash_key_t)dlp->dl_name, (mod_hash_val_t *)&ddp)) != 0) {
1160 ASSERT(err == MH_ERR_NOTFOUND);
1161 rw_exit(&i_dls_devnet_lock);
1162 return (ENOENT);
1163 }
1164
1165 mutex_enter(&ddp->dd_mutex);
1166 ASSERT(ddp->dd_ref > 0);
1167 if (ddp->dd_flags & DD_CONDEMNED) {
1168 mutex_exit(&ddp->dd_mutex);
1169 rw_exit(&i_dls_devnet_lock);
1170 return (ENOENT);
1171 }
1172 ddp->dd_tref++;
1173 mutex_exit(&ddp->dd_mutex);
1174 rw_exit(&i_dls_devnet_lock);
1175
1176 *ddhp = ddp;
1177 return (0);
1178 }
1179
1180 static int
1181 dls_devnet_hold_common(datalink_id_t linkid, dls_devnet_t **ddpp,
1182 boolean_t tmp_hold)
1183 {
1184 dls_devnet_t *ddp;
1185 int err;
1186
1187 rw_enter(&i_dls_devnet_lock, RW_READER);
1188 if ((err = mod_hash_find(i_dls_devnet_id_hash,
1189 (mod_hash_key_t)(uintptr_t)linkid, (mod_hash_val_t *)&ddp)) != 0) {
1190 ASSERT(err == MH_ERR_NOTFOUND);
1191 rw_exit(&i_dls_devnet_lock);
1192 return (ENOENT);
1193 }
1194
1195 mutex_enter(&ddp->dd_mutex);
1196 VERIFY(ddp->dd_ref > 0);
1197 if (DD_NOT_VISIBLE(ddp->dd_flags)) {
1198 mutex_exit(&ddp->dd_mutex);
1199 rw_exit(&i_dls_devnet_lock);
1200 return (ENOENT);
1201 }
1202 if (tmp_hold)
1203 ddp->dd_tref++;
1204 else
1205 ddp->dd_ref++;
1206 mutex_exit(&ddp->dd_mutex);
1207 rw_exit(&i_dls_devnet_lock);
1208
1209 *ddpp = ddp;
1210 return (0);
1211 }
1212
1213 int
1214 dls_devnet_hold(datalink_id_t linkid, dls_devnet_t **ddpp)
1215 {
1216 return (dls_devnet_hold_common(linkid, ddpp, B_FALSE));
1217 }
1218
1219 /*
1220 * Hold the vanity naming structure (dls_devnet_t) temporarily. The request to
1221 * delete the dls_devnet_t will wait until the temporary reference is released.
1222 */
1223 int
1224 dls_devnet_hold_tmp(datalink_id_t linkid, dls_devnet_t **ddpp)
1225 {
1226 return (dls_devnet_hold_common(linkid, ddpp, B_TRUE));
1227 }
1228
1229 /*
1230 * This funtion is called when a DLS client tries to open a device node.
1231 * This dev_t could be a result of a /dev/net node access (returned by
1232 * devnet_create_rvp->dls_devnet_open()) or a direct /dev node access.
1233 * In both cases, this function bumps up the reference count of the
1234 * dls_devnet_t structure. The reference is held as long as the device node
1235 * is open. In the case of /dev/net while it is true that the initial reference
1236 * is held when the devnet_create_rvp->dls_devnet_open call happens, this
1237 * initial reference is released immediately in devnet_inactive_callback ->
1238 * dls_devnet_close(). (Note that devnet_inactive_callback() is called right
1239 * after dld_open completes, not when the /dev/net node is being closed).
1240 * To undo this function, call dls_devnet_rele()
1241 */
1242 int
1243 dls_devnet_hold_by_dev(dev_t dev, dls_dl_handle_t *ddhp)
1244 {
1245 char name[MAXNAMELEN];
1246 char *drv;
1247 dls_devnet_t *ddp;
1248 int err;
1249
1250 if ((drv = ddi_major_to_name(getmajor(dev))) == NULL)
1251 return (EINVAL);
1252
1253 (void) snprintf(name, sizeof (name), "%s%d", drv,
1254 DLS_MINOR2INST(getminor(dev)));
1255
1256 rw_enter(&i_dls_devnet_lock, RW_READER);
1257 if ((err = mod_hash_find(i_dls_devnet_hash,
1258 (mod_hash_key_t)name, (mod_hash_val_t *)&ddp)) != 0) {
1259 ASSERT(err == MH_ERR_NOTFOUND);
1260 rw_exit(&i_dls_devnet_lock);
1261 return (ENOENT);
1262 }
1263 mutex_enter(&ddp->dd_mutex);
1264 VERIFY(ddp->dd_ref > 0);
1265 if (DD_NOT_VISIBLE(ddp->dd_flags)) {
1266 mutex_exit(&ddp->dd_mutex);
1267 rw_exit(&i_dls_devnet_lock);
1268 return (ENOENT);
1269 }
1270 ddp->dd_ref++;
1271 mutex_exit(&ddp->dd_mutex);
1272 rw_exit(&i_dls_devnet_lock);
1273
1274 *ddhp = ddp;
1275 return (0);
1276 }
1277
1278 void
1279 dls_devnet_rele(dls_devnet_t *ddp)
1280 {
1281 mutex_enter(&ddp->dd_mutex);
1282 VERIFY(ddp->dd_ref > 1);
1283 ddp->dd_ref--;
1284 if ((ddp->dd_flags & DD_IMPLICIT_IPTUN) && ddp->dd_ref == 1) {
1285 mutex_exit(&ddp->dd_mutex);
1286 if (i_dls_devnet_destroy_iptun(ddp->dd_linkid) != 0)
1287 ddp->dd_flags |= DD_IMPLICIT_IPTUN;
1288 return;
1289 }
1290 mutex_exit(&ddp->dd_mutex);
1291 }
1292
1293 static int
1294 dls_devnet_hold_by_name(const char *link, dls_devnet_t **ddpp, zoneid_t zid)
1295 {
1296 char drv[MAXLINKNAMELEN];
1297 uint_t ppa;
1298 major_t major;
1299 dev_t phy_dev, tmp_dev;
1300 datalink_id_t linkid;
1301 dls_dev_handle_t ddh;
1302 int err;
1303
1304 if ((err = dls_mgmt_get_linkid_in_zone(link, &linkid, zid)) == 0)
1305 return (dls_devnet_hold(linkid, ddpp));
1306
1307 /*
1308 * If we failed to get the link's linkid because the dlmgmtd daemon
1309 * has not been started, return ENOENT so that the application can
1310 * fallback to open the /dev node.
1311 */
1312 if (err == EBADF)
1313 return (ENOENT);
1314
1315 if (err != ENOENT)
1316 return (err);
1317
1318 /*
1319 * If we reach this point it means dlmgmtd is up but has no
1320 * mapping for the link name.
1321 */
1322 if (ddi_parse(link, drv, &ppa) != DDI_SUCCESS)
1323 return (ENOENT);
1324
1325 if (IS_IPTUN_LINK(drv)) {
1326 if ((err = i_dls_devnet_create_iptun(link, drv, &linkid)) != 0)
1327 return (err);
1328 /*
1329 * At this point, an IP tunnel MAC has registered, which
1330 * resulted in a link being created.
1331 */
1332 err = dls_devnet_hold(linkid, ddpp);
1333 if (err != 0) {
1334 VERIFY(i_dls_devnet_destroy_iptun(linkid) == 0);
1335 return (err);
1336 }
1337 /*
1338 * dls_devnet_rele() will know to destroy the implicit IP
1339 * tunnel on last reference release if DD_IMPLICIT_IPTUN is
1340 * set.
1341 */
1342 (*ddpp)->dd_flags |= DD_IMPLICIT_IPTUN;
1343 return (0);
1344 }
1345
1346 /*
1347 * If this link:
1348 * (a) is a physical device, (b) this is the first boot, (c) the MAC
1349 * is not registered yet, and (d) we cannot find its linkid, then the
1350 * linkname is the same as the devname.
1351 *
1352 * First filter out invalid names.
1353 */
1354 if ((major = ddi_name_to_major(drv)) == (major_t)-1)
1355 return (ENOENT);
1356
1357 phy_dev = makedevice(major, DLS_PPA2MINOR(ppa));
1358 if (softmac_hold_device(phy_dev, &ddh) != 0)
1359 return (ENOENT);
1360
1361 /*
1362 * At this time, the MAC should be registered, check its phy_dev using
1363 * the given name.
1364 */
1365 if ((err = dls_mgmt_get_linkid(link, &linkid)) != 0 ||
1366 (err = dls_mgmt_get_phydev(linkid, &tmp_dev)) != 0) {
1367 softmac_rele_device(ddh);
1368 return (err);
1369 }
1370 if (tmp_dev != phy_dev) {
1371 softmac_rele_device(ddh);
1372 return (ENOENT);
1373 }
1374
1375 err = dls_devnet_hold(linkid, ddpp);
1376 softmac_rele_device(ddh);
1377 return (err);
1378 }
1379
1380 int
1381 dls_devnet_macname2linkid(const char *macname, datalink_id_t *linkidp)
1382 {
1383 dls_devnet_t *ddp;
1384
1385 rw_enter(&i_dls_devnet_lock, RW_READER);
1386 if (mod_hash_find(i_dls_devnet_hash, (mod_hash_key_t)macname,
1387 (mod_hash_val_t *)&ddp) != 0) {
1388 rw_exit(&i_dls_devnet_lock);
1389 return (ENOENT);
1390 }
1391
1392 *linkidp = ddp->dd_linkid;
1393 rw_exit(&i_dls_devnet_lock);
1394 return (0);
1395 }
1396
1397 /*
1398 * Get linkid for the given dev.
1399 */
1400 int
1401 dls_devnet_dev2linkid(dev_t dev, datalink_id_t *linkidp)
1402 {
1403 char macname[MAXNAMELEN];
1404 char *drv;
1405
1406 if ((drv = ddi_major_to_name(getmajor(dev))) == NULL)
1407 return (EINVAL);
1408
1409 (void) snprintf(macname, sizeof (macname), "%s%d", drv,
1410 DLS_MINOR2INST(getminor(dev)));
1411 return (dls_devnet_macname2linkid(macname, linkidp));
1412 }
1413
1414 /*
1415 * Get the link's physical dev_t. It this is a VLAN, get the dev_t of the
1416 * link this VLAN is created on.
1417 */
1418 int
1419 dls_devnet_phydev(datalink_id_t vlanid, dev_t *devp)
1420 {
1421 dls_devnet_t *ddp;
1422 int err;
1423
1424 if ((err = dls_devnet_hold_tmp(vlanid, &ddp)) != 0)
1425 return (err);
1426
1427 err = dls_mgmt_get_phydev(ddp->dd_linkid, devp);
1428 dls_devnet_rele_tmp(ddp);
1429 return (err);
1430 }
1431
1432 /*
1433 * Handle the renaming requests. There are two rename cases:
1434 *
1435 * 1. Request to rename a valid link (id1) to an non-existent link name
1436 * (id2). In this case id2 is DATALINK_INVALID_LINKID. Just check whether
1437 * id1 is held by any applications.
1438 *
1439 * In this case, the link's kstats need to be updated using the given name.
1440 *
1441 * 2. Request to rename a valid link (id1) to the name of a REMOVED
1442 * physical link (id2). In this case, check that id1 and its associated
1443 * mac is not held by any application, and update the link's linkid to id2.
1444 *
1445 * This case does not change the <link name, linkid> mapping, so the link's
1446 * kstats need to be updated with using name associated the given id2.
1447 *
1448 * The zoneinit parameter is used to allow us to create a VNIC in the global
1449 * zone which is assigned to a non-global zone. Since there is a race condition
1450 * in the create process if two VNICs have the same name, we need to rename it
1451 * after it has been assigned to the zone.
1452 */
1453 int
1454 dls_devnet_rename(datalink_id_t id1, datalink_id_t id2, const char *link,
1455 boolean_t zoneinit)
1456 {
1457 dls_dev_handle_t ddh = NULL;
1458 int err = 0;
1459 dev_t phydev = 0;
1460 dls_devnet_t *ddp;
1461 mac_perim_handle_t mph = NULL;
1462 mac_handle_t mh;
1463 mod_hash_val_t val;
1464
1465 /*
1466 * In the second case, id2 must be a REMOVED physical link.
1467 */
1468 if ((id2 != DATALINK_INVALID_LINKID) &&
1469 (dls_mgmt_get_phydev(id2, &phydev) == 0) &&
1470 softmac_hold_device(phydev, &ddh) == 0) {
1471 softmac_rele_device(ddh);
1472 return (EEXIST);
1473 }
1474
1475 /*
1476 * Hold id1 to prevent it from being detached (if a physical link).
1477 */
1478 if (dls_mgmt_get_phydev(id1, &phydev) == 0)
1479 (void) softmac_hold_device(phydev, &ddh);
1480
1481 /*
1482 * The framework does not hold hold locks across calls to the
1483 * mac perimeter, hence enter the perimeter first. This also waits
1484 * for the property loading to finish.
1485 */
1486 if ((err = mac_perim_enter_by_linkid(id1, &mph)) != 0) {
1487 softmac_rele_device(ddh);
1488 return (err);
1489 }
1490
1491 rw_enter(&i_dls_devnet_lock, RW_WRITER);
1492 if ((err = mod_hash_find(i_dls_devnet_id_hash,
1493 (mod_hash_key_t)(uintptr_t)id1, (mod_hash_val_t *)&ddp)) != 0) {
1494 ASSERT(err == MH_ERR_NOTFOUND);
1495 err = ENOENT;
1496 goto done;
1497 }
1498
1499 mutex_enter(&ddp->dd_mutex);
1500 if (!zoneinit) {
1501 if (ddp->dd_ref > 1) {
1502 mutex_exit(&ddp->dd_mutex);
1503 err = EBUSY;
1504 goto done;
1505 }
1506 }
1507 mutex_exit(&ddp->dd_mutex);
1508
1509 if (id2 == DATALINK_INVALID_LINKID) {
1510 (void) strlcpy(ddp->dd_linkname, link,
1511 sizeof (ddp->dd_linkname));
1512
1513 /* rename mac client name and its flow if exists */
1514 if ((err = mac_open(ddp->dd_mac, &mh)) != 0)
1515 goto done;
1516 if (zoneinit) {
1517 char tname[MAXLINKNAMELEN];
1518
1519 (void) snprintf(tname, sizeof (tname), "z%d_%s",
1520 ddp->dd_zid, link);
1521 (void) mac_rename_primary(mh, tname);
1522 } else {
1523 (void) mac_rename_primary(mh, link);
1524 }
1525 mac_close(mh);
1526 goto done;
1527 }
1528
1529 /*
1530 * The second case, check whether the MAC is used by any MAC
1531 * user. This must be a physical link so ddh must not be NULL.
1532 */
1533 if (ddh == NULL) {
1534 err = EINVAL;
1535 goto done;
1536 }
1537
1538 if ((err = mac_open(ddp->dd_mac, &mh)) != 0)
1539 goto done;
1540
1541 /*
1542 * We release the reference of the MAC which mac_open() is
1543 * holding. Note that this mac will not be unregistered
1544 * because the physical device is held.
1545 */
1546 mac_close(mh);
1547
1548 /*
1549 * Check if there is any other MAC clients, if not, hold this mac
1550 * exclusively until we are done.
1551 */
1552 if ((err = mac_mark_exclusive(mh)) != 0)
1553 goto done;
1554
1555 /*
1556 * Update the link's linkid.
1557 */
1558 if ((err = mod_hash_find(i_dls_devnet_id_hash,
1559 (mod_hash_key_t)(uintptr_t)id2, &val)) != MH_ERR_NOTFOUND) {
1560 mac_unmark_exclusive(mh);
1561 err = EEXIST;
1562 goto done;
1563 }
1564
1565 err = dls_mgmt_get_linkinfo(id2, ddp->dd_linkname, NULL, NULL, NULL);
1566 if (err != 0) {
1567 mac_unmark_exclusive(mh);
1568 goto done;
1569 }
1570
1571 (void) mod_hash_remove(i_dls_devnet_id_hash,
1572 (mod_hash_key_t)(uintptr_t)id1, &val);
1573
1574 ddp->dd_linkid = id2;
1575 (void) mod_hash_insert(i_dls_devnet_id_hash,
1576 (mod_hash_key_t)(uintptr_t)ddp->dd_linkid, (mod_hash_val_t)ddp);
1577
1578 mac_unmark_exclusive(mh);
1579
1580 /* load properties for new id */
1581 mutex_enter(&ddp->dd_mutex);
1582 ddp->dd_prop_loaded = B_FALSE;
1583 ddp->dd_prop_taskid = taskq_dispatch(system_taskq,
1584 dls_devnet_prop_task, ddp, TQ_SLEEP);
1585 mutex_exit(&ddp->dd_mutex);
1586
1587 done:
1588 rw_exit(&i_dls_devnet_lock);
1589
1590 if (err == 0)
1591 dls_devnet_stat_rename(ddp, zoneinit);
1592
1593 if (mph != NULL)
1594 mac_perim_exit(mph);
1595 softmac_rele_device(ddh);
1596 return (err);
1597 }
1598
1599 static int
1600 i_dls_devnet_setzid(dls_devnet_t *ddp, zoneid_t new_zoneid, boolean_t setprop,
1601 boolean_t transient)
1602 {
1603 int err;
1604 mac_perim_handle_t mph;
1605 boolean_t upcall_done = B_FALSE;
1606 datalink_id_t linkid = ddp->dd_linkid;
1607 zoneid_t old_zoneid = ddp->dd_zid;
1608 dlmgmt_door_setzoneid_t setzid;
1609 dlmgmt_setzoneid_retval_t retval;
1610
1611 if (old_zoneid == new_zoneid)
1612 return (0);
1613
1614 if ((err = mac_perim_enter_by_macname(ddp->dd_mac, &mph)) != 0)
1615 return (err);
1616
1617 /*
1618 * When changing the zoneid of an existing link, we need to tell
1619 * dlmgmtd about it. dlmgmtd already knows the zoneid associated with
1620 * newly created links.
1621 */
1622 if (setprop) {
1623 setzid.ld_cmd = DLMGMT_CMD_SETZONEID;
1624 setzid.ld_linkid = linkid;
1625 setzid.ld_zoneid = new_zoneid;
1626 err = i_dls_mgmt_upcall(&setzid, sizeof (setzid), &retval,
1627 sizeof (retval));
1628 if (err != 0)
1629 goto done;
1630
1631 /*
1632 * We set upcall_done only if the upcall is
1633 * successful. This way, if dls_link_setzid() fails,
1634 * we know another upcall must be done to reset the
1635 * dlmgmtd state.
1636 */
1637 upcall_done = B_TRUE;
1638 }
1639 if ((err = dls_link_setzid(ddp->dd_mac, new_zoneid)) == 0) {
1640 ddp->dd_zid = new_zoneid;
1641 ddp->dd_transient = transient;
1642 devnet_need_rebuild = B_TRUE;
1643 }
1644
1645 done:
1646 if (err != 0 && upcall_done) {
1647 setzid.ld_zoneid = old_zoneid;
1648 (void) i_dls_mgmt_upcall(&setzid, sizeof (setzid), &retval,
1649 sizeof (retval));
1650 }
1651 mac_perim_exit(mph);
1652 return (err);
1653 }
1654
1655 int
1656 dls_devnet_setzid(dls_dl_handle_t ddh, zoneid_t new_zid, boolean_t transient)
1657 {
1658 dls_devnet_t *ddp;
1659 int err;
1660 zoneid_t old_zid;
1661 boolean_t refheld = B_FALSE;
1662
1663 old_zid = ddh->dd_zid;
1664
1665 if (old_zid == new_zid)
1666 return (0);
1667
1668 /*
1669 * Acquire an additional reference to the link if it is being assigned
1670 * to a non-global zone from the global zone.
1671 */
1672 if (old_zid == GLOBAL_ZONEID && new_zid != GLOBAL_ZONEID) {
1673 if ((err = dls_devnet_hold(ddh->dd_linkid, &ddp)) != 0)
1674 return (err);
1675 refheld = B_TRUE;
1676 }
1677
1678 if ((err = i_dls_devnet_setzid(ddh, new_zid, B_TRUE, transient)) != 0) {
1679 if (refheld)
1680 dls_devnet_rele(ddp);
1681 return (err);
1682 }
1683
1684 /*
1685 * Release the additional reference if the link is returning to the
1686 * global zone from a non-global zone.
1687 */
1688 if (old_zid != GLOBAL_ZONEID && new_zid == GLOBAL_ZONEID)
1689 dls_devnet_rele(ddh);
1690
1691 /* Re-create kstats in the appropriate zones. */
1692 if (old_zid != GLOBAL_ZONEID)
1693 dls_devnet_stat_destroy(ddh, old_zid);
1694 if (new_zid != GLOBAL_ZONEID)
1695 dls_devnet_stat_create(ddh, new_zid, new_zid);
1696
1697 return (0);
1698 }
1699
1700 zoneid_t
1701 dls_devnet_getzid(dls_dl_handle_t ddh)
1702 {
1703 return (((dls_devnet_t *)ddh)->dd_zid);
1704 }
1705
1706 zoneid_t
1707 dls_devnet_getownerzid(dls_dl_handle_t ddh)
1708 {
1709 return (((dls_devnet_t *)ddh)->dd_owner_zid);
1710 }
1711
1712 /*
1713 * Is linkid visible from zoneid? A link is visible if it was created in the
1714 * zone, or if it is currently assigned to the zone.
1715 */
1716 boolean_t
1717 dls_devnet_islinkvisible(datalink_id_t linkid, zoneid_t zoneid)
1718 {
1719 dls_devnet_t *ddp;
1720 boolean_t result;
1721
1722 if (dls_devnet_hold_tmp(linkid, &ddp) != 0)
1723 return (B_FALSE);
1724 result = (ddp->dd_owner_zid == zoneid || ddp->dd_zid == zoneid);
1725 dls_devnet_rele_tmp(ddp);
1726 return (result);
1727 }
1728
1729 /*
1730 * Access a vanity naming node.
1731 */
1732 int
1733 dls_devnet_open_in_zone(const char *link, dls_dl_handle_t *dhp, dev_t *devp,
1734 zoneid_t zid)
1735 {
1736 dls_devnet_t *ddp;
1737 dls_link_t *dlp;
1738 zoneid_t czid = getzoneid();
1739 int err;
1740 mac_perim_handle_t mph;
1741
1742 if (czid != GLOBAL_ZONEID && czid != zid)
1743 return (ENOENT);
1744
1745 if ((err = dls_devnet_hold_by_name(link, &ddp, zid)) != 0)
1746 return (err);
1747
1748 dls_devnet_prop_task_wait(ddp);
1749
1750 /*
1751 * Opening a link that does not belong to the current non-global zone
1752 * is not allowed.
1753 */
1754 if (zid != GLOBAL_ZONEID && ddp->dd_zid != zid) {
1755 dls_devnet_rele(ddp);
1756 return (ENOENT);
1757 }
1758
1759 err = mac_perim_enter_by_macname(ddp->dd_mac, &mph);
1760 if (err != 0) {
1761 dls_devnet_rele(ddp);
1762 return (err);
1763 }
1764
1765 err = dls_link_hold_create(ddp->dd_mac, &dlp);
1766 mac_perim_exit(mph);
1767
1768 if (err != 0) {
1769 dls_devnet_rele(ddp);
1770 return (err);
1771 }
1772
1773 *dhp = ddp;
1774 *devp = dls_link_dev(dlp);
1775 return (0);
1776 }
1777
1778 int
1779 dls_devnet_open(const char *link, dls_dl_handle_t *dhp, dev_t *devp)
1780 {
1781 return (dls_devnet_open_in_zone(link, dhp, devp, getzoneid()));
1782 }
1783
1784 /*
1785 * Close access to a vanity naming node.
1786 */
1787 void
1788 dls_devnet_close(dls_dl_handle_t dlh)
1789 {
1790 dls_devnet_t *ddp = dlh;
1791 dls_link_t *dlp;
1792 mac_perim_handle_t mph;
1793
1794 VERIFY(mac_perim_enter_by_macname(ddp->dd_mac, &mph) == 0);
1795 VERIFY(dls_link_hold(ddp->dd_mac, &dlp) == 0);
1796
1797 /*
1798 * One rele for the hold placed in dls_devnet_open, another for
1799 * the hold done just above
1800 */
1801 dls_link_rele(dlp);
1802 dls_link_rele(dlp);
1803 mac_perim_exit(mph);
1804
1805 dls_devnet_rele(ddp);
1806 }
1807
1808 /*
1809 * This is used by /dev/net to rebuild the nodes for readdir(). It is not
1810 * critical and no protection is needed.
1811 */
1812 boolean_t
1813 dls_devnet_rebuild()
1814 {
1815 boolean_t updated = devnet_need_rebuild;
1816
1817 devnet_need_rebuild = B_FALSE;
1818 return (updated);
1819 }
1820
1821 int
1822 dls_devnet_create(mac_handle_t mh, datalink_id_t linkid, zoneid_t zoneid)
1823 {
1824 dls_link_t *dlp;
1825 dls_devnet_t *ddp;
1826 int err;
1827 mac_perim_handle_t mph;
1828
1829 /*
1830 * Holding the mac perimeter ensures that the downcall from the
1831 * dlmgmt daemon which does the property loading does not proceed
1832 * until we relinquish the perimeter.
1833 */
1834 mac_perim_enter_by_mh(mh, &mph);
1835 /*
1836 * Make this association before we call dls_link_hold_create as
1837 * we need to use the linkid to get the user name for the link
1838 * when we create the MAC client.
1839 */
1840 if ((err = dls_devnet_set(mh, linkid, zoneid, &ddp)) == 0) {
1841 if ((err = dls_link_hold_create(mac_name(mh), &dlp)) != 0) {
1842 mac_perim_exit(mph);
1843 (void) dls_devnet_unset(mh, &linkid, B_FALSE);
1844 return (err);
1845 }
1846
1847 /*
1848 * If dd_linkid is set then the link was successfully
1849 * initialized. In this case we can remove the
1850 * initializing flag and make the link visible to the
1851 * rest of the system.
1852 *
1853 * If not set then we were called by softmac and it
1854 * was unable to obtain a linkid for the physical link
1855 * because dlmgmtd is down. In that case softmac will
1856 * eventually obtain a linkid and call
1857 * dls_devnet_recreate() to complete initialization.
1858 */
1859 mutex_enter(&ddp->dd_mutex);
1860 if (ddp->dd_linkid != DATALINK_INVALID_LINKID)
1861 ddp->dd_flags &= ~DD_INITIALIZING;
1862 mutex_exit(&ddp->dd_mutex);
1863
1864 }
1865
1866 mac_perim_exit(mph);
1867 return (err);
1868 }
1869
1870 /*
1871 * Set the linkid of the dls_devnet_t and add it into the i_dls_devnet_id_hash.
1872 * This is called in the case that the dlmgmtd daemon is started later than
1873 * the physical devices get attached, and the linkid is only known after the
1874 * daemon starts.
1875 */
1876 int
1877 dls_devnet_recreate(mac_handle_t mh, datalink_id_t linkid)
1878 {
1879 dls_devnet_t *ddp;
1880 int err;
1881
1882 VERIFY(linkid != DATALINK_INVALID_LINKID);
1883 if ((err = dls_devnet_set(mh, linkid, GLOBAL_ZONEID, &ddp)) == 0) {
1884 mutex_enter(&ddp->dd_mutex);
1885 if (ddp->dd_linkid != DATALINK_INVALID_LINKID)
1886 ddp->dd_flags &= ~DD_INITIALIZING;
1887 mutex_exit(&ddp->dd_mutex);
1888 }
1889
1890 return (err);
1891
1892 }
1893
1894 int
1895 dls_devnet_destroy(mac_handle_t mh, datalink_id_t *idp, boolean_t wait)
1896 {
1897 int err;
1898 mac_perim_handle_t mph;
1899
1900 *idp = DATALINK_INVALID_LINKID;
1901 err = dls_devnet_unset(mh, idp, wait);
1902
1903 /*
1904 * We continue on in the face of ENOENT because the devnet
1905 * unset and DLS link release are not atomic and we may have a
1906 * scenario where there is no entry in i_dls_devnet_hash for
1907 * the MAC name but there is an entry in i_dls_link_hash. For
1908 * example, if the following occurred:
1909 *
1910 * 1. dls_devnet_unset() returns success, and
1911 *
1912 * 2. dls_link_rele_by_name() fails with ENOTEMPTY because
1913 * flows still exist, and
1914 *
1915 * 3. dls_devnet_set() fails to set the zone id and calls
1916 * dls_devnet_unset() -- leaving an entry in
1917 * i_dls_link_hash but no corresponding entry in
1918 * i_dls_devnet_hash.
1919 *
1920 * Even if #3 wasn't true the dls_devnet_set() may fail for
1921 * different reasons in the future; the point is that it _can_
1922 * fail as part of its contract. We can't rely on it working
1923 * so we must assume that these two pieces of state (devnet
1924 * and link hashes), which should always be in sync, can get
1925 * out of sync and thus even if we get ENOENT from the devnet
1926 * hash we should still try to delete from the link hash just
1927 * in case.
1928 *
1929 * We could prevent the ENOTEMPTY from dls_link_rele_by_name()
1930 * by calling mac_disable() before calling
1931 * dls_devnet_destroy() but that's not currently possible due
1932 * to a long-standing bug. OpenSolaris 6791335: The semantics
1933 * of mac_disable() were modified by Crossbow such that
1934 * dls_devnet_destroy() needs to be called before
1935 * mac_disable() can succeed. This is because of the implicit
1936 * reference that dls has on the mac_impl_t.
1937 */
1938 if (err != 0 && err != ENOENT) {
1939 return (err);
1940 }
1941
1942 mac_perim_enter_by_mh(mh, &mph);
1943 err = dls_link_rele_by_name(mac_name(mh));
1944 if (err != 0) {
1945 dls_devnet_t *ddp;
1946
1947 /*
1948 * XXX It is a general GLDv3 bug that dls_devnet_set() has to
1949 * be called to re-set the link when destroy fails. The
1950 * zoneid below will be incorrect if this function is ever
1951 * called from kernel context or from a zone other than that
1952 * which initially created the link.
1953 */
1954 (void) dls_devnet_set(mh, *idp, crgetzoneid(CRED()), &ddp);
1955
1956 /*
1957 * You might think dd_linkid should always be set
1958 * here, but in the case where dls_devnet_unset()
1959 * returns ENOENT it will be DATALINK_INVALID_LINKID.
1960 * Stay consistent with the rest of DLS and only
1961 * remove the initializing flag if linkid is set.
1962 */
1963 mutex_enter(&ddp->dd_mutex);
1964 if (ddp->dd_linkid != DATALINK_INVALID_LINKID)
1965 ddp->dd_flags &= ~DD_INITIALIZING;
1966 mutex_exit(&ddp->dd_mutex);
1967 }
1968
1969 mac_perim_exit(mph);
1970 return (err);
1971 }
1972
1973 /*
1974 * Implicitly create an IP tunnel link.
1975 */
1976 static int
1977 i_dls_devnet_create_iptun(const char *linkname, const char *drvname,
1978 datalink_id_t *linkid)
1979 {
1980 int err;
1981 iptun_kparams_t ik;
1982 uint32_t media;
1983 netstack_t *ns;
1984 major_t iptun_major;
1985 dev_info_t *iptun_dip;
1986
1987 /* First ensure that the iptun device is attached. */
1988 if ((iptun_major = ddi_name_to_major(IPTUN_DRIVER_NAME)) == (major_t)-1)
1989 return (EINVAL);
1990 if ((iptun_dip = ddi_hold_devi_by_instance(iptun_major, 0, 0)) == NULL)
1991 return (EINVAL);
1992
1993 if (IS_IPV4_TUN(drvname)) {
1994 ik.iptun_kparam_type = IPTUN_TYPE_IPV4;
1995 media = DL_IPV4;
1996 } else if (IS_6TO4_TUN(drvname)) {
1997 ik.iptun_kparam_type = IPTUN_TYPE_6TO4;
1998 media = DL_6TO4;
1999 } else if (IS_IPV6_TUN(drvname)) {
2000 ik.iptun_kparam_type = IPTUN_TYPE_IPV6;
2001 media = DL_IPV6;
2002 }
2003 ik.iptun_kparam_flags = (IPTUN_KPARAM_TYPE | IPTUN_KPARAM_IMPLICIT);
2004
2005 /* Obtain a datalink id for this tunnel. */
2006 err = dls_mgmt_create((char *)linkname, 0, DATALINK_CLASS_IPTUN, media,
2007 B_FALSE, &ik.iptun_kparam_linkid);
2008 if (err != 0) {
2009 ddi_release_devi(iptun_dip);
2010 return (err);
2011 }
2012
2013 ns = netstack_get_current();
2014 err = iptun_create(&ik, CRED());
2015 netstack_rele(ns);
2016
2017 if (err != 0)
2018 VERIFY(dls_mgmt_destroy(ik.iptun_kparam_linkid, B_FALSE) == 0);
2019 else
2020 *linkid = ik.iptun_kparam_linkid;
2021
2022 ddi_release_devi(iptun_dip);
2023 return (err);
2024 }
2025
2026 static int
2027 i_dls_devnet_destroy_iptun(datalink_id_t linkid)
2028 {
2029 int err;
2030
2031 /*
2032 * Note the use of zone_kcred() here as opposed to CRED(). This is
2033 * because the process that does the last close of this /dev/net node
2034 * may not have necessary privileges to delete this IP tunnel, but the
2035 * tunnel must always be implicitly deleted on last close.
2036 */
2037 if ((err = iptun_delete(linkid, zone_kcred())) == 0)
2038 (void) dls_mgmt_destroy(linkid, B_FALSE);
2039 return (err);
2040 }
2041
2042 const char *
2043 dls_devnet_link(dls_dl_handle_t ddh)
2044 {
2045 return (ddh->dd_linkname);
2046 }
2047
2048 const char *
2049 dls_devnet_mac(dls_dl_handle_t ddh)
2050 {
2051 return (ddh->dd_mac);
2052 }
2053
2054 datalink_id_t
2055 dls_devnet_linkid(dls_dl_handle_t ddh)
2056 {
2057 return (ddh->dd_linkid);
2058 }