xref: /titanic_53/usr/src/cmd/dladm/dladm.c (revision 0b8f054691a3974b7c86dd2700ecbf6108a2d55e)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5219a2a31Shl157128  * Common Development and Distribution License (the "License").
6219a2a31Shl157128  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
22ad091ee1SMichael Lim  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate #include <stdio.h>
270ba2cbe9Sxc151355 #include <ctype.h>
287c478bd9Sstevel@tonic-gate #include <locale.h>
290ba2cbe9Sxc151355 #include <signal.h>
307c478bd9Sstevel@tonic-gate #include <stdarg.h>
317c478bd9Sstevel@tonic-gate #include <stdlib.h>
327c478bd9Sstevel@tonic-gate #include <fcntl.h>
337c478bd9Sstevel@tonic-gate #include <string.h>
347c478bd9Sstevel@tonic-gate #include <stropts.h>
35d62bc4baSyz147064 #include <sys/stat.h>
367c478bd9Sstevel@tonic-gate #include <errno.h>
377c478bd9Sstevel@tonic-gate #include <kstat.h>
387c478bd9Sstevel@tonic-gate #include <strings.h>
397c478bd9Sstevel@tonic-gate #include <getopt.h>
407c478bd9Sstevel@tonic-gate #include <unistd.h>
41cd93090eSericheng #include <priv.h>
420ba2cbe9Sxc151355 #include <termios.h>
430ba2cbe9Sxc151355 #include <pwd.h>
440ba2cbe9Sxc151355 #include <auth_attr.h>
450ba2cbe9Sxc151355 #include <auth_list.h>
467c478bd9Sstevel@tonic-gate #include <libintl.h>
47d62bc4baSyz147064 #include <libdevinfo.h>
487c478bd9Sstevel@tonic-gate #include <libdlpi.h>
49da14cebeSEric Cheng #include <libdladm.h>
50f595a68aSyz147064 #include <libdllink.h>
51da14cebeSEric Cheng #include <libdlstat.h>
52f595a68aSyz147064 #include <libdlaggr.h>
53f595a68aSyz147064 #include <libdlwlan.h>
54d62bc4baSyz147064 #include <libdlvlan.h>
55d62bc4baSyz147064 #include <libdlvnic.h>
564784fcbdSSowmini Varadhan #include <libdlether.h>
57b509e89bSRishi Srivatsavai #include <libdlsim.h>
580ba2cbe9Sxc151355 #include <libinetutil.h>
590ba2cbe9Sxc151355 #include <bsm/adt.h>
600ba2cbe9Sxc151355 #include <bsm/adt_event.h>
61da14cebeSEric Cheng #include <libdlvnic.h>
62da14cebeSEric Cheng #include <sys/types.h>
63da14cebeSEric Cheng #include <sys/socket.h>
64da14cebeSEric Cheng #include <sys/processor.h>
65da14cebeSEric Cheng #include <netinet/in.h>
66da14cebeSEric Cheng #include <arpa/inet.h>
67da14cebeSEric Cheng #include <net/if_types.h>
68e7801d59Ssowmini #include <stddef.h>
698002d411SSowmini Varadhan #include <ofmt.h>
707c478bd9Sstevel@tonic-gate 
717c478bd9Sstevel@tonic-gate #define	MAXPORT			256
72da14cebeSEric Cheng #define	MAXVNIC			256
73d62bc4baSyz147064 #define	BUFLEN(lim, ptr)	(((lim) > (ptr)) ? ((lim) - (ptr)) : 0)
74d62bc4baSyz147064 #define	MAXLINELEN		1024
75d62bc4baSyz147064 #define	SMF_UPGRADE_FILE		"/var/svc/profile/upgrade"
76d62bc4baSyz147064 #define	SMF_UPGRADEDATALINK_FILE	"/var/svc/profile/upgrade_datalink"
77d62bc4baSyz147064 #define	SMF_DLADM_UPGRADE_MSG		" # added by dladm(1M)"
788002d411SSowmini Varadhan #define	DLADM_DEFAULT_COL	80
797c478bd9Sstevel@tonic-gate 
808002d411SSowmini Varadhan /*
818002d411SSowmini Varadhan  * used by the wifi show-* commands to set up ofmt_field_t structures.
828002d411SSowmini Varadhan  */
83e7801d59Ssowmini #define	WIFI_CMD_SCAN		0x00000001
84e7801d59Ssowmini #define	WIFI_CMD_SHOW		0x00000002
85e7801d59Ssowmini #define	WIFI_CMD_ALL		(WIFI_CMD_SCAN | WIFI_CMD_SHOW)
86e7801d59Ssowmini 
87d62bc4baSyz147064 typedef struct show_state {
887c478bd9Sstevel@tonic-gate 	boolean_t	ls_firstonly;
897c478bd9Sstevel@tonic-gate 	boolean_t	ls_donefirst;
907c478bd9Sstevel@tonic-gate 	pktsum_t	ls_prevstats;
91d62bc4baSyz147064 	uint32_t	ls_flags;
92d62bc4baSyz147064 	dladm_status_t	ls_status;
938002d411SSowmini Varadhan 	ofmt_handle_t	ls_ofmt;
948002d411SSowmini Varadhan 	boolean_t	ls_parsable;
95da14cebeSEric Cheng 	boolean_t	ls_mac;
96da14cebeSEric Cheng 	boolean_t	ls_hwgrp;
97d62bc4baSyz147064 } show_state_t;
987c478bd9Sstevel@tonic-gate 
997c478bd9Sstevel@tonic-gate typedef struct show_grp_state {
100e7801d59Ssowmini 	pktsum_t	gs_prevstats[MAXPORT];
101e7801d59Ssowmini 	uint32_t	gs_flags;
102e7801d59Ssowmini 	dladm_status_t	gs_status;
1038002d411SSowmini Varadhan 	boolean_t	gs_parsable;
1047c478bd9Sstevel@tonic-gate 	boolean_t	gs_lacp;
105d62bc4baSyz147064 	boolean_t	gs_extended;
1067c478bd9Sstevel@tonic-gate 	boolean_t	gs_stats;
1077c478bd9Sstevel@tonic-gate 	boolean_t	gs_firstonly;
108d62bc4baSyz147064 	boolean_t	gs_donefirst;
1098002d411SSowmini Varadhan 	ofmt_handle_t	gs_ofmt;
1107c478bd9Sstevel@tonic-gate } show_grp_state_t;
1117c478bd9Sstevel@tonic-gate 
112da14cebeSEric Cheng typedef struct show_vnic_state {
113da14cebeSEric Cheng 	datalink_id_t	vs_vnic_id;
114da14cebeSEric Cheng 	datalink_id_t	vs_link_id;
115da14cebeSEric Cheng 	char		vs_vnic[MAXLINKNAMELEN];
116da14cebeSEric Cheng 	char		vs_link[MAXLINKNAMELEN];
1178002d411SSowmini Varadhan 	boolean_t	vs_parsable;
118da14cebeSEric Cheng 	boolean_t	vs_found;
119da14cebeSEric Cheng 	boolean_t	vs_firstonly;
120da14cebeSEric Cheng 	boolean_t	vs_donefirst;
121da14cebeSEric Cheng 	boolean_t	vs_stats;
122da14cebeSEric Cheng 	boolean_t	vs_printstats;
123da14cebeSEric Cheng 	pktsum_t	vs_totalstats;
124da14cebeSEric Cheng 	pktsum_t	vs_prevstats[MAXVNIC];
125da14cebeSEric Cheng 	boolean_t	vs_etherstub;
126da14cebeSEric Cheng 	dladm_status_t	vs_status;
127da14cebeSEric Cheng 	uint32_t	vs_flags;
1288002d411SSowmini Varadhan 	ofmt_handle_t	vs_ofmt;
129da14cebeSEric Cheng } show_vnic_state_t;
130da14cebeSEric Cheng 
131da14cebeSEric Cheng typedef struct show_usage_state_s {
132da14cebeSEric Cheng 	boolean_t	us_plot;
1338002d411SSowmini Varadhan 	boolean_t	us_parsable;
134da14cebeSEric Cheng 	boolean_t	us_printheader;
135da14cebeSEric Cheng 	boolean_t	us_first;
136ae6aa22aSVenugopal Iyer 	boolean_t	us_showall;
1378002d411SSowmini Varadhan 	ofmt_handle_t	us_ofmt;
138da14cebeSEric Cheng } show_usage_state_t;
139da14cebeSEric Cheng 
1408002d411SSowmini Varadhan /*
1418002d411SSowmini Varadhan  * callback functions for printing output and error diagnostics.
1428002d411SSowmini Varadhan  */
1438002d411SSowmini Varadhan static ofmt_cb_t print_default_cb, print_link_stats_cb, print_linkprop_cb;
1448002d411SSowmini Varadhan static ofmt_cb_t print_lacp_cb, print_phys_one_mac_cb;
1458002d411SSowmini Varadhan static ofmt_cb_t print_xaggr_cb, print_aggr_stats_cb;
1468002d411SSowmini Varadhan static ofmt_cb_t print_phys_one_hwgrp_cb, print_wlan_attr_cb;
1478002d411SSowmini Varadhan static ofmt_cb_t print_wifi_status_cb, print_link_attr_cb;
1488002d411SSowmini Varadhan static void dladm_ofmt_check(ofmt_status_t, boolean_t, ofmt_handle_t);
1498002d411SSowmini Varadhan 
1508d5c46e6Sam223141 typedef void cmdfunc_t(int, char **, const char *);
1510ba2cbe9Sxc151355 
152da14cebeSEric Cheng static cmdfunc_t do_show_link, do_show_wifi, do_show_phys;
1530ba2cbe9Sxc151355 static cmdfunc_t do_create_aggr, do_delete_aggr, do_add_aggr, do_remove_aggr;
154d62bc4baSyz147064 static cmdfunc_t do_modify_aggr, do_show_aggr, do_up_aggr;
1550ba2cbe9Sxc151355 static cmdfunc_t do_scan_wifi, do_connect_wifi, do_disconnect_wifi;
1560ba2cbe9Sxc151355 static cmdfunc_t do_show_linkprop, do_set_linkprop, do_reset_linkprop;
1570ba2cbe9Sxc151355 static cmdfunc_t do_create_secobj, do_delete_secobj, do_show_secobj;
1580ba2cbe9Sxc151355 static cmdfunc_t do_init_linkprop, do_init_secobj;
159d62bc4baSyz147064 static cmdfunc_t do_create_vlan, do_delete_vlan, do_up_vlan, do_show_vlan;
160d62bc4baSyz147064 static cmdfunc_t do_rename_link, do_delete_phys, do_init_phys;
161d62bc4baSyz147064 static cmdfunc_t do_show_linkmap;
162e7801d59Ssowmini static cmdfunc_t do_show_ether;
163da14cebeSEric Cheng static cmdfunc_t do_create_vnic, do_delete_vnic, do_show_vnic;
164da14cebeSEric Cheng static cmdfunc_t do_up_vnic;
165da14cebeSEric Cheng static cmdfunc_t do_create_etherstub, do_delete_etherstub, do_show_etherstub;
166b509e89bSRishi Srivatsavai static cmdfunc_t do_create_simnet, do_modify_simnet;
167b509e89bSRishi Srivatsavai static cmdfunc_t do_delete_simnet, do_show_simnet, do_up_simnet;
168da14cebeSEric Cheng static cmdfunc_t do_show_usage;
169da14cebeSEric Cheng 
170da14cebeSEric Cheng static void 	do_up_vnic_common(int, char **, const char *, boolean_t);
1717c478bd9Sstevel@tonic-gate 
172d62bc4baSyz147064 static void	altroot_cmd(char *, int, char **);
1734ac67f02SAnurag S. Maskey static int	show_linkprop_onelink(dladm_handle_t, datalink_id_t, void *);
174f4b3ec61Sdh155122 
1756be03d0bSVasumathi Sundaram - Sun Microsystems static void	link_stats(datalink_id_t, uint_t, char *, show_state_t *);
176d62bc4baSyz147064 static void	aggr_stats(datalink_id_t, show_grp_state_t *, uint_t);
177da14cebeSEric Cheng static void	vnic_stats(show_vnic_state_t *, uint32_t);
1787c478bd9Sstevel@tonic-gate 
179d62bc4baSyz147064 static int	get_one_kstat(const char *, const char *, uint8_t,
180d62bc4baSyz147064 		    void *, boolean_t);
181ba2e4443Sseb static void	get_mac_stats(const char *, pktsum_t *);
1827c478bd9Sstevel@tonic-gate static void	get_link_stats(const char *, pktsum_t *);
183d62bc4baSyz147064 static uint64_t	get_ifspeed(const char *, boolean_t);
184d62bc4baSyz147064 static const char	*get_linkstate(const char *, boolean_t, char *);
185d62bc4baSyz147064 static const char	*get_linkduplex(const char *, boolean_t, char *);
1867c478bd9Sstevel@tonic-gate 
1874ac67f02SAnurag S. Maskey static int	show_etherprop(dladm_handle_t, datalink_id_t, void *);
1884784fcbdSSowmini Varadhan static void	show_ether_xprop(void *, dladm_ether_info_t *);
189e7801d59Ssowmini static boolean_t	link_is_ether(const char *, datalink_id_t *);
190e7801d59Ssowmini 
19133343a97Smeem static boolean_t str2int(const char *, int *);
19233343a97Smeem static void	die(const char *, ...);
19333343a97Smeem static void	die_optdup(int);
1948d5c46e6Sam223141 static void	die_opterr(int, int, const char *);
19533343a97Smeem static void	die_dlerr(dladm_status_t, const char *, ...);
19633343a97Smeem static void	warn(const char *, ...);
19733343a97Smeem static void	warn_dlerr(dladm_status_t, const char *, ...);
19833343a97Smeem 
1997c478bd9Sstevel@tonic-gate typedef struct	cmd {
2007c478bd9Sstevel@tonic-gate 	char		*c_name;
2010ba2cbe9Sxc151355 	cmdfunc_t	*c_fn;
2028d5c46e6Sam223141 	const char	*c_usage;
2037c478bd9Sstevel@tonic-gate } cmd_t;
2047c478bd9Sstevel@tonic-gate 
2057c478bd9Sstevel@tonic-gate static cmd_t	cmds[] = {
2068d5c46e6Sam223141 	{ "rename-link",	do_rename_link,
2070790b6dcSAnurag S. Maskey 	    "    rename-link      <oldlink> <newlink>"			},
2080790b6dcSAnurag S. Maskey 	{ "show-link",		do_show_link,
2090790b6dcSAnurag S. Maskey 	    "    show-link        [-pP] [-o <field>,..] [-s [-i <interval>]] "
2100790b6dcSAnurag S. Maskey 	    "[<link>]\n"						},
2118d5c46e6Sam223141 	{ "create-aggr",	do_create_aggr,
2120790b6dcSAnurag S. Maskey 	    "    create-aggr      [-t] [-P <policy>] [-L <mode>] [-T <time>] "
2130790b6dcSAnurag S. Maskey 	    "[-u <address>]\n"
2140790b6dcSAnurag S. Maskey 	    "\t\t     -l <link> [-l <link>...] <link>"			},
2158d5c46e6Sam223141 	{ "delete-aggr",	do_delete_aggr,
2160790b6dcSAnurag S. Maskey 	    "    delete-aggr      [-t] <link>"				},
2178d5c46e6Sam223141 	{ "add-aggr",		do_add_aggr,
2180790b6dcSAnurag S. Maskey 	    "    add-aggr         [-t] -l <link> [-l <link>...] <link>" },
2198d5c46e6Sam223141 	{ "remove-aggr",	do_remove_aggr,
2200790b6dcSAnurag S. Maskey 	    "    remove-aggr      [-t] -l <link> [-l <link>...] <link>" },
2218d5c46e6Sam223141 	{ "modify-aggr",	do_modify_aggr,
2220790b6dcSAnurag S. Maskey 	    "    modify-aggr      [-t] [-P <policy>] [-L <mode>] [-T <time>] "
2230790b6dcSAnurag S. Maskey 	    "[-u <address>]\n"
2240790b6dcSAnurag S. Maskey 	    "\t\t     <link>"						},
2258d5c46e6Sam223141 	{ "show-aggr",		do_show_aggr,
2260790b6dcSAnurag S. Maskey 	    "    show-aggr        [-pPLx] [-o <field>,..] [-s [-i <interval>]] "
2278d5c46e6Sam223141 	    "[<link>]\n"						},
2288d5c46e6Sam223141 	{ "up-aggr",		do_up_aggr,	NULL			},
2298d5c46e6Sam223141 	{ "scan-wifi",		do_scan_wifi,
2300790b6dcSAnurag S. Maskey 	    "    scan-wifi        [-p] [-o <field>,...] [<link>]"	},
2318d5c46e6Sam223141 	{ "connect-wifi",	do_connect_wifi,
2320790b6dcSAnurag S. Maskey 	    "    connect-wifi     [-e <essid>] [-i <bssid>] [-k <key>,...] "
2338d5c46e6Sam223141 	    "[-s wep|wpa]\n"
2340790b6dcSAnurag S. Maskey 	    "\t\t     [-a open|shared] [-b bss|ibss] [-c] [-m a|b|g] "
2350790b6dcSAnurag S. Maskey 	    "[-T <time>]\n"
2360790b6dcSAnurag S. Maskey 	    "\t\t     [<link>]"						},
2378d5c46e6Sam223141 	{ "disconnect-wifi",	do_disconnect_wifi,
2380790b6dcSAnurag S. Maskey 	    "    disconnect-wifi  [-a] [<link>]"			},
2398d5c46e6Sam223141 	{ "show-wifi",		do_show_wifi,
2400790b6dcSAnurag S. Maskey 	    "    show-wifi        [-p] [-o <field>,...] [<link>]\n"	},
2418d5c46e6Sam223141 	{ "set-linkprop",	do_set_linkprop,
2420790b6dcSAnurag S. Maskey 	    "    set-linkprop     [-t] -p <prop>=<value>[,...] <name>"	},
2438d5c46e6Sam223141 	{ "reset-linkprop",	do_reset_linkprop,
2440790b6dcSAnurag S. Maskey 	    "    reset-linkprop   [-t] [-p <prop>,...] <name>"		},
2450790b6dcSAnurag S. Maskey 	{ "show-linkprop",	do_show_linkprop,
2460790b6dcSAnurag S. Maskey 	    "    show-linkprop    [-cP] [-o <field>,...] [-p <prop>,...] "
2470790b6dcSAnurag S. Maskey 	    "<name>\n"							},
2488d5c46e6Sam223141 	{ "show-ether",		do_show_ether,
2490790b6dcSAnurag S. Maskey 	    "    show-ether       [-px][-o <field>,...] <link>\n"	},
2508d5c46e6Sam223141 	{ "create-secobj",	do_create_secobj,
2510790b6dcSAnurag S. Maskey 	    "    create-secobj    [-t] [-f <file>] -c <class> <secobj>"	},
2528d5c46e6Sam223141 	{ "delete-secobj",	do_delete_secobj,
2530790b6dcSAnurag S. Maskey 	    "    delete-secobj    [-t] <secobj>[,...]"			},
2548d5c46e6Sam223141 	{ "show-secobj",	do_show_secobj,
2550790b6dcSAnurag S. Maskey 	    "    show-secobj      [-pP] [-o <field>,...] [<secobj>,...]\n" },
2568d5c46e6Sam223141 	{ "init-linkprop",	do_init_linkprop,	NULL		},
2578d5c46e6Sam223141 	{ "init-secobj",	do_init_secobj,		NULL		},
2588d5c46e6Sam223141 	{ "create-vlan", 	do_create_vlan,
2590790b6dcSAnurag S. Maskey 	    "    create-vlan      [-ft] -l <link> -v <vid> [link]"	},
2608d5c46e6Sam223141 	{ "delete-vlan", 	do_delete_vlan,
2610790b6dcSAnurag S. Maskey 	    "    delete-vlan      [-t] <link>"				},
2628d5c46e6Sam223141 	{ "show-vlan",		do_show_vlan,
2630790b6dcSAnurag S. Maskey 	    "    show-vlan        [-pP] [-o <field>,..] [<link>]\n"	},
2648d5c46e6Sam223141 	{ "up-vlan",		do_up_vlan,		NULL		},
2658d5c46e6Sam223141 	{ "delete-phys",	do_delete_phys,
2660790b6dcSAnurag S. Maskey 	    "    delete-phys      <link>"				},
2678d5c46e6Sam223141 	{ "show-phys",		do_show_phys,
2680790b6dcSAnurag S. Maskey 	    "    show-phys        [-pP] [-o <field>,..] [-H] [<link>]\n"},
2698d5c46e6Sam223141 	{ "init-phys",		do_init_phys,		NULL		},
270da14cebeSEric Cheng 	{ "show-linkmap",	do_show_linkmap,	NULL		},
271da14cebeSEric Cheng 	{ "create-vnic",	do_create_vnic,
2720790b6dcSAnurag S. Maskey 	    "    create-vnic      [-t] -l <link> [-m <value> | auto |\n"
2730790b6dcSAnurag S. Maskey 	    "\t\t     {factory [-n <slot-id>]} | {random [-r <prefix>]}]\n"
2740790b6dcSAnurag S. Maskey 	    "\t\t     [-v <vid> [-f]] [-p <prop>=<value>[,...]] [-H] "
2750790b6dcSAnurag S. Maskey 	    "<vnic-link>"						},
276da14cebeSEric Cheng 	{ "delete-vnic",	do_delete_vnic,
2770790b6dcSAnurag S. Maskey 	    "    delete-vnic      [-t] <vnic-link>"			},
278da14cebeSEric Cheng 	{ "show-vnic",		do_show_vnic,
2790790b6dcSAnurag S. Maskey 	    "    show-vnic        [-pP] [-l <link>] [-s [-i <interval>]] "
2800790b6dcSAnurag S. Maskey 	    "[<link>]\n"						},
281da14cebeSEric Cheng 	{ "up-vnic",		do_up_vnic,		NULL		},
282da14cebeSEric Cheng 	{ "create-etherstub",	do_create_etherstub,
2830790b6dcSAnurag S. Maskey 	    "    create-etherstub [-t] <link>"				},
284da14cebeSEric Cheng 	{ "delete-etherstub",	do_delete_etherstub,
2850790b6dcSAnurag S. Maskey 	    "    delete-etherstub [-t] <link>"				},
286da14cebeSEric Cheng 	{ "show-etherstub",	do_show_etherstub,
2870790b6dcSAnurag S. Maskey 	    "    show-etherstub   [-t] [<link>]\n"			},
288b509e89bSRishi Srivatsavai 	{ "create-simnet",	do_create_simnet,
289b509e89bSRishi Srivatsavai 	    "    create-simnet [-t] [-m <media>] <link>"		},
290b509e89bSRishi Srivatsavai 	{ "modify-simnet",	do_modify_simnet,
291b509e89bSRishi Srivatsavai 	    "    modify-simnet [-t] [-p <peer>] <link>"			},
292b509e89bSRishi Srivatsavai 	{ "delete-simnet",	do_delete_simnet,
293b509e89bSRishi Srivatsavai 	    "    delete-simnet [-t] <link>"				},
294b509e89bSRishi Srivatsavai 	{ "show-simnet",	do_show_simnet,
295b509e89bSRishi Srivatsavai 	    "    show-simnet   [-pP] [-o <field>,...] [<link>]\n"	},
296b509e89bSRishi Srivatsavai 	{ "up-simnet",		do_up_simnet,		NULL		},
297da14cebeSEric Cheng 	{ "show-usage",		do_show_usage,
298ae6aa22aSVenugopal Iyer 	    "    show-usage       [-a] [-d | -F <format>] "
2990790b6dcSAnurag S. Maskey 	    "[-s <DD/MM/YYYY,HH:MM:SS>]\n"
3000790b6dcSAnurag S. Maskey 	    "\t\t     [-e <DD/MM/YYYY,HH:MM:SS>] -f <logfile> [<link>]"	}
3017c478bd9Sstevel@tonic-gate };
3027c478bd9Sstevel@tonic-gate 
303d62bc4baSyz147064 static const struct option lopts[] = {
3047c478bd9Sstevel@tonic-gate 	{"vlan-id",	required_argument,	0, 'v'},
305e7801d59Ssowmini 	{"output",	required_argument,	0, 'o'},
3067c478bd9Sstevel@tonic-gate 	{"dev",		required_argument,	0, 'd'},
3077c478bd9Sstevel@tonic-gate 	{"policy",	required_argument,	0, 'P'},
308d62bc4baSyz147064 	{"lacp-mode",	required_argument,	0, 'L'},
3097c478bd9Sstevel@tonic-gate 	{"lacp-timer",	required_argument,	0, 'T'},
3107c478bd9Sstevel@tonic-gate 	{"unicast",	required_argument,	0, 'u'},
311d62bc4baSyz147064 	{"temporary",	no_argument,		0, 't'},
312d62bc4baSyz147064 	{"root-dir",	required_argument,	0, 'R'},
313d62bc4baSyz147064 	{"link",	required_argument,	0, 'l'},
314d62bc4baSyz147064 	{"forcible",	no_argument,		0, 'f'},
315da14cebeSEric Cheng 	{"bw-limit",	required_argument,	0, 'b'},
316da14cebeSEric Cheng 	{"mac-address",	required_argument,	0, 'm'},
317da14cebeSEric Cheng 	{"slot",	required_argument,	0, 'n'},
318d62bc4baSyz147064 	{ 0, 0, 0, 0 }
319d62bc4baSyz147064 };
320d62bc4baSyz147064 
321d62bc4baSyz147064 static const struct option show_lopts[] = {
3227c478bd9Sstevel@tonic-gate 	{"statistics",	no_argument,		0, 's'},
323da14cebeSEric Cheng 	{"continuous",	no_argument,		0, 'S'},
3247c478bd9Sstevel@tonic-gate 	{"interval",	required_argument,	0, 'i'},
3258002d411SSowmini Varadhan 	{"parsable",	no_argument,		0, 'p'},
3267c478bd9Sstevel@tonic-gate 	{"parseable",	no_argument,		0, 'p'},
327d62bc4baSyz147064 	{"extended",	no_argument,		0, 'x'},
328e7801d59Ssowmini 	{"output",	required_argument,	0, 'o'},
329d62bc4baSyz147064 	{"persistent",	no_argument,		0, 'P'},
330d62bc4baSyz147064 	{"lacp",	no_argument,		0, 'L'},
3317c478bd9Sstevel@tonic-gate 	{ 0, 0, 0, 0 }
3327c478bd9Sstevel@tonic-gate };
3337c478bd9Sstevel@tonic-gate 
3340ba2cbe9Sxc151355 static const struct option prop_longopts[] = {
3350ba2cbe9Sxc151355 	{"temporary",	no_argument,		0, 't'  },
336e7801d59Ssowmini 	{"output",	required_argument,	0, 'o'  },
3370ba2cbe9Sxc151355 	{"root-dir",	required_argument,	0, 'R'  },
3380ba2cbe9Sxc151355 	{"prop",	required_argument,	0, 'p'  },
3398002d411SSowmini Varadhan 	{"parsable",	no_argument,		0, 'c'  },
3400ba2cbe9Sxc151355 	{"parseable",	no_argument,		0, 'c'  },
3410ba2cbe9Sxc151355 	{"persistent",	no_argument,		0, 'P'  },
3420ba2cbe9Sxc151355 	{ 0, 0, 0, 0 }
3430ba2cbe9Sxc151355 };
3440ba2cbe9Sxc151355 
3450ba2cbe9Sxc151355 static const struct option wifi_longopts[] = {
3468002d411SSowmini Varadhan 	{"parsable",	no_argument,		0, 'p'  },
3470ba2cbe9Sxc151355 	{"parseable",	no_argument,		0, 'p'  },
3480ba2cbe9Sxc151355 	{"output",	required_argument,	0, 'o'  },
3490ba2cbe9Sxc151355 	{"essid",	required_argument,	0, 'e'  },
3500ba2cbe9Sxc151355 	{"bsstype",	required_argument,	0, 'b'  },
3510ba2cbe9Sxc151355 	{"mode",	required_argument,	0, 'm'  },
3520ba2cbe9Sxc151355 	{"key",		required_argument,	0, 'k'  },
3530ba2cbe9Sxc151355 	{"sec",		required_argument,	0, 's'  },
3540ba2cbe9Sxc151355 	{"auth",	required_argument,	0, 'a'  },
3550ba2cbe9Sxc151355 	{"create-ibss",	required_argument,	0, 'c'  },
3560ba2cbe9Sxc151355 	{"timeout",	required_argument,	0, 'T'  },
3570ba2cbe9Sxc151355 	{"all-links",	no_argument,		0, 'a'  },
3580ba2cbe9Sxc151355 	{"temporary",	no_argument,		0, 't'  },
3590ba2cbe9Sxc151355 	{"root-dir",	required_argument,	0, 'R'  },
3600ba2cbe9Sxc151355 	{"persistent",	no_argument,		0, 'P'  },
3610ba2cbe9Sxc151355 	{"file",	required_argument,	0, 'f'  },
3620ba2cbe9Sxc151355 	{ 0, 0, 0, 0 }
3630ba2cbe9Sxc151355 };
364e7801d59Ssowmini static const struct option showeth_lopts[] = {
3658002d411SSowmini Varadhan 	{"parsable",	no_argument,		0, 'p'	},
366e7801d59Ssowmini 	{"parseable",	no_argument,		0, 'p'	},
367e7801d59Ssowmini 	{"extended",	no_argument,		0, 'x'	},
368e7801d59Ssowmini 	{"output",	required_argument,	0, 'o'	},
369e7801d59Ssowmini 	{ 0, 0, 0, 0 }
370e7801d59Ssowmini };
371e7801d59Ssowmini 
372da14cebeSEric Cheng static const struct option vnic_lopts[] = {
373da14cebeSEric Cheng 	{"temporary",	no_argument,		0, 't'	},
374da14cebeSEric Cheng 	{"root-dir",	required_argument,	0, 'R'	},
375da14cebeSEric Cheng 	{"dev",		required_argument,	0, 'd'	},
376da14cebeSEric Cheng 	{"mac-address",	required_argument,	0, 'm'	},
377da14cebeSEric Cheng 	{"cpus",	required_argument,	0, 'c'	},
378da14cebeSEric Cheng 	{"bw-limit",	required_argument,	0, 'b'	},
379da14cebeSEric Cheng 	{"slot",	required_argument,	0, 'n'	},
380da14cebeSEric Cheng 	{"mac-prefix",	required_argument,	0, 'r'	},
381da14cebeSEric Cheng 	{ 0, 0, 0, 0 }
382da14cebeSEric Cheng };
383da14cebeSEric Cheng 
384da14cebeSEric Cheng static const struct option etherstub_lopts[] = {
385da14cebeSEric Cheng 	{"temporary",	no_argument,		0, 't'	},
386da14cebeSEric Cheng 	{"root-dir",	required_argument,	0, 'R'	},
387da14cebeSEric Cheng 	{ 0, 0, 0, 0 }
388da14cebeSEric Cheng };
389da14cebeSEric Cheng 
390ae6aa22aSVenugopal Iyer static const struct option usage_opts[] = {
391ae6aa22aSVenugopal Iyer 	{"file",	required_argument,	0, 'f'	},
392ae6aa22aSVenugopal Iyer 	{"format",	required_argument,	0, 'F'	},
393ae6aa22aSVenugopal Iyer 	{"start",	required_argument,	0, 's'	},
394ae6aa22aSVenugopal Iyer 	{"stop",	required_argument,	0, 'e'	},
395ae6aa22aSVenugopal Iyer 	{ 0, 0, 0, 0 }
396ae6aa22aSVenugopal Iyer };
397ae6aa22aSVenugopal Iyer 
398b509e89bSRishi Srivatsavai static const struct option simnet_lopts[] = {
399b509e89bSRishi Srivatsavai 	{"temporary",	no_argument,		0, 't'	},
400b509e89bSRishi Srivatsavai 	{"root-dir",	required_argument,	0, 'R'	},
401b509e89bSRishi Srivatsavai 	{"media",	required_argument,	0, 'm'	},
402b509e89bSRishi Srivatsavai 	{"peer",	required_argument,	0, 'p'	},
403b509e89bSRishi Srivatsavai 	{ 0, 0, 0, 0 }
404b509e89bSRishi Srivatsavai };
405b509e89bSRishi Srivatsavai 
406e7801d59Ssowmini /*
407e7801d59Ssowmini  * structures for 'dladm show-ether'
408e7801d59Ssowmini  */
4094784fcbdSSowmini Varadhan static const char *ptype[] = {LEI_ATTR_NAMES};
4104784fcbdSSowmini Varadhan 
411e7801d59Ssowmini typedef struct ether_fields_buf_s
412e7801d59Ssowmini {
413e7801d59Ssowmini 	char	eth_link[15];
414e7801d59Ssowmini 	char	eth_ptype[8];
415e7801d59Ssowmini 	char	eth_state[8];
416e7801d59Ssowmini 	char	eth_autoneg[5];
417e7801d59Ssowmini 	char	eth_spdx[31];
418e7801d59Ssowmini 	char	eth_pause[6];
419e7801d59Ssowmini 	char	eth_rem_fault[16];
420e7801d59Ssowmini } ether_fields_buf_t;
421e7801d59Ssowmini 
4228002d411SSowmini Varadhan static ofmt_field_t ether_fields[] = {
4238002d411SSowmini Varadhan /* name,	field width,	offset	    callback */
4248002d411SSowmini Varadhan { "LINK",	16,
4258002d411SSowmini Varadhan 	offsetof(ether_fields_buf_t, eth_link), print_default_cb},
4268002d411SSowmini Varadhan { "PTYPE",	9,
4278002d411SSowmini Varadhan 	offsetof(ether_fields_buf_t, eth_ptype), print_default_cb},
4288002d411SSowmini Varadhan { "STATE",	9,
4298002d411SSowmini Varadhan 	offsetof(ether_fields_buf_t, eth_state),
4308002d411SSowmini Varadhan 	print_default_cb},
4318002d411SSowmini Varadhan { "AUTO",	6,
4328002d411SSowmini Varadhan 	offsetof(ether_fields_buf_t, eth_autoneg), print_default_cb},
4338002d411SSowmini Varadhan { "SPEED-DUPLEX", 32,
4348002d411SSowmini Varadhan 	offsetof(ether_fields_buf_t, eth_spdx), print_default_cb},
4358002d411SSowmini Varadhan { "PAUSE",	7,
4368002d411SSowmini Varadhan 	offsetof(ether_fields_buf_t, eth_pause), print_default_cb},
4378002d411SSowmini Varadhan { "REM_FAULT",	17,
4388002d411SSowmini Varadhan 	offsetof(ether_fields_buf_t, eth_rem_fault), print_default_cb},
4398002d411SSowmini Varadhan {NULL,		0,
4408002d411SSowmini Varadhan 	0, 	NULL}}
441e7801d59Ssowmini ;
442e7801d59Ssowmini 
443e7801d59Ssowmini typedef struct print_ether_state {
444e7801d59Ssowmini 	const char	*es_link;
4458002d411SSowmini Varadhan 	boolean_t	es_parsable;
446e7801d59Ssowmini 	boolean_t	es_header;
447e7801d59Ssowmini 	boolean_t	es_extended;
4488002d411SSowmini Varadhan 	ofmt_handle_t	es_ofmt;
449e7801d59Ssowmini } print_ether_state_t;
450e7801d59Ssowmini 
451e7801d59Ssowmini /*
452da14cebeSEric Cheng  * structures for 'dladm show-link -s' (print statistics)
453e7801d59Ssowmini  */
454e7801d59Ssowmini typedef enum {
455ae6aa22aSVenugopal Iyer 	LINK_S_LINK,
456ae6aa22aSVenugopal Iyer 	LINK_S_IPKTS,
457ae6aa22aSVenugopal Iyer 	LINK_S_RBYTES,
458ae6aa22aSVenugopal Iyer 	LINK_S_IERRORS,
459ae6aa22aSVenugopal Iyer 	LINK_S_OPKTS,
460ae6aa22aSVenugopal Iyer 	LINK_S_OBYTES,
461ae6aa22aSVenugopal Iyer 	LINK_S_OERRORS
462ae6aa22aSVenugopal Iyer } link_s_field_index_t;
463e7801d59Ssowmini 
4648002d411SSowmini Varadhan static ofmt_field_t link_s_fields[] = {
4658002d411SSowmini Varadhan /* name,	field width,	index,		callback	*/
4668002d411SSowmini Varadhan { "LINK",	15,		LINK_S_LINK,	print_link_stats_cb},
4678002d411SSowmini Varadhan { "IPACKETS",	10,		LINK_S_IPKTS,	print_link_stats_cb},
4688002d411SSowmini Varadhan { "RBYTES",	8,		LINK_S_RBYTES,	print_link_stats_cb},
4698002d411SSowmini Varadhan { "IERRORS",	10,		LINK_S_IERRORS,	print_link_stats_cb},
4708002d411SSowmini Varadhan { "OPACKETS",	12,		LINK_S_OPKTS,	print_link_stats_cb},
4718002d411SSowmini Varadhan { "OBYTES",	12,		LINK_S_OBYTES,	print_link_stats_cb},
4728002d411SSowmini Varadhan { "OERRORS",	8,		LINK_S_OERRORS,	print_link_stats_cb}}
473e7801d59Ssowmini ;
474ae6aa22aSVenugopal Iyer 
475ae6aa22aSVenugopal Iyer typedef struct link_args_s {
476ae6aa22aSVenugopal Iyer 	char		*link_s_link;
477ae6aa22aSVenugopal Iyer 	pktsum_t	*link_s_psum;
478ae6aa22aSVenugopal Iyer } link_args_t;
479e7801d59Ssowmini 
480e7801d59Ssowmini /*
481e7801d59Ssowmini  * buffer used by print functions for show-{link,phys,vlan} commands.
482e7801d59Ssowmini  */
483e7801d59Ssowmini typedef struct link_fields_buf_s {
484e7801d59Ssowmini 	char link_name[MAXLINKNAMELEN];
485e7801d59Ssowmini 	char link_class[DLADM_STRSIZE];
486c08e5e1aSdr146992 	char link_mtu[11];
487e7801d59Ssowmini 	char link_state[DLADM_STRSIZE];
488e7801d59Ssowmini 	char link_over[MAXLINKNAMELEN];
4894045d941Ssowmini 	char link_phys_state[DLADM_STRSIZE];
490e7801d59Ssowmini 	char link_phys_media[DLADM_STRSIZE];
491e7801d59Ssowmini 	char link_phys_speed[DLADM_STRSIZE];
492e7801d59Ssowmini 	char link_phys_duplex[DLPI_LINKNAME_MAX];
493e7801d59Ssowmini 	char link_phys_device[DLPI_LINKNAME_MAX];
494e7801d59Ssowmini 	char link_flags[6];
495e7801d59Ssowmini 	char link_vlan_vid[6];
496e7801d59Ssowmini } link_fields_buf_t;
497e7801d59Ssowmini 
498e7801d59Ssowmini /*
499e7801d59Ssowmini  * structures for 'dladm show-link'
500e7801d59Ssowmini  */
5018002d411SSowmini Varadhan static ofmt_field_t link_fields[] = {
5028002d411SSowmini Varadhan /* name,	field width,	index,	callback */
5038002d411SSowmini Varadhan { "LINK",	12,
5048002d411SSowmini Varadhan 	offsetof(link_fields_buf_t, link_name), print_default_cb},
5058002d411SSowmini Varadhan { "CLASS",	9,
5068002d411SSowmini Varadhan 	offsetof(link_fields_buf_t, link_class), print_default_cb},
5078002d411SSowmini Varadhan { "MTU",	7,
5088002d411SSowmini Varadhan 	offsetof(link_fields_buf_t, link_mtu), print_default_cb},
5098002d411SSowmini Varadhan { "STATE",	9,
5108002d411SSowmini Varadhan 	offsetof(link_fields_buf_t, link_state), print_default_cb},
5118002d411SSowmini Varadhan { "OVER",	DLPI_LINKNAME_MAX,
5128002d411SSowmini Varadhan 	offsetof(link_fields_buf_t, link_over), print_default_cb},
5138002d411SSowmini Varadhan { NULL,		0, 0, NULL}}
514e7801d59Ssowmini ;
515e7801d59Ssowmini 
516e7801d59Ssowmini /*
517e7801d59Ssowmini  * structures for 'dladm show-aggr'
518e7801d59Ssowmini  */
519e7801d59Ssowmini typedef struct laggr_fields_buf_s {
520e7801d59Ssowmini 	char laggr_name[DLPI_LINKNAME_MAX];
521e7801d59Ssowmini 	char laggr_policy[9];
522e7801d59Ssowmini 	char laggr_addrpolicy[ETHERADDRL * 3 + 3];
523e7801d59Ssowmini 	char laggr_lacpactivity[14];
524e7801d59Ssowmini 	char laggr_lacptimer[DLADM_STRSIZE];
525e7801d59Ssowmini 	char laggr_flags[7];
526e7801d59Ssowmini } laggr_fields_buf_t;
527e7801d59Ssowmini 
528e7801d59Ssowmini typedef struct laggr_args_s {
529e7801d59Ssowmini 	int			laggr_lport; /* -1 indicates the aggr itself */
530e7801d59Ssowmini 	const char 		*laggr_link;
531e7801d59Ssowmini 	dladm_aggr_grp_attr_t	*laggr_ginfop;
532e7801d59Ssowmini 	dladm_status_t		*laggr_status;
533e7801d59Ssowmini 	pktsum_t		*laggr_pktsumtot; /* -s only */
5342d40c3b2SPrakash Jalan 	pktsum_t		*laggr_diffstats; /* -s only */
5358002d411SSowmini Varadhan 	boolean_t		laggr_parsable;
536e7801d59Ssowmini } laggr_args_t;
537e7801d59Ssowmini 
5388002d411SSowmini Varadhan static ofmt_field_t laggr_fields[] = {
5398002d411SSowmini Varadhan /* name,	field width,	offset,	callback */
5408002d411SSowmini Varadhan { "LINK",	16,
5418002d411SSowmini Varadhan 	offsetof(laggr_fields_buf_t, laggr_name), print_default_cb},
5428002d411SSowmini Varadhan { "POLICY",	9,
5438002d411SSowmini Varadhan 	offsetof(laggr_fields_buf_t, laggr_policy), print_default_cb},
5448002d411SSowmini Varadhan { "ADDRPOLICY",	ETHERADDRL * 3 + 3,
5458002d411SSowmini Varadhan 	offsetof(laggr_fields_buf_t, laggr_addrpolicy), print_default_cb},
5468002d411SSowmini Varadhan { "LACPACTIVITY", 14,
5478002d411SSowmini Varadhan 	offsetof(laggr_fields_buf_t, laggr_lacpactivity), print_default_cb},
5488002d411SSowmini Varadhan { "LACPTIMER",	12,
5498002d411SSowmini Varadhan 	offsetof(laggr_fields_buf_t, laggr_lacptimer), print_default_cb},
5508002d411SSowmini Varadhan { "FLAGS",	8,
5518002d411SSowmini Varadhan 	offsetof(laggr_fields_buf_t, laggr_flags), print_default_cb},
5528002d411SSowmini Varadhan { NULL,		0, 0, NULL}}
553e7801d59Ssowmini ;
554e7801d59Ssowmini 
555e7801d59Ssowmini /*
556e7801d59Ssowmini  * structures for 'dladm show-aggr -x'.
557e7801d59Ssowmini  */
558e7801d59Ssowmini typedef enum {
559e7801d59Ssowmini 	AGGR_X_LINK,
560e7801d59Ssowmini 	AGGR_X_PORT,
561e7801d59Ssowmini 	AGGR_X_SPEED,
562e7801d59Ssowmini 	AGGR_X_DUPLEX,
563e7801d59Ssowmini 	AGGR_X_STATE,
564e7801d59Ssowmini 	AGGR_X_ADDRESS,
565e7801d59Ssowmini 	AGGR_X_PORTSTATE
566e7801d59Ssowmini } aggr_x_field_index_t;
567e7801d59Ssowmini 
5688002d411SSowmini Varadhan static ofmt_field_t aggr_x_fields[] = {
5698002d411SSowmini Varadhan /* name,	field width,	index		callback */
5708002d411SSowmini Varadhan { "LINK",	12,	AGGR_X_LINK,		print_xaggr_cb},
5718002d411SSowmini Varadhan { "PORT",	15,	AGGR_X_PORT,		print_xaggr_cb},
5728002d411SSowmini Varadhan { "SPEED",	5,	AGGR_X_SPEED,		print_xaggr_cb},
5738002d411SSowmini Varadhan { "DUPLEX",	10,	AGGR_X_DUPLEX,		print_xaggr_cb},
5748002d411SSowmini Varadhan { "STATE",	10,	AGGR_X_STATE,		print_xaggr_cb},
5758002d411SSowmini Varadhan { "ADDRESS",	19,	AGGR_X_ADDRESS,		print_xaggr_cb},
5768002d411SSowmini Varadhan { "PORTSTATE",	16,	AGGR_X_PORTSTATE,	print_xaggr_cb},
5778002d411SSowmini Varadhan { NULL,		0,	0,			NULL}}
578e7801d59Ssowmini ;
579e7801d59Ssowmini 
580e7801d59Ssowmini /*
581e7801d59Ssowmini  * structures for 'dladm show-aggr -s'.
582e7801d59Ssowmini  */
583e7801d59Ssowmini typedef enum {
584e7801d59Ssowmini 	AGGR_S_LINK,
585e7801d59Ssowmini 	AGGR_S_PORT,
586e7801d59Ssowmini 	AGGR_S_IPKTS,
587e7801d59Ssowmini 	AGGR_S_RBYTES,
588e7801d59Ssowmini 	AGGR_S_OPKTS,
589e7801d59Ssowmini 	AGGR_S_OBYTES,
590e7801d59Ssowmini 	AGGR_S_IPKTDIST,
591e7801d59Ssowmini 	AGGR_S_OPKTDIST
592e7801d59Ssowmini } aggr_s_field_index_t;
593e7801d59Ssowmini 
5948002d411SSowmini Varadhan static ofmt_field_t aggr_s_fields[] = {
5958002d411SSowmini Varadhan { "LINK",		12,	AGGR_S_LINK, print_aggr_stats_cb},
5968002d411SSowmini Varadhan { "PORT",		10,	AGGR_S_PORT, print_aggr_stats_cb},
5978002d411SSowmini Varadhan { "IPACKETS",		8,	AGGR_S_IPKTS, print_aggr_stats_cb},
5988002d411SSowmini Varadhan { "RBYTES",		8,	AGGR_S_RBYTES, print_aggr_stats_cb},
5998002d411SSowmini Varadhan { "OPACKETS",		8,	AGGR_S_OPKTS, print_aggr_stats_cb},
6008002d411SSowmini Varadhan { "OBYTES",		8,	AGGR_S_OBYTES, print_aggr_stats_cb},
6018002d411SSowmini Varadhan { "IPKTDIST",		9,	AGGR_S_IPKTDIST, print_aggr_stats_cb},
6028002d411SSowmini Varadhan { "OPKTDIST",		15,	AGGR_S_OPKTDIST, print_aggr_stats_cb},
6038002d411SSowmini Varadhan { NULL,			0,	0,		NULL}}
604e7801d59Ssowmini ;
605e7801d59Ssowmini 
606e7801d59Ssowmini /*
607da14cebeSEric Cheng  * structures for 'dladm show-aggr -L'.
608e7801d59Ssowmini  */
609e7801d59Ssowmini typedef enum {
610e7801d59Ssowmini 	AGGR_L_LINK,
611e7801d59Ssowmini 	AGGR_L_PORT,
612e7801d59Ssowmini 	AGGR_L_AGGREGATABLE,
613e7801d59Ssowmini 	AGGR_L_SYNC,
614e7801d59Ssowmini 	AGGR_L_COLL,
615e7801d59Ssowmini 	AGGR_L_DIST,
616e7801d59Ssowmini 	AGGR_L_DEFAULTED,
617e7801d59Ssowmini 	AGGR_L_EXPIRED
618e7801d59Ssowmini } aggr_l_field_index_t;
619e7801d59Ssowmini 
6208002d411SSowmini Varadhan static ofmt_field_t aggr_l_fields[] = {
6218002d411SSowmini Varadhan /* name,		field width,	index */
6228002d411SSowmini Varadhan { "LINK",		12,	AGGR_L_LINK,		print_lacp_cb},
6238002d411SSowmini Varadhan { "PORT",		13,	AGGR_L_PORT,		print_lacp_cb},
6248002d411SSowmini Varadhan { "AGGREGATABLE",	13,	AGGR_L_AGGREGATABLE,	print_lacp_cb},
6258002d411SSowmini Varadhan { "SYNC",		5,	AGGR_L_SYNC,		print_lacp_cb},
6268002d411SSowmini Varadhan { "COLL",		5,	AGGR_L_COLL,		print_lacp_cb},
6278002d411SSowmini Varadhan { "DIST",		5,	AGGR_L_DIST,		print_lacp_cb},
6288002d411SSowmini Varadhan { "DEFAULTED",		10,	AGGR_L_DEFAULTED,	print_lacp_cb},
6298002d411SSowmini Varadhan { "EXPIRED",		15,	AGGR_L_EXPIRED,		print_lacp_cb},
6308002d411SSowmini Varadhan { NULL,			0,	0,			NULL}}
631e7801d59Ssowmini ;
632e7801d59Ssowmini 
633e7801d59Ssowmini /*
634e7801d59Ssowmini  * structures for 'dladm show-phys'
635e7801d59Ssowmini  */
636e7801d59Ssowmini 
6378002d411SSowmini Varadhan static ofmt_field_t phys_fields[] = {
6388002d411SSowmini Varadhan /* name,	field width,	offset */
6398002d411SSowmini Varadhan { "LINK",	13,
6408002d411SSowmini Varadhan 	offsetof(link_fields_buf_t, link_name), print_default_cb},
6418002d411SSowmini Varadhan { "MEDIA",	21,
6428002d411SSowmini Varadhan 	offsetof(link_fields_buf_t, link_phys_media), print_default_cb},
6438002d411SSowmini Varadhan { "STATE",	11,
6448002d411SSowmini Varadhan 	offsetof(link_fields_buf_t, link_phys_state), print_default_cb},
6458002d411SSowmini Varadhan { "SPEED",	7,
6468002d411SSowmini Varadhan 	offsetof(link_fields_buf_t, link_phys_speed), print_default_cb},
6478002d411SSowmini Varadhan { "DUPLEX",	10,
6488002d411SSowmini Varadhan 	offsetof(link_fields_buf_t, link_phys_duplex), print_default_cb},
6498002d411SSowmini Varadhan { "DEVICE",	13,
6508002d411SSowmini Varadhan 	offsetof(link_fields_buf_t, link_phys_device), print_default_cb},
6518002d411SSowmini Varadhan { "FLAGS",	7,
6528002d411SSowmini Varadhan 	offsetof(link_fields_buf_t, link_flags), print_default_cb},
6538002d411SSowmini Varadhan { NULL,		0, NULL, 0}}
654e7801d59Ssowmini ;
655e7801d59Ssowmini 
656e7801d59Ssowmini /*
657da14cebeSEric Cheng  * structures for 'dladm show-phys -m'
658da14cebeSEric Cheng  */
659da14cebeSEric Cheng 
660da14cebeSEric Cheng typedef enum {
661da14cebeSEric Cheng 	PHYS_M_LINK,
662da14cebeSEric Cheng 	PHYS_M_SLOT,
663da14cebeSEric Cheng 	PHYS_M_ADDRESS,
664da14cebeSEric Cheng 	PHYS_M_INUSE,
665da14cebeSEric Cheng 	PHYS_M_CLIENT
666da14cebeSEric Cheng } phys_m_field_index_t;
667da14cebeSEric Cheng 
6688002d411SSowmini Varadhan static ofmt_field_t phys_m_fields[] = {
6698002d411SSowmini Varadhan /* name,	field width,	offset */
6708002d411SSowmini Varadhan { "LINK",	13,	PHYS_M_LINK,	print_phys_one_mac_cb},
6718002d411SSowmini Varadhan { "SLOT",	9,	PHYS_M_SLOT,	print_phys_one_mac_cb},
6728002d411SSowmini Varadhan { "ADDRESS",	19,	PHYS_M_ADDRESS,	print_phys_one_mac_cb},
6738002d411SSowmini Varadhan { "INUSE",	5,	PHYS_M_INUSE,	print_phys_one_mac_cb},
6748002d411SSowmini Varadhan { "CLIENT",	13,	PHYS_M_CLIENT,	print_phys_one_mac_cb},
6758002d411SSowmini Varadhan { NULL,		0,	0,		NULL}}
676da14cebeSEric Cheng ;
677da14cebeSEric Cheng 
678da14cebeSEric Cheng /*
679da14cebeSEric Cheng  * structures for 'dladm show-phys -H'
680da14cebeSEric Cheng  */
681da14cebeSEric Cheng 
682da14cebeSEric Cheng typedef enum {
683da14cebeSEric Cheng 	PHYS_H_LINK,
684da14cebeSEric Cheng 	PHYS_H_GROUP,
685da14cebeSEric Cheng 	PHYS_H_GRPTYPE,
686da14cebeSEric Cheng 	PHYS_H_RINGS,
687da14cebeSEric Cheng 	PHYS_H_CLIENTS
688da14cebeSEric Cheng } phys_h_field_index_t;
689da14cebeSEric Cheng 
6908002d411SSowmini Varadhan static ofmt_field_t phys_h_fields[] = {
6918002d411SSowmini Varadhan { "LINK",	13,	PHYS_H_LINK,	print_phys_one_hwgrp_cb},
6928002d411SSowmini Varadhan { "GROUP",	9,	PHYS_H_GROUP,	print_phys_one_hwgrp_cb},
6938002d411SSowmini Varadhan { "GROUPTYPE",	7,	PHYS_H_GRPTYPE,	print_phys_one_hwgrp_cb},
6948002d411SSowmini Varadhan { "RINGS",	17,	PHYS_H_RINGS,	print_phys_one_hwgrp_cb},
6958002d411SSowmini Varadhan { "CLIENTS",	21,	PHYS_H_CLIENTS,	print_phys_one_hwgrp_cb},
6968002d411SSowmini Varadhan { NULL,		0,	0,		NULL}}
697da14cebeSEric Cheng ;
698da14cebeSEric Cheng 
699da14cebeSEric Cheng /*
700e7801d59Ssowmini  * structures for 'dladm show-vlan'
701e7801d59Ssowmini  */
7028002d411SSowmini Varadhan static ofmt_field_t vlan_fields[] = {
7038002d411SSowmini Varadhan { "LINK",	16,
7048002d411SSowmini Varadhan 	offsetof(link_fields_buf_t, link_name), print_default_cb},
7058002d411SSowmini Varadhan { "VID",	9,
7068002d411SSowmini Varadhan 	offsetof(link_fields_buf_t, link_vlan_vid), print_default_cb},
7078002d411SSowmini Varadhan { "OVER",	13,
7088002d411SSowmini Varadhan 	offsetof(link_fields_buf_t, link_over), print_default_cb},
7098002d411SSowmini Varadhan { "FLAGS",	7,
7108002d411SSowmini Varadhan 	offsetof(link_fields_buf_t, link_flags), print_default_cb},
7118002d411SSowmini Varadhan { NULL,		0, 0, NULL}}
712e7801d59Ssowmini ;
713da14cebeSEric Cheng 
714e7801d59Ssowmini /*
7158002d411SSowmini Varadhan  * structures common to 'dladm scan-wifi' and 'dladm show-wifi'
7168002d411SSowmini Varadhan  * callback will be determined in parse_wifi_fields.
717e7801d59Ssowmini  */
7188002d411SSowmini Varadhan static ofmt_field_t wifi_common_fields[] = {
7198002d411SSowmini Varadhan { "LINK",	11, 0,				NULL},
7208002d411SSowmini Varadhan { "ESSID",	20, DLADM_WLAN_ATTR_ESSID,	NULL},
7218002d411SSowmini Varadhan { "BSSID",	18, DLADM_WLAN_ATTR_BSSID,	NULL},
7228002d411SSowmini Varadhan { "IBSSID",	18, DLADM_WLAN_ATTR_BSSID,	NULL},
7238002d411SSowmini Varadhan { "MODE",	7,  DLADM_WLAN_ATTR_MODE,	NULL},
7248002d411SSowmini Varadhan { "SPEED",	7,  DLADM_WLAN_ATTR_SPEED,	NULL},
7258002d411SSowmini Varadhan { "BSSTYPE",	9,  DLADM_WLAN_ATTR_BSSTYPE,	NULL},
7268002d411SSowmini Varadhan { "SEC",	7,  DLADM_WLAN_ATTR_SECMODE,	NULL},
7278002d411SSowmini Varadhan { "STRENGTH",	11, DLADM_WLAN_ATTR_STRENGTH,	NULL},
7288002d411SSowmini Varadhan { NULL,		0,  0,				NULL}};
7298002d411SSowmini Varadhan 
7308002d411SSowmini Varadhan /*
7318002d411SSowmini Varadhan  * the 'show-wifi' command supports all the fields in wifi_common_fields
7328002d411SSowmini Varadhan  * plus the AUTH and STATUS fields.
7338002d411SSowmini Varadhan  */
7348002d411SSowmini Varadhan static ofmt_field_t wifi_show_fields[A_CNT(wifi_common_fields) + 2] = {
7358002d411SSowmini Varadhan { "AUTH",	9,  DLADM_WLAN_ATTR_AUTH,	NULL},
7368002d411SSowmini Varadhan { "STATUS",	18, DLADM_WLAN_LINKATTR_STATUS,	print_wifi_status_cb},
7378002d411SSowmini Varadhan /* copy wifi_common_fields here */
7388002d411SSowmini Varadhan };
739e7801d59Ssowmini 
740e7801d59Ssowmini static char *all_scan_wifi_fields =
741e7801d59Ssowmini 	"link,essid,bssid,sec,strength,mode,speed,bsstype";
742e7801d59Ssowmini static char *all_show_wifi_fields =
743e7801d59Ssowmini 	"link,status,essid,sec,strength,mode,speed,auth,bssid,bsstype";
744e7801d59Ssowmini static char *def_scan_wifi_fields =
745e7801d59Ssowmini 	"link,essid,bssid,sec,strength,mode,speed";
746e7801d59Ssowmini static char *def_show_wifi_fields =
747e7801d59Ssowmini 	"link,status,essid,sec,strength,mode,speed";
748e7801d59Ssowmini 
749e7801d59Ssowmini /*
750e7801d59Ssowmini  * structures for 'dladm show-linkprop'
751e7801d59Ssowmini  */
752e7801d59Ssowmini typedef enum {
753e7801d59Ssowmini 	LINKPROP_LINK,
754e7801d59Ssowmini 	LINKPROP_PROPERTY,
755afdda45fSVasumathi Sundaram - Sun Microsystems 	LINKPROP_PERM,
756e7801d59Ssowmini 	LINKPROP_VALUE,
757e7801d59Ssowmini 	LINKPROP_DEFAULT,
758e7801d59Ssowmini 	LINKPROP_POSSIBLE
759e7801d59Ssowmini } linkprop_field_index_t;
760e7801d59Ssowmini 
7618002d411SSowmini Varadhan static ofmt_field_t linkprop_fields[] = {
7628002d411SSowmini Varadhan /* name,	field width,  index */
7638002d411SSowmini Varadhan { "LINK",	13,	LINKPROP_LINK,		print_linkprop_cb},
7648002d411SSowmini Varadhan { "PROPERTY",	16,	LINKPROP_PROPERTY,	print_linkprop_cb},
7658002d411SSowmini Varadhan { "PERM",	5,	LINKPROP_PERM,		print_linkprop_cb},
7668002d411SSowmini Varadhan { "VALUE",	15,	LINKPROP_VALUE,		print_linkprop_cb},
7678002d411SSowmini Varadhan { "DEFAULT",	15,	LINKPROP_DEFAULT,	print_linkprop_cb},
7688002d411SSowmini Varadhan { "POSSIBLE",	21,	LINKPROP_POSSIBLE,	print_linkprop_cb},
7698002d411SSowmini Varadhan { NULL,		0,	0,			NULL}}
770e7801d59Ssowmini ;
771e7801d59Ssowmini 
772e7801d59Ssowmini #define	MAX_PROP_LINE		512
773e7801d59Ssowmini 
774e7801d59Ssowmini typedef struct show_linkprop_state {
775e7801d59Ssowmini 	char			ls_link[MAXLINKNAMELEN];
776e7801d59Ssowmini 	char			*ls_line;
777e7801d59Ssowmini 	char			**ls_propvals;
778da14cebeSEric Cheng 	dladm_arg_list_t	*ls_proplist;
7798002d411SSowmini Varadhan 	boolean_t		ls_parsable;
780e7801d59Ssowmini 	boolean_t		ls_persist;
781e7801d59Ssowmini 	boolean_t		ls_header;
782e7801d59Ssowmini 	dladm_status_t		ls_status;
783e7801d59Ssowmini 	dladm_status_t		ls_retstatus;
7848002d411SSowmini Varadhan 	ofmt_handle_t		ls_ofmt;
785e7801d59Ssowmini } show_linkprop_state_t;
786e7801d59Ssowmini 
787da14cebeSEric Cheng typedef struct set_linkprop_state {
788da14cebeSEric Cheng 	const char		*ls_name;
789da14cebeSEric Cheng 	boolean_t		ls_reset;
790da14cebeSEric Cheng 	boolean_t		ls_temp;
791da14cebeSEric Cheng 	dladm_status_t		ls_status;
792da14cebeSEric Cheng } set_linkprop_state_t;
793da14cebeSEric Cheng 
794e7801d59Ssowmini typedef struct linkprop_args_s {
795e7801d59Ssowmini 	show_linkprop_state_t	*ls_state;
796e7801d59Ssowmini 	char			*ls_propname;
797e7801d59Ssowmini 	datalink_id_t		ls_linkid;
798e7801d59Ssowmini } linkprop_args_t;
799e7801d59Ssowmini 
800e7801d59Ssowmini /*
801e7801d59Ssowmini  * structures for 'dladm show-secobj'
802e7801d59Ssowmini  */
803e7801d59Ssowmini typedef struct secobj_fields_buf_s {
804e7801d59Ssowmini 	char			ss_obj_name[DLADM_SECOBJ_VAL_MAX];
805e7801d59Ssowmini 	char			ss_class[20];
806e7801d59Ssowmini 	char			ss_val[30];
807e7801d59Ssowmini } secobj_fields_buf_t;
8088002d411SSowmini Varadhan 
8098002d411SSowmini Varadhan static ofmt_field_t secobj_fields[] = {
8108002d411SSowmini Varadhan { "OBJECT",	21,
8118002d411SSowmini Varadhan 	offsetof(secobj_fields_buf_t, ss_obj_name), print_default_cb},
8128002d411SSowmini Varadhan { "CLASS",	21,
8138002d411SSowmini Varadhan 	offsetof(secobj_fields_buf_t, ss_class), print_default_cb},
8148002d411SSowmini Varadhan { "VALUE",	31,
8158002d411SSowmini Varadhan 	offsetof(secobj_fields_buf_t, ss_val), print_default_cb},
8168002d411SSowmini Varadhan { NULL,		0, 0, NULL}}
817e7801d59Ssowmini ;
8180ba2cbe9Sxc151355 
819da14cebeSEric Cheng /*
820da14cebeSEric Cheng  * structures for 'dladm show-vnic'
821da14cebeSEric Cheng  */
822da14cebeSEric Cheng typedef struct vnic_fields_buf_s
823da14cebeSEric Cheng {
824da14cebeSEric Cheng 	char vnic_link[DLPI_LINKNAME_MAX];
825da14cebeSEric Cheng 	char vnic_over[DLPI_LINKNAME_MAX];
826da14cebeSEric Cheng 	char vnic_speed[6];
827b509e89bSRishi Srivatsavai 	char vnic_macaddr[18];
828da14cebeSEric Cheng 	char vnic_macaddrtype[19];
829da14cebeSEric Cheng 	char vnic_vid[6];
830da14cebeSEric Cheng } vnic_fields_buf_t;
831da14cebeSEric Cheng 
8328002d411SSowmini Varadhan static ofmt_field_t vnic_fields[] = {
8338002d411SSowmini Varadhan { "LINK",		13,
8348002d411SSowmini Varadhan 	offsetof(vnic_fields_buf_t, vnic_link),	print_default_cb},
8358002d411SSowmini Varadhan { "OVER",		13,
8368002d411SSowmini Varadhan 	offsetof(vnic_fields_buf_t, vnic_over),	print_default_cb},
8378002d411SSowmini Varadhan { "SPEED",		7,
8388002d411SSowmini Varadhan 	offsetof(vnic_fields_buf_t, vnic_speed), print_default_cb},
839b509e89bSRishi Srivatsavai { "MACADDRESS",		18,
8408002d411SSowmini Varadhan 	offsetof(vnic_fields_buf_t, vnic_macaddr), print_default_cb},
8418002d411SSowmini Varadhan { "MACADDRTYPE",	20,
8428002d411SSowmini Varadhan 	offsetof(vnic_fields_buf_t, vnic_macaddrtype), print_default_cb},
8438002d411SSowmini Varadhan { "VID",		7,
8448002d411SSowmini Varadhan 	offsetof(vnic_fields_buf_t, vnic_vid), print_default_cb},
8458002d411SSowmini Varadhan { NULL,			0, 0, NULL}}
846da14cebeSEric Cheng ;
847da14cebeSEric Cheng 
848da14cebeSEric Cheng /*
849b509e89bSRishi Srivatsavai  * structures for 'dladm show-simnet'
850b509e89bSRishi Srivatsavai  */
851b509e89bSRishi Srivatsavai typedef struct simnet_fields_buf_s
852b509e89bSRishi Srivatsavai {
853b509e89bSRishi Srivatsavai 	char simnet_name[DLPI_LINKNAME_MAX];
854b509e89bSRishi Srivatsavai 	char simnet_media[DLADM_STRSIZE];
855b509e89bSRishi Srivatsavai 	char simnet_macaddr[18];
856b509e89bSRishi Srivatsavai 	char simnet_otherlink[DLPI_LINKNAME_MAX];
857b509e89bSRishi Srivatsavai } simnet_fields_buf_t;
858b509e89bSRishi Srivatsavai 
859b509e89bSRishi Srivatsavai static ofmt_field_t simnet_fields[] = {
860b509e89bSRishi Srivatsavai { "LINK",		12,
861b509e89bSRishi Srivatsavai 	offsetof(simnet_fields_buf_t, simnet_name), print_default_cb},
862b509e89bSRishi Srivatsavai { "MEDIA",		20,
863b509e89bSRishi Srivatsavai 	offsetof(simnet_fields_buf_t, simnet_media), print_default_cb},
864b509e89bSRishi Srivatsavai { "MACADDRESS",		18,
865b509e89bSRishi Srivatsavai 	offsetof(simnet_fields_buf_t, simnet_macaddr), print_default_cb},
866b509e89bSRishi Srivatsavai { "OTHERLINK",		12,
867b509e89bSRishi Srivatsavai 	offsetof(simnet_fields_buf_t, simnet_otherlink), print_default_cb},
868b509e89bSRishi Srivatsavai { NULL,			0, 0, NULL}}
869b509e89bSRishi Srivatsavai ;
870b509e89bSRishi Srivatsavai 
871b509e89bSRishi Srivatsavai /*
872da14cebeSEric Cheng  * structures for 'dladm show-usage'
873da14cebeSEric Cheng  */
874da14cebeSEric Cheng 
875da14cebeSEric Cheng typedef struct  usage_fields_buf_s {
876da14cebeSEric Cheng 	char	usage_link[12];
877da14cebeSEric Cheng 	char	usage_duration[10];
878da14cebeSEric Cheng 	char	usage_ipackets[9];
879da14cebeSEric Cheng 	char	usage_rbytes[10];
880da14cebeSEric Cheng 	char	usage_opackets[9];
881da14cebeSEric Cheng 	char	usage_obytes[10];
882da14cebeSEric Cheng 	char	usage_bandwidth[14];
883da14cebeSEric Cheng } usage_fields_buf_t;
884da14cebeSEric Cheng 
8858002d411SSowmini Varadhan static ofmt_field_t usage_fields[] = {
8868002d411SSowmini Varadhan { "LINK",	13,
8878002d411SSowmini Varadhan 	offsetof(usage_fields_buf_t, usage_link), print_default_cb},
8888002d411SSowmini Varadhan { "DURATION",	11,
8898002d411SSowmini Varadhan 	offsetof(usage_fields_buf_t, usage_duration), print_default_cb},
8908002d411SSowmini Varadhan { "IPACKETS",	10,
8918002d411SSowmini Varadhan 	offsetof(usage_fields_buf_t, usage_ipackets), print_default_cb},
8928002d411SSowmini Varadhan { "RBYTES",	11,
8938002d411SSowmini Varadhan 	offsetof(usage_fields_buf_t, usage_rbytes), print_default_cb},
8948002d411SSowmini Varadhan { "OPACKETS",	10,
8958002d411SSowmini Varadhan 	offsetof(usage_fields_buf_t, usage_opackets), print_default_cb},
8968002d411SSowmini Varadhan { "OBYTES",	11,
8978002d411SSowmini Varadhan 	offsetof(usage_fields_buf_t, usage_obytes), print_default_cb},
8988002d411SSowmini Varadhan { "BANDWIDTH",	15,
8998002d411SSowmini Varadhan 	offsetof(usage_fields_buf_t, usage_bandwidth), print_default_cb},
9008002d411SSowmini Varadhan { NULL,		0, 0, NULL}}
901da14cebeSEric Cheng ;
902da14cebeSEric Cheng 
903da14cebeSEric Cheng 
904da14cebeSEric Cheng /*
905da14cebeSEric Cheng  * structures for 'dladm show-usage link'
906da14cebeSEric Cheng  */
907da14cebeSEric Cheng 
908da14cebeSEric Cheng typedef struct  usage_l_fields_buf_s {
909da14cebeSEric Cheng 	char	usage_l_link[12];
910da14cebeSEric Cheng 	char	usage_l_stime[13];
911da14cebeSEric Cheng 	char	usage_l_etime[13];
912da14cebeSEric Cheng 	char	usage_l_rbytes[8];
913da14cebeSEric Cheng 	char	usage_l_obytes[8];
914da14cebeSEric Cheng 	char	usage_l_bandwidth[14];
915da14cebeSEric Cheng } usage_l_fields_buf_t;
916da14cebeSEric Cheng 
9178002d411SSowmini Varadhan static ofmt_field_t usage_l_fields[] = {
9188002d411SSowmini Varadhan /* name,	field width,	offset */
9198002d411SSowmini Varadhan { "LINK",	13,
9208002d411SSowmini Varadhan 	offsetof(usage_l_fields_buf_t, usage_l_link), print_default_cb},
9218002d411SSowmini Varadhan { "START",	14,
9228002d411SSowmini Varadhan 	offsetof(usage_l_fields_buf_t, usage_l_stime), print_default_cb},
9238002d411SSowmini Varadhan { "END",	14,
9248002d411SSowmini Varadhan 	offsetof(usage_l_fields_buf_t, usage_l_etime), print_default_cb},
9258002d411SSowmini Varadhan { "RBYTES",	9,
9268002d411SSowmini Varadhan 	offsetof(usage_l_fields_buf_t, usage_l_rbytes), print_default_cb},
9278002d411SSowmini Varadhan { "OBYTES",	9,
9288002d411SSowmini Varadhan 	offsetof(usage_l_fields_buf_t, usage_l_obytes), print_default_cb},
9298002d411SSowmini Varadhan { "BANDWIDTH",	15,
9308002d411SSowmini Varadhan 	offsetof(usage_l_fields_buf_t, usage_l_bandwidth), print_default_cb},
9318002d411SSowmini Varadhan { NULL,		0, 0, NULL}}
932da14cebeSEric Cheng ;
933da14cebeSEric Cheng 
9347c478bd9Sstevel@tonic-gate static char *progname;
9350ba2cbe9Sxc151355 static sig_atomic_t signalled;
9367c478bd9Sstevel@tonic-gate 
9374ac67f02SAnurag S. Maskey /*
9384ac67f02SAnurag S. Maskey  * Handle to libdladm.  Opened in main() before the sub-command
9394ac67f02SAnurag S. Maskey  * specific function is called.
9404ac67f02SAnurag S. Maskey  */
9414ac67f02SAnurag S. Maskey static dladm_handle_t handle = NULL;
9424ac67f02SAnurag S. Maskey 
943da14cebeSEric Cheng #define	DLADM_ETHERSTUB_NAME	"etherstub"
944da14cebeSEric Cheng #define	DLADM_IS_ETHERSTUB(id)	(id == DATALINK_INVALID_LINKID)
945da14cebeSEric Cheng 
9467c478bd9Sstevel@tonic-gate static void
9477c478bd9Sstevel@tonic-gate usage(void)
9487c478bd9Sstevel@tonic-gate {
9498d5c46e6Sam223141 	int	i;
9508d5c46e6Sam223141 	cmd_t	*cmdp;
9518d5c46e6Sam223141 	(void) fprintf(stderr, gettext("usage:  dladm <subcommand> <args> ..."
9528d5c46e6Sam223141 	    "\n"));
9538d5c46e6Sam223141 	for (i = 0; i < sizeof (cmds) / sizeof (cmds[0]); i++) {
9548d5c46e6Sam223141 		cmdp = &cmds[i];
9558d5c46e6Sam223141 		if (cmdp->c_usage != NULL)
9568d5c46e6Sam223141 			(void) fprintf(stderr, "%s\n", gettext(cmdp->c_usage));
9578d5c46e6Sam223141 	}
9584ac67f02SAnurag S. Maskey 
9594ac67f02SAnurag S. Maskey 	/* close dladm handle if it was opened */
9604ac67f02SAnurag S. Maskey 	if (handle != NULL)
9614ac67f02SAnurag S. Maskey 		dladm_close(handle);
9624ac67f02SAnurag S. Maskey 
9637c478bd9Sstevel@tonic-gate 	exit(1);
9647c478bd9Sstevel@tonic-gate }
9657c478bd9Sstevel@tonic-gate 
9667c478bd9Sstevel@tonic-gate int
9677c478bd9Sstevel@tonic-gate main(int argc, char *argv[])
9687c478bd9Sstevel@tonic-gate {
9697c478bd9Sstevel@tonic-gate 	int	i;
9707c478bd9Sstevel@tonic-gate 	cmd_t	*cmdp;
9714ac67f02SAnurag S. Maskey 	dladm_status_t status;
9727c478bd9Sstevel@tonic-gate 
9737c478bd9Sstevel@tonic-gate 	(void) setlocale(LC_ALL, "");
9747c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN)
9757c478bd9Sstevel@tonic-gate #define	TEXT_DOMAIN "SYS_TEST"
9767c478bd9Sstevel@tonic-gate #endif
9777c478bd9Sstevel@tonic-gate 	(void) textdomain(TEXT_DOMAIN);
9787c478bd9Sstevel@tonic-gate 
9797c478bd9Sstevel@tonic-gate 	progname = argv[0];
9807c478bd9Sstevel@tonic-gate 
9817c478bd9Sstevel@tonic-gate 	if (argc < 2)
9827c478bd9Sstevel@tonic-gate 		usage();
9837c478bd9Sstevel@tonic-gate 
9847c478bd9Sstevel@tonic-gate 	for (i = 0; i < sizeof (cmds) / sizeof (cmds[0]); i++) {
9857c478bd9Sstevel@tonic-gate 		cmdp = &cmds[i];
9867c478bd9Sstevel@tonic-gate 		if (strcmp(argv[1], cmdp->c_name) == 0) {
9874ac67f02SAnurag S. Maskey 			/* Open the libdladm handle */
9884ac67f02SAnurag S. Maskey 			if ((status = dladm_open(&handle)) != DLADM_STATUS_OK) {
9894ac67f02SAnurag S. Maskey 				die_dlerr(status,
9904ac67f02SAnurag S. Maskey 				    "could not open /dev/dld");
9914ac67f02SAnurag S. Maskey 			}
9924ac67f02SAnurag S. Maskey 
9938d5c46e6Sam223141 			cmdp->c_fn(argc - 1, &argv[1], cmdp->c_usage);
9944ac67f02SAnurag S. Maskey 
9954ac67f02SAnurag S. Maskey 			dladm_close(handle);
9967c478bd9Sstevel@tonic-gate 			exit(0);
9977c478bd9Sstevel@tonic-gate 		}
9987c478bd9Sstevel@tonic-gate 	}
9997c478bd9Sstevel@tonic-gate 
10007c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, gettext("%s: unknown subcommand '%s'\n"),
10017c478bd9Sstevel@tonic-gate 	    progname, argv[1]);
10027c478bd9Sstevel@tonic-gate 	usage();
10037c478bd9Sstevel@tonic-gate 
10047c478bd9Sstevel@tonic-gate 	return (0);
10057c478bd9Sstevel@tonic-gate }
10067c478bd9Sstevel@tonic-gate 
1007da14cebeSEric Cheng /*ARGSUSED*/
1008da14cebeSEric Cheng static int
1009da14cebeSEric Cheng show_usage_date(dladm_usage_t *usage, void *arg)
1010da14cebeSEric Cheng {
1011ae6aa22aSVenugopal Iyer 	show_usage_state_t	*state = (show_usage_state_t *)arg;
1012da14cebeSEric Cheng 	time_t			stime;
1013da14cebeSEric Cheng 	char			timebuf[20];
1014ae6aa22aSVenugopal Iyer 	dladm_status_t		status;
1015ae6aa22aSVenugopal Iyer 	uint32_t		flags;
1016ae6aa22aSVenugopal Iyer 
1017ae6aa22aSVenugopal Iyer 	/*
1018ae6aa22aSVenugopal Iyer 	 * Only show usage information for existing links unless '-a'
1019ae6aa22aSVenugopal Iyer 	 * is specified.
1020ae6aa22aSVenugopal Iyer 	 */
1021ae6aa22aSVenugopal Iyer 	if (!state->us_showall) {
1022ae6aa22aSVenugopal Iyer 		if ((status = dladm_name2info(handle, usage->du_name,
1023ae6aa22aSVenugopal Iyer 		    NULL, &flags, NULL, NULL)) != DLADM_STATUS_OK) {
1024ae6aa22aSVenugopal Iyer 			return (status);
1025ae6aa22aSVenugopal Iyer 		}
1026ae6aa22aSVenugopal Iyer 		if ((flags & DLADM_OPT_ACTIVE) == 0)
1027ae6aa22aSVenugopal Iyer 			return (DLADM_STATUS_LINKINVAL);
1028ae6aa22aSVenugopal Iyer 	}
1029da14cebeSEric Cheng 
1030da14cebeSEric Cheng 	stime = usage->du_stime;
1031da14cebeSEric Cheng 	(void) strftime(timebuf, sizeof (timebuf), "%m/%d/%Y",
1032da14cebeSEric Cheng 	    localtime(&stime));
1033da14cebeSEric Cheng 	(void) printf("%s\n", timebuf);
1034da14cebeSEric Cheng 
1035da14cebeSEric Cheng 	return (DLADM_STATUS_OK);
1036da14cebeSEric Cheng }
1037da14cebeSEric Cheng 
1038da14cebeSEric Cheng static int
1039da14cebeSEric Cheng show_usage_time(dladm_usage_t *usage, void *arg)
1040da14cebeSEric Cheng {
1041da14cebeSEric Cheng 	show_usage_state_t	*state = (show_usage_state_t *)arg;
1042da14cebeSEric Cheng 	char			buf[DLADM_STRSIZE];
1043da14cebeSEric Cheng 	usage_l_fields_buf_t 	ubuf;
1044da14cebeSEric Cheng 	time_t			time;
1045da14cebeSEric Cheng 	double			bw;
1046ae6aa22aSVenugopal Iyer 	dladm_status_t		status;
1047ae6aa22aSVenugopal Iyer 	uint32_t		flags;
1048ae6aa22aSVenugopal Iyer 
1049ae6aa22aSVenugopal Iyer 	/*
1050ae6aa22aSVenugopal Iyer 	 * Only show usage information for existing links unless '-a'
1051ae6aa22aSVenugopal Iyer 	 * is specified.
1052ae6aa22aSVenugopal Iyer 	 */
1053ae6aa22aSVenugopal Iyer 	if (!state->us_showall) {
1054ae6aa22aSVenugopal Iyer 		if ((status = dladm_name2info(handle, usage->du_name,
1055ae6aa22aSVenugopal Iyer 		    NULL, &flags, NULL, NULL)) != DLADM_STATUS_OK) {
1056ae6aa22aSVenugopal Iyer 			return (status);
1057ae6aa22aSVenugopal Iyer 		}
1058ae6aa22aSVenugopal Iyer 		if ((flags & DLADM_OPT_ACTIVE) == 0)
1059ae6aa22aSVenugopal Iyer 			return (DLADM_STATUS_LINKINVAL);
1060ae6aa22aSVenugopal Iyer 	}
1061da14cebeSEric Cheng 
1062da14cebeSEric Cheng 	if (state->us_plot) {
1063da14cebeSEric Cheng 		if (!state->us_printheader) {
1064da14cebeSEric Cheng 			if (state->us_first) {
1065da14cebeSEric Cheng 				(void) printf("# Time");
1066da14cebeSEric Cheng 				state->us_first = B_FALSE;
1067da14cebeSEric Cheng 			}
1068da14cebeSEric Cheng 			(void) printf(" %s", usage->du_name);
1069da14cebeSEric Cheng 			if (usage->du_last) {
1070da14cebeSEric Cheng 				(void) printf("\n");
1071da14cebeSEric Cheng 				state->us_first = B_TRUE;
1072da14cebeSEric Cheng 				state->us_printheader = B_TRUE;
1073da14cebeSEric Cheng 			}
1074da14cebeSEric Cheng 		} else {
1075da14cebeSEric Cheng 			if (state->us_first) {
1076da14cebeSEric Cheng 				time = usage->du_etime;
1077da14cebeSEric Cheng 				(void) strftime(buf, sizeof (buf), "%T",
1078da14cebeSEric Cheng 				    localtime(&time));
1079da14cebeSEric Cheng 				state->us_first = B_FALSE;
1080da14cebeSEric Cheng 				(void) printf("%s", buf);
1081da14cebeSEric Cheng 			}
1082da14cebeSEric Cheng 			bw = (double)usage->du_bandwidth/1000;
1083da14cebeSEric Cheng 			(void) printf(" %.2f", bw);
1084da14cebeSEric Cheng 			if (usage->du_last) {
1085da14cebeSEric Cheng 				(void) printf("\n");
1086da14cebeSEric Cheng 				state->us_first = B_TRUE;
1087da14cebeSEric Cheng 			}
1088da14cebeSEric Cheng 		}
1089da14cebeSEric Cheng 		return (DLADM_STATUS_OK);
1090da14cebeSEric Cheng 	}
1091da14cebeSEric Cheng 
1092da14cebeSEric Cheng 	bzero(&ubuf, sizeof (ubuf));
1093da14cebeSEric Cheng 
1094da14cebeSEric Cheng 	(void) snprintf(ubuf.usage_l_link, sizeof (ubuf.usage_l_link), "%s",
1095da14cebeSEric Cheng 	    usage->du_name);
1096da14cebeSEric Cheng 	time = usage->du_stime;
1097da14cebeSEric Cheng 	(void) strftime(buf, sizeof (buf), "%T", localtime(&time));
1098da14cebeSEric Cheng 	(void) snprintf(ubuf.usage_l_stime, sizeof (ubuf.usage_l_stime), "%s",
1099da14cebeSEric Cheng 	    buf);
1100da14cebeSEric Cheng 	time = usage->du_etime;
1101da14cebeSEric Cheng 	(void) strftime(buf, sizeof (buf), "%T", localtime(&time));
1102da14cebeSEric Cheng 	(void) snprintf(ubuf.usage_l_etime, sizeof (ubuf.usage_l_etime), "%s",
1103da14cebeSEric Cheng 	    buf);
1104da14cebeSEric Cheng 	(void) snprintf(ubuf.usage_l_rbytes, sizeof (ubuf.usage_l_rbytes),
1105da14cebeSEric Cheng 	    "%llu", usage->du_rbytes);
1106da14cebeSEric Cheng 	(void) snprintf(ubuf.usage_l_obytes, sizeof (ubuf.usage_l_obytes),
1107da14cebeSEric Cheng 	    "%llu", usage->du_obytes);
1108da14cebeSEric Cheng 	(void) snprintf(ubuf.usage_l_bandwidth, sizeof (ubuf.usage_l_bandwidth),
1109da14cebeSEric Cheng 	    "%s Mbps", dladm_bw2str(usage->du_bandwidth, buf));
1110da14cebeSEric Cheng 
11118002d411SSowmini Varadhan 	ofmt_print(state->us_ofmt, &ubuf);
1112da14cebeSEric Cheng 	return (DLADM_STATUS_OK);
1113da14cebeSEric Cheng }
1114da14cebeSEric Cheng 
1115da14cebeSEric Cheng static int
1116da14cebeSEric Cheng show_usage_res(dladm_usage_t *usage, void *arg)
1117da14cebeSEric Cheng {
1118da14cebeSEric Cheng 	show_usage_state_t	*state = (show_usage_state_t *)arg;
1119da14cebeSEric Cheng 	char			buf[DLADM_STRSIZE];
1120da14cebeSEric Cheng 	usage_fields_buf_t	ubuf;
1121ae6aa22aSVenugopal Iyer 	dladm_status_t		status;
1122ae6aa22aSVenugopal Iyer 	uint32_t		flags;
1123ae6aa22aSVenugopal Iyer 
1124ae6aa22aSVenugopal Iyer 	/*
1125ae6aa22aSVenugopal Iyer 	 * Only show usage information for existing links unless '-a'
1126ae6aa22aSVenugopal Iyer 	 * is specified.
1127ae6aa22aSVenugopal Iyer 	 */
1128ae6aa22aSVenugopal Iyer 	if (!state->us_showall) {
1129ae6aa22aSVenugopal Iyer 		if ((status = dladm_name2info(handle, usage->du_name,
1130ae6aa22aSVenugopal Iyer 		    NULL, &flags, NULL, NULL)) != DLADM_STATUS_OK) {
1131ae6aa22aSVenugopal Iyer 			return (status);
1132ae6aa22aSVenugopal Iyer 		}
1133ae6aa22aSVenugopal Iyer 		if ((flags & DLADM_OPT_ACTIVE) == 0)
1134ae6aa22aSVenugopal Iyer 			return (DLADM_STATUS_LINKINVAL);
1135ae6aa22aSVenugopal Iyer 	}
1136da14cebeSEric Cheng 
1137da14cebeSEric Cheng 	bzero(&ubuf, sizeof (ubuf));
1138da14cebeSEric Cheng 
1139da14cebeSEric Cheng 	(void) snprintf(ubuf.usage_link, sizeof (ubuf.usage_link), "%s",
1140da14cebeSEric Cheng 	    usage->du_name);
1141da14cebeSEric Cheng 	(void) snprintf(ubuf.usage_duration, sizeof (ubuf.usage_duration),
1142da14cebeSEric Cheng 	    "%llu", usage->du_duration);
1143da14cebeSEric Cheng 	(void) snprintf(ubuf.usage_ipackets, sizeof (ubuf.usage_ipackets),
1144da14cebeSEric Cheng 	    "%llu", usage->du_ipackets);
1145da14cebeSEric Cheng 	(void) snprintf(ubuf.usage_rbytes, sizeof (ubuf.usage_rbytes),
1146da14cebeSEric Cheng 	    "%llu", usage->du_rbytes);
1147da14cebeSEric Cheng 	(void) snprintf(ubuf.usage_opackets, sizeof (ubuf.usage_opackets),
1148da14cebeSEric Cheng 	    "%llu", usage->du_opackets);
1149da14cebeSEric Cheng 	(void) snprintf(ubuf.usage_obytes, sizeof (ubuf.usage_obytes),
1150da14cebeSEric Cheng 	    "%llu", usage->du_obytes);
1151da14cebeSEric Cheng 	(void) snprintf(ubuf.usage_bandwidth, sizeof (ubuf.usage_bandwidth),
1152da14cebeSEric Cheng 	    "%s Mbps", dladm_bw2str(usage->du_bandwidth, buf));
1153da14cebeSEric Cheng 
11548002d411SSowmini Varadhan 	ofmt_print(state->us_ofmt, &ubuf);
1155da14cebeSEric Cheng 
1156da14cebeSEric Cheng 	return (DLADM_STATUS_OK);
1157da14cebeSEric Cheng }
1158da14cebeSEric Cheng 
1159da14cebeSEric Cheng static boolean_t
1160da14cebeSEric Cheng valid_formatspec(char *formatspec_str)
1161da14cebeSEric Cheng {
1162da14cebeSEric Cheng 	if (strcmp(formatspec_str, "gnuplot") == 0)
1163da14cebeSEric Cheng 		return (B_TRUE);
1164da14cebeSEric Cheng 	return (B_FALSE);
1165da14cebeSEric Cheng 
1166da14cebeSEric Cheng }
1167da14cebeSEric Cheng 
1168da14cebeSEric Cheng /*ARGSUSED*/
1169da14cebeSEric Cheng static void
1170da14cebeSEric Cheng do_show_usage(int argc, char *argv[], const char *use)
1171da14cebeSEric Cheng {
1172da14cebeSEric Cheng 	char			*file = NULL;
1173da14cebeSEric Cheng 	int			opt;
1174da14cebeSEric Cheng 	dladm_status_t		status;
1175da14cebeSEric Cheng 	boolean_t		d_arg = B_FALSE;
1176da14cebeSEric Cheng 	char			*stime = NULL;
1177da14cebeSEric Cheng 	char			*etime = NULL;
1178da14cebeSEric Cheng 	char			*resource = NULL;
1179da14cebeSEric Cheng 	show_usage_state_t	state;
1180da14cebeSEric Cheng 	boolean_t		o_arg = B_FALSE;
1181da14cebeSEric Cheng 	boolean_t		F_arg = B_FALSE;
1182da14cebeSEric Cheng 	char			*fields_str = NULL;
1183da14cebeSEric Cheng 	char			*formatspec_str = NULL;
1184da14cebeSEric Cheng 	char			*all_l_fields =
1185da14cebeSEric Cheng 	    "link,start,end,rbytes,obytes,bandwidth";
11868002d411SSowmini Varadhan 	ofmt_handle_t		ofmt;
11878002d411SSowmini Varadhan 	ofmt_status_t		oferr;
11888002d411SSowmini Varadhan 	uint_t			ofmtflags = 0;
1189da14cebeSEric Cheng 
1190da14cebeSEric Cheng 	bzero(&state, sizeof (show_usage_state_t));
11918002d411SSowmini Varadhan 	state.us_parsable = B_FALSE;
1192da14cebeSEric Cheng 	state.us_printheader = B_FALSE;
1193da14cebeSEric Cheng 	state.us_plot = B_FALSE;
1194da14cebeSEric Cheng 	state.us_first = B_TRUE;
1195da14cebeSEric Cheng 
1196ae6aa22aSVenugopal Iyer 	while ((opt = getopt_long(argc, argv, "das:e:o:f:F:",
1197ae6aa22aSVenugopal Iyer 	    usage_opts, NULL)) != -1) {
1198da14cebeSEric Cheng 		switch (opt) {
1199da14cebeSEric Cheng 		case 'd':
1200da14cebeSEric Cheng 			d_arg = B_TRUE;
1201da14cebeSEric Cheng 			break;
1202ae6aa22aSVenugopal Iyer 		case 'a':
1203ae6aa22aSVenugopal Iyer 			state.us_showall = B_TRUE;
1204da14cebeSEric Cheng 			break;
1205da14cebeSEric Cheng 		case 'f':
1206da14cebeSEric Cheng 			file = optarg;
1207da14cebeSEric Cheng 			break;
1208da14cebeSEric Cheng 		case 's':
1209da14cebeSEric Cheng 			stime = optarg;
1210da14cebeSEric Cheng 			break;
1211da14cebeSEric Cheng 		case 'e':
1212da14cebeSEric Cheng 			etime = optarg;
1213da14cebeSEric Cheng 			break;
1214da14cebeSEric Cheng 		case 'o':
1215da14cebeSEric Cheng 			o_arg = B_TRUE;
1216da14cebeSEric Cheng 			fields_str = optarg;
1217da14cebeSEric Cheng 			break;
1218da14cebeSEric Cheng 		case 'F':
1219ae6aa22aSVenugopal Iyer 			state.us_plot = F_arg = B_TRUE;
1220da14cebeSEric Cheng 			formatspec_str = optarg;
1221da14cebeSEric Cheng 			break;
1222da14cebeSEric Cheng 		default:
1223da14cebeSEric Cheng 			die_opterr(optopt, opt, use);
1224da14cebeSEric Cheng 			break;
1225da14cebeSEric Cheng 		}
1226da14cebeSEric Cheng 	}
1227da14cebeSEric Cheng 
1228da14cebeSEric Cheng 	if (file == NULL)
1229da14cebeSEric Cheng 		die("show-usage requires a file");
1230da14cebeSEric Cheng 
1231da14cebeSEric Cheng 	if (optind == (argc-1)) {
1232ae6aa22aSVenugopal Iyer 		uint32_t 	flags;
1233ae6aa22aSVenugopal Iyer 
1234da14cebeSEric Cheng 		resource = argv[optind];
1235ae6aa22aSVenugopal Iyer 		if (!state.us_showall &&
1236ae6aa22aSVenugopal Iyer 		    (((status = dladm_name2info(handle, resource, NULL, &flags,
1237ae6aa22aSVenugopal Iyer 		    NULL, NULL)) != DLADM_STATUS_OK) ||
1238ae6aa22aSVenugopal Iyer 		    ((flags & DLADM_OPT_ACTIVE) == 0))) {
1239ae6aa22aSVenugopal Iyer 			die("invalid link: '%s'", resource);
1240ae6aa22aSVenugopal Iyer 		}
1241da14cebeSEric Cheng 	}
1242da14cebeSEric Cheng 
1243ae6aa22aSVenugopal Iyer 	if (F_arg && d_arg)
1244ae6aa22aSVenugopal Iyer 		die("incompatible -d and -F options");
1245da14cebeSEric Cheng 
1246da14cebeSEric Cheng 	if (F_arg && valid_formatspec(formatspec_str) == B_FALSE)
1247da14cebeSEric Cheng 		die("Format specifier %s not supported", formatspec_str);
1248da14cebeSEric Cheng 
12498002d411SSowmini Varadhan 	if (state.us_parsable)
12508002d411SSowmini Varadhan 		ofmtflags |= OFMT_PARSABLE;
12518002d411SSowmini Varadhan 
12528002d411SSowmini Varadhan 	if (resource == NULL && stime == NULL && etime == NULL) {
12538002d411SSowmini Varadhan 		oferr = ofmt_open(fields_str, usage_fields, ofmtflags, 0,
12548002d411SSowmini Varadhan 		    &ofmt);
12558002d411SSowmini Varadhan 	} else {
12568002d411SSowmini Varadhan 		if (!o_arg || (o_arg && strcasecmp(fields_str, "all") == 0))
12578002d411SSowmini Varadhan 			fields_str = all_l_fields;
12588002d411SSowmini Varadhan 		oferr = ofmt_open(fields_str, usage_l_fields, ofmtflags, 0,
12598002d411SSowmini Varadhan 		    &ofmt);
12608002d411SSowmini Varadhan 
12618002d411SSowmini Varadhan 	}
12628002d411SSowmini Varadhan 	dladm_ofmt_check(oferr, state.us_parsable, ofmt);
12638002d411SSowmini Varadhan 	state.us_ofmt = ofmt;
12648002d411SSowmini Varadhan 
1265da14cebeSEric Cheng 	if (d_arg) {
1266da14cebeSEric Cheng 		/* Print log dates */
1267da14cebeSEric Cheng 		status = dladm_usage_dates(show_usage_date,
1268da14cebeSEric Cheng 		    DLADM_LOGTYPE_LINK, file, resource, &state);
1269da14cebeSEric Cheng 	} else if (resource == NULL && stime == NULL && etime == NULL &&
1270ae6aa22aSVenugopal Iyer 	    !F_arg) {
1271da14cebeSEric Cheng 		/* Print summary */
1272da14cebeSEric Cheng 		status = dladm_usage_summary(show_usage_res,
1273da14cebeSEric Cheng 		    DLADM_LOGTYPE_LINK, file, &state);
1274da14cebeSEric Cheng 	} else if (resource != NULL) {
1275da14cebeSEric Cheng 		/* Print log entries for named resource */
1276da14cebeSEric Cheng 		status = dladm_walk_usage_res(show_usage_time,
1277da14cebeSEric Cheng 		    DLADM_LOGTYPE_LINK, file, resource, stime, etime, &state);
1278da14cebeSEric Cheng 	} else {
1279da14cebeSEric Cheng 		/* Print time and information for each link */
1280da14cebeSEric Cheng 		status = dladm_walk_usage_time(show_usage_time,
1281da14cebeSEric Cheng 		    DLADM_LOGTYPE_LINK, file, stime, etime, &state);
1282da14cebeSEric Cheng 	}
1283da14cebeSEric Cheng 
1284da14cebeSEric Cheng 	if (status != DLADM_STATUS_OK)
1285da14cebeSEric Cheng 		die_dlerr(status, "show-usage");
12868002d411SSowmini Varadhan 	ofmt_close(ofmt);
1287da14cebeSEric Cheng }
1288da14cebeSEric Cheng 
12897c478bd9Sstevel@tonic-gate static void
12908d5c46e6Sam223141 do_create_aggr(int argc, char *argv[], const char *use)
12917c478bd9Sstevel@tonic-gate {
1292b509e89bSRishi Srivatsavai 	int			option;
1293d62bc4baSyz147064 	int			key = 0;
12947c478bd9Sstevel@tonic-gate 	uint32_t		policy = AGGR_POLICY_L4;
12957c478bd9Sstevel@tonic-gate 	aggr_lacp_mode_t	lacp_mode = AGGR_LACP_OFF;
12967c478bd9Sstevel@tonic-gate 	aggr_lacp_timer_t	lacp_timer = AGGR_LACP_TIMER_SHORT;
1297f595a68aSyz147064 	dladm_aggr_port_attr_db_t	port[MAXPORT];
1298d62bc4baSyz147064 	uint_t			n, ndev, nlink;
12997c478bd9Sstevel@tonic-gate 	uint8_t			mac_addr[ETHERADDRL];
13007c478bd9Sstevel@tonic-gate 	boolean_t		mac_addr_fixed = B_FALSE;
13017c478bd9Sstevel@tonic-gate 	boolean_t		P_arg = B_FALSE;
13027c478bd9Sstevel@tonic-gate 	boolean_t		l_arg = B_FALSE;
13037c478bd9Sstevel@tonic-gate 	boolean_t		u_arg = B_FALSE;
13047c478bd9Sstevel@tonic-gate 	boolean_t		T_arg = B_FALSE;
1305d62bc4baSyz147064 	uint32_t		flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST;
13067c478bd9Sstevel@tonic-gate 	char			*altroot = NULL;
1307d62bc4baSyz147064 	char			name[MAXLINKNAMELEN];
1308d62bc4baSyz147064 	char			*devs[MAXPORT];
1309d62bc4baSyz147064 	char			*links[MAXPORT];
1310f595a68aSyz147064 	dladm_status_t		status;
1311da14cebeSEric Cheng 	dladm_status_t		pstatus;
131263a6526dSMichael Lim 	char			propstr[DLADM_STRSIZE];
1313da14cebeSEric Cheng 	dladm_arg_list_t	*proplist = NULL;
1314da14cebeSEric Cheng 	int			i;
1315da14cebeSEric Cheng 	datalink_id_t		linkid;
13167c478bd9Sstevel@tonic-gate 
1317d62bc4baSyz147064 	ndev = nlink = opterr = 0;
131863a6526dSMichael Lim 	bzero(propstr, DLADM_STRSIZE);
131963a6526dSMichael Lim 
1320da14cebeSEric Cheng 	while ((option = getopt_long(argc, argv, ":d:l:L:P:R:tfu:T:p:",
1321d62bc4baSyz147064 	    lopts, NULL)) != -1) {
13227c478bd9Sstevel@tonic-gate 		switch (option) {
13237c478bd9Sstevel@tonic-gate 		case 'd':
1324d62bc4baSyz147064 			if (ndev + nlink >= MAXPORT)
1325d62bc4baSyz147064 				die("too many ports specified");
13267c478bd9Sstevel@tonic-gate 
1327d62bc4baSyz147064 			devs[ndev++] = optarg;
13287c478bd9Sstevel@tonic-gate 			break;
13297c478bd9Sstevel@tonic-gate 		case 'P':
133033343a97Smeem 			if (P_arg)
133133343a97Smeem 				die_optdup(option);
13327c478bd9Sstevel@tonic-gate 
13337c478bd9Sstevel@tonic-gate 			P_arg = B_TRUE;
1334f595a68aSyz147064 			if (!dladm_aggr_str2policy(optarg, &policy))
133533343a97Smeem 				die("invalid policy '%s'", optarg);
13367c478bd9Sstevel@tonic-gate 			break;
13377c478bd9Sstevel@tonic-gate 		case 'u':
133833343a97Smeem 			if (u_arg)
133933343a97Smeem 				die_optdup(option);
13407c478bd9Sstevel@tonic-gate 
13417c478bd9Sstevel@tonic-gate 			u_arg = B_TRUE;
1342f595a68aSyz147064 			if (!dladm_aggr_str2macaddr(optarg, &mac_addr_fixed,
134333343a97Smeem 			    mac_addr))
134433343a97Smeem 				die("invalid MAC address '%s'", optarg);
13457c478bd9Sstevel@tonic-gate 			break;
13467c478bd9Sstevel@tonic-gate 		case 'l':
1347d62bc4baSyz147064 			if (isdigit(optarg[strlen(optarg) - 1])) {
1348d62bc4baSyz147064 
1349d62bc4baSyz147064 				/*
1350d62bc4baSyz147064 				 * Ended with digit, possibly a link name.
1351d62bc4baSyz147064 				 */
1352d62bc4baSyz147064 				if (ndev + nlink >= MAXPORT)
1353d62bc4baSyz147064 					die("too many ports specified");
1354d62bc4baSyz147064 
1355d62bc4baSyz147064 				links[nlink++] = optarg;
1356d62bc4baSyz147064 				break;
1357d62bc4baSyz147064 			}
1358d62bc4baSyz147064 			/* FALLTHROUGH */
1359d62bc4baSyz147064 		case 'L':
136033343a97Smeem 			if (l_arg)
136133343a97Smeem 				die_optdup(option);
13627c478bd9Sstevel@tonic-gate 
13637c478bd9Sstevel@tonic-gate 			l_arg = B_TRUE;
1364f595a68aSyz147064 			if (!dladm_aggr_str2lacpmode(optarg, &lacp_mode))
136533343a97Smeem 				die("invalid LACP mode '%s'", optarg);
13667c478bd9Sstevel@tonic-gate 			break;
13677c478bd9Sstevel@tonic-gate 		case 'T':
136833343a97Smeem 			if (T_arg)
136933343a97Smeem 				die_optdup(option);
13707c478bd9Sstevel@tonic-gate 
13717c478bd9Sstevel@tonic-gate 			T_arg = B_TRUE;
1372f595a68aSyz147064 			if (!dladm_aggr_str2lacptimer(optarg, &lacp_timer))
137333343a97Smeem 				die("invalid LACP timer value '%s'", optarg);
13747c478bd9Sstevel@tonic-gate 			break;
13757c478bd9Sstevel@tonic-gate 		case 't':
1376d62bc4baSyz147064 			flags &= ~DLADM_OPT_PERSIST;
1377d62bc4baSyz147064 			break;
1378d62bc4baSyz147064 		case 'f':
1379d62bc4baSyz147064 			flags |= DLADM_OPT_FORCE;
13807c478bd9Sstevel@tonic-gate 			break;
13817c478bd9Sstevel@tonic-gate 		case 'R':
13827c478bd9Sstevel@tonic-gate 			altroot = optarg;
13837c478bd9Sstevel@tonic-gate 			break;
1384da14cebeSEric Cheng 		case 'p':
138563a6526dSMichael Lim 			(void) strlcat(propstr, optarg, DLADM_STRSIZE);
138663a6526dSMichael Lim 			if (strlcat(propstr, ",", DLADM_STRSIZE) >=
138763a6526dSMichael Lim 			    DLADM_STRSIZE)
138863a6526dSMichael Lim 				die("property list too long '%s'", propstr);
1389da14cebeSEric Cheng 			break;
139063a6526dSMichael Lim 
13917c478bd9Sstevel@tonic-gate 		default:
13928d5c46e6Sam223141 			die_opterr(optopt, option, use);
139333343a97Smeem 			break;
13947c478bd9Sstevel@tonic-gate 		}
13957c478bd9Sstevel@tonic-gate 	}
13967c478bd9Sstevel@tonic-gate 
1397d62bc4baSyz147064 	if (ndev + nlink == 0)
13987c478bd9Sstevel@tonic-gate 		usage();
13997c478bd9Sstevel@tonic-gate 
1400d62bc4baSyz147064 	/* get key value or the aggregation name (required last argument) */
14017c478bd9Sstevel@tonic-gate 	if (optind != (argc-1))
14027c478bd9Sstevel@tonic-gate 		usage();
14037c478bd9Sstevel@tonic-gate 
1404d62bc4baSyz147064 	if (!str2int(argv[optind], &key)) {
1405d62bc4baSyz147064 		if (strlcpy(name, argv[optind], MAXLINKNAMELEN) >=
1406d62bc4baSyz147064 		    MAXLINKNAMELEN) {
1407d62bc4baSyz147064 			die("link name too long '%s'", argv[optind]);
1408d62bc4baSyz147064 		}
14097c478bd9Sstevel@tonic-gate 
1410d62bc4baSyz147064 		if (!dladm_valid_linkname(name))
1411d62bc4baSyz147064 			die("invalid link name '%s'", argv[optind]);
1412d62bc4baSyz147064 	} else {
1413d62bc4baSyz147064 		(void) snprintf(name, MAXLINKNAMELEN, "aggr%d", key);
1414d62bc4baSyz147064 	}
1415d62bc4baSyz147064 
1416d62bc4baSyz147064 	if (altroot != NULL)
1417d62bc4baSyz147064 		altroot_cmd(altroot, argc, argv);
1418d62bc4baSyz147064 
1419d62bc4baSyz147064 	for (n = 0; n < ndev; n++) {
14204ac67f02SAnurag S. Maskey 		if ((status = dladm_dev2linkid(handle, devs[n],
14214ac67f02SAnurag S. Maskey 		    &port[n].lp_linkid)) != DLADM_STATUS_OK) {
14224ac67f02SAnurag S. Maskey 			die_dlerr(status, "invalid dev name '%s'", devs[n]);
1423d62bc4baSyz147064 		}
1424d62bc4baSyz147064 	}
1425d62bc4baSyz147064 
1426d62bc4baSyz147064 	for (n = 0; n < nlink; n++) {
14274ac67f02SAnurag S. Maskey 		if ((status = dladm_name2info(handle, links[n],
14284ac67f02SAnurag S. Maskey 		    &port[ndev + n].lp_linkid, NULL, NULL, NULL)) !=
14294ac67f02SAnurag S. Maskey 		    DLADM_STATUS_OK) {
14304ac67f02SAnurag S. Maskey 			die_dlerr(status, "invalid link name '%s'", links[n]);
1431d62bc4baSyz147064 		}
1432d62bc4baSyz147064 	}
1433d62bc4baSyz147064 
14344ac67f02SAnurag S. Maskey 	status = dladm_aggr_create(handle, name, key, ndev + nlink, port,
14354ac67f02SAnurag S. Maskey 	    policy, mac_addr_fixed, (const uchar_t *)mac_addr, lacp_mode,
1436d62bc4baSyz147064 	    lacp_timer, flags);
1437da14cebeSEric Cheng 	if (status != DLADM_STATUS_OK)
1438da14cebeSEric Cheng 		goto done;
1439da14cebeSEric Cheng 
144063a6526dSMichael Lim 	if (dladm_parse_link_props(propstr, &proplist, B_FALSE)
144163a6526dSMichael Lim 	    != DLADM_STATUS_OK)
144263a6526dSMichael Lim 		die("invalid aggregation property");
144363a6526dSMichael Lim 
1444da14cebeSEric Cheng 	if (proplist == NULL)
1445da14cebeSEric Cheng 		return;
1446da14cebeSEric Cheng 
14474ac67f02SAnurag S. Maskey 	status = dladm_name2info(handle, name, &linkid, NULL, NULL, NULL);
1448da14cebeSEric Cheng 	if (status != DLADM_STATUS_OK)
1449da14cebeSEric Cheng 		goto done;
1450da14cebeSEric Cheng 
1451da14cebeSEric Cheng 	for (i = 0; i < proplist->al_count; i++) {
1452da14cebeSEric Cheng 		dladm_arg_info_t	*aip = &proplist->al_info[i];
1453da14cebeSEric Cheng 
14544ac67f02SAnurag S. Maskey 		pstatus = dladm_set_linkprop(handle, linkid, aip->ai_name,
1455da14cebeSEric Cheng 		    aip->ai_val, aip->ai_count, flags);
1456da14cebeSEric Cheng 
1457da14cebeSEric Cheng 		if (pstatus != DLADM_STATUS_OK) {
1458da14cebeSEric Cheng 			die_dlerr(pstatus,
1459da14cebeSEric Cheng 			    "aggr creation succeeded but "
1460da14cebeSEric Cheng 			    "could not set property '%s'", aip->ai_name);
1461da14cebeSEric Cheng 		}
1462da14cebeSEric Cheng 	}
1463d62bc4baSyz147064 done:
1464da14cebeSEric Cheng 	dladm_free_props(proplist);
1465d62bc4baSyz147064 	if (status != DLADM_STATUS_OK) {
1466d62bc4baSyz147064 		if (status == DLADM_STATUS_NONOTIF) {
1467d62bc4baSyz147064 			die_dlerr(status, "not all links have link up/down "
1468d62bc4baSyz147064 			    "detection; must use -f (see dladm(1M))\n");
1469d62bc4baSyz147064 		} else {
1470f595a68aSyz147064 			die_dlerr(status, "create operation failed");
14717c478bd9Sstevel@tonic-gate 		}
1472d62bc4baSyz147064 	}
1473d62bc4baSyz147064 }
1474d62bc4baSyz147064 
1475d62bc4baSyz147064 /*
1476d62bc4baSyz147064  * arg is either the key or the aggr name. Validate it and convert it to
1477d62bc4baSyz147064  * the linkid if altroot is NULL.
1478d62bc4baSyz147064  */
1479d62bc4baSyz147064 static dladm_status_t
1480d62bc4baSyz147064 i_dladm_aggr_get_linkid(const char *altroot, const char *arg,
1481d62bc4baSyz147064     datalink_id_t *linkidp, uint32_t flags)
1482d62bc4baSyz147064 {
1483d62bc4baSyz147064 	int		key = 0;
1484d62bc4baSyz147064 	char		*aggr = NULL;
1485d62bc4baSyz147064 	dladm_status_t	status;
1486d62bc4baSyz147064 
1487d62bc4baSyz147064 	if (!str2int(arg, &key))
1488d62bc4baSyz147064 		aggr = (char *)arg;
1489d62bc4baSyz147064 
1490d62bc4baSyz147064 	if (aggr == NULL && key == 0)
1491d62bc4baSyz147064 		return (DLADM_STATUS_LINKINVAL);
1492d62bc4baSyz147064 
1493d62bc4baSyz147064 	if (altroot != NULL)
1494d62bc4baSyz147064 		return (DLADM_STATUS_OK);
1495d62bc4baSyz147064 
1496d62bc4baSyz147064 	if (aggr != NULL) {
14974ac67f02SAnurag S. Maskey 		status = dladm_name2info(handle, aggr, linkidp, NULL, NULL,
14984ac67f02SAnurag S. Maskey 		    NULL);
1499d62bc4baSyz147064 	} else {
15004ac67f02SAnurag S. Maskey 		status = dladm_key2linkid(handle, key, linkidp, flags);
1501d62bc4baSyz147064 	}
1502d62bc4baSyz147064 
1503d62bc4baSyz147064 	return (status);
1504d62bc4baSyz147064 }
15057c478bd9Sstevel@tonic-gate 
15067c478bd9Sstevel@tonic-gate static void
15078d5c46e6Sam223141 do_delete_aggr(int argc, char *argv[], const char *use)
15087c478bd9Sstevel@tonic-gate {
1509b509e89bSRishi Srivatsavai 	int			option;
15107c478bd9Sstevel@tonic-gate 	char			*altroot = NULL;
1511d62bc4baSyz147064 	uint32_t		flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST;
1512f595a68aSyz147064 	dladm_status_t		status;
1513d62bc4baSyz147064 	datalink_id_t		linkid;
15147c478bd9Sstevel@tonic-gate 
15157c478bd9Sstevel@tonic-gate 	opterr = 0;
1516d62bc4baSyz147064 	while ((option = getopt_long(argc, argv, ":R:t", lopts, NULL)) != -1) {
15177c478bd9Sstevel@tonic-gate 		switch (option) {
15187c478bd9Sstevel@tonic-gate 		case 't':
1519d62bc4baSyz147064 			flags &= ~DLADM_OPT_PERSIST;
15207c478bd9Sstevel@tonic-gate 			break;
15217c478bd9Sstevel@tonic-gate 		case 'R':
15227c478bd9Sstevel@tonic-gate 			altroot = optarg;
15237c478bd9Sstevel@tonic-gate 			break;
15247c478bd9Sstevel@tonic-gate 		default:
15258d5c46e6Sam223141 			die_opterr(optopt, option, use);
15267c478bd9Sstevel@tonic-gate 			break;
15277c478bd9Sstevel@tonic-gate 		}
15287c478bd9Sstevel@tonic-gate 	}
15297c478bd9Sstevel@tonic-gate 
1530d62bc4baSyz147064 	/* get key value or the aggregation name (required last argument) */
15317c478bd9Sstevel@tonic-gate 	if (optind != (argc-1))
15327c478bd9Sstevel@tonic-gate 		usage();
15337c478bd9Sstevel@tonic-gate 
1534d62bc4baSyz147064 	status = i_dladm_aggr_get_linkid(altroot, argv[optind], &linkid, flags);
1535d62bc4baSyz147064 	if (status != DLADM_STATUS_OK)
1536d62bc4baSyz147064 		goto done;
15377c478bd9Sstevel@tonic-gate 
1538d62bc4baSyz147064 	if (altroot != NULL)
1539d62bc4baSyz147064 		altroot_cmd(altroot, argc, argv);
1540d62bc4baSyz147064 
15414ac67f02SAnurag S. Maskey 	status = dladm_aggr_delete(handle, linkid, flags);
1542d62bc4baSyz147064 done:
1543f595a68aSyz147064 	if (status != DLADM_STATUS_OK)
1544f595a68aSyz147064 		die_dlerr(status, "delete operation failed");
15457c478bd9Sstevel@tonic-gate }
15467c478bd9Sstevel@tonic-gate 
15477c478bd9Sstevel@tonic-gate static void
15488d5c46e6Sam223141 do_add_aggr(int argc, char *argv[], const char *use)
15497c478bd9Sstevel@tonic-gate {
1550b509e89bSRishi Srivatsavai 	int			option;
1551d62bc4baSyz147064 	uint_t			n, ndev, nlink;
15527c478bd9Sstevel@tonic-gate 	char			*altroot = NULL;
1553d62bc4baSyz147064 	uint32_t		flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST;
1554d62bc4baSyz147064 	datalink_id_t		linkid;
1555f595a68aSyz147064 	dladm_status_t		status;
1556d62bc4baSyz147064 	dladm_aggr_port_attr_db_t	port[MAXPORT];
1557d62bc4baSyz147064 	char			*devs[MAXPORT];
1558d62bc4baSyz147064 	char			*links[MAXPORT];
15597c478bd9Sstevel@tonic-gate 
1560d62bc4baSyz147064 	ndev = nlink = opterr = 0;
1561d62bc4baSyz147064 	while ((option = getopt_long(argc, argv, ":d:l:R:tf", lopts,
15627c478bd9Sstevel@tonic-gate 	    NULL)) != -1) {
15637c478bd9Sstevel@tonic-gate 		switch (option) {
15647c478bd9Sstevel@tonic-gate 		case 'd':
1565d62bc4baSyz147064 			if (ndev + nlink >= MAXPORT)
1566d62bc4baSyz147064 				die("too many ports specified");
15677c478bd9Sstevel@tonic-gate 
1568d62bc4baSyz147064 			devs[ndev++] = optarg;
1569d62bc4baSyz147064 			break;
1570d62bc4baSyz147064 		case 'l':
1571d62bc4baSyz147064 			if (ndev + nlink >= MAXPORT)
1572d62bc4baSyz147064 				die("too many ports specified");
157333343a97Smeem 
1574d62bc4baSyz147064 			links[nlink++] = optarg;
15757c478bd9Sstevel@tonic-gate 			break;
15767c478bd9Sstevel@tonic-gate 		case 't':
1577d62bc4baSyz147064 			flags &= ~DLADM_OPT_PERSIST;
1578d62bc4baSyz147064 			break;
1579d62bc4baSyz147064 		case 'f':
1580d62bc4baSyz147064 			flags |= DLADM_OPT_FORCE;
15817c478bd9Sstevel@tonic-gate 			break;
15827c478bd9Sstevel@tonic-gate 		case 'R':
15837c478bd9Sstevel@tonic-gate 			altroot = optarg;
15847c478bd9Sstevel@tonic-gate 			break;
15857c478bd9Sstevel@tonic-gate 		default:
15868d5c46e6Sam223141 			die_opterr(optopt, option, use);
158733343a97Smeem 			break;
15887c478bd9Sstevel@tonic-gate 		}
15897c478bd9Sstevel@tonic-gate 	}
15907c478bd9Sstevel@tonic-gate 
1591d62bc4baSyz147064 	if (ndev + nlink == 0)
15927c478bd9Sstevel@tonic-gate 		usage();
15937c478bd9Sstevel@tonic-gate 
1594d62bc4baSyz147064 	/* get key value or the aggregation name (required last argument) */
15957c478bd9Sstevel@tonic-gate 	if (optind != (argc-1))
15967c478bd9Sstevel@tonic-gate 		usage();
15977c478bd9Sstevel@tonic-gate 
1598d62bc4baSyz147064 	if ((status = i_dladm_aggr_get_linkid(altroot, argv[optind], &linkid,
1599d62bc4baSyz147064 	    flags & (DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST))) !=
1600d62bc4baSyz147064 	    DLADM_STATUS_OK) {
1601d62bc4baSyz147064 		goto done;
1602d62bc4baSyz147064 	}
16037c478bd9Sstevel@tonic-gate 
1604d62bc4baSyz147064 	if (altroot != NULL)
1605d62bc4baSyz147064 		altroot_cmd(altroot, argc, argv);
1606d62bc4baSyz147064 
1607d62bc4baSyz147064 	for (n = 0; n < ndev; n++) {
16084ac67f02SAnurag S. Maskey 		if ((status = dladm_dev2linkid(handle, devs[n],
16094ac67f02SAnurag S. Maskey 		    &(port[n].lp_linkid))) != DLADM_STATUS_OK) {
16104ac67f02SAnurag S. Maskey 			die_dlerr(status, "invalid <dev> '%s'", devs[n]);
1611d62bc4baSyz147064 		}
1612d62bc4baSyz147064 	}
1613d62bc4baSyz147064 
1614d62bc4baSyz147064 	for (n = 0; n < nlink; n++) {
16154ac67f02SAnurag S. Maskey 		if ((status = dladm_name2info(handle, links[n],
16164ac67f02SAnurag S. Maskey 		    &port[n + ndev].lp_linkid, NULL, NULL, NULL)) !=
16174ac67f02SAnurag S. Maskey 		    DLADM_STATUS_OK) {
16184ac67f02SAnurag S. Maskey 			die_dlerr(status, "invalid <link> '%s'", links[n]);
1619d62bc4baSyz147064 		}
1620d62bc4baSyz147064 	}
1621d62bc4baSyz147064 
16224ac67f02SAnurag S. Maskey 	status = dladm_aggr_add(handle, linkid, ndev + nlink, port, flags);
1623d62bc4baSyz147064 done:
1624f595a68aSyz147064 	if (status != DLADM_STATUS_OK) {
1625219a2a31Shl157128 		/*
1626f595a68aSyz147064 		 * checking DLADM_STATUS_NOTSUP is a temporary workaround
1627219a2a31Shl157128 		 * and should be removed once 6399681 is fixed.
1628219a2a31Shl157128 		 */
1629f595a68aSyz147064 		if (status == DLADM_STATUS_NOTSUP) {
1630219a2a31Shl157128 			(void) fprintf(stderr,
1631219a2a31Shl157128 			    gettext("%s: add operation failed: %s\n"),
1632219a2a31Shl157128 			    progname,
1633d62bc4baSyz147064 			    gettext("link capabilities don't match"));
16344ac67f02SAnurag S. Maskey 			dladm_close(handle);
1635219a2a31Shl157128 			exit(ENOTSUP);
1636d62bc4baSyz147064 		} else if (status == DLADM_STATUS_NONOTIF) {
1637d62bc4baSyz147064 			die_dlerr(status, "not all links have link up/down "
1638d62bc4baSyz147064 			    "detection; must use -f (see dladm(1M))\n");
1639d62bc4baSyz147064 		} else {
1640f595a68aSyz147064 			die_dlerr(status, "add operation failed");
16417c478bd9Sstevel@tonic-gate 		}
16427c478bd9Sstevel@tonic-gate 	}
1643d62bc4baSyz147064 }
16447c478bd9Sstevel@tonic-gate 
16457c478bd9Sstevel@tonic-gate static void
16468d5c46e6Sam223141 do_remove_aggr(int argc, char *argv[], const char *use)
16477c478bd9Sstevel@tonic-gate {
1648b509e89bSRishi Srivatsavai 	int				option;
1649f595a68aSyz147064 	dladm_aggr_port_attr_db_t	port[MAXPORT];
1650d62bc4baSyz147064 	uint_t				n, ndev, nlink;
1651d62bc4baSyz147064 	char				*devs[MAXPORT];
1652d62bc4baSyz147064 	char				*links[MAXPORT];
16537c478bd9Sstevel@tonic-gate 	char				*altroot = NULL;
1654d62bc4baSyz147064 	uint32_t			flags;
1655d62bc4baSyz147064 	datalink_id_t			linkid;
1656f595a68aSyz147064 	dladm_status_t			status;
16577c478bd9Sstevel@tonic-gate 
1658d62bc4baSyz147064 	flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST;
1659d62bc4baSyz147064 	ndev = nlink = opterr = 0;
1660d62bc4baSyz147064 	while ((option = getopt_long(argc, argv, ":d:l:R:t",
1661d62bc4baSyz147064 	    lopts, NULL)) != -1) {
16627c478bd9Sstevel@tonic-gate 		switch (option) {
16637c478bd9Sstevel@tonic-gate 		case 'd':
1664d62bc4baSyz147064 			if (ndev + nlink >= MAXPORT)
1665d62bc4baSyz147064 				die("too many ports specified");
16667c478bd9Sstevel@tonic-gate 
1667d62bc4baSyz147064 			devs[ndev++] = optarg;
1668d62bc4baSyz147064 			break;
1669d62bc4baSyz147064 		case 'l':
1670d62bc4baSyz147064 			if (ndev + nlink >= MAXPORT)
1671d62bc4baSyz147064 				die("too many ports specified");
167233343a97Smeem 
1673d62bc4baSyz147064 			links[nlink++] = optarg;
16747c478bd9Sstevel@tonic-gate 			break;
16757c478bd9Sstevel@tonic-gate 		case 't':
1676d62bc4baSyz147064 			flags &= ~DLADM_OPT_PERSIST;
16777c478bd9Sstevel@tonic-gate 			break;
16787c478bd9Sstevel@tonic-gate 		case 'R':
16797c478bd9Sstevel@tonic-gate 			altroot = optarg;
16807c478bd9Sstevel@tonic-gate 			break;
16817c478bd9Sstevel@tonic-gate 		default:
16828d5c46e6Sam223141 			die_opterr(optopt, option, use);
168333343a97Smeem 			break;
16847c478bd9Sstevel@tonic-gate 		}
16857c478bd9Sstevel@tonic-gate 	}
16867c478bd9Sstevel@tonic-gate 
1687d62bc4baSyz147064 	if (ndev + nlink == 0)
16887c478bd9Sstevel@tonic-gate 		usage();
16897c478bd9Sstevel@tonic-gate 
1690d62bc4baSyz147064 	/* get key value or the aggregation name (required last argument) */
16917c478bd9Sstevel@tonic-gate 	if (optind != (argc-1))
16927c478bd9Sstevel@tonic-gate 		usage();
16937c478bd9Sstevel@tonic-gate 
1694d62bc4baSyz147064 	status = i_dladm_aggr_get_linkid(altroot, argv[optind], &linkid, flags);
1695d62bc4baSyz147064 	if (status != DLADM_STATUS_OK)
1696d62bc4baSyz147064 		goto done;
16977c478bd9Sstevel@tonic-gate 
1698d62bc4baSyz147064 	if (altroot != NULL)
1699d62bc4baSyz147064 		altroot_cmd(altroot, argc, argv);
1700d62bc4baSyz147064 
1701d62bc4baSyz147064 	for (n = 0; n < ndev; n++) {
17024ac67f02SAnurag S. Maskey 		if ((status = dladm_dev2linkid(handle, devs[n],
17034ac67f02SAnurag S. Maskey 		    &(port[n].lp_linkid))) != DLADM_STATUS_OK) {
17044ac67f02SAnurag S. Maskey 			die_dlerr(status, "invalid <dev> '%s'", devs[n]);
1705d62bc4baSyz147064 		}
1706d62bc4baSyz147064 	}
1707d62bc4baSyz147064 
1708d62bc4baSyz147064 	for (n = 0; n < nlink; n++) {
17094ac67f02SAnurag S. Maskey 		if ((status = dladm_name2info(handle, links[n],
17104ac67f02SAnurag S. Maskey 		    &port[n + ndev].lp_linkid, NULL, NULL, NULL)) !=
17114ac67f02SAnurag S. Maskey 		    DLADM_STATUS_OK) {
17124ac67f02SAnurag S. Maskey 			die_dlerr(status, "invalid <link> '%s'", links[n]);
1713d62bc4baSyz147064 		}
1714d62bc4baSyz147064 	}
1715d62bc4baSyz147064 
17164ac67f02SAnurag S. Maskey 	status = dladm_aggr_remove(handle, linkid, ndev + nlink, port, flags);
1717d62bc4baSyz147064 done:
1718f595a68aSyz147064 	if (status != DLADM_STATUS_OK)
1719f595a68aSyz147064 		die_dlerr(status, "remove operation failed");
17207c478bd9Sstevel@tonic-gate }
17217c478bd9Sstevel@tonic-gate 
17227c478bd9Sstevel@tonic-gate static void
17238d5c46e6Sam223141 do_modify_aggr(int argc, char *argv[], const char *use)
17247c478bd9Sstevel@tonic-gate {
1725b509e89bSRishi Srivatsavai 	int			option;
17267c478bd9Sstevel@tonic-gate 	uint32_t		policy = AGGR_POLICY_L4;
17277c478bd9Sstevel@tonic-gate 	aggr_lacp_mode_t	lacp_mode = AGGR_LACP_OFF;
17287c478bd9Sstevel@tonic-gate 	aggr_lacp_timer_t	lacp_timer = AGGR_LACP_TIMER_SHORT;
17297c478bd9Sstevel@tonic-gate 	uint8_t			mac_addr[ETHERADDRL];
17307c478bd9Sstevel@tonic-gate 	boolean_t		mac_addr_fixed = B_FALSE;
17317c478bd9Sstevel@tonic-gate 	uint8_t			modify_mask = 0;
17327c478bd9Sstevel@tonic-gate 	char			*altroot = NULL;
1733d62bc4baSyz147064 	uint32_t		flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST;
1734d62bc4baSyz147064 	datalink_id_t		linkid;
1735f595a68aSyz147064 	dladm_status_t		status;
17367c478bd9Sstevel@tonic-gate 
17377c478bd9Sstevel@tonic-gate 	opterr = 0;
1738d62bc4baSyz147064 	while ((option = getopt_long(argc, argv, ":L:l:P:R:tu:T:", lopts,
17397c478bd9Sstevel@tonic-gate 	    NULL)) != -1) {
17407c478bd9Sstevel@tonic-gate 		switch (option) {
17417c478bd9Sstevel@tonic-gate 		case 'P':
1742f595a68aSyz147064 			if (modify_mask & DLADM_AGGR_MODIFY_POLICY)
174333343a97Smeem 				die_optdup(option);
17447c478bd9Sstevel@tonic-gate 
1745f595a68aSyz147064 			modify_mask |= DLADM_AGGR_MODIFY_POLICY;
17467c478bd9Sstevel@tonic-gate 
1747f595a68aSyz147064 			if (!dladm_aggr_str2policy(optarg, &policy))
174833343a97Smeem 				die("invalid policy '%s'", optarg);
17497c478bd9Sstevel@tonic-gate 			break;
17507c478bd9Sstevel@tonic-gate 		case 'u':
1751f595a68aSyz147064 			if (modify_mask & DLADM_AGGR_MODIFY_MAC)
175233343a97Smeem 				die_optdup(option);
17537c478bd9Sstevel@tonic-gate 
1754f595a68aSyz147064 			modify_mask |= DLADM_AGGR_MODIFY_MAC;
17557c478bd9Sstevel@tonic-gate 
1756f595a68aSyz147064 			if (!dladm_aggr_str2macaddr(optarg, &mac_addr_fixed,
175733343a97Smeem 			    mac_addr))
175833343a97Smeem 				die("invalid MAC address '%s'", optarg);
17597c478bd9Sstevel@tonic-gate 			break;
17607c478bd9Sstevel@tonic-gate 		case 'l':
1761d62bc4baSyz147064 		case 'L':
1762f595a68aSyz147064 			if (modify_mask & DLADM_AGGR_MODIFY_LACP_MODE)
176333343a97Smeem 				die_optdup(option);
17647c478bd9Sstevel@tonic-gate 
1765f595a68aSyz147064 			modify_mask |= DLADM_AGGR_MODIFY_LACP_MODE;
17667c478bd9Sstevel@tonic-gate 
1767f595a68aSyz147064 			if (!dladm_aggr_str2lacpmode(optarg, &lacp_mode))
176833343a97Smeem 				die("invalid LACP mode '%s'", optarg);
17697c478bd9Sstevel@tonic-gate 			break;
17707c478bd9Sstevel@tonic-gate 		case 'T':
1771f595a68aSyz147064 			if (modify_mask & DLADM_AGGR_MODIFY_LACP_TIMER)
177233343a97Smeem 				die_optdup(option);
17737c478bd9Sstevel@tonic-gate 
1774f595a68aSyz147064 			modify_mask |= DLADM_AGGR_MODIFY_LACP_TIMER;
17757c478bd9Sstevel@tonic-gate 
1776f595a68aSyz147064 			if (!dladm_aggr_str2lacptimer(optarg, &lacp_timer))
177733343a97Smeem 				die("invalid LACP timer value '%s'", optarg);
17787c478bd9Sstevel@tonic-gate 			break;
17797c478bd9Sstevel@tonic-gate 		case 't':
1780d62bc4baSyz147064 			flags &= ~DLADM_OPT_PERSIST;
17817c478bd9Sstevel@tonic-gate 			break;
17827c478bd9Sstevel@tonic-gate 		case 'R':
17837c478bd9Sstevel@tonic-gate 			altroot = optarg;
17847c478bd9Sstevel@tonic-gate 			break;
17857c478bd9Sstevel@tonic-gate 		default:
17868d5c46e6Sam223141 			die_opterr(optopt, option, use);
178733343a97Smeem 			break;
17887c478bd9Sstevel@tonic-gate 		}
17897c478bd9Sstevel@tonic-gate 	}
17907c478bd9Sstevel@tonic-gate 
179133343a97Smeem 	if (modify_mask == 0)
179233343a97Smeem 		die("at least one of the -PulT options must be specified");
17937c478bd9Sstevel@tonic-gate 
1794d62bc4baSyz147064 	/* get key value or the aggregation name (required last argument) */
17957c478bd9Sstevel@tonic-gate 	if (optind != (argc-1))
17967c478bd9Sstevel@tonic-gate 		usage();
17977c478bd9Sstevel@tonic-gate 
1798d62bc4baSyz147064 	status = i_dladm_aggr_get_linkid(altroot, argv[optind], &linkid, flags);
1799d62bc4baSyz147064 	if (status != DLADM_STATUS_OK)
1800d62bc4baSyz147064 		goto done;
18017c478bd9Sstevel@tonic-gate 
1802d62bc4baSyz147064 	if (altroot != NULL)
1803d62bc4baSyz147064 		altroot_cmd(altroot, argc, argv);
1804d62bc4baSyz147064 
18054ac67f02SAnurag S. Maskey 	status = dladm_aggr_modify(handle, linkid, modify_mask, policy,
18064ac67f02SAnurag S. Maskey 	    mac_addr_fixed, (const uchar_t *)mac_addr, lacp_mode, lacp_timer,
18074ac67f02SAnurag S. Maskey 	    flags);
1808d62bc4baSyz147064 
1809d62bc4baSyz147064 done:
1810f595a68aSyz147064 	if (status != DLADM_STATUS_OK)
1811f595a68aSyz147064 		die_dlerr(status, "modify operation failed");
18127c478bd9Sstevel@tonic-gate }
18137c478bd9Sstevel@tonic-gate 
18148d5c46e6Sam223141 /*ARGSUSED*/
18157c478bd9Sstevel@tonic-gate static void
18168d5c46e6Sam223141 do_up_aggr(int argc, char *argv[], const char *use)
18177c478bd9Sstevel@tonic-gate {
1818d62bc4baSyz147064 	datalink_id_t	linkid = DATALINK_ALL_LINKID;
1819f595a68aSyz147064 	dladm_status_t	status;
18207c478bd9Sstevel@tonic-gate 
1821d62bc4baSyz147064 	/*
1822d62bc4baSyz147064 	 * get the key or the name of the aggregation (optional last argument)
1823d62bc4baSyz147064 	 */
18247c478bd9Sstevel@tonic-gate 	if (argc == 2) {
1825d62bc4baSyz147064 		if ((status = i_dladm_aggr_get_linkid(NULL, argv[1], &linkid,
18264ac67f02SAnurag S. Maskey 		    DLADM_OPT_PERSIST)) != DLADM_STATUS_OK)
1827d62bc4baSyz147064 			goto done;
18287c478bd9Sstevel@tonic-gate 	} else if (argc > 2) {
18297c478bd9Sstevel@tonic-gate 		usage();
18307c478bd9Sstevel@tonic-gate 	}
18317c478bd9Sstevel@tonic-gate 
18324ac67f02SAnurag S. Maskey 	status = dladm_aggr_up(handle, linkid);
1833d62bc4baSyz147064 done:
1834d62bc4baSyz147064 	if (status != DLADM_STATUS_OK) {
1835d62bc4baSyz147064 		if (argc == 2) {
1836d62bc4baSyz147064 			die_dlerr(status,
1837d62bc4baSyz147064 			    "could not bring up aggregation '%s'", argv[1]);
18387c478bd9Sstevel@tonic-gate 		} else {
1839f595a68aSyz147064 			die_dlerr(status, "could not bring aggregations up");
18407c478bd9Sstevel@tonic-gate 		}
18417c478bd9Sstevel@tonic-gate 	}
18427c478bd9Sstevel@tonic-gate }
18437c478bd9Sstevel@tonic-gate 
18447c478bd9Sstevel@tonic-gate static void
18458d5c46e6Sam223141 do_create_vlan(int argc, char *argv[], const char *use)
18467c478bd9Sstevel@tonic-gate {
1847d62bc4baSyz147064 	char			*link = NULL;
1848d62bc4baSyz147064 	char			drv[DLPI_LINKNAME_MAX];
1849d62bc4baSyz147064 	uint_t			ppa;
1850d62bc4baSyz147064 	datalink_id_t		linkid;
1851da14cebeSEric Cheng 	datalink_id_t		dev_linkid;
1852d62bc4baSyz147064 	int			vid = 0;
1853b509e89bSRishi Srivatsavai 	int			option;
1854d62bc4baSyz147064 	uint32_t		flags = (DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST);
1855d62bc4baSyz147064 	char			*altroot = NULL;
1856d62bc4baSyz147064 	char			vlan[MAXLINKNAMELEN];
185763a6526dSMichael Lim 	char			propstr[DLADM_STRSIZE];
1858da14cebeSEric Cheng 	dladm_arg_list_t	*proplist = NULL;
1859f595a68aSyz147064 	dladm_status_t		status;
18607c478bd9Sstevel@tonic-gate 
1861d62bc4baSyz147064 	opterr = 0;
186263a6526dSMichael Lim 	bzero(propstr, DLADM_STRSIZE);
186363a6526dSMichael Lim 
1864da14cebeSEric Cheng 	while ((option = getopt_long(argc, argv, ":tfR:l:v:p:",
1865d62bc4baSyz147064 	    lopts, NULL)) != -1) {
1866d62bc4baSyz147064 		switch (option) {
1867d62bc4baSyz147064 		case 'v':
1868d62bc4baSyz147064 			if (vid != 0)
1869d62bc4baSyz147064 				die_optdup(option);
1870d62bc4baSyz147064 
1871d62bc4baSyz147064 			if (!str2int(optarg, &vid) || vid < 1 || vid > 4094)
1872d62bc4baSyz147064 				die("invalid VLAN identifier '%s'", optarg);
1873d62bc4baSyz147064 
1874d62bc4baSyz147064 			break;
1875d62bc4baSyz147064 		case 'l':
1876d62bc4baSyz147064 			if (link != NULL)
1877d62bc4baSyz147064 				die_optdup(option);
1878d62bc4baSyz147064 
1879d62bc4baSyz147064 			link = optarg;
1880d62bc4baSyz147064 			break;
1881d62bc4baSyz147064 		case 't':
1882d62bc4baSyz147064 			flags &= ~DLADM_OPT_PERSIST;
1883d62bc4baSyz147064 			break;
1884d62bc4baSyz147064 		case 'R':
1885d62bc4baSyz147064 			altroot = optarg;
1886d62bc4baSyz147064 			break;
1887da14cebeSEric Cheng 		case 'p':
188863a6526dSMichael Lim 			(void) strlcat(propstr, optarg, DLADM_STRSIZE);
188963a6526dSMichael Lim 			if (strlcat(propstr, ",", DLADM_STRSIZE) >=
189063a6526dSMichael Lim 			    DLADM_STRSIZE)
189163a6526dSMichael Lim 				die("property list too long '%s'", propstr);
1892da14cebeSEric Cheng 			break;
1893da14cebeSEric Cheng 		case 'f':
1894da14cebeSEric Cheng 			flags |= DLADM_OPT_FORCE;
1895da14cebeSEric Cheng 			break;
1896d62bc4baSyz147064 		default:
18978d5c46e6Sam223141 			die_opterr(optopt, option, use);
1898d62bc4baSyz147064 			break;
1899d62bc4baSyz147064 		}
1900d62bc4baSyz147064 	}
1901d62bc4baSyz147064 
1902d62bc4baSyz147064 	/* get vlan name if there is any */
1903d62bc4baSyz147064 	if ((vid == 0) || (link == NULL) || (argc - optind > 1))
19047c478bd9Sstevel@tonic-gate 		usage();
1905d62bc4baSyz147064 
1906d62bc4baSyz147064 	if (optind == (argc - 1)) {
1907d62bc4baSyz147064 		if (strlcpy(vlan, argv[optind], MAXLINKNAMELEN) >=
1908d62bc4baSyz147064 		    MAXLINKNAMELEN) {
1909d62bc4baSyz147064 			die("vlan name too long '%s'", argv[optind]);
1910d62bc4baSyz147064 		}
1911d62bc4baSyz147064 	} else {
1912d62bc4baSyz147064 		if ((dlpi_parselink(link, drv, &ppa) != DLPI_SUCCESS) ||
1913d62bc4baSyz147064 		    (ppa >= 1000) ||
1914d62bc4baSyz147064 		    (dlpi_makelink(vlan, drv, vid * 1000 + ppa) !=
1915d62bc4baSyz147064 		    DLPI_SUCCESS)) {
1916d62bc4baSyz147064 			die("invalid link name '%s'", link);
1917d62bc4baSyz147064 		}
19187c478bd9Sstevel@tonic-gate 	}
19197c478bd9Sstevel@tonic-gate 
1920d62bc4baSyz147064 	if (altroot != NULL)
1921d62bc4baSyz147064 		altroot_cmd(altroot, argc, argv);
1922d62bc4baSyz147064 
19234ac67f02SAnurag S. Maskey 	if (dladm_name2info(handle, link, &dev_linkid, NULL, NULL, NULL) !=
1924d62bc4baSyz147064 	    DLADM_STATUS_OK) {
1925d62bc4baSyz147064 		die("invalid link name '%s'", link);
1926d62bc4baSyz147064 	}
1927d62bc4baSyz147064 
192863a6526dSMichael Lim 	if (dladm_parse_link_props(propstr, &proplist, B_FALSE)
192963a6526dSMichael Lim 	    != DLADM_STATUS_OK)
193063a6526dSMichael Lim 		die("invalid vlan property");
193163a6526dSMichael Lim 
19324ac67f02SAnurag S. Maskey 	if ((status = dladm_vlan_create(handle, vlan, dev_linkid, vid, proplist,
19334ac67f02SAnurag S. Maskey 	    flags, &linkid)) != DLADM_STATUS_OK) {
1934da14cebeSEric Cheng 		die_dlerr(status, "create operation over %s failed", link);
1935d62bc4baSyz147064 	}
1936d62bc4baSyz147064 }
1937d62bc4baSyz147064 
1938d62bc4baSyz147064 static void
19398d5c46e6Sam223141 do_delete_vlan(int argc, char *argv[], const char *use)
1940d62bc4baSyz147064 {
1941b509e89bSRishi Srivatsavai 	int		option;
1942d62bc4baSyz147064 	uint32_t	flags = (DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST);
1943d62bc4baSyz147064 	char		*altroot = NULL;
1944d62bc4baSyz147064 	datalink_id_t	linkid;
1945d62bc4baSyz147064 	dladm_status_t	status;
1946d62bc4baSyz147064 
1947d62bc4baSyz147064 	opterr = 0;
1948d62bc4baSyz147064 	while ((option = getopt_long(argc, argv, ":R:t", lopts, NULL)) != -1) {
1949d62bc4baSyz147064 		switch (option) {
1950d62bc4baSyz147064 		case 't':
1951d62bc4baSyz147064 			flags &= ~DLADM_OPT_PERSIST;
1952d62bc4baSyz147064 			break;
1953d62bc4baSyz147064 		case 'R':
1954d62bc4baSyz147064 			altroot = optarg;
1955d62bc4baSyz147064 			break;
1956d62bc4baSyz147064 		default:
19578d5c46e6Sam223141 			die_opterr(optopt, option, use);
1958d62bc4baSyz147064 			break;
1959d62bc4baSyz147064 		}
1960d62bc4baSyz147064 	}
1961d62bc4baSyz147064 
1962d62bc4baSyz147064 	/* get VLAN link name (required last argument) */
1963d62bc4baSyz147064 	if (optind != (argc - 1))
1964d62bc4baSyz147064 		usage();
1965d62bc4baSyz147064 
1966d62bc4baSyz147064 	if (altroot != NULL)
1967d62bc4baSyz147064 		altroot_cmd(altroot, argc, argv);
1968d62bc4baSyz147064 
19694ac67f02SAnurag S. Maskey 	status = dladm_name2info(handle, argv[optind], &linkid, NULL, NULL,
19704ac67f02SAnurag S. Maskey 	    NULL);
1971d62bc4baSyz147064 	if (status != DLADM_STATUS_OK)
1972d62bc4baSyz147064 		goto done;
1973d62bc4baSyz147064 
19744ac67f02SAnurag S. Maskey 	status = dladm_vlan_delete(handle, linkid, flags);
1975d62bc4baSyz147064 done:
1976d62bc4baSyz147064 	if (status != DLADM_STATUS_OK)
1977d62bc4baSyz147064 		die_dlerr(status, "delete operation failed");
1978d62bc4baSyz147064 }
1979d62bc4baSyz147064 
19808d5c46e6Sam223141 /*ARGSUSED*/
1981d62bc4baSyz147064 static void
19828d5c46e6Sam223141 do_up_vlan(int argc, char *argv[], const char *use)
1983d62bc4baSyz147064 {
1984da14cebeSEric Cheng 	do_up_vnic_common(argc, argv, use, B_TRUE);
19857c478bd9Sstevel@tonic-gate }
19867c478bd9Sstevel@tonic-gate 
1987210db224Sericheng static void
19888d5c46e6Sam223141 do_rename_link(int argc, char *argv[], const char *use)
1989210db224Sericheng {
1990b509e89bSRishi Srivatsavai 	int		option;
1991d62bc4baSyz147064 	char		*link1, *link2;
1992d62bc4baSyz147064 	char		*altroot = NULL;
1993d62bc4baSyz147064 	dladm_status_t	status;
1994210db224Sericheng 
1995d62bc4baSyz147064 	opterr = 0;
1996d62bc4baSyz147064 	while ((option = getopt_long(argc, argv, ":R:", lopts, NULL)) != -1) {
1997d62bc4baSyz147064 		switch (option) {
1998d62bc4baSyz147064 		case 'R':
1999d62bc4baSyz147064 			altroot = optarg;
2000d62bc4baSyz147064 			break;
2001d62bc4baSyz147064 		default:
20028d5c46e6Sam223141 			die_opterr(optopt, option, use);
2003d62bc4baSyz147064 			break;
2004210db224Sericheng 		}
2005210db224Sericheng 	}
2006210db224Sericheng 
2007d62bc4baSyz147064 	/* get link1 and link2 name (required the last 2 arguments) */
2008d62bc4baSyz147064 	if (optind != (argc - 2))
2009d62bc4baSyz147064 		usage();
2010d62bc4baSyz147064 
2011d62bc4baSyz147064 	if (altroot != NULL)
2012d62bc4baSyz147064 		altroot_cmd(altroot, argc, argv);
2013d62bc4baSyz147064 
2014d62bc4baSyz147064 	link1 = argv[optind++];
2015d62bc4baSyz147064 	link2 = argv[optind];
20164ac67f02SAnurag S. Maskey 	if ((status = dladm_rename_link(handle, link1, link2)) !=
20174ac67f02SAnurag S. Maskey 	    DLADM_STATUS_OK)
2018d62bc4baSyz147064 		die_dlerr(status, "rename operation failed");
2019d62bc4baSyz147064 }
2020d62bc4baSyz147064 
20218d5c46e6Sam223141 /*ARGSUSED*/
2022d62bc4baSyz147064 static void
20238d5c46e6Sam223141 do_delete_phys(int argc, char *argv[], const char *use)
2024d62bc4baSyz147064 {
2025d62bc4baSyz147064 	datalink_id_t	linkid = DATALINK_ALL_LINKID;
2026d62bc4baSyz147064 	dladm_status_t	status;
2027d62bc4baSyz147064 
2028d62bc4baSyz147064 	/* get link name (required the last argument) */
2029d62bc4baSyz147064 	if (argc > 2)
2030d62bc4baSyz147064 		usage();
2031d62bc4baSyz147064 
2032d62bc4baSyz147064 	if (argc == 2) {
20334ac67f02SAnurag S. Maskey 		if ((status = dladm_name2info(handle, argv[1], &linkid, NULL,
20344ac67f02SAnurag S. Maskey 		    NULL, NULL)) != DLADM_STATUS_OK)
2035d62bc4baSyz147064 			die_dlerr(status, "cannot delete '%s'", argv[1]);
2036d62bc4baSyz147064 	}
2037d62bc4baSyz147064 
20384ac67f02SAnurag S. Maskey 	if ((status = dladm_phys_delete(handle, linkid)) != DLADM_STATUS_OK) {
2039d62bc4baSyz147064 		if (argc == 2)
2040d62bc4baSyz147064 			die_dlerr(status, "cannot delete '%s'", argv[1]);
2041d62bc4baSyz147064 		else
2042d62bc4baSyz147064 			die_dlerr(status, "delete operation failed");
2043d62bc4baSyz147064 	}
2044d62bc4baSyz147064 }
2045d62bc4baSyz147064 
2046d62bc4baSyz147064 /*ARGSUSED*/
2047210db224Sericheng static int
20484ac67f02SAnurag S. Maskey i_dladm_walk_linkmap(dladm_handle_t dh, datalink_id_t linkid, void *arg)
2049210db224Sericheng {
2050d62bc4baSyz147064 	char			name[MAXLINKNAMELEN];
2051d62bc4baSyz147064 	char			mediabuf[DLADM_STRSIZE];
2052d62bc4baSyz147064 	char			classbuf[DLADM_STRSIZE];
2053d62bc4baSyz147064 	datalink_class_t	class;
2054d62bc4baSyz147064 	uint32_t		media;
2055d62bc4baSyz147064 	uint32_t		flags;
2056210db224Sericheng 
20574ac67f02SAnurag S. Maskey 	if (dladm_datalink_id2info(dh, linkid, &flags, &class, &media, name,
2058d62bc4baSyz147064 	    MAXLINKNAMELEN) == DLADM_STATUS_OK) {
2059d62bc4baSyz147064 		(void) dladm_class2str(class, classbuf);
2060d62bc4baSyz147064 		(void) dladm_media2str(media, mediabuf);
2061d62bc4baSyz147064 		(void) printf("%-12s%8d  %-12s%-20s %6d\n", name,
2062d62bc4baSyz147064 		    linkid, classbuf, mediabuf, flags);
2063210db224Sericheng 	}
2064d62bc4baSyz147064 	return (DLADM_WALK_CONTINUE);
2065210db224Sericheng }
20667c478bd9Sstevel@tonic-gate 
20677c478bd9Sstevel@tonic-gate /*ARGSUSED*/
20687c478bd9Sstevel@tonic-gate static void
20698d5c46e6Sam223141 do_show_linkmap(int argc, char *argv[], const char *use)
20707c478bd9Sstevel@tonic-gate {
2071d62bc4baSyz147064 	if (argc != 1)
2072d62bc4baSyz147064 		die("invalid arguments");
20737c478bd9Sstevel@tonic-gate 
2074d62bc4baSyz147064 	(void) printf("%-12s%8s  %-12s%-20s %6s\n", "NAME", "LINKID",
2075d62bc4baSyz147064 	    "CLASS", "MEDIA", "FLAGS");
20764ac67f02SAnurag S. Maskey 
20774ac67f02SAnurag S. Maskey 	(void) dladm_walk_datalink_id(i_dladm_walk_linkmap, handle, NULL,
2078d62bc4baSyz147064 	    DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE,
2079d62bc4baSyz147064 	    DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST);
20807c478bd9Sstevel@tonic-gate }
2081d62bc4baSyz147064 
2082d62bc4baSyz147064 /*
2083d62bc4baSyz147064  * Delete inactive physical links.
2084d62bc4baSyz147064  */
2085d62bc4baSyz147064 /*ARGSUSED*/
2086d62bc4baSyz147064 static int
20874ac67f02SAnurag S. Maskey purge_phys(dladm_handle_t dh, datalink_id_t linkid, void *arg)
2088d62bc4baSyz147064 {
2089d62bc4baSyz147064 	datalink_class_t	class;
2090d62bc4baSyz147064 	uint32_t		flags;
2091d62bc4baSyz147064 
20924ac67f02SAnurag S. Maskey 	if (dladm_datalink_id2info(dh, linkid, &flags, &class, NULL, NULL, 0)
20934ac67f02SAnurag S. Maskey 	    != DLADM_STATUS_OK) {
2094d62bc4baSyz147064 		return (DLADM_WALK_CONTINUE);
2095d62bc4baSyz147064 	}
2096d62bc4baSyz147064 
2097d62bc4baSyz147064 	if (class == DATALINK_CLASS_PHYS && !(flags & DLADM_OPT_ACTIVE))
20984ac67f02SAnurag S. Maskey 		(void) dladm_phys_delete(dh, linkid);
2099d62bc4baSyz147064 
2100d62bc4baSyz147064 	return (DLADM_WALK_CONTINUE);
2101d62bc4baSyz147064 }
2102d62bc4baSyz147064 
2103d62bc4baSyz147064 /*ARGSUSED*/
2104d62bc4baSyz147064 static void
21058d5c46e6Sam223141 do_init_phys(int argc, char *argv[], const char *use)
2106d62bc4baSyz147064 {
2107d62bc4baSyz147064 	di_node_t	devtree;
2108d62bc4baSyz147064 
2109d62bc4baSyz147064 	if (argc > 1)
2110d62bc4baSyz147064 		usage();
2111d62bc4baSyz147064 
2112d62bc4baSyz147064 	/*
2113d62bc4baSyz147064 	 * Force all the devices to attach, therefore all the network physical
2114d62bc4baSyz147064 	 * devices can be known to the dlmgmtd daemon.
2115d62bc4baSyz147064 	 */
2116d62bc4baSyz147064 	if ((devtree = di_init("/", DINFOFORCE | DINFOSUBTREE)) != DI_NODE_NIL)
2117d62bc4baSyz147064 		di_fini(devtree);
2118d62bc4baSyz147064 
21194ac67f02SAnurag S. Maskey 	(void) dladm_walk_datalink_id(purge_phys, handle, NULL,
2120d62bc4baSyz147064 	    DATALINK_CLASS_PHYS, DATALINK_ANY_MEDIATYPE, DLADM_OPT_PERSIST);
21217c478bd9Sstevel@tonic-gate }
21227c478bd9Sstevel@tonic-gate 
2123d62bc4baSyz147064 
2124d62bc4baSyz147064 /*
2125d62bc4baSyz147064  * Print the active topology information.
2126d62bc4baSyz147064  */
2127d62bc4baSyz147064 static dladm_status_t
2128d62bc4baSyz147064 print_link_topology(show_state_t *state, datalink_id_t linkid,
2129e7801d59Ssowmini     datalink_class_t class, link_fields_buf_t *lbuf)
2130d62bc4baSyz147064 {
2131d62bc4baSyz147064 	uint32_t	flags = state->ls_flags;
2132d62bc4baSyz147064 	dladm_status_t	status = DLADM_STATUS_OK;
21336b9e797cSsowmini 	char		tmpbuf[MAXLINKNAMELEN];
2134d62bc4baSyz147064 
2135b509e89bSRishi Srivatsavai 	lbuf->link_over[0] = '\0';
2136b509e89bSRishi Srivatsavai 
2137b509e89bSRishi Srivatsavai 	switch (class) {
2138b509e89bSRishi Srivatsavai 	case DATALINK_CLASS_VLAN: {
2139d62bc4baSyz147064 		dladm_vlan_attr_t	vinfo;
2140d62bc4baSyz147064 
21414ac67f02SAnurag S. Maskey 		status = dladm_vlan_info(handle, linkid, &vinfo, flags);
2142d62bc4baSyz147064 		if (status != DLADM_STATUS_OK)
2143b509e89bSRishi Srivatsavai 			break;
21444ac67f02SAnurag S. Maskey 		status = dladm_datalink_id2info(handle, vinfo.dv_linkid, NULL,
21454ac67f02SAnurag S. Maskey 		    NULL, NULL, lbuf->link_over, sizeof (lbuf->link_over));
2146b509e89bSRishi Srivatsavai 		break;
2147b509e89bSRishi Srivatsavai 	}
2148b509e89bSRishi Srivatsavai 
2149b509e89bSRishi Srivatsavai 	case DATALINK_CLASS_AGGR: {
2150d62bc4baSyz147064 		dladm_aggr_grp_attr_t	ginfo;
2151d62bc4baSyz147064 		int			i;
2152d62bc4baSyz147064 
21534ac67f02SAnurag S. Maskey 		status = dladm_aggr_info(handle, linkid, &ginfo, flags);
2154d62bc4baSyz147064 		if (status != DLADM_STATUS_OK)
2155b509e89bSRishi Srivatsavai 			break;
2156d62bc4baSyz147064 
2157d62bc4baSyz147064 		if (ginfo.lg_nports == 0) {
2158d62bc4baSyz147064 			status = DLADM_STATUS_BADVAL;
2159b509e89bSRishi Srivatsavai 			break;
2160d62bc4baSyz147064 		}
2161d62bc4baSyz147064 		for (i = 0; i < ginfo.lg_nports; i++) {
21624ac67f02SAnurag S. Maskey 			status = dladm_datalink_id2info(handle,
2163e7801d59Ssowmini 			    ginfo.lg_ports[i].lp_linkid, NULL, NULL, NULL,
21646b9e797cSsowmini 			    tmpbuf, sizeof (tmpbuf));
2165d62bc4baSyz147064 			if (status != DLADM_STATUS_OK) {
2166d62bc4baSyz147064 				free(ginfo.lg_ports);
2167b509e89bSRishi Srivatsavai 				break;
2168d62bc4baSyz147064 			}
21696b9e797cSsowmini 			(void) strlcat(lbuf->link_over, tmpbuf,
21706b9e797cSsowmini 			    sizeof (lbuf->link_over));
21716b9e797cSsowmini 			if (i != (ginfo.lg_nports - 1)) {
21726b9e797cSsowmini 				(void) strlcat(lbuf->link_over, " ",
21736b9e797cSsowmini 				    sizeof (lbuf->link_over));
21746b9e797cSsowmini 			}
2175d62bc4baSyz147064 		}
2176d62bc4baSyz147064 		free(ginfo.lg_ports);
2177b509e89bSRishi Srivatsavai 		break;
2178b509e89bSRishi Srivatsavai 	}
2179b509e89bSRishi Srivatsavai 
2180b509e89bSRishi Srivatsavai 	case DATALINK_CLASS_VNIC: {
2181da14cebeSEric Cheng 		dladm_vnic_attr_t	vinfo;
2182d62bc4baSyz147064 
2183b509e89bSRishi Srivatsavai 		status = dladm_vnic_info(handle, linkid, &vinfo, flags);
2184b509e89bSRishi Srivatsavai 		if (status == DLADM_STATUS_OK)
2185b509e89bSRishi Srivatsavai 			status = dladm_datalink_id2info(handle,
2186b509e89bSRishi Srivatsavai 			    vinfo.va_link_id, NULL, NULL, NULL, lbuf->link_over,
2187b509e89bSRishi Srivatsavai 			    sizeof (lbuf->link_over));
2188b509e89bSRishi Srivatsavai 		break;
2189b509e89bSRishi Srivatsavai 	}
2190b509e89bSRishi Srivatsavai 
2191b509e89bSRishi Srivatsavai 	case DATALINK_CLASS_SIMNET: {
2192b509e89bSRishi Srivatsavai 		dladm_simnet_attr_t	slinfo;
2193b509e89bSRishi Srivatsavai 
2194b509e89bSRishi Srivatsavai 		status = dladm_simnet_info(handle, linkid, &slinfo, flags);
2195b509e89bSRishi Srivatsavai 		if (status == DLADM_STATUS_OK &&
2196b509e89bSRishi Srivatsavai 		    slinfo.sna_peer_link_id != DATALINK_INVALID_LINKID)
2197b509e89bSRishi Srivatsavai 			status = dladm_datalink_id2info(handle,
2198b509e89bSRishi Srivatsavai 			    slinfo.sna_peer_link_id, NULL, NULL, NULL,
2199b509e89bSRishi Srivatsavai 			    lbuf->link_over, sizeof (lbuf->link_over));
2200b509e89bSRishi Srivatsavai 		break;
2201d62bc4baSyz147064 	}
2202d62bc4baSyz147064 	}
2203b509e89bSRishi Srivatsavai 
2204d62bc4baSyz147064 	return (status);
2205d62bc4baSyz147064 }
2206d62bc4baSyz147064 
2207d62bc4baSyz147064 static dladm_status_t
2208e7801d59Ssowmini print_link(show_state_t *state, datalink_id_t linkid, link_fields_buf_t *lbuf)
2209d62bc4baSyz147064 {
2210d62bc4baSyz147064 	char			link[MAXLINKNAMELEN];
2211d62bc4baSyz147064 	datalink_class_t	class;
2212d62bc4baSyz147064 	uint_t			mtu;
2213d62bc4baSyz147064 	uint32_t		flags;
2214d62bc4baSyz147064 	dladm_status_t		status;
2215d62bc4baSyz147064 
22164ac67f02SAnurag S. Maskey 	if ((status = dladm_datalink_id2info(handle, linkid, &flags, &class,
22174ac67f02SAnurag S. Maskey 	    NULL, link, sizeof (link))) != DLADM_STATUS_OK) {
2218d62bc4baSyz147064 		goto done;
2219d62bc4baSyz147064 	}
2220d62bc4baSyz147064 
2221d62bc4baSyz147064 	if (!(state->ls_flags & flags)) {
2222d62bc4baSyz147064 		status = DLADM_STATUS_NOTFOUND;
2223d62bc4baSyz147064 		goto done;
2224d62bc4baSyz147064 	}
2225d62bc4baSyz147064 
2226d62bc4baSyz147064 	if (state->ls_flags == DLADM_OPT_ACTIVE) {
2227d62bc4baSyz147064 		dladm_attr_t	dlattr;
2228d62bc4baSyz147064 
2229d62bc4baSyz147064 		if (class == DATALINK_CLASS_PHYS) {
2230d62bc4baSyz147064 			dladm_phys_attr_t	dpa;
2231d62bc4baSyz147064 			dlpi_handle_t		dh;
2232d62bc4baSyz147064 			dlpi_info_t		dlinfo;
2233d62bc4baSyz147064 
22344ac67f02SAnurag S. Maskey 			if ((status = dladm_phys_info(handle, linkid, &dpa,
2235d62bc4baSyz147064 			    DLADM_OPT_ACTIVE)) != DLADM_STATUS_OK) {
2236d62bc4baSyz147064 				goto done;
2237d62bc4baSyz147064 			}
2238d62bc4baSyz147064 
2239d62bc4baSyz147064 			if (!dpa.dp_novanity)
2240d62bc4baSyz147064 				goto link_mtu;
2241d62bc4baSyz147064 
2242d62bc4baSyz147064 			/*
2243d62bc4baSyz147064 			 * This is a physical link that does not have
2244d62bc4baSyz147064 			 * vanity naming support.
2245d62bc4baSyz147064 			 */
2246d62bc4baSyz147064 			if (dlpi_open(dpa.dp_dev, &dh, DLPI_DEVONLY) !=
2247d62bc4baSyz147064 			    DLPI_SUCCESS) {
2248d62bc4baSyz147064 				status = DLADM_STATUS_NOTFOUND;
2249d62bc4baSyz147064 				goto done;
2250d62bc4baSyz147064 			}
2251d62bc4baSyz147064 
2252d62bc4baSyz147064 			if (dlpi_info(dh, &dlinfo, 0) != DLPI_SUCCESS) {
2253d62bc4baSyz147064 				dlpi_close(dh);
2254d62bc4baSyz147064 				status = DLADM_STATUS_BADARG;
2255d62bc4baSyz147064 				goto done;
2256d62bc4baSyz147064 			}
2257d62bc4baSyz147064 
2258d62bc4baSyz147064 			dlpi_close(dh);
2259d62bc4baSyz147064 			mtu = dlinfo.di_max_sdu;
2260d62bc4baSyz147064 		} else {
2261d62bc4baSyz147064 link_mtu:
22624ac67f02SAnurag S. Maskey 			status = dladm_info(handle, linkid, &dlattr);
2263d62bc4baSyz147064 			if (status != DLADM_STATUS_OK)
2264d62bc4baSyz147064 				goto done;
2265d62bc4baSyz147064 			mtu = dlattr.da_max_sdu;
2266d62bc4baSyz147064 		}
2267d62bc4baSyz147064 	}
2268d62bc4baSyz147064 
2269e7801d59Ssowmini 	(void) snprintf(lbuf->link_name, sizeof (lbuf->link_name),
2270e7801d59Ssowmini 	    "%s", link);
2271e7801d59Ssowmini 	(void) dladm_class2str(class, lbuf->link_class);
2272d62bc4baSyz147064 	if (state->ls_flags == DLADM_OPT_ACTIVE) {
2273e7801d59Ssowmini 		(void) snprintf(lbuf->link_mtu, sizeof (lbuf->link_mtu),
2274c08e5e1aSdr146992 		    "%u", mtu);
2275e7801d59Ssowmini 		(void) get_linkstate(link, B_TRUE, lbuf->link_state);
2276d62bc4baSyz147064 	}
2277d62bc4baSyz147064 
2278e7801d59Ssowmini 	status = print_link_topology(state, linkid, class, lbuf);
2279d62bc4baSyz147064 	if (status != DLADM_STATUS_OK)
2280d62bc4baSyz147064 		goto done;
2281d62bc4baSyz147064 
2282d62bc4baSyz147064 done:
2283d62bc4baSyz147064 	return (status);
2284d62bc4baSyz147064 }
2285d62bc4baSyz147064 
22864ac67f02SAnurag S. Maskey /* ARGSUSED */
2287d62bc4baSyz147064 static int
22884ac67f02SAnurag S. Maskey show_link(dladm_handle_t dh, datalink_id_t linkid, void *arg)
2289d62bc4baSyz147064 {
2290e7801d59Ssowmini 	show_state_t		*state = (show_state_t *)arg;
2291d62bc4baSyz147064 	dladm_status_t		status;
2292e7801d59Ssowmini 	link_fields_buf_t	lbuf;
2293d62bc4baSyz147064 
2294e7801d59Ssowmini 	/*
2295e7801d59Ssowmini 	 * first get all the link attributes into lbuf;
2296e7801d59Ssowmini 	 */
22975f5c9f54SAnurag S. Maskey 	bzero(&lbuf, sizeof (link_fields_buf_t));
2298e7801d59Ssowmini 	status = print_link(state, linkid, &lbuf);
2299e7801d59Ssowmini 
2300d62bc4baSyz147064 	if (status != DLADM_STATUS_OK)
2301d62bc4baSyz147064 		goto done;
2302e7801d59Ssowmini 
23038002d411SSowmini Varadhan 	ofmt_print(state->ls_ofmt, &lbuf);
2304d62bc4baSyz147064 
2305d62bc4baSyz147064 done:
2306d62bc4baSyz147064 	state->ls_status = status;
2307d62bc4baSyz147064 	return (DLADM_WALK_CONTINUE);
2308d62bc4baSyz147064 }
2309d62bc4baSyz147064 
23108002d411SSowmini Varadhan static boolean_t
23118002d411SSowmini Varadhan print_link_stats_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize)
2312ae6aa22aSVenugopal Iyer {
23138002d411SSowmini Varadhan 	link_args_t *largs = ofarg->ofmt_cbarg;
2314ae6aa22aSVenugopal Iyer 	pktsum_t *diff_stats = largs->link_s_psum;
2315ae6aa22aSVenugopal Iyer 
23168002d411SSowmini Varadhan 	switch (ofarg->ofmt_id) {
2317ae6aa22aSVenugopal Iyer 	case LINK_S_LINK:
23188002d411SSowmini Varadhan 		(void) snprintf(buf, bufsize, "%s", largs->link_s_link);
2319ae6aa22aSVenugopal Iyer 		break;
2320ae6aa22aSVenugopal Iyer 	case LINK_S_IPKTS:
23218002d411SSowmini Varadhan 		(void) snprintf(buf, bufsize, "%llu", diff_stats->ipackets);
2322ae6aa22aSVenugopal Iyer 		break;
2323ae6aa22aSVenugopal Iyer 	case LINK_S_RBYTES:
23248002d411SSowmini Varadhan 		(void) snprintf(buf, bufsize, "%llu", diff_stats->rbytes);
2325ae6aa22aSVenugopal Iyer 		break;
2326ae6aa22aSVenugopal Iyer 	case LINK_S_IERRORS:
23278002d411SSowmini Varadhan 		(void) snprintf(buf, bufsize, "%u", diff_stats->ierrors);
2328ae6aa22aSVenugopal Iyer 		break;
2329ae6aa22aSVenugopal Iyer 	case LINK_S_OPKTS:
23308002d411SSowmini Varadhan 		(void) snprintf(buf, bufsize, "%llu", diff_stats->opackets);
2331ae6aa22aSVenugopal Iyer 		break;
2332ae6aa22aSVenugopal Iyer 	case LINK_S_OBYTES:
23338002d411SSowmini Varadhan 		(void) snprintf(buf, bufsize, "%llu", diff_stats->obytes);
2334ae6aa22aSVenugopal Iyer 		break;
2335ae6aa22aSVenugopal Iyer 	case LINK_S_OERRORS:
23368002d411SSowmini Varadhan 		(void) snprintf(buf, bufsize, "%u", diff_stats->oerrors);
2337ae6aa22aSVenugopal Iyer 		break;
2338ae6aa22aSVenugopal Iyer 	default:
2339ae6aa22aSVenugopal Iyer 		die("invalid input");
2340ae6aa22aSVenugopal Iyer 		break;
2341ae6aa22aSVenugopal Iyer 	}
23428002d411SSowmini Varadhan 	return (B_TRUE);
2343ae6aa22aSVenugopal Iyer }
2344ae6aa22aSVenugopal Iyer 
2345d62bc4baSyz147064 static int
23464ac67f02SAnurag S. Maskey show_link_stats(dladm_handle_t dh, datalink_id_t linkid, void *arg)
2347d62bc4baSyz147064 {
2348e7801d59Ssowmini 	char			link[DLPI_LINKNAME_MAX];
2349d62bc4baSyz147064 	datalink_class_t	class;
2350e7801d59Ssowmini 	show_state_t		*state = (show_state_t *)arg;
23517c478bd9Sstevel@tonic-gate 	pktsum_t		stats, diff_stats;
2352d62bc4baSyz147064 	dladm_phys_attr_t	dpa;
2353ae6aa22aSVenugopal Iyer 	link_args_t		largs;
23547c478bd9Sstevel@tonic-gate 
23557c478bd9Sstevel@tonic-gate 	if (state->ls_firstonly) {
23567c478bd9Sstevel@tonic-gate 		if (state->ls_donefirst)
2357d62bc4baSyz147064 			return (DLADM_WALK_CONTINUE);
23587c478bd9Sstevel@tonic-gate 		state->ls_donefirst = B_TRUE;
23597c478bd9Sstevel@tonic-gate 	} else {
23607c478bd9Sstevel@tonic-gate 		bzero(&state->ls_prevstats, sizeof (state->ls_prevstats));
23617c478bd9Sstevel@tonic-gate 	}
23627c478bd9Sstevel@tonic-gate 
23634ac67f02SAnurag S. Maskey 	if (dladm_datalink_id2info(dh, linkid, NULL, &class, NULL, link,
2364e7801d59Ssowmini 	    DLPI_LINKNAME_MAX) != DLADM_STATUS_OK) {
2365d62bc4baSyz147064 		return (DLADM_WALK_CONTINUE);
2366d62bc4baSyz147064 	}
2367d62bc4baSyz147064 
2368d62bc4baSyz147064 	if (class == DATALINK_CLASS_PHYS) {
23694ac67f02SAnurag S. Maskey 		if (dladm_phys_info(dh, linkid, &dpa, DLADM_OPT_ACTIVE) !=
2370d62bc4baSyz147064 		    DLADM_STATUS_OK) {
2371d62bc4baSyz147064 			return (DLADM_WALK_CONTINUE);
2372d62bc4baSyz147064 		}
2373d62bc4baSyz147064 		if (dpa.dp_novanity)
2374d62bc4baSyz147064 			get_mac_stats(dpa.dp_dev, &stats);
2375d62bc4baSyz147064 		else
2376d62bc4baSyz147064 			get_link_stats(link, &stats);
2377d62bc4baSyz147064 	} else {
2378d62bc4baSyz147064 		get_link_stats(link, &stats);
2379d62bc4baSyz147064 	}
2380da14cebeSEric Cheng 	dladm_stats_diff(&diff_stats, &stats, &state->ls_prevstats);
23817c478bd9Sstevel@tonic-gate 
2382ae6aa22aSVenugopal Iyer 	largs.link_s_link = link;
2383ae6aa22aSVenugopal Iyer 	largs.link_s_psum = &diff_stats;
23848002d411SSowmini Varadhan 	ofmt_print(state->ls_ofmt, &largs);
23857c478bd9Sstevel@tonic-gate 
23867c478bd9Sstevel@tonic-gate 	state->ls_prevstats = stats;
2387d62bc4baSyz147064 	return (DLADM_WALK_CONTINUE);
23887c478bd9Sstevel@tonic-gate }
23897c478bd9Sstevel@tonic-gate 
2390d62bc4baSyz147064 
2391d62bc4baSyz147064 static dladm_status_t
2392d62bc4baSyz147064 print_aggr_info(show_grp_state_t *state, const char *link,
2393e7801d59Ssowmini     dladm_aggr_grp_attr_t *ginfop)
2394d62bc4baSyz147064 {
2395d62bc4baSyz147064 	char			addr_str[ETHERADDRL * 3];
2396e7801d59Ssowmini 	laggr_fields_buf_t	lbuf;
2397d62bc4baSyz147064 
2398e7801d59Ssowmini 	(void) snprintf(lbuf.laggr_name, sizeof (lbuf.laggr_name),
2399e7801d59Ssowmini 	    "%s", link);
2400e7801d59Ssowmini 
2401e7801d59Ssowmini 	(void) dladm_aggr_policy2str(ginfop->lg_policy,
2402e7801d59Ssowmini 	    lbuf.laggr_policy);
2403d62bc4baSyz147064 
2404d62bc4baSyz147064 	if (ginfop->lg_mac_fixed) {
2405d62bc4baSyz147064 		(void) dladm_aggr_macaddr2str(ginfop->lg_mac, addr_str);
2406e7801d59Ssowmini 		(void) snprintf(lbuf.laggr_addrpolicy,
2407e7801d59Ssowmini 		    sizeof (lbuf.laggr_addrpolicy), "fixed (%s)", addr_str);
2408d62bc4baSyz147064 	} else {
2409e7801d59Ssowmini 		(void) snprintf(lbuf.laggr_addrpolicy,
2410e7801d59Ssowmini 		    sizeof (lbuf.laggr_addrpolicy), "auto");
2411d62bc4baSyz147064 	}
2412d62bc4baSyz147064 
2413d62bc4baSyz147064 
2414e7801d59Ssowmini 	(void) dladm_aggr_lacpmode2str(ginfop->lg_lacp_mode,
2415e7801d59Ssowmini 	    lbuf.laggr_lacpactivity);
2416e7801d59Ssowmini 	(void) dladm_aggr_lacptimer2str(ginfop->lg_lacp_timer,
2417e7801d59Ssowmini 	    lbuf.laggr_lacptimer);
2418e7801d59Ssowmini 	(void) snprintf(lbuf.laggr_flags, sizeof (lbuf.laggr_flags), "%c----",
2419d62bc4baSyz147064 	    ginfop->lg_force ? 'f' : '-');
2420e7801d59Ssowmini 
24218002d411SSowmini Varadhan 	ofmt_print(state->gs_ofmt, &lbuf);
2422e7801d59Ssowmini 
2423d62bc4baSyz147064 	return (DLADM_STATUS_OK);
2424d62bc4baSyz147064 }
2425d62bc4baSyz147064 
24268002d411SSowmini Varadhan static boolean_t
24278002d411SSowmini Varadhan print_xaggr_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize)
2428d62bc4baSyz147064 {
24298002d411SSowmini Varadhan 	const laggr_args_t 	*l = ofarg->ofmt_cbarg;
2430e7801d59Ssowmini 	int 			portnum;
2431e7801d59Ssowmini 	boolean_t		is_port = (l->laggr_lport >= 0);
24328002d411SSowmini Varadhan 	static char		tmpbuf[DLADM_STRSIZE];
2433e7801d59Ssowmini 	dladm_aggr_port_attr_t *portp;
2434d62bc4baSyz147064 	dladm_phys_attr_t	dpa;
24358002d411SSowmini Varadhan 	dladm_status_t		*stat, status = DLADM_STATUS_OK;
2436d62bc4baSyz147064 
2437e7801d59Ssowmini 	stat = l->laggr_status;
2438d62bc4baSyz147064 
2439e7801d59Ssowmini 	if (is_port) {
2440e7801d59Ssowmini 		portnum = l->laggr_lport;
2441e7801d59Ssowmini 		portp = &(l->laggr_ginfop->lg_ports[portnum]);
24424ac67f02SAnurag S. Maskey 		if ((status = dladm_datalink_id2info(handle,
24438002d411SSowmini Varadhan 		    portp->lp_linkid, NULL, NULL, NULL, buf, bufsize)) !=
2444e7801d59Ssowmini 		    DLADM_STATUS_OK) {
2445e7801d59Ssowmini 			goto err;
2446d62bc4baSyz147064 		}
24474ac67f02SAnurag S. Maskey 
24484ac67f02SAnurag S. Maskey 		if ((status = dladm_phys_info(handle, portp->lp_linkid,
24494ac67f02SAnurag S. Maskey 		    &dpa, DLADM_OPT_ACTIVE)) != DLADM_STATUS_OK) {
2450e7801d59Ssowmini 			goto err;
2451e7801d59Ssowmini 		}
2452d62bc4baSyz147064 	}
2453d62bc4baSyz147064 
24548002d411SSowmini Varadhan 	switch (ofarg->ofmt_id) {
2455e7801d59Ssowmini 	case AGGR_X_LINK:
24568002d411SSowmini Varadhan 		(void) snprintf(buf, bufsize, "%s",
24578002d411SSowmini Varadhan 		    (is_port && !l->laggr_parsable ? " " : l->laggr_link));
2458e7801d59Ssowmini 		break;
2459e7801d59Ssowmini 	case AGGR_X_PORT:
2460e7801d59Ssowmini 		if (is_port)
2461e7801d59Ssowmini 			break;
24628002d411SSowmini Varadhan 		*stat = DLADM_STATUS_OK;
24638002d411SSowmini Varadhan 		return (B_TRUE);
2464d62bc4baSyz147064 
2465e7801d59Ssowmini 	case AGGR_X_SPEED:
2466e7801d59Ssowmini 		if (is_port) {
24678002d411SSowmini Varadhan 			(void) snprintf(buf, bufsize, "%uMb",
2468e7801d59Ssowmini 			    (uint_t)((get_ifspeed(dpa.dp_dev,
2469e7801d59Ssowmini 			    B_FALSE)) / 1000000ull));
2470e7801d59Ssowmini 		} else {
24718002d411SSowmini Varadhan 			(void) snprintf(buf, bufsize, "%uMb",
2472e7801d59Ssowmini 			    (uint_t)((get_ifspeed(l->laggr_link,
2473e7801d59Ssowmini 			    B_TRUE)) / 1000000ull));
2474e7801d59Ssowmini 		}
2475e7801d59Ssowmini 		break;
2476e7801d59Ssowmini 
2477e7801d59Ssowmini 	case AGGR_X_DUPLEX:
2478e7801d59Ssowmini 		if (is_port)
24798002d411SSowmini Varadhan 			(void) get_linkduplex(dpa.dp_dev, B_FALSE, tmpbuf);
2480d62bc4baSyz147064 		else
24818002d411SSowmini Varadhan 			(void) get_linkduplex(l->laggr_link, B_TRUE, tmpbuf);
24828002d411SSowmini Varadhan 		(void) strlcpy(buf, tmpbuf, bufsize);
2483e7801d59Ssowmini 		break;
2484d62bc4baSyz147064 
2485e7801d59Ssowmini 	case AGGR_X_STATE:
24861a1811a0Svs226613 		if (is_port)
24878002d411SSowmini Varadhan 			(void) get_linkstate(dpa.dp_dev,  B_FALSE, tmpbuf);
24881a1811a0Svs226613 		else
24898002d411SSowmini Varadhan 			(void) get_linkstate(l->laggr_link, B_TRUE, tmpbuf);
24908002d411SSowmini Varadhan 		(void) strlcpy(buf, tmpbuf, bufsize);
2491e7801d59Ssowmini 		break;
2492e7801d59Ssowmini 	case AGGR_X_ADDRESS:
2493e7801d59Ssowmini 		(void) dladm_aggr_macaddr2str(
2494e7801d59Ssowmini 		    (is_port ? portp->lp_mac : l->laggr_ginfop->lg_mac),
24958002d411SSowmini Varadhan 		    tmpbuf);
24968002d411SSowmini Varadhan 		(void) strlcpy(buf, tmpbuf, bufsize);
2497e7801d59Ssowmini 		break;
2498e7801d59Ssowmini 	case AGGR_X_PORTSTATE:
24998002d411SSowmini Varadhan 		if (is_port) {
25008002d411SSowmini Varadhan 			(void) dladm_aggr_portstate2str(portp->lp_state,
25018002d411SSowmini Varadhan 			    tmpbuf);
25028002d411SSowmini Varadhan 			(void) strlcpy(buf, tmpbuf, bufsize);
25038002d411SSowmini Varadhan 		}
2504e7801d59Ssowmini 		break;
2505e7801d59Ssowmini 	}
2506e7801d59Ssowmini err:
2507e7801d59Ssowmini 	*stat = status;
25088002d411SSowmini Varadhan 	return (B_TRUE);
2509e7801d59Ssowmini }
2510e7801d59Ssowmini 
2511e7801d59Ssowmini static dladm_status_t
2512e7801d59Ssowmini print_aggr_extended(show_grp_state_t *state, const char *link,
2513e7801d59Ssowmini     dladm_aggr_grp_attr_t *ginfop)
2514e7801d59Ssowmini {
2515e7801d59Ssowmini 	int			i;
2516e7801d59Ssowmini 	dladm_status_t		status;
2517e7801d59Ssowmini 	laggr_args_t		largs;
2518e7801d59Ssowmini 
2519e7801d59Ssowmini 	largs.laggr_lport = -1;
2520e7801d59Ssowmini 	largs.laggr_link = link;
2521e7801d59Ssowmini 	largs.laggr_ginfop = ginfop;
2522e7801d59Ssowmini 	largs.laggr_status = &status;
25238002d411SSowmini Varadhan 	largs.laggr_parsable = state->gs_parsable;
2524e7801d59Ssowmini 
25258002d411SSowmini Varadhan 	ofmt_print(state->gs_ofmt, &largs);
2526e7801d59Ssowmini 
2527e7801d59Ssowmini 	if (status != DLADM_STATUS_OK)
2528e7801d59Ssowmini 		goto done;
2529e7801d59Ssowmini 
2530e7801d59Ssowmini 	for (i = 0; i < ginfop->lg_nports; i++) {
2531e7801d59Ssowmini 		largs.laggr_lport = i;
25328002d411SSowmini Varadhan 		ofmt_print(state->gs_ofmt, &largs);
2533e7801d59Ssowmini 		if (status != DLADM_STATUS_OK)
2534e7801d59Ssowmini 			goto done;
2535d62bc4baSyz147064 	}
2536d62bc4baSyz147064 
2537d62bc4baSyz147064 	status = DLADM_STATUS_OK;
2538d62bc4baSyz147064 done:
2539d62bc4baSyz147064 	return (status);
2540d62bc4baSyz147064 }
2541d62bc4baSyz147064 
25428002d411SSowmini Varadhan static boolean_t
25438002d411SSowmini Varadhan print_lacp_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize)
2544e7801d59Ssowmini {
25458002d411SSowmini Varadhan 	const laggr_args_t	*l = ofarg->ofmt_cbarg;
2546e7801d59Ssowmini 	int			portnum;
2547e7801d59Ssowmini 	boolean_t		is_port = (l->laggr_lport >= 0);
2548e7801d59Ssowmini 	dladm_aggr_port_attr_t	*portp;
2549e7801d59Ssowmini 	dladm_status_t		*stat, status;
2550e7801d59Ssowmini 	aggr_lacp_state_t	*lstate;
2551e7801d59Ssowmini 
2552e7801d59Ssowmini 	if (!is_port) {
25538002d411SSowmini Varadhan 		return (B_FALSE); /* cannot happen! */
2554e7801d59Ssowmini 	}
2555e7801d59Ssowmini 
2556e7801d59Ssowmini 	stat = l->laggr_status;
2557e7801d59Ssowmini 
2558e7801d59Ssowmini 	portnum = l->laggr_lport;
2559e7801d59Ssowmini 	portp = &(l->laggr_ginfop->lg_ports[portnum]);
25604ac67f02SAnurag S. Maskey 
25614ac67f02SAnurag S. Maskey 	if ((status = dladm_datalink_id2info(handle, portp->lp_linkid,
25628002d411SSowmini Varadhan 	    NULL, NULL, NULL, buf, bufsize)) != DLADM_STATUS_OK) {
2563e7801d59Ssowmini 			goto err;
2564e7801d59Ssowmini 	}
2565e7801d59Ssowmini 	lstate = &(portp->lp_lacp_state);
2566e7801d59Ssowmini 
25678002d411SSowmini Varadhan 	switch (ofarg->ofmt_id) {
2568e7801d59Ssowmini 	case AGGR_L_LINK:
25698002d411SSowmini Varadhan 		(void) snprintf(buf, bufsize, "%s",
2570e7801d59Ssowmini 		    (portnum > 0 ? "" : l->laggr_link));
2571e7801d59Ssowmini 		break;
2572e7801d59Ssowmini 
2573e7801d59Ssowmini 	case AGGR_L_PORT:
25748002d411SSowmini Varadhan 		/*
25758002d411SSowmini Varadhan 		 * buf already contains portname as a result of the
25768002d411SSowmini Varadhan 		 * earlier call to dladm_datalink_id2info().
25778002d411SSowmini Varadhan 		 */
2578e7801d59Ssowmini 		break;
2579e7801d59Ssowmini 
2580e7801d59Ssowmini 	case AGGR_L_AGGREGATABLE:
25818002d411SSowmini Varadhan 		(void) snprintf(buf, bufsize, "%s",
2582e7801d59Ssowmini 		    (lstate->bit.aggregation ? "yes" : "no"));
2583e7801d59Ssowmini 		break;
2584e7801d59Ssowmini 
2585e7801d59Ssowmini 	case AGGR_L_SYNC:
25868002d411SSowmini Varadhan 		(void) snprintf(buf, bufsize, "%s",
2587e7801d59Ssowmini 		    (lstate->bit.sync ? "yes" : "no"));
2588e7801d59Ssowmini 		break;
2589e7801d59Ssowmini 
2590e7801d59Ssowmini 	case AGGR_L_COLL:
25918002d411SSowmini Varadhan 		(void) snprintf(buf, bufsize, "%s",
2592e7801d59Ssowmini 		    (lstate->bit.collecting ? "yes" : "no"));
2593e7801d59Ssowmini 		break;
2594e7801d59Ssowmini 
2595e7801d59Ssowmini 	case AGGR_L_DIST:
25968002d411SSowmini Varadhan 		(void) snprintf(buf, bufsize, "%s",
2597e7801d59Ssowmini 		    (lstate->bit.distributing ? "yes" : "no"));
2598e7801d59Ssowmini 		break;
2599e7801d59Ssowmini 
2600e7801d59Ssowmini 	case AGGR_L_DEFAULTED:
26018002d411SSowmini Varadhan 		(void) snprintf(buf, bufsize, "%s",
2602e7801d59Ssowmini 		    (lstate->bit.defaulted ? "yes" : "no"));
2603e7801d59Ssowmini 		break;
2604e7801d59Ssowmini 
2605e7801d59Ssowmini 	case AGGR_L_EXPIRED:
26068002d411SSowmini Varadhan 		(void) snprintf(buf, bufsize, "%s",
2607e7801d59Ssowmini 		    (lstate->bit.expired ? "yes" : "no"));
2608e7801d59Ssowmini 		break;
2609e7801d59Ssowmini 	}
2610e7801d59Ssowmini 
2611e7801d59Ssowmini 	*stat = DLADM_STATUS_OK;
26128002d411SSowmini Varadhan 	return (B_TRUE);
2613e7801d59Ssowmini 
2614e7801d59Ssowmini err:
2615e7801d59Ssowmini 	*stat = status;
26168002d411SSowmini Varadhan 	return (B_TRUE);
2617e7801d59Ssowmini }
2618e7801d59Ssowmini 
2619d62bc4baSyz147064 static dladm_status_t
2620d62bc4baSyz147064 print_aggr_lacp(show_grp_state_t *state, const char *link,
2621e7801d59Ssowmini     dladm_aggr_grp_attr_t *ginfop)
2622d62bc4baSyz147064 {
2623d62bc4baSyz147064 	int		i;
2624d62bc4baSyz147064 	dladm_status_t	status;
2625e7801d59Ssowmini 	laggr_args_t	largs;
2626d62bc4baSyz147064 
2627e7801d59Ssowmini 	largs.laggr_link = link;
2628e7801d59Ssowmini 	largs.laggr_ginfop = ginfop;
2629e7801d59Ssowmini 	largs.laggr_status = &status;
2630d62bc4baSyz147064 
2631e7801d59Ssowmini 	for (i = 0; i < ginfop->lg_nports; i++) {
2632e7801d59Ssowmini 		largs.laggr_lport = i;
26338002d411SSowmini Varadhan 		ofmt_print(state->gs_ofmt, &largs);
2634d62bc4baSyz147064 		if (status != DLADM_STATUS_OK)
2635d62bc4baSyz147064 			goto done;
2636d62bc4baSyz147064 	}
2637d62bc4baSyz147064 
2638d62bc4baSyz147064 	status = DLADM_STATUS_OK;
2639d62bc4baSyz147064 done:
2640d62bc4baSyz147064 	return (status);
2641d62bc4baSyz147064 }
2642d62bc4baSyz147064 
26438002d411SSowmini Varadhan static boolean_t
26448002d411SSowmini Varadhan print_aggr_stats_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize)
2645e7801d59Ssowmini {
26468002d411SSowmini Varadhan 	const laggr_args_t	*l = ofarg->ofmt_cbarg;
2647e7801d59Ssowmini 	int 			portnum;
2648e7801d59Ssowmini 	boolean_t		is_port = (l->laggr_lport >= 0);
2649e7801d59Ssowmini 	dladm_aggr_port_attr_t	*portp;
2650e7801d59Ssowmini 	dladm_status_t		*stat, status;
26512d40c3b2SPrakash Jalan 	pktsum_t		*diff_stats;
2652e7801d59Ssowmini 
2653e7801d59Ssowmini 	stat = l->laggr_status;
2654e7801d59Ssowmini 	*stat = DLADM_STATUS_OK;
2655e7801d59Ssowmini 
2656e7801d59Ssowmini 	if (is_port) {
2657e7801d59Ssowmini 		portnum = l->laggr_lport;
2658e7801d59Ssowmini 		portp = &(l->laggr_ginfop->lg_ports[portnum]);
2659e7801d59Ssowmini 
26604ac67f02SAnurag S. Maskey 		if ((status = dladm_datalink_id2info(handle,
26618002d411SSowmini Varadhan 		    portp->lp_linkid, NULL, NULL, NULL, buf, bufsize)) !=
26624ac67f02SAnurag S. Maskey 		    DLADM_STATUS_OK) {
2663e7801d59Ssowmini 			goto err;
2664e7801d59Ssowmini 		}
26652d40c3b2SPrakash Jalan 		diff_stats = l->laggr_diffstats;
2666e7801d59Ssowmini 	}
2667e7801d59Ssowmini 
26688002d411SSowmini Varadhan 	switch (ofarg->ofmt_id) {
2669e7801d59Ssowmini 	case AGGR_S_LINK:
26708002d411SSowmini Varadhan 		(void) snprintf(buf, bufsize, "%s",
2671e7801d59Ssowmini 		    (is_port ? "" : l->laggr_link));
2672e7801d59Ssowmini 		break;
2673e7801d59Ssowmini 	case AGGR_S_PORT:
26748002d411SSowmini Varadhan 		/*
26758002d411SSowmini Varadhan 		 * if (is_port), buf has port name. Otherwise we print
26768002d411SSowmini Varadhan 		 * STR_UNDEF_VAL
26778002d411SSowmini Varadhan 		 */
2678e7801d59Ssowmini 		break;
2679e7801d59Ssowmini 
2680e7801d59Ssowmini 	case AGGR_S_IPKTS:
2681e7801d59Ssowmini 		if (is_port) {
26828002d411SSowmini Varadhan 			(void) snprintf(buf, bufsize, "%llu",
26832d40c3b2SPrakash Jalan 			    diff_stats->ipackets);
2684e7801d59Ssowmini 		} else {
26858002d411SSowmini Varadhan 			(void) snprintf(buf, bufsize, "%llu",
2686e7801d59Ssowmini 			    l->laggr_pktsumtot->ipackets);
2687e7801d59Ssowmini 		}
2688e7801d59Ssowmini 		break;
2689e7801d59Ssowmini 
2690e7801d59Ssowmini 	case AGGR_S_RBYTES:
2691e7801d59Ssowmini 		if (is_port) {
26928002d411SSowmini Varadhan 			(void) snprintf(buf, bufsize, "%llu",
26932d40c3b2SPrakash Jalan 			    diff_stats->rbytes);
2694e7801d59Ssowmini 		} else {
26958002d411SSowmini Varadhan 			(void) snprintf(buf, bufsize, "%llu",
2696e7801d59Ssowmini 			    l->laggr_pktsumtot->rbytes);
2697e7801d59Ssowmini 		}
2698e7801d59Ssowmini 		break;
2699e7801d59Ssowmini 
2700e7801d59Ssowmini 	case AGGR_S_OPKTS:
2701e7801d59Ssowmini 		if (is_port) {
27028002d411SSowmini Varadhan 			(void) snprintf(buf, bufsize, "%llu",
27032d40c3b2SPrakash Jalan 			    diff_stats->opackets);
2704e7801d59Ssowmini 		} else {
27058002d411SSowmini Varadhan 			(void) snprintf(buf, bufsize, "%llu",
2706e7801d59Ssowmini 			    l->laggr_pktsumtot->opackets);
2707e7801d59Ssowmini 		}
2708e7801d59Ssowmini 		break;
2709e7801d59Ssowmini 	case AGGR_S_OBYTES:
2710e7801d59Ssowmini 		if (is_port) {
27118002d411SSowmini Varadhan 			(void) snprintf(buf, bufsize, "%llu",
27122d40c3b2SPrakash Jalan 			    diff_stats->obytes);
2713e7801d59Ssowmini 		} else {
27148002d411SSowmini Varadhan 			(void) snprintf(buf, bufsize, "%llu",
2715e7801d59Ssowmini 			    l->laggr_pktsumtot->obytes);
2716e7801d59Ssowmini 		}
2717e7801d59Ssowmini 		break;
2718e7801d59Ssowmini 
2719e7801d59Ssowmini 	case AGGR_S_IPKTDIST:
2720e7801d59Ssowmini 		if (is_port) {
27218002d411SSowmini Varadhan 			(void) snprintf(buf, bufsize, "%-6.1f",
27222d40c3b2SPrakash Jalan 			    (double)diff_stats->ipackets/
2723e7801d59Ssowmini 			    (double)l->laggr_pktsumtot->ipackets * 100);
2724e7801d59Ssowmini 		}
2725e7801d59Ssowmini 		break;
2726e7801d59Ssowmini 	case AGGR_S_OPKTDIST:
2727e7801d59Ssowmini 		if (is_port) {
27288002d411SSowmini Varadhan 			(void) snprintf(buf, bufsize, "%-6.1f",
27292d40c3b2SPrakash Jalan 			    (double)diff_stats->opackets/
2730e7801d59Ssowmini 			    (double)l->laggr_pktsumtot->opackets * 100);
2731e7801d59Ssowmini 		}
2732e7801d59Ssowmini 		break;
2733e7801d59Ssowmini 	}
27348002d411SSowmini Varadhan 	return (B_TRUE);
2735e7801d59Ssowmini 
2736e7801d59Ssowmini err:
2737e7801d59Ssowmini 	*stat = status;
27388002d411SSowmini Varadhan 	return (B_TRUE);
2739e7801d59Ssowmini }
2740e7801d59Ssowmini 
2741d62bc4baSyz147064 static dladm_status_t
2742d62bc4baSyz147064 print_aggr_stats(show_grp_state_t *state, const char *link,
2743e7801d59Ssowmini     dladm_aggr_grp_attr_t *ginfop)
2744d62bc4baSyz147064 {
2745d62bc4baSyz147064 	dladm_phys_attr_t	dpa;
2746d62bc4baSyz147064 	dladm_aggr_port_attr_t	*portp;
27472d40c3b2SPrakash Jalan 	pktsum_t		pktsumtot, *port_stat;
2748d62bc4baSyz147064 	dladm_status_t		status;
2749d62bc4baSyz147064 	int			i;
2750e7801d59Ssowmini 	laggr_args_t		largs;
27517c478bd9Sstevel@tonic-gate 
27527c478bd9Sstevel@tonic-gate 	/* sum the ports statistics */
27537c478bd9Sstevel@tonic-gate 	bzero(&pktsumtot, sizeof (pktsumtot));
2754d62bc4baSyz147064 
27552d40c3b2SPrakash Jalan 	/* Allocate memory to keep stats of each port */
27562d40c3b2SPrakash Jalan 	port_stat = malloc(ginfop->lg_nports * sizeof (pktsum_t));
27572d40c3b2SPrakash Jalan 	if (port_stat == NULL) {
27582d40c3b2SPrakash Jalan 		/* Bail out; no memory */
27592d40c3b2SPrakash Jalan 		return (DLADM_STATUS_NOMEM);
27602d40c3b2SPrakash Jalan 	}
27612d40c3b2SPrakash Jalan 
27622d40c3b2SPrakash Jalan 
2763d62bc4baSyz147064 	for (i = 0; i < ginfop->lg_nports; i++) {
2764d62bc4baSyz147064 
2765d62bc4baSyz147064 		portp = &(ginfop->lg_ports[i]);
27664ac67f02SAnurag S. Maskey 		if ((status = dladm_phys_info(handle, portp->lp_linkid, &dpa,
2767d62bc4baSyz147064 		    DLADM_OPT_ACTIVE)) != DLADM_STATUS_OK) {
2768d62bc4baSyz147064 			goto done;
27697c478bd9Sstevel@tonic-gate 		}
27707c478bd9Sstevel@tonic-gate 
27712d40c3b2SPrakash Jalan 		get_mac_stats(dpa.dp_dev, &port_stat[i]);
27722d40c3b2SPrakash Jalan 
27732d40c3b2SPrakash Jalan 		/*
27742d40c3b2SPrakash Jalan 		 * Let's re-use gs_prevstats[] to store the difference of the
27752d40c3b2SPrakash Jalan 		 * counters since last use. We will store the new stats from
27762d40c3b2SPrakash Jalan 		 * port_stat[] once we have the stats displayed.
27772d40c3b2SPrakash Jalan 		 */
27782d40c3b2SPrakash Jalan 
27792d40c3b2SPrakash Jalan 		dladm_stats_diff(&state->gs_prevstats[i], &port_stat[i],
27802d40c3b2SPrakash Jalan 		    &state->gs_prevstats[i]);
27812d40c3b2SPrakash Jalan 		dladm_stats_total(&pktsumtot, &pktsumtot,
2782da14cebeSEric Cheng 		    &state->gs_prevstats[i]);
27837c478bd9Sstevel@tonic-gate 	}
27847c478bd9Sstevel@tonic-gate 
2785e7801d59Ssowmini 	largs.laggr_lport = -1;
2786e7801d59Ssowmini 	largs.laggr_link = link;
2787e7801d59Ssowmini 	largs.laggr_ginfop = ginfop;
2788e7801d59Ssowmini 	largs.laggr_status = &status;
2789e7801d59Ssowmini 	largs.laggr_pktsumtot = &pktsumtot;
2790e7801d59Ssowmini 
27918002d411SSowmini Varadhan 	ofmt_print(state->gs_ofmt, &largs);
2792e7801d59Ssowmini 
2793e7801d59Ssowmini 	if (status != DLADM_STATUS_OK)
2794e7801d59Ssowmini 		goto done;
2795d62bc4baSyz147064 
2796d62bc4baSyz147064 	for (i = 0; i < ginfop->lg_nports; i++) {
2797e7801d59Ssowmini 		largs.laggr_lport = i;
27982d40c3b2SPrakash Jalan 		largs.laggr_diffstats = &state->gs_prevstats[i];
27998002d411SSowmini Varadhan 		ofmt_print(state->gs_ofmt, &largs);
2800e7801d59Ssowmini 		if (status != DLADM_STATUS_OK)
2801d62bc4baSyz147064 			goto done;
2802d62bc4baSyz147064 	}
2803d62bc4baSyz147064 
2804d62bc4baSyz147064 	status = DLADM_STATUS_OK;
28052d40c3b2SPrakash Jalan 	for (i = 0; i < ginfop->lg_nports; i++)
28062d40c3b2SPrakash Jalan 		state->gs_prevstats[i] = port_stat[i];
28072d40c3b2SPrakash Jalan 
2808d62bc4baSyz147064 done:
28092d40c3b2SPrakash Jalan 	free(port_stat);
2810d62bc4baSyz147064 	return (status);
2811d62bc4baSyz147064 }
2812d62bc4baSyz147064 
2813d62bc4baSyz147064 static dladm_status_t
2814e7801d59Ssowmini print_aggr(show_grp_state_t *state, datalink_id_t linkid)
2815d62bc4baSyz147064 {
2816d62bc4baSyz147064 	char			link[MAXLINKNAMELEN];
2817d62bc4baSyz147064 	dladm_aggr_grp_attr_t	ginfo;
2818d62bc4baSyz147064 	uint32_t		flags;
2819d62bc4baSyz147064 	dladm_status_t		status;
2820d62bc4baSyz147064 
28215f5c9f54SAnurag S. Maskey 	bzero(&ginfo, sizeof (dladm_aggr_grp_attr_t));
28224ac67f02SAnurag S. Maskey 	if ((status = dladm_datalink_id2info(handle, linkid, &flags, NULL,
28234ac67f02SAnurag S. Maskey 	    NULL, link, MAXLINKNAMELEN)) != DLADM_STATUS_OK) {
2824d62bc4baSyz147064 		return (status);
2825d62bc4baSyz147064 	}
2826d62bc4baSyz147064 
2827d62bc4baSyz147064 	if (!(state->gs_flags & flags))
2828d62bc4baSyz147064 		return (DLADM_STATUS_NOTFOUND);
2829d62bc4baSyz147064 
28304ac67f02SAnurag S. Maskey 	status = dladm_aggr_info(handle, linkid, &ginfo, state->gs_flags);
2831d62bc4baSyz147064 	if (status != DLADM_STATUS_OK)
2832d62bc4baSyz147064 		return (status);
2833d62bc4baSyz147064 
2834d62bc4baSyz147064 	if (state->gs_lacp)
2835e7801d59Ssowmini 		status = print_aggr_lacp(state, link, &ginfo);
2836d62bc4baSyz147064 	else if (state->gs_extended)
2837e7801d59Ssowmini 		status = print_aggr_extended(state, link, &ginfo);
2838d62bc4baSyz147064 	else if (state->gs_stats)
2839e7801d59Ssowmini 		status = print_aggr_stats(state, link, &ginfo);
28404ac67f02SAnurag S. Maskey 	else
2841e7801d59Ssowmini 		status = print_aggr_info(state, link, &ginfo);
2842d62bc4baSyz147064 
2843d62bc4baSyz147064 done:
2844d62bc4baSyz147064 	free(ginfo.lg_ports);
2845d62bc4baSyz147064 	return (status);
2846d62bc4baSyz147064 }
2847d62bc4baSyz147064 
28484ac67f02SAnurag S. Maskey /* ARGSUSED */
2849d62bc4baSyz147064 static int
28504ac67f02SAnurag S. Maskey show_aggr(dladm_handle_t dh, datalink_id_t linkid, void *arg)
2851d62bc4baSyz147064 {
2852d62bc4baSyz147064 	show_grp_state_t	*state = arg;
2853d62bc4baSyz147064 
28548002d411SSowmini Varadhan 	state->gs_status = print_aggr(state, linkid);
2855d62bc4baSyz147064 	return (DLADM_WALK_CONTINUE);
28567c478bd9Sstevel@tonic-gate }
28577c478bd9Sstevel@tonic-gate 
28587c478bd9Sstevel@tonic-gate static void
28598d5c46e6Sam223141 do_show_link(int argc, char *argv[], const char *use)
28607c478bd9Sstevel@tonic-gate {
28617c478bd9Sstevel@tonic-gate 	int		option;
28627c478bd9Sstevel@tonic-gate 	boolean_t	s_arg = B_FALSE;
2863da14cebeSEric Cheng 	boolean_t	S_arg = B_FALSE;
28647c478bd9Sstevel@tonic-gate 	boolean_t	i_arg = B_FALSE;
2865d62bc4baSyz147064 	uint32_t	flags = DLADM_OPT_ACTIVE;
2866d62bc4baSyz147064 	boolean_t	p_arg = B_FALSE;
2867d62bc4baSyz147064 	datalink_id_t	linkid = DATALINK_ALL_LINKID;
2868da14cebeSEric Cheng 	char		linkname[MAXLINKNAMELEN];
286963a6526dSMichael Lim 	uint32_t	interval = 0;
2870d62bc4baSyz147064 	show_state_t	state;
2871d62bc4baSyz147064 	dladm_status_t	status;
2872e7801d59Ssowmini 	boolean_t	o_arg = B_FALSE;
2873e7801d59Ssowmini 	char		*fields_str = NULL;
2874e7801d59Ssowmini 	char		*all_active_fields = "link,class,mtu,state,over";
2875e7801d59Ssowmini 	char		*all_inactive_fields = "link,class,over";
28766be03d0bSVasumathi Sundaram - Sun Microsystems 	char		*allstat_fields =
28776be03d0bSVasumathi Sundaram - Sun Microsystems 	    "link,ipackets,rbytes,ierrors,opackets,obytes,oerrors";
28788002d411SSowmini Varadhan 	ofmt_handle_t	ofmt;
28798002d411SSowmini Varadhan 	ofmt_status_t	oferr;
28808002d411SSowmini Varadhan 	uint_t		ofmtflags = 0;
2881e7801d59Ssowmini 
2882e7801d59Ssowmini 	bzero(&state, sizeof (state));
28837c478bd9Sstevel@tonic-gate 
28847c478bd9Sstevel@tonic-gate 	opterr = 0;
2885da14cebeSEric Cheng 	while ((option = getopt_long(argc, argv, ":pPsSi:o:",
2886d62bc4baSyz147064 	    show_lopts, NULL)) != -1) {
28877c478bd9Sstevel@tonic-gate 		switch (option) {
28887c478bd9Sstevel@tonic-gate 		case 'p':
2889d62bc4baSyz147064 			if (p_arg)
2890d62bc4baSyz147064 				die_optdup(option);
2891d62bc4baSyz147064 
2892d62bc4baSyz147064 			p_arg = B_TRUE;
28937c478bd9Sstevel@tonic-gate 			break;
28947c478bd9Sstevel@tonic-gate 		case 's':
289533343a97Smeem 			if (s_arg)
289633343a97Smeem 				die_optdup(option);
28977c478bd9Sstevel@tonic-gate 
28987c478bd9Sstevel@tonic-gate 			s_arg = B_TRUE;
28997c478bd9Sstevel@tonic-gate 			break;
2900d62bc4baSyz147064 		case 'P':
2901d62bc4baSyz147064 			if (flags != DLADM_OPT_ACTIVE)
2902d62bc4baSyz147064 				die_optdup(option);
2903d62bc4baSyz147064 
2904d62bc4baSyz147064 			flags = DLADM_OPT_PERSIST;
2905d62bc4baSyz147064 			break;
2906da14cebeSEric Cheng 		case 'S':
2907da14cebeSEric Cheng 			if (S_arg)
2908da14cebeSEric Cheng 				die_optdup(option);
2909da14cebeSEric Cheng 
2910da14cebeSEric Cheng 			S_arg = B_TRUE;
2911da14cebeSEric Cheng 			break;
2912e7801d59Ssowmini 		case 'o':
2913e7801d59Ssowmini 			o_arg = B_TRUE;
2914e7801d59Ssowmini 			fields_str = optarg;
2915e7801d59Ssowmini 			break;
29167c478bd9Sstevel@tonic-gate 		case 'i':
291733343a97Smeem 			if (i_arg)
291833343a97Smeem 				die_optdup(option);
29197c478bd9Sstevel@tonic-gate 
29207c478bd9Sstevel@tonic-gate 			i_arg = B_TRUE;
292163a6526dSMichael Lim 			if (!dladm_str2interval(optarg, &interval))
292233343a97Smeem 				die("invalid interval value '%s'", optarg);
29237c478bd9Sstevel@tonic-gate 			break;
29247c478bd9Sstevel@tonic-gate 		default:
29258d5c46e6Sam223141 			die_opterr(optopt, option, use);
292633343a97Smeem 			break;
29277c478bd9Sstevel@tonic-gate 		}
29287c478bd9Sstevel@tonic-gate 	}
29297c478bd9Sstevel@tonic-gate 
2930da14cebeSEric Cheng 	if (i_arg && !(s_arg || S_arg))
2931da14cebeSEric Cheng 		die("the option -i can be used only with -s or -S");
2932da14cebeSEric Cheng 
2933da14cebeSEric Cheng 	if (s_arg && S_arg)
2934da14cebeSEric Cheng 		die("the -s option cannot be used with -S");
29357c478bd9Sstevel@tonic-gate 
29366be03d0bSVasumathi Sundaram - Sun Microsystems 	if (s_arg && flags != DLADM_OPT_ACTIVE)
29376be03d0bSVasumathi Sundaram - Sun Microsystems 		die("the option -P cannot be used with -s");
2938d62bc4baSyz147064 
2939da14cebeSEric Cheng 	if (S_arg && (p_arg || flags != DLADM_OPT_ACTIVE))
2940da14cebeSEric Cheng 		die("the option -%c cannot be used with -S", p_arg ? 'p' : 'P');
2941da14cebeSEric Cheng 
29427c478bd9Sstevel@tonic-gate 	/* get link name (optional last argument) */
2943d62bc4baSyz147064 	if (optind == (argc-1)) {
2944d62bc4baSyz147064 		uint32_t	f;
2945d62bc4baSyz147064 
2946da14cebeSEric Cheng 		if (strlcpy(linkname, argv[optind], MAXLINKNAMELEN)
2947da14cebeSEric Cheng 		    >= MAXLINKNAMELEN) {
2948da14cebeSEric Cheng 			(void) fprintf(stderr,
2949da14cebeSEric Cheng 			    gettext("%s: link name too long\n"),
2950da14cebeSEric Cheng 			    progname);
29514ac67f02SAnurag S. Maskey 			dladm_close(handle);
2952da14cebeSEric Cheng 			exit(1);
2953da14cebeSEric Cheng 		}
29544ac67f02SAnurag S. Maskey 		if ((status = dladm_name2info(handle, linkname, &linkid, &f,
2955d62bc4baSyz147064 		    NULL, NULL)) != DLADM_STATUS_OK) {
2956da14cebeSEric Cheng 			die_dlerr(status, "link %s is not valid", linkname);
2957d62bc4baSyz147064 		}
2958d62bc4baSyz147064 
2959d62bc4baSyz147064 		if (!(f & flags)) {
2960d62bc4baSyz147064 			die_dlerr(DLADM_STATUS_BADARG, "link %s is %s",
2961d62bc4baSyz147064 			    argv[optind], flags == DLADM_OPT_PERSIST ?
2962d62bc4baSyz147064 			    "a temporary link" : "temporarily removed");
2963d62bc4baSyz147064 		}
2964d62bc4baSyz147064 	} else if (optind != argc) {
29657c478bd9Sstevel@tonic-gate 		usage();
2966d62bc4baSyz147064 	}
29677c478bd9Sstevel@tonic-gate 
29680d365605Sschuster 	if (p_arg && !o_arg)
29690d365605Sschuster 		die("-p requires -o");
29700d365605Sschuster 
2971da14cebeSEric Cheng 	if (S_arg) {
29724ac67f02SAnurag S. Maskey 		dladm_continuous(handle, linkid, NULL, interval, LINK_REPORT);
2973da14cebeSEric Cheng 		return;
2974da14cebeSEric Cheng 	}
2975da14cebeSEric Cheng 
29760d365605Sschuster 	if (p_arg && strcasecmp(fields_str, "all") == 0)
29770d365605Sschuster 		die("\"-o all\" is invalid with -p");
29780d365605Sschuster 
2979e7801d59Ssowmini 	if (!o_arg || (o_arg && strcasecmp(fields_str, "all") == 0)) {
29806be03d0bSVasumathi Sundaram - Sun Microsystems 		if (s_arg)
29816be03d0bSVasumathi Sundaram - Sun Microsystems 			fields_str = allstat_fields;
29826be03d0bSVasumathi Sundaram - Sun Microsystems 		else if (flags & DLADM_OPT_ACTIVE)
2983e7801d59Ssowmini 			fields_str = all_active_fields;
2984e7801d59Ssowmini 		else
2985e7801d59Ssowmini 			fields_str = all_inactive_fields;
2986e7801d59Ssowmini 	}
2987e7801d59Ssowmini 
29888002d411SSowmini Varadhan 	state.ls_parsable = p_arg;
29896be03d0bSVasumathi Sundaram - Sun Microsystems 	state.ls_flags = flags;
29906be03d0bSVasumathi Sundaram - Sun Microsystems 	state.ls_donefirst = B_FALSE;
29916be03d0bSVasumathi Sundaram - Sun Microsystems 
29926be03d0bSVasumathi Sundaram - Sun Microsystems 	if (s_arg) {
29936be03d0bSVasumathi Sundaram - Sun Microsystems 		link_stats(linkid, interval, fields_str, &state);
29946be03d0bSVasumathi Sundaram - Sun Microsystems 		return;
29956be03d0bSVasumathi Sundaram - Sun Microsystems 	}
29968002d411SSowmini Varadhan 	if (state.ls_parsable)
29978002d411SSowmini Varadhan 		ofmtflags |= OFMT_PARSABLE;
29988002d411SSowmini Varadhan 	oferr = ofmt_open(fields_str, link_fields, ofmtflags, 0, &ofmt);
29998002d411SSowmini Varadhan 	dladm_ofmt_check(oferr, state.ls_parsable, ofmt);
30008002d411SSowmini Varadhan 	state.ls_ofmt = ofmt;
3001e7801d59Ssowmini 
3002d62bc4baSyz147064 	if (linkid == DATALINK_ALL_LINKID) {
30034ac67f02SAnurag S. Maskey 		(void) dladm_walk_datalink_id(show_link, handle, &state,
3004d62bc4baSyz147064 		    DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE, flags);
3005210db224Sericheng 	} else {
30064ac67f02SAnurag S. Maskey 		(void) show_link(handle, linkid, &state);
3007d62bc4baSyz147064 		if (state.ls_status != DLADM_STATUS_OK) {
3008d62bc4baSyz147064 			die_dlerr(state.ls_status, "failed to show link %s",
3009d62bc4baSyz147064 			    argv[optind]);
3010d62bc4baSyz147064 		}
30117c478bd9Sstevel@tonic-gate 	}
30128002d411SSowmini Varadhan 	ofmt_close(ofmt);
3013210db224Sericheng }
30147c478bd9Sstevel@tonic-gate 
30157c478bd9Sstevel@tonic-gate static void
30168d5c46e6Sam223141 do_show_aggr(int argc, char *argv[], const char *use)
30177c478bd9Sstevel@tonic-gate {
30187c478bd9Sstevel@tonic-gate 	boolean_t		L_arg = B_FALSE;
30197c478bd9Sstevel@tonic-gate 	boolean_t		s_arg = B_FALSE;
30207c478bd9Sstevel@tonic-gate 	boolean_t		i_arg = B_FALSE;
3021d62bc4baSyz147064 	boolean_t		p_arg = B_FALSE;
3022d62bc4baSyz147064 	boolean_t		x_arg = B_FALSE;
30237c478bd9Sstevel@tonic-gate 	show_grp_state_t	state;
3024d62bc4baSyz147064 	uint32_t		flags = DLADM_OPT_ACTIVE;
3025d62bc4baSyz147064 	datalink_id_t		linkid = DATALINK_ALL_LINKID;
3026d62bc4baSyz147064 	int			option;
302763a6526dSMichael Lim 	uint32_t		interval = 0;
3028d62bc4baSyz147064 	int			key;
3029d62bc4baSyz147064 	dladm_status_t		status;
3030e7801d59Ssowmini 	boolean_t		o_arg = B_FALSE;
3031e7801d59Ssowmini 	char			*fields_str = NULL;
3032e7801d59Ssowmini 	char			*all_fields =
3033e7801d59Ssowmini 	    "link,policy,addrpolicy,lacpactivity,lacptimer,flags";
3034e7801d59Ssowmini 	char			*all_lacp_fields =
3035e7801d59Ssowmini 	    "link,port,aggregatable,sync,coll,dist,defaulted,expired";
3036e7801d59Ssowmini 	char			*all_stats_fields =
3037e7801d59Ssowmini 	    "link,port,ipackets,rbytes,opackets,obytes,ipktdist,opktdist";
3038e7801d59Ssowmini 	char			*all_extended_fields =
3039e7801d59Ssowmini 	    "link,port,speed,duplex,state,address,portstate";
30408002d411SSowmini Varadhan 	ofmt_field_t		*pf;
30418002d411SSowmini Varadhan 	ofmt_handle_t		ofmt;
30428002d411SSowmini Varadhan 	ofmt_status_t		oferr;
30438002d411SSowmini Varadhan 	uint_t			ofmtflags = 0;
3044e7801d59Ssowmini 
30457c478bd9Sstevel@tonic-gate 	opterr = 0;
3046e7801d59Ssowmini 	while ((option = getopt_long(argc, argv, ":LpPxsi:o:",
3047d62bc4baSyz147064 	    show_lopts, NULL)) != -1) {
30487c478bd9Sstevel@tonic-gate 		switch (option) {
30497c478bd9Sstevel@tonic-gate 		case 'L':
305033343a97Smeem 			if (L_arg)
305133343a97Smeem 				die_optdup(option);
30527c478bd9Sstevel@tonic-gate 
30537c478bd9Sstevel@tonic-gate 			L_arg = B_TRUE;
30547c478bd9Sstevel@tonic-gate 			break;
30557c478bd9Sstevel@tonic-gate 		case 'p':
3056d62bc4baSyz147064 			if (p_arg)
3057d62bc4baSyz147064 				die_optdup(option);
3058d62bc4baSyz147064 
3059d62bc4baSyz147064 			p_arg = B_TRUE;
3060d62bc4baSyz147064 			break;
3061d62bc4baSyz147064 		case 'x':
3062d62bc4baSyz147064 			if (x_arg)
3063d62bc4baSyz147064 				die_optdup(option);
3064d62bc4baSyz147064 
3065d62bc4baSyz147064 			x_arg = B_TRUE;
3066d62bc4baSyz147064 			break;
3067d62bc4baSyz147064 		case 'P':
3068d62bc4baSyz147064 			if (flags != DLADM_OPT_ACTIVE)
3069d62bc4baSyz147064 				die_optdup(option);
3070d62bc4baSyz147064 
3071d62bc4baSyz147064 			flags = DLADM_OPT_PERSIST;
30727c478bd9Sstevel@tonic-gate 			break;
30737c478bd9Sstevel@tonic-gate 		case 's':
307433343a97Smeem 			if (s_arg)
307533343a97Smeem 				die_optdup(option);
30767c478bd9Sstevel@tonic-gate 
30777c478bd9Sstevel@tonic-gate 			s_arg = B_TRUE;
30787c478bd9Sstevel@tonic-gate 			break;
3079e7801d59Ssowmini 		case 'o':
3080e7801d59Ssowmini 			o_arg = B_TRUE;
3081e7801d59Ssowmini 			fields_str = optarg;
3082e7801d59Ssowmini 			break;
30837c478bd9Sstevel@tonic-gate 		case 'i':
308433343a97Smeem 			if (i_arg)
308533343a97Smeem 				die_optdup(option);
30867c478bd9Sstevel@tonic-gate 
30877c478bd9Sstevel@tonic-gate 			i_arg = B_TRUE;
308863a6526dSMichael Lim 			if (!dladm_str2interval(optarg, &interval))
308933343a97Smeem 				die("invalid interval value '%s'", optarg);
30907c478bd9Sstevel@tonic-gate 			break;
30917c478bd9Sstevel@tonic-gate 		default:
30928d5c46e6Sam223141 			die_opterr(optopt, option, use);
309333343a97Smeem 			break;
30947c478bd9Sstevel@tonic-gate 		}
30957c478bd9Sstevel@tonic-gate 	}
30967c478bd9Sstevel@tonic-gate 
30970d365605Sschuster 	if (p_arg && !o_arg)
30980d365605Sschuster 		die("-p requires -o");
30990d365605Sschuster 
31000d365605Sschuster 	if (p_arg && strcasecmp(fields_str, "all") == 0)
31010d365605Sschuster 		die("\"-o all\" is invalid with -p");
31020d365605Sschuster 
310333343a97Smeem 	if (i_arg && !s_arg)
310433343a97Smeem 		die("the option -i can be used only with -s");
31057c478bd9Sstevel@tonic-gate 
3106d62bc4baSyz147064 	if (s_arg && (L_arg || p_arg || x_arg || flags != DLADM_OPT_ACTIVE)) {
3107d62bc4baSyz147064 		die("the option -%c cannot be used with -s",
3108d62bc4baSyz147064 		    L_arg ? 'L' : (p_arg ? 'p' : (x_arg ? 'x' : 'P')));
3109d62bc4baSyz147064 	}
3110d62bc4baSyz147064 
3111d62bc4baSyz147064 	if (L_arg && flags != DLADM_OPT_ACTIVE)
3112d62bc4baSyz147064 		die("the option -P cannot be used with -L");
3113d62bc4baSyz147064 
3114d62bc4baSyz147064 	if (x_arg && (L_arg || flags != DLADM_OPT_ACTIVE))
3115d62bc4baSyz147064 		die("the option -%c cannot be used with -x", L_arg ? 'L' : 'P');
3116d62bc4baSyz147064 
3117d62bc4baSyz147064 	/* get aggregation key or aggrname (optional last argument) */
31187c478bd9Sstevel@tonic-gate 	if (optind == (argc-1)) {
3119d62bc4baSyz147064 		if (!str2int(argv[optind], &key)) {
31204ac67f02SAnurag S. Maskey 			status = dladm_name2info(handle, argv[optind],
31214ac67f02SAnurag S. Maskey 			    &linkid, NULL, NULL, NULL);
3122d62bc4baSyz147064 		} else {
31234ac67f02SAnurag S. Maskey 			status = dladm_key2linkid(handle, (uint16_t)key,
3124d62bc4baSyz147064 			    &linkid, DLADM_OPT_ACTIVE);
3125d62bc4baSyz147064 		}
3126d62bc4baSyz147064 
3127d62bc4baSyz147064 		if (status != DLADM_STATUS_OK)
3128d62bc4baSyz147064 			die("non-existent aggregation '%s'", argv[optind]);
3129d62bc4baSyz147064 
31307c478bd9Sstevel@tonic-gate 	} else if (optind != argc) {
31317c478bd9Sstevel@tonic-gate 		usage();
31327c478bd9Sstevel@tonic-gate 	}
31337c478bd9Sstevel@tonic-gate 
3134d62bc4baSyz147064 	bzero(&state, sizeof (state));
3135d62bc4baSyz147064 	state.gs_lacp = L_arg;
3136d62bc4baSyz147064 	state.gs_stats = s_arg;
3137d62bc4baSyz147064 	state.gs_flags = flags;
31388002d411SSowmini Varadhan 	state.gs_parsable = p_arg;
3139d62bc4baSyz147064 	state.gs_extended = x_arg;
3140d62bc4baSyz147064 
3141e7801d59Ssowmini 	if (!o_arg || (o_arg && strcasecmp(fields_str, "all") == 0)) {
3142e7801d59Ssowmini 		if (state.gs_lacp)
3143e7801d59Ssowmini 			fields_str = all_lacp_fields;
3144e7801d59Ssowmini 		else if (state.gs_stats)
3145e7801d59Ssowmini 			fields_str = all_stats_fields;
3146e7801d59Ssowmini 		else if (state.gs_extended)
3147e7801d59Ssowmini 			fields_str = all_extended_fields;
3148e7801d59Ssowmini 		else
3149e7801d59Ssowmini 			fields_str = all_fields;
3150e7801d59Ssowmini 	}
3151e7801d59Ssowmini 
3152e7801d59Ssowmini 	if (state.gs_lacp) {
3153e7801d59Ssowmini 		pf = aggr_l_fields;
3154e7801d59Ssowmini 	} else if (state.gs_stats) {
3155e7801d59Ssowmini 		pf = aggr_s_fields;
3156e7801d59Ssowmini 	} else if (state.gs_extended) {
3157e7801d59Ssowmini 		pf = aggr_x_fields;
3158e7801d59Ssowmini 	} else {
3159e7801d59Ssowmini 		pf = laggr_fields;
3160e7801d59Ssowmini 	}
3161e7801d59Ssowmini 
31628002d411SSowmini Varadhan 	if (state.gs_parsable)
31638002d411SSowmini Varadhan 		ofmtflags |= OFMT_PARSABLE;
31648002d411SSowmini Varadhan 	oferr = ofmt_open(fields_str, pf, ofmtflags, 0, &ofmt);
31658002d411SSowmini Varadhan 	dladm_ofmt_check(oferr, state.gs_parsable, ofmt);
31668002d411SSowmini Varadhan 	state.gs_ofmt = ofmt;
3167e7801d59Ssowmini 
31687c478bd9Sstevel@tonic-gate 	if (s_arg) {
3169d62bc4baSyz147064 		aggr_stats(linkid, &state, interval);
31708002d411SSowmini Varadhan 		ofmt_close(ofmt);
31717c478bd9Sstevel@tonic-gate 		return;
31727c478bd9Sstevel@tonic-gate 	}
31737c478bd9Sstevel@tonic-gate 
3174d62bc4baSyz147064 	if (linkid == DATALINK_ALL_LINKID) {
31754ac67f02SAnurag S. Maskey 		(void) dladm_walk_datalink_id(show_aggr, handle, &state,
3176d62bc4baSyz147064 		    DATALINK_CLASS_AGGR, DATALINK_ANY_MEDIATYPE, flags);
3177d62bc4baSyz147064 	} else {
31784ac67f02SAnurag S. Maskey 		(void) show_aggr(handle, linkid, &state);
3179d62bc4baSyz147064 		if (state.gs_status != DLADM_STATUS_OK) {
3180d62bc4baSyz147064 			die_dlerr(state.gs_status, "failed to show aggr %s",
3181d62bc4baSyz147064 			    argv[optind]);
3182d62bc4baSyz147064 		}
3183d62bc4baSyz147064 	}
31848002d411SSowmini Varadhan 	ofmt_close(ofmt);
31857c478bd9Sstevel@tonic-gate }
31867c478bd9Sstevel@tonic-gate 
3187da14cebeSEric Cheng static dladm_status_t
3188da14cebeSEric Cheng print_phys_default(show_state_t *state, datalink_id_t linkid,
3189da14cebeSEric Cheng     const char *link, uint32_t flags, uint32_t media)
31907c478bd9Sstevel@tonic-gate {
3191da14cebeSEric Cheng 	dladm_phys_attr_t dpa;
3192da14cebeSEric Cheng 	dladm_status_t status;
3193da14cebeSEric Cheng 	link_fields_buf_t pattr;
3194e7801d59Ssowmini 
31954ac67f02SAnurag S. Maskey 	status = dladm_phys_info(handle, linkid, &dpa, state->ls_flags);
3196da14cebeSEric Cheng 	if (status != DLADM_STATUS_OK)
3197da14cebeSEric Cheng 		goto done;
31987c478bd9Sstevel@tonic-gate 
3199da14cebeSEric Cheng 	(void) snprintf(pattr.link_phys_device,
3200da14cebeSEric Cheng 	    sizeof (pattr.link_phys_device), "%s", dpa.dp_dev);
3201da14cebeSEric Cheng 	(void) dladm_media2str(media, pattr.link_phys_media);
3202da14cebeSEric Cheng 	if (state->ls_flags == DLADM_OPT_ACTIVE) {
3203da14cebeSEric Cheng 		boolean_t	islink;
3204d62bc4baSyz147064 
3205da14cebeSEric Cheng 		if (!dpa.dp_novanity) {
3206da14cebeSEric Cheng 			(void) strlcpy(pattr.link_name, link,
3207da14cebeSEric Cheng 			    sizeof (pattr.link_name));
3208da14cebeSEric Cheng 			islink = B_TRUE;
3209d62bc4baSyz147064 		} else {
3210da14cebeSEric Cheng 			/*
3211da14cebeSEric Cheng 			 * This is a physical link that does not have
3212da14cebeSEric Cheng 			 * vanity naming support.
3213da14cebeSEric Cheng 			 */
3214da14cebeSEric Cheng 			(void) strlcpy(pattr.link_name, dpa.dp_dev,
3215da14cebeSEric Cheng 			    sizeof (pattr.link_name));
3216da14cebeSEric Cheng 			islink = B_FALSE;
32177c478bd9Sstevel@tonic-gate 		}
32187c478bd9Sstevel@tonic-gate 
3219da14cebeSEric Cheng 		(void) get_linkstate(pattr.link_name, islink,
3220da14cebeSEric Cheng 		    pattr.link_phys_state);
3221da14cebeSEric Cheng 		(void) snprintf(pattr.link_phys_speed,
3222da14cebeSEric Cheng 		    sizeof (pattr.link_phys_speed), "%u",
3223da14cebeSEric Cheng 		    (uint_t)((get_ifspeed(pattr.link_name,
3224da14cebeSEric Cheng 		    islink)) / 1000000ull));
3225da14cebeSEric Cheng 		(void) get_linkduplex(pattr.link_name, islink,
3226da14cebeSEric Cheng 		    pattr.link_phys_duplex);
3227da14cebeSEric Cheng 	} else {
3228da14cebeSEric Cheng 		(void) snprintf(pattr.link_name, sizeof (pattr.link_name),
3229da14cebeSEric Cheng 		    "%s", link);
3230da14cebeSEric Cheng 		(void) snprintf(pattr.link_flags, sizeof (pattr.link_flags),
3231da14cebeSEric Cheng 		    "%c----", flags & DLADM_OPT_ACTIVE ? '-' : 'r');
3232da14cebeSEric Cheng 	}
3233da14cebeSEric Cheng 
32348002d411SSowmini Varadhan 	ofmt_print(state->ls_ofmt, &pattr);
3235da14cebeSEric Cheng 
3236da14cebeSEric Cheng done:
3237da14cebeSEric Cheng 	return (status);
3238da14cebeSEric Cheng }
3239da14cebeSEric Cheng 
3240da14cebeSEric Cheng typedef struct {
3241da14cebeSEric Cheng 	show_state_t	*ms_state;
3242da14cebeSEric Cheng 	char		*ms_link;
3243da14cebeSEric Cheng 	dladm_macaddr_attr_t *ms_mac_attr;
3244da14cebeSEric Cheng } print_phys_mac_state_t;
3245da14cebeSEric Cheng 
32468002d411SSowmini Varadhan /*
32478002d411SSowmini Varadhan  *  callback for ofmt_print()
32488002d411SSowmini Varadhan  */
32498002d411SSowmini Varadhan static boolean_t
32508002d411SSowmini Varadhan print_phys_one_mac_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize)
3251da14cebeSEric Cheng {
32528002d411SSowmini Varadhan 	print_phys_mac_state_t *mac_state = ofarg->ofmt_cbarg;
3253da14cebeSEric Cheng 	dladm_macaddr_attr_t *attr = mac_state->ms_mac_attr;
3254da14cebeSEric Cheng 	boolean_t is_primary = (attr->ma_slot == 0);
32558002d411SSowmini Varadhan 	boolean_t is_parsable = mac_state->ms_state->ls_parsable;
3256da14cebeSEric Cheng 
32578002d411SSowmini Varadhan 	switch (ofarg->ofmt_id) {
3258da14cebeSEric Cheng 	case PHYS_M_LINK:
32598002d411SSowmini Varadhan 		(void) snprintf(buf, bufsize, "%s",
32608002d411SSowmini Varadhan 		    (is_primary || is_parsable) ? mac_state->ms_link : " ");
3261da14cebeSEric Cheng 		break;
3262da14cebeSEric Cheng 	case PHYS_M_SLOT:
3263da14cebeSEric Cheng 		if (is_primary)
32648002d411SSowmini Varadhan 			(void) snprintf(buf, bufsize, gettext("primary"));
3265da14cebeSEric Cheng 		else
32668002d411SSowmini Varadhan 			(void) snprintf(buf, bufsize, "%d", attr->ma_slot);
3267da14cebeSEric Cheng 		break;
3268da14cebeSEric Cheng 	case PHYS_M_ADDRESS:
3269da14cebeSEric Cheng 		(void) dladm_aggr_macaddr2str(attr->ma_addr, buf);
3270da14cebeSEric Cheng 		break;
3271da14cebeSEric Cheng 	case PHYS_M_INUSE:
32728002d411SSowmini Varadhan 		(void) snprintf(buf, bufsize, "%s",
3273da14cebeSEric Cheng 		    attr->ma_flags & DLADM_MACADDR_USED ? gettext("yes") :
3274da14cebeSEric Cheng 		    gettext("no"));
3275da14cebeSEric Cheng 		break;
3276da14cebeSEric Cheng 	case PHYS_M_CLIENT:
3277da14cebeSEric Cheng 		/*
3278da14cebeSEric Cheng 		 * CR 6678526: resolve link id to actual link name if
3279da14cebeSEric Cheng 		 * it is valid.
3280da14cebeSEric Cheng 		 */
32818002d411SSowmini Varadhan 		(void) snprintf(buf, bufsize, "%s", attr->ma_client_name);
3282da14cebeSEric Cheng 		break;
3283da14cebeSEric Cheng 	}
3284da14cebeSEric Cheng 
32858002d411SSowmini Varadhan 	return (B_TRUE);
3286da14cebeSEric Cheng }
3287da14cebeSEric Cheng 
3288da14cebeSEric Cheng typedef struct {
3289da14cebeSEric Cheng 	show_state_t	*hs_state;
3290da14cebeSEric Cheng 	char		*hs_link;
3291da14cebeSEric Cheng 	dladm_hwgrp_attr_t *hs_grp_attr;
3292da14cebeSEric Cheng } print_phys_hwgrp_state_t;
3293da14cebeSEric Cheng 
32948002d411SSowmini Varadhan static boolean_t
32958002d411SSowmini Varadhan print_phys_one_hwgrp_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize)
3296da14cebeSEric Cheng {
32978002d411SSowmini Varadhan 	print_phys_hwgrp_state_t *hg_state = ofarg->ofmt_cbarg;
3298da14cebeSEric Cheng 	dladm_hwgrp_attr_t *attr = hg_state->hs_grp_attr;
3299da14cebeSEric Cheng 
33008002d411SSowmini Varadhan 	switch (ofarg->ofmt_id) {
3301da14cebeSEric Cheng 	case PHYS_H_LINK:
33028002d411SSowmini Varadhan 		(void) snprintf(buf, bufsize, "%s", attr->hg_link_name);
3303da14cebeSEric Cheng 		break;
3304da14cebeSEric Cheng 	case PHYS_H_GROUP:
33058002d411SSowmini Varadhan 		(void) snprintf(buf, bufsize, "%d", attr->hg_grp_num);
3306da14cebeSEric Cheng 		break;
3307da14cebeSEric Cheng 	case PHYS_H_GRPTYPE:
33088002d411SSowmini Varadhan 		(void) snprintf(buf, bufsize, "%s",
3309da14cebeSEric Cheng 		    attr->hg_grp_type == DLADM_HWGRP_TYPE_RX ? "RX" : "TX");
3310da14cebeSEric Cheng 		break;
3311da14cebeSEric Cheng 	case PHYS_H_RINGS:
33128002d411SSowmini Varadhan 		(void) snprintf(buf, bufsize, "%d", attr->hg_n_rings);
3313da14cebeSEric Cheng 		break;
3314da14cebeSEric Cheng 	case PHYS_H_CLIENTS:
3315da14cebeSEric Cheng 		if (attr->hg_client_names[0] == '\0') {
33168002d411SSowmini Varadhan 			(void) snprintf(buf, bufsize, "--");
3317da14cebeSEric Cheng 		} else {
33188002d411SSowmini Varadhan 			(void) snprintf(buf, bufsize, "%s ",
3319da14cebeSEric Cheng 			    attr->hg_client_names);
3320da14cebeSEric Cheng 		}
3321da14cebeSEric Cheng 		break;
3322da14cebeSEric Cheng 	}
3323da14cebeSEric Cheng 
33248002d411SSowmini Varadhan 	return (B_TRUE);
3325da14cebeSEric Cheng }
3326da14cebeSEric Cheng 
33278002d411SSowmini Varadhan /*
33288002d411SSowmini Varadhan  * callback for dladm_walk_macaddr, invoked for each MAC address slot
33298002d411SSowmini Varadhan  */
3330da14cebeSEric Cheng static boolean_t
3331da14cebeSEric Cheng print_phys_mac_callback(void *arg, dladm_macaddr_attr_t *attr)
3332da14cebeSEric Cheng {
3333da14cebeSEric Cheng 	print_phys_mac_state_t *mac_state = arg;
3334da14cebeSEric Cheng 	show_state_t *state = mac_state->ms_state;
3335da14cebeSEric Cheng 
3336da14cebeSEric Cheng 	mac_state->ms_mac_attr = attr;
33378002d411SSowmini Varadhan 	ofmt_print(state->ls_ofmt, mac_state);
3338da14cebeSEric Cheng 
3339da14cebeSEric Cheng 	return (B_TRUE);
3340da14cebeSEric Cheng }
3341da14cebeSEric Cheng 
33428002d411SSowmini Varadhan /*
33438002d411SSowmini Varadhan  * invoked by show-phys -m for each physical data-link
33448002d411SSowmini Varadhan  */
3345da14cebeSEric Cheng static dladm_status_t
3346da14cebeSEric Cheng print_phys_mac(show_state_t *state, datalink_id_t linkid, char *link)
3347da14cebeSEric Cheng {
3348da14cebeSEric Cheng 	print_phys_mac_state_t mac_state;
3349da14cebeSEric Cheng 
3350da14cebeSEric Cheng 	mac_state.ms_state = state;
3351da14cebeSEric Cheng 	mac_state.ms_link = link;
3352da14cebeSEric Cheng 
33534ac67f02SAnurag S. Maskey 	return (dladm_walk_macaddr(handle, linkid, &mac_state,
3354da14cebeSEric Cheng 	    print_phys_mac_callback));
3355da14cebeSEric Cheng }
3356da14cebeSEric Cheng 
33578002d411SSowmini Varadhan /*
33588002d411SSowmini Varadhan  * callback for dladm_walk_hwgrp, invoked for each MAC hwgrp
33598002d411SSowmini Varadhan  */
3360da14cebeSEric Cheng static boolean_t
3361da14cebeSEric Cheng print_phys_hwgrp_callback(void *arg, dladm_hwgrp_attr_t *attr)
3362da14cebeSEric Cheng {
3363da14cebeSEric Cheng 	print_phys_hwgrp_state_t *hwgrp_state = arg;
3364da14cebeSEric Cheng 	show_state_t *state = hwgrp_state->hs_state;
3365da14cebeSEric Cheng 
3366da14cebeSEric Cheng 	hwgrp_state->hs_grp_attr = attr;
33678002d411SSowmini Varadhan 	ofmt_print(state->ls_ofmt, hwgrp_state);
3368da14cebeSEric Cheng 
3369da14cebeSEric Cheng 	return (B_TRUE);
3370da14cebeSEric Cheng }
3371da14cebeSEric Cheng 
3372da14cebeSEric Cheng /* invoked by show-phys -H for each physical data-link */
3373da14cebeSEric Cheng static dladm_status_t
3374da14cebeSEric Cheng print_phys_hwgrp(show_state_t *state, datalink_id_t linkid, char *link)
3375da14cebeSEric Cheng {
3376da14cebeSEric Cheng 	print_phys_hwgrp_state_t hwgrp_state;
3377da14cebeSEric Cheng 
3378da14cebeSEric Cheng 	hwgrp_state.hs_state = state;
3379da14cebeSEric Cheng 	hwgrp_state.hs_link = link;
33804ac67f02SAnurag S. Maskey 	return (dladm_walk_hwgrp(handle, linkid, &hwgrp_state,
3381da14cebeSEric Cheng 	    print_phys_hwgrp_callback));
3382da14cebeSEric Cheng }
3383d62bc4baSyz147064 
3384d62bc4baSyz147064 static dladm_status_t
3385da14cebeSEric Cheng print_phys(show_state_t *state, datalink_id_t linkid)
3386d62bc4baSyz147064 {
3387d62bc4baSyz147064 	char			link[MAXLINKNAMELEN];
3388d62bc4baSyz147064 	uint32_t		flags;
3389da14cebeSEric Cheng 	dladm_status_t		status;
3390d62bc4baSyz147064 	datalink_class_t	class;
3391d62bc4baSyz147064 	uint32_t		media;
3392d62bc4baSyz147064 
33934ac67f02SAnurag S. Maskey 	if ((status = dladm_datalink_id2info(handle, linkid, &flags, &class,
33944ac67f02SAnurag S. Maskey 	    &media, link, MAXLINKNAMELEN)) != DLADM_STATUS_OK) {
3395d62bc4baSyz147064 		goto done;
3396d62bc4baSyz147064 	}
3397d62bc4baSyz147064 
3398d62bc4baSyz147064 	if (class != DATALINK_CLASS_PHYS) {
3399d62bc4baSyz147064 		status = DLADM_STATUS_BADARG;
3400d62bc4baSyz147064 		goto done;
3401d62bc4baSyz147064 	}
3402d62bc4baSyz147064 
3403d62bc4baSyz147064 	if (!(state->ls_flags & flags)) {
3404d62bc4baSyz147064 		status = DLADM_STATUS_NOTFOUND;
3405d62bc4baSyz147064 		goto done;
3406d62bc4baSyz147064 	}
3407d62bc4baSyz147064 
3408da14cebeSEric Cheng 	if (state->ls_mac)
3409da14cebeSEric Cheng 		status = print_phys_mac(state, linkid, link);
3410da14cebeSEric Cheng 	else if (state->ls_hwgrp)
3411da14cebeSEric Cheng 		status = print_phys_hwgrp(state, linkid, link);
3412da14cebeSEric Cheng 	else
3413da14cebeSEric Cheng 		status = print_phys_default(state, linkid, link, flags, media);
3414d62bc4baSyz147064 
3415d62bc4baSyz147064 done:
3416d62bc4baSyz147064 	return (status);
3417d62bc4baSyz147064 }
3418d62bc4baSyz147064 
34194ac67f02SAnurag S. Maskey /* ARGSUSED */
3420d62bc4baSyz147064 static int
34214ac67f02SAnurag S. Maskey show_phys(dladm_handle_t dh, datalink_id_t linkid, void *arg)
3422d62bc4baSyz147064 {
3423d62bc4baSyz147064 	show_state_t	*state = arg;
3424d62bc4baSyz147064 
3425da14cebeSEric Cheng 	state->ls_status = print_phys(state, linkid);
3426d62bc4baSyz147064 	return (DLADM_WALK_CONTINUE);
3427d62bc4baSyz147064 }
3428d62bc4baSyz147064 
3429d62bc4baSyz147064 /*
3430d62bc4baSyz147064  * Print the active topology information.
3431d62bc4baSyz147064  */
3432d62bc4baSyz147064 static dladm_status_t
3433e7801d59Ssowmini print_vlan(show_state_t *state, datalink_id_t linkid, link_fields_buf_t *l)
3434d62bc4baSyz147064 {
3435d62bc4baSyz147064 	dladm_vlan_attr_t	vinfo;
3436d62bc4baSyz147064 	uint32_t		flags;
3437d62bc4baSyz147064 	dladm_status_t		status;
3438d62bc4baSyz147064 
34394ac67f02SAnurag S. Maskey 	if ((status = dladm_datalink_id2info(handle, linkid, &flags, NULL, NULL,
3440e7801d59Ssowmini 	    l->link_name, sizeof (l->link_name))) != DLADM_STATUS_OK) {
3441d62bc4baSyz147064 		goto done;
3442d62bc4baSyz147064 	}
3443d62bc4baSyz147064 
3444d62bc4baSyz147064 	if (!(state->ls_flags & flags)) {
3445d62bc4baSyz147064 		status = DLADM_STATUS_NOTFOUND;
3446d62bc4baSyz147064 		goto done;
3447d62bc4baSyz147064 	}
3448d62bc4baSyz147064 
34494ac67f02SAnurag S. Maskey 	if ((status = dladm_vlan_info(handle, linkid, &vinfo,
34504ac67f02SAnurag S. Maskey 	    state->ls_flags)) != DLADM_STATUS_OK ||
34514ac67f02SAnurag S. Maskey 	    (status = dladm_datalink_id2info(handle, vinfo.dv_linkid, NULL,
34524ac67f02SAnurag S. Maskey 	    NULL, NULL, l->link_over, sizeof (l->link_over))) !=
34534ac67f02SAnurag S. Maskey 	    DLADM_STATUS_OK) {
3454d62bc4baSyz147064 		goto done;
3455d62bc4baSyz147064 	}
3456d62bc4baSyz147064 
3457e7801d59Ssowmini 	(void) snprintf(l->link_vlan_vid, sizeof (l->link_vlan_vid), "%d",
3458e7801d59Ssowmini 	    vinfo.dv_vid);
3459da14cebeSEric Cheng 	(void) snprintf(l->link_flags, sizeof (l->link_flags), "%c----",
3460da14cebeSEric Cheng 	    vinfo.dv_force ? 'f' : '-');
3461d62bc4baSyz147064 
3462d62bc4baSyz147064 done:
3463d62bc4baSyz147064 	return (status);
3464d62bc4baSyz147064 }
3465d62bc4baSyz147064 
34664ac67f02SAnurag S. Maskey /* ARGSUSED */
3467d62bc4baSyz147064 static int
34684ac67f02SAnurag S. Maskey show_vlan(dladm_handle_t dh, datalink_id_t linkid, void *arg)
3469d62bc4baSyz147064 {
3470d62bc4baSyz147064 	show_state_t		*state = arg;
3471d62bc4baSyz147064 	dladm_status_t		status;
3472e7801d59Ssowmini 	link_fields_buf_t	lbuf;
3473d62bc4baSyz147064 
34745f5c9f54SAnurag S. Maskey 	bzero(&lbuf, sizeof (link_fields_buf_t));
3475e7801d59Ssowmini 	status = print_vlan(state, linkid, &lbuf);
3476d62bc4baSyz147064 	if (status != DLADM_STATUS_OK)
3477d62bc4baSyz147064 		goto done;
3478e7801d59Ssowmini 
34798002d411SSowmini Varadhan 	ofmt_print(state->ls_ofmt, &lbuf);
3480d62bc4baSyz147064 
3481d62bc4baSyz147064 done:
3482d62bc4baSyz147064 	state->ls_status = status;
3483d62bc4baSyz147064 	return (DLADM_WALK_CONTINUE);
3484d62bc4baSyz147064 }
3485d62bc4baSyz147064 
3486d62bc4baSyz147064 static void
34878d5c46e6Sam223141 do_show_phys(int argc, char *argv[], const char *use)
3488d62bc4baSyz147064 {
3489d62bc4baSyz147064 	int		option;
3490d62bc4baSyz147064 	uint32_t	flags = DLADM_OPT_ACTIVE;
3491d62bc4baSyz147064 	boolean_t	p_arg = B_FALSE;
3492e7801d59Ssowmini 	boolean_t	o_arg = B_FALSE;
3493da14cebeSEric Cheng 	boolean_t	m_arg = B_FALSE;
3494da14cebeSEric Cheng 	boolean_t	H_arg = B_FALSE;
3495d62bc4baSyz147064 	datalink_id_t	linkid = DATALINK_ALL_LINKID;
3496d62bc4baSyz147064 	show_state_t	state;
3497d62bc4baSyz147064 	dladm_status_t	status;
3498e7801d59Ssowmini 	char		*fields_str = NULL;
3499e7801d59Ssowmini 	char		*all_active_fields =
3500e7801d59Ssowmini 	    "link,media,state,speed,duplex,device";
35015f5c9f54SAnurag S. Maskey 	char		*all_inactive_fields = "link,device,media,flags";
3502da14cebeSEric Cheng 	char		*all_mac_fields = "link,slot,address,inuse,client";
3503da14cebeSEric Cheng 	char		*all_hwgrp_fields =
3504da14cebeSEric Cheng 	    "link,group,grouptype,rings,clients";
35058002d411SSowmini Varadhan 	ofmt_field_t	*pf;
35068002d411SSowmini Varadhan 	ofmt_handle_t	ofmt;
35078002d411SSowmini Varadhan 	ofmt_status_t	oferr;
35088002d411SSowmini Varadhan 	uint_t		ofmtflags = 0;
3509d62bc4baSyz147064 
3510e7801d59Ssowmini 	bzero(&state, sizeof (state));
3511d62bc4baSyz147064 	opterr = 0;
3512da14cebeSEric Cheng 	while ((option = getopt_long(argc, argv, ":pPo:mH",
3513d62bc4baSyz147064 	    show_lopts, NULL)) != -1) {
3514d62bc4baSyz147064 		switch (option) {
3515d62bc4baSyz147064 		case 'p':
3516d62bc4baSyz147064 			if (p_arg)
3517d62bc4baSyz147064 				die_optdup(option);
3518d62bc4baSyz147064 
3519d62bc4baSyz147064 			p_arg = B_TRUE;
3520d62bc4baSyz147064 			break;
3521d62bc4baSyz147064 		case 'P':
3522d62bc4baSyz147064 			if (flags != DLADM_OPT_ACTIVE)
3523d62bc4baSyz147064 				die_optdup(option);
3524d62bc4baSyz147064 
3525d62bc4baSyz147064 			flags = DLADM_OPT_PERSIST;
3526d62bc4baSyz147064 			break;
3527e7801d59Ssowmini 		case 'o':
3528e7801d59Ssowmini 			o_arg = B_TRUE;
3529e7801d59Ssowmini 			fields_str = optarg;
3530e7801d59Ssowmini 			break;
3531da14cebeSEric Cheng 		case 'm':
3532da14cebeSEric Cheng 			m_arg = B_TRUE;
3533da14cebeSEric Cheng 			break;
3534da14cebeSEric Cheng 		case 'H':
3535da14cebeSEric Cheng 			H_arg = B_TRUE;
3536da14cebeSEric Cheng 			break;
3537d62bc4baSyz147064 		default:
35388d5c46e6Sam223141 			die_opterr(optopt, option, use);
3539d62bc4baSyz147064 			break;
3540d62bc4baSyz147064 		}
3541d62bc4baSyz147064 	}
3542d62bc4baSyz147064 
35430d365605Sschuster 	if (p_arg && !o_arg)
35440d365605Sschuster 		die("-p requires -o");
35450d365605Sschuster 
3546da14cebeSEric Cheng 	if (m_arg && H_arg)
3547da14cebeSEric Cheng 		die("-m cannot combine with -H");
3548da14cebeSEric Cheng 
35490d365605Sschuster 	if (p_arg && strcasecmp(fields_str, "all") == 0)
35500d365605Sschuster 		die("\"-o all\" is invalid with -p");
35510d365605Sschuster 
3552d62bc4baSyz147064 	/* get link name (optional last argument) */
3553d62bc4baSyz147064 	if (optind == (argc-1)) {
35544ac67f02SAnurag S. Maskey 		if ((status = dladm_name2info(handle, argv[optind], &linkid,
35554ac67f02SAnurag S. Maskey 		    NULL, NULL, NULL)) != DLADM_STATUS_OK) {
3556d62bc4baSyz147064 			die_dlerr(status, "link %s is not valid", argv[optind]);
3557d62bc4baSyz147064 		}
3558d62bc4baSyz147064 	} else if (optind != argc) {
3559d62bc4baSyz147064 		usage();
3560d62bc4baSyz147064 	}
3561d62bc4baSyz147064 
35628002d411SSowmini Varadhan 	state.ls_parsable = p_arg;
3563d62bc4baSyz147064 	state.ls_flags = flags;
3564d62bc4baSyz147064 	state.ls_donefirst = B_FALSE;
3565da14cebeSEric Cheng 	state.ls_mac = m_arg;
3566da14cebeSEric Cheng 	state.ls_hwgrp = H_arg;
3567d62bc4baSyz147064 
3568da14cebeSEric Cheng 	if (m_arg && !(flags & DLADM_OPT_ACTIVE)) {
3569da14cebeSEric Cheng 		/*
3570da14cebeSEric Cheng 		 * We can only display the factory MAC addresses of
3571da14cebeSEric Cheng 		 * active data-links.
3572da14cebeSEric Cheng 		 */
3573da14cebeSEric Cheng 		die("-m not compatible with -P");
3574e7801d59Ssowmini 	}
3575e7801d59Ssowmini 
3576da14cebeSEric Cheng 	if (!o_arg || (o_arg && strcasecmp(fields_str, "all") == 0)) {
3577da14cebeSEric Cheng 		if (state.ls_mac)
3578da14cebeSEric Cheng 			fields_str = all_mac_fields;
3579da14cebeSEric Cheng 		else if (state.ls_hwgrp)
3580da14cebeSEric Cheng 			fields_str = all_hwgrp_fields;
3581da14cebeSEric Cheng 		else if (state.ls_flags & DLADM_OPT_ACTIVE) {
3582da14cebeSEric Cheng 			fields_str = all_active_fields;
3583da14cebeSEric Cheng 		} else {
3584da14cebeSEric Cheng 			fields_str = all_inactive_fields;
3585da14cebeSEric Cheng 		}
3586da14cebeSEric Cheng 	}
3587da14cebeSEric Cheng 
3588da14cebeSEric Cheng 	if (state.ls_mac) {
3589da14cebeSEric Cheng 		pf = phys_m_fields;
3590da14cebeSEric Cheng 	} else if (state.ls_hwgrp) {
3591da14cebeSEric Cheng 		pf = phys_h_fields;
3592da14cebeSEric Cheng 	} else {
3593da14cebeSEric Cheng 		pf = phys_fields;
3594da14cebeSEric Cheng 	}
3595da14cebeSEric Cheng 
35968002d411SSowmini Varadhan 	if (state.ls_parsable)
35978002d411SSowmini Varadhan 		ofmtflags |= OFMT_PARSABLE;
35988002d411SSowmini Varadhan 	oferr = ofmt_open(fields_str, pf, ofmtflags, 0, &ofmt);
35998002d411SSowmini Varadhan 	dladm_ofmt_check(oferr, state.ls_parsable, ofmt);
36008002d411SSowmini Varadhan 	state.ls_ofmt = ofmt;
3601e7801d59Ssowmini 
3602d62bc4baSyz147064 	if (linkid == DATALINK_ALL_LINKID) {
36034ac67f02SAnurag S. Maskey 		(void) dladm_walk_datalink_id(show_phys, handle, &state,
3604d62bc4baSyz147064 		    DATALINK_CLASS_PHYS, DATALINK_ANY_MEDIATYPE, flags);
3605d62bc4baSyz147064 	} else {
36064ac67f02SAnurag S. Maskey 		(void) show_phys(handle, linkid, &state);
3607d62bc4baSyz147064 		if (state.ls_status != DLADM_STATUS_OK) {
3608d62bc4baSyz147064 			die_dlerr(state.ls_status,
3609d62bc4baSyz147064 			    "failed to show physical link %s", argv[optind]);
3610d62bc4baSyz147064 		}
3611d62bc4baSyz147064 	}
36128002d411SSowmini Varadhan 	ofmt_close(ofmt);
3613d62bc4baSyz147064 }
3614d62bc4baSyz147064 
3615d62bc4baSyz147064 static void
36168d5c46e6Sam223141 do_show_vlan(int argc, char *argv[], const char *use)
3617d62bc4baSyz147064 {
3618d62bc4baSyz147064 	int		option;
3619d62bc4baSyz147064 	uint32_t	flags = DLADM_OPT_ACTIVE;
3620d62bc4baSyz147064 	boolean_t	p_arg = B_FALSE;
3621d62bc4baSyz147064 	datalink_id_t	linkid = DATALINK_ALL_LINKID;
3622d62bc4baSyz147064 	show_state_t	state;
3623d62bc4baSyz147064 	dladm_status_t	status;
3624e7801d59Ssowmini 	boolean_t	o_arg = B_FALSE;
3625e7801d59Ssowmini 	char		*fields_str = NULL;
36268002d411SSowmini Varadhan 	ofmt_handle_t	ofmt;
36278002d411SSowmini Varadhan 	ofmt_status_t	oferr;
36288002d411SSowmini Varadhan 	uint_t		ofmtflags = 0;
3629e7801d59Ssowmini 
3630e7801d59Ssowmini 	bzero(&state, sizeof (state));
3631d62bc4baSyz147064 
3632d62bc4baSyz147064 	opterr = 0;
3633e7801d59Ssowmini 	while ((option = getopt_long(argc, argv, ":pPo:",
3634d62bc4baSyz147064 	    show_lopts, NULL)) != -1) {
3635d62bc4baSyz147064 		switch (option) {
3636d62bc4baSyz147064 		case 'p':
3637d62bc4baSyz147064 			if (p_arg)
3638d62bc4baSyz147064 				die_optdup(option);
3639d62bc4baSyz147064 
3640d62bc4baSyz147064 			p_arg = B_TRUE;
3641d62bc4baSyz147064 			break;
3642d62bc4baSyz147064 		case 'P':
3643d62bc4baSyz147064 			if (flags != DLADM_OPT_ACTIVE)
3644d62bc4baSyz147064 				die_optdup(option);
3645d62bc4baSyz147064 
3646d62bc4baSyz147064 			flags = DLADM_OPT_PERSIST;
3647d62bc4baSyz147064 			break;
3648e7801d59Ssowmini 		case 'o':
3649e7801d59Ssowmini 			o_arg = B_TRUE;
3650e7801d59Ssowmini 			fields_str = optarg;
3651e7801d59Ssowmini 			break;
3652d62bc4baSyz147064 		default:
36538d5c46e6Sam223141 			die_opterr(optopt, option, use);
3654d62bc4baSyz147064 			break;
3655d62bc4baSyz147064 		}
3656d62bc4baSyz147064 	}
3657d62bc4baSyz147064 
3658d62bc4baSyz147064 	/* get link name (optional last argument) */
3659d62bc4baSyz147064 	if (optind == (argc-1)) {
36604ac67f02SAnurag S. Maskey 		if ((status = dladm_name2info(handle, argv[optind], &linkid,
36614ac67f02SAnurag S. Maskey 		    NULL, NULL, NULL)) != DLADM_STATUS_OK) {
3662d62bc4baSyz147064 			die_dlerr(status, "link %s is not valid", argv[optind]);
3663d62bc4baSyz147064 		}
3664d62bc4baSyz147064 	} else if (optind != argc) {
3665d62bc4baSyz147064 		usage();
3666d62bc4baSyz147064 	}
3667d62bc4baSyz147064 
36688002d411SSowmini Varadhan 	state.ls_parsable = p_arg;
3669d62bc4baSyz147064 	state.ls_flags = flags;
3670d62bc4baSyz147064 	state.ls_donefirst = B_FALSE;
3671d62bc4baSyz147064 
3672e7801d59Ssowmini 	if (!o_arg || (o_arg && strcasecmp(fields_str, "all") == 0))
36738002d411SSowmini Varadhan 		fields_str = NULL;
3674e7801d59Ssowmini 
36758002d411SSowmini Varadhan 	if (state.ls_parsable)
36768002d411SSowmini Varadhan 		ofmtflags |= OFMT_PARSABLE;
36778002d411SSowmini Varadhan 	oferr = ofmt_open(fields_str, vlan_fields, ofmtflags, 0, &ofmt);
36788002d411SSowmini Varadhan 	dladm_ofmt_check(oferr, state.ls_parsable, ofmt);
36798002d411SSowmini Varadhan 	state.ls_ofmt = ofmt;
3680e7801d59Ssowmini 
3681d62bc4baSyz147064 	if (linkid == DATALINK_ALL_LINKID) {
36824ac67f02SAnurag S. Maskey 		(void) dladm_walk_datalink_id(show_vlan, handle, &state,
3683d62bc4baSyz147064 		    DATALINK_CLASS_VLAN, DATALINK_ANY_MEDIATYPE, flags);
3684d62bc4baSyz147064 	} else {
36854ac67f02SAnurag S. Maskey 		(void) show_vlan(handle, linkid, &state);
3686d62bc4baSyz147064 		if (state.ls_status != DLADM_STATUS_OK) {
3687d62bc4baSyz147064 			die_dlerr(state.ls_status, "failed to show vlan %s",
3688d62bc4baSyz147064 			    argv[optind]);
3689d62bc4baSyz147064 		}
3690d62bc4baSyz147064 	}
36918002d411SSowmini Varadhan 	ofmt_close(ofmt);
3692d62bc4baSyz147064 }
3693d62bc4baSyz147064 
3694d62bc4baSyz147064 static void
3695da14cebeSEric Cheng do_create_vnic(int argc, char *argv[], const char *use)
3696da14cebeSEric Cheng {
3697da14cebeSEric Cheng 	datalink_id_t		linkid, dev_linkid;
3698da14cebeSEric Cheng 	char			devname[MAXLINKNAMELEN];
3699da14cebeSEric Cheng 	char			name[MAXLINKNAMELEN];
3700da14cebeSEric Cheng 	boolean_t		l_arg = B_FALSE;
3701da14cebeSEric Cheng 	uint32_t		flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST;
3702da14cebeSEric Cheng 	char			*altroot = NULL;
3703b509e89bSRishi Srivatsavai 	int			option;
3704da14cebeSEric Cheng 	char			*endp = NULL;
3705da14cebeSEric Cheng 	dladm_status_t		status;
3706da14cebeSEric Cheng 	vnic_mac_addr_type_t	mac_addr_type = VNIC_MAC_ADDR_TYPE_AUTO;
3707da14cebeSEric Cheng 	uchar_t			*mac_addr;
3708da14cebeSEric Cheng 	int			mac_slot = -1, maclen = 0, mac_prefix_len = 0;
370963a6526dSMichael Lim 	char			propstr[DLADM_STRSIZE];
3710da14cebeSEric Cheng 	dladm_arg_list_t	*proplist = NULL;
3711285e94f9SMichael Lim 	int			vid = 0;
3712da14cebeSEric Cheng 
3713da14cebeSEric Cheng 	opterr = 0;
371463a6526dSMichael Lim 	bzero(propstr, DLADM_STRSIZE);
371563a6526dSMichael Lim 
3716da14cebeSEric Cheng 	while ((option = getopt_long(argc, argv, ":tfR:l:m:n:p:r:v:H",
3717da14cebeSEric Cheng 	    vnic_lopts, NULL)) != -1) {
3718da14cebeSEric Cheng 		switch (option) {
3719da14cebeSEric Cheng 		case 't':
3720da14cebeSEric Cheng 			flags &= ~DLADM_OPT_PERSIST;
3721da14cebeSEric Cheng 			break;
3722da14cebeSEric Cheng 		case 'R':
3723da14cebeSEric Cheng 			altroot = optarg;
3724da14cebeSEric Cheng 			break;
3725da14cebeSEric Cheng 		case 'l':
3726da14cebeSEric Cheng 			if (strlcpy(devname, optarg, MAXLINKNAMELEN) >=
3727da14cebeSEric Cheng 			    MAXLINKNAMELEN)
3728da14cebeSEric Cheng 				die("link name too long");
3729da14cebeSEric Cheng 			l_arg = B_TRUE;
3730da14cebeSEric Cheng 			break;
3731da14cebeSEric Cheng 		case 'm':
3732da14cebeSEric Cheng 			if (strcmp(optarg, "fixed") == 0) {
3733da14cebeSEric Cheng 				/*
3734da14cebeSEric Cheng 				 * A fixed MAC address must be specified
3735da14cebeSEric Cheng 				 * by its value, not by the keyword 'fixed'.
3736da14cebeSEric Cheng 				 */
3737da14cebeSEric Cheng 				die("'fixed' is not a valid MAC address");
3738da14cebeSEric Cheng 			}
3739da14cebeSEric Cheng 			if (dladm_vnic_str2macaddrtype(optarg,
3740da14cebeSEric Cheng 			    &mac_addr_type) != DLADM_STATUS_OK) {
3741da14cebeSEric Cheng 				mac_addr_type = VNIC_MAC_ADDR_TYPE_FIXED;
3742da14cebeSEric Cheng 				/* MAC address specified by value */
3743da14cebeSEric Cheng 				mac_addr = _link_aton(optarg, &maclen);
3744da14cebeSEric Cheng 				if (mac_addr == NULL) {
3745da14cebeSEric Cheng 					if (maclen == -1)
3746da14cebeSEric Cheng 						die("invalid MAC address");
3747da14cebeSEric Cheng 					else
3748da14cebeSEric Cheng 						die("out of memory");
3749da14cebeSEric Cheng 				}
3750da14cebeSEric Cheng 			}
3751da14cebeSEric Cheng 			break;
3752da14cebeSEric Cheng 		case 'n':
3753da14cebeSEric Cheng 			errno = 0;
3754da14cebeSEric Cheng 			mac_slot = (int)strtol(optarg, &endp, 10);
3755da14cebeSEric Cheng 			if (errno != 0 || *endp != '\0')
3756da14cebeSEric Cheng 				die("invalid slot number");
3757da14cebeSEric Cheng 			break;
3758da14cebeSEric Cheng 		case 'p':
375963a6526dSMichael Lim 			(void) strlcat(propstr, optarg, DLADM_STRSIZE);
376063a6526dSMichael Lim 			if (strlcat(propstr, ",", DLADM_STRSIZE) >=
376163a6526dSMichael Lim 			    DLADM_STRSIZE)
376263a6526dSMichael Lim 				die("property list too long '%s'", propstr);
3763da14cebeSEric Cheng 			break;
3764da14cebeSEric Cheng 		case 'r':
3765da14cebeSEric Cheng 			mac_addr = _link_aton(optarg, &mac_prefix_len);
3766da14cebeSEric Cheng 			if (mac_addr == NULL) {
3767da14cebeSEric Cheng 				if (mac_prefix_len == -1)
3768da14cebeSEric Cheng 					die("invalid MAC address");
3769da14cebeSEric Cheng 				else
3770da14cebeSEric Cheng 					die("out of memory");
3771da14cebeSEric Cheng 			}
3772da14cebeSEric Cheng 			break;
3773da14cebeSEric Cheng 		case 'v':
3774285e94f9SMichael Lim 			if (vid != 0)
3775285e94f9SMichael Lim 				die_optdup(option);
3776285e94f9SMichael Lim 
3777285e94f9SMichael Lim 			if (!str2int(optarg, &vid) || vid < 1 || vid > 4094)
3778285e94f9SMichael Lim 				die("invalid VLAN identifier '%s'", optarg);
3779285e94f9SMichael Lim 
3780da14cebeSEric Cheng 			break;
3781da14cebeSEric Cheng 		case 'f':
3782da14cebeSEric Cheng 			flags |= DLADM_OPT_FORCE;
3783da14cebeSEric Cheng 			break;
3784da14cebeSEric Cheng 		case 'H':
3785da14cebeSEric Cheng 			flags |= DLADM_OPT_HWRINGS;
3786da14cebeSEric Cheng 			break;
3787da14cebeSEric Cheng 		default:
3788da14cebeSEric Cheng 			die_opterr(optopt, option, use);
3789da14cebeSEric Cheng 		}
3790da14cebeSEric Cheng 	}
3791da14cebeSEric Cheng 
3792da14cebeSEric Cheng 	/*
3793da14cebeSEric Cheng 	 * 'f' - force, flag can be specified only with 'v' - vlan.
3794da14cebeSEric Cheng 	 */
3795da14cebeSEric Cheng 	if ((flags & DLADM_OPT_FORCE) != 0 && vid == 0)
3796da14cebeSEric Cheng 		die("-f option can only be used with -v");
3797da14cebeSEric Cheng 
3798da14cebeSEric Cheng 	if (mac_prefix_len != 0 && mac_addr_type != VNIC_MAC_ADDR_TYPE_RANDOM &&
3799da14cebeSEric Cheng 	    mac_addr_type != VNIC_MAC_ADDR_TYPE_FIXED)
3800da14cebeSEric Cheng 		usage();
3801da14cebeSEric Cheng 
3802da14cebeSEric Cheng 	/* check required options */
3803da14cebeSEric Cheng 	if (!l_arg)
3804da14cebeSEric Cheng 		usage();
3805da14cebeSEric Cheng 
3806da14cebeSEric Cheng 	if (mac_slot != -1 && mac_addr_type != VNIC_MAC_ADDR_TYPE_FACTORY)
3807da14cebeSEric Cheng 		usage();
3808da14cebeSEric Cheng 
3809da14cebeSEric Cheng 	/* the VNIC id is the required operand */
3810da14cebeSEric Cheng 	if (optind != (argc - 1))
3811da14cebeSEric Cheng 		usage();
3812da14cebeSEric Cheng 
3813da14cebeSEric Cheng 	if (strlcpy(name, argv[optind], MAXLINKNAMELEN) >= MAXLINKNAMELEN)
3814da14cebeSEric Cheng 		die("link name too long '%s'", argv[optind]);
3815da14cebeSEric Cheng 
3816da14cebeSEric Cheng 	if (!dladm_valid_linkname(name))
3817da14cebeSEric Cheng 		die("invalid link name '%s'", argv[optind]);
3818da14cebeSEric Cheng 
3819da14cebeSEric Cheng 	if (altroot != NULL)
3820da14cebeSEric Cheng 		altroot_cmd(altroot, argc, argv);
3821da14cebeSEric Cheng 
38224ac67f02SAnurag S. Maskey 	if (dladm_name2info(handle, devname, &dev_linkid, NULL, NULL, NULL) !=
3823da14cebeSEric Cheng 	    DLADM_STATUS_OK)
3824da14cebeSEric Cheng 		die("invalid link name '%s'", devname);
3825da14cebeSEric Cheng 
382663a6526dSMichael Lim 	if (dladm_parse_link_props(propstr, &proplist, B_FALSE)
382763a6526dSMichael Lim 	    != DLADM_STATUS_OK)
382863a6526dSMichael Lim 		die("invalid vnic property");
382963a6526dSMichael Lim 
38304ac67f02SAnurag S. Maskey 	status = dladm_vnic_create(handle, name, dev_linkid, mac_addr_type,
38314ac67f02SAnurag S. Maskey 	    mac_addr, maclen, &mac_slot, mac_prefix_len, vid, &linkid, proplist,
38324ac67f02SAnurag S. Maskey 	    flags);
3833da14cebeSEric Cheng 	if (status != DLADM_STATUS_OK)
3834da14cebeSEric Cheng 		die_dlerr(status, "vnic creation over %s failed", devname);
3835da14cebeSEric Cheng 
3836da14cebeSEric Cheng 	dladm_free_props(proplist);
3837da14cebeSEric Cheng }
3838da14cebeSEric Cheng 
3839da14cebeSEric Cheng static void
3840da14cebeSEric Cheng do_etherstub_check(const char *name, datalink_id_t linkid, boolean_t etherstub,
3841da14cebeSEric Cheng     uint32_t flags)
3842da14cebeSEric Cheng {
3843da14cebeSEric Cheng 	boolean_t is_etherstub;
3844da14cebeSEric Cheng 	dladm_vnic_attr_t attr;
3845da14cebeSEric Cheng 
38464ac67f02SAnurag S. Maskey 	if (dladm_vnic_info(handle, linkid, &attr, flags) != DLADM_STATUS_OK) {
3847da14cebeSEric Cheng 		/*
3848da14cebeSEric Cheng 		 * Let the delete continue anyway.
3849da14cebeSEric Cheng 		 */
3850da14cebeSEric Cheng 		return;
3851da14cebeSEric Cheng 	}
3852da14cebeSEric Cheng 	is_etherstub = (attr.va_link_id == DATALINK_INVALID_LINKID);
3853da14cebeSEric Cheng 	if (is_etherstub != etherstub) {
3854da14cebeSEric Cheng 		die("'%s' is not %s", name,
3855da14cebeSEric Cheng 		    (is_etherstub ? "a vnic" : "an etherstub"));
3856da14cebeSEric Cheng 	}
3857da14cebeSEric Cheng }
3858da14cebeSEric Cheng 
3859da14cebeSEric Cheng static void
3860da14cebeSEric Cheng do_delete_vnic_common(int argc, char *argv[], const char *use,
3861da14cebeSEric Cheng     boolean_t etherstub)
3862da14cebeSEric Cheng {
3863b509e89bSRishi Srivatsavai 	int option;
3864da14cebeSEric Cheng 	uint32_t flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST;
3865da14cebeSEric Cheng 	datalink_id_t linkid;
3866da14cebeSEric Cheng 	char *altroot = NULL;
3867da14cebeSEric Cheng 	dladm_status_t status;
3868da14cebeSEric Cheng 
3869da14cebeSEric Cheng 	opterr = 0;
3870da14cebeSEric Cheng 	while ((option = getopt_long(argc, argv, ":R:t", lopts,
3871da14cebeSEric Cheng 	    NULL)) != -1) {
3872da14cebeSEric Cheng 		switch (option) {
3873da14cebeSEric Cheng 		case 't':
3874da14cebeSEric Cheng 			flags &= ~DLADM_OPT_PERSIST;
3875da14cebeSEric Cheng 			break;
3876da14cebeSEric Cheng 		case 'R':
3877da14cebeSEric Cheng 			altroot = optarg;
3878da14cebeSEric Cheng 			break;
3879da14cebeSEric Cheng 		default:
3880da14cebeSEric Cheng 			die_opterr(optopt, option, use);
3881da14cebeSEric Cheng 		}
3882da14cebeSEric Cheng 	}
3883da14cebeSEric Cheng 
3884da14cebeSEric Cheng 	/* get vnic name (required last argument) */
3885da14cebeSEric Cheng 	if (optind != (argc - 1))
3886da14cebeSEric Cheng 		usage();
3887da14cebeSEric Cheng 
3888da14cebeSEric Cheng 	if (altroot != NULL)
3889da14cebeSEric Cheng 		altroot_cmd(altroot, argc, argv);
3890da14cebeSEric Cheng 
38914ac67f02SAnurag S. Maskey 	status = dladm_name2info(handle, argv[optind], &linkid, NULL, NULL,
38924ac67f02SAnurag S. Maskey 	    NULL);
3893da14cebeSEric Cheng 	if (status != DLADM_STATUS_OK)
3894da14cebeSEric Cheng 		die("invalid link name '%s'", argv[optind]);
3895da14cebeSEric Cheng 
3896da14cebeSEric Cheng 	if ((flags & DLADM_OPT_ACTIVE) != 0) {
3897da14cebeSEric Cheng 		do_etherstub_check(argv[optind], linkid, etherstub,
3898da14cebeSEric Cheng 		    DLADM_OPT_ACTIVE);
3899da14cebeSEric Cheng 	}
3900da14cebeSEric Cheng 	if ((flags & DLADM_OPT_PERSIST) != 0) {
3901da14cebeSEric Cheng 		do_etherstub_check(argv[optind], linkid, etherstub,
3902da14cebeSEric Cheng 		    DLADM_OPT_PERSIST);
3903da14cebeSEric Cheng 	}
3904da14cebeSEric Cheng 
39054ac67f02SAnurag S. Maskey 	status = dladm_vnic_delete(handle, linkid, flags);
3906da14cebeSEric Cheng 	if (status != DLADM_STATUS_OK)
3907da14cebeSEric Cheng 		die_dlerr(status, "vnic deletion failed");
3908da14cebeSEric Cheng }
3909da14cebeSEric Cheng 
3910da14cebeSEric Cheng static void
3911da14cebeSEric Cheng do_delete_vnic(int argc, char *argv[], const char *use)
3912da14cebeSEric Cheng {
3913da14cebeSEric Cheng 	do_delete_vnic_common(argc, argv, use, B_FALSE);
3914da14cebeSEric Cheng }
3915da14cebeSEric Cheng 
3916da14cebeSEric Cheng /* ARGSUSED */
3917da14cebeSEric Cheng static void
3918da14cebeSEric Cheng do_up_vnic_common(int argc, char *argv[], const char *use, boolean_t vlan)
3919da14cebeSEric Cheng {
3920da14cebeSEric Cheng 	datalink_id_t	linkid = DATALINK_ALL_LINKID;
3921da14cebeSEric Cheng 	dladm_status_t	status;
3922da14cebeSEric Cheng 	char 		*type;
3923da14cebeSEric Cheng 
3924da14cebeSEric Cheng 	type = vlan ? "vlan" : "vnic";
3925da14cebeSEric Cheng 
3926da14cebeSEric Cheng 	/*
3927da14cebeSEric Cheng 	 * get the id or the name of the vnic/vlan (optional last argument)
3928da14cebeSEric Cheng 	 */
3929da14cebeSEric Cheng 	if (argc == 2) {
39304ac67f02SAnurag S. Maskey 		status = dladm_name2info(handle, argv[1], &linkid, NULL, NULL,
39314ac67f02SAnurag S. Maskey 		    NULL);
3932da14cebeSEric Cheng 		if (status != DLADM_STATUS_OK)
3933da14cebeSEric Cheng 			goto done;
3934da14cebeSEric Cheng 
3935da14cebeSEric Cheng 	} else if (argc > 2) {
3936da14cebeSEric Cheng 		usage();
3937da14cebeSEric Cheng 	}
3938da14cebeSEric Cheng 
3939da14cebeSEric Cheng 	if (vlan)
39404ac67f02SAnurag S. Maskey 		status = dladm_vlan_up(handle, linkid);
3941da14cebeSEric Cheng 	else
39424ac67f02SAnurag S. Maskey 		status = dladm_vnic_up(handle, linkid, 0);
3943da14cebeSEric Cheng 
3944da14cebeSEric Cheng done:
3945da14cebeSEric Cheng 	if (status != DLADM_STATUS_OK) {
3946da14cebeSEric Cheng 		if (argc == 2) {
3947da14cebeSEric Cheng 			die_dlerr(status,
3948da14cebeSEric Cheng 			    "could not bring up %s '%s'", type, argv[1]);
3949da14cebeSEric Cheng 		} else {
3950da14cebeSEric Cheng 			die_dlerr(status, "could not bring %ss up", type);
3951da14cebeSEric Cheng 		}
3952da14cebeSEric Cheng 	}
3953da14cebeSEric Cheng }
3954da14cebeSEric Cheng 
3955da14cebeSEric Cheng static void
3956da14cebeSEric Cheng do_up_vnic(int argc, char *argv[], const char *use)
3957da14cebeSEric Cheng {
3958da14cebeSEric Cheng 	do_up_vnic_common(argc, argv, use, B_FALSE);
3959da14cebeSEric Cheng }
3960da14cebeSEric Cheng 
3961da14cebeSEric Cheng static void
3962da14cebeSEric Cheng dump_vnics_head(const char *dev)
3963da14cebeSEric Cheng {
3964da14cebeSEric Cheng 	if (strlen(dev))
3965da14cebeSEric Cheng 		(void) printf("%s", dev);
3966da14cebeSEric Cheng 
3967da14cebeSEric Cheng 	(void) printf("\tipackets  rbytes      opackets  obytes          ");
3968da14cebeSEric Cheng 
3969da14cebeSEric Cheng 	if (strlen(dev))
3970da14cebeSEric Cheng 		(void) printf("%%ipkts  %%opkts\n");
3971da14cebeSEric Cheng 	else
3972da14cebeSEric Cheng 		(void) printf("\n");
3973da14cebeSEric Cheng }
3974da14cebeSEric Cheng 
3975da14cebeSEric Cheng static void
3976da14cebeSEric Cheng dump_vnic_stat(const char *name, datalink_id_t vnic_id,
3977da14cebeSEric Cheng     show_vnic_state_t *state, pktsum_t *vnic_stats, pktsum_t *tot_stats)
3978da14cebeSEric Cheng {
3979da14cebeSEric Cheng 	pktsum_t	diff_stats;
3980da14cebeSEric Cheng 	pktsum_t	*old_stats = &state->vs_prevstats[vnic_id];
3981da14cebeSEric Cheng 
3982da14cebeSEric Cheng 	dladm_stats_diff(&diff_stats, vnic_stats, old_stats);
3983da14cebeSEric Cheng 
3984da14cebeSEric Cheng 	(void) printf("%s", name);
3985da14cebeSEric Cheng 
3986da14cebeSEric Cheng 	(void) printf("\t%-10llu", diff_stats.ipackets);
3987da14cebeSEric Cheng 	(void) printf("%-12llu", diff_stats.rbytes);
3988da14cebeSEric Cheng 	(void) printf("%-10llu", diff_stats.opackets);
3989da14cebeSEric Cheng 	(void) printf("%-12llu", diff_stats.obytes);
3990da14cebeSEric Cheng 
3991da14cebeSEric Cheng 	if (tot_stats) {
3992da14cebeSEric Cheng 		if (tot_stats->ipackets == 0) {
3993da14cebeSEric Cheng 			(void) printf("\t-");
3994da14cebeSEric Cheng 		} else {
3995da14cebeSEric Cheng 			(void) printf("\t%-6.1f", (double)diff_stats.ipackets/
3996da14cebeSEric Cheng 			    (double)tot_stats->ipackets * 100);
3997da14cebeSEric Cheng 		}
3998da14cebeSEric Cheng 		if (tot_stats->opackets == 0) {
3999da14cebeSEric Cheng 			(void) printf("\t-");
4000da14cebeSEric Cheng 		} else {
4001da14cebeSEric Cheng 			(void) printf("\t%-6.1f", (double)diff_stats.opackets/
4002da14cebeSEric Cheng 			    (double)tot_stats->opackets * 100);
4003da14cebeSEric Cheng 		}
4004da14cebeSEric Cheng 	}
4005da14cebeSEric Cheng 	(void) printf("\n");
4006da14cebeSEric Cheng 
4007da14cebeSEric Cheng 	*old_stats = *vnic_stats;
4008da14cebeSEric Cheng }
4009da14cebeSEric Cheng 
4010da14cebeSEric Cheng /*
4011da14cebeSEric Cheng  * Called from the walker dladm_vnic_walk_sys() for each vnic to display
4012da14cebeSEric Cheng  * vnic information or statistics.
4013da14cebeSEric Cheng  */
4014da14cebeSEric Cheng static dladm_status_t
4015da14cebeSEric Cheng print_vnic(show_vnic_state_t *state, datalink_id_t linkid)
4016da14cebeSEric Cheng {
4017da14cebeSEric Cheng 	dladm_vnic_attr_t	attr, *vnic = &attr;
4018da14cebeSEric Cheng 	dladm_status_t		status;
4019da14cebeSEric Cheng 	boolean_t		is_etherstub;
4020da14cebeSEric Cheng 	char			devname[MAXLINKNAMELEN];
4021da14cebeSEric Cheng 	char			vnic_name[MAXLINKNAMELEN];
4022da14cebeSEric Cheng 	char			mstr[MAXMACADDRLEN * 3];
4023da14cebeSEric Cheng 	vnic_fields_buf_t	vbuf;
4024da14cebeSEric Cheng 
40254ac67f02SAnurag S. Maskey 	if ((status = dladm_vnic_info(handle, linkid, vnic, state->vs_flags)) !=
4026da14cebeSEric Cheng 	    DLADM_STATUS_OK)
4027da14cebeSEric Cheng 		return (status);
4028da14cebeSEric Cheng 
4029da14cebeSEric Cheng 	is_etherstub = (vnic->va_link_id == DATALINK_INVALID_LINKID);
4030da14cebeSEric Cheng 	if (state->vs_etherstub != is_etherstub) {
4031da14cebeSEric Cheng 		/*
4032da14cebeSEric Cheng 		 * Want all etherstub but it's not one, or want
4033da14cebeSEric Cheng 		 * non-etherstub and it's one.
4034da14cebeSEric Cheng 		 */
4035da14cebeSEric Cheng 		return (DLADM_STATUS_OK);
4036da14cebeSEric Cheng 	}
4037da14cebeSEric Cheng 
4038da14cebeSEric Cheng 	if (state->vs_link_id != DATALINK_ALL_LINKID) {
4039da14cebeSEric Cheng 		if (state->vs_link_id != vnic->va_link_id)
4040da14cebeSEric Cheng 			return (DLADM_STATUS_OK);
4041da14cebeSEric Cheng 	}
4042da14cebeSEric Cheng 
40434ac67f02SAnurag S. Maskey 	if (dladm_datalink_id2info(handle, linkid, NULL, NULL,
4044da14cebeSEric Cheng 	    NULL, vnic_name, sizeof (vnic_name)) != DLADM_STATUS_OK)
4045da14cebeSEric Cheng 		return (DLADM_STATUS_BADARG);
4046da14cebeSEric Cheng 
4047da14cebeSEric Cheng 	bzero(devname, sizeof (devname));
4048da14cebeSEric Cheng 	if (!is_etherstub &&
40494ac67f02SAnurag S. Maskey 	    dladm_datalink_id2info(handle, vnic->va_link_id, NULL, NULL,
4050da14cebeSEric Cheng 	    NULL, devname, sizeof (devname)) != DLADM_STATUS_OK)
4051da14cebeSEric Cheng 		return (DLADM_STATUS_BADARG);
4052da14cebeSEric Cheng 
4053da14cebeSEric Cheng 	state->vs_found = B_TRUE;
4054da14cebeSEric Cheng 	if (state->vs_stats) {
4055da14cebeSEric Cheng 		/* print vnic statistics */
4056da14cebeSEric Cheng 		pktsum_t vnic_stats;
4057da14cebeSEric Cheng 
4058da14cebeSEric Cheng 		if (state->vs_firstonly) {
4059da14cebeSEric Cheng 			if (state->vs_donefirst)
4060da14cebeSEric Cheng 				return (0);
4061da14cebeSEric Cheng 			state->vs_donefirst = B_TRUE;
4062da14cebeSEric Cheng 		}
4063da14cebeSEric Cheng 
4064da14cebeSEric Cheng 		if (!state->vs_printstats) {
4065da14cebeSEric Cheng 			/*
4066da14cebeSEric Cheng 			 * get vnic statistics and add to the sum for the
4067da14cebeSEric Cheng 			 * named device.
4068da14cebeSEric Cheng 			 */
4069da14cebeSEric Cheng 			get_link_stats(vnic_name, &vnic_stats);
4070da14cebeSEric Cheng 			dladm_stats_total(&state->vs_totalstats, &vnic_stats,
4071da14cebeSEric Cheng 			    &state->vs_prevstats[vnic->va_vnic_id]);
4072da14cebeSEric Cheng 		} else {
4073da14cebeSEric Cheng 			/* get and print vnic statistics */
4074da14cebeSEric Cheng 			get_link_stats(vnic_name, &vnic_stats);
4075da14cebeSEric Cheng 			dump_vnic_stat(vnic_name, linkid, state, &vnic_stats,
4076da14cebeSEric Cheng 			    &state->vs_totalstats);
4077da14cebeSEric Cheng 		}
4078da14cebeSEric Cheng 		return (DLADM_STATUS_OK);
4079da14cebeSEric Cheng 	} else {
4080da14cebeSEric Cheng 		(void) snprintf(vbuf.vnic_link, sizeof (vbuf.vnic_link),
4081da14cebeSEric Cheng 		    "%s", vnic_name);
4082da14cebeSEric Cheng 
4083da14cebeSEric Cheng 		if (!is_etherstub) {
4084da14cebeSEric Cheng 
4085da14cebeSEric Cheng 			(void) snprintf(vbuf.vnic_over, sizeof (vbuf.vnic_over),
4086da14cebeSEric Cheng 			    "%s", devname);
4087da14cebeSEric Cheng 			(void) snprintf(vbuf.vnic_speed,
4088da14cebeSEric Cheng 			    sizeof (vbuf.vnic_speed), "%u",
4089da14cebeSEric Cheng 			    (uint_t)((get_ifspeed(vnic_name, B_TRUE))
4090da14cebeSEric Cheng 			    / 1000000ull));
4091da14cebeSEric Cheng 
4092da14cebeSEric Cheng 			switch (vnic->va_mac_addr_type) {
4093da14cebeSEric Cheng 			case VNIC_MAC_ADDR_TYPE_FIXED:
4094da14cebeSEric Cheng 			case VNIC_MAC_ADDR_TYPE_PRIMARY:
4095da14cebeSEric Cheng 				(void) snprintf(vbuf.vnic_macaddrtype,
4096da14cebeSEric Cheng 				    sizeof (vbuf.vnic_macaddrtype),
4097da14cebeSEric Cheng 				    gettext("fixed"));
4098da14cebeSEric Cheng 				break;
4099da14cebeSEric Cheng 			case VNIC_MAC_ADDR_TYPE_RANDOM:
4100da14cebeSEric Cheng 				(void) snprintf(vbuf.vnic_macaddrtype,
4101da14cebeSEric Cheng 				    sizeof (vbuf.vnic_macaddrtype),
4102da14cebeSEric Cheng 				    gettext("random"));
4103da14cebeSEric Cheng 				break;
4104da14cebeSEric Cheng 			case VNIC_MAC_ADDR_TYPE_FACTORY:
4105da14cebeSEric Cheng 				(void) snprintf(vbuf.vnic_macaddrtype,
4106da14cebeSEric Cheng 				    sizeof (vbuf.vnic_macaddrtype),
4107da14cebeSEric Cheng 				    gettext("factory, slot %d"),
4108da14cebeSEric Cheng 				    vnic->va_mac_slot);
4109da14cebeSEric Cheng 				break;
4110da14cebeSEric Cheng 			}
4111da14cebeSEric Cheng 
4112da14cebeSEric Cheng 			if (strlen(vbuf.vnic_macaddrtype) > 0) {
4113da14cebeSEric Cheng 				(void) snprintf(vbuf.vnic_macaddr,
4114da14cebeSEric Cheng 				    sizeof (vbuf.vnic_macaddr), "%s",
4115da14cebeSEric Cheng 				    dladm_aggr_macaddr2str(vnic->va_mac_addr,
4116da14cebeSEric Cheng 				    mstr));
4117da14cebeSEric Cheng 			}
4118da14cebeSEric Cheng 
4119da14cebeSEric Cheng 			(void) snprintf(vbuf.vnic_vid, sizeof (vbuf.vnic_vid),
4120da14cebeSEric Cheng 			    "%d", vnic->va_vid);
4121da14cebeSEric Cheng 		}
4122da14cebeSEric Cheng 
41238002d411SSowmini Varadhan 		ofmt_print(state->vs_ofmt, &vbuf);
4124da14cebeSEric Cheng 
4125da14cebeSEric Cheng 		return (DLADM_STATUS_OK);
4126da14cebeSEric Cheng 	}
4127da14cebeSEric Cheng }
4128da14cebeSEric Cheng 
41294ac67f02SAnurag S. Maskey /* ARGSUSED */
4130da14cebeSEric Cheng static int
41314ac67f02SAnurag S. Maskey show_vnic(dladm_handle_t dh, datalink_id_t linkid, void *arg)
4132da14cebeSEric Cheng {
4133da14cebeSEric Cheng 	show_vnic_state_t	*state = arg;
4134da14cebeSEric Cheng 
4135da14cebeSEric Cheng 	state->vs_status = print_vnic(state, linkid);
4136da14cebeSEric Cheng 	return (DLADM_WALK_CONTINUE);
4137da14cebeSEric Cheng }
4138da14cebeSEric Cheng 
4139da14cebeSEric Cheng static void
4140da14cebeSEric Cheng do_show_vnic_common(int argc, char *argv[], const char *use,
4141da14cebeSEric Cheng     boolean_t etherstub)
4142da14cebeSEric Cheng {
4143da14cebeSEric Cheng 	int			option;
4144da14cebeSEric Cheng 	boolean_t		s_arg = B_FALSE;
4145da14cebeSEric Cheng 	boolean_t		i_arg = B_FALSE;
4146da14cebeSEric Cheng 	boolean_t		l_arg = B_FALSE;
4147da14cebeSEric Cheng 	uint32_t		interval = 0, flags = DLADM_OPT_ACTIVE;
4148da14cebeSEric Cheng 	datalink_id_t		linkid = DATALINK_ALL_LINKID;
4149da14cebeSEric Cheng 	datalink_id_t		dev_linkid = DATALINK_ALL_LINKID;
4150da14cebeSEric Cheng 	show_vnic_state_t	state;
4151da14cebeSEric Cheng 	dladm_status_t		status;
4152da14cebeSEric Cheng 	boolean_t		o_arg = B_FALSE;
4153da14cebeSEric Cheng 	char			*fields_str = NULL;
41548002d411SSowmini Varadhan 	ofmt_field_t		*pf;
41558002d411SSowmini Varadhan 	char			*all_e_fields = "link";
41568002d411SSowmini Varadhan 	ofmt_handle_t		ofmt;
41578002d411SSowmini Varadhan 	ofmt_status_t		oferr;
41588002d411SSowmini Varadhan 	uint_t			ofmtflags = 0;
4159da14cebeSEric Cheng 
4160da14cebeSEric Cheng 	bzero(&state, sizeof (state));
4161da14cebeSEric Cheng 	opterr = 0;
4162da14cebeSEric Cheng 	while ((option = getopt_long(argc, argv, ":pPl:si:o:", lopts,
4163da14cebeSEric Cheng 	    NULL)) != -1) {
4164da14cebeSEric Cheng 		switch (option) {
4165da14cebeSEric Cheng 		case 'p':
41668002d411SSowmini Varadhan 			state.vs_parsable = B_TRUE;
4167da14cebeSEric Cheng 			break;
4168da14cebeSEric Cheng 		case 'P':
4169da14cebeSEric Cheng 			flags = DLADM_OPT_PERSIST;
4170da14cebeSEric Cheng 			break;
4171da14cebeSEric Cheng 		case 'l':
4172da14cebeSEric Cheng 			if (etherstub)
4173da14cebeSEric Cheng 				die("option not supported for this command");
4174da14cebeSEric Cheng 
4175da14cebeSEric Cheng 			if (strlcpy(state.vs_link, optarg, MAXLINKNAMELEN) >=
4176da14cebeSEric Cheng 			    MAXLINKNAMELEN)
4177da14cebeSEric Cheng 				die("link name too long");
4178da14cebeSEric Cheng 
4179da14cebeSEric Cheng 			l_arg = B_TRUE;
4180da14cebeSEric Cheng 			break;
4181da14cebeSEric Cheng 		case 's':
4182da14cebeSEric Cheng 			if (s_arg) {
4183da14cebeSEric Cheng 				die("the option -s cannot be specified "
4184da14cebeSEric Cheng 				    "more than once");
4185da14cebeSEric Cheng 			}
4186da14cebeSEric Cheng 			s_arg = B_TRUE;
4187da14cebeSEric Cheng 			break;
4188da14cebeSEric Cheng 		case 'i':
4189da14cebeSEric Cheng 			if (i_arg) {
4190da14cebeSEric Cheng 				die("the option -i cannot be specified "
4191da14cebeSEric Cheng 				    "more than once");
4192da14cebeSEric Cheng 			}
4193da14cebeSEric Cheng 			i_arg = B_TRUE;
419463a6526dSMichael Lim 			if (!dladm_str2interval(optarg, &interval))
4195da14cebeSEric Cheng 				die("invalid interval value '%s'", optarg);
4196da14cebeSEric Cheng 			break;
4197da14cebeSEric Cheng 		case 'o':
4198da14cebeSEric Cheng 			o_arg = B_TRUE;
4199da14cebeSEric Cheng 			fields_str = optarg;
4200da14cebeSEric Cheng 			break;
4201da14cebeSEric Cheng 		default:
4202da14cebeSEric Cheng 			die_opterr(optopt, option, use);
4203da14cebeSEric Cheng 		}
4204da14cebeSEric Cheng 	}
4205da14cebeSEric Cheng 
4206da14cebeSEric Cheng 	if (i_arg && !s_arg)
4207da14cebeSEric Cheng 		die("the option -i can be used only with -s");
4208da14cebeSEric Cheng 
4209da14cebeSEric Cheng 	/* get vnic ID (optional last argument) */
4210da14cebeSEric Cheng 	if (optind == (argc - 1)) {
42114ac67f02SAnurag S. Maskey 		status = dladm_name2info(handle, argv[optind], &linkid, NULL,
4212da14cebeSEric Cheng 		    NULL, NULL);
4213da14cebeSEric Cheng 		if (status != DLADM_STATUS_OK) {
4214da14cebeSEric Cheng 			die_dlerr(status, "invalid vnic name '%s'",
4215da14cebeSEric Cheng 			    argv[optind]);
4216da14cebeSEric Cheng 		}
4217da14cebeSEric Cheng 		(void) strlcpy(state.vs_vnic, argv[optind], MAXLINKNAMELEN);
4218da14cebeSEric Cheng 	} else if (optind != argc) {
4219da14cebeSEric Cheng 		usage();
4220da14cebeSEric Cheng 	}
4221da14cebeSEric Cheng 
4222da14cebeSEric Cheng 	if (l_arg) {
42234ac67f02SAnurag S. Maskey 		status = dladm_name2info(handle, state.vs_link, &dev_linkid,
42244ac67f02SAnurag S. Maskey 		    NULL, NULL, NULL);
4225da14cebeSEric Cheng 		if (status != DLADM_STATUS_OK) {
4226da14cebeSEric Cheng 			die_dlerr(status, "invalid link name '%s'",
4227da14cebeSEric Cheng 			    state.vs_link);
4228da14cebeSEric Cheng 		}
4229da14cebeSEric Cheng 	}
4230da14cebeSEric Cheng 
4231da14cebeSEric Cheng 	state.vs_vnic_id = linkid;
4232da14cebeSEric Cheng 	state.vs_link_id = dev_linkid;
4233da14cebeSEric Cheng 	state.vs_etherstub = etherstub;
4234da14cebeSEric Cheng 	state.vs_found = B_FALSE;
4235da14cebeSEric Cheng 	state.vs_flags = flags;
4236da14cebeSEric Cheng 
4237da14cebeSEric Cheng 	if (!o_arg || (o_arg && strcasecmp(fields_str, "all") == 0)) {
4238da14cebeSEric Cheng 		if (etherstub)
4239da14cebeSEric Cheng 			fields_str = all_e_fields;
4240da14cebeSEric Cheng 	}
4241da14cebeSEric Cheng 	pf = vnic_fields;
4242da14cebeSEric Cheng 
42438002d411SSowmini Varadhan 	if (state.vs_parsable)
42448002d411SSowmini Varadhan 		ofmtflags |= OFMT_PARSABLE;
42458002d411SSowmini Varadhan 	oferr = ofmt_open(fields_str, pf, ofmtflags, 0, &ofmt);
42468002d411SSowmini Varadhan 	dladm_ofmt_check(oferr, state.vs_parsable, ofmt);
42478002d411SSowmini Varadhan 	state.vs_ofmt = ofmt;
4248da14cebeSEric Cheng 
4249da14cebeSEric Cheng 	if (s_arg) {
4250da14cebeSEric Cheng 		/* Display vnic statistics */
4251da14cebeSEric Cheng 		vnic_stats(&state, interval);
42528002d411SSowmini Varadhan 		ofmt_close(ofmt);
4253da14cebeSEric Cheng 		return;
4254da14cebeSEric Cheng 	}
4255da14cebeSEric Cheng 
4256da14cebeSEric Cheng 	/* Display vnic information */
4257da14cebeSEric Cheng 	state.vs_donefirst = B_FALSE;
4258da14cebeSEric Cheng 
4259da14cebeSEric Cheng 	if (linkid == DATALINK_ALL_LINKID) {
42604ac67f02SAnurag S. Maskey 		(void) dladm_walk_datalink_id(show_vnic, handle, &state,
4261da14cebeSEric Cheng 		    DATALINK_CLASS_VNIC | DATALINK_CLASS_ETHERSTUB,
4262c3affd82SMichael Lim 		    DATALINK_ANY_MEDIATYPE, flags);
4263da14cebeSEric Cheng 	} else {
42644ac67f02SAnurag S. Maskey 		(void) show_vnic(handle, linkid, &state);
4265da14cebeSEric Cheng 		if (state.vs_status != DLADM_STATUS_OK) {
42668002d411SSowmini Varadhan 			ofmt_close(ofmt);
4267da14cebeSEric Cheng 			die_dlerr(state.vs_status, "failed to show vnic '%s'",
4268da14cebeSEric Cheng 			    state.vs_vnic);
4269da14cebeSEric Cheng 		}
4270da14cebeSEric Cheng 	}
42718002d411SSowmini Varadhan 	ofmt_close(ofmt);
4272da14cebeSEric Cheng }
4273da14cebeSEric Cheng 
4274da14cebeSEric Cheng static void
4275da14cebeSEric Cheng do_show_vnic(int argc, char *argv[], const char *use)
4276da14cebeSEric Cheng {
4277da14cebeSEric Cheng 	do_show_vnic_common(argc, argv, use, B_FALSE);
4278da14cebeSEric Cheng }
4279da14cebeSEric Cheng 
4280da14cebeSEric Cheng static void
4281da14cebeSEric Cheng do_create_etherstub(int argc, char *argv[], const char *use)
4282da14cebeSEric Cheng {
4283da14cebeSEric Cheng 	uint32_t flags;
4284da14cebeSEric Cheng 	char *altroot = NULL;
4285b509e89bSRishi Srivatsavai 	int option;
4286da14cebeSEric Cheng 	dladm_status_t status;
4287da14cebeSEric Cheng 	char name[MAXLINKNAMELEN];
4288da14cebeSEric Cheng 	uchar_t mac_addr[ETHERADDRL];
4289da14cebeSEric Cheng 
4290da14cebeSEric Cheng 	name[0] = '\0';
4291da14cebeSEric Cheng 	bzero(mac_addr, sizeof (mac_addr));
4292da14cebeSEric Cheng 	flags = DLADM_OPT_ANCHOR | DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST;
4293da14cebeSEric Cheng 
4294da14cebeSEric Cheng 	opterr = 0;
4295da14cebeSEric Cheng 	while ((option = getopt_long(argc, argv, "tR:",
4296da14cebeSEric Cheng 	    etherstub_lopts, NULL)) != -1) {
4297da14cebeSEric Cheng 		switch (option) {
4298da14cebeSEric Cheng 		case 't':
4299da14cebeSEric Cheng 			flags &= ~DLADM_OPT_PERSIST;
4300da14cebeSEric Cheng 			break;
4301da14cebeSEric Cheng 		case 'R':
4302da14cebeSEric Cheng 			altroot = optarg;
4303da14cebeSEric Cheng 			break;
4304da14cebeSEric Cheng 		default:
4305da14cebeSEric Cheng 			die_opterr(optopt, option, use);
4306da14cebeSEric Cheng 		}
4307da14cebeSEric Cheng 	}
4308da14cebeSEric Cheng 
4309da14cebeSEric Cheng 	/* the etherstub id is the required operand */
4310da14cebeSEric Cheng 	if (optind != (argc - 1))
4311da14cebeSEric Cheng 		usage();
4312da14cebeSEric Cheng 
4313da14cebeSEric Cheng 	if (strlcpy(name, argv[optind], MAXLINKNAMELEN) >= MAXLINKNAMELEN)
4314da14cebeSEric Cheng 		die("link name too long '%s'", argv[optind]);
4315da14cebeSEric Cheng 
4316da14cebeSEric Cheng 	if (!dladm_valid_linkname(name))
4317da14cebeSEric Cheng 		die("invalid link name '%s'", argv[optind]);
4318da14cebeSEric Cheng 
4319da14cebeSEric Cheng 	if (altroot != NULL)
4320da14cebeSEric Cheng 		altroot_cmd(altroot, argc, argv);
4321da14cebeSEric Cheng 
43224ac67f02SAnurag S. Maskey 	status = dladm_vnic_create(handle, name, DATALINK_INVALID_LINKID,
4323da14cebeSEric Cheng 	    VNIC_MAC_ADDR_TYPE_AUTO, mac_addr, ETHERADDRL, NULL, 0, 0, NULL,
4324da14cebeSEric Cheng 	    NULL, flags);
4325da14cebeSEric Cheng 	if (status != DLADM_STATUS_OK)
4326da14cebeSEric Cheng 		die_dlerr(status, "etherstub creation failed");
4327da14cebeSEric Cheng }
4328da14cebeSEric Cheng 
4329da14cebeSEric Cheng static void
4330da14cebeSEric Cheng do_delete_etherstub(int argc, char *argv[], const char *use)
4331da14cebeSEric Cheng {
4332da14cebeSEric Cheng 	do_delete_vnic_common(argc, argv, use, B_TRUE);
4333da14cebeSEric Cheng }
4334da14cebeSEric Cheng 
4335da14cebeSEric Cheng /* ARGSUSED */
4336da14cebeSEric Cheng static void
4337da14cebeSEric Cheng do_show_etherstub(int argc, char *argv[], const char *use)
4338da14cebeSEric Cheng {
4339da14cebeSEric Cheng 	do_show_vnic_common(argc, argv, use, B_TRUE);
4340da14cebeSEric Cheng }
4341da14cebeSEric Cheng 
4342b509e89bSRishi Srivatsavai /* ARGSUSED */
4343b509e89bSRishi Srivatsavai static void
4344b509e89bSRishi Srivatsavai do_up_simnet(int argc, char *argv[], const char *use)
4345b509e89bSRishi Srivatsavai {
4346b509e89bSRishi Srivatsavai 	(void) dladm_simnet_up(handle, DATALINK_ALL_LINKID, 0);
4347b509e89bSRishi Srivatsavai }
4348b509e89bSRishi Srivatsavai 
4349b509e89bSRishi Srivatsavai static void
4350b509e89bSRishi Srivatsavai do_create_simnet(int argc, char *argv[], const char *use)
4351b509e89bSRishi Srivatsavai {
4352b509e89bSRishi Srivatsavai 	uint32_t flags;
4353b509e89bSRishi Srivatsavai 	char *altroot = NULL;
4354b509e89bSRishi Srivatsavai 	char *media = NULL;
4355b509e89bSRishi Srivatsavai 	uint32_t mtype = DL_ETHER;
4356b509e89bSRishi Srivatsavai 	int option;
4357b509e89bSRishi Srivatsavai 	dladm_status_t status;
4358b509e89bSRishi Srivatsavai 	char name[MAXLINKNAMELEN];
4359b509e89bSRishi Srivatsavai 
4360b509e89bSRishi Srivatsavai 	name[0] = '\0';
4361b509e89bSRishi Srivatsavai 	flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST;
4362b509e89bSRishi Srivatsavai 
4363b509e89bSRishi Srivatsavai 	opterr = 0;
4364b509e89bSRishi Srivatsavai 	while ((option = getopt_long(argc, argv, ":tR:m:",
4365b509e89bSRishi Srivatsavai 	    simnet_lopts, NULL)) != -1) {
4366b509e89bSRishi Srivatsavai 		switch (option) {
4367b509e89bSRishi Srivatsavai 		case 't':
4368b509e89bSRishi Srivatsavai 			flags &= ~DLADM_OPT_PERSIST;
4369b509e89bSRishi Srivatsavai 			break;
4370b509e89bSRishi Srivatsavai 		case 'R':
4371b509e89bSRishi Srivatsavai 			altroot = optarg;
4372b509e89bSRishi Srivatsavai 			break;
4373b509e89bSRishi Srivatsavai 		case 'm':
4374b509e89bSRishi Srivatsavai 			media = optarg;
4375b509e89bSRishi Srivatsavai 			break;
4376b509e89bSRishi Srivatsavai 		default:
4377b509e89bSRishi Srivatsavai 			die_opterr(optopt, option, use);
4378b509e89bSRishi Srivatsavai 		}
4379b509e89bSRishi Srivatsavai 	}
4380b509e89bSRishi Srivatsavai 
4381b509e89bSRishi Srivatsavai 	/* the simnet id is the required operand */
4382b509e89bSRishi Srivatsavai 	if (optind != (argc - 1))
4383b509e89bSRishi Srivatsavai 		usage();
4384b509e89bSRishi Srivatsavai 
4385b509e89bSRishi Srivatsavai 	if (strlcpy(name, argv[optind], MAXLINKNAMELEN) >= MAXLINKNAMELEN)
4386b509e89bSRishi Srivatsavai 		die("link name too long '%s'", argv[optind]);
4387b509e89bSRishi Srivatsavai 
4388b509e89bSRishi Srivatsavai 	if (!dladm_valid_linkname(name))
4389b509e89bSRishi Srivatsavai 		die("invalid link name '%s'", name);
4390b509e89bSRishi Srivatsavai 
4391b509e89bSRishi Srivatsavai 	if (media != NULL) {
4392b509e89bSRishi Srivatsavai 		mtype = dladm_str2media(media);
4393b509e89bSRishi Srivatsavai 		if (mtype != DL_ETHER && mtype != DL_WIFI)
4394b509e89bSRishi Srivatsavai 			die("media type '%s' is not supported", media);
4395b509e89bSRishi Srivatsavai 	}
4396b509e89bSRishi Srivatsavai 
4397b509e89bSRishi Srivatsavai 	if (altroot != NULL)
4398b509e89bSRishi Srivatsavai 		altroot_cmd(altroot, argc, argv);
4399b509e89bSRishi Srivatsavai 
4400b509e89bSRishi Srivatsavai 	status = dladm_simnet_create(handle, name, mtype, flags);
4401b509e89bSRishi Srivatsavai 	if (status != DLADM_STATUS_OK)
4402b509e89bSRishi Srivatsavai 		die_dlerr(status, "simnet creation failed");
4403b509e89bSRishi Srivatsavai }
4404b509e89bSRishi Srivatsavai 
4405b509e89bSRishi Srivatsavai static void
4406b509e89bSRishi Srivatsavai do_delete_simnet(int argc, char *argv[], const char *use)
4407b509e89bSRishi Srivatsavai {
4408b509e89bSRishi Srivatsavai 	int option;
4409b509e89bSRishi Srivatsavai 	uint32_t flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST;
4410b509e89bSRishi Srivatsavai 	datalink_id_t linkid;
4411b509e89bSRishi Srivatsavai 	char *altroot = NULL;
4412b509e89bSRishi Srivatsavai 	dladm_status_t status;
4413b509e89bSRishi Srivatsavai 	dladm_simnet_attr_t slinfo;
4414b509e89bSRishi Srivatsavai 
4415b509e89bSRishi Srivatsavai 	opterr = 0;
4416b509e89bSRishi Srivatsavai 	while ((option = getopt_long(argc, argv, ":tR:", simnet_lopts,
4417b509e89bSRishi Srivatsavai 	    NULL)) != -1) {
4418b509e89bSRishi Srivatsavai 		switch (option) {
4419b509e89bSRishi Srivatsavai 		case 't':
4420b509e89bSRishi Srivatsavai 			flags &= ~DLADM_OPT_PERSIST;
4421b509e89bSRishi Srivatsavai 			break;
4422b509e89bSRishi Srivatsavai 		case 'R':
4423b509e89bSRishi Srivatsavai 			altroot = optarg;
4424b509e89bSRishi Srivatsavai 			break;
4425b509e89bSRishi Srivatsavai 		default:
4426b509e89bSRishi Srivatsavai 			die_opterr(optopt, option, use);
4427b509e89bSRishi Srivatsavai 		}
4428b509e89bSRishi Srivatsavai 	}
4429b509e89bSRishi Srivatsavai 
4430b509e89bSRishi Srivatsavai 	/* get simnet name (required last argument) */
4431b509e89bSRishi Srivatsavai 	if (optind != (argc - 1))
4432b509e89bSRishi Srivatsavai 		usage();
4433b509e89bSRishi Srivatsavai 
4434b509e89bSRishi Srivatsavai 	if (!dladm_valid_linkname(argv[optind]))
4435b509e89bSRishi Srivatsavai 		die("invalid link name '%s'", argv[optind]);
4436b509e89bSRishi Srivatsavai 
4437b509e89bSRishi Srivatsavai 	if (altroot != NULL)
4438b509e89bSRishi Srivatsavai 		altroot_cmd(altroot, argc, argv);
4439b509e89bSRishi Srivatsavai 
4440b509e89bSRishi Srivatsavai 	status = dladm_name2info(handle, argv[optind], &linkid, NULL, NULL,
4441b509e89bSRishi Srivatsavai 	    NULL);
4442b509e89bSRishi Srivatsavai 	if (status != DLADM_STATUS_OK)
4443b509e89bSRishi Srivatsavai 		die("simnet '%s' not found", argv[optind]);
4444b509e89bSRishi Srivatsavai 
4445b509e89bSRishi Srivatsavai 	if ((status = dladm_simnet_info(handle, linkid, &slinfo,
4446b509e89bSRishi Srivatsavai 	    flags)) != DLADM_STATUS_OK)
4447b509e89bSRishi Srivatsavai 		die_dlerr(status, "failed to retrieve simnet information");
4448b509e89bSRishi Srivatsavai 
4449b509e89bSRishi Srivatsavai 	status = dladm_simnet_delete(handle, linkid, flags);
4450b509e89bSRishi Srivatsavai 	if (status != DLADM_STATUS_OK)
4451b509e89bSRishi Srivatsavai 		die_dlerr(status, "simnet deletion failed");
4452b509e89bSRishi Srivatsavai }
4453b509e89bSRishi Srivatsavai 
4454b509e89bSRishi Srivatsavai static void
4455b509e89bSRishi Srivatsavai do_modify_simnet(int argc, char *argv[], const char *use)
4456b509e89bSRishi Srivatsavai {
4457b509e89bSRishi Srivatsavai 	int option;
4458b509e89bSRishi Srivatsavai 	uint32_t flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST;
4459b509e89bSRishi Srivatsavai 	datalink_id_t linkid;
4460b509e89bSRishi Srivatsavai 	datalink_id_t peer_linkid;
4461b509e89bSRishi Srivatsavai 	char *altroot = NULL;
4462b509e89bSRishi Srivatsavai 	dladm_status_t status;
4463b509e89bSRishi Srivatsavai 	boolean_t p_arg = B_FALSE;
4464b509e89bSRishi Srivatsavai 
4465b509e89bSRishi Srivatsavai 	opterr = 0;
4466b509e89bSRishi Srivatsavai 	while ((option = getopt_long(argc, argv, ":tR:p:", simnet_lopts,
4467b509e89bSRishi Srivatsavai 	    NULL)) != -1) {
4468b509e89bSRishi Srivatsavai 		switch (option) {
4469b509e89bSRishi Srivatsavai 		case 't':
4470b509e89bSRishi Srivatsavai 			flags &= ~DLADM_OPT_PERSIST;
4471b509e89bSRishi Srivatsavai 			break;
4472b509e89bSRishi Srivatsavai 		case 'R':
4473b509e89bSRishi Srivatsavai 			altroot = optarg;
4474b509e89bSRishi Srivatsavai 			break;
4475b509e89bSRishi Srivatsavai 		case 'p':
4476b509e89bSRishi Srivatsavai 			if (p_arg)
4477b509e89bSRishi Srivatsavai 				die_optdup(option);
4478b509e89bSRishi Srivatsavai 			p_arg = B_TRUE;
4479b509e89bSRishi Srivatsavai 			if (strcasecmp(optarg, "none") == 0)
4480b509e89bSRishi Srivatsavai 				peer_linkid = DATALINK_INVALID_LINKID;
4481b509e89bSRishi Srivatsavai 			else if (dladm_name2info(handle, optarg, &peer_linkid,
4482b509e89bSRishi Srivatsavai 			    NULL, NULL, NULL) != DLADM_STATUS_OK)
4483b509e89bSRishi Srivatsavai 				die("invalid peer link name '%s'", optarg);
4484b509e89bSRishi Srivatsavai 			break;
4485b509e89bSRishi Srivatsavai 		default:
4486b509e89bSRishi Srivatsavai 			die_opterr(optopt, option, use);
4487b509e89bSRishi Srivatsavai 		}
4488b509e89bSRishi Srivatsavai 	}
4489b509e89bSRishi Srivatsavai 
4490b509e89bSRishi Srivatsavai 	/* get simnet name (required last argument) */
4491b509e89bSRishi Srivatsavai 	if (optind != (argc - 1))
4492b509e89bSRishi Srivatsavai 		usage();
4493b509e89bSRishi Srivatsavai 
4494b509e89bSRishi Srivatsavai 	/* Nothing to do if no peer link argument */
4495b509e89bSRishi Srivatsavai 	if (!p_arg)
4496b509e89bSRishi Srivatsavai 		return;
4497b509e89bSRishi Srivatsavai 
4498b509e89bSRishi Srivatsavai 	if (altroot != NULL)
4499b509e89bSRishi Srivatsavai 		altroot_cmd(altroot, argc, argv);
4500b509e89bSRishi Srivatsavai 
4501b509e89bSRishi Srivatsavai 	status = dladm_name2info(handle, argv[optind], &linkid, NULL, NULL,
4502b509e89bSRishi Srivatsavai 	    NULL);
4503b509e89bSRishi Srivatsavai 	if (status != DLADM_STATUS_OK)
4504b509e89bSRishi Srivatsavai 		die("invalid link name '%s'", argv[optind]);
4505b509e89bSRishi Srivatsavai 
4506b509e89bSRishi Srivatsavai 	status = dladm_simnet_modify(handle, linkid, peer_linkid, flags);
4507b509e89bSRishi Srivatsavai 	if (status != DLADM_STATUS_OK)
4508b509e89bSRishi Srivatsavai 		die_dlerr(status, "simnet modification failed");
4509b509e89bSRishi Srivatsavai }
4510b509e89bSRishi Srivatsavai 
4511b509e89bSRishi Srivatsavai static dladm_status_t
4512b509e89bSRishi Srivatsavai print_simnet(show_state_t *state, datalink_id_t linkid)
4513b509e89bSRishi Srivatsavai {
4514b509e89bSRishi Srivatsavai 	dladm_simnet_attr_t	slinfo;
4515b509e89bSRishi Srivatsavai 	uint32_t		flags;
4516b509e89bSRishi Srivatsavai 	dladm_status_t		status;
4517b509e89bSRishi Srivatsavai 	simnet_fields_buf_t	slbuf;
4518b509e89bSRishi Srivatsavai 	char			mstr[ETHERADDRL * 3];
4519b509e89bSRishi Srivatsavai 
4520b509e89bSRishi Srivatsavai 	bzero(&slbuf, sizeof (slbuf));
4521b509e89bSRishi Srivatsavai 	if ((status = dladm_datalink_id2info(handle, linkid, &flags, NULL, NULL,
4522b509e89bSRishi Srivatsavai 	    slbuf.simnet_name, sizeof (slbuf.simnet_name)))
4523b509e89bSRishi Srivatsavai 	    != DLADM_STATUS_OK)
4524b509e89bSRishi Srivatsavai 		return (status);
4525b509e89bSRishi Srivatsavai 
4526b509e89bSRishi Srivatsavai 	if (!(state->ls_flags & flags))
4527b509e89bSRishi Srivatsavai 		return (DLADM_STATUS_NOTFOUND);
4528b509e89bSRishi Srivatsavai 
4529b509e89bSRishi Srivatsavai 	if ((status = dladm_simnet_info(handle, linkid, &slinfo,
4530b509e89bSRishi Srivatsavai 	    state->ls_flags)) != DLADM_STATUS_OK)
4531b509e89bSRishi Srivatsavai 		return (status);
4532b509e89bSRishi Srivatsavai 
4533b509e89bSRishi Srivatsavai 	if (slinfo.sna_peer_link_id != DATALINK_INVALID_LINKID &&
4534b509e89bSRishi Srivatsavai 	    (status = dladm_datalink_id2info(handle, slinfo.sna_peer_link_id,
4535b509e89bSRishi Srivatsavai 	    NULL, NULL, NULL, slbuf.simnet_otherlink,
4536b509e89bSRishi Srivatsavai 	    sizeof (slbuf.simnet_otherlink))) !=
4537b509e89bSRishi Srivatsavai 	    DLADM_STATUS_OK)
4538b509e89bSRishi Srivatsavai 		return (status);
4539b509e89bSRishi Srivatsavai 
4540b509e89bSRishi Srivatsavai 	if (slinfo.sna_mac_len > sizeof (slbuf.simnet_macaddr))
4541b509e89bSRishi Srivatsavai 		return (DLADM_STATUS_BADVAL);
4542b509e89bSRishi Srivatsavai 
4543b509e89bSRishi Srivatsavai 	(void) strlcpy(slbuf.simnet_macaddr,
4544b509e89bSRishi Srivatsavai 	    dladm_aggr_macaddr2str(slinfo.sna_mac_addr, mstr),
4545b509e89bSRishi Srivatsavai 	    sizeof (slbuf.simnet_macaddr));
4546b509e89bSRishi Srivatsavai 	(void) dladm_media2str(slinfo.sna_type, slbuf.simnet_media);
4547b509e89bSRishi Srivatsavai 
4548b509e89bSRishi Srivatsavai 	ofmt_print(state->ls_ofmt, &slbuf);
4549b509e89bSRishi Srivatsavai 	return (status);
4550b509e89bSRishi Srivatsavai }
4551b509e89bSRishi Srivatsavai 
4552b509e89bSRishi Srivatsavai /* ARGSUSED */
4553b509e89bSRishi Srivatsavai static int
4554b509e89bSRishi Srivatsavai show_simnet(dladm_handle_t dh, datalink_id_t linkid, void *arg)
4555b509e89bSRishi Srivatsavai {
4556b509e89bSRishi Srivatsavai 	show_state_t		*state = arg;
4557b509e89bSRishi Srivatsavai 
4558b509e89bSRishi Srivatsavai 	state->ls_status = print_simnet(state, linkid);
4559b509e89bSRishi Srivatsavai 	return (DLADM_WALK_CONTINUE);
4560b509e89bSRishi Srivatsavai }
4561b509e89bSRishi Srivatsavai 
4562b509e89bSRishi Srivatsavai static void
4563b509e89bSRishi Srivatsavai do_show_simnet(int argc, char *argv[], const char *use)
4564b509e89bSRishi Srivatsavai {
4565b509e89bSRishi Srivatsavai 	int		option;
4566b509e89bSRishi Srivatsavai 	uint32_t	flags = DLADM_OPT_ACTIVE;
4567b509e89bSRishi Srivatsavai 	boolean_t	p_arg = B_FALSE;
4568b509e89bSRishi Srivatsavai 	datalink_id_t	linkid = DATALINK_ALL_LINKID;
4569b509e89bSRishi Srivatsavai 	show_state_t	state;
4570b509e89bSRishi Srivatsavai 	dladm_status_t	status;
4571b509e89bSRishi Srivatsavai 	boolean_t	o_arg = B_FALSE;
4572b509e89bSRishi Srivatsavai 	ofmt_handle_t	ofmt;
4573b509e89bSRishi Srivatsavai 	ofmt_status_t	oferr;
4574b509e89bSRishi Srivatsavai 	char		*all_fields = "link,media,macaddress,otherlink";
4575b509e89bSRishi Srivatsavai 	char		*fields_str = all_fields;
4576b509e89bSRishi Srivatsavai 	uint_t		ofmtflags = 0;
4577b509e89bSRishi Srivatsavai 
4578b509e89bSRishi Srivatsavai 	bzero(&state, sizeof (state));
4579b509e89bSRishi Srivatsavai 
4580b509e89bSRishi Srivatsavai 	opterr = 0;
4581b509e89bSRishi Srivatsavai 	while ((option = getopt_long(argc, argv, ":pPo:",
4582b509e89bSRishi Srivatsavai 	    show_lopts, NULL)) != -1) {
4583b509e89bSRishi Srivatsavai 		switch (option) {
4584b509e89bSRishi Srivatsavai 		case 'p':
4585b509e89bSRishi Srivatsavai 			if (p_arg)
4586b509e89bSRishi Srivatsavai 				die_optdup(option);
4587b509e89bSRishi Srivatsavai 
4588b509e89bSRishi Srivatsavai 			p_arg = B_TRUE;
4589b509e89bSRishi Srivatsavai 			state.ls_parsable = p_arg;
4590b509e89bSRishi Srivatsavai 			break;
4591b509e89bSRishi Srivatsavai 		case 'P':
4592b509e89bSRishi Srivatsavai 			if (flags != DLADM_OPT_ACTIVE)
4593b509e89bSRishi Srivatsavai 				die_optdup(option);
4594b509e89bSRishi Srivatsavai 
4595b509e89bSRishi Srivatsavai 			flags = DLADM_OPT_PERSIST;
4596b509e89bSRishi Srivatsavai 			break;
4597b509e89bSRishi Srivatsavai 		case 'o':
4598b509e89bSRishi Srivatsavai 			o_arg = B_TRUE;
4599b509e89bSRishi Srivatsavai 			fields_str = optarg;
4600b509e89bSRishi Srivatsavai 			break;
4601b509e89bSRishi Srivatsavai 		default:
4602b509e89bSRishi Srivatsavai 			die_opterr(optopt, option, use);
4603b509e89bSRishi Srivatsavai 			break;
4604b509e89bSRishi Srivatsavai 		}
4605b509e89bSRishi Srivatsavai 	}
4606b509e89bSRishi Srivatsavai 
4607b509e89bSRishi Srivatsavai 	if (p_arg && !o_arg)
4608b509e89bSRishi Srivatsavai 		die("-p requires -o");
4609b509e89bSRishi Srivatsavai 
4610b509e89bSRishi Srivatsavai 	if (strcasecmp(fields_str, "all") == 0) {
4611b509e89bSRishi Srivatsavai 		if (p_arg)
4612b509e89bSRishi Srivatsavai 			die("\"-o all\" is invalid with -p");
4613b509e89bSRishi Srivatsavai 		fields_str = all_fields;
4614b509e89bSRishi Srivatsavai 	}
4615b509e89bSRishi Srivatsavai 
4616b509e89bSRishi Srivatsavai 	/* get link name (optional last argument) */
4617b509e89bSRishi Srivatsavai 	if (optind == (argc-1)) {
4618b509e89bSRishi Srivatsavai 		if ((status = dladm_name2info(handle, argv[optind], &linkid,
4619b509e89bSRishi Srivatsavai 		    NULL, NULL, NULL)) != DLADM_STATUS_OK) {
4620b509e89bSRishi Srivatsavai 			die_dlerr(status, "link %s is not valid", argv[optind]);
4621b509e89bSRishi Srivatsavai 		}
4622b509e89bSRishi Srivatsavai 	} else if (optind != argc) {
4623b509e89bSRishi Srivatsavai 		usage();
4624b509e89bSRishi Srivatsavai 	}
4625b509e89bSRishi Srivatsavai 
4626b509e89bSRishi Srivatsavai 	state.ls_flags = flags;
4627b509e89bSRishi Srivatsavai 	state.ls_donefirst = B_FALSE;
4628b509e89bSRishi Srivatsavai 	if (state.ls_parsable)
4629b509e89bSRishi Srivatsavai 		ofmtflags |= OFMT_PARSABLE;
4630b509e89bSRishi Srivatsavai 	oferr = ofmt_open(fields_str, simnet_fields, ofmtflags, 0, &ofmt);
4631b509e89bSRishi Srivatsavai 	dladm_ofmt_check(oferr, state.ls_parsable, ofmt);
4632b509e89bSRishi Srivatsavai 	state.ls_ofmt = ofmt;
4633b509e89bSRishi Srivatsavai 
4634b509e89bSRishi Srivatsavai 	if (linkid == DATALINK_ALL_LINKID) {
4635b509e89bSRishi Srivatsavai 		(void) dladm_walk_datalink_id(show_simnet, handle, &state,
4636b509e89bSRishi Srivatsavai 		    DATALINK_CLASS_SIMNET, DATALINK_ANY_MEDIATYPE, flags);
4637b509e89bSRishi Srivatsavai 	} else {
4638b509e89bSRishi Srivatsavai 		(void) show_simnet(handle, linkid, &state);
4639b509e89bSRishi Srivatsavai 		if (state.ls_status != DLADM_STATUS_OK) {
4640b509e89bSRishi Srivatsavai 			ofmt_close(ofmt);
4641b509e89bSRishi Srivatsavai 			die_dlerr(state.ls_status, "failed to show simnet %s",
4642b509e89bSRishi Srivatsavai 			    argv[optind]);
4643b509e89bSRishi Srivatsavai 		}
4644b509e89bSRishi Srivatsavai 	}
4645b509e89bSRishi Srivatsavai 	ofmt_close(ofmt);
4646b509e89bSRishi Srivatsavai }
4647b509e89bSRishi Srivatsavai 
4648da14cebeSEric Cheng static void
46496be03d0bSVasumathi Sundaram - Sun Microsystems link_stats(datalink_id_t linkid, uint_t interval, char *fields_str,
46506be03d0bSVasumathi Sundaram - Sun Microsystems     show_state_t *state)
4651d62bc4baSyz147064 {
46528002d411SSowmini Varadhan 	ofmt_handle_t	ofmt;
46538002d411SSowmini Varadhan 	ofmt_status_t	oferr;
46548002d411SSowmini Varadhan 	uint_t		ofmtflags = 0;
465533343a97Smeem 
46568002d411SSowmini Varadhan 	if (state->ls_parsable)
46578002d411SSowmini Varadhan 		ofmtflags |= OFMT_PARSABLE;
46588002d411SSowmini Varadhan 	oferr = ofmt_open(fields_str, link_s_fields, ofmtflags, 0, &ofmt);
46598002d411SSowmini Varadhan 	dladm_ofmt_check(oferr, state->ls_parsable, ofmt);
46608002d411SSowmini Varadhan 	state->ls_ofmt = ofmt;
46617c478bd9Sstevel@tonic-gate 
46627c478bd9Sstevel@tonic-gate 	/*
46637c478bd9Sstevel@tonic-gate 	 * If an interval is specified, continuously show the stats
46647c478bd9Sstevel@tonic-gate 	 * only for the first MAC port.
46657c478bd9Sstevel@tonic-gate 	 */
46666be03d0bSVasumathi Sundaram - Sun Microsystems 	state->ls_firstonly = (interval != 0);
46677c478bd9Sstevel@tonic-gate 
46687c478bd9Sstevel@tonic-gate 	for (;;) {
46696be03d0bSVasumathi Sundaram - Sun Microsystems 		state->ls_donefirst = B_FALSE;
4670d62bc4baSyz147064 		if (linkid == DATALINK_ALL_LINKID) {
46714ac67f02SAnurag S. Maskey 			(void) dladm_walk_datalink_id(show_link_stats, handle,
46724ac67f02SAnurag S. Maskey 			    state, DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE,
4673d62bc4baSyz147064 			    DLADM_OPT_ACTIVE);
4674d62bc4baSyz147064 		} else {
46754ac67f02SAnurag S. Maskey 			(void) show_link_stats(handle, linkid, state);
4676d62bc4baSyz147064 		}
46777c478bd9Sstevel@tonic-gate 
46787c478bd9Sstevel@tonic-gate 		if (interval == 0)
46797c478bd9Sstevel@tonic-gate 			break;
46807c478bd9Sstevel@tonic-gate 
4681c3affd82SMichael Lim 		(void) fflush(stdout);
46827c478bd9Sstevel@tonic-gate 		(void) sleep(interval);
46837c478bd9Sstevel@tonic-gate 	}
46848002d411SSowmini Varadhan 	ofmt_close(ofmt);
46857c478bd9Sstevel@tonic-gate }
46867c478bd9Sstevel@tonic-gate 
46877c478bd9Sstevel@tonic-gate static void
4688d62bc4baSyz147064 aggr_stats(datalink_id_t linkid, show_grp_state_t *state, uint_t interval)
46897c478bd9Sstevel@tonic-gate {
46907c478bd9Sstevel@tonic-gate 	/*
46917c478bd9Sstevel@tonic-gate 	 * If an interval is specified, continuously show the stats
46927c478bd9Sstevel@tonic-gate 	 * only for the first group.
46937c478bd9Sstevel@tonic-gate 	 */
4694d62bc4baSyz147064 	state->gs_firstonly = (interval != 0);
46957c478bd9Sstevel@tonic-gate 
46967c478bd9Sstevel@tonic-gate 	for (;;) {
4697d62bc4baSyz147064 		state->gs_donefirst = B_FALSE;
4698d62bc4baSyz147064 		if (linkid == DATALINK_ALL_LINKID)
46994ac67f02SAnurag S. Maskey 			(void) dladm_walk_datalink_id(show_aggr, handle, state,
4700d62bc4baSyz147064 			    DATALINK_CLASS_AGGR, DATALINK_ANY_MEDIATYPE,
4701d62bc4baSyz147064 			    DLADM_OPT_ACTIVE);
4702d62bc4baSyz147064 		else
47034ac67f02SAnurag S. Maskey 			(void) show_aggr(handle, linkid, state);
47047c478bd9Sstevel@tonic-gate 
47057c478bd9Sstevel@tonic-gate 		if (interval == 0)
47067c478bd9Sstevel@tonic-gate 			break;
47077c478bd9Sstevel@tonic-gate 
4708c3affd82SMichael Lim 		(void) fflush(stdout);
47097c478bd9Sstevel@tonic-gate 		(void) sleep(interval);
47107c478bd9Sstevel@tonic-gate 	}
47117c478bd9Sstevel@tonic-gate }
47127c478bd9Sstevel@tonic-gate 
4713da14cebeSEric Cheng /* ARGSUSED */
47147c478bd9Sstevel@tonic-gate static void
4715da14cebeSEric Cheng vnic_stats(show_vnic_state_t *sp, uint32_t interval)
47167c478bd9Sstevel@tonic-gate {
4717da14cebeSEric Cheng 	show_vnic_state_t	state;
4718da14cebeSEric Cheng 	boolean_t		specific_link, specific_dev;
47197c478bd9Sstevel@tonic-gate 
4720da14cebeSEric Cheng 	/* Display vnic statistics */
4721da14cebeSEric Cheng 	dump_vnics_head(sp->vs_link);
4722e7801d59Ssowmini 
4723da14cebeSEric Cheng 	bzero(&state, sizeof (state));
4724da14cebeSEric Cheng 	state.vs_stats = B_TRUE;
4725da14cebeSEric Cheng 	state.vs_vnic_id = sp->vs_vnic_id;
4726da14cebeSEric Cheng 	state.vs_link_id = sp->vs_link_id;
47277c478bd9Sstevel@tonic-gate 
47287c478bd9Sstevel@tonic-gate 	/*
4729da14cebeSEric Cheng 	 * If an interval is specified, and a vnic ID is not specified,
4730da14cebeSEric Cheng 	 * continuously show the stats only for the first vnic.
47317c478bd9Sstevel@tonic-gate 	 */
4732da14cebeSEric Cheng 	specific_link = (sp->vs_vnic_id != DATALINK_ALL_LINKID);
4733da14cebeSEric Cheng 	specific_dev = (sp->vs_link_id != DATALINK_ALL_LINKID);
47347c478bd9Sstevel@tonic-gate 
47357c478bd9Sstevel@tonic-gate 	for (;;) {
4736da14cebeSEric Cheng 		/* Get stats for each vnic */
4737da14cebeSEric Cheng 		state.vs_found = B_FALSE;
4738da14cebeSEric Cheng 		state.vs_donefirst = B_FALSE;
4739da14cebeSEric Cheng 		state.vs_printstats = B_FALSE;
4740da14cebeSEric Cheng 		state.vs_flags = DLADM_OPT_ACTIVE;
47417c478bd9Sstevel@tonic-gate 
4742da14cebeSEric Cheng 		if (!specific_link) {
47434ac67f02SAnurag S. Maskey 			(void) dladm_walk_datalink_id(show_vnic, handle, &state,
4744da14cebeSEric Cheng 			    DATALINK_CLASS_VNIC, DATALINK_ANY_MEDIATYPE,
4745da14cebeSEric Cheng 			    DLADM_OPT_ACTIVE);
4746da14cebeSEric Cheng 		} else {
47474ac67f02SAnurag S. Maskey 			(void) show_vnic(handle, sp->vs_vnic_id, &state);
4748da14cebeSEric Cheng 			if (state.vs_status != DLADM_STATUS_OK) {
4749da14cebeSEric Cheng 				die_dlerr(state.vs_status,
4750da14cebeSEric Cheng 				    "failed to show vnic '%s'", sp->vs_vnic);
4751da14cebeSEric Cheng 			}
4752da14cebeSEric Cheng 		}
47537c478bd9Sstevel@tonic-gate 
4754da14cebeSEric Cheng 		if (specific_link && !state.vs_found)
4755da14cebeSEric Cheng 			die("non-existent vnic '%s'", sp->vs_vnic);
4756da14cebeSEric Cheng 		if (specific_dev && !state.vs_found)
4757da14cebeSEric Cheng 			die("device %s has no vnics", sp->vs_link);
4758da14cebeSEric Cheng 
4759da14cebeSEric Cheng 		/* Show totals */
4760da14cebeSEric Cheng 		if ((specific_link | specific_dev) && !interval) {
4761da14cebeSEric Cheng 			(void) printf("Total");
4762da14cebeSEric Cheng 			(void) printf("\t%-10llu",
4763da14cebeSEric Cheng 			    state.vs_totalstats.ipackets);
4764da14cebeSEric Cheng 			(void) printf("%-12llu",
4765da14cebeSEric Cheng 			    state.vs_totalstats.rbytes);
4766da14cebeSEric Cheng 			(void) printf("%-10llu",
4767da14cebeSEric Cheng 			    state.vs_totalstats.opackets);
4768da14cebeSEric Cheng 			(void) printf("%-12llu\n",
4769da14cebeSEric Cheng 			    state.vs_totalstats.obytes);
4770da14cebeSEric Cheng 		}
4771da14cebeSEric Cheng 
4772da14cebeSEric Cheng 		/* Show stats for each vnic */
4773da14cebeSEric Cheng 		state.vs_donefirst = B_FALSE;
4774da14cebeSEric Cheng 		state.vs_printstats = B_TRUE;
4775da14cebeSEric Cheng 
4776da14cebeSEric Cheng 		if (!specific_link) {
47774ac67f02SAnurag S. Maskey 			(void) dladm_walk_datalink_id(show_vnic, handle, &state,
4778da14cebeSEric Cheng 			    DATALINK_CLASS_VNIC, DATALINK_ANY_MEDIATYPE,
4779da14cebeSEric Cheng 			    DLADM_OPT_ACTIVE);
4780da14cebeSEric Cheng 		} else {
47814ac67f02SAnurag S. Maskey 			(void) show_vnic(handle, sp->vs_vnic_id, &state);
4782da14cebeSEric Cheng 			if (state.vs_status != DLADM_STATUS_OK) {
4783da14cebeSEric Cheng 				die_dlerr(state.vs_status,
4784da14cebeSEric Cheng 				    "failed to show vnic '%s'", sp->vs_vnic);
4785da14cebeSEric Cheng 			}
4786da14cebeSEric Cheng 		}
47877c478bd9Sstevel@tonic-gate 
47887c478bd9Sstevel@tonic-gate 		if (interval == 0)
47897c478bd9Sstevel@tonic-gate 			break;
47907c478bd9Sstevel@tonic-gate 
4791c3affd82SMichael Lim 		(void) fflush(stdout);
47927c478bd9Sstevel@tonic-gate 		(void) sleep(interval);
47937c478bd9Sstevel@tonic-gate 	}
47947c478bd9Sstevel@tonic-gate }
47957c478bd9Sstevel@tonic-gate 
47967c478bd9Sstevel@tonic-gate static void
4797da14cebeSEric Cheng get_mac_stats(const char *dev, pktsum_t *stats)
47987c478bd9Sstevel@tonic-gate {
47997c478bd9Sstevel@tonic-gate 	kstat_ctl_t	*kcp;
48007c478bd9Sstevel@tonic-gate 	kstat_t		*ksp;
4801da14cebeSEric Cheng 	char module[DLPI_LINKNAME_MAX];
4802da14cebeSEric Cheng 	uint_t instance;
4803da14cebeSEric Cheng 
4804da14cebeSEric Cheng 
4805da14cebeSEric Cheng 	bzero(stats, sizeof (*stats));
4806da14cebeSEric Cheng 
4807da14cebeSEric Cheng 	if (dlpi_parselink(dev, module, &instance) != DLPI_SUCCESS)
4808da14cebeSEric Cheng 		return;
48097c478bd9Sstevel@tonic-gate 
48107c478bd9Sstevel@tonic-gate 	if ((kcp = kstat_open()) == NULL) {
481133343a97Smeem 		warn("kstat open operation failed");
48127c478bd9Sstevel@tonic-gate 		return;
48137c478bd9Sstevel@tonic-gate 	}
48147c478bd9Sstevel@tonic-gate 
4815da14cebeSEric Cheng 	ksp = dladm_kstat_lookup(kcp, module, instance, "mac", NULL);
4816da14cebeSEric Cheng 	if (ksp != NULL)
4817da14cebeSEric Cheng 		dladm_get_stats(kcp, ksp, stats);
4818da14cebeSEric Cheng 
48197c478bd9Sstevel@tonic-gate 	(void) kstat_close(kcp);
48207c478bd9Sstevel@tonic-gate 
48217c478bd9Sstevel@tonic-gate }
48227c478bd9Sstevel@tonic-gate 
48237c478bd9Sstevel@tonic-gate static void
48247c478bd9Sstevel@tonic-gate get_link_stats(const char *link, pktsum_t *stats)
48257c478bd9Sstevel@tonic-gate {
4826da14cebeSEric Cheng 	kstat_ctl_t	*kcp;
4827da14cebeSEric Cheng 	kstat_t		*ksp;
4828da14cebeSEric Cheng 
48297c478bd9Sstevel@tonic-gate 	bzero(stats, sizeof (*stats));
4830da14cebeSEric Cheng 
4831da14cebeSEric Cheng 	if ((kcp = kstat_open()) == NULL) {
4832da14cebeSEric Cheng 		warn("kstat_open operation failed");
4833da14cebeSEric Cheng 		return;
4834da14cebeSEric Cheng 	}
4835da14cebeSEric Cheng 
4836da14cebeSEric Cheng 	ksp = dladm_kstat_lookup(kcp, "link", 0, link, NULL);
4837da14cebeSEric Cheng 
4838da14cebeSEric Cheng 	if (ksp != NULL)
4839da14cebeSEric Cheng 		dladm_get_stats(kcp, ksp, stats);
4840da14cebeSEric Cheng 
4841da14cebeSEric Cheng 	(void) kstat_close(kcp);
48427c478bd9Sstevel@tonic-gate }
48437c478bd9Sstevel@tonic-gate 
4844ba2e4443Sseb static int
4845d62bc4baSyz147064 query_kstat(char *module, int instance, const char *name, const char *stat,
4846d62bc4baSyz147064     uint8_t type, void *val)
48477c478bd9Sstevel@tonic-gate {
48487c478bd9Sstevel@tonic-gate 	kstat_ctl_t	*kcp;
48497c478bd9Sstevel@tonic-gate 	kstat_t		*ksp;
48507c478bd9Sstevel@tonic-gate 
48517c478bd9Sstevel@tonic-gate 	if ((kcp = kstat_open()) == NULL) {
485233343a97Smeem 		warn("kstat open operation failed");
4853ba2e4443Sseb 		return (-1);
48547c478bd9Sstevel@tonic-gate 	}
48557c478bd9Sstevel@tonic-gate 
4856d62bc4baSyz147064 	if ((ksp = kstat_lookup(kcp, module, instance, (char *)name)) == NULL) {
48577c478bd9Sstevel@tonic-gate 		/*
48587c478bd9Sstevel@tonic-gate 		 * The kstat query could fail if the underlying MAC
48597c478bd9Sstevel@tonic-gate 		 * driver was already detached.
48607c478bd9Sstevel@tonic-gate 		 */
48617c478bd9Sstevel@tonic-gate 		goto bail;
48627c478bd9Sstevel@tonic-gate 	}
48637c478bd9Sstevel@tonic-gate 
48647c478bd9Sstevel@tonic-gate 	if (kstat_read(kcp, ksp, NULL) == -1) {
486533343a97Smeem 		warn("kstat read failed");
48667c478bd9Sstevel@tonic-gate 		goto bail;
48677c478bd9Sstevel@tonic-gate 	}
48687c478bd9Sstevel@tonic-gate 
4869e7801d59Ssowmini 	if (dladm_kstat_value(ksp, stat, type, val) < 0)
48707c478bd9Sstevel@tonic-gate 		goto bail;
4871ba2e4443Sseb 
4872ba2e4443Sseb 	(void) kstat_close(kcp);
4873ba2e4443Sseb 	return (0);
48747c478bd9Sstevel@tonic-gate 
48757c478bd9Sstevel@tonic-gate bail:
48767c478bd9Sstevel@tonic-gate 	(void) kstat_close(kcp);
4877ba2e4443Sseb 	return (-1);
4878ba2e4443Sseb }
4879ba2e4443Sseb 
4880d62bc4baSyz147064 static int
4881d62bc4baSyz147064 get_one_kstat(const char *name, const char *stat, uint8_t type,
4882d62bc4baSyz147064     void *val, boolean_t islink)
4883d62bc4baSyz147064 {
4884d62bc4baSyz147064 	char		module[DLPI_LINKNAME_MAX];
4885d62bc4baSyz147064 	uint_t		instance;
4886d62bc4baSyz147064 
4887d62bc4baSyz147064 	if (islink) {
4888d62bc4baSyz147064 		return (query_kstat("link", 0, name, stat, type, val));
4889d62bc4baSyz147064 	} else {
4890d62bc4baSyz147064 		if (dlpi_parselink(name, module, &instance) != DLPI_SUCCESS)
4891d62bc4baSyz147064 			return (-1);
4892d62bc4baSyz147064 
4893d62bc4baSyz147064 		return (query_kstat(module, instance, "mac", stat, type, val));
4894d62bc4baSyz147064 	}
4895d62bc4baSyz147064 }
4896d62bc4baSyz147064 
4897ba2e4443Sseb static uint64_t
4898d62bc4baSyz147064 get_ifspeed(const char *name, boolean_t islink)
4899ba2e4443Sseb {
4900ba2e4443Sseb 	uint64_t ifspeed = 0;
4901ba2e4443Sseb 
4902d62bc4baSyz147064 	(void) get_one_kstat(name, "ifspeed", KSTAT_DATA_UINT64,
4903d62bc4baSyz147064 	    &ifspeed, islink);
4904d62bc4baSyz147064 
49057c478bd9Sstevel@tonic-gate 	return (ifspeed);
49067c478bd9Sstevel@tonic-gate }
49077c478bd9Sstevel@tonic-gate 
4908f595a68aSyz147064 static const char *
4909d62bc4baSyz147064 get_linkstate(const char *name, boolean_t islink, char *buf)
49107c478bd9Sstevel@tonic-gate {
4911d62bc4baSyz147064 	link_state_t	linkstate;
49127c478bd9Sstevel@tonic-gate 
4913d62bc4baSyz147064 	if (get_one_kstat(name, "link_state", KSTAT_DATA_UINT32,
4914d62bc4baSyz147064 	    &linkstate, islink) != 0) {
4915da14cebeSEric Cheng 		(void) strlcpy(buf, "?", DLADM_STRSIZE);
49163a62633bSyz147064 		return (buf);
49177c478bd9Sstevel@tonic-gate 	}
4918d62bc4baSyz147064 	return (dladm_linkstate2str(linkstate, buf));
49197c478bd9Sstevel@tonic-gate }
49207c478bd9Sstevel@tonic-gate 
4921f595a68aSyz147064 static const char *
4922d62bc4baSyz147064 get_linkduplex(const char *name, boolean_t islink, char *buf)
49237c478bd9Sstevel@tonic-gate {
4924d62bc4baSyz147064 	link_duplex_t	linkduplex;
49257c478bd9Sstevel@tonic-gate 
4926d62bc4baSyz147064 	if (get_one_kstat(name, "link_duplex", KSTAT_DATA_UINT32,
4927d62bc4baSyz147064 	    &linkduplex, islink) != 0) {
49283a62633bSyz147064 		(void) strlcpy(buf, "unknown", DLADM_STRSIZE);
49293a62633bSyz147064 		return (buf);
49307c478bd9Sstevel@tonic-gate 	}
49317c478bd9Sstevel@tonic-gate 
4932d62bc4baSyz147064 	return (dladm_linkduplex2str(linkduplex, buf));
49337c478bd9Sstevel@tonic-gate }
49340ba2cbe9Sxc151355 
49350ba2cbe9Sxc151355 static int
49368002d411SSowmini Varadhan parse_wifi_fields(char *str, ofmt_handle_t *ofmt, uint_t cmdtype,
49378002d411SSowmini Varadhan     boolean_t parsable)
49380ba2cbe9Sxc151355 {
49398002d411SSowmini Varadhan 	ofmt_field_t	*template, *of;
49408002d411SSowmini Varadhan 	ofmt_cb_t	*fn;
49418002d411SSowmini Varadhan 	ofmt_status_t	oferr;
49420ba2cbe9Sxc151355 
49430ba2cbe9Sxc151355 	if (cmdtype == WIFI_CMD_SCAN) {
49448002d411SSowmini Varadhan 		template = wifi_common_fields;
49450ba2cbe9Sxc151355 		if (str == NULL)
49460ba2cbe9Sxc151355 			str = def_scan_wifi_fields;
49470ba2cbe9Sxc151355 		if (strcasecmp(str, "all") == 0)
49480ba2cbe9Sxc151355 			str = all_scan_wifi_fields;
49498002d411SSowmini Varadhan 		fn = print_wlan_attr_cb;
49500ba2cbe9Sxc151355 	} else if (cmdtype == WIFI_CMD_SHOW) {
49518002d411SSowmini Varadhan 		bcopy(wifi_common_fields, &wifi_show_fields[2],
49528002d411SSowmini Varadhan 		    sizeof (wifi_common_fields));
49538002d411SSowmini Varadhan 		template = wifi_show_fields;
49540ba2cbe9Sxc151355 		if (str == NULL)
49550ba2cbe9Sxc151355 			str = def_show_wifi_fields;
49560ba2cbe9Sxc151355 		if (strcasecmp(str, "all") == 0)
49570ba2cbe9Sxc151355 			str = all_show_wifi_fields;
49588002d411SSowmini Varadhan 		fn = print_link_attr_cb;
49590ba2cbe9Sxc151355 	} else {
49600ba2cbe9Sxc151355 		return (-1);
49610ba2cbe9Sxc151355 	}
49628002d411SSowmini Varadhan 
49638002d411SSowmini Varadhan 	for (of = template; of->of_name != NULL; of++) {
49648002d411SSowmini Varadhan 		if (of->of_cb == NULL)
49658002d411SSowmini Varadhan 			of->of_cb = fn;
49668002d411SSowmini Varadhan 	}
49678002d411SSowmini Varadhan 
49688002d411SSowmini Varadhan 	oferr = ofmt_open(str, template, (parsable ? OFMT_PARSABLE : 0),
49698002d411SSowmini Varadhan 	    0, ofmt);
49708002d411SSowmini Varadhan 	dladm_ofmt_check(oferr, parsable, *ofmt);
4971e7801d59Ssowmini 	return (0);
49720ba2cbe9Sxc151355 }
49730ba2cbe9Sxc151355 
49740ba2cbe9Sxc151355 typedef struct print_wifi_state {
4975d62bc4baSyz147064 	char		*ws_link;
49768002d411SSowmini Varadhan 	boolean_t	ws_parsable;
49770ba2cbe9Sxc151355 	boolean_t	ws_header;
49788002d411SSowmini Varadhan 	ofmt_handle_t	ws_ofmt;
49790ba2cbe9Sxc151355 } print_wifi_state_t;
49800ba2cbe9Sxc151355 
4981e7801d59Ssowmini typedef struct  wlan_scan_args_s {
4982e7801d59Ssowmini 	print_wifi_state_t	*ws_state;
4983e7801d59Ssowmini 	void			*ws_attr;
4984e7801d59Ssowmini } wlan_scan_args_t;
49850ba2cbe9Sxc151355 
49868002d411SSowmini Varadhan static boolean_t
49878002d411SSowmini Varadhan print_wlan_attr_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize)
49880ba2cbe9Sxc151355 {
49898002d411SSowmini Varadhan 	wlan_scan_args_t	*w = ofarg->ofmt_cbarg;
4990e7801d59Ssowmini 	print_wifi_state_t	*statep = w->ws_state;
4991e7801d59Ssowmini 	dladm_wlan_attr_t	*attrp = w->ws_attr;
49928002d411SSowmini Varadhan 	char			tmpbuf[DLADM_STRSIZE];
49930ba2cbe9Sxc151355 
49948002d411SSowmini Varadhan 	if (ofarg->ofmt_id == 0) {
49958002d411SSowmini Varadhan 		(void) strlcpy(buf, (char *)statep->ws_link, bufsize);
49968002d411SSowmini Varadhan 		return (B_TRUE);
49970ba2cbe9Sxc151355 	}
49980ba2cbe9Sxc151355 
49998002d411SSowmini Varadhan 	if ((ofarg->ofmt_id & attrp->wa_valid) == 0)
50008002d411SSowmini Varadhan 		return (B_TRUE);
50010ba2cbe9Sxc151355 
50028002d411SSowmini Varadhan 	switch (ofarg->ofmt_id) {
5003f595a68aSyz147064 	case DLADM_WLAN_ATTR_ESSID:
50048002d411SSowmini Varadhan 		(void) dladm_wlan_essid2str(&attrp->wa_essid, tmpbuf);
50050ba2cbe9Sxc151355 		break;
5006f595a68aSyz147064 	case DLADM_WLAN_ATTR_BSSID:
50078002d411SSowmini Varadhan 		(void) dladm_wlan_bssid2str(&attrp->wa_bssid, tmpbuf);
50080ba2cbe9Sxc151355 		break;
5009f595a68aSyz147064 	case DLADM_WLAN_ATTR_SECMODE:
50108002d411SSowmini Varadhan 		(void) dladm_wlan_secmode2str(&attrp->wa_secmode, tmpbuf);
50110ba2cbe9Sxc151355 		break;
5012f595a68aSyz147064 	case DLADM_WLAN_ATTR_STRENGTH:
50138002d411SSowmini Varadhan 		(void) dladm_wlan_strength2str(&attrp->wa_strength, tmpbuf);
50140ba2cbe9Sxc151355 		break;
5015f595a68aSyz147064 	case DLADM_WLAN_ATTR_MODE:
50168002d411SSowmini Varadhan 		(void) dladm_wlan_mode2str(&attrp->wa_mode, tmpbuf);
50170ba2cbe9Sxc151355 		break;
5018f595a68aSyz147064 	case DLADM_WLAN_ATTR_SPEED:
50198002d411SSowmini Varadhan 		(void) dladm_wlan_speed2str(&attrp->wa_speed, tmpbuf);
50208002d411SSowmini Varadhan 		(void) strlcat(tmpbuf, "Mb", sizeof (tmpbuf));
50210ba2cbe9Sxc151355 		break;
5022f595a68aSyz147064 	case DLADM_WLAN_ATTR_AUTH:
50238002d411SSowmini Varadhan 		(void) dladm_wlan_auth2str(&attrp->wa_auth, tmpbuf);
50240ba2cbe9Sxc151355 		break;
5025f595a68aSyz147064 	case DLADM_WLAN_ATTR_BSSTYPE:
50268002d411SSowmini Varadhan 		(void) dladm_wlan_bsstype2str(&attrp->wa_bsstype, tmpbuf);
50270ba2cbe9Sxc151355 		break;
50280ba2cbe9Sxc151355 	}
50298002d411SSowmini Varadhan 	(void) strlcpy(buf, tmpbuf, bufsize);
50300ba2cbe9Sxc151355 
50318002d411SSowmini Varadhan 	return (B_TRUE);
50320ba2cbe9Sxc151355 }
50330ba2cbe9Sxc151355 
50340ba2cbe9Sxc151355 static boolean_t
5035f595a68aSyz147064 print_scan_results(void *arg, dladm_wlan_attr_t *attrp)
50360ba2cbe9Sxc151355 {
50370ba2cbe9Sxc151355 	print_wifi_state_t	*statep = arg;
5038e7801d59Ssowmini 	wlan_scan_args_t	warg;
50390ba2cbe9Sxc151355 
5040e7801d59Ssowmini 	bzero(&warg, sizeof (warg));
5041e7801d59Ssowmini 	warg.ws_state = statep;
5042e7801d59Ssowmini 	warg.ws_attr = attrp;
50438002d411SSowmini Varadhan 	ofmt_print(statep->ws_ofmt, &warg);
50440ba2cbe9Sxc151355 	return (B_TRUE);
50450ba2cbe9Sxc151355 }
50460ba2cbe9Sxc151355 
5047d62bc4baSyz147064 static int
50484ac67f02SAnurag S. Maskey scan_wifi(dladm_handle_t dh, datalink_id_t linkid, void *arg)
50490ba2cbe9Sxc151355 {
50500ba2cbe9Sxc151355 	print_wifi_state_t	*statep = arg;
5051f595a68aSyz147064 	dladm_status_t		status;
5052d62bc4baSyz147064 	char			link[MAXLINKNAMELEN];
5053d62bc4baSyz147064 
50544ac67f02SAnurag S. Maskey 	if ((status = dladm_datalink_id2info(dh, linkid, NULL, NULL, NULL, link,
5055e7801d59Ssowmini 	    sizeof (link))) != DLADM_STATUS_OK) {
5056d62bc4baSyz147064 		return (DLADM_WALK_CONTINUE);
5057d62bc4baSyz147064 	}
50580ba2cbe9Sxc151355 
50590ba2cbe9Sxc151355 	statep->ws_link = link;
50604ac67f02SAnurag S. Maskey 	status = dladm_wlan_scan(dh, linkid, statep, print_scan_results);
5061f595a68aSyz147064 	if (status != DLADM_STATUS_OK)
5062d62bc4baSyz147064 		die_dlerr(status, "cannot scan link '%s'", statep->ws_link);
506333343a97Smeem 
5064d62bc4baSyz147064 	return (DLADM_WALK_CONTINUE);
50650ba2cbe9Sxc151355 }
50660ba2cbe9Sxc151355 
50678002d411SSowmini Varadhan static boolean_t
50688002d411SSowmini Varadhan print_wifi_status_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize)
50690ba2cbe9Sxc151355 {
50708002d411SSowmini Varadhan 	static char		tmpbuf[DLADM_STRSIZE];
50718002d411SSowmini Varadhan 	wlan_scan_args_t	*w = ofarg->ofmt_cbarg;
50728002d411SSowmini Varadhan 	dladm_wlan_linkattr_t	*attrp = w->ws_attr;
50738002d411SSowmini Varadhan 
50748002d411SSowmini Varadhan 	if ((ofarg->ofmt_id & attrp->la_valid) != 0) {
50758002d411SSowmini Varadhan 		(void) dladm_wlan_linkstatus2str(&attrp->la_status, tmpbuf);
50768002d411SSowmini Varadhan 		(void) strlcpy(buf, tmpbuf, bufsize);
50778002d411SSowmini Varadhan 	}
50788002d411SSowmini Varadhan 	return (B_TRUE);
50798002d411SSowmini Varadhan }
50808002d411SSowmini Varadhan 
50818002d411SSowmini Varadhan static boolean_t
50828002d411SSowmini Varadhan print_link_attr_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize)
50838002d411SSowmini Varadhan {
50848002d411SSowmini Varadhan 	wlan_scan_args_t	*w = ofarg->ofmt_cbarg, w1;
5085e7801d59Ssowmini 	print_wifi_state_t	*statep = w->ws_state;
5086e7801d59Ssowmini 	dladm_wlan_linkattr_t	*attrp = w->ws_attr;
50870ba2cbe9Sxc151355 
5088e7801d59Ssowmini 	bzero(&w1, sizeof (w1));
5089e7801d59Ssowmini 	w1.ws_state = statep;
5090e7801d59Ssowmini 	w1.ws_attr = &attrp->la_wlan_attr;
50918002d411SSowmini Varadhan 	ofarg->ofmt_cbarg = &w1;
50928002d411SSowmini Varadhan 	return (print_wlan_attr_cb(ofarg, buf, bufsize));
50930ba2cbe9Sxc151355 }
50940ba2cbe9Sxc151355 
5095d62bc4baSyz147064 static int
50964ac67f02SAnurag S. Maskey show_wifi(dladm_handle_t dh, datalink_id_t linkid, void *arg)
50970ba2cbe9Sxc151355 {
50980ba2cbe9Sxc151355 	print_wifi_state_t	*statep = arg;
5099f595a68aSyz147064 	dladm_wlan_linkattr_t	attr;
5100f595a68aSyz147064 	dladm_status_t		status;
5101d62bc4baSyz147064 	char			link[MAXLINKNAMELEN];
5102e7801d59Ssowmini 	wlan_scan_args_t	warg;
51030ba2cbe9Sxc151355 
51044ac67f02SAnurag S. Maskey 	if ((status = dladm_datalink_id2info(dh, linkid, NULL, NULL, NULL, link,
5105e7801d59Ssowmini 	    sizeof (link))) != DLADM_STATUS_OK) {
5106d62bc4baSyz147064 		return (DLADM_WALK_CONTINUE);
5107d62bc4baSyz147064 	}
5108d62bc4baSyz147064 
51095f5c9f54SAnurag S. Maskey 	/* dladm_wlan_get_linkattr() memsets attr with 0 */
51104ac67f02SAnurag S. Maskey 	status = dladm_wlan_get_linkattr(dh, linkid, &attr);
5111f595a68aSyz147064 	if (status != DLADM_STATUS_OK)
5112d62bc4baSyz147064 		die_dlerr(status, "cannot get link attributes for %s", link);
5113d62bc4baSyz147064 
5114d62bc4baSyz147064 	statep->ws_link = link;
51150ba2cbe9Sxc151355 
5116e7801d59Ssowmini 	bzero(&warg, sizeof (warg));
5117e7801d59Ssowmini 	warg.ws_state = statep;
5118e7801d59Ssowmini 	warg.ws_attr = &attr;
51198002d411SSowmini Varadhan 	ofmt_print(statep->ws_ofmt, &warg);
5120d62bc4baSyz147064 	return (DLADM_WALK_CONTINUE);
51210ba2cbe9Sxc151355 }
51220ba2cbe9Sxc151355 
51230ba2cbe9Sxc151355 static void
51248d5c46e6Sam223141 do_display_wifi(int argc, char **argv, int cmd, const char *use)
51250ba2cbe9Sxc151355 {
51260ba2cbe9Sxc151355 	int			option;
51270ba2cbe9Sxc151355 	char			*fields_str = NULL;
51284ac67f02SAnurag S. Maskey 	int		(*callback)(dladm_handle_t, datalink_id_t, void *);
51290ba2cbe9Sxc151355 	print_wifi_state_t	state;
5130d62bc4baSyz147064 	datalink_id_t		linkid = DATALINK_ALL_LINKID;
5131f595a68aSyz147064 	dladm_status_t		status;
51320ba2cbe9Sxc151355 
51330ba2cbe9Sxc151355 	if (cmd == WIFI_CMD_SCAN)
51340ba2cbe9Sxc151355 		callback = scan_wifi;
51350ba2cbe9Sxc151355 	else if (cmd == WIFI_CMD_SHOW)
51360ba2cbe9Sxc151355 		callback = show_wifi;
51370ba2cbe9Sxc151355 	else
51380ba2cbe9Sxc151355 		return;
51390ba2cbe9Sxc151355 
51408002d411SSowmini Varadhan 	state.ws_parsable = B_FALSE;
51410ba2cbe9Sxc151355 	state.ws_header = B_TRUE;
51420ba2cbe9Sxc151355 	opterr = 0;
51430ba2cbe9Sxc151355 	while ((option = getopt_long(argc, argv, ":o:p",
51440ba2cbe9Sxc151355 	    wifi_longopts, NULL)) != -1) {
51450ba2cbe9Sxc151355 		switch (option) {
51460ba2cbe9Sxc151355 		case 'o':
51470ba2cbe9Sxc151355 			fields_str = optarg;
51480ba2cbe9Sxc151355 			break;
51490ba2cbe9Sxc151355 		case 'p':
51508002d411SSowmini Varadhan 			state.ws_parsable = B_TRUE;
51510ba2cbe9Sxc151355 			break;
51520ba2cbe9Sxc151355 		default:
51538d5c46e6Sam223141 			die_opterr(optopt, option, use);
51540ba2cbe9Sxc151355 		}
51550ba2cbe9Sxc151355 	}
51560ba2cbe9Sxc151355 
51578002d411SSowmini Varadhan 	if (state.ws_parsable && fields_str == NULL)
51580d365605Sschuster 		die("-p requires -o");
51590d365605Sschuster 
51608002d411SSowmini Varadhan 	if (state.ws_parsable && strcasecmp(fields_str, "all") == 0)
51610d365605Sschuster 		die("\"-o all\" is invalid with -p");
51620d365605Sschuster 
5163d62bc4baSyz147064 	if (optind == (argc - 1)) {
51644ac67f02SAnurag S. Maskey 		if ((status = dladm_name2info(handle, argv[optind], &linkid,
51654ac67f02SAnurag S. Maskey 		    NULL, NULL, NULL)) != DLADM_STATUS_OK) {
5166d62bc4baSyz147064 			die_dlerr(status, "link %s is not valid", argv[optind]);
5167d62bc4baSyz147064 		}
5168d62bc4baSyz147064 	} else if (optind != argc) {
51690ba2cbe9Sxc151355 		usage();
5170d62bc4baSyz147064 	}
51710ba2cbe9Sxc151355 
51728002d411SSowmini Varadhan 	if (parse_wifi_fields(fields_str, &state.ws_ofmt, cmd,
51738002d411SSowmini Varadhan 	    state.ws_parsable) < 0)
517433343a97Smeem 		die("invalid field(s) specified");
517533343a97Smeem 
5176d62bc4baSyz147064 	if (linkid == DATALINK_ALL_LINKID) {
51774ac67f02SAnurag S. Maskey 		(void) dladm_walk_datalink_id(callback, handle, &state,
5178b509e89bSRishi Srivatsavai 		    DATALINK_CLASS_PHYS | DATALINK_CLASS_SIMNET,
5179b509e89bSRishi Srivatsavai 		    DL_WIFI, DLADM_OPT_ACTIVE);
51800ba2cbe9Sxc151355 	} else {
51814ac67f02SAnurag S. Maskey 		(void) (*callback)(handle, linkid, &state);
51820ba2cbe9Sxc151355 	}
51838002d411SSowmini Varadhan 	ofmt_close(state.ws_ofmt);
51840ba2cbe9Sxc151355 }
51850ba2cbe9Sxc151355 
51860ba2cbe9Sxc151355 static void
51878d5c46e6Sam223141 do_scan_wifi(int argc, char **argv, const char *use)
51880ba2cbe9Sxc151355 {
51898d5c46e6Sam223141 	do_display_wifi(argc, argv, WIFI_CMD_SCAN, use);
51900ba2cbe9Sxc151355 }
51910ba2cbe9Sxc151355 
51920ba2cbe9Sxc151355 static void
51938d5c46e6Sam223141 do_show_wifi(int argc, char **argv, const char *use)
51940ba2cbe9Sxc151355 {
51958d5c46e6Sam223141 	do_display_wifi(argc, argv, WIFI_CMD_SHOW, use);
51960ba2cbe9Sxc151355 }
51970ba2cbe9Sxc151355 
51980ba2cbe9Sxc151355 typedef struct wlan_count_attr {
51990ba2cbe9Sxc151355 	uint_t		wc_count;
5200d62bc4baSyz147064 	datalink_id_t	wc_linkid;
52010ba2cbe9Sxc151355 } wlan_count_attr_t;
52020ba2cbe9Sxc151355 
52034ac67f02SAnurag S. Maskey /* ARGSUSED */
5204d62bc4baSyz147064 static int
52054ac67f02SAnurag S. Maskey do_count_wlan(dladm_handle_t dh, datalink_id_t linkid, void *arg)
52060ba2cbe9Sxc151355 {
520733343a97Smeem 	wlan_count_attr_t *cp = arg;
52080ba2cbe9Sxc151355 
52090ba2cbe9Sxc151355 	if (cp->wc_count == 0)
5210d62bc4baSyz147064 		cp->wc_linkid = linkid;
52110ba2cbe9Sxc151355 	cp->wc_count++;
5212d62bc4baSyz147064 	return (DLADM_WALK_CONTINUE);
52130ba2cbe9Sxc151355 }
52140ba2cbe9Sxc151355 
52150ba2cbe9Sxc151355 static int
5216a399b765Szf162725 parse_wlan_keys(char *str, dladm_wlan_key_t **keys, uint_t *key_countp)
52170ba2cbe9Sxc151355 {
52180ba2cbe9Sxc151355 	uint_t			i;
5219a399b765Szf162725 	dladm_wlan_key_t	*wk;
52208002d411SSowmini Varadhan 	int			nfields = 1;
52218002d411SSowmini Varadhan 	char			*field, *token, *lasts = NULL, c;
52220ba2cbe9Sxc151355 
52238002d411SSowmini Varadhan 	token = str;
52248002d411SSowmini Varadhan 	while ((c = *token++) != NULL) {
52258002d411SSowmini Varadhan 		if (c == ',')
52268002d411SSowmini Varadhan 			nfields++;
52278002d411SSowmini Varadhan 	}
52288002d411SSowmini Varadhan 	token = strdup(str);
52298002d411SSowmini Varadhan 	if (token == NULL)
52300ba2cbe9Sxc151355 		return (-1);
52310ba2cbe9Sxc151355 
52328002d411SSowmini Varadhan 	wk = malloc(nfields * sizeof (dladm_wlan_key_t));
52330ba2cbe9Sxc151355 	if (wk == NULL)
52340ba2cbe9Sxc151355 		goto fail;
52350ba2cbe9Sxc151355 
52368002d411SSowmini Varadhan 	token = str;
52378002d411SSowmini Varadhan 	for (i = 0; i < nfields; i++) {
52380ba2cbe9Sxc151355 		char			*s;
52390ba2cbe9Sxc151355 		dladm_secobj_class_t	class;
52400ba2cbe9Sxc151355 		dladm_status_t		status;
52410ba2cbe9Sxc151355 
52428002d411SSowmini Varadhan 		field = strtok_r(token, ",", &lasts);
52438002d411SSowmini Varadhan 		token = NULL;
52448002d411SSowmini Varadhan 
52458002d411SSowmini Varadhan 		(void) strlcpy(wk[i].wk_name, field,
5246a399b765Szf162725 		    DLADM_WLAN_MAX_KEYNAME_LEN);
52470ba2cbe9Sxc151355 
52480ba2cbe9Sxc151355 		wk[i].wk_idx = 1;
52490ba2cbe9Sxc151355 		if ((s = strrchr(wk[i].wk_name, ':')) != NULL) {
52500ba2cbe9Sxc151355 			if (s[1] == '\0' || s[2] != '\0' || !isdigit(s[1]))
52510ba2cbe9Sxc151355 				goto fail;
52520ba2cbe9Sxc151355 
52530ba2cbe9Sxc151355 			wk[i].wk_idx = (uint_t)(s[1] - '0');
52540ba2cbe9Sxc151355 			*s = '\0';
52550ba2cbe9Sxc151355 		}
5256a399b765Szf162725 		wk[i].wk_len = DLADM_WLAN_MAX_KEY_LEN;
52570ba2cbe9Sxc151355 
52584ac67f02SAnurag S. Maskey 		status = dladm_get_secobj(handle, wk[i].wk_name, &class,
52590ba2cbe9Sxc151355 		    wk[i].wk_val, &wk[i].wk_len, 0);
52600ba2cbe9Sxc151355 		if (status != DLADM_STATUS_OK) {
52610ba2cbe9Sxc151355 			if (status == DLADM_STATUS_NOTFOUND) {
52624ac67f02SAnurag S. Maskey 				status = dladm_get_secobj(handle, wk[i].wk_name,
52630ba2cbe9Sxc151355 				    &class, wk[i].wk_val, &wk[i].wk_len,
52640ba2cbe9Sxc151355 				    DLADM_OPT_PERSIST);
52650ba2cbe9Sxc151355 			}
52660ba2cbe9Sxc151355 			if (status != DLADM_STATUS_OK)
52670ba2cbe9Sxc151355 				goto fail;
52680ba2cbe9Sxc151355 		}
5269a399b765Szf162725 		wk[i].wk_class = class;
52700ba2cbe9Sxc151355 	}
52710ba2cbe9Sxc151355 	*keys = wk;
52720ba2cbe9Sxc151355 	*key_countp = i;
52738002d411SSowmini Varadhan 	free(token);
52740ba2cbe9Sxc151355 	return (0);
52750ba2cbe9Sxc151355 fail:
52760ba2cbe9Sxc151355 	free(wk);
52778002d411SSowmini Varadhan 	free(token);
52780ba2cbe9Sxc151355 	return (-1);
52790ba2cbe9Sxc151355 }
52800ba2cbe9Sxc151355 
52810ba2cbe9Sxc151355 static void
52828d5c46e6Sam223141 do_connect_wifi(int argc, char **argv, const char *use)
52830ba2cbe9Sxc151355 {
52840ba2cbe9Sxc151355 	int			option;
5285f595a68aSyz147064 	dladm_wlan_attr_t	attr, *attrp;
5286f595a68aSyz147064 	dladm_status_t		status = DLADM_STATUS_OK;
5287f595a68aSyz147064 	int			timeout = DLADM_WLAN_CONNECT_TIMEOUT_DEFAULT;
5288d62bc4baSyz147064 	datalink_id_t		linkid = DATALINK_ALL_LINKID;
5289a399b765Szf162725 	dladm_wlan_key_t	*keys = NULL;
52900ba2cbe9Sxc151355 	uint_t			key_count = 0;
52910ba2cbe9Sxc151355 	uint_t			flags = 0;
5292f595a68aSyz147064 	dladm_wlan_secmode_t	keysecmode = DLADM_WLAN_SECMODE_NONE;
5293a399b765Szf162725 	char			buf[DLADM_STRSIZE];
52940ba2cbe9Sxc151355 
52950ba2cbe9Sxc151355 	opterr = 0;
52960ba2cbe9Sxc151355 	(void) memset(&attr, 0, sizeof (attr));
52970ba2cbe9Sxc151355 	while ((option = getopt_long(argc, argv, ":e:i:a:m:b:s:k:T:c",
52980ba2cbe9Sxc151355 	    wifi_longopts, NULL)) != -1) {
52990ba2cbe9Sxc151355 		switch (option) {
53000ba2cbe9Sxc151355 		case 'e':
5301f595a68aSyz147064 			status = dladm_wlan_str2essid(optarg, &attr.wa_essid);
5302f595a68aSyz147064 			if (status != DLADM_STATUS_OK)
530333343a97Smeem 				die("invalid ESSID '%s'", optarg);
530433343a97Smeem 
5305f595a68aSyz147064 			attr.wa_valid |= DLADM_WLAN_ATTR_ESSID;
53060ba2cbe9Sxc151355 			/*
53070ba2cbe9Sxc151355 			 * Try to connect without doing a scan.
53080ba2cbe9Sxc151355 			 */
5309f595a68aSyz147064 			flags |= DLADM_WLAN_CONNECT_NOSCAN;
53100ba2cbe9Sxc151355 			break;
53110ba2cbe9Sxc151355 		case 'i':
5312f595a68aSyz147064 			status = dladm_wlan_str2bssid(optarg, &attr.wa_bssid);
5313f595a68aSyz147064 			if (status != DLADM_STATUS_OK)
531433343a97Smeem 				die("invalid BSSID %s", optarg);
531533343a97Smeem 
5316f595a68aSyz147064 			attr.wa_valid |= DLADM_WLAN_ATTR_BSSID;
53170ba2cbe9Sxc151355 			break;
53180ba2cbe9Sxc151355 		case 'a':
5319f595a68aSyz147064 			status = dladm_wlan_str2auth(optarg, &attr.wa_auth);
5320f595a68aSyz147064 			if (status != DLADM_STATUS_OK)
532133343a97Smeem 				die("invalid authentication mode '%s'", optarg);
532233343a97Smeem 
5323f595a68aSyz147064 			attr.wa_valid |= DLADM_WLAN_ATTR_AUTH;
53240ba2cbe9Sxc151355 			break;
53250ba2cbe9Sxc151355 		case 'm':
5326f595a68aSyz147064 			status = dladm_wlan_str2mode(optarg, &attr.wa_mode);
5327f595a68aSyz147064 			if (status != DLADM_STATUS_OK)
532833343a97Smeem 				die("invalid mode '%s'", optarg);
532933343a97Smeem 
5330f595a68aSyz147064 			attr.wa_valid |= DLADM_WLAN_ATTR_MODE;
53310ba2cbe9Sxc151355 			break;
53320ba2cbe9Sxc151355 		case 'b':
5333f595a68aSyz147064 			if ((status = dladm_wlan_str2bsstype(optarg,
5334f595a68aSyz147064 			    &attr.wa_bsstype)) != DLADM_STATUS_OK) {
533533343a97Smeem 				die("invalid bsstype '%s'", optarg);
5336f595a68aSyz147064 			}
533733343a97Smeem 
5338f595a68aSyz147064 			attr.wa_valid |= DLADM_WLAN_ATTR_BSSTYPE;
53390ba2cbe9Sxc151355 			break;
53400ba2cbe9Sxc151355 		case 's':
5341f595a68aSyz147064 			if ((status = dladm_wlan_str2secmode(optarg,
5342f595a68aSyz147064 			    &attr.wa_secmode)) != DLADM_STATUS_OK) {
534333343a97Smeem 				die("invalid security mode '%s'", optarg);
5344f595a68aSyz147064 			}
534533343a97Smeem 
5346f595a68aSyz147064 			attr.wa_valid |= DLADM_WLAN_ATTR_SECMODE;
53470ba2cbe9Sxc151355 			break;
53480ba2cbe9Sxc151355 		case 'k':
5349a399b765Szf162725 			if (parse_wlan_keys(optarg, &keys, &key_count) < 0)
535033343a97Smeem 				die("invalid key(s) '%s'", optarg);
535133343a97Smeem 
5352a399b765Szf162725 			if (keys[0].wk_class == DLADM_SECOBJ_CLASS_WEP)
5353f595a68aSyz147064 				keysecmode = DLADM_WLAN_SECMODE_WEP;
5354a399b765Szf162725 			else
5355a399b765Szf162725 				keysecmode = DLADM_WLAN_SECMODE_WPA;
53560ba2cbe9Sxc151355 			break;
53570ba2cbe9Sxc151355 		case 'T':
53580ba2cbe9Sxc151355 			if (strcasecmp(optarg, "forever") == 0) {
53590ba2cbe9Sxc151355 				timeout = -1;
53600ba2cbe9Sxc151355 				break;
53610ba2cbe9Sxc151355 			}
536233343a97Smeem 			if (!str2int(optarg, &timeout) || timeout < 0)
536333343a97Smeem 				die("invalid timeout value '%s'", optarg);
53640ba2cbe9Sxc151355 			break;
53650ba2cbe9Sxc151355 		case 'c':
5366f595a68aSyz147064 			flags |= DLADM_WLAN_CONNECT_CREATEIBSS;
5367a399b765Szf162725 			flags |= DLADM_WLAN_CONNECT_CREATEIBSS;
53680ba2cbe9Sxc151355 			break;
53690ba2cbe9Sxc151355 		default:
53708d5c46e6Sam223141 			die_opterr(optopt, option, use);
53710ba2cbe9Sxc151355 			break;
53720ba2cbe9Sxc151355 		}
53730ba2cbe9Sxc151355 	}
53740ba2cbe9Sxc151355 
5375f595a68aSyz147064 	if (keysecmode == DLADM_WLAN_SECMODE_NONE) {
5376a399b765Szf162725 		if ((attr.wa_valid & DLADM_WLAN_ATTR_SECMODE) != 0) {
5377a399b765Szf162725 			die("key required for security mode '%s'",
5378a399b765Szf162725 			    dladm_wlan_secmode2str(&attr.wa_secmode, buf));
5379a399b765Szf162725 		}
53800ba2cbe9Sxc151355 	} else {
5381f595a68aSyz147064 		if ((attr.wa_valid & DLADM_WLAN_ATTR_SECMODE) != 0 &&
538233343a97Smeem 		    attr.wa_secmode != keysecmode)
538333343a97Smeem 			die("incompatible -s and -k options");
5384f595a68aSyz147064 		attr.wa_valid |= DLADM_WLAN_ATTR_SECMODE;
5385a399b765Szf162725 		attr.wa_secmode = keysecmode;
5386a399b765Szf162725 	}
53870ba2cbe9Sxc151355 
5388d62bc4baSyz147064 	if (optind == (argc - 1)) {
53894ac67f02SAnurag S. Maskey 		if ((status = dladm_name2info(handle, argv[optind], &linkid,
53904ac67f02SAnurag S. Maskey 		    NULL, NULL, NULL)) != DLADM_STATUS_OK) {
5391d62bc4baSyz147064 			die_dlerr(status, "link %s is not valid", argv[optind]);
5392d62bc4baSyz147064 		}
5393d62bc4baSyz147064 	} else if (optind != argc) {
53940ba2cbe9Sxc151355 		usage();
5395d62bc4baSyz147064 	}
53960ba2cbe9Sxc151355 
5397d62bc4baSyz147064 	if (linkid == DATALINK_ALL_LINKID) {
53980ba2cbe9Sxc151355 		wlan_count_attr_t wcattr;
53990ba2cbe9Sxc151355 
5400d62bc4baSyz147064 		wcattr.wc_linkid = DATALINK_INVALID_LINKID;
54010ba2cbe9Sxc151355 		wcattr.wc_count = 0;
54024ac67f02SAnurag S. Maskey 		(void) dladm_walk_datalink_id(do_count_wlan, handle, &wcattr,
5403b509e89bSRishi Srivatsavai 		    DATALINK_CLASS_PHYS | DATALINK_CLASS_SIMNET,
5404b509e89bSRishi Srivatsavai 		    DL_WIFI, DLADM_OPT_ACTIVE);
54050ba2cbe9Sxc151355 		if (wcattr.wc_count == 0) {
540633343a97Smeem 			die("no wifi links are available");
54070ba2cbe9Sxc151355 		} else if (wcattr.wc_count > 1) {
540833343a97Smeem 			die("link name is required when more than one wifi "
540933343a97Smeem 			    "link is available");
54100ba2cbe9Sxc151355 		}
5411d62bc4baSyz147064 		linkid = wcattr.wc_linkid;
54120ba2cbe9Sxc151355 	}
54130ba2cbe9Sxc151355 	attrp = (attr.wa_valid == 0) ? NULL : &attr;
541433343a97Smeem again:
54154ac67f02SAnurag S. Maskey 	if ((status = dladm_wlan_connect(handle, linkid, attrp, timeout, keys,
5416f595a68aSyz147064 	    key_count, flags)) != DLADM_STATUS_OK) {
5417f595a68aSyz147064 		if ((flags & DLADM_WLAN_CONNECT_NOSCAN) != 0) {
54180ba2cbe9Sxc151355 			/*
541933343a97Smeem 			 * Try again with scanning and filtering.
54200ba2cbe9Sxc151355 			 */
5421f595a68aSyz147064 			flags &= ~DLADM_WLAN_CONNECT_NOSCAN;
542233343a97Smeem 			goto again;
54230ba2cbe9Sxc151355 		}
542433343a97Smeem 
5425f595a68aSyz147064 		if (status == DLADM_STATUS_NOTFOUND) {
54260ba2cbe9Sxc151355 			if (attr.wa_valid == 0) {
542733343a97Smeem 				die("no wifi networks are available");
54280ba2cbe9Sxc151355 			} else {
542933343a97Smeem 				die("no wifi networks with the specified "
543033343a97Smeem 				    "criteria are available");
54310ba2cbe9Sxc151355 			}
54320ba2cbe9Sxc151355 		}
5433d62bc4baSyz147064 		die_dlerr(status, "cannot connect");
54340ba2cbe9Sxc151355 	}
54350ba2cbe9Sxc151355 	free(keys);
54360ba2cbe9Sxc151355 }
54370ba2cbe9Sxc151355 
54380ba2cbe9Sxc151355 /* ARGSUSED */
5439d62bc4baSyz147064 static int
54404ac67f02SAnurag S. Maskey do_all_disconnect_wifi(dladm_handle_t dh, datalink_id_t linkid, void *arg)
54410ba2cbe9Sxc151355 {
5442f595a68aSyz147064 	dladm_status_t	status;
54430ba2cbe9Sxc151355 
54444ac67f02SAnurag S. Maskey 	status = dladm_wlan_disconnect(dh, linkid);
5445f595a68aSyz147064 	if (status != DLADM_STATUS_OK)
5446d62bc4baSyz147064 		warn_dlerr(status, "cannot disconnect link");
544733343a97Smeem 
5448d62bc4baSyz147064 	return (DLADM_WALK_CONTINUE);
54490ba2cbe9Sxc151355 }
54500ba2cbe9Sxc151355 
54510ba2cbe9Sxc151355 static void
54528d5c46e6Sam223141 do_disconnect_wifi(int argc, char **argv, const char *use)
54530ba2cbe9Sxc151355 {
54540ba2cbe9Sxc151355 	int			option;
5455d62bc4baSyz147064 	datalink_id_t		linkid = DATALINK_ALL_LINKID;
54560ba2cbe9Sxc151355 	boolean_t		all_links = B_FALSE;
5457f595a68aSyz147064 	dladm_status_t		status;
54580ba2cbe9Sxc151355 	wlan_count_attr_t	wcattr;
54590ba2cbe9Sxc151355 
54600ba2cbe9Sxc151355 	opterr = 0;
54610ba2cbe9Sxc151355 	while ((option = getopt_long(argc, argv, ":a",
54620ba2cbe9Sxc151355 	    wifi_longopts, NULL)) != -1) {
54630ba2cbe9Sxc151355 		switch (option) {
54640ba2cbe9Sxc151355 		case 'a':
54650ba2cbe9Sxc151355 			all_links = B_TRUE;
54660ba2cbe9Sxc151355 			break;
54670ba2cbe9Sxc151355 		default:
54688d5c46e6Sam223141 			die_opterr(optopt, option, use);
54690ba2cbe9Sxc151355 			break;
54700ba2cbe9Sxc151355 		}
54710ba2cbe9Sxc151355 	}
54720ba2cbe9Sxc151355 
5473d62bc4baSyz147064 	if (optind == (argc - 1)) {
54744ac67f02SAnurag S. Maskey 		if ((status = dladm_name2info(handle, argv[optind], &linkid,
54754ac67f02SAnurag S. Maskey 		    NULL, NULL, NULL)) != DLADM_STATUS_OK) {
5476d62bc4baSyz147064 			die_dlerr(status, "link %s is not valid", argv[optind]);
5477d62bc4baSyz147064 		}
5478d62bc4baSyz147064 	} else if (optind != argc) {
54790ba2cbe9Sxc151355 		usage();
5480d62bc4baSyz147064 	}
54810ba2cbe9Sxc151355 
5482d62bc4baSyz147064 	if (linkid == DATALINK_ALL_LINKID) {
54830ba2cbe9Sxc151355 		if (!all_links) {
5484d62bc4baSyz147064 			wcattr.wc_linkid = linkid;
54850ba2cbe9Sxc151355 			wcattr.wc_count = 0;
54864ac67f02SAnurag S. Maskey 			(void) dladm_walk_datalink_id(do_count_wlan, handle,
5487b509e89bSRishi Srivatsavai 			    &wcattr,
5488b509e89bSRishi Srivatsavai 			    DATALINK_CLASS_PHYS | DATALINK_CLASS_SIMNET,
5489b509e89bSRishi Srivatsavai 			    DL_WIFI, DLADM_OPT_ACTIVE);
54900ba2cbe9Sxc151355 			if (wcattr.wc_count == 0) {
549133343a97Smeem 				die("no wifi links are available");
54920ba2cbe9Sxc151355 			} else if (wcattr.wc_count > 1) {
549333343a97Smeem 				die("link name is required when more than "
549433343a97Smeem 				    "one wifi link is available");
54950ba2cbe9Sxc151355 			}
5496d62bc4baSyz147064 			linkid = wcattr.wc_linkid;
54970ba2cbe9Sxc151355 		} else {
5498d62bc4baSyz147064 			(void) dladm_walk_datalink_id(do_all_disconnect_wifi,
5499b509e89bSRishi Srivatsavai 			    handle, NULL,
5500b509e89bSRishi Srivatsavai 			    DATALINK_CLASS_PHYS | DATALINK_CLASS_SIMNET,
5501b509e89bSRishi Srivatsavai 			    DL_WIFI, DLADM_OPT_ACTIVE);
55020ba2cbe9Sxc151355 			return;
55030ba2cbe9Sxc151355 		}
55040ba2cbe9Sxc151355 	}
55054ac67f02SAnurag S. Maskey 	status = dladm_wlan_disconnect(handle, linkid);
5506f595a68aSyz147064 	if (status != DLADM_STATUS_OK)
5507d62bc4baSyz147064 		die_dlerr(status, "cannot disconnect");
55080ba2cbe9Sxc151355 }
55090ba2cbe9Sxc151355 
55100ba2cbe9Sxc151355 static void
5511d62bc4baSyz147064 print_linkprop(datalink_id_t linkid, show_linkprop_state_t *statep,
55124ac67f02SAnurag S. Maskey     const char *propname, dladm_prop_type_t type, const char *format,
55134ac67f02SAnurag S. Maskey     char **pptr)
55140ba2cbe9Sxc151355 {
55150ba2cbe9Sxc151355 	int		i;
55160ba2cbe9Sxc151355 	char		*ptr, *lim;
55170ba2cbe9Sxc151355 	char		buf[DLADM_STRSIZE];
5518da14cebeSEric Cheng 	char		*unknown = "--", *notsup = "";
55190ba2cbe9Sxc151355 	char		**propvals = statep->ls_propvals;
5520d62bc4baSyz147064 	uint_t		valcnt = DLADM_MAX_PROP_VALCNT;
55210ba2cbe9Sxc151355 	dladm_status_t	status;
55220ba2cbe9Sxc151355 
55234ac67f02SAnurag S. Maskey 	status = dladm_get_linkprop(handle, linkid, type, propname, propvals,
55244ac67f02SAnurag S. Maskey 	    &valcnt);
55250ba2cbe9Sxc151355 	if (status != DLADM_STATUS_OK) {
5526f595a68aSyz147064 		if (status == DLADM_STATUS_TEMPONLY) {
5527d62bc4baSyz147064 			if (type == DLADM_PROP_VAL_MODIFIABLE &&
5528d62bc4baSyz147064 			    statep->ls_persist) {
5529d62bc4baSyz147064 				valcnt = 1;
5530d62bc4baSyz147064 				propvals = &unknown;
5531d62bc4baSyz147064 			} else {
5532f595a68aSyz147064 				statep->ls_status = status;
5533e7801d59Ssowmini 				statep->ls_retstatus = status;
5534f595a68aSyz147064 				return;
5535d62bc4baSyz147064 			}
5536f595a68aSyz147064 		} else if (status == DLADM_STATUS_NOTSUP ||
5537f595a68aSyz147064 		    statep->ls_persist) {
55380ba2cbe9Sxc151355 			valcnt = 1;
5539afdda45fSVasumathi Sundaram - Sun Microsystems 			if (type == DLADM_PROP_VAL_CURRENT ||
5540afdda45fSVasumathi Sundaram - Sun Microsystems 			    type == DLADM_PROP_VAL_PERM)
55410ba2cbe9Sxc151355 				propvals = &unknown;
55420ba2cbe9Sxc151355 			else
55430ba2cbe9Sxc151355 				propvals = &notsup;
5544149b7eb2SSowmini Varadhan 		} else if (status == DLADM_STATUS_NOTDEFINED) {
5545149b7eb2SSowmini Varadhan 			propvals = &notsup; /* STR_UNDEF_VAL */
55460ba2cbe9Sxc151355 		} else {
5547e7801d59Ssowmini 			if (statep->ls_proplist &&
5548e7801d59Ssowmini 			    statep->ls_status == DLADM_STATUS_OK) {
5549f595a68aSyz147064 				warn_dlerr(status,
5550f595a68aSyz147064 				    "cannot get link property '%s' for %s",
5551f595a68aSyz147064 				    propname, statep->ls_link);
5552d62bc4baSyz147064 			}
5553e7801d59Ssowmini 			statep->ls_status = status;
5554e7801d59Ssowmini 			statep->ls_retstatus = status;
5555f595a68aSyz147064 			return;
55560ba2cbe9Sxc151355 		}
55570ba2cbe9Sxc151355 	}
55580ba2cbe9Sxc151355 
5559e7801d59Ssowmini 	statep->ls_status = DLADM_STATUS_OK;
5560e7801d59Ssowmini 
55610ba2cbe9Sxc151355 	ptr = buf;
55620ba2cbe9Sxc151355 	lim = buf + DLADM_STRSIZE;
55630ba2cbe9Sxc151355 	for (i = 0; i < valcnt; i++) {
55648002d411SSowmini Varadhan 		if (propvals[i][0] == '\0' && !statep->ls_parsable)
55658002d411SSowmini Varadhan 			ptr += snprintf(ptr, lim - ptr, "--,");
55660ba2cbe9Sxc151355 		else
55670ba2cbe9Sxc151355 			ptr += snprintf(ptr, lim - ptr, "%s,", propvals[i]);
55680ba2cbe9Sxc151355 		if (ptr >= lim)
55690ba2cbe9Sxc151355 			break;
55700ba2cbe9Sxc151355 	}
55710ba2cbe9Sxc151355 	if (valcnt > 0)
55720ba2cbe9Sxc151355 		buf[strlen(buf) - 1] = '\0';
55730ba2cbe9Sxc151355 
55740ba2cbe9Sxc151355 	lim = statep->ls_line + MAX_PROP_LINE;
55758002d411SSowmini Varadhan 	if (statep->ls_parsable) {
55760ba2cbe9Sxc151355 		*pptr += snprintf(*pptr, lim - *pptr,
5577e7801d59Ssowmini 		    "%s", buf);
55780ba2cbe9Sxc151355 	} else {
55790ba2cbe9Sxc151355 		*pptr += snprintf(*pptr, lim - *pptr, format, buf);
55800ba2cbe9Sxc151355 	}
55810ba2cbe9Sxc151355 }
55820ba2cbe9Sxc151355 
55838002d411SSowmini Varadhan static boolean_t
55848002d411SSowmini Varadhan print_linkprop_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize)
5585e7801d59Ssowmini {
55868002d411SSowmini Varadhan 	linkprop_args_t		*arg = ofarg->ofmt_cbarg;
5587e7801d59Ssowmini 	char 			*propname = arg->ls_propname;
5588e7801d59Ssowmini 	show_linkprop_state_t	*statep = arg->ls_state;
5589e7801d59Ssowmini 	char			*ptr = statep->ls_line;
5590e7801d59Ssowmini 	char			*lim = ptr + MAX_PROP_LINE;
5591e7801d59Ssowmini 	datalink_id_t		linkid = arg->ls_linkid;
5592e7801d59Ssowmini 
55938002d411SSowmini Varadhan 	switch (ofarg->ofmt_id) {
5594e7801d59Ssowmini 	case LINKPROP_LINK:
5595e7801d59Ssowmini 		(void) snprintf(ptr, lim - ptr, "%s", statep->ls_link);
5596e7801d59Ssowmini 		break;
5597e7801d59Ssowmini 	case LINKPROP_PROPERTY:
5598e7801d59Ssowmini 		(void) snprintf(ptr, lim - ptr, "%s", propname);
5599e7801d59Ssowmini 		break;
5600e7801d59Ssowmini 	case LINKPROP_VALUE:
5601e7801d59Ssowmini 		print_linkprop(linkid, statep, propname,
5602e7801d59Ssowmini 		    statep->ls_persist ? DLADM_PROP_VAL_PERSISTENT :
5603e7801d59Ssowmini 		    DLADM_PROP_VAL_CURRENT, "%s", &ptr);
5604e7801d59Ssowmini 		/*
5605e7801d59Ssowmini 		 * If we failed to query the link property, for example, query
5606e7801d59Ssowmini 		 * the persistent value of a non-persistable link property,
5607e7801d59Ssowmini 		 * simply skip the output.
5608e7801d59Ssowmini 		 */
5609e7801d59Ssowmini 		if (statep->ls_status != DLADM_STATUS_OK)
5610e7801d59Ssowmini 			goto skip;
5611e7801d59Ssowmini 		ptr = statep->ls_line;
5612e7801d59Ssowmini 		break;
5613afdda45fSVasumathi Sundaram - Sun Microsystems 	case LINKPROP_PERM:
5614afdda45fSVasumathi Sundaram - Sun Microsystems 		print_linkprop(linkid, statep, propname,
5615afdda45fSVasumathi Sundaram - Sun Microsystems 		    DLADM_PROP_VAL_PERM, "%s", &ptr);
5616afdda45fSVasumathi Sundaram - Sun Microsystems 		if (statep->ls_status != DLADM_STATUS_OK)
5617afdda45fSVasumathi Sundaram - Sun Microsystems 			goto skip;
5618afdda45fSVasumathi Sundaram - Sun Microsystems 		ptr = statep->ls_line;
5619afdda45fSVasumathi Sundaram - Sun Microsystems 		break;
5620e7801d59Ssowmini 	case LINKPROP_DEFAULT:
5621e7801d59Ssowmini 		print_linkprop(linkid, statep, propname,
5622e7801d59Ssowmini 		    DLADM_PROP_VAL_DEFAULT, "%s", &ptr);
5623e7801d59Ssowmini 		if (statep->ls_status != DLADM_STATUS_OK)
5624e7801d59Ssowmini 			goto skip;
5625e7801d59Ssowmini 		ptr = statep->ls_line;
5626e7801d59Ssowmini 		break;
5627e7801d59Ssowmini 	case LINKPROP_POSSIBLE:
5628e7801d59Ssowmini 		print_linkprop(linkid, statep, propname,
5629e7801d59Ssowmini 		    DLADM_PROP_VAL_MODIFIABLE, "%s ", &ptr);
5630e7801d59Ssowmini 		if (statep->ls_status != DLADM_STATUS_OK)
5631e7801d59Ssowmini 			goto skip;
5632e7801d59Ssowmini 		ptr = statep->ls_line;
5633e7801d59Ssowmini 		break;
5634e7801d59Ssowmini 	default:
5635e7801d59Ssowmini 		die("invalid input");
5636e7801d59Ssowmini 		break;
5637e7801d59Ssowmini 	}
56388002d411SSowmini Varadhan 	(void) strlcpy(buf, ptr, bufsize);
56398002d411SSowmini Varadhan 	return (B_TRUE);
5640e7801d59Ssowmini skip:
56418002d411SSowmini Varadhan 	return ((statep->ls_status == DLADM_STATUS_OK) ?
56428002d411SSowmini Varadhan 	    B_TRUE : B_FALSE);
5643e7801d59Ssowmini }
5644e7801d59Ssowmini 
5645bcb5c89dSSowmini Varadhan static boolean_t
5646bcb5c89dSSowmini Varadhan linkprop_is_supported(datalink_id_t  linkid, const char *propname,
5647bcb5c89dSSowmini Varadhan     show_linkprop_state_t *statep)
5648bcb5c89dSSowmini Varadhan {
5649bcb5c89dSSowmini Varadhan 	dladm_status_t	status;
5650bcb5c89dSSowmini Varadhan 	uint_t		valcnt = DLADM_MAX_PROP_VALCNT;
5651bcb5c89dSSowmini Varadhan 
56524784fcbdSSowmini Varadhan 	/* if used with -p flag, always print output */
56534784fcbdSSowmini Varadhan 	if (statep->ls_proplist != NULL)
56544784fcbdSSowmini Varadhan 		return (B_TRUE);
56554784fcbdSSowmini Varadhan 
56564ac67f02SAnurag S. Maskey 	status = dladm_get_linkprop(handle, linkid, DLADM_PROP_VAL_DEFAULT,
5657bcb5c89dSSowmini Varadhan 	    propname, statep->ls_propvals, &valcnt);
5658bcb5c89dSSowmini Varadhan 
5659149b7eb2SSowmini Varadhan 	if (status == DLADM_STATUS_OK)
5660149b7eb2SSowmini Varadhan 		return (B_TRUE);
5661149b7eb2SSowmini Varadhan 
5662149b7eb2SSowmini Varadhan 	/*
5663149b7eb2SSowmini Varadhan 	 * A system wide default value is not available for the
5664149b7eb2SSowmini Varadhan 	 * property. Check if current value can be retrieved.
5665149b7eb2SSowmini Varadhan 	 */
56664ac67f02SAnurag S. Maskey 	status = dladm_get_linkprop(handle, linkid, DLADM_PROP_VAL_CURRENT,
5667149b7eb2SSowmini Varadhan 	    propname, statep->ls_propvals, &valcnt);
5668149b7eb2SSowmini Varadhan 
5669149b7eb2SSowmini Varadhan 	return (status == DLADM_STATUS_OK);
5670bcb5c89dSSowmini Varadhan }
5671bcb5c89dSSowmini Varadhan 
56724ac67f02SAnurag S. Maskey /* ARGSUSED */
5673d62bc4baSyz147064 static int
56744ac67f02SAnurag S. Maskey show_linkprop(dladm_handle_t dh, datalink_id_t linkid, const char *propname,
56754ac67f02SAnurag S. Maskey     void *arg)
56760ba2cbe9Sxc151355 {
56770ba2cbe9Sxc151355 	show_linkprop_state_t	*statep = arg;
5678e7801d59Ssowmini 	linkprop_args_t		ls_arg;
56790ba2cbe9Sxc151355 
5680e7801d59Ssowmini 	bzero(&ls_arg, sizeof (ls_arg));
5681e7801d59Ssowmini 	ls_arg.ls_state = statep;
5682e7801d59Ssowmini 	ls_arg.ls_propname = (char *)propname;
5683e7801d59Ssowmini 	ls_arg.ls_linkid = linkid;
56840ba2cbe9Sxc151355 
568562ee1d25SArtem Kachitchkine 	/*
568662ee1d25SArtem Kachitchkine 	 * This will need to be fixed when kernel interfaces are added
568762ee1d25SArtem Kachitchkine 	 * to enable walking of all known private properties. For now,
568862ee1d25SArtem Kachitchkine 	 * we are limited to walking persistent private properties only.
568962ee1d25SArtem Kachitchkine 	 */
569062ee1d25SArtem Kachitchkine 	if ((propname[0] == '_') && !statep->ls_persist &&
569162ee1d25SArtem Kachitchkine 	    (statep->ls_proplist == NULL))
569262ee1d25SArtem Kachitchkine 		return (DLADM_WALK_CONTINUE);
56938002d411SSowmini Varadhan 	if (!statep->ls_parsable &&
5694149b7eb2SSowmini Varadhan 	    !linkprop_is_supported(linkid, propname, statep))
5695bcb5c89dSSowmini Varadhan 		return (DLADM_WALK_CONTINUE);
5696bcb5c89dSSowmini Varadhan 
56978002d411SSowmini Varadhan 	ofmt_print(statep->ls_ofmt, &ls_arg);
5698e7801d59Ssowmini 
5699d62bc4baSyz147064 	return (DLADM_WALK_CONTINUE);
57000ba2cbe9Sxc151355 }
57010ba2cbe9Sxc151355 
57020ba2cbe9Sxc151355 static void
57038d5c46e6Sam223141 do_show_linkprop(int argc, char **argv, const char *use)
57040ba2cbe9Sxc151355 {
5705f4b3ec61Sdh155122 	int			option;
570663a6526dSMichael Lim 	char			propstr[DLADM_STRSIZE];
5707da14cebeSEric Cheng 	dladm_arg_list_t	*proplist = NULL;
5708d62bc4baSyz147064 	datalink_id_t		linkid = DATALINK_ALL_LINKID;
57090ba2cbe9Sxc151355 	show_linkprop_state_t	state;
5710d62bc4baSyz147064 	uint32_t		flags = DLADM_OPT_ACTIVE;
5711d62bc4baSyz147064 	dladm_status_t		status;
5712e7801d59Ssowmini 	char			*fields_str = NULL;
57138002d411SSowmini Varadhan 	ofmt_handle_t		ofmt;
57148002d411SSowmini Varadhan 	ofmt_status_t		oferr;
57158002d411SSowmini Varadhan 	uint_t			ofmtflags = 0;
57160ba2cbe9Sxc151355 
571763a6526dSMichael Lim 	bzero(propstr, DLADM_STRSIZE);
57180ba2cbe9Sxc151355 	opterr = 0;
57190ba2cbe9Sxc151355 	state.ls_propvals = NULL;
57200ba2cbe9Sxc151355 	state.ls_line = NULL;
57218002d411SSowmini Varadhan 	state.ls_parsable = B_FALSE;
57220ba2cbe9Sxc151355 	state.ls_persist = B_FALSE;
57230ba2cbe9Sxc151355 	state.ls_header = B_TRUE;
5724e7801d59Ssowmini 	state.ls_retstatus = DLADM_STATUS_OK;
572563a6526dSMichael Lim 
5726e7801d59Ssowmini 	while ((option = getopt_long(argc, argv, ":p:cPo:",
57270ba2cbe9Sxc151355 	    prop_longopts, NULL)) != -1) {
57280ba2cbe9Sxc151355 		switch (option) {
57290ba2cbe9Sxc151355 		case 'p':
573063a6526dSMichael Lim 			(void) strlcat(propstr, optarg, DLADM_STRSIZE);
573163a6526dSMichael Lim 			if (strlcat(propstr, ",", DLADM_STRSIZE) >=
573263a6526dSMichael Lim 			    DLADM_STRSIZE)
573363a6526dSMichael Lim 				die("property list too long '%s'", propstr);
57340ba2cbe9Sxc151355 			break;
57350ba2cbe9Sxc151355 		case 'c':
57368002d411SSowmini Varadhan 			state.ls_parsable = B_TRUE;
57370ba2cbe9Sxc151355 			break;
57380ba2cbe9Sxc151355 		case 'P':
57390ba2cbe9Sxc151355 			state.ls_persist = B_TRUE;
5740d62bc4baSyz147064 			flags = DLADM_OPT_PERSIST;
57410ba2cbe9Sxc151355 			break;
5742e7801d59Ssowmini 		case 'o':
5743e7801d59Ssowmini 			fields_str = optarg;
5744e7801d59Ssowmini 			break;
57450ba2cbe9Sxc151355 		default:
57468d5c46e6Sam223141 			die_opterr(optopt, option, use);
57470ba2cbe9Sxc151355 			break;
57480ba2cbe9Sxc151355 		}
57490ba2cbe9Sxc151355 	}
57500ba2cbe9Sxc151355 
5751d62bc4baSyz147064 	if (optind == (argc - 1)) {
57524ac67f02SAnurag S. Maskey 		if ((status = dladm_name2info(handle, argv[optind], &linkid,
57534ac67f02SAnurag S. Maskey 		    NULL, NULL, NULL)) != DLADM_STATUS_OK) {
5754d62bc4baSyz147064 			die_dlerr(status, "link %s is not valid", argv[optind]);
5755d62bc4baSyz147064 		}
5756d62bc4baSyz147064 	} else if (optind != argc) {
57570ba2cbe9Sxc151355 		usage();
5758d62bc4baSyz147064 	}
57590ba2cbe9Sxc151355 
576063a6526dSMichael Lim 	if (dladm_parse_link_props(propstr, &proplist, B_TRUE)
576163a6526dSMichael Lim 	    != DLADM_STATUS_OK)
576263a6526dSMichael Lim 		die("invalid link properties specified");
5763f4b3ec61Sdh155122 	state.ls_proplist = proplist;
5764f595a68aSyz147064 	state.ls_status = DLADM_STATUS_OK;
5765f4b3ec61Sdh155122 
57668002d411SSowmini Varadhan 	if (state.ls_parsable)
57678002d411SSowmini Varadhan 		ofmtflags |= OFMT_PARSABLE;
57688002d411SSowmini Varadhan 	oferr = ofmt_open(fields_str, linkprop_fields, ofmtflags, 0, &ofmt);
57698002d411SSowmini Varadhan 	dladm_ofmt_check(oferr, state.ls_parsable, ofmt);
57708002d411SSowmini Varadhan 	state.ls_ofmt = ofmt;
5771e7801d59Ssowmini 
5772d62bc4baSyz147064 	if (linkid == DATALINK_ALL_LINKID) {
57734ac67f02SAnurag S. Maskey 		(void) dladm_walk_datalink_id(show_linkprop_onelink, handle,
57744ac67f02SAnurag S. Maskey 		    &state, DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE, flags);
5775f4b3ec61Sdh155122 	} else {
57764ac67f02SAnurag S. Maskey 		(void) show_linkprop_onelink(handle, linkid, &state);
5777f4b3ec61Sdh155122 	}
57788002d411SSowmini Varadhan 	ofmt_close(ofmt);
5779da14cebeSEric Cheng 	dladm_free_props(proplist);
5780f595a68aSyz147064 
57814ac67f02SAnurag S. Maskey 	if (state.ls_retstatus != DLADM_STATUS_OK) {
57824ac67f02SAnurag S. Maskey 		dladm_close(handle);
5783f595a68aSyz147064 		exit(EXIT_FAILURE);
5784f4b3ec61Sdh155122 	}
57854ac67f02SAnurag S. Maskey }
5786f4b3ec61Sdh155122 
5787d62bc4baSyz147064 static int
57884ac67f02SAnurag S. Maskey show_linkprop_onelink(dladm_handle_t hdl, datalink_id_t linkid, void *arg)
5789f4b3ec61Sdh155122 {
5790948f2876Sss150715 	int			i;
5791f4b3ec61Sdh155122 	char			*buf;
5792d62bc4baSyz147064 	uint32_t		flags;
5793da14cebeSEric Cheng 	dladm_arg_list_t	*proplist = NULL;
5794d62bc4baSyz147064 	show_linkprop_state_t	*statep = arg;
5795d62bc4baSyz147064 	dlpi_handle_t		dh = NULL;
5796f4b3ec61Sdh155122 
5797d62bc4baSyz147064 	statep->ls_status = DLADM_STATUS_OK;
5798d62bc4baSyz147064 
57994ac67f02SAnurag S. Maskey 	if (dladm_datalink_id2info(hdl, linkid, &flags, NULL, NULL,
58004ac67f02SAnurag S. Maskey 	    statep->ls_link, MAXLINKNAMELEN) != DLADM_STATUS_OK) {
5801d62bc4baSyz147064 		statep->ls_status = DLADM_STATUS_NOTFOUND;
5802d62bc4baSyz147064 		return (DLADM_WALK_CONTINUE);
5803d62bc4baSyz147064 	}
5804d62bc4baSyz147064 
5805d62bc4baSyz147064 	if ((statep->ls_persist && !(flags & DLADM_OPT_PERSIST)) ||
5806d62bc4baSyz147064 	    (!statep->ls_persist && !(flags & DLADM_OPT_ACTIVE))) {
5807d62bc4baSyz147064 		statep->ls_status = DLADM_STATUS_BADARG;
5808d62bc4baSyz147064 		return (DLADM_WALK_CONTINUE);
5809d62bc4baSyz147064 	}
5810d62bc4baSyz147064 
5811f4b3ec61Sdh155122 	proplist = statep->ls_proplist;
58120ba2cbe9Sxc151355 
58130ba2cbe9Sxc151355 	/*
58140ba2cbe9Sxc151355 	 * When some WiFi links are opened for the first time, their hardware
58150ba2cbe9Sxc151355 	 * automatically scans for APs and does other slow operations.	Thus,
58160ba2cbe9Sxc151355 	 * if there are no open links, the retrieval of link properties
58170ba2cbe9Sxc151355 	 * (below) will proceed slowly unless we hold the link open.
5818d62bc4baSyz147064 	 *
5819d62bc4baSyz147064 	 * Note that failure of dlpi_open() does not necessarily mean invalid
5820d62bc4baSyz147064 	 * link properties, because dlpi_open() may fail because of incorrect
5821d62bc4baSyz147064 	 * autopush configuration. Therefore, we ingore the return value of
5822d62bc4baSyz147064 	 * dlpi_open().
58230ba2cbe9Sxc151355 	 */
5824d62bc4baSyz147064 	if (!statep->ls_persist)
5825d62bc4baSyz147064 		(void) dlpi_open(statep->ls_link, &dh, 0);
58260ba2cbe9Sxc151355 
5827d62bc4baSyz147064 	buf = malloc((sizeof (char *) + DLADM_PROP_VAL_MAX) *
5828d62bc4baSyz147064 	    DLADM_MAX_PROP_VALCNT + MAX_PROP_LINE);
582933343a97Smeem 	if (buf == NULL)
583033343a97Smeem 		die("insufficient memory");
583133343a97Smeem 
5832f4b3ec61Sdh155122 	statep->ls_propvals = (char **)(void *)buf;
5833d62bc4baSyz147064 	for (i = 0; i < DLADM_MAX_PROP_VALCNT; i++) {
5834d62bc4baSyz147064 		statep->ls_propvals[i] = buf +
5835d62bc4baSyz147064 		    sizeof (char *) * DLADM_MAX_PROP_VALCNT +
58360ba2cbe9Sxc151355 		    i * DLADM_PROP_VAL_MAX;
58370ba2cbe9Sxc151355 	}
5838f4b3ec61Sdh155122 	statep->ls_line = buf +
5839d62bc4baSyz147064 	    (sizeof (char *) + DLADM_PROP_VAL_MAX) * DLADM_MAX_PROP_VALCNT;
58400ba2cbe9Sxc151355 
58410ba2cbe9Sxc151355 	if (proplist != NULL) {
5842da14cebeSEric Cheng 		for (i = 0; i < proplist->al_count; i++) {
58434ac67f02SAnurag S. Maskey 			(void) show_linkprop(hdl, linkid,
5844da14cebeSEric Cheng 			    proplist->al_info[i].ai_name, statep);
58450ba2cbe9Sxc151355 		}
5846d62bc4baSyz147064 	} else {
58474ac67f02SAnurag S. Maskey 		(void) dladm_walk_linkprop(hdl, linkid, statep,
58484ac67f02SAnurag S. Maskey 		    show_linkprop);
5849d62bc4baSyz147064 	}
5850d62bc4baSyz147064 	if (dh != NULL)
5851948f2876Sss150715 		dlpi_close(dh);
58520ba2cbe9Sxc151355 	free(buf);
5853d62bc4baSyz147064 	return (DLADM_WALK_CONTINUE);
58540ba2cbe9Sxc151355 }
58550ba2cbe9Sxc151355 
58560ba2cbe9Sxc151355 static dladm_status_t
5857d62bc4baSyz147064 set_linkprop_persist(datalink_id_t linkid, const char *prop_name,
5858d62bc4baSyz147064     char **prop_val, uint_t val_cnt, boolean_t reset)
58590ba2cbe9Sxc151355 {
58600ba2cbe9Sxc151355 	dladm_status_t	status;
58610ba2cbe9Sxc151355 
58624ac67f02SAnurag S. Maskey 	status = dladm_set_linkprop(handle, linkid, prop_name, prop_val,
58634ac67f02SAnurag S. Maskey 	    val_cnt, DLADM_OPT_PERSIST);
58640ba2cbe9Sxc151355 
58650ba2cbe9Sxc151355 	if (status != DLADM_STATUS_OK) {
5866da14cebeSEric Cheng 		warn_dlerr(status, "cannot persistently %s link property '%s'",
5867da14cebeSEric Cheng 		    reset ? "reset" : "set", prop_name);
58680ba2cbe9Sxc151355 	}
58690ba2cbe9Sxc151355 	return (status);
58700ba2cbe9Sxc151355 }
58710ba2cbe9Sxc151355 
5872da14cebeSEric Cheng static int
58734ac67f02SAnurag S. Maskey reset_one_linkprop(dladm_handle_t dh, datalink_id_t linkid,
58744ac67f02SAnurag S. Maskey     const char *propname, void *arg)
5875da14cebeSEric Cheng {
5876da14cebeSEric Cheng 	set_linkprop_state_t	*statep = arg;
5877da14cebeSEric Cheng 	dladm_status_t		status;
5878da14cebeSEric Cheng 
58794ac67f02SAnurag S. Maskey 	status = dladm_set_linkprop(dh, linkid, propname, NULL, 0,
5880da14cebeSEric Cheng 	    DLADM_OPT_ACTIVE);
5881*0b8f0546SSowmini Varadhan 	if (status != DLADM_STATUS_OK &&
5882*0b8f0546SSowmini Varadhan 	    status != DLADM_STATUS_PROPRDONLY &&
5883*0b8f0546SSowmini Varadhan 	    status != DLADM_STATUS_NOTSUP) {
5884da14cebeSEric Cheng 		warn_dlerr(status, "cannot reset link property '%s' on '%s'",
5885da14cebeSEric Cheng 		    propname, statep->ls_name);
5886da14cebeSEric Cheng 	}
5887da14cebeSEric Cheng 	if (!statep->ls_temp) {
5888da14cebeSEric Cheng 		dladm_status_t	s;
5889da14cebeSEric Cheng 
5890da14cebeSEric Cheng 		s = set_linkprop_persist(linkid, propname, NULL, 0,
5891da14cebeSEric Cheng 		    statep->ls_reset);
5892da14cebeSEric Cheng 		if (s != DLADM_STATUS_OK)
5893da14cebeSEric Cheng 			status = s;
5894da14cebeSEric Cheng 	}
5895da14cebeSEric Cheng 	if (status != DLADM_STATUS_OK)
5896da14cebeSEric Cheng 		statep->ls_status = status;
5897da14cebeSEric Cheng 
5898da14cebeSEric Cheng 	return (DLADM_WALK_CONTINUE);
5899da14cebeSEric Cheng }
5900da14cebeSEric Cheng 
59010ba2cbe9Sxc151355 static void
59028d5c46e6Sam223141 set_linkprop(int argc, char **argv, boolean_t reset, const char *use)
59030ba2cbe9Sxc151355 {
59040ba2cbe9Sxc151355 	int			i, option;
59050ba2cbe9Sxc151355 	char			errmsg[DLADM_STRSIZE];
5906d62bc4baSyz147064 	char			*altroot = NULL;
5907d62bc4baSyz147064 	datalink_id_t		linkid;
59080ba2cbe9Sxc151355 	boolean_t		temp = B_FALSE;
59090ba2cbe9Sxc151355 	dladm_status_t		status = DLADM_STATUS_OK;
591063a6526dSMichael Lim 	char			propstr[DLADM_STRSIZE];
5911da14cebeSEric Cheng 	dladm_arg_list_t	*proplist = NULL;
59120ba2cbe9Sxc151355 
59130ba2cbe9Sxc151355 	opterr = 0;
591463a6526dSMichael Lim 	bzero(propstr, DLADM_STRSIZE);
591563a6526dSMichael Lim 
59160ba2cbe9Sxc151355 	while ((option = getopt_long(argc, argv, ":p:R:t",
59170ba2cbe9Sxc151355 	    prop_longopts, NULL)) != -1) {
59180ba2cbe9Sxc151355 		switch (option) {
59190ba2cbe9Sxc151355 		case 'p':
592063a6526dSMichael Lim 			(void) strlcat(propstr, optarg, DLADM_STRSIZE);
592163a6526dSMichael Lim 			if (strlcat(propstr, ",", DLADM_STRSIZE) >=
592263a6526dSMichael Lim 			    DLADM_STRSIZE)
592363a6526dSMichael Lim 				die("property list too long '%s'", propstr);
59240ba2cbe9Sxc151355 			break;
59250ba2cbe9Sxc151355 		case 't':
59260ba2cbe9Sxc151355 			temp = B_TRUE;
59270ba2cbe9Sxc151355 			break;
59280ba2cbe9Sxc151355 		case 'R':
5929d62bc4baSyz147064 			altroot = optarg;
59300ba2cbe9Sxc151355 			break;
59310ba2cbe9Sxc151355 		default:
59328d5c46e6Sam223141 			die_opterr(optopt, option, use);
59338d5c46e6Sam223141 
59340ba2cbe9Sxc151355 		}
59350ba2cbe9Sxc151355 	}
59360ba2cbe9Sxc151355 
5937d62bc4baSyz147064 	/* get link name (required last argument) */
5938d62bc4baSyz147064 	if (optind != (argc - 1))
59390ba2cbe9Sxc151355 		usage();
59400ba2cbe9Sxc151355 
594163a6526dSMichael Lim 	if (dladm_parse_link_props(propstr, &proplist, reset) !=
594263a6526dSMichael Lim 	    DLADM_STATUS_OK)
594363a6526dSMichael Lim 		die("invalid link properties specified");
594463a6526dSMichael Lim 
5945d62bc4baSyz147064 	if (proplist == NULL && !reset)
594633343a97Smeem 		die("link property must be specified");
594733343a97Smeem 
5948d62bc4baSyz147064 	if (altroot != NULL) {
5949da14cebeSEric Cheng 		dladm_free_props(proplist);
5950d62bc4baSyz147064 		altroot_cmd(altroot, argc, argv);
5951d62bc4baSyz147064 	}
5952d62bc4baSyz147064 
59534ac67f02SAnurag S. Maskey 	status = dladm_name2info(handle, argv[optind], &linkid, NULL, NULL,
59544ac67f02SAnurag S. Maskey 	    NULL);
5955d62bc4baSyz147064 	if (status != DLADM_STATUS_OK)
5956d62bc4baSyz147064 		die_dlerr(status, "link %s is not valid", argv[optind]);
5957d62bc4baSyz147064 
5958d62bc4baSyz147064 	if (proplist == NULL) {
5959da14cebeSEric Cheng 		set_linkprop_state_t	state;
596013994ee8Sxz162242 
5961da14cebeSEric Cheng 		state.ls_name = argv[optind];
5962da14cebeSEric Cheng 		state.ls_reset = reset;
5963da14cebeSEric Cheng 		state.ls_temp = temp;
5964da14cebeSEric Cheng 		state.ls_status = DLADM_STATUS_OK;
5965da14cebeSEric Cheng 
59664ac67f02SAnurag S. Maskey 		(void) dladm_walk_linkprop(handle, linkid, &state,
59674ac67f02SAnurag S. Maskey 		    reset_one_linkprop);
5968da14cebeSEric Cheng 
5969da14cebeSEric Cheng 		status = state.ls_status;
59700ba2cbe9Sxc151355 		goto done;
59710ba2cbe9Sxc151355 	}
59720ba2cbe9Sxc151355 
5973da14cebeSEric Cheng 	for (i = 0; i < proplist->al_count; i++) {
5974da14cebeSEric Cheng 		dladm_arg_info_t	*aip = &proplist->al_info[i];
59750ba2cbe9Sxc151355 		char		**val;
59760ba2cbe9Sxc151355 		uint_t		count;
59770ba2cbe9Sxc151355 		dladm_status_t	s;
59780ba2cbe9Sxc151355 
59790ba2cbe9Sxc151355 		if (reset) {
59800ba2cbe9Sxc151355 			val = NULL;
59810ba2cbe9Sxc151355 			count = 0;
59820ba2cbe9Sxc151355 		} else {
5983da14cebeSEric Cheng 			val = aip->ai_val;
5984da14cebeSEric Cheng 			count = aip->ai_count;
59850ba2cbe9Sxc151355 			if (count == 0) {
598633343a97Smeem 				warn("no value specified for '%s'",
5987da14cebeSEric Cheng 				    aip->ai_name);
59880ba2cbe9Sxc151355 				status = DLADM_STATUS_BADARG;
59890ba2cbe9Sxc151355 				continue;
59900ba2cbe9Sxc151355 			}
59910ba2cbe9Sxc151355 		}
59924ac67f02SAnurag S. Maskey 		s = dladm_set_linkprop(handle, linkid, aip->ai_name, val, count,
5993d62bc4baSyz147064 		    DLADM_OPT_ACTIVE);
59940ba2cbe9Sxc151355 		if (s == DLADM_STATUS_OK) {
59950ba2cbe9Sxc151355 			if (!temp) {
5996d62bc4baSyz147064 				s = set_linkprop_persist(linkid,
5997da14cebeSEric Cheng 				    aip->ai_name, val, count, reset);
59980ba2cbe9Sxc151355 				if (s != DLADM_STATUS_OK)
59990ba2cbe9Sxc151355 					status = s;
60000ba2cbe9Sxc151355 			}
60010ba2cbe9Sxc151355 			continue;
60020ba2cbe9Sxc151355 		}
60030ba2cbe9Sxc151355 		status = s;
60040ba2cbe9Sxc151355 		switch (s) {
60050ba2cbe9Sxc151355 		case DLADM_STATUS_NOTFOUND:
6006da14cebeSEric Cheng 			warn("invalid link property '%s'", aip->ai_name);
60070ba2cbe9Sxc151355 			break;
60080ba2cbe9Sxc151355 		case DLADM_STATUS_BADVAL: {
60090ba2cbe9Sxc151355 			int		j;
60100ba2cbe9Sxc151355 			char		*ptr, *lim;
60110ba2cbe9Sxc151355 			char		**propvals = NULL;
6012d62bc4baSyz147064 			uint_t		valcnt = DLADM_MAX_PROP_VALCNT;
60130ba2cbe9Sxc151355 
60140ba2cbe9Sxc151355 			ptr = malloc((sizeof (char *) +
6015d62bc4baSyz147064 			    DLADM_PROP_VAL_MAX) * DLADM_MAX_PROP_VALCNT +
60160ba2cbe9Sxc151355 			    MAX_PROP_LINE);
60170ba2cbe9Sxc151355 
60180ba2cbe9Sxc151355 			propvals = (char **)(void *)ptr;
601933343a97Smeem 			if (propvals == NULL)
602033343a97Smeem 				die("insufficient memory");
602133343a97Smeem 
6022d62bc4baSyz147064 			for (j = 0; j < DLADM_MAX_PROP_VALCNT; j++) {
60230ba2cbe9Sxc151355 				propvals[j] = ptr + sizeof (char *) *
6024d62bc4baSyz147064 				    DLADM_MAX_PROP_VALCNT +
60250ba2cbe9Sxc151355 				    j * DLADM_PROP_VAL_MAX;
60260ba2cbe9Sxc151355 			}
60274ac67f02SAnurag S. Maskey 			s = dladm_get_linkprop(handle, linkid,
6028da14cebeSEric Cheng 			    DLADM_PROP_VAL_MODIFIABLE, aip->ai_name, propvals,
6029d62bc4baSyz147064 			    &valcnt);
6030d62bc4baSyz147064 
6031d62bc4baSyz147064 			if (s != DLADM_STATUS_OK) {
6032d62bc4baSyz147064 				warn_dlerr(status, "cannot set link property "
6033da14cebeSEric Cheng 				    "'%s' on '%s'", aip->ai_name, argv[optind]);
6034d62bc4baSyz147064 				free(propvals);
6035d62bc4baSyz147064 				break;
6036d62bc4baSyz147064 			}
60370ba2cbe9Sxc151355 
60380ba2cbe9Sxc151355 			ptr = errmsg;
60390ba2cbe9Sxc151355 			lim = ptr + DLADM_STRSIZE;
60400ba2cbe9Sxc151355 			*ptr = '\0';
6041d62bc4baSyz147064 			for (j = 0; j < valcnt; j++) {
60420ba2cbe9Sxc151355 				ptr += snprintf(ptr, lim - ptr, "%s,",
60430ba2cbe9Sxc151355 				    propvals[j]);
60440ba2cbe9Sxc151355 				if (ptr >= lim)
60450ba2cbe9Sxc151355 					break;
60460ba2cbe9Sxc151355 			}
6047f4b3ec61Sdh155122 			if (ptr > errmsg) {
60480ba2cbe9Sxc151355 				*(ptr - 1) = '\0';
604933343a97Smeem 				warn("link property '%s' must be one of: %s",
6050da14cebeSEric Cheng 				    aip->ai_name, errmsg);
6051f4b3ec61Sdh155122 			} else
6052f4b3ec61Sdh155122 				warn("invalid link property '%s'", *val);
60530ba2cbe9Sxc151355 			free(propvals);
60540ba2cbe9Sxc151355 			break;
60550ba2cbe9Sxc151355 		}
60560ba2cbe9Sxc151355 		default:
60570ba2cbe9Sxc151355 			if (reset) {
605833343a97Smeem 				warn_dlerr(status, "cannot reset link property "
6059da14cebeSEric Cheng 				    "'%s' on '%s'", aip->ai_name, argv[optind]);
60600ba2cbe9Sxc151355 			} else {
606133343a97Smeem 				warn_dlerr(status, "cannot set link property "
6062da14cebeSEric Cheng 				    "'%s' on '%s'", aip->ai_name, argv[optind]);
60630ba2cbe9Sxc151355 			}
60640ba2cbe9Sxc151355 			break;
60650ba2cbe9Sxc151355 		}
60660ba2cbe9Sxc151355 	}
60670ba2cbe9Sxc151355 done:
6068da14cebeSEric Cheng 	dladm_free_props(proplist);
60694ac67f02SAnurag S. Maskey 	if (status != DLADM_STATUS_OK) {
60704ac67f02SAnurag S. Maskey 		dladm_close(handle);
60710ba2cbe9Sxc151355 		exit(1);
60720ba2cbe9Sxc151355 	}
60734ac67f02SAnurag S. Maskey }
60740ba2cbe9Sxc151355 
60750ba2cbe9Sxc151355 static void
60768d5c46e6Sam223141 do_set_linkprop(int argc, char **argv, const char *use)
60770ba2cbe9Sxc151355 {
60788d5c46e6Sam223141 	set_linkprop(argc, argv, B_FALSE, use);
60790ba2cbe9Sxc151355 }
60800ba2cbe9Sxc151355 
60810ba2cbe9Sxc151355 static void
60828d5c46e6Sam223141 do_reset_linkprop(int argc, char **argv, const char *use)
60830ba2cbe9Sxc151355 {
60848d5c46e6Sam223141 	set_linkprop(argc, argv, B_TRUE, use);
60850ba2cbe9Sxc151355 }
60860ba2cbe9Sxc151355 
60870ba2cbe9Sxc151355 static int
60880ba2cbe9Sxc151355 convert_secobj(char *buf, uint_t len, uint8_t *obj_val, uint_t *obj_lenp,
60890ba2cbe9Sxc151355     dladm_secobj_class_t class)
60900ba2cbe9Sxc151355 {
60910ba2cbe9Sxc151355 	int error = 0;
60920ba2cbe9Sxc151355 
6093a399b765Szf162725 	if (class == DLADM_SECOBJ_CLASS_WPA) {
6094a399b765Szf162725 		if (len < 8 || len > 63)
6095a399b765Szf162725 			return (EINVAL);
6096a399b765Szf162725 		(void) memcpy(obj_val, buf, len);
6097a399b765Szf162725 		*obj_lenp = len;
6098a399b765Szf162725 		return (error);
6099a399b765Szf162725 	}
61000ba2cbe9Sxc151355 
6101a399b765Szf162725 	if (class == DLADM_SECOBJ_CLASS_WEP) {
61020ba2cbe9Sxc151355 		switch (len) {
61030ba2cbe9Sxc151355 		case 5:			/* ASCII key sizes */
61040ba2cbe9Sxc151355 		case 13:
61050ba2cbe9Sxc151355 			(void) memcpy(obj_val, buf, len);
61060ba2cbe9Sxc151355 			*obj_lenp = len;
61070ba2cbe9Sxc151355 			break;
61080ba2cbe9Sxc151355 		case 10:		/* Hex key sizes, not preceded by 0x */
61090ba2cbe9Sxc151355 		case 26:
61100ba2cbe9Sxc151355 			error = hexascii_to_octet(buf, len, obj_val, obj_lenp);
61110ba2cbe9Sxc151355 			break;
61120ba2cbe9Sxc151355 		case 12:		/* Hex key sizes, preceded by 0x */
61130ba2cbe9Sxc151355 		case 28:
61140ba2cbe9Sxc151355 			if (strncmp(buf, "0x", 2) != 0)
61150ba2cbe9Sxc151355 				return (EINVAL);
6116a399b765Szf162725 			error = hexascii_to_octet(buf + 2, len - 2,
6117a399b765Szf162725 			    obj_val, obj_lenp);
61180ba2cbe9Sxc151355 			break;
61190ba2cbe9Sxc151355 		default:
61200ba2cbe9Sxc151355 			return (EINVAL);
61210ba2cbe9Sxc151355 		}
61220ba2cbe9Sxc151355 		return (error);
61230ba2cbe9Sxc151355 	}
61240ba2cbe9Sxc151355 
6125a399b765Szf162725 	return (ENOENT);
6126a399b765Szf162725 }
6127a399b765Szf162725 
61280ba2cbe9Sxc151355 static void
61290ba2cbe9Sxc151355 defersig(int sig)
61300ba2cbe9Sxc151355 {
61310ba2cbe9Sxc151355 	signalled = sig;
61320ba2cbe9Sxc151355 }
61330ba2cbe9Sxc151355 
61340ba2cbe9Sxc151355 static int
61350ba2cbe9Sxc151355 get_secobj_from_tty(uint_t try, const char *objname, char *buf)
61360ba2cbe9Sxc151355 {
61370ba2cbe9Sxc151355 	uint_t		len = 0;
61380ba2cbe9Sxc151355 	int		c;
61390ba2cbe9Sxc151355 	struct termios	stored, current;
61400ba2cbe9Sxc151355 	void		(*sigfunc)(int);
61410ba2cbe9Sxc151355 
61420ba2cbe9Sxc151355 	/*
61430ba2cbe9Sxc151355 	 * Turn off echo -- but before we do so, defer SIGINT handling
61440ba2cbe9Sxc151355 	 * so that a ^C doesn't leave the terminal corrupted.
61450ba2cbe9Sxc151355 	 */
61460ba2cbe9Sxc151355 	sigfunc = signal(SIGINT, defersig);
61470ba2cbe9Sxc151355 	(void) fflush(stdin);
61480ba2cbe9Sxc151355 	(void) tcgetattr(0, &stored);
61490ba2cbe9Sxc151355 	current = stored;
61500ba2cbe9Sxc151355 	current.c_lflag &= ~(ICANON|ECHO);
61510ba2cbe9Sxc151355 	current.c_cc[VTIME] = 0;
61520ba2cbe9Sxc151355 	current.c_cc[VMIN] = 1;
61530ba2cbe9Sxc151355 	(void) tcsetattr(0, TCSANOW, &current);
61540ba2cbe9Sxc151355 again:
61550ba2cbe9Sxc151355 	if (try == 1)
61560ba2cbe9Sxc151355 		(void) printf(gettext("provide value for '%s': "), objname);
61570ba2cbe9Sxc151355 	else
61580ba2cbe9Sxc151355 		(void) printf(gettext("confirm value for '%s': "), objname);
61590ba2cbe9Sxc151355 
61600ba2cbe9Sxc151355 	(void) fflush(stdout);
61610ba2cbe9Sxc151355 	while (signalled == 0) {
61620ba2cbe9Sxc151355 		c = getchar();
61630ba2cbe9Sxc151355 		if (c == '\n' || c == '\r') {
61640ba2cbe9Sxc151355 			if (len != 0)
61650ba2cbe9Sxc151355 				break;
61660ba2cbe9Sxc151355 			(void) putchar('\n');
61670ba2cbe9Sxc151355 			goto again;
61680ba2cbe9Sxc151355 		}
61690ba2cbe9Sxc151355 
61700ba2cbe9Sxc151355 		buf[len++] = c;
61710ba2cbe9Sxc151355 		if (len >= DLADM_SECOBJ_VAL_MAX - 1)
61720ba2cbe9Sxc151355 			break;
61730ba2cbe9Sxc151355 		(void) putchar('*');
61740ba2cbe9Sxc151355 	}
61750ba2cbe9Sxc151355 
61760ba2cbe9Sxc151355 	(void) putchar('\n');
61770ba2cbe9Sxc151355 	(void) fflush(stdin);
61780ba2cbe9Sxc151355 
61790ba2cbe9Sxc151355 	/*
61800ba2cbe9Sxc151355 	 * Restore terminal setting and handle deferred signals.
61810ba2cbe9Sxc151355 	 */
61820ba2cbe9Sxc151355 	(void) tcsetattr(0, TCSANOW, &stored);
61830ba2cbe9Sxc151355 
61840ba2cbe9Sxc151355 	(void) signal(SIGINT, sigfunc);
61850ba2cbe9Sxc151355 	if (signalled != 0)
61860ba2cbe9Sxc151355 		(void) kill(getpid(), signalled);
61870ba2cbe9Sxc151355 
61880ba2cbe9Sxc151355 	return (len);
61890ba2cbe9Sxc151355 }
61900ba2cbe9Sxc151355 
61910ba2cbe9Sxc151355 static int
61920ba2cbe9Sxc151355 get_secobj_val(char *obj_name, uint8_t *obj_val, uint_t *obj_lenp,
61930ba2cbe9Sxc151355     dladm_secobj_class_t class, FILE *filep)
61940ba2cbe9Sxc151355 {
61950ba2cbe9Sxc151355 	int		rval;
61960ba2cbe9Sxc151355 	uint_t		len, len2;
61970ba2cbe9Sxc151355 	char		buf[DLADM_SECOBJ_VAL_MAX], buf2[DLADM_SECOBJ_VAL_MAX];
61980ba2cbe9Sxc151355 
61990ba2cbe9Sxc151355 	if (filep == NULL) {
62000ba2cbe9Sxc151355 		len = get_secobj_from_tty(1, obj_name, buf);
62010ba2cbe9Sxc151355 		rval = convert_secobj(buf, len, obj_val, obj_lenp, class);
62020ba2cbe9Sxc151355 		if (rval == 0) {
62030ba2cbe9Sxc151355 			len2 = get_secobj_from_tty(2, obj_name, buf2);
62040ba2cbe9Sxc151355 			if (len != len2 || memcmp(buf, buf2, len) != 0)
62050ba2cbe9Sxc151355 				rval = ENOTSUP;
62060ba2cbe9Sxc151355 		}
62070ba2cbe9Sxc151355 		return (rval);
62080ba2cbe9Sxc151355 	} else {
62090ba2cbe9Sxc151355 		for (;;) {
62100ba2cbe9Sxc151355 			if (fgets(buf, sizeof (buf), filep) == NULL)
62110ba2cbe9Sxc151355 				break;
62120ba2cbe9Sxc151355 			if (isspace(buf[0]))
62130ba2cbe9Sxc151355 				continue;
62140ba2cbe9Sxc151355 
62150ba2cbe9Sxc151355 			len = strlen(buf);
62160ba2cbe9Sxc151355 			if (buf[len - 1] == '\n') {
62170ba2cbe9Sxc151355 				buf[len - 1] = '\0';
62180ba2cbe9Sxc151355 				len--;
62190ba2cbe9Sxc151355 			}
62200ba2cbe9Sxc151355 			break;
62210ba2cbe9Sxc151355 		}
62220ba2cbe9Sxc151355 		(void) fclose(filep);
62230ba2cbe9Sxc151355 	}
62240ba2cbe9Sxc151355 	return (convert_secobj(buf, len, obj_val, obj_lenp, class));
62250ba2cbe9Sxc151355 }
62260ba2cbe9Sxc151355 
62270ba2cbe9Sxc151355 static boolean_t
62280ba2cbe9Sxc151355 check_auth(const char *auth)
62290ba2cbe9Sxc151355 {
62300ba2cbe9Sxc151355 	struct passwd	*pw;
62310ba2cbe9Sxc151355 
62320ba2cbe9Sxc151355 	if ((pw = getpwuid(getuid())) == NULL)
62330ba2cbe9Sxc151355 		return (B_FALSE);
62340ba2cbe9Sxc151355 
62350ba2cbe9Sxc151355 	return (chkauthattr(auth, pw->pw_name) != 0);
62360ba2cbe9Sxc151355 }
62370ba2cbe9Sxc151355 
62380ba2cbe9Sxc151355 static void
62390ba2cbe9Sxc151355 audit_secobj(char *auth, char *class, char *obj,
62400ba2cbe9Sxc151355     boolean_t success, boolean_t create)
62410ba2cbe9Sxc151355 {
62420ba2cbe9Sxc151355 	adt_session_data_t	*ah;
62430ba2cbe9Sxc151355 	adt_event_data_t	*event;
62440ba2cbe9Sxc151355 	au_event_t		flag;
62450ba2cbe9Sxc151355 	char			*errstr;
62460ba2cbe9Sxc151355 
62470ba2cbe9Sxc151355 	if (create) {
62480ba2cbe9Sxc151355 		flag = ADT_dladm_create_secobj;
62490ba2cbe9Sxc151355 		errstr = "ADT_dladm_create_secobj";
62500ba2cbe9Sxc151355 	} else {
62510ba2cbe9Sxc151355 		flag = ADT_dladm_delete_secobj;
62520ba2cbe9Sxc151355 		errstr = "ADT_dladm_delete_secobj";
62530ba2cbe9Sxc151355 	}
62540ba2cbe9Sxc151355 
625533343a97Smeem 	if (adt_start_session(&ah, NULL, ADT_USE_PROC_DATA) != 0)
625633343a97Smeem 		die("adt_start_session: %s", strerror(errno));
62570ba2cbe9Sxc151355 
625833343a97Smeem 	if ((event = adt_alloc_event(ah, flag)) == NULL)
625933343a97Smeem 		die("adt_alloc_event (%s): %s", errstr, strerror(errno));
62600ba2cbe9Sxc151355 
62610ba2cbe9Sxc151355 	/* fill in audit info */
62620ba2cbe9Sxc151355 	if (create) {
62630ba2cbe9Sxc151355 		event->adt_dladm_create_secobj.auth_used = auth;
62640ba2cbe9Sxc151355 		event->adt_dladm_create_secobj.obj_class = class;
62650ba2cbe9Sxc151355 		event->adt_dladm_create_secobj.obj_name = obj;
62660ba2cbe9Sxc151355 	} else {
62670ba2cbe9Sxc151355 		event->adt_dladm_delete_secobj.auth_used = auth;
62680ba2cbe9Sxc151355 		event->adt_dladm_delete_secobj.obj_class = class;
62690ba2cbe9Sxc151355 		event->adt_dladm_delete_secobj.obj_name = obj;
62700ba2cbe9Sxc151355 	}
62710ba2cbe9Sxc151355 
62720ba2cbe9Sxc151355 	if (success) {
62730ba2cbe9Sxc151355 		if (adt_put_event(event, ADT_SUCCESS, ADT_SUCCESS) != 0) {
627433343a97Smeem 			die("adt_put_event (%s, success): %s", errstr,
627533343a97Smeem 			    strerror(errno));
62760ba2cbe9Sxc151355 		}
62770ba2cbe9Sxc151355 	} else {
62780ba2cbe9Sxc151355 		if (adt_put_event(event, ADT_FAILURE,
62790ba2cbe9Sxc151355 		    ADT_FAIL_VALUE_AUTH) != 0) {
628033343a97Smeem 			die("adt_put_event: (%s, failure): %s", errstr,
628133343a97Smeem 			    strerror(errno));
62820ba2cbe9Sxc151355 		}
62830ba2cbe9Sxc151355 	}
62840ba2cbe9Sxc151355 
62850ba2cbe9Sxc151355 	adt_free_event(event);
62860ba2cbe9Sxc151355 	(void) adt_end_session(ah);
62870ba2cbe9Sxc151355 }
62880ba2cbe9Sxc151355 
62890ba2cbe9Sxc151355 #define	MAX_SECOBJS		32
62900ba2cbe9Sxc151355 #define	MAX_SECOBJ_NAMELEN	32
62910ba2cbe9Sxc151355 static void
62928d5c46e6Sam223141 do_create_secobj(int argc, char **argv, const char *use)
62930ba2cbe9Sxc151355 {
62940ba2cbe9Sxc151355 	int			option, rval;
62950ba2cbe9Sxc151355 	FILE			*filep = NULL;
62960ba2cbe9Sxc151355 	char			*obj_name = NULL;
62970ba2cbe9Sxc151355 	char			*class_name = NULL;
62980ba2cbe9Sxc151355 	uint8_t			obj_val[DLADM_SECOBJ_VAL_MAX];
62990ba2cbe9Sxc151355 	uint_t			obj_len;
63000ba2cbe9Sxc151355 	boolean_t		success, temp = B_FALSE;
63010ba2cbe9Sxc151355 	dladm_status_t		status;
63020ba2cbe9Sxc151355 	dladm_secobj_class_t	class = -1;
63030ba2cbe9Sxc151355 	uid_t			euid;
63040ba2cbe9Sxc151355 
63050ba2cbe9Sxc151355 	opterr = 0;
63060ba2cbe9Sxc151355 	(void) memset(obj_val, 0, DLADM_SECOBJ_VAL_MAX);
63070ba2cbe9Sxc151355 	while ((option = getopt_long(argc, argv, ":f:c:R:t",
63080ba2cbe9Sxc151355 	    wifi_longopts, NULL)) != -1) {
63090ba2cbe9Sxc151355 		switch (option) {
63100ba2cbe9Sxc151355 		case 'f':
63110ba2cbe9Sxc151355 			euid = geteuid();
63120ba2cbe9Sxc151355 			(void) seteuid(getuid());
63130ba2cbe9Sxc151355 			filep = fopen(optarg, "r");
63140ba2cbe9Sxc151355 			if (filep == NULL) {
631533343a97Smeem 				die("cannot open %s: %s", optarg,
631633343a97Smeem 				    strerror(errno));
63170ba2cbe9Sxc151355 			}
63180ba2cbe9Sxc151355 			(void) seteuid(euid);
63190ba2cbe9Sxc151355 			break;
63200ba2cbe9Sxc151355 		case 'c':
63210ba2cbe9Sxc151355 			class_name = optarg;
63220ba2cbe9Sxc151355 			status = dladm_str2secobjclass(optarg, &class);
63230ba2cbe9Sxc151355 			if (status != DLADM_STATUS_OK) {
632433343a97Smeem 				die("invalid secure object class '%s', "
6325a399b765Szf162725 				    "valid values are: wep, wpa", optarg);
63260ba2cbe9Sxc151355 			}
63270ba2cbe9Sxc151355 			break;
63280ba2cbe9Sxc151355 		case 't':
63290ba2cbe9Sxc151355 			temp = B_TRUE;
63300ba2cbe9Sxc151355 			break;
63310ba2cbe9Sxc151355 		case 'R':
63320ba2cbe9Sxc151355 			status = dladm_set_rootdir(optarg);
63330ba2cbe9Sxc151355 			if (status != DLADM_STATUS_OK) {
633433343a97Smeem 				die_dlerr(status, "invalid directory "
633533343a97Smeem 				    "specified");
63360ba2cbe9Sxc151355 			}
63370ba2cbe9Sxc151355 			break;
63380ba2cbe9Sxc151355 		default:
63398d5c46e6Sam223141 			die_opterr(optopt, option, use);
63400ba2cbe9Sxc151355 			break;
63410ba2cbe9Sxc151355 		}
63420ba2cbe9Sxc151355 	}
63430ba2cbe9Sxc151355 
63440ba2cbe9Sxc151355 	if (optind == (argc - 1))
63450ba2cbe9Sxc151355 		obj_name = argv[optind];
63460ba2cbe9Sxc151355 	else if (optind != argc)
63470ba2cbe9Sxc151355 		usage();
63480ba2cbe9Sxc151355 
634933343a97Smeem 	if (class == -1)
635033343a97Smeem 		die("secure object class required");
63510ba2cbe9Sxc151355 
635233343a97Smeem 	if (obj_name == NULL)
635333343a97Smeem 		die("secure object name required");
63540ba2cbe9Sxc151355 
6355a9489f61SAnurag S. Maskey 	if (!dladm_valid_secobj_name(obj_name))
6356a9489f61SAnurag S. Maskey 		die("invalid secure object name '%s'", obj_name);
6357a9489f61SAnurag S. Maskey 
63580ba2cbe9Sxc151355 	success = check_auth(LINK_SEC_AUTH);
63590ba2cbe9Sxc151355 	audit_secobj(LINK_SEC_AUTH, class_name, obj_name, success, B_TRUE);
636033343a97Smeem 	if (!success)
636133343a97Smeem 		die("authorization '%s' is required", LINK_SEC_AUTH);
63620ba2cbe9Sxc151355 
636333343a97Smeem 	rval = get_secobj_val(obj_name, obj_val, &obj_len, class, filep);
636433343a97Smeem 	if (rval != 0) {
63650ba2cbe9Sxc151355 		switch (rval) {
63660ba2cbe9Sxc151355 		case ENOENT:
636733343a97Smeem 			die("invalid secure object class");
63680ba2cbe9Sxc151355 			break;
63690ba2cbe9Sxc151355 		case EINVAL:
637033343a97Smeem 			die("invalid secure object value");
63710ba2cbe9Sxc151355 			break;
63720ba2cbe9Sxc151355 		case ENOTSUP:
637333343a97Smeem 			die("verification failed");
63740ba2cbe9Sxc151355 			break;
63750ba2cbe9Sxc151355 		default:
637633343a97Smeem 			die("invalid secure object: %s", strerror(rval));
63770ba2cbe9Sxc151355 			break;
63780ba2cbe9Sxc151355 		}
63790ba2cbe9Sxc151355 	}
63800ba2cbe9Sxc151355 
63814ac67f02SAnurag S. Maskey 	status = dladm_set_secobj(handle, obj_name, class, obj_val, obj_len,
6382d62bc4baSyz147064 	    DLADM_OPT_CREATE | DLADM_OPT_ACTIVE);
63830ba2cbe9Sxc151355 	if (status != DLADM_STATUS_OK) {
638433343a97Smeem 		die_dlerr(status, "could not create secure object '%s'",
638533343a97Smeem 		    obj_name);
63860ba2cbe9Sxc151355 	}
63870ba2cbe9Sxc151355 	if (temp)
63880ba2cbe9Sxc151355 		return;
63890ba2cbe9Sxc151355 
63904ac67f02SAnurag S. Maskey 	status = dladm_set_secobj(handle, obj_name, class, obj_val, obj_len,
63910ba2cbe9Sxc151355 	    DLADM_OPT_PERSIST);
63920ba2cbe9Sxc151355 	if (status != DLADM_STATUS_OK) {
639333343a97Smeem 		warn_dlerr(status, "could not persistently create secure "
639433343a97Smeem 		    "object '%s'", obj_name);
63950ba2cbe9Sxc151355 	}
63960ba2cbe9Sxc151355 }
63970ba2cbe9Sxc151355 
63980ba2cbe9Sxc151355 static void
63998d5c46e6Sam223141 do_delete_secobj(int argc, char **argv, const char *use)
64000ba2cbe9Sxc151355 {
64010ba2cbe9Sxc151355 	int		i, option;
64020ba2cbe9Sxc151355 	boolean_t	temp = B_FALSE;
64030ba2cbe9Sxc151355 	boolean_t	success;
64040ba2cbe9Sxc151355 	dladm_status_t	status, pstatus;
64058002d411SSowmini Varadhan 	int		nfields = 1;
64068002d411SSowmini Varadhan 	char		*field, *token, *lasts = NULL, c;
64070ba2cbe9Sxc151355 
64080ba2cbe9Sxc151355 	opterr = 0;
64090ba2cbe9Sxc151355 	status = pstatus = DLADM_STATUS_OK;
641033343a97Smeem 	while ((option = getopt_long(argc, argv, ":R:t",
64110ba2cbe9Sxc151355 	    wifi_longopts, NULL)) != -1) {
64120ba2cbe9Sxc151355 		switch (option) {
64130ba2cbe9Sxc151355 		case 't':
64140ba2cbe9Sxc151355 			temp = B_TRUE;
64150ba2cbe9Sxc151355 			break;
64160ba2cbe9Sxc151355 		case 'R':
64170ba2cbe9Sxc151355 			status = dladm_set_rootdir(optarg);
64180ba2cbe9Sxc151355 			if (status != DLADM_STATUS_OK) {
641933343a97Smeem 				die_dlerr(status, "invalid directory "
642033343a97Smeem 				    "specified");
64210ba2cbe9Sxc151355 			}
64220ba2cbe9Sxc151355 			break;
64230ba2cbe9Sxc151355 		default:
64248d5c46e6Sam223141 			die_opterr(optopt, option, use);
64250ba2cbe9Sxc151355 			break;
64260ba2cbe9Sxc151355 		}
64270ba2cbe9Sxc151355 	}
64280ba2cbe9Sxc151355 
64290ba2cbe9Sxc151355 	if (optind == (argc - 1)) {
64308002d411SSowmini Varadhan 		token = argv[optind];
64318002d411SSowmini Varadhan 		if (token == NULL)
64328002d411SSowmini Varadhan 			die("secure object name required");
64338002d411SSowmini Varadhan 		while ((c = *token++) != NULL) {
64348002d411SSowmini Varadhan 			if (c == ',')
64358002d411SSowmini Varadhan 				nfields++;
64360ba2cbe9Sxc151355 		}
64378002d411SSowmini Varadhan 		token = strdup(argv[optind]);
64388002d411SSowmini Varadhan 		if (token == NULL)
64398002d411SSowmini Varadhan 			die("no memory");
64400ba2cbe9Sxc151355 	} else if (optind != argc)
64410ba2cbe9Sxc151355 		usage();
64420ba2cbe9Sxc151355 
64430ba2cbe9Sxc151355 	success = check_auth(LINK_SEC_AUTH);
6444a399b765Szf162725 	audit_secobj(LINK_SEC_AUTH, "unknown", argv[optind], success, B_FALSE);
644533343a97Smeem 	if (!success)
644633343a97Smeem 		die("authorization '%s' is required", LINK_SEC_AUTH);
64470ba2cbe9Sxc151355 
64488002d411SSowmini Varadhan 	for (i = 0; i < nfields; i++) {
64498002d411SSowmini Varadhan 
64508002d411SSowmini Varadhan 		field = strtok_r(token, ",", &lasts);
64518002d411SSowmini Varadhan 		token = NULL;
64528002d411SSowmini Varadhan 		status = dladm_unset_secobj(handle, field, DLADM_OPT_ACTIVE);
64530ba2cbe9Sxc151355 		if (!temp) {
64548002d411SSowmini Varadhan 			pstatus = dladm_unset_secobj(handle, field,
64550ba2cbe9Sxc151355 			    DLADM_OPT_PERSIST);
64560ba2cbe9Sxc151355 		} else {
64570ba2cbe9Sxc151355 			pstatus = DLADM_STATUS_OK;
64580ba2cbe9Sxc151355 		}
64590ba2cbe9Sxc151355 
64600ba2cbe9Sxc151355 		if (status != DLADM_STATUS_OK) {
646133343a97Smeem 			warn_dlerr(status, "could not delete secure object "
64628002d411SSowmini Varadhan 			    "'%s'", field);
64630ba2cbe9Sxc151355 		}
64640ba2cbe9Sxc151355 		if (pstatus != DLADM_STATUS_OK) {
646533343a97Smeem 			warn_dlerr(pstatus, "could not persistently delete "
64668002d411SSowmini Varadhan 			    "secure object '%s'", field);
64670ba2cbe9Sxc151355 		}
64680ba2cbe9Sxc151355 	}
64698002d411SSowmini Varadhan 	free(token);
64704ac67f02SAnurag S. Maskey 
64714ac67f02SAnurag S. Maskey 	if (status != DLADM_STATUS_OK || pstatus != DLADM_STATUS_OK) {
64724ac67f02SAnurag S. Maskey 		dladm_close(handle);
64730ba2cbe9Sxc151355 		exit(1);
64740ba2cbe9Sxc151355 	}
64754ac67f02SAnurag S. Maskey }
64760ba2cbe9Sxc151355 
64770ba2cbe9Sxc151355 typedef struct show_secobj_state {
64780ba2cbe9Sxc151355 	boolean_t	ss_persist;
64798002d411SSowmini Varadhan 	boolean_t	ss_parsable;
64800ba2cbe9Sxc151355 	boolean_t	ss_header;
64818002d411SSowmini Varadhan 	ofmt_handle_t	ss_ofmt;
64820ba2cbe9Sxc151355 } show_secobj_state_t;
64830ba2cbe9Sxc151355 
64840ba2cbe9Sxc151355 
64850ba2cbe9Sxc151355 static boolean_t
64864ac67f02SAnurag S. Maskey show_secobj(dladm_handle_t dh, void *arg, const char *obj_name)
64870ba2cbe9Sxc151355 {
64880ba2cbe9Sxc151355 	uint_t			obj_len = DLADM_SECOBJ_VAL_MAX;
64890ba2cbe9Sxc151355 	uint8_t			obj_val[DLADM_SECOBJ_VAL_MAX];
64900ba2cbe9Sxc151355 	char			buf[DLADM_STRSIZE];
64910ba2cbe9Sxc151355 	uint_t			flags = 0;
64920ba2cbe9Sxc151355 	dladm_secobj_class_t	class;
64930ba2cbe9Sxc151355 	show_secobj_state_t	*statep = arg;
64940ba2cbe9Sxc151355 	dladm_status_t		status;
6495e7801d59Ssowmini 	secobj_fields_buf_t	sbuf;
64960ba2cbe9Sxc151355 
64975f5c9f54SAnurag S. Maskey 	bzero(&sbuf, sizeof (secobj_fields_buf_t));
64980ba2cbe9Sxc151355 	if (statep->ss_persist)
64990ba2cbe9Sxc151355 		flags |= DLADM_OPT_PERSIST;
65000ba2cbe9Sxc151355 
65014ac67f02SAnurag S. Maskey 	status = dladm_get_secobj(dh, obj_name, &class, obj_val, &obj_len,
65024ac67f02SAnurag S. Maskey 	    flags);
650333343a97Smeem 	if (status != DLADM_STATUS_OK)
650433343a97Smeem 		die_dlerr(status, "cannot get secure object '%s'", obj_name);
65050ba2cbe9Sxc151355 
6506e7801d59Ssowmini 	(void) snprintf(sbuf.ss_obj_name, sizeof (sbuf.ss_obj_name),
6507e7801d59Ssowmini 	    obj_name);
6508e7801d59Ssowmini 	(void) dladm_secobjclass2str(class, buf);
6509e7801d59Ssowmini 	(void) snprintf(sbuf.ss_class, sizeof (sbuf.ss_class), "%s", buf);
6510e7801d59Ssowmini 	if (getuid() == 0) {
65110ba2cbe9Sxc151355 		char	val[DLADM_SECOBJ_VAL_MAX * 2];
65120ba2cbe9Sxc151355 		uint_t	len = sizeof (val);
65130ba2cbe9Sxc151355 
6514e7801d59Ssowmini 		if (octet_to_hexascii(obj_val, obj_len, val, &len) == 0)
6515e7801d59Ssowmini 			(void) snprintf(sbuf.ss_val,
6516e7801d59Ssowmini 			    sizeof (sbuf.ss_val), "%s", val);
65170ba2cbe9Sxc151355 	}
65188002d411SSowmini Varadhan 	ofmt_print(statep->ss_ofmt, &sbuf);
65190ba2cbe9Sxc151355 	return (B_TRUE);
65200ba2cbe9Sxc151355 }
65210ba2cbe9Sxc151355 
65220ba2cbe9Sxc151355 static void
65238d5c46e6Sam223141 do_show_secobj(int argc, char **argv, const char *use)
65240ba2cbe9Sxc151355 {
65250ba2cbe9Sxc151355 	int			option;
65260ba2cbe9Sxc151355 	show_secobj_state_t	state;
65270ba2cbe9Sxc151355 	dladm_status_t		status;
65280d365605Sschuster 	boolean_t		o_arg = B_FALSE;
65290ba2cbe9Sxc151355 	uint_t			i;
65300ba2cbe9Sxc151355 	uint_t			flags;
6531e7801d59Ssowmini 	char			*fields_str = NULL;
6532e7801d59Ssowmini 	char			*def_fields = "object,class";
6533e7801d59Ssowmini 	char			*all_fields = "object,class,value";
65348002d411SSowmini Varadhan 	char			*field, *token, *lasts = NULL, c;
65358002d411SSowmini Varadhan 	ofmt_handle_t		ofmt;
65368002d411SSowmini Varadhan 	ofmt_status_t		oferr;
65378002d411SSowmini Varadhan 	uint_t			ofmtflags = 0;
65380ba2cbe9Sxc151355 
65390ba2cbe9Sxc151355 	opterr = 0;
6540e7801d59Ssowmini 	bzero(&state, sizeof (state));
65418002d411SSowmini Varadhan 	state.ss_parsable = B_FALSE;
6542e7801d59Ssowmini 	fields_str = def_fields;
65430ba2cbe9Sxc151355 	state.ss_persist = B_FALSE;
65448002d411SSowmini Varadhan 	state.ss_parsable = B_FALSE;
65450ba2cbe9Sxc151355 	state.ss_header = B_TRUE;
6546e7801d59Ssowmini 	while ((option = getopt_long(argc, argv, ":pPo:",
65470ba2cbe9Sxc151355 	    wifi_longopts, NULL)) != -1) {
65480ba2cbe9Sxc151355 		switch (option) {
65490ba2cbe9Sxc151355 		case 'p':
65508002d411SSowmini Varadhan 			state.ss_parsable = B_TRUE;
65510ba2cbe9Sxc151355 			break;
65520ba2cbe9Sxc151355 		case 'P':
65530ba2cbe9Sxc151355 			state.ss_persist = B_TRUE;
65540ba2cbe9Sxc151355 			break;
6555e7801d59Ssowmini 		case 'o':
65560d365605Sschuster 			o_arg = B_TRUE;
6557e7801d59Ssowmini 			if (strcasecmp(optarg, "all") == 0)
6558e7801d59Ssowmini 				fields_str = all_fields;
6559e7801d59Ssowmini 			else
6560e7801d59Ssowmini 				fields_str = optarg;
65610ba2cbe9Sxc151355 			break;
65620ba2cbe9Sxc151355 		default:
65638d5c46e6Sam223141 			die_opterr(optopt, option, use);
65640ba2cbe9Sxc151355 			break;
65650ba2cbe9Sxc151355 		}
65660ba2cbe9Sxc151355 	}
65670ba2cbe9Sxc151355 
65688002d411SSowmini Varadhan 	if (state.ss_parsable && !o_arg)
65690d365605Sschuster 		die("option -c requires -o");
65700d365605Sschuster 
65718002d411SSowmini Varadhan 	if (state.ss_parsable && fields_str == all_fields)
65720d365605Sschuster 		die("\"-o all\" is invalid with -p");
65730d365605Sschuster 
65748002d411SSowmini Varadhan 	if (state.ss_parsable)
65758002d411SSowmini Varadhan 		ofmtflags |= OFMT_PARSABLE;
65768002d411SSowmini Varadhan 	oferr = ofmt_open(fields_str, secobj_fields, ofmtflags, 0, &ofmt);
65778002d411SSowmini Varadhan 	dladm_ofmt_check(oferr, state.ss_parsable, ofmt);
65788002d411SSowmini Varadhan 	state.ss_ofmt = ofmt;
6579e7801d59Ssowmini 
6580e7801d59Ssowmini 	flags = state.ss_persist ? DLADM_OPT_PERSIST : 0;
65814ac67f02SAnurag S. Maskey 
65820ba2cbe9Sxc151355 	if (optind == (argc - 1)) {
65838002d411SSowmini Varadhan 		uint_t obj_fields = 1;
65848002d411SSowmini Varadhan 
65858002d411SSowmini Varadhan 		token = argv[optind];
65868002d411SSowmini Varadhan 		if (token == NULL)
65878002d411SSowmini Varadhan 			die("secure object name required");
65888002d411SSowmini Varadhan 		while ((c = *token++) != NULL) {
65898002d411SSowmini Varadhan 			if (c == ',')
65908002d411SSowmini Varadhan 				obj_fields++;
65910ba2cbe9Sxc151355 		}
65928002d411SSowmini Varadhan 		token = strdup(argv[optind]);
65938002d411SSowmini Varadhan 		if (token == NULL)
65948002d411SSowmini Varadhan 			die("no memory");
65958002d411SSowmini Varadhan 		for (i = 0; i < obj_fields; i++) {
65968002d411SSowmini Varadhan 			field = strtok_r(token, ",", &lasts);
65978002d411SSowmini Varadhan 			token = NULL;
65988002d411SSowmini Varadhan 			if (!show_secobj(handle, &state, field))
65990ba2cbe9Sxc151355 				break;
66000ba2cbe9Sxc151355 		}
66018002d411SSowmini Varadhan 		free(token);
66028002d411SSowmini Varadhan 		ofmt_close(ofmt);
66030ba2cbe9Sxc151355 		return;
66040ba2cbe9Sxc151355 	} else if (optind != argc)
66050ba2cbe9Sxc151355 		usage();
66060ba2cbe9Sxc151355 
66074ac67f02SAnurag S. Maskey 	status = dladm_walk_secobj(handle, &state, show_secobj, flags);
66084ac67f02SAnurag S. Maskey 
660933343a97Smeem 	if (status != DLADM_STATUS_OK)
661033343a97Smeem 		die_dlerr(status, "show-secobj");
66118002d411SSowmini Varadhan 	ofmt_close(ofmt);
66120ba2cbe9Sxc151355 }
66130ba2cbe9Sxc151355 
66140ba2cbe9Sxc151355 /*ARGSUSED*/
6615d62bc4baSyz147064 static int
66164ac67f02SAnurag S. Maskey i_dladm_init_linkprop(dladm_handle_t dh, datalink_id_t linkid, void *arg)
6617d62bc4baSyz147064 {
66184ac67f02SAnurag S. Maskey 	(void) dladm_init_linkprop(dh, linkid, B_TRUE);
6619d62bc4baSyz147064 	return (DLADM_WALK_CONTINUE);
6620d62bc4baSyz147064 }
6621d62bc4baSyz147064 
66228d5c46e6Sam223141 /*ARGSUSED*/
6623da14cebeSEric Cheng void
66248d5c46e6Sam223141 do_init_linkprop(int argc, char **argv, const char *use)
66250ba2cbe9Sxc151355 {
662630890389Sartem 	int			option;
662730890389Sartem 	dladm_status_t		status;
662830890389Sartem 	datalink_id_t		linkid = DATALINK_ALL_LINKID;
662930890389Sartem 	datalink_media_t	media = DATALINK_ANY_MEDIATYPE;
663030890389Sartem 	uint_t			any_media = B_TRUE;
663130890389Sartem 
663230890389Sartem 	opterr = 0;
663330890389Sartem 	while ((option = getopt(argc, argv, ":w")) != -1) {
663430890389Sartem 		switch (option) {
663530890389Sartem 		case 'w':
663630890389Sartem 			media = DL_WIFI;
663730890389Sartem 			any_media = B_FALSE;
663830890389Sartem 			break;
663930890389Sartem 		default:
66408d5c46e6Sam223141 			/*
66418d5c46e6Sam223141 			 * Because init-linkprop is not a public command,
66428d5c46e6Sam223141 			 * print the usage instead.
66438d5c46e6Sam223141 			 */
66448d5c46e6Sam223141 			usage();
664530890389Sartem 			break;
664630890389Sartem 		}
664730890389Sartem 	}
664830890389Sartem 
664930890389Sartem 	if (optind == (argc - 1)) {
66504ac67f02SAnurag S. Maskey 		if ((status = dladm_name2info(handle, argv[optind], &linkid,
66514ac67f02SAnurag S. Maskey 		    NULL, NULL, NULL)) != DLADM_STATUS_OK)
665230890389Sartem 			die_dlerr(status, "link %s is not valid", argv[optind]);
665330890389Sartem 	} else if (optind != argc) {
665430890389Sartem 		usage();
665530890389Sartem 	}
665630890389Sartem 
665730890389Sartem 	if (linkid == DATALINK_ALL_LINKID) {
6658d62bc4baSyz147064 		/*
665930890389Sartem 		 * linkprops of links of other classes have been initialized as
6660d62bc4baSyz147064 		 * part of the dladm up-xxx operation.
6661d62bc4baSyz147064 		 */
66624ac67f02SAnurag S. Maskey 		(void) dladm_walk_datalink_id(i_dladm_init_linkprop, handle,
66634ac67f02SAnurag S. Maskey 		    NULL, DATALINK_CLASS_PHYS, media, DLADM_OPT_PERSIST);
666430890389Sartem 	} else {
66654ac67f02SAnurag S. Maskey 		(void) dladm_init_linkprop(handle, linkid, any_media);
666630890389Sartem 	}
66670ba2cbe9Sxc151355 }
66680ba2cbe9Sxc151355 
66690ba2cbe9Sxc151355 static void
66708d5c46e6Sam223141 do_show_ether(int argc, char **argv, const char *use)
6671e7801d59Ssowmini {
6672e7801d59Ssowmini 	int 			option;
6673e7801d59Ssowmini 	datalink_id_t		linkid;
6674e7801d59Ssowmini 	print_ether_state_t 	state;
66758002d411SSowmini Varadhan 	char			*fields_str = NULL;
66768002d411SSowmini Varadhan 	ofmt_handle_t		ofmt;
66778002d411SSowmini Varadhan 	ofmt_status_t		oferr;
66788002d411SSowmini Varadhan 	uint_t			ofmtflags = 0;
6679e7801d59Ssowmini 
6680e7801d59Ssowmini 	bzero(&state, sizeof (state));
6681e7801d59Ssowmini 	state.es_link = NULL;
66828002d411SSowmini Varadhan 	state.es_parsable = B_FALSE;
6683e7801d59Ssowmini 
6684e7801d59Ssowmini 	while ((option = getopt_long(argc, argv, "o:px",
6685e7801d59Ssowmini 	    showeth_lopts, NULL)) != -1) {
6686e7801d59Ssowmini 		switch (option) {
6687e7801d59Ssowmini 			case 'x':
6688e7801d59Ssowmini 				state.es_extended = B_TRUE;
6689e7801d59Ssowmini 				break;
6690e7801d59Ssowmini 			case 'p':
66918002d411SSowmini Varadhan 				state.es_parsable = B_TRUE;
6692e7801d59Ssowmini 				break;
6693e7801d59Ssowmini 			case 'o':
6694e7801d59Ssowmini 				fields_str = optarg;
6695e7801d59Ssowmini 				break;
6696e7801d59Ssowmini 			default:
66978d5c46e6Sam223141 				die_opterr(optopt, option, use);
6698e7801d59Ssowmini 				break;
6699e7801d59Ssowmini 		}
6700e7801d59Ssowmini 	}
6701e7801d59Ssowmini 
6702e7801d59Ssowmini 	if (optind == (argc - 1))
6703e7801d59Ssowmini 		state.es_link = argv[optind];
6704e7801d59Ssowmini 
67058002d411SSowmini Varadhan 	if (state.es_parsable)
67068002d411SSowmini Varadhan 		ofmtflags |= OFMT_PARSABLE;
67078002d411SSowmini Varadhan 	oferr = ofmt_open(fields_str, ether_fields, ofmtflags,
67088002d411SSowmini Varadhan 	    DLADM_DEFAULT_COL, &ofmt);
67098002d411SSowmini Varadhan 	dladm_ofmt_check(oferr, state.es_parsable, ofmt);
67108002d411SSowmini Varadhan 	state.es_ofmt = ofmt;
67114ac67f02SAnurag S. Maskey 
6712e7801d59Ssowmini 	if (state.es_link == NULL) {
67134ac67f02SAnurag S. Maskey 		(void) dladm_walk_datalink_id(show_etherprop, handle, &state,
67143361618bSRishi Srivatsavai 		    DATALINK_CLASS_PHYS, DL_ETHER, DLADM_OPT_ACTIVE);
6715e7801d59Ssowmini 	} else {
67164ac67f02SAnurag S. Maskey 		if (!link_is_ether(state.es_link, &linkid))
6717e7801d59Ssowmini 			die("invalid link specified");
67184ac67f02SAnurag S. Maskey 		(void) show_etherprop(handle, linkid, &state);
6719e7801d59Ssowmini 	}
67208002d411SSowmini Varadhan 	ofmt_close(ofmt);
6721e7801d59Ssowmini }
6722e7801d59Ssowmini 
6723e7801d59Ssowmini static int
67244ac67f02SAnurag S. Maskey show_etherprop(dladm_handle_t dh, datalink_id_t linkid, void *arg)
6725e7801d59Ssowmini {
6726e7801d59Ssowmini 	print_ether_state_t	*statep = arg;
6727e7801d59Ssowmini 	ether_fields_buf_t	ebuf;
67284784fcbdSSowmini Varadhan 	dladm_ether_info_t	eattr;
67294784fcbdSSowmini Varadhan 	dladm_status_t		status;
6730e7801d59Ssowmini 
67315f5c9f54SAnurag S. Maskey 	bzero(&ebuf, sizeof (ether_fields_buf_t));
67324ac67f02SAnurag S. Maskey 	if (dladm_datalink_id2info(dh, linkid, NULL, NULL, NULL,
6733e7801d59Ssowmini 	    ebuf.eth_link, sizeof (ebuf.eth_link)) != DLADM_STATUS_OK) {
6734e7801d59Ssowmini 		return (DLADM_WALK_CONTINUE);
6735e7801d59Ssowmini 	}
6736e7801d59Ssowmini 
67374ac67f02SAnurag S. Maskey 	status = dladm_ether_info(dh, linkid, &eattr);
67384784fcbdSSowmini Varadhan 	if (status != DLADM_STATUS_OK)
67394784fcbdSSowmini Varadhan 		goto cleanup;
6740e7801d59Ssowmini 
67414784fcbdSSowmini Varadhan 	(void) strlcpy(ebuf.eth_ptype, "current", sizeof (ebuf.eth_ptype));
6742e7801d59Ssowmini 
67434784fcbdSSowmini Varadhan 	(void) dladm_ether_autoneg2str(ebuf.eth_autoneg,
67444784fcbdSSowmini Varadhan 	    sizeof (ebuf.eth_autoneg), &eattr, CURRENT);
67454784fcbdSSowmini Varadhan 	(void) dladm_ether_pause2str(ebuf.eth_pause,
67464784fcbdSSowmini Varadhan 	    sizeof (ebuf.eth_pause), &eattr, CURRENT);
67474784fcbdSSowmini Varadhan 	(void) dladm_ether_spdx2str(ebuf.eth_spdx,
67484784fcbdSSowmini Varadhan 	    sizeof (ebuf.eth_spdx), &eattr, CURRENT);
67494784fcbdSSowmini Varadhan 	(void) strlcpy(ebuf.eth_state,
67504784fcbdSSowmini Varadhan 	    dladm_linkstate2str(eattr.lei_state, ebuf.eth_state),
67514784fcbdSSowmini Varadhan 	    sizeof (ebuf.eth_state));
67524784fcbdSSowmini Varadhan 	(void) strlcpy(ebuf.eth_rem_fault,
67534784fcbdSSowmini Varadhan 	    (eattr.lei_attr[CURRENT].le_fault ? "fault" : "none"),
67544784fcbdSSowmini Varadhan 	    sizeof (ebuf.eth_rem_fault));
6755e7801d59Ssowmini 
67568002d411SSowmini Varadhan 	ofmt_print(statep->es_ofmt, &ebuf);
6757e7801d59Ssowmini 
6758e7801d59Ssowmini 	if (statep->es_extended)
67594784fcbdSSowmini Varadhan 		show_ether_xprop(arg, &eattr);
6760e7801d59Ssowmini 
67614784fcbdSSowmini Varadhan cleanup:
67624784fcbdSSowmini Varadhan 	dladm_ether_info_done(&eattr);
6763e7801d59Ssowmini 	return (DLADM_WALK_CONTINUE);
6764e7801d59Ssowmini }
6765e7801d59Ssowmini 
6766e7801d59Ssowmini /* ARGSUSED */
6767e7801d59Ssowmini static void
67688d5c46e6Sam223141 do_init_secobj(int argc, char **argv, const char *use)
67690ba2cbe9Sxc151355 {
67700ba2cbe9Sxc151355 	dladm_status_t	status;
67710ba2cbe9Sxc151355 
67724ac67f02SAnurag S. Maskey 	status = dladm_init_secobj(handle);
677333343a97Smeem 	if (status != DLADM_STATUS_OK)
677433343a97Smeem 		die_dlerr(status, "secure object initialization failed");
677533343a97Smeem }
677633343a97Smeem 
6777d62bc4baSyz147064 /*
6778d62bc4baSyz147064  * "-R" option support. It is used for live upgrading. Append dladm commands
6779d62bc4baSyz147064  * to a upgrade script which will be run when the alternative root boots up:
6780d62bc4baSyz147064  *
6781b9e076dcSyz147064  * - If the /etc/dladm/datalink.conf file exists on the alternative root,
6782b9e076dcSyz147064  * append dladm commands to the <altroot>/var/svc/profile/upgrade_datalink
6783b9e076dcSyz147064  * script. This script will be run as part of the network/physical service.
6784b9e076dcSyz147064  * We cannot defer this to /var/svc/profile/upgrade because then the
6785b9e076dcSyz147064  * configuration will not be able to take effect before network/physical
6786b9e076dcSyz147064  * plumbs various interfaces.
6787d62bc4baSyz147064  *
6788b9e076dcSyz147064  * - If the /etc/dladm/datalink.conf file does not exist on the alternative
6789b9e076dcSyz147064  * root, append dladm commands to the <altroot>/var/svc/profile/upgrade script,
6790b9e076dcSyz147064  * which will be run in the manifest-import service.
6791d62bc4baSyz147064  *
6792d62bc4baSyz147064  * Note that the SMF team is considering to move the manifest-import service
6793d62bc4baSyz147064  * to be run at the very begining of boot. Once that is done, the need for
6794d62bc4baSyz147064  * the /var/svc/profile/upgrade_datalink script will not exist any more.
6795d62bc4baSyz147064  */
6796d62bc4baSyz147064 static void
6797d62bc4baSyz147064 altroot_cmd(char *altroot, int argc, char *argv[])
6798d62bc4baSyz147064 {
6799d62bc4baSyz147064 	char		path[MAXPATHLEN];
6800d62bc4baSyz147064 	struct stat	stbuf;
6801d62bc4baSyz147064 	FILE		*fp;
6802d62bc4baSyz147064 	int		i;
6803d62bc4baSyz147064 
6804d62bc4baSyz147064 	/*
6805b9e076dcSyz147064 	 * Check for the existence of the /etc/dladm/datalink.conf
6806b9e076dcSyz147064 	 * configuration file, and determine the name of script file.
6807d62bc4baSyz147064 	 */
6808b9e076dcSyz147064 	(void) snprintf(path, MAXPATHLEN, "/%s/etc/dladm/datalink.conf",
6809b9e076dcSyz147064 	    altroot);
6810d62bc4baSyz147064 	if (stat(path, &stbuf) < 0) {
6811d62bc4baSyz147064 		(void) snprintf(path, MAXPATHLEN, "/%s/%s", altroot,
6812d62bc4baSyz147064 		    SMF_UPGRADE_FILE);
6813d62bc4baSyz147064 	} else {
6814d62bc4baSyz147064 		(void) snprintf(path, MAXPATHLEN, "/%s/%s", altroot,
6815d62bc4baSyz147064 		    SMF_UPGRADEDATALINK_FILE);
6816d62bc4baSyz147064 	}
6817d62bc4baSyz147064 
6818d62bc4baSyz147064 	if ((fp = fopen(path, "a+")) == NULL)
6819d62bc4baSyz147064 		die("operation not supported on %s", altroot);
6820d62bc4baSyz147064 
6821d62bc4baSyz147064 	(void) fprintf(fp, "/sbin/dladm ");
6822d62bc4baSyz147064 	for (i = 0; i < argc; i++) {
6823d62bc4baSyz147064 		/*
6824d62bc4baSyz147064 		 * Directly write to the file if it is not the "-R <altroot>"
6825d62bc4baSyz147064 		 * option. In which case, skip it.
6826d62bc4baSyz147064 		 */
6827d62bc4baSyz147064 		if (strcmp(argv[i], "-R") != 0)
6828d62bc4baSyz147064 			(void) fprintf(fp, "%s ", argv[i]);
6829d62bc4baSyz147064 		else
6830d62bc4baSyz147064 			i ++;
6831d62bc4baSyz147064 	}
6832d62bc4baSyz147064 	(void) fprintf(fp, "%s\n", SMF_DLADM_UPGRADE_MSG);
6833d62bc4baSyz147064 	(void) fclose(fp);
68344ac67f02SAnurag S. Maskey 	dladm_close(handle);
6835d62bc4baSyz147064 	exit(0);
6836d62bc4baSyz147064 }
6837d62bc4baSyz147064 
6838d62bc4baSyz147064 /*
6839d62bc4baSyz147064  * Convert the string to an integer. Note that the string must not have any
6840d62bc4baSyz147064  * trailing non-integer characters.
6841d62bc4baSyz147064  */
684233343a97Smeem static boolean_t
684333343a97Smeem str2int(const char *str, int *valp)
684433343a97Smeem {
684533343a97Smeem 	int	val;
684633343a97Smeem 	char	*endp = NULL;
684733343a97Smeem 
684833343a97Smeem 	errno = 0;
684933343a97Smeem 	val = strtol(str, &endp, 10);
685033343a97Smeem 	if (errno != 0 || *endp != '\0')
685133343a97Smeem 		return (B_FALSE);
685233343a97Smeem 
685333343a97Smeem 	*valp = val;
685433343a97Smeem 	return (B_TRUE);
685533343a97Smeem }
685633343a97Smeem 
685733343a97Smeem /* PRINTFLIKE1 */
685833343a97Smeem static void
685933343a97Smeem warn(const char *format, ...)
686033343a97Smeem {
686133343a97Smeem 	va_list alist;
686233343a97Smeem 
686333343a97Smeem 	format = gettext(format);
686433343a97Smeem 	(void) fprintf(stderr, "%s: warning: ", progname);
686533343a97Smeem 
686633343a97Smeem 	va_start(alist, format);
686733343a97Smeem 	(void) vfprintf(stderr, format, alist);
686833343a97Smeem 	va_end(alist);
686933343a97Smeem 
687033343a97Smeem 	(void) putchar('\n');
687133343a97Smeem }
687233343a97Smeem 
687333343a97Smeem /* PRINTFLIKE2 */
687433343a97Smeem static void
687533343a97Smeem warn_dlerr(dladm_status_t err, const char *format, ...)
687633343a97Smeem {
687733343a97Smeem 	va_list alist;
687833343a97Smeem 	char	errmsg[DLADM_STRSIZE];
687933343a97Smeem 
688033343a97Smeem 	format = gettext(format);
688133343a97Smeem 	(void) fprintf(stderr, gettext("%s: warning: "), progname);
688233343a97Smeem 
688333343a97Smeem 	va_start(alist, format);
688433343a97Smeem 	(void) vfprintf(stderr, format, alist);
688533343a97Smeem 	va_end(alist);
688633343a97Smeem 	(void) fprintf(stderr, ": %s\n", dladm_status2str(err, errmsg));
688733343a97Smeem }
688833343a97Smeem 
68894ac67f02SAnurag S. Maskey /*
68904ac67f02SAnurag S. Maskey  * Also closes the dladm handle if it is not NULL.
68914ac67f02SAnurag S. Maskey  */
689233343a97Smeem /* PRINTFLIKE2 */
689333343a97Smeem static void
689433343a97Smeem die_dlerr(dladm_status_t err, const char *format, ...)
689533343a97Smeem {
689633343a97Smeem 	va_list alist;
689733343a97Smeem 	char	errmsg[DLADM_STRSIZE];
689833343a97Smeem 
689933343a97Smeem 	format = gettext(format);
690033343a97Smeem 	(void) fprintf(stderr, "%s: ", progname);
690133343a97Smeem 
690233343a97Smeem 	va_start(alist, format);
690333343a97Smeem 	(void) vfprintf(stderr, format, alist);
690433343a97Smeem 	va_end(alist);
690533343a97Smeem 	(void) fprintf(stderr, ": %s\n", dladm_status2str(err, errmsg));
690633343a97Smeem 
69074ac67f02SAnurag S. Maskey 	/* close dladm handle if it was opened */
69084ac67f02SAnurag S. Maskey 	if (handle != NULL)
69094ac67f02SAnurag S. Maskey 		dladm_close(handle);
69104ac67f02SAnurag S. Maskey 
691133343a97Smeem 	exit(EXIT_FAILURE);
691233343a97Smeem }
691333343a97Smeem 
691433343a97Smeem /* PRINTFLIKE1 */
691533343a97Smeem static void
691633343a97Smeem die(const char *format, ...)
691733343a97Smeem {
691833343a97Smeem 	va_list alist;
691933343a97Smeem 
692033343a97Smeem 	format = gettext(format);
692133343a97Smeem 	(void) fprintf(stderr, "%s: ", progname);
692233343a97Smeem 
692333343a97Smeem 	va_start(alist, format);
692433343a97Smeem 	(void) vfprintf(stderr, format, alist);
692533343a97Smeem 	va_end(alist);
692633343a97Smeem 
692733343a97Smeem 	(void) putchar('\n');
69284ac67f02SAnurag S. Maskey 
69294ac67f02SAnurag S. Maskey 	/* close dladm handle if it was opened */
69304ac67f02SAnurag S. Maskey 	if (handle != NULL)
69314ac67f02SAnurag S. Maskey 		dladm_close(handle);
69324ac67f02SAnurag S. Maskey 
693333343a97Smeem 	exit(EXIT_FAILURE);
693433343a97Smeem }
693533343a97Smeem 
693633343a97Smeem static void
693733343a97Smeem die_optdup(int opt)
693833343a97Smeem {
693933343a97Smeem 	die("the option -%c cannot be specified more than once", opt);
694033343a97Smeem }
694133343a97Smeem 
694233343a97Smeem static void
69438d5c46e6Sam223141 die_opterr(int opt, int opterr, const char *usage)
694433343a97Smeem {
694533343a97Smeem 	switch (opterr) {
694633343a97Smeem 	case ':':
69478d5c46e6Sam223141 		die("option '-%c' requires a value\nusage: %s", opt,
69488d5c46e6Sam223141 		    gettext(usage));
694933343a97Smeem 		break;
695033343a97Smeem 	case '?':
695133343a97Smeem 	default:
69528d5c46e6Sam223141 		die("unrecognized option '-%c'\nusage: %s", opt,
69538d5c46e6Sam223141 		    gettext(usage));
695433343a97Smeem 		break;
69550ba2cbe9Sxc151355 	}
69560ba2cbe9Sxc151355 }
6957e7801d59Ssowmini 
6958e7801d59Ssowmini static void
69594784fcbdSSowmini Varadhan show_ether_xprop(void *arg, dladm_ether_info_t *eattr)
6960e7801d59Ssowmini {
6961e7801d59Ssowmini 	print_ether_state_t	*statep = arg;
6962e7801d59Ssowmini 	ether_fields_buf_t	ebuf;
69634784fcbdSSowmini Varadhan 	int			i;
6964e7801d59Ssowmini 
69654784fcbdSSowmini Varadhan 	for (i = CAPABLE; i <= PEERADV; i++)  {
6966e7801d59Ssowmini 		bzero(&ebuf, sizeof (ebuf));
69674784fcbdSSowmini Varadhan 		(void) strlcpy(ebuf.eth_ptype, ptype[i],
69684784fcbdSSowmini Varadhan 		    sizeof (ebuf.eth_ptype));
69694784fcbdSSowmini Varadhan 		(void) dladm_ether_autoneg2str(ebuf.eth_autoneg,
69704784fcbdSSowmini Varadhan 		    sizeof (ebuf.eth_autoneg), eattr, i);
69714784fcbdSSowmini Varadhan 		(void) dladm_ether_spdx2str(ebuf.eth_spdx,
69724784fcbdSSowmini Varadhan 		    sizeof (ebuf.eth_spdx), eattr, i);
69734784fcbdSSowmini Varadhan 		(void) dladm_ether_pause2str(ebuf.eth_pause,
69744784fcbdSSowmini Varadhan 		    sizeof (ebuf.eth_pause), eattr, i);
69754784fcbdSSowmini Varadhan 		(void) strlcpy(ebuf.eth_rem_fault,
69764784fcbdSSowmini Varadhan 		    (eattr->lei_attr[i].le_fault ? "fault" : "none"),
69774784fcbdSSowmini Varadhan 		    sizeof (ebuf.eth_rem_fault));
69788002d411SSowmini Varadhan 		ofmt_print(statep->es_ofmt, &ebuf);
6979e7801d59Ssowmini 	}
6980e7801d59Ssowmini 
6981e7801d59Ssowmini }
6982e7801d59Ssowmini 
6983e7801d59Ssowmini static boolean_t
6984e7801d59Ssowmini link_is_ether(const char *link, datalink_id_t *linkid)
6985e7801d59Ssowmini {
6986e7801d59Ssowmini 	uint32_t media;
6987e7801d59Ssowmini 	datalink_class_t class;
6988e7801d59Ssowmini 
69894ac67f02SAnurag S. Maskey 	if (dladm_name2info(handle, link, linkid, NULL, &class, &media) ==
6990e7801d59Ssowmini 	    DLADM_STATUS_OK) {
6991e7801d59Ssowmini 		if (class == DATALINK_CLASS_PHYS && media == DL_ETHER)
6992e7801d59Ssowmini 			return (B_TRUE);
6993e7801d59Ssowmini 	}
6994e7801d59Ssowmini 	return (B_FALSE);
6995e7801d59Ssowmini }
69968002d411SSowmini Varadhan 
69978002d411SSowmini Varadhan /*
69988002d411SSowmini Varadhan  * default output callback function that, when invoked,
69998002d411SSowmini Varadhan  * prints string which is offset by ofmt_arg->ofmt_id within buf.
70008002d411SSowmini Varadhan  */
70018002d411SSowmini Varadhan static boolean_t
70028002d411SSowmini Varadhan print_default_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize)
70038002d411SSowmini Varadhan {
70048002d411SSowmini Varadhan 	char *value;
70058002d411SSowmini Varadhan 
70068002d411SSowmini Varadhan 	value = (char *)ofarg->ofmt_cbarg + ofarg->ofmt_id;
70078002d411SSowmini Varadhan 	(void) strlcpy(buf, value, bufsize);
70088002d411SSowmini Varadhan 	return (B_TRUE);
70098002d411SSowmini Varadhan }
70108002d411SSowmini Varadhan 
70118002d411SSowmini Varadhan static void
70128002d411SSowmini Varadhan dladm_ofmt_check(ofmt_status_t oferr, boolean_t parsable,
70138002d411SSowmini Varadhan     ofmt_handle_t ofmt)
70148002d411SSowmini Varadhan {
70158002d411SSowmini Varadhan 	char buf[OFMT_BUFSIZE];
70168002d411SSowmini Varadhan 
70178002d411SSowmini Varadhan 	if (oferr == OFMT_SUCCESS)
70188002d411SSowmini Varadhan 		return;
70198002d411SSowmini Varadhan 	(void) ofmt_strerror(ofmt, oferr, buf, sizeof (buf));
70208002d411SSowmini Varadhan 	/*
70218002d411SSowmini Varadhan 	 * All errors are considered fatal in parsable mode.
70228002d411SSowmini Varadhan 	 * NOMEM errors are always fatal, regardless of mode.
70238002d411SSowmini Varadhan 	 * For other errors, we print diagnostics in human-readable
70248002d411SSowmini Varadhan 	 * mode and processs what we can.
70258002d411SSowmini Varadhan 	 */
70268002d411SSowmini Varadhan 	if (parsable || oferr == OFMT_ENOFIELDS) {
70278002d411SSowmini Varadhan 		ofmt_close(ofmt);
70288002d411SSowmini Varadhan 		die(buf);
70298002d411SSowmini Varadhan 	} else {
70308002d411SSowmini Varadhan 		warn(buf);
70318002d411SSowmini Varadhan 	}
70328002d411SSowmini Varadhan }
7033