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 = ¬sup; 5544149b7eb2SSowmini Varadhan } else if (status == DLADM_STATUS_NOTDEFINED) { 5545149b7eb2SSowmini Varadhan propvals = ¬sup; /* 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, ¤t); 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