17c478bdstevel@tonic-gate/*
27c478bdstevel@tonic-gate * CDDL HEADER START
37c478bdstevel@tonic-gate *
47c478bdstevel@tonic-gate * The contents of this file are subject to the terms of the
5ba2e444seb * Common Development and Distribution License (the "License").
6ba2e444seb * You may not use this file except in compliance with the License.
77c478bdstevel@tonic-gate *
87c478bdstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bdstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bdstevel@tonic-gate * See the License for the specific language governing permissions
117c478bdstevel@tonic-gate * and limitations under the License.
127c478bdstevel@tonic-gate *
137c478bdstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bdstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bdstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bdstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bdstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bdstevel@tonic-gate *
197c478bdstevel@tonic-gate * CDDL HEADER END
207c478bdstevel@tonic-gate */
217c478bdstevel@tonic-gate/*
221cfa752Ramaswamy Tummala * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
2345d3dd9Robert Mustacchi * Copyright (c) 2017, Joyent, Inc.
247c478bdstevel@tonic-gate */
257c478bdstevel@tonic-gate
267c478bdstevel@tonic-gate/*
277c478bdstevel@tonic-gate * Data-Link Driver
287c478bdstevel@tonic-gate */
297c478bdstevel@tonic-gate
307c478bdstevel@tonic-gate#include	<sys/conf.h>
31210db22ericheng#include	<sys/mkdev.h>
327c478bdstevel@tonic-gate#include	<sys/modctl.h>
33210db22ericheng#include	<sys/stat.h>
347c478bdstevel@tonic-gate#include	<sys/dld_impl.h>
3582a2fc4James Carlson#include	<sys/dld_ioc.h>
36210db22ericheng#include	<sys/dls_impl.h>
37d62bc4byz#include	<sys/softmac.h>
38da14cebEric Cheng#include	<sys/mac.h>
39da14cebEric Cheng#include	<sys/mac_ether.h>
40da14cebEric Cheng#include	<sys/mac_client.h>
41da14cebEric Cheng#include	<sys/mac_client_impl.h>
42da14cebEric Cheng#include	<sys/mac_client_priv.h>
43210db22ericheng#include	<inet/common.h>
44da14cebEric Cheng#include	<sys/policy.h>
45da14cebEric Cheng#include	<sys/priv_names.h>
462b24ab6Sebastien Roy#include	<sys/zone.h>
470591dddPrakash Jalan#include	<sys/sysmacros.h>
48210db22ericheng
497c478bdstevel@tonic-gatestatic void	drv_init(void);
507c478bdstevel@tonic-gatestatic int	drv_fini(void);
517c478bdstevel@tonic-gate
527c478bdstevel@tonic-gatestatic int	drv_getinfo(dev_info_t	*, ddi_info_cmd_t, void *, void **);
537c478bdstevel@tonic-gatestatic int	drv_attach(dev_info_t *, ddi_attach_cmd_t);
547c478bdstevel@tonic-gatestatic int	drv_detach(dev_info_t *, ddi_detach_cmd_t);
557c478bdstevel@tonic-gate
56210db22ericheng/*
570ba2cbexc * Secure objects declarations
580ba2cbexc */
590ba2cbexc#define	SECOBJ_WEP_HASHSZ	67
600ba2cbexcstatic krwlock_t	drv_secobj_lock;
610ba2cbexcstatic kmem_cache_t	*drv_secobj_cachep;
620ba2cbexcstatic mod_hash_t	*drv_secobj_hash;
630ba2cbexcstatic void		drv_secobj_init(void);
640ba2cbexcstatic void		drv_secobj_fini(void);
653bc21d0Aruna Ramakrishna - Sun Microsystemsstatic int		drv_ioc_setap(datalink_id_t, struct dlautopush *);
663bc21d0Aruna Ramakrishna - Sun Microsystemsstatic int		drv_ioc_getap(datalink_id_t, struct dlautopush *);
673bc21d0Aruna Ramakrishna - Sun Microsystemsstatic int		drv_ioc_clrap(datalink_id_t);
680ba2cbexc
69eae72b5Sebastien Roy
700ba2cbexc/*
71210db22ericheng * The following entry points are private to dld and are used for control
72210db22ericheng * operations only. The entry points exported to mac drivers are defined
73210db22ericheng * in dld_str.c. Refer to the comment on top of dld_str.c for details.
74210db22ericheng */
75eae72b5Sebastien Roystatic int	drv_open(dev_t *, int, int, cred_t *);
76eae72b5Sebastien Roystatic int	drv_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
777c478bdstevel@tonic-gate
78eae72b5Sebastien Roystatic dev_info_t	*dld_dip;	/* dev_info_t for the driver */
79eae72b5Sebastien Royuint32_t		dld_opt = 0;	/* Global options */
807c478bdstevel@tonic-gate
81d62bc4byz#define	NAUTOPUSH 32
82d62bc4byzstatic mod_hash_t *dld_ap_hashp;
83d62bc4byzstatic krwlock_t dld_ap_hash_lock;
84d62bc4byz
85eae72b5Sebastien Roystatic struct cb_ops drv_cb_ops = {
86eae72b5Sebastien Roy	drv_open,		/* open */
87eae72b5Sebastien Roy	nulldev,		/* close */
88eae72b5Sebastien Roy	nulldev,		/* strategy */
89eae72b5Sebastien Roy	nulldev,		/* print */
90eae72b5Sebastien Roy	nodev,			/* dump */
91eae72b5Sebastien Roy	nodev,			/* read */
92eae72b5Sebastien Roy	nodev,			/* write */
93eae72b5Sebastien Roy	drv_ioctl,		/* ioctl */
94eae72b5Sebastien Roy	nodev,			/* devmap */
95eae72b5Sebastien Roy	nodev,			/* mmap */
96eae72b5Sebastien Roy	nodev,			/* segmap */
97eae72b5Sebastien Roy	nochpoll,		/* poll */
98eae72b5Sebastien Roy	ddi_prop_op,		/* cb_prop_op */
99eae72b5Sebastien Roy	0,			/* streamtab  */
100eae72b5Sebastien Roy	D_MP			/* Driver compatibility flag */
1017c478bdstevel@tonic-gate};
1027c478bdstevel@tonic-gate
103eae72b5Sebastien Roystatic struct dev_ops drv_ops = {
104eae72b5Sebastien Roy	DEVO_REV,		/* devo_rev */
105eae72b5Sebastien Roy	0,			/* refcnt */
106eae72b5Sebastien Roy	drv_getinfo,		/* get_dev_info */
107eae72b5Sebastien Roy	nulldev,		/* identify */
108eae72b5Sebastien Roy	nulldev,		/* probe */
109eae72b5Sebastien Roy	drv_attach,		/* attach */
110eae72b5Sebastien Roy	drv_detach,		/* detach */
111eae72b5Sebastien Roy	nodev,			/* reset */
112eae72b5Sebastien Roy	&drv_cb_ops,		/* driver operations */
113eae72b5Sebastien Roy	NULL,			/* bus operations */
1141939740Sherry Moore	nodev,			/* dev power */
1151939740Sherry Moore	ddi_quiesce_not_supported,	/* dev quiesce */
1167c478bdstevel@tonic-gate};
1177c478bdstevel@tonic-gate
1187c478bdstevel@tonic-gate/*
1197c478bdstevel@tonic-gate * Module linkage information for the kernel.
1207c478bdstevel@tonic-gate */
1217c478bdstevel@tonic-gatestatic	struct modldrv		drv_modldrv = {
1227c478bdstevel@tonic-gate	&mod_driverops,
1237c478bdstevel@tonic-gate	DLD_INFO,
1247c478bdstevel@tonic-gate	&drv_ops
1257c478bdstevel@tonic-gate};
1267c478bdstevel@tonic-gate
1277c478bdstevel@tonic-gatestatic	struct modlinkage	drv_modlinkage = {
1287c478bdstevel@tonic-gate	MODREV_1,
1297c478bdstevel@tonic-gate	&drv_modldrv,
1307c478bdstevel@tonic-gate	NULL
1317c478bdstevel@tonic-gate};
1327c478bdstevel@tonic-gate
1337c478bdstevel@tonic-gateint
1347c478bdstevel@tonic-gate_init(void)
1357c478bdstevel@tonic-gate{
136eae72b5Sebastien Roy	return (mod_install(&drv_modlinkage));
1377c478bdstevel@tonic-gate}
1387c478bdstevel@tonic-gate
1397c478bdstevel@tonic-gateint
1407c478bdstevel@tonic-gate_fini(void)
1417c478bdstevel@tonic-gate{
142eae72b5Sebastien Roy	return (mod_remove(&drv_modlinkage));
1437c478bdstevel@tonic-gate}
1447c478bdstevel@tonic-gate
1457c478bdstevel@tonic-gateint
1467c478bdstevel@tonic-gate_info(struct modinfo *modinfop)
1477c478bdstevel@tonic-gate{
1487c478bdstevel@tonic-gate	return (mod_info(&drv_modlinkage, modinfop));
1497c478bdstevel@tonic-gate}
1507c478bdstevel@tonic-gate
1517c478bdstevel@tonic-gate/*
152210db22ericheng * Initialize component modules.
1537c478bdstevel@tonic-gate */
1547c478bdstevel@tonic-gatestatic void
1557c478bdstevel@tonic-gatedrv_init(void)
1567c478bdstevel@tonic-gate{
1570ba2cbexc	drv_secobj_init();
1587c478bdstevel@tonic-gate	dld_str_init();
159da14cebEric Cheng
160d62bc4byz	/*
161d62bc4byz	 * Create a hash table for autopush configuration.
162d62bc4byz	 */
163d62bc4byz	dld_ap_hashp = mod_hash_create_idhash("dld_autopush_hash",
164d62bc4byz	    NAUTOPUSH, mod_hash_null_valdtor);
165d62bc4byz
166d62bc4byz	ASSERT(dld_ap_hashp != NULL);
167d62bc4byz	rw_init(&dld_ap_hash_lock, NULL, RW_DRIVER, NULL);
168d62bc4byz}
169d62bc4byz
170d62bc4byz/* ARGSUSED */
171d62bc4byzstatic uint_t
172d62bc4byzdrv_ap_exist(mod_hash_key_t key, mod_hash_val_t *val, void *arg)
173d62bc4byz{
174d62bc4byz	boolean_t *pexist = arg;
175d62bc4byz
176d62bc4byz	*pexist = B_TRUE;
177d62bc4byz	return (MH_WALK_TERMINATE);
1787c478bdstevel@tonic-gate}
1797c478bdstevel@tonic-gate
1807c478bdstevel@tonic-gatestatic int
1817c478bdstevel@tonic-gatedrv_fini(void)
1827c478bdstevel@tonic-gate{
183d62bc4byz	int		err;
184d62bc4byz	boolean_t	exist = B_FALSE;
185d62bc4byz
186d62bc4byz	rw_enter(&dld_ap_hash_lock, RW_READER);
187d62bc4byz	mod_hash_walk(dld_ap_hashp, drv_ap_exist, &exist);
188d62bc4byz	rw_exit(&dld_ap_hash_lock);
189d62bc4byz	if (exist)
190d62bc4byz		return (EBUSY);
1917c478bdstevel@tonic-gate
192210db22ericheng	if ((err = dld_str_fini()) != 0)
1937c478bdstevel@tonic-gate		return (err);
1947c478bdstevel@tonic-gate
1950ba2cbexc	drv_secobj_fini();
196d62bc4byz	mod_hash_destroy_idhash(dld_ap_hashp);
197d62bc4byz	rw_destroy(&dld_ap_hash_lock);
1987c478bdstevel@tonic-gate	return (0);
1997c478bdstevel@tonic-gate}
2007c478bdstevel@tonic-gate
2017c478bdstevel@tonic-gate/*
2027c478bdstevel@tonic-gate * devo_getinfo: getinfo(9e)
2037c478bdstevel@tonic-gate */
2047c478bdstevel@tonic-gate/*ARGSUSED*/
2057c478bdstevel@tonic-gatestatic int
2067c478bdstevel@tonic-gatedrv_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **resp)
2077c478bdstevel@tonic-gate{
2087c478bdstevel@tonic-gate	if (dld_dip == NULL)
2097c478bdstevel@tonic-gate		return (DDI_FAILURE);
2107c478bdstevel@tonic-gate
2117c478bdstevel@tonic-gate	switch (cmd) {
2127c478bdstevel@tonic-gate	case DDI_INFO_DEVT2INSTANCE:
213eae72b5Sebastien Roy		*resp = 0;
2147c478bdstevel@tonic-gate		break;
2157c478bdstevel@tonic-gate	case DDI_INFO_DEVT2DEVINFO:
216eae72b5Sebastien Roy		*resp = dld_dip;
2177c478bdstevel@tonic-gate		break;
2187c478bdstevel@tonic-gate	default:
2197c478bdstevel@tonic-gate		return (DDI_FAILURE);
2207c478bdstevel@tonic-gate	}
2217c478bdstevel@tonic-gate
2227c478bdstevel@tonic-gate	return (DDI_SUCCESS);
2237c478bdstevel@tonic-gate}
2247c478bdstevel@tonic-gate
2257c478bdstevel@tonic-gate/*
2267c478bdstevel@tonic-gate * Check properties to set options. (See dld.h for property definitions).
2277c478bdstevel@tonic-gate */
2287c478bdstevel@tonic-gatestatic void
2297c478bdstevel@tonic-gatedrv_set_opt(dev_info_t *dip)
2307c478bdstevel@tonic-gate{
2317c478bdstevel@tonic-gate	if (ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
2327c478bdstevel@tonic-gate	    DLD_PROP_NO_FASTPATH, 0) != 0) {
2337c478bdstevel@tonic-gate		dld_opt |= DLD_OPT_NO_FASTPATH;
2347c478bdstevel@tonic-gate	}
2357c478bdstevel@tonic-gate
2367c478bdstevel@tonic-gate	if (ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
2377c478bdstevel@tonic-gate	    DLD_PROP_NO_POLL, 0) != 0) {
2387c478bdstevel@tonic-gate		dld_opt |= DLD_OPT_NO_POLL;
2397c478bdstevel@tonic-gate	}
2407c478bdstevel@tonic-gate
2417c478bdstevel@tonic-gate	if (ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
2427c478bdstevel@tonic-gate	    DLD_PROP_NO_ZEROCOPY, 0) != 0) {
2437c478bdstevel@tonic-gate		dld_opt |= DLD_OPT_NO_ZEROCOPY;
2447c478bdstevel@tonic-gate	}
2459c17512ja
2469c17512ja	if (ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
2479c17512ja	    DLD_PROP_NO_SOFTRING, 0) != 0) {
2489c17512ja		dld_opt |= DLD_OPT_NO_SOFTRING;
2499c17512ja	}
2507c478bdstevel@tonic-gate}
2517c478bdstevel@tonic-gate
2527c478bdstevel@tonic-gate/*
2537c478bdstevel@tonic-gate * devo_attach: attach(9e)
2547c478bdstevel@tonic-gate */
2557c478bdstevel@tonic-gatestatic int
2567c478bdstevel@tonic-gatedrv_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
2577c478bdstevel@tonic-gate{
2587c478bdstevel@tonic-gate	if (cmd != DDI_ATTACH)
2597c478bdstevel@tonic-gate		return (DDI_FAILURE);
2607c478bdstevel@tonic-gate
2617c478bdstevel@tonic-gate	ASSERT(ddi_get_instance(dip) == 0);
262eae72b5Sebastien Roy	drv_init();
2637c478bdstevel@tonic-gate	drv_set_opt(dip);
2647c478bdstevel@tonic-gate
2657c478bdstevel@tonic-gate	/*
2667c478bdstevel@tonic-gate	 * Create control node. DLPI provider nodes will be created on demand.
2677c478bdstevel@tonic-gate	 */
2687c478bdstevel@tonic-gate	if (ddi_create_minor_node(dip, DLD_CONTROL_MINOR_NAME, S_IFCHR,
2697c478bdstevel@tonic-gate	    DLD_CONTROL_MINOR, DDI_PSEUDO, 0) != DDI_SUCCESS)
2707c478bdstevel@tonic-gate		return (DDI_FAILURE);
2717c478bdstevel@tonic-gate
2727c478bdstevel@tonic-gate	dld_dip = dip;
2737c478bdstevel@tonic-gate
2747c478bdstevel@tonic-gate	/*
2757c478bdstevel@tonic-gate	 * Log the fact that the driver is now attached.
2767c478bdstevel@tonic-gate	 */
2777c478bdstevel@tonic-gate	ddi_report_dev(dip);
2787c478bdstevel@tonic-gate	return (DDI_SUCCESS);
2797c478bdstevel@tonic-gate}
2807c478bdstevel@tonic-gate
2817c478bdstevel@tonic-gate/*
2827c478bdstevel@tonic-gate * devo_detach: detach(9e)
2837c478bdstevel@tonic-gate */
2847c478bdstevel@tonic-gatestatic int
2857c478bdstevel@tonic-gatedrv_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
2867c478bdstevel@tonic-gate{
2877c478bdstevel@tonic-gate	if (cmd != DDI_DETACH)
2887c478bdstevel@tonic-gate		return (DDI_FAILURE);
2897c478bdstevel@tonic-gate
2907c478bdstevel@tonic-gate	ASSERT(dld_dip == dip);
291eae72b5Sebastien Roy	if (drv_fini() != 0)
292eae72b5Sebastien Roy		return (DDI_FAILURE);
2937c478bdstevel@tonic-gate
2947c478bdstevel@tonic-gate	/*
2957c478bdstevel@tonic-gate	 * Remove the control node.
2967c478bdstevel@tonic-gate	 */
2977c478bdstevel@tonic-gate	ddi_remove_minor_node(dip, DLD_CONTROL_MINOR_NAME);
2987c478bdstevel@tonic-gate	dld_dip = NULL;
2997c478bdstevel@tonic-gate
3007c478bdstevel@tonic-gate	return (DDI_SUCCESS);
3017c478bdstevel@tonic-gate}
3027c478bdstevel@tonic-gate
3037c478bdstevel@tonic-gate/*
304210db22ericheng * dld control node open procedure.
3057c478bdstevel@tonic-gate */
3067c478bdstevel@tonic-gate/*ARGSUSED*/
3077c478bdstevel@tonic-gatestatic int
308eae72b5Sebastien Roydrv_open(dev_t *devp, int flag, int sflag, cred_t *credp)
3097c478bdstevel@tonic-gate{
3107c478bdstevel@tonic-gate	/*
311eae72b5Sebastien Roy	 * Only the control node can be opened.
3127c478bdstevel@tonic-gate	 */
313eae72b5Sebastien Roy	if (getminor(*devp) != DLD_CONTROL_MINOR)
314eae72b5Sebastien Roy		return (ENODEV);
3157c478bdstevel@tonic-gate	return (0);
3167c478bdstevel@tonic-gate}
3177c478bdstevel@tonic-gate
3187c478bdstevel@tonic-gate/*
3192b24ab6Sebastien Roy * Verify if the caller is allowed to modify a link of the given class.
3202b24ab6Sebastien Roy */
3212b24ab6Sebastien Roystatic int
3222b24ab6Sebastien Roydrv_ioc_checkprivs(datalink_class_t class, cred_t *cred)
3232b24ab6Sebastien Roy{
3242b24ab6Sebastien Roy	if (class == DATALINK_CLASS_IPTUN)
3252b24ab6Sebastien Roy		return (secpolicy_iptun_config(cred));
3262b24ab6Sebastien Roy	return (secpolicy_dl_config(cred));
3272b24ab6Sebastien Roy}
3282b24ab6Sebastien Roy
3292b24ab6Sebastien Roy/*
330d62bc4byz * DLDIOC_ATTR
3317c478bdstevel@tonic-gate */
332eae72b5Sebastien Roy/* ARGSUSED */
333eae72b5Sebastien Roystatic int
334da14cebEric Chengdrv_ioc_attr(void *karg, intptr_t arg, int mode, cred_t *cred, int *rvalp)
3357c478bdstevel@tonic-gate{
336eae72b5Sebastien Roy	dld_ioc_attr_t		*diap = karg;
337d62bc4byz	dls_dl_handle_t		dlh;
338da14cebEric Cheng	dls_link_t		*dlp;
3392b24ab6Sebastien Roy	zoneid_t		zoneid = crgetzoneid(cred);
340d62bc4byz	int			err;
341da14cebEric Cheng	mac_perim_handle_t	mph;
342210db22ericheng
3432b24ab6Sebastien Roy	if (zoneid != GLOBAL_ZONEID &&
3442b24ab6Sebastien Roy	    zone_check_datalink(&zoneid, diap->dia_linkid) != 0)
3452b24ab6Sebastien Roy		return (ENOENT);
3462b24ab6Sebastien Roy
347d62bc4byz	if ((err = dls_devnet_hold_tmp(diap->dia_linkid, &dlh)) != 0)
348eae72b5Sebastien Roy		return (err);
349210db22ericheng
350da14cebEric Cheng	if ((err = mac_perim_enter_by_macname(
351da14cebEric Cheng	    dls_devnet_mac(dlh), &mph)) != 0) {
352d62bc4byz		dls_devnet_rele_tmp(dlh);
353eae72b5Sebastien Roy		return (err);
354d62bc4byz	}
355210db22ericheng
356da14cebEric Cheng	if ((err = dls_link_hold(dls_devnet_mac(dlh), &dlp)) != 0) {
357da14cebEric Cheng		mac_perim_exit(mph);
358da14cebEric Cheng		dls_devnet_rele_tmp(dlh);
359da14cebEric Cheng		return (err);
360da14cebEric Cheng	}
361da14cebEric Cheng
362da14cebEric Cheng	mac_sdu_get(dlp->dl_mh, NULL, &diap->dia_max_sdu);
363da14cebEric Cheng
364da14cebEric Cheng	dls_link_rele(dlp);
365da14cebEric Cheng	mac_perim_exit(mph);
366d62bc4byz	dls_devnet_rele_tmp(dlh);
367d62bc4byz
368eae72b5Sebastien Roy	return (0);
369d62bc4byz}
370210db22ericheng
371d62bc4byz/*
372d62bc4byz * DLDIOC_PHYS_ATTR
373d62bc4byz */
374eae72b5Sebastien Roy/* ARGSUSED */
375eae72b5Sebastien Roystatic int
376da14cebEric Chengdrv_ioc_phys_attr(void *karg, intptr_t arg, int mode, cred_t *cred, int *rvalp)
377d62bc4byz{
378eae72b5Sebastien Roy	dld_ioc_phys_attr_t	*dipp = karg;
379d62bc4byz	int			err;
380d62bc4byz	dls_dl_handle_t		dlh;
381d62bc4byz	dls_dev_handle_t	ddh;
382d62bc4byz	dev_t			phydev;
3832b24ab6Sebastien Roy	zoneid_t		zoneid = crgetzoneid(cred);
3842b24ab6Sebastien Roy
3852b24ab6Sebastien Roy	if (zoneid != GLOBAL_ZONEID &&
3862b24ab6Sebastien Roy	    zone_check_datalink(&zoneid, dipp->dip_linkid) != 0)
3872b24ab6Sebastien Roy		return (ENOENT);
388d62bc4byz
389d62bc4byz	/*
390d62bc4byz	 * Every physical link should have its physical dev_t kept in the
391d62bc4byz	 * daemon. If not, it is not a valid physical link.
392d62bc4byz	 */
393eae72b5Sebastien Roy	if (dls_mgmt_get_phydev(dipp->dip_linkid, &phydev) != 0)
394eae72b5Sebastien Roy		return (EINVAL);
395d62bc4byz
396d62bc4byz	/*
397d62bc4byz	 * Although this is a valid physical link, it might already be removed
398d62bc4byz	 * by DR or during system shutdown. softmac_hold_device() would return
399d62bc4byz	 * ENOENT in this case.
400d62bc4byz	 */
401d62bc4byz	if ((err = softmac_hold_device(phydev, &ddh)) != 0)
402eae72b5Sebastien Roy		return (err);
403d62bc4byz
404d62bc4byz	if (dls_devnet_hold_tmp(dipp->dip_linkid, &dlh) != 0) {
405210db22ericheng		/*
406d62bc4byz		 * Although this is an active physical link, its link type is
407d62bc4byz		 * not supported by GLDv3, and therefore it does not have
408d62bc4byz		 * vanity naming support.
409210db22ericheng		 */
410d62bc4byz		dipp->dip_novanity = B_TRUE;
411d62bc4byz	} else {
412d62bc4byz		dipp->dip_novanity = B_FALSE;
413d62bc4byz		dls_devnet_rele_tmp(dlh);
414210db22ericheng	}
415d62bc4byz	/*
416d62bc4byz	 * Get the physical device name from the major number and the instance
417d62bc4byz	 * number derived from phydev.
418d62bc4byz	 */
419d62bc4byz	(void) snprintf(dipp->dip_dev, MAXLINKNAMELEN, "%s%d",
420d62bc4byz	    ddi_major_to_name(getmajor(phydev)), getminor(phydev) - 1);
421d62bc4byz
422d62bc4byz	softmac_rele_device(ddh);
423eae72b5Sebastien Roy	return (0);
4247c478bdstevel@tonic-gate}
4257c478bdstevel@tonic-gate
426da14cebEric Cheng/* ARGSUSED */
427da14cebEric Chengstatic int
428da14cebEric Chengdrv_ioc_hwgrpget(void *karg, intptr_t arg, int mode, cred_t *cred, int *rvalp)
429da14cebEric Cheng{
430da14cebEric Cheng	dld_ioc_hwgrpget_t	*hwgrpp = karg;
431da14cebEric Cheng	dld_hwgrpinfo_t		hwgrp, *hip;
432da14cebEric Cheng	mac_handle_t		mh = NULL;
4330dc2366Venugopal Iyer	int			i, err, rgrpnum, tgrpnum;
434da14cebEric Cheng	uint_t			bytes_left;
4350dc2366Venugopal Iyer	int			totgrps = 0;
4362b24ab6Sebastien Roy	zoneid_t		zoneid = crgetzoneid(cred);
4372b24ab6Sebastien Roy
4382b24ab6Sebastien Roy	if (zoneid != GLOBAL_ZONEID &&
4392b24ab6Sebastien Roy	    zone_check_datalink(&zoneid, hwgrpp->dih_linkid) != 0)
4402b24ab6Sebastien Roy		return (ENOENT);
441da14cebEric Cheng
442da14cebEric Cheng	hwgrpp->dih_n_groups = 0;
443da14cebEric Cheng	err = mac_open_by_linkid(hwgrpp->dih_linkid, &mh);
444da14cebEric Cheng	if (err != 0)
445da14cebEric Cheng		goto done;
446da14cebEric Cheng
447da14cebEric Cheng	hip = (dld_hwgrpinfo_t *)
448da14cebEric Cheng	    ((uchar_t *)arg + sizeof (dld_ioc_hwgrpget_t));
449da14cebEric Cheng	bytes_left = hwgrpp->dih_size;
4500dc2366Venugopal Iyer
4510dc2366Venugopal Iyer	rgrpnum = mac_hwgrp_num(mh, MAC_RING_TYPE_RX);
4520dc2366Venugopal Iyer	/* display the default group information first */
4530dc2366Venugopal Iyer	if (rgrpnum > 0) {
4540dc2366Venugopal Iyer		if (sizeof (dld_hwgrpinfo_t) > bytes_left) {
4550dc2366Venugopal Iyer			err = ENOSPC;
4560dc2366Venugopal Iyer			goto done;
4570dc2366Venugopal Iyer		}
4580dc2366Venugopal Iyer
4590dc2366Venugopal Iyer		bzero(&hwgrp, sizeof (hwgrp));
4600dc2366Venugopal Iyer		bcopy(mac_name(mh), hwgrp.dhi_link_name,
4610dc2366Venugopal Iyer		    sizeof (hwgrp.dhi_link_name));
4620dc2366Venugopal Iyer		mac_get_hwrxgrp_info(mh, 0, &hwgrp.dhi_grp_num,
4630dc2366Venugopal Iyer		    &hwgrp.dhi_n_rings, hwgrp.dhi_rings, &hwgrp.dhi_grp_type,
4640dc2366Venugopal Iyer		    &hwgrp.dhi_n_clnts, hwgrp.dhi_clnts);
4650dc2366Venugopal Iyer		if (hwgrp.dhi_n_rings != 0) {
4660dc2366Venugopal Iyer			if (copyout(&hwgrp, hip, sizeof (hwgrp)) != 0) {
4670dc2366Venugopal Iyer				err = EFAULT;
4680dc2366Venugopal Iyer				goto done;
4690dc2366Venugopal Iyer			}
4700dc2366Venugopal Iyer		}
4710dc2366Venugopal Iyer		hip++;
4720dc2366Venugopal Iyer		totgrps++;
4730dc2366Venugopal Iyer		bytes_left -= sizeof (dld_hwgrpinfo_t);
474