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> 570ba2cbe9Sxc151355 #include <libinetutil.h> 580ba2cbe9Sxc151355 #include <bsm/adt.h> 590ba2cbe9Sxc151355 #include <bsm/adt_event.h> 60da14cebeSEric Cheng #include <libdlvnic.h> 61da14cebeSEric Cheng #include <sys/types.h> 62da14cebeSEric Cheng #include <sys/socket.h> 63da14cebeSEric Cheng #include <sys/processor.h> 64da14cebeSEric Cheng #include <netinet/in.h> 65da14cebeSEric Cheng #include <arpa/inet.h> 66da14cebeSEric Cheng #include <net/if_types.h> 67e7801d59Ssowmini #include <stddef.h> 68*8002d411SSowmini Varadhan #include <ofmt.h> 697c478bd9Sstevel@tonic-gate 707c478bd9Sstevel@tonic-gate #define MAXPORT 256 71da14cebeSEric Cheng #define MAXVNIC 256 72d62bc4baSyz147064 #define BUFLEN(lim, ptr) (((lim) > (ptr)) ? ((lim) - (ptr)) : 0) 73d62bc4baSyz147064 #define MAXLINELEN 1024 74d62bc4baSyz147064 #define SMF_UPGRADE_FILE "/var/svc/profile/upgrade" 75d62bc4baSyz147064 #define SMF_UPGRADEDATALINK_FILE "/var/svc/profile/upgrade_datalink" 76d62bc4baSyz147064 #define SMF_DLADM_UPGRADE_MSG " # added by dladm(1M)" 77*8002d411SSowmini Varadhan #define DLADM_DEFAULT_COL 80 787c478bd9Sstevel@tonic-gate 79*8002d411SSowmini Varadhan /* 80*8002d411SSowmini Varadhan * used by the wifi show-* commands to set up ofmt_field_t structures. 81*8002d411SSowmini Varadhan */ 82e7801d59Ssowmini #define WIFI_CMD_SCAN 0x00000001 83e7801d59Ssowmini #define WIFI_CMD_SHOW 0x00000002 84e7801d59Ssowmini #define WIFI_CMD_ALL (WIFI_CMD_SCAN | WIFI_CMD_SHOW) 85e7801d59Ssowmini 86d62bc4baSyz147064 typedef struct show_state { 877c478bd9Sstevel@tonic-gate boolean_t ls_firstonly; 887c478bd9Sstevel@tonic-gate boolean_t ls_donefirst; 897c478bd9Sstevel@tonic-gate pktsum_t ls_prevstats; 90d62bc4baSyz147064 uint32_t ls_flags; 91d62bc4baSyz147064 dladm_status_t ls_status; 92*8002d411SSowmini Varadhan ofmt_handle_t ls_ofmt; 93*8002d411SSowmini Varadhan boolean_t ls_parsable; 94da14cebeSEric Cheng boolean_t ls_mac; 95da14cebeSEric Cheng boolean_t ls_hwgrp; 96d62bc4baSyz147064 } show_state_t; 977c478bd9Sstevel@tonic-gate 987c478bd9Sstevel@tonic-gate typedef struct show_grp_state { 99e7801d59Ssowmini pktsum_t gs_prevstats[MAXPORT]; 100e7801d59Ssowmini uint32_t gs_flags; 101e7801d59Ssowmini dladm_status_t gs_status; 102*8002d411SSowmini Varadhan boolean_t gs_parsable; 1037c478bd9Sstevel@tonic-gate boolean_t gs_lacp; 104d62bc4baSyz147064 boolean_t gs_extended; 1057c478bd9Sstevel@tonic-gate boolean_t gs_stats; 1067c478bd9Sstevel@tonic-gate boolean_t gs_firstonly; 107d62bc4baSyz147064 boolean_t gs_donefirst; 108*8002d411SSowmini Varadhan ofmt_handle_t gs_ofmt; 1097c478bd9Sstevel@tonic-gate } show_grp_state_t; 1107c478bd9Sstevel@tonic-gate 111da14cebeSEric Cheng typedef struct show_vnic_state { 112da14cebeSEric Cheng datalink_id_t vs_vnic_id; 113da14cebeSEric Cheng datalink_id_t vs_link_id; 114da14cebeSEric Cheng char vs_vnic[MAXLINKNAMELEN]; 115da14cebeSEric Cheng char vs_link[MAXLINKNAMELEN]; 116*8002d411SSowmini Varadhan boolean_t vs_parsable; 117da14cebeSEric Cheng boolean_t vs_found; 118da14cebeSEric Cheng boolean_t vs_firstonly; 119da14cebeSEric Cheng boolean_t vs_donefirst; 120da14cebeSEric Cheng boolean_t vs_stats; 121da14cebeSEric Cheng boolean_t vs_printstats; 122da14cebeSEric Cheng pktsum_t vs_totalstats; 123da14cebeSEric Cheng pktsum_t vs_prevstats[MAXVNIC]; 124da14cebeSEric Cheng boolean_t vs_etherstub; 125da14cebeSEric Cheng dladm_status_t vs_status; 126da14cebeSEric Cheng uint32_t vs_flags; 127*8002d411SSowmini Varadhan ofmt_handle_t vs_ofmt; 128da14cebeSEric Cheng } show_vnic_state_t; 129da14cebeSEric Cheng 130da14cebeSEric Cheng typedef struct show_usage_state_s { 131da14cebeSEric Cheng boolean_t us_plot; 132*8002d411SSowmini Varadhan boolean_t us_parsable; 133da14cebeSEric Cheng boolean_t us_printheader; 134da14cebeSEric Cheng boolean_t us_first; 135ae6aa22aSVenugopal Iyer boolean_t us_showall; 136*8002d411SSowmini Varadhan ofmt_handle_t us_ofmt; 137da14cebeSEric Cheng } show_usage_state_t; 138da14cebeSEric Cheng 139*8002d411SSowmini Varadhan /* 140*8002d411SSowmini Varadhan * callback functions for printing output and error diagnostics. 141*8002d411SSowmini Varadhan */ 142*8002d411SSowmini Varadhan static ofmt_cb_t print_default_cb, print_link_stats_cb, print_linkprop_cb; 143*8002d411SSowmini Varadhan static ofmt_cb_t print_lacp_cb, print_phys_one_mac_cb; 144*8002d411SSowmini Varadhan static ofmt_cb_t print_xaggr_cb, print_aggr_stats_cb; 145*8002d411SSowmini Varadhan static ofmt_cb_t print_phys_one_hwgrp_cb, print_wlan_attr_cb; 146*8002d411SSowmini Varadhan static ofmt_cb_t print_wifi_status_cb, print_link_attr_cb; 147*8002d411SSowmini Varadhan static void dladm_ofmt_check(ofmt_status_t, boolean_t, ofmt_handle_t); 148*8002d411SSowmini Varadhan 1498d5c46e6Sam223141 typedef void cmdfunc_t(int, char **, const char *); 1500ba2cbe9Sxc151355 151da14cebeSEric Cheng static cmdfunc_t do_show_link, do_show_wifi, do_show_phys; 1520ba2cbe9Sxc151355 static cmdfunc_t do_create_aggr, do_delete_aggr, do_add_aggr, do_remove_aggr; 153d62bc4baSyz147064 static cmdfunc_t do_modify_aggr, do_show_aggr, do_up_aggr; 1540ba2cbe9Sxc151355 static cmdfunc_t do_scan_wifi, do_connect_wifi, do_disconnect_wifi; 1550ba2cbe9Sxc151355 static cmdfunc_t do_show_linkprop, do_set_linkprop, do_reset_linkprop; 1560ba2cbe9Sxc151355 static cmdfunc_t do_create_secobj, do_delete_secobj, do_show_secobj; 1570ba2cbe9Sxc151355 static cmdfunc_t do_init_linkprop, do_init_secobj; 158d62bc4baSyz147064 static cmdfunc_t do_create_vlan, do_delete_vlan, do_up_vlan, do_show_vlan; 159d62bc4baSyz147064 static cmdfunc_t do_rename_link, do_delete_phys, do_init_phys; 160d62bc4baSyz147064 static cmdfunc_t do_show_linkmap; 161e7801d59Ssowmini static cmdfunc_t do_show_ether; 162da14cebeSEric Cheng static cmdfunc_t do_create_vnic, do_delete_vnic, do_show_vnic; 163da14cebeSEric Cheng static cmdfunc_t do_up_vnic; 164da14cebeSEric Cheng static cmdfunc_t do_create_etherstub, do_delete_etherstub, do_show_etherstub; 165da14cebeSEric Cheng static cmdfunc_t do_show_usage; 166da14cebeSEric Cheng 167da14cebeSEric Cheng static void do_up_vnic_common(int, char **, const char *, boolean_t); 1687c478bd9Sstevel@tonic-gate 169d62bc4baSyz147064 static void altroot_cmd(char *, int, char **); 1704ac67f02SAnurag S. Maskey static int show_linkprop_onelink(dladm_handle_t, datalink_id_t, void *); 171f4b3ec61Sdh155122 1726be03d0bSVasumathi Sundaram - Sun Microsystems static void link_stats(datalink_id_t, uint_t, char *, show_state_t *); 173d62bc4baSyz147064 static void aggr_stats(datalink_id_t, show_grp_state_t *, uint_t); 174da14cebeSEric Cheng static void vnic_stats(show_vnic_state_t *, uint32_t); 1757c478bd9Sstevel@tonic-gate 176d62bc4baSyz147064 static int get_one_kstat(const char *, const char *, uint8_t, 177d62bc4baSyz147064 void *, boolean_t); 178ba2e4443Sseb static void get_mac_stats(const char *, pktsum_t *); 1797c478bd9Sstevel@tonic-gate static void get_link_stats(const char *, pktsum_t *); 180d62bc4baSyz147064 static uint64_t get_ifspeed(const char *, boolean_t); 181d62bc4baSyz147064 static const char *get_linkstate(const char *, boolean_t, char *); 182d62bc4baSyz147064 static const char *get_linkduplex(const char *, boolean_t, char *); 1837c478bd9Sstevel@tonic-gate 1844ac67f02SAnurag S. Maskey static int show_etherprop(dladm_handle_t, datalink_id_t, void *); 1854784fcbdSSowmini Varadhan static void show_ether_xprop(void *, dladm_ether_info_t *); 186e7801d59Ssowmini static boolean_t link_is_ether(const char *, datalink_id_t *); 187e7801d59Ssowmini 18833343a97Smeem static boolean_t str2int(const char *, int *); 18933343a97Smeem static void die(const char *, ...); 19033343a97Smeem static void die_optdup(int); 1918d5c46e6Sam223141 static void die_opterr(int, int, const char *); 19233343a97Smeem static void die_dlerr(dladm_status_t, const char *, ...); 19333343a97Smeem static void warn(const char *, ...); 19433343a97Smeem static void warn_dlerr(dladm_status_t, const char *, ...); 19533343a97Smeem 1967c478bd9Sstevel@tonic-gate typedef struct cmd { 1977c478bd9Sstevel@tonic-gate char *c_name; 1980ba2cbe9Sxc151355 cmdfunc_t *c_fn; 1998d5c46e6Sam223141 const char *c_usage; 2007c478bd9Sstevel@tonic-gate } cmd_t; 2017c478bd9Sstevel@tonic-gate 2027c478bd9Sstevel@tonic-gate static cmd_t cmds[] = { 2038d5c46e6Sam223141 { "rename-link", do_rename_link, 2040790b6dcSAnurag S. Maskey " rename-link <oldlink> <newlink>" }, 2050790b6dcSAnurag S. Maskey { "show-link", do_show_link, 2060790b6dcSAnurag S. Maskey " show-link [-pP] [-o <field>,..] [-s [-i <interval>]] " 2070790b6dcSAnurag S. Maskey "[<link>]\n" }, 2088d5c46e6Sam223141 { "create-aggr", do_create_aggr, 2090790b6dcSAnurag S. Maskey " create-aggr [-t] [-P <policy>] [-L <mode>] [-T <time>] " 2100790b6dcSAnurag S. Maskey "[-u <address>]\n" 2110790b6dcSAnurag S. Maskey "\t\t -l <link> [-l <link>...] <link>" }, 2128d5c46e6Sam223141 { "delete-aggr", do_delete_aggr, 2130790b6dcSAnurag S. Maskey " delete-aggr [-t] <link>" }, 2148d5c46e6Sam223141 { "add-aggr", do_add_aggr, 2150790b6dcSAnurag S. Maskey " add-aggr [-t] -l <link> [-l <link>...] <link>" }, 2168d5c46e6Sam223141 { "remove-aggr", do_remove_aggr, 2170790b6dcSAnurag S. Maskey " remove-aggr [-t] -l <link> [-l <link>...] <link>" }, 2188d5c46e6Sam223141 { "modify-aggr", do_modify_aggr, 2190790b6dcSAnurag S. Maskey " modify-aggr [-t] [-P <policy>] [-L <mode>] [-T <time>] " 2200790b6dcSAnurag S. Maskey "[-u <address>]\n" 2210790b6dcSAnurag S. Maskey "\t\t <link>" }, 2228d5c46e6Sam223141 { "show-aggr", do_show_aggr, 2230790b6dcSAnurag S. Maskey " show-aggr [-pPLx] [-o <field>,..] [-s [-i <interval>]] " 2248d5c46e6Sam223141 "[<link>]\n" }, 2258d5c46e6Sam223141 { "up-aggr", do_up_aggr, NULL }, 2268d5c46e6Sam223141 { "scan-wifi", do_scan_wifi, 2270790b6dcSAnurag S. Maskey " scan-wifi [-p] [-o <field>,...] [<link>]" }, 2288d5c46e6Sam223141 { "connect-wifi", do_connect_wifi, 2290790b6dcSAnurag S. Maskey " connect-wifi [-e <essid>] [-i <bssid>] [-k <key>,...] " 2308d5c46e6Sam223141 "[-s wep|wpa]\n" 2310790b6dcSAnurag S. Maskey "\t\t [-a open|shared] [-b bss|ibss] [-c] [-m a|b|g] " 2320790b6dcSAnurag S. Maskey "[-T <time>]\n" 2330790b6dcSAnurag S. Maskey "\t\t [<link>]" }, 2348d5c46e6Sam223141 { "disconnect-wifi", do_disconnect_wifi, 2350790b6dcSAnurag S. Maskey " disconnect-wifi [-a] [<link>]" }, 2368d5c46e6Sam223141 { "show-wifi", do_show_wifi, 2370790b6dcSAnurag S. Maskey " show-wifi [-p] [-o <field>,...] [<link>]\n" }, 2388d5c46e6Sam223141 { "set-linkprop", do_set_linkprop, 2390790b6dcSAnurag S. Maskey " set-linkprop [-t] -p <prop>=<value>[,...] <name>" }, 2408d5c46e6Sam223141 { "reset-linkprop", do_reset_linkprop, 2410790b6dcSAnurag S. Maskey " reset-linkprop [-t] [-p <prop>,...] <name>" }, 2420790b6dcSAnurag S. Maskey { "show-linkprop", do_show_linkprop, 2430790b6dcSAnurag S. Maskey " show-linkprop [-cP] [-o <field>,...] [-p <prop>,...] " 2440790b6dcSAnurag S. Maskey "<name>\n" }, 2458d5c46e6Sam223141 { "show-ether", do_show_ether, 2460790b6dcSAnurag S. Maskey " show-ether [-px][-o <field>,...] <link>\n" }, 2478d5c46e6Sam223141 { "create-secobj", do_create_secobj, 2480790b6dcSAnurag S. Maskey " create-secobj [-t] [-f <file>] -c <class> <secobj>" }, 2498d5c46e6Sam223141 { "delete-secobj", do_delete_secobj, 2500790b6dcSAnurag S. Maskey " delete-secobj [-t] <secobj>[,...]" }, 2518d5c46e6Sam223141 { "show-secobj", do_show_secobj, 2520790b6dcSAnurag S. Maskey " show-secobj [-pP] [-o <field>,...] [<secobj>,...]\n" }, 2538d5c46e6Sam223141 { "init-linkprop", do_init_linkprop, NULL }, 2548d5c46e6Sam223141 { "init-secobj", do_init_secobj, NULL }, 2558d5c46e6Sam223141 { "create-vlan", do_create_vlan, 2560790b6dcSAnurag S. Maskey " create-vlan [-ft] -l <link> -v <vid> [link]" }, 2578d5c46e6Sam223141 { "delete-vlan", do_delete_vlan, 2580790b6dcSAnurag S. Maskey " delete-vlan [-t] <link>" }, 2598d5c46e6Sam223141 { "show-vlan", do_show_vlan, 2600790b6dcSAnurag S. Maskey " show-vlan [-pP] [-o <field>,..] [<link>]\n" }, 2618d5c46e6Sam223141 { "up-vlan", do_up_vlan, NULL }, 2628d5c46e6Sam223141 { "delete-phys", do_delete_phys, 2630790b6dcSAnurag S. Maskey " delete-phys <link>" }, 2648d5c46e6Sam223141 { "show-phys", do_show_phys, 2650790b6dcSAnurag S. Maskey " show-phys [-pP] [-o <field>,..] [-H] [<link>]\n"}, 2668d5c46e6Sam223141 { "init-phys", do_init_phys, NULL }, 267da14cebeSEric Cheng { "show-linkmap", do_show_linkmap, NULL }, 268da14cebeSEric Cheng { "create-vnic", do_create_vnic, 2690790b6dcSAnurag S. Maskey " create-vnic [-t] -l <link> [-m <value> | auto |\n" 2700790b6dcSAnurag S. Maskey "\t\t {factory [-n <slot-id>]} | {random [-r <prefix>]}]\n" 2710790b6dcSAnurag S. Maskey "\t\t [-v <vid> [-f]] [-p <prop>=<value>[,...]] [-H] " 2720790b6dcSAnurag S. Maskey "<vnic-link>" }, 273da14cebeSEric Cheng { "delete-vnic", do_delete_vnic, 2740790b6dcSAnurag S. Maskey " delete-vnic [-t] <vnic-link>" }, 275da14cebeSEric Cheng { "show-vnic", do_show_vnic, 2760790b6dcSAnurag S. Maskey " show-vnic [-pP] [-l <link>] [-s [-i <interval>]] " 2770790b6dcSAnurag S. Maskey "[<link>]\n" }, 278da14cebeSEric Cheng { "up-vnic", do_up_vnic, NULL }, 279da14cebeSEric Cheng { "create-etherstub", do_create_etherstub, 2800790b6dcSAnurag S. Maskey " create-etherstub [-t] <link>" }, 281da14cebeSEric Cheng { "delete-etherstub", do_delete_etherstub, 2820790b6dcSAnurag S. Maskey " delete-etherstub [-t] <link>" }, 283da14cebeSEric Cheng { "show-etherstub", do_show_etherstub, 2840790b6dcSAnurag S. Maskey " show-etherstub [-t] [<link>]\n" }, 285da14cebeSEric Cheng { "show-usage", do_show_usage, 286ae6aa22aSVenugopal Iyer " show-usage [-a] [-d | -F <format>] " 2870790b6dcSAnurag S. Maskey "[-s <DD/MM/YYYY,HH:MM:SS>]\n" 2880790b6dcSAnurag S. Maskey "\t\t [-e <DD/MM/YYYY,HH:MM:SS>] -f <logfile> [<link>]" } 2897c478bd9Sstevel@tonic-gate }; 2907c478bd9Sstevel@tonic-gate 291d62bc4baSyz147064 static const struct option lopts[] = { 2927c478bd9Sstevel@tonic-gate {"vlan-id", required_argument, 0, 'v'}, 293e7801d59Ssowmini {"output", required_argument, 0, 'o'}, 2947c478bd9Sstevel@tonic-gate {"dev", required_argument, 0, 'd'}, 2957c478bd9Sstevel@tonic-gate {"policy", required_argument, 0, 'P'}, 296d62bc4baSyz147064 {"lacp-mode", required_argument, 0, 'L'}, 2977c478bd9Sstevel@tonic-gate {"lacp-timer", required_argument, 0, 'T'}, 2987c478bd9Sstevel@tonic-gate {"unicast", required_argument, 0, 'u'}, 299d62bc4baSyz147064 {"temporary", no_argument, 0, 't'}, 300d62bc4baSyz147064 {"root-dir", required_argument, 0, 'R'}, 301d62bc4baSyz147064 {"link", required_argument, 0, 'l'}, 302d62bc4baSyz147064 {"forcible", no_argument, 0, 'f'}, 303da14cebeSEric Cheng {"bw-limit", required_argument, 0, 'b'}, 304da14cebeSEric Cheng {"mac-address", required_argument, 0, 'm'}, 305da14cebeSEric Cheng {"slot", required_argument, 0, 'n'}, 306d62bc4baSyz147064 { 0, 0, 0, 0 } 307d62bc4baSyz147064 }; 308d62bc4baSyz147064 309d62bc4baSyz147064 static const struct option show_lopts[] = { 3107c478bd9Sstevel@tonic-gate {"statistics", no_argument, 0, 's'}, 311da14cebeSEric Cheng {"continuous", no_argument, 0, 'S'}, 3127c478bd9Sstevel@tonic-gate {"interval", required_argument, 0, 'i'}, 313*8002d411SSowmini Varadhan {"parsable", no_argument, 0, 'p'}, 3147c478bd9Sstevel@tonic-gate {"parseable", no_argument, 0, 'p'}, 315d62bc4baSyz147064 {"extended", no_argument, 0, 'x'}, 316e7801d59Ssowmini {"output", required_argument, 0, 'o'}, 317d62bc4baSyz147064 {"persistent", no_argument, 0, 'P'}, 318d62bc4baSyz147064 {"lacp", no_argument, 0, 'L'}, 3197c478bd9Sstevel@tonic-gate { 0, 0, 0, 0 } 3207c478bd9Sstevel@tonic-gate }; 3217c478bd9Sstevel@tonic-gate 3220ba2cbe9Sxc151355 static const struct option prop_longopts[] = { 3230ba2cbe9Sxc151355 {"temporary", no_argument, 0, 't' }, 324e7801d59Ssowmini {"output", required_argument, 0, 'o' }, 3250ba2cbe9Sxc151355 {"root-dir", required_argument, 0, 'R' }, 3260ba2cbe9Sxc151355 {"prop", required_argument, 0, 'p' }, 327*8002d411SSowmini Varadhan {"parsable", no_argument, 0, 'c' }, 3280ba2cbe9Sxc151355 {"parseable", no_argument, 0, 'c' }, 3290ba2cbe9Sxc151355 {"persistent", no_argument, 0, 'P' }, 3300ba2cbe9Sxc151355 { 0, 0, 0, 0 } 3310ba2cbe9Sxc151355 }; 3320ba2cbe9Sxc151355 3330ba2cbe9Sxc151355 static const struct option wifi_longopts[] = { 334*8002d411SSowmini Varadhan {"parsable", no_argument, 0, 'p' }, 3350ba2cbe9Sxc151355 {"parseable", no_argument, 0, 'p' }, 3360ba2cbe9Sxc151355 {"output", required_argument, 0, 'o' }, 3370ba2cbe9Sxc151355 {"essid", required_argument, 0, 'e' }, 3380ba2cbe9Sxc151355 {"bsstype", required_argument, 0, 'b' }, 3390ba2cbe9Sxc151355 {"mode", required_argument, 0, 'm' }, 3400ba2cbe9Sxc151355 {"key", required_argument, 0, 'k' }, 3410ba2cbe9Sxc151355 {"sec", required_argument, 0, 's' }, 3420ba2cbe9Sxc151355 {"auth", required_argument, 0, 'a' }, 3430ba2cbe9Sxc151355 {"create-ibss", required_argument, 0, 'c' }, 3440ba2cbe9Sxc151355 {"timeout", required_argument, 0, 'T' }, 3450ba2cbe9Sxc151355 {"all-links", no_argument, 0, 'a' }, 3460ba2cbe9Sxc151355 {"temporary", no_argument, 0, 't' }, 3470ba2cbe9Sxc151355 {"root-dir", required_argument, 0, 'R' }, 3480ba2cbe9Sxc151355 {"persistent", no_argument, 0, 'P' }, 3490ba2cbe9Sxc151355 {"file", required_argument, 0, 'f' }, 3500ba2cbe9Sxc151355 { 0, 0, 0, 0 } 3510ba2cbe9Sxc151355 }; 352e7801d59Ssowmini static const struct option showeth_lopts[] = { 353*8002d411SSowmini Varadhan {"parsable", no_argument, 0, 'p' }, 354e7801d59Ssowmini {"parseable", no_argument, 0, 'p' }, 355e7801d59Ssowmini {"extended", no_argument, 0, 'x' }, 356e7801d59Ssowmini {"output", required_argument, 0, 'o' }, 357e7801d59Ssowmini { 0, 0, 0, 0 } 358e7801d59Ssowmini }; 359e7801d59Ssowmini 360da14cebeSEric Cheng static const struct option vnic_lopts[] = { 361da14cebeSEric Cheng {"temporary", no_argument, 0, 't' }, 362da14cebeSEric Cheng {"root-dir", required_argument, 0, 'R' }, 363da14cebeSEric Cheng {"dev", required_argument, 0, 'd' }, 364da14cebeSEric Cheng {"mac-address", required_argument, 0, 'm' }, 365da14cebeSEric Cheng {"cpus", required_argument, 0, 'c' }, 366da14cebeSEric Cheng {"bw-limit", required_argument, 0, 'b' }, 367da14cebeSEric Cheng {"slot", required_argument, 0, 'n' }, 368da14cebeSEric Cheng {"mac-prefix", required_argument, 0, 'r' }, 369da14cebeSEric Cheng { 0, 0, 0, 0 } 370da14cebeSEric Cheng }; 371da14cebeSEric Cheng 372da14cebeSEric Cheng static const struct option etherstub_lopts[] = { 373da14cebeSEric Cheng {"temporary", no_argument, 0, 't' }, 374da14cebeSEric Cheng {"root-dir", required_argument, 0, 'R' }, 375da14cebeSEric Cheng { 0, 0, 0, 0 } 376da14cebeSEric Cheng }; 377da14cebeSEric Cheng 378ae6aa22aSVenugopal Iyer static const struct option usage_opts[] = { 379ae6aa22aSVenugopal Iyer {"file", required_argument, 0, 'f' }, 380ae6aa22aSVenugopal Iyer {"format", required_argument, 0, 'F' }, 381ae6aa22aSVenugopal Iyer {"start", required_argument, 0, 's' }, 382ae6aa22aSVenugopal Iyer {"stop", required_argument, 0, 'e' }, 383ae6aa22aSVenugopal Iyer { 0, 0, 0, 0 } 384ae6aa22aSVenugopal Iyer }; 385ae6aa22aSVenugopal Iyer 386e7801d59Ssowmini /* 387e7801d59Ssowmini * structures for 'dladm show-ether' 388e7801d59Ssowmini */ 3894784fcbdSSowmini Varadhan static const char *ptype[] = {LEI_ATTR_NAMES}; 3904784fcbdSSowmini Varadhan 391e7801d59Ssowmini typedef struct ether_fields_buf_s 392e7801d59Ssowmini { 393e7801d59Ssowmini char eth_link[15]; 394e7801d59Ssowmini char eth_ptype[8]; 395e7801d59Ssowmini char eth_state[8]; 396e7801d59Ssowmini char eth_autoneg[5]; 397e7801d59Ssowmini char eth_spdx[31]; 398e7801d59Ssowmini char eth_pause[6]; 399e7801d59Ssowmini char eth_rem_fault[16]; 400e7801d59Ssowmini } ether_fields_buf_t; 401e7801d59Ssowmini 402*8002d411SSowmini Varadhan static ofmt_field_t ether_fields[] = { 403*8002d411SSowmini Varadhan /* name, field width, offset callback */ 404*8002d411SSowmini Varadhan { "LINK", 16, 405*8002d411SSowmini Varadhan offsetof(ether_fields_buf_t, eth_link), print_default_cb}, 406*8002d411SSowmini Varadhan { "PTYPE", 9, 407*8002d411SSowmini Varadhan offsetof(ether_fields_buf_t, eth_ptype), print_default_cb}, 408*8002d411SSowmini Varadhan { "STATE", 9, 409*8002d411SSowmini Varadhan offsetof(ether_fields_buf_t, eth_state), 410*8002d411SSowmini Varadhan print_default_cb}, 411*8002d411SSowmini Varadhan { "AUTO", 6, 412*8002d411SSowmini Varadhan offsetof(ether_fields_buf_t, eth_autoneg), print_default_cb}, 413*8002d411SSowmini Varadhan { "SPEED-DUPLEX", 32, 414*8002d411SSowmini Varadhan offsetof(ether_fields_buf_t, eth_spdx), print_default_cb}, 415*8002d411SSowmini Varadhan { "PAUSE", 7, 416*8002d411SSowmini Varadhan offsetof(ether_fields_buf_t, eth_pause), print_default_cb}, 417*8002d411SSowmini Varadhan { "REM_FAULT", 17, 418*8002d411SSowmini Varadhan offsetof(ether_fields_buf_t, eth_rem_fault), print_default_cb}, 419*8002d411SSowmini Varadhan {NULL, 0, 420*8002d411SSowmini Varadhan 0, NULL}} 421e7801d59Ssowmini ; 422e7801d59Ssowmini 423e7801d59Ssowmini typedef struct print_ether_state { 424e7801d59Ssowmini const char *es_link; 425*8002d411SSowmini Varadhan boolean_t es_parsable; 426e7801d59Ssowmini boolean_t es_header; 427e7801d59Ssowmini boolean_t es_extended; 428*8002d411SSowmini Varadhan ofmt_handle_t es_ofmt; 429e7801d59Ssowmini } print_ether_state_t; 430e7801d59Ssowmini 431e7801d59Ssowmini /* 432da14cebeSEric Cheng * structures for 'dladm show-link -s' (print statistics) 433e7801d59Ssowmini */ 434e7801d59Ssowmini typedef enum { 435ae6aa22aSVenugopal Iyer LINK_S_LINK, 436ae6aa22aSVenugopal Iyer LINK_S_IPKTS, 437ae6aa22aSVenugopal Iyer LINK_S_RBYTES, 438ae6aa22aSVenugopal Iyer LINK_S_IERRORS, 439ae6aa22aSVenugopal Iyer LINK_S_OPKTS, 440ae6aa22aSVenugopal Iyer LINK_S_OBYTES, 441ae6aa22aSVenugopal Iyer LINK_S_OERRORS 442ae6aa22aSVenugopal Iyer } link_s_field_index_t; 443e7801d59Ssowmini 444*8002d411SSowmini Varadhan static ofmt_field_t link_s_fields[] = { 445*8002d411SSowmini Varadhan /* name, field width, index, callback */ 446*8002d411SSowmini Varadhan { "LINK", 15, LINK_S_LINK, print_link_stats_cb}, 447*8002d411SSowmini Varadhan { "IPACKETS", 10, LINK_S_IPKTS, print_link_stats_cb}, 448*8002d411SSowmini Varadhan { "RBYTES", 8, LINK_S_RBYTES, print_link_stats_cb}, 449*8002d411SSowmini Varadhan { "IERRORS", 10, LINK_S_IERRORS, print_link_stats_cb}, 450*8002d411SSowmini Varadhan { "OPACKETS", 12, LINK_S_OPKTS, print_link_stats_cb}, 451*8002d411SSowmini Varadhan { "OBYTES", 12, LINK_S_OBYTES, print_link_stats_cb}, 452*8002d411SSowmini Varadhan { "OERRORS", 8, LINK_S_OERRORS, print_link_stats_cb}} 453e7801d59Ssowmini ; 454ae6aa22aSVenugopal Iyer 455ae6aa22aSVenugopal Iyer typedef struct link_args_s { 456ae6aa22aSVenugopal Iyer char *link_s_link; 457ae6aa22aSVenugopal Iyer pktsum_t *link_s_psum; 458ae6aa22aSVenugopal Iyer } link_args_t; 459e7801d59Ssowmini 460e7801d59Ssowmini /* 461e7801d59Ssowmini * buffer used by print functions for show-{link,phys,vlan} commands. 462e7801d59Ssowmini */ 463e7801d59Ssowmini typedef struct link_fields_buf_s { 464e7801d59Ssowmini char link_name[MAXLINKNAMELEN]; 465e7801d59Ssowmini char link_class[DLADM_STRSIZE]; 466c08e5e1aSdr146992 char link_mtu[11]; 467e7801d59Ssowmini char link_state[DLADM_STRSIZE]; 468e7801d59Ssowmini char link_over[MAXLINKNAMELEN]; 4694045d941Ssowmini char link_phys_state[DLADM_STRSIZE]; 470e7801d59Ssowmini char link_phys_media[DLADM_STRSIZE]; 471e7801d59Ssowmini char link_phys_speed[DLADM_STRSIZE]; 472e7801d59Ssowmini char link_phys_duplex[DLPI_LINKNAME_MAX]; 473e7801d59Ssowmini char link_phys_device[DLPI_LINKNAME_MAX]; 474e7801d59Ssowmini char link_flags[6]; 475e7801d59Ssowmini char link_vlan_vid[6]; 476e7801d59Ssowmini } link_fields_buf_t; 477e7801d59Ssowmini 478e7801d59Ssowmini /* 479e7801d59Ssowmini * structures for 'dladm show-link' 480e7801d59Ssowmini */ 481*8002d411SSowmini Varadhan static ofmt_field_t link_fields[] = { 482*8002d411SSowmini Varadhan /* name, field width, index, callback */ 483*8002d411SSowmini Varadhan { "LINK", 12, 484*8002d411SSowmini Varadhan offsetof(link_fields_buf_t, link_name), print_default_cb}, 485*8002d411SSowmini Varadhan { "CLASS", 9, 486*8002d411SSowmini Varadhan offsetof(link_fields_buf_t, link_class), print_default_cb}, 487*8002d411SSowmini Varadhan { "MTU", 7, 488*8002d411SSowmini Varadhan offsetof(link_fields_buf_t, link_mtu), print_default_cb}, 489*8002d411SSowmini Varadhan { "STATE", 9, 490*8002d411SSowmini Varadhan offsetof(link_fields_buf_t, link_state), print_default_cb}, 491*8002d411SSowmini Varadhan { "OVER", DLPI_LINKNAME_MAX, 492*8002d411SSowmini Varadhan offsetof(link_fields_buf_t, link_over), print_default_cb}, 493*8002d411SSowmini Varadhan { NULL, 0, 0, NULL}} 494e7801d59Ssowmini ; 495e7801d59Ssowmini 496e7801d59Ssowmini /* 497e7801d59Ssowmini * structures for 'dladm show-aggr' 498e7801d59Ssowmini */ 499e7801d59Ssowmini typedef struct laggr_fields_buf_s { 500e7801d59Ssowmini char laggr_name[DLPI_LINKNAME_MAX]; 501e7801d59Ssowmini char laggr_policy[9]; 502e7801d59Ssowmini char laggr_addrpolicy[ETHERADDRL * 3 + 3]; 503e7801d59Ssowmini char laggr_lacpactivity[14]; 504e7801d59Ssowmini char laggr_lacptimer[DLADM_STRSIZE]; 505e7801d59Ssowmini char laggr_flags[7]; 506e7801d59Ssowmini } laggr_fields_buf_t; 507e7801d59Ssowmini 508e7801d59Ssowmini typedef struct laggr_args_s { 509e7801d59Ssowmini int laggr_lport; /* -1 indicates the aggr itself */ 510e7801d59Ssowmini const char *laggr_link; 511e7801d59Ssowmini dladm_aggr_grp_attr_t *laggr_ginfop; 512e7801d59Ssowmini dladm_status_t *laggr_status; 513e7801d59Ssowmini pktsum_t *laggr_pktsumtot; /* -s only */ 514e7801d59Ssowmini pktsum_t *laggr_prevstats; /* -s only */ 515*8002d411SSowmini Varadhan boolean_t laggr_parsable; 516e7801d59Ssowmini } laggr_args_t; 517e7801d59Ssowmini 518*8002d411SSowmini Varadhan static ofmt_field_t laggr_fields[] = { 519*8002d411SSowmini Varadhan /* name, field width, offset, callback */ 520*8002d411SSowmini Varadhan { "LINK", 16, 521*8002d411SSowmini Varadhan offsetof(laggr_fields_buf_t, laggr_name), print_default_cb}, 522*8002d411SSowmini Varadhan { "POLICY", 9, 523*8002d411SSowmini Varadhan offsetof(laggr_fields_buf_t, laggr_policy), print_default_cb}, 524*8002d411SSowmini Varadhan { "ADDRPOLICY", ETHERADDRL * 3 + 3, 525*8002d411SSowmini Varadhan offsetof(laggr_fields_buf_t, laggr_addrpolicy), print_default_cb}, 526*8002d411SSowmini Varadhan { "LACPACTIVITY", 14, 527*8002d411SSowmini Varadhan offsetof(laggr_fields_buf_t, laggr_lacpactivity), print_default_cb}, 528*8002d411SSowmini Varadhan { "LACPTIMER", 12, 529*8002d411SSowmini Varadhan offsetof(laggr_fields_buf_t, laggr_lacptimer), print_default_cb}, 530*8002d411SSowmini Varadhan { "FLAGS", 8, 531*8002d411SSowmini Varadhan offsetof(laggr_fields_buf_t, laggr_flags), print_default_cb}, 532*8002d411SSowmini Varadhan { NULL, 0, 0, NULL}} 533e7801d59Ssowmini ; 534e7801d59Ssowmini 535e7801d59Ssowmini /* 536e7801d59Ssowmini * structures for 'dladm show-aggr -x'. 537e7801d59Ssowmini */ 538e7801d59Ssowmini typedef enum { 539e7801d59Ssowmini AGGR_X_LINK, 540e7801d59Ssowmini AGGR_X_PORT, 541e7801d59Ssowmini AGGR_X_SPEED, 542e7801d59Ssowmini AGGR_X_DUPLEX, 543e7801d59Ssowmini AGGR_X_STATE, 544e7801d59Ssowmini AGGR_X_ADDRESS, 545e7801d59Ssowmini AGGR_X_PORTSTATE 546e7801d59Ssowmini } aggr_x_field_index_t; 547e7801d59Ssowmini 548*8002d411SSowmini Varadhan static ofmt_field_t aggr_x_fields[] = { 549*8002d411SSowmini Varadhan /* name, field width, index callback */ 550*8002d411SSowmini Varadhan { "LINK", 12, AGGR_X_LINK, print_xaggr_cb}, 551*8002d411SSowmini Varadhan { "PORT", 15, AGGR_X_PORT, print_xaggr_cb}, 552*8002d411SSowmini Varadhan { "SPEED", 5, AGGR_X_SPEED, print_xaggr_cb}, 553*8002d411SSowmini Varadhan { "DUPLEX", 10, AGGR_X_DUPLEX, print_xaggr_cb}, 554*8002d411SSowmini Varadhan { "STATE", 10, AGGR_X_STATE, print_xaggr_cb}, 555*8002d411SSowmini Varadhan { "ADDRESS", 19, AGGR_X_ADDRESS, print_xaggr_cb}, 556*8002d411SSowmini Varadhan { "PORTSTATE", 16, AGGR_X_PORTSTATE, print_xaggr_cb}, 557*8002d411SSowmini Varadhan { NULL, 0, 0, NULL}} 558e7801d59Ssowmini ; 559e7801d59Ssowmini 560e7801d59Ssowmini /* 561e7801d59Ssowmini * structures for 'dladm show-aggr -s'. 562e7801d59Ssowmini */ 563e7801d59Ssowmini typedef enum { 564e7801d59Ssowmini AGGR_S_LINK, 565e7801d59Ssowmini AGGR_S_PORT, 566e7801d59Ssowmini AGGR_S_IPKTS, 567e7801d59Ssowmini AGGR_S_RBYTES, 568e7801d59Ssowmini AGGR_S_OPKTS, 569e7801d59Ssowmini AGGR_S_OBYTES, 570e7801d59Ssowmini AGGR_S_IPKTDIST, 571e7801d59Ssowmini AGGR_S_OPKTDIST 572e7801d59Ssowmini } aggr_s_field_index_t; 573e7801d59Ssowmini 574*8002d411SSowmini Varadhan static ofmt_field_t aggr_s_fields[] = { 575*8002d411SSowmini Varadhan { "LINK", 12, AGGR_S_LINK, print_aggr_stats_cb}, 576*8002d411SSowmini Varadhan { "PORT", 10, AGGR_S_PORT, print_aggr_stats_cb}, 577*8002d411SSowmini Varadhan { "IPACKETS", 8, AGGR_S_IPKTS, print_aggr_stats_cb}, 578*8002d411SSowmini Varadhan { "RBYTES", 8, AGGR_S_RBYTES, print_aggr_stats_cb}, 579*8002d411SSowmini Varadhan { "OPACKETS", 8, AGGR_S_OPKTS, print_aggr_stats_cb}, 580*8002d411SSowmini Varadhan { "OBYTES", 8, AGGR_S_OBYTES, print_aggr_stats_cb}, 581*8002d411SSowmini Varadhan { "IPKTDIST", 9, AGGR_S_IPKTDIST, print_aggr_stats_cb}, 582*8002d411SSowmini Varadhan { "OPKTDIST", 15, AGGR_S_OPKTDIST, print_aggr_stats_cb}, 583*8002d411SSowmini Varadhan { NULL, 0, 0, NULL}} 584e7801d59Ssowmini ; 585e7801d59Ssowmini 586e7801d59Ssowmini /* 587da14cebeSEric Cheng * structures for 'dladm show-aggr -L'. 588e7801d59Ssowmini */ 589e7801d59Ssowmini typedef enum { 590e7801d59Ssowmini AGGR_L_LINK, 591e7801d59Ssowmini AGGR_L_PORT, 592e7801d59Ssowmini AGGR_L_AGGREGATABLE, 593e7801d59Ssowmini AGGR_L_SYNC, 594e7801d59Ssowmini AGGR_L_COLL, 595e7801d59Ssowmini AGGR_L_DIST, 596e7801d59Ssowmini AGGR_L_DEFAULTED, 597e7801d59Ssowmini AGGR_L_EXPIRED 598e7801d59Ssowmini } aggr_l_field_index_t; 599e7801d59Ssowmini 600*8002d411SSowmini Varadhan static ofmt_field_t aggr_l_fields[] = { 601*8002d411SSowmini Varadhan /* name, field width, index */ 602*8002d411SSowmini Varadhan { "LINK", 12, AGGR_L_LINK, print_lacp_cb}, 603*8002d411SSowmini Varadhan { "PORT", 13, AGGR_L_PORT, print_lacp_cb}, 604*8002d411SSowmini Varadhan { "AGGREGATABLE", 13, AGGR_L_AGGREGATABLE, print_lacp_cb}, 605*8002d411SSowmini Varadhan { "SYNC", 5, AGGR_L_SYNC, print_lacp_cb}, 606*8002d411SSowmini Varadhan { "COLL", 5, AGGR_L_COLL, print_lacp_cb}, 607*8002d411SSowmini Varadhan { "DIST", 5, AGGR_L_DIST, print_lacp_cb}, 608*8002d411SSowmini Varadhan { "DEFAULTED", 10, AGGR_L_DEFAULTED, print_lacp_cb}, 609*8002d411SSowmini Varadhan { "EXPIRED", 15, AGGR_L_EXPIRED, print_lacp_cb}, 610*8002d411SSowmini Varadhan { NULL, 0, 0, NULL}} 611e7801d59Ssowmini ; 612e7801d59Ssowmini 613e7801d59Ssowmini /* 614e7801d59Ssowmini * structures for 'dladm show-phys' 615e7801d59Ssowmini */ 616e7801d59Ssowmini 617*8002d411SSowmini Varadhan static ofmt_field_t phys_fields[] = { 618*8002d411SSowmini Varadhan /* name, field width, offset */ 619*8002d411SSowmini Varadhan { "LINK", 13, 620*8002d411SSowmini Varadhan offsetof(link_fields_buf_t, link_name), print_default_cb}, 621*8002d411SSowmini Varadhan { "MEDIA", 21, 622*8002d411SSowmini Varadhan offsetof(link_fields_buf_t, link_phys_media), print_default_cb}, 623*8002d411SSowmini Varadhan { "STATE", 11, 624*8002d411SSowmini Varadhan offsetof(link_fields_buf_t, link_phys_state), print_default_cb}, 625*8002d411SSowmini Varadhan { "SPEED", 7, 626*8002d411SSowmini Varadhan offsetof(link_fields_buf_t, link_phys_speed), print_default_cb}, 627*8002d411SSowmini Varadhan { "DUPLEX", 10, 628*8002d411SSowmini Varadhan offsetof(link_fields_buf_t, link_phys_duplex), print_default_cb}, 629*8002d411SSowmini Varadhan { "DEVICE", 13, 630*8002d411SSowmini Varadhan offsetof(link_fields_buf_t, link_phys_device), print_default_cb}, 631*8002d411SSowmini Varadhan { "FLAGS", 7, 632*8002d411SSowmini Varadhan offsetof(link_fields_buf_t, link_flags), print_default_cb}, 633*8002d411SSowmini Varadhan { NULL, 0, NULL, 0}} 634e7801d59Ssowmini ; 635e7801d59Ssowmini 636e7801d59Ssowmini /* 637da14cebeSEric Cheng * structures for 'dladm show-phys -m' 638da14cebeSEric Cheng */ 639da14cebeSEric Cheng 640da14cebeSEric Cheng typedef enum { 641da14cebeSEric Cheng PHYS_M_LINK, 642da14cebeSEric Cheng PHYS_M_SLOT, 643da14cebeSEric Cheng PHYS_M_ADDRESS, 644da14cebeSEric Cheng PHYS_M_INUSE, 645da14cebeSEric Cheng PHYS_M_CLIENT 646da14cebeSEric Cheng } phys_m_field_index_t; 647da14cebeSEric Cheng 648*8002d411SSowmini Varadhan static ofmt_field_t phys_m_fields[] = { 649*8002d411SSowmini Varadhan /* name, field width, offset */ 650*8002d411SSowmini Varadhan { "LINK", 13, PHYS_M_LINK, print_phys_one_mac_cb}, 651*8002d411SSowmini Varadhan { "SLOT", 9, PHYS_M_SLOT, print_phys_one_mac_cb}, 652*8002d411SSowmini Varadhan { "ADDRESS", 19, PHYS_M_ADDRESS, print_phys_one_mac_cb}, 653*8002d411SSowmini Varadhan { "INUSE", 5, PHYS_M_INUSE, print_phys_one_mac_cb}, 654*8002d411SSowmini Varadhan { "CLIENT", 13, PHYS_M_CLIENT, print_phys_one_mac_cb}, 655*8002d411SSowmini Varadhan { NULL, 0, 0, NULL}} 656da14cebeSEric Cheng ; 657da14cebeSEric Cheng 658da14cebeSEric Cheng /* 659da14cebeSEric Cheng * structures for 'dladm show-phys -H' 660da14cebeSEric Cheng */ 661da14cebeSEric Cheng 662da14cebeSEric Cheng typedef enum { 663da14cebeSEric Cheng PHYS_H_LINK, 664da14cebeSEric Cheng PHYS_H_GROUP, 665da14cebeSEric Cheng PHYS_H_GRPTYPE, 666da14cebeSEric Cheng PHYS_H_RINGS, 667da14cebeSEric Cheng PHYS_H_CLIENTS 668da14cebeSEric Cheng } phys_h_field_index_t; 669da14cebeSEric Cheng 670*8002d411SSowmini Varadhan static ofmt_field_t phys_h_fields[] = { 671*8002d411SSowmini Varadhan { "LINK", 13, PHYS_H_LINK, print_phys_one_hwgrp_cb}, 672*8002d411SSowmini Varadhan { "GROUP", 9, PHYS_H_GROUP, print_phys_one_hwgrp_cb}, 673*8002d411SSowmini Varadhan { "GROUPTYPE", 7, PHYS_H_GRPTYPE, print_phys_one_hwgrp_cb}, 674*8002d411SSowmini Varadhan { "RINGS", 17, PHYS_H_RINGS, print_phys_one_hwgrp_cb}, 675*8002d411SSowmini Varadhan { "CLIENTS", 21, PHYS_H_CLIENTS, print_phys_one_hwgrp_cb}, 676*8002d411SSowmini Varadhan { NULL, 0, 0, NULL}} 677da14cebeSEric Cheng ; 678da14cebeSEric Cheng 679da14cebeSEric Cheng /* 680e7801d59Ssowmini * structures for 'dladm show-vlan' 681e7801d59Ssowmini */ 682*8002d411SSowmini Varadhan static ofmt_field_t vlan_fields[] = { 683*8002d411SSowmini Varadhan { "LINK", 16, 684*8002d411SSowmini Varadhan offsetof(link_fields_buf_t, link_name), print_default_cb}, 685*8002d411SSowmini Varadhan { "VID", 9, 686*8002d411SSowmini Varadhan offsetof(link_fields_buf_t, link_vlan_vid), print_default_cb}, 687*8002d411SSowmini Varadhan { "OVER", 13, 688*8002d411SSowmini Varadhan offsetof(link_fields_buf_t, link_over), print_default_cb}, 689*8002d411SSowmini Varadhan { "FLAGS", 7, 690*8002d411SSowmini Varadhan offsetof(link_fields_buf_t, link_flags), print_default_cb}, 691*8002d411SSowmini Varadhan { NULL, 0, 0, NULL}} 692e7801d59Ssowmini ; 693da14cebeSEric Cheng 694e7801d59Ssowmini /* 695*8002d411SSowmini Varadhan * structures common to 'dladm scan-wifi' and 'dladm show-wifi' 696*8002d411SSowmini Varadhan * callback will be determined in parse_wifi_fields. 697e7801d59Ssowmini */ 698*8002d411SSowmini Varadhan static ofmt_field_t wifi_common_fields[] = { 699*8002d411SSowmini Varadhan { "LINK", 11, 0, NULL}, 700*8002d411SSowmini Varadhan { "ESSID", 20, DLADM_WLAN_ATTR_ESSID, NULL}, 701*8002d411SSowmini Varadhan { "BSSID", 18, DLADM_WLAN_ATTR_BSSID, NULL}, 702*8002d411SSowmini Varadhan { "IBSSID", 18, DLADM_WLAN_ATTR_BSSID, NULL}, 703*8002d411SSowmini Varadhan { "MODE", 7, DLADM_WLAN_ATTR_MODE, NULL}, 704*8002d411SSowmini Varadhan { "SPEED", 7, DLADM_WLAN_ATTR_SPEED, NULL}, 705*8002d411SSowmini Varadhan { "BSSTYPE", 9, DLADM_WLAN_ATTR_BSSTYPE, NULL}, 706*8002d411SSowmini Varadhan { "SEC", 7, DLADM_WLAN_ATTR_SECMODE, NULL}, 707*8002d411SSowmini Varadhan { "STRENGTH", 11, DLADM_WLAN_ATTR_STRENGTH, NULL}, 708*8002d411SSowmini Varadhan { NULL, 0, 0, NULL}}; 709*8002d411SSowmini Varadhan 710*8002d411SSowmini Varadhan /* 711*8002d411SSowmini Varadhan * the 'show-wifi' command supports all the fields in wifi_common_fields 712*8002d411SSowmini Varadhan * plus the AUTH and STATUS fields. 713*8002d411SSowmini Varadhan */ 714*8002d411SSowmini Varadhan static ofmt_field_t wifi_show_fields[A_CNT(wifi_common_fields) + 2] = { 715*8002d411SSowmini Varadhan { "AUTH", 9, DLADM_WLAN_ATTR_AUTH, NULL}, 716*8002d411SSowmini Varadhan { "STATUS", 18, DLADM_WLAN_LINKATTR_STATUS, print_wifi_status_cb}, 717*8002d411SSowmini Varadhan /* copy wifi_common_fields here */ 718*8002d411SSowmini Varadhan }; 719e7801d59Ssowmini 720e7801d59Ssowmini static char *all_scan_wifi_fields = 721e7801d59Ssowmini "link,essid,bssid,sec,strength,mode,speed,bsstype"; 722e7801d59Ssowmini static char *all_show_wifi_fields = 723e7801d59Ssowmini "link,status,essid,sec,strength,mode,speed,auth,bssid,bsstype"; 724e7801d59Ssowmini static char *def_scan_wifi_fields = 725e7801d59Ssowmini "link,essid,bssid,sec,strength,mode,speed"; 726e7801d59Ssowmini static char *def_show_wifi_fields = 727e7801d59Ssowmini "link,status,essid,sec,strength,mode,speed"; 728e7801d59Ssowmini 729e7801d59Ssowmini /* 730e7801d59Ssowmini * structures for 'dladm show-linkprop' 731e7801d59Ssowmini */ 732e7801d59Ssowmini typedef enum { 733e7801d59Ssowmini LINKPROP_LINK, 734e7801d59Ssowmini LINKPROP_PROPERTY, 735afdda45fSVasumathi Sundaram - Sun Microsystems LINKPROP_PERM, 736e7801d59Ssowmini LINKPROP_VALUE, 737e7801d59Ssowmini LINKPROP_DEFAULT, 738e7801d59Ssowmini LINKPROP_POSSIBLE 739e7801d59Ssowmini } linkprop_field_index_t; 740e7801d59Ssowmini 741*8002d411SSowmini Varadhan static ofmt_field_t linkprop_fields[] = { 742*8002d411SSowmini Varadhan /* name, field width, index */ 743*8002d411SSowmini Varadhan { "LINK", 13, LINKPROP_LINK, print_linkprop_cb}, 744*8002d411SSowmini Varadhan { "PROPERTY", 16, LINKPROP_PROPERTY, print_linkprop_cb}, 745*8002d411SSowmini Varadhan { "PERM", 5, LINKPROP_PERM, print_linkprop_cb}, 746*8002d411SSowmini Varadhan { "VALUE", 15, LINKPROP_VALUE, print_linkprop_cb}, 747*8002d411SSowmini Varadhan { "DEFAULT", 15, LINKPROP_DEFAULT, print_linkprop_cb}, 748*8002d411SSowmini Varadhan { "POSSIBLE", 21, LINKPROP_POSSIBLE, print_linkprop_cb}, 749*8002d411SSowmini Varadhan { NULL, 0, 0, NULL}} 750e7801d59Ssowmini ; 751e7801d59Ssowmini 752e7801d59Ssowmini #define MAX_PROP_LINE 512 753e7801d59Ssowmini 754e7801d59Ssowmini typedef struct show_linkprop_state { 755e7801d59Ssowmini char ls_link[MAXLINKNAMELEN]; 756e7801d59Ssowmini char *ls_line; 757e7801d59Ssowmini char **ls_propvals; 758da14cebeSEric Cheng dladm_arg_list_t *ls_proplist; 759*8002d411SSowmini Varadhan boolean_t ls_parsable; 760e7801d59Ssowmini boolean_t ls_persist; 761e7801d59Ssowmini boolean_t ls_header; 762e7801d59Ssowmini dladm_status_t ls_status; 763e7801d59Ssowmini dladm_status_t ls_retstatus; 764*8002d411SSowmini Varadhan ofmt_handle_t ls_ofmt; 765e7801d59Ssowmini } show_linkprop_state_t; 766e7801d59Ssowmini 767da14cebeSEric Cheng typedef struct set_linkprop_state { 768da14cebeSEric Cheng const char *ls_name; 769da14cebeSEric Cheng boolean_t ls_reset; 770da14cebeSEric Cheng boolean_t ls_temp; 771da14cebeSEric Cheng dladm_status_t ls_status; 772da14cebeSEric Cheng } set_linkprop_state_t; 773da14cebeSEric Cheng 774e7801d59Ssowmini typedef struct linkprop_args_s { 775e7801d59Ssowmini show_linkprop_state_t *ls_state; 776e7801d59Ssowmini char *ls_propname; 777e7801d59Ssowmini datalink_id_t ls_linkid; 778e7801d59Ssowmini } linkprop_args_t; 779e7801d59Ssowmini 780e7801d59Ssowmini /* 781e7801d59Ssowmini * structures for 'dladm show-secobj' 782e7801d59Ssowmini */ 783e7801d59Ssowmini typedef struct secobj_fields_buf_s { 784e7801d59Ssowmini char ss_obj_name[DLADM_SECOBJ_VAL_MAX]; 785e7801d59Ssowmini char ss_class[20]; 786e7801d59Ssowmini char ss_val[30]; 787e7801d59Ssowmini } secobj_fields_buf_t; 788*8002d411SSowmini Varadhan 789*8002d411SSowmini Varadhan static ofmt_field_t secobj_fields[] = { 790*8002d411SSowmini Varadhan { "OBJECT", 21, 791*8002d411SSowmini Varadhan offsetof(secobj_fields_buf_t, ss_obj_name), print_default_cb}, 792*8002d411SSowmini Varadhan { "CLASS", 21, 793*8002d411SSowmini Varadhan offsetof(secobj_fields_buf_t, ss_class), print_default_cb}, 794*8002d411SSowmini Varadhan { "VALUE", 31, 795*8002d411SSowmini Varadhan offsetof(secobj_fields_buf_t, ss_val), print_default_cb}, 796*8002d411SSowmini Varadhan { NULL, 0, 0, NULL}} 797e7801d59Ssowmini ; 7980ba2cbe9Sxc151355 799da14cebeSEric Cheng /* 800da14cebeSEric Cheng * structures for 'dladm show-vnic' 801da14cebeSEric Cheng */ 802da14cebeSEric Cheng typedef struct vnic_fields_buf_s 803da14cebeSEric Cheng { 804da14cebeSEric Cheng char vnic_link[DLPI_LINKNAME_MAX]; 805da14cebeSEric Cheng char vnic_over[DLPI_LINKNAME_MAX]; 806da14cebeSEric Cheng char vnic_speed[6]; 807da14cebeSEric Cheng char vnic_macaddr[19]; 808da14cebeSEric Cheng char vnic_macaddrtype[19]; 809da14cebeSEric Cheng char vnic_vid[6]; 810da14cebeSEric Cheng } vnic_fields_buf_t; 811da14cebeSEric Cheng 812*8002d411SSowmini Varadhan static ofmt_field_t vnic_fields[] = { 813*8002d411SSowmini Varadhan { "LINK", 13, 814*8002d411SSowmini Varadhan offsetof(vnic_fields_buf_t, vnic_link), print_default_cb}, 815*8002d411SSowmini Varadhan { "OVER", 13, 816*8002d411SSowmini Varadhan offsetof(vnic_fields_buf_t, vnic_over), print_default_cb}, 817*8002d411SSowmini Varadhan { "SPEED", 7, 818*8002d411SSowmini Varadhan offsetof(vnic_fields_buf_t, vnic_speed), print_default_cb}, 819*8002d411SSowmini Varadhan { "MACADDRESS", 21, 820*8002d411SSowmini Varadhan offsetof(vnic_fields_buf_t, vnic_macaddr), print_default_cb}, 821*8002d411SSowmini Varadhan { "MACADDRTYPE", 20, 822*8002d411SSowmini Varadhan offsetof(vnic_fields_buf_t, vnic_macaddrtype), print_default_cb}, 823*8002d411SSowmini Varadhan { "VID", 7, 824*8002d411SSowmini Varadhan offsetof(vnic_fields_buf_t, vnic_vid), print_default_cb}, 825*8002d411SSowmini Varadhan { NULL, 0, 0, NULL}} 826da14cebeSEric Cheng ; 827da14cebeSEric Cheng 828da14cebeSEric Cheng /* 829da14cebeSEric Cheng * structures for 'dladm show-usage' 830da14cebeSEric Cheng */ 831da14cebeSEric Cheng 832da14cebeSEric Cheng typedef struct usage_fields_buf_s { 833da14cebeSEric Cheng char usage_link[12]; 834da14cebeSEric Cheng char usage_duration[10]; 835da14cebeSEric Cheng char usage_ipackets[9]; 836da14cebeSEric Cheng char usage_rbytes[10]; 837da14cebeSEric Cheng char usage_opackets[9]; 838da14cebeSEric Cheng char usage_obytes[10]; 839da14cebeSEric Cheng char usage_bandwidth[14]; 840da14cebeSEric Cheng } usage_fields_buf_t; 841da14cebeSEric Cheng 842*8002d411SSowmini Varadhan static ofmt_field_t usage_fields[] = { 843*8002d411SSowmini Varadhan { "LINK", 13, 844*8002d411SSowmini Varadhan offsetof(usage_fields_buf_t, usage_link), print_default_cb}, 845*8002d411SSowmini Varadhan { "DURATION", 11, 846*8002d411SSowmini Varadhan offsetof(usage_fields_buf_t, usage_duration), print_default_cb}, 847*8002d411SSowmini Varadhan { "IPACKETS", 10, 848*8002d411SSowmini Varadhan offsetof(usage_fields_buf_t, usage_ipackets), print_default_cb}, 849*8002d411SSowmini Varadhan { "RBYTES", 11, 850*8002d411SSowmini Varadhan offsetof(usage_fields_buf_t, usage_rbytes), print_default_cb}, 851*8002d411SSowmini Varadhan { "OPACKETS", 10, 852*8002d411SSowmini Varadhan offsetof(usage_fields_buf_t, usage_opackets), print_default_cb}, 853*8002d411SSowmini Varadhan { "OBYTES", 11, 854*8002d411SSowmini Varadhan offsetof(usage_fields_buf_t, usage_obytes), print_default_cb}, 855*8002d411SSowmini Varadhan { "BANDWIDTH", 15, 856*8002d411SSowmini Varadhan offsetof(usage_fields_buf_t, usage_bandwidth), print_default_cb}, 857*8002d411SSowmini Varadhan { NULL, 0, 0, NULL}} 858da14cebeSEric Cheng ; 859da14cebeSEric Cheng 860da14cebeSEric Cheng 861da14cebeSEric Cheng /* 862da14cebeSEric Cheng * structures for 'dladm show-usage link' 863da14cebeSEric Cheng */ 864da14cebeSEric Cheng 865da14cebeSEric Cheng typedef struct usage_l_fields_buf_s { 866da14cebeSEric Cheng char usage_l_link[12]; 867da14cebeSEric Cheng char usage_l_stime[13]; 868da14cebeSEric Cheng char usage_l_etime[13]; 869da14cebeSEric Cheng char usage_l_rbytes[8]; 870da14cebeSEric Cheng char usage_l_obytes[8]; 871da14cebeSEric Cheng char usage_l_bandwidth[14]; 872da14cebeSEric Cheng } usage_l_fields_buf_t; 873da14cebeSEric Cheng 874*8002d411SSowmini Varadhan static ofmt_field_t usage_l_fields[] = { 875*8002d411SSowmini Varadhan /* name, field width, offset */ 876*8002d411SSowmini Varadhan { "LINK", 13, 877*8002d411SSowmini Varadhan offsetof(usage_l_fields_buf_t, usage_l_link), print_default_cb}, 878*8002d411SSowmini Varadhan { "START", 14, 879*8002d411SSowmini Varadhan offsetof(usage_l_fields_buf_t, usage_l_stime), print_default_cb}, 880*8002d411SSowmini Varadhan { "END", 14, 881*8002d411SSowmini Varadhan offsetof(usage_l_fields_buf_t, usage_l_etime), print_default_cb}, 882*8002d411SSowmini Varadhan { "RBYTES", 9, 883*8002d411SSowmini Varadhan offsetof(usage_l_fields_buf_t, usage_l_rbytes), print_default_cb}, 884*8002d411SSowmini Varadhan { "OBYTES", 9, 885*8002d411SSowmini Varadhan offsetof(usage_l_fields_buf_t, usage_l_obytes), print_default_cb}, 886*8002d411SSowmini Varadhan { "BANDWIDTH", 15, 887*8002d411SSowmini Varadhan offsetof(usage_l_fields_buf_t, usage_l_bandwidth), print_default_cb}, 888*8002d411SSowmini Varadhan { NULL, 0, 0, NULL}} 889da14cebeSEric Cheng ; 890da14cebeSEric Cheng 8917c478bd9Sstevel@tonic-gate static char *progname; 8920ba2cbe9Sxc151355 static sig_atomic_t signalled; 8937c478bd9Sstevel@tonic-gate 8944ac67f02SAnurag S. Maskey /* 8954ac67f02SAnurag S. Maskey * Handle to libdladm. Opened in main() before the sub-command 8964ac67f02SAnurag S. Maskey * specific function is called. 8974ac67f02SAnurag S. Maskey */ 8984ac67f02SAnurag S. Maskey static dladm_handle_t handle = NULL; 8994ac67f02SAnurag S. Maskey 900da14cebeSEric Cheng #define DLADM_ETHERSTUB_NAME "etherstub" 901da14cebeSEric Cheng #define DLADM_IS_ETHERSTUB(id) (id == DATALINK_INVALID_LINKID) 902da14cebeSEric Cheng 9037c478bd9Sstevel@tonic-gate static void 9047c478bd9Sstevel@tonic-gate usage(void) 9057c478bd9Sstevel@tonic-gate { 9068d5c46e6Sam223141 int i; 9078d5c46e6Sam223141 cmd_t *cmdp; 9088d5c46e6Sam223141 (void) fprintf(stderr, gettext("usage: dladm <subcommand> <args> ..." 9098d5c46e6Sam223141 "\n")); 9108d5c46e6Sam223141 for (i = 0; i < sizeof (cmds) / sizeof (cmds[0]); i++) { 9118d5c46e6Sam223141 cmdp = &cmds[i]; 9128d5c46e6Sam223141 if (cmdp->c_usage != NULL) 9138d5c46e6Sam223141 (void) fprintf(stderr, "%s\n", gettext(cmdp->c_usage)); 9148d5c46e6Sam223141 } 9154ac67f02SAnurag S. Maskey 9164ac67f02SAnurag S. Maskey /* close dladm handle if it was opened */ 9174ac67f02SAnurag S. Maskey if (handle != NULL) 9184ac67f02SAnurag S. Maskey dladm_close(handle); 9194ac67f02SAnurag S. Maskey 9207c478bd9Sstevel@tonic-gate exit(1); 9217c478bd9Sstevel@tonic-gate } 9227c478bd9Sstevel@tonic-gate 9237c478bd9Sstevel@tonic-gate int 9247c478bd9Sstevel@tonic-gate main(int argc, char *argv[]) 9257c478bd9Sstevel@tonic-gate { 9267c478bd9Sstevel@tonic-gate int i; 9277c478bd9Sstevel@tonic-gate cmd_t *cmdp; 9284ac67f02SAnurag S. Maskey dladm_status_t status; 9297c478bd9Sstevel@tonic-gate 9307c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, ""); 9317c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN) 9327c478bd9Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST" 9337c478bd9Sstevel@tonic-gate #endif 9347c478bd9Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN); 9357c478bd9Sstevel@tonic-gate 9367c478bd9Sstevel@tonic-gate progname = argv[0]; 9377c478bd9Sstevel@tonic-gate 9387c478bd9Sstevel@tonic-gate if (argc < 2) 9397c478bd9Sstevel@tonic-gate usage(); 9407c478bd9Sstevel@tonic-gate 9417c478bd9Sstevel@tonic-gate for (i = 0; i < sizeof (cmds) / sizeof (cmds[0]); i++) { 9427c478bd9Sstevel@tonic-gate cmdp = &cmds[i]; 9437c478bd9Sstevel@tonic-gate if (strcmp(argv[1], cmdp->c_name) == 0) { 9444ac67f02SAnurag S. Maskey /* Open the libdladm handle */ 9454ac67f02SAnurag S. Maskey if ((status = dladm_open(&handle)) != DLADM_STATUS_OK) { 9464ac67f02SAnurag S. Maskey die_dlerr(status, 9474ac67f02SAnurag S. Maskey "could not open /dev/dld"); 9484ac67f02SAnurag S. Maskey } 9494ac67f02SAnurag S. Maskey 9508d5c46e6Sam223141 cmdp->c_fn(argc - 1, &argv[1], cmdp->c_usage); 9514ac67f02SAnurag S. Maskey 9524ac67f02SAnurag S. Maskey dladm_close(handle); 9537c478bd9Sstevel@tonic-gate exit(0); 9547c478bd9Sstevel@tonic-gate } 9557c478bd9Sstevel@tonic-gate } 9567c478bd9Sstevel@tonic-gate 9577c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("%s: unknown subcommand '%s'\n"), 9587c478bd9Sstevel@tonic-gate progname, argv[1]); 9597c478bd9Sstevel@tonic-gate usage(); 9607c478bd9Sstevel@tonic-gate 9617c478bd9Sstevel@tonic-gate return (0); 9627c478bd9Sstevel@tonic-gate } 9637c478bd9Sstevel@tonic-gate 964da14cebeSEric Cheng /*ARGSUSED*/ 965da14cebeSEric Cheng static int 966da14cebeSEric Cheng show_usage_date(dladm_usage_t *usage, void *arg) 967da14cebeSEric Cheng { 968ae6aa22aSVenugopal Iyer show_usage_state_t *state = (show_usage_state_t *)arg; 969da14cebeSEric Cheng time_t stime; 970da14cebeSEric Cheng char timebuf[20]; 971ae6aa22aSVenugopal Iyer dladm_status_t status; 972ae6aa22aSVenugopal Iyer uint32_t flags; 973ae6aa22aSVenugopal Iyer 974ae6aa22aSVenugopal Iyer /* 975ae6aa22aSVenugopal Iyer * Only show usage information for existing links unless '-a' 976ae6aa22aSVenugopal Iyer * is specified. 977ae6aa22aSVenugopal Iyer */ 978ae6aa22aSVenugopal Iyer if (!state->us_showall) { 979ae6aa22aSVenugopal Iyer if ((status = dladm_name2info(handle, usage->du_name, 980ae6aa22aSVenugopal Iyer NULL, &flags, NULL, NULL)) != DLADM_STATUS_OK) { 981ae6aa22aSVenugopal Iyer return (status); 982ae6aa22aSVenugopal Iyer } 983ae6aa22aSVenugopal Iyer if ((flags & DLADM_OPT_ACTIVE) == 0) 984ae6aa22aSVenugopal Iyer return (DLADM_STATUS_LINKINVAL); 985ae6aa22aSVenugopal Iyer } 986da14cebeSEric Cheng 987da14cebeSEric Cheng stime = usage->du_stime; 988da14cebeSEric Cheng (void) strftime(timebuf, sizeof (timebuf), "%m/%d/%Y", 989da14cebeSEric Cheng localtime(&stime)); 990da14cebeSEric Cheng (void) printf("%s\n", timebuf); 991da14cebeSEric Cheng 992da14cebeSEric Cheng return (DLADM_STATUS_OK); 993da14cebeSEric Cheng } 994da14cebeSEric Cheng 995da14cebeSEric Cheng static int 996da14cebeSEric Cheng show_usage_time(dladm_usage_t *usage, void *arg) 997da14cebeSEric Cheng { 998da14cebeSEric Cheng show_usage_state_t *state = (show_usage_state_t *)arg; 999da14cebeSEric Cheng char buf[DLADM_STRSIZE]; 1000da14cebeSEric Cheng usage_l_fields_buf_t ubuf; 1001da14cebeSEric Cheng time_t time; 1002da14cebeSEric Cheng double bw; 1003ae6aa22aSVenugopal Iyer dladm_status_t status; 1004ae6aa22aSVenugopal Iyer uint32_t flags; 1005ae6aa22aSVenugopal Iyer 1006ae6aa22aSVenugopal Iyer /* 1007ae6aa22aSVenugopal Iyer * Only show usage information for existing links unless '-a' 1008ae6aa22aSVenugopal Iyer * is specified. 1009ae6aa22aSVenugopal Iyer */ 1010ae6aa22aSVenugopal Iyer if (!state->us_showall) { 1011ae6aa22aSVenugopal Iyer if ((status = dladm_name2info(handle, usage->du_name, 1012ae6aa22aSVenugopal Iyer NULL, &flags, NULL, NULL)) != DLADM_STATUS_OK) { 1013ae6aa22aSVenugopal Iyer return (status); 1014ae6aa22aSVenugopal Iyer } 1015ae6aa22aSVenugopal Iyer if ((flags & DLADM_OPT_ACTIVE) == 0) 1016ae6aa22aSVenugopal Iyer return (DLADM_STATUS_LINKINVAL); 1017ae6aa22aSVenugopal Iyer } 1018da14cebeSEric Cheng 1019da14cebeSEric Cheng if (state->us_plot) { 1020da14cebeSEric Cheng if (!state->us_printheader) { 1021da14cebeSEric Cheng if (state->us_first) { 1022da14cebeSEric Cheng (void) printf("# Time"); 1023da14cebeSEric Cheng state->us_first = B_FALSE; 1024da14cebeSEric Cheng } 1025da14cebeSEric Cheng (void) printf(" %s", usage->du_name); 1026da14cebeSEric Cheng if (usage->du_last) { 1027da14cebeSEric Cheng (void) printf("\n"); 1028da14cebeSEric Cheng state->us_first = B_TRUE; 1029da14cebeSEric Cheng state->us_printheader = B_TRUE; 1030da14cebeSEric Cheng } 1031da14cebeSEric Cheng } else { 1032da14cebeSEric Cheng if (state->us_first) { 1033da14cebeSEric Cheng time = usage->du_etime; 1034da14cebeSEric Cheng (void) strftime(buf, sizeof (buf), "%T", 1035da14cebeSEric Cheng localtime(&time)); 1036da14cebeSEric Cheng state->us_first = B_FALSE; 1037da14cebeSEric Cheng (void) printf("%s", buf); 1038da14cebeSEric Cheng } 1039da14cebeSEric Cheng bw = (double)usage->du_bandwidth/1000; 1040da14cebeSEric Cheng (void) printf(" %.2f", bw); 1041da14cebeSEric Cheng if (usage->du_last) { 1042da14cebeSEric Cheng (void) printf("\n"); 1043da14cebeSEric Cheng state->us_first = B_TRUE; 1044da14cebeSEric Cheng } 1045da14cebeSEric Cheng } 1046da14cebeSEric Cheng return (DLADM_STATUS_OK); 1047da14cebeSEric Cheng } 1048da14cebeSEric Cheng 1049da14cebeSEric Cheng bzero(&ubuf, sizeof (ubuf)); 1050da14cebeSEric Cheng 1051da14cebeSEric Cheng (void) snprintf(ubuf.usage_l_link, sizeof (ubuf.usage_l_link), "%s", 1052da14cebeSEric Cheng usage->du_name); 1053da14cebeSEric Cheng time = usage->du_stime; 1054da14cebeSEric Cheng (void) strftime(buf, sizeof (buf), "%T", localtime(&time)); 1055da14cebeSEric Cheng (void) snprintf(ubuf.usage_l_stime, sizeof (ubuf.usage_l_stime), "%s", 1056da14cebeSEric Cheng buf); 1057da14cebeSEric Cheng time = usage->du_etime; 1058da14cebeSEric Cheng (void) strftime(buf, sizeof (buf), "%T", localtime(&time)); 1059da14cebeSEric Cheng (void) snprintf(ubuf.usage_l_etime, sizeof (ubuf.usage_l_etime), "%s", 1060da14cebeSEric Cheng buf); 1061da14cebeSEric Cheng (void) snprintf(ubuf.usage_l_rbytes, sizeof (ubuf.usage_l_rbytes), 1062da14cebeSEric Cheng "%llu", usage->du_rbytes); 1063da14cebeSEric Cheng (void) snprintf(ubuf.usage_l_obytes, sizeof (ubuf.usage_l_obytes), 1064da14cebeSEric Cheng "%llu", usage->du_obytes); 1065da14cebeSEric Cheng (void) snprintf(ubuf.usage_l_bandwidth, sizeof (ubuf.usage_l_bandwidth), 1066da14cebeSEric Cheng "%s Mbps", dladm_bw2str(usage->du_bandwidth, buf)); 1067da14cebeSEric Cheng 1068*8002d411SSowmini Varadhan ofmt_print(state->us_ofmt, &ubuf); 1069da14cebeSEric Cheng return (DLADM_STATUS_OK); 1070da14cebeSEric Cheng } 1071da14cebeSEric Cheng 1072da14cebeSEric Cheng static int 1073da14cebeSEric Cheng show_usage_res(dladm_usage_t *usage, void *arg) 1074da14cebeSEric Cheng { 1075da14cebeSEric Cheng show_usage_state_t *state = (show_usage_state_t *)arg; 1076da14cebeSEric Cheng char buf[DLADM_STRSIZE]; 1077da14cebeSEric Cheng usage_fields_buf_t ubuf; 1078ae6aa22aSVenugopal Iyer dladm_status_t status; 1079ae6aa22aSVenugopal Iyer uint32_t flags; 1080ae6aa22aSVenugopal Iyer 1081ae6aa22aSVenugopal Iyer /* 1082ae6aa22aSVenugopal Iyer * Only show usage information for existing links unless '-a' 1083ae6aa22aSVenugopal Iyer * is specified. 1084ae6aa22aSVenugopal Iyer */ 1085ae6aa22aSVenugopal Iyer if (!state->us_showall) { 1086ae6aa22aSVenugopal Iyer if ((status = dladm_name2info(handle, usage->du_name, 1087ae6aa22aSVenugopal Iyer NULL, &flags, NULL, NULL)) != DLADM_STATUS_OK) { 1088ae6aa22aSVenugopal Iyer return (status); 1089ae6aa22aSVenugopal Iyer } 1090ae6aa22aSVenugopal Iyer if ((flags & DLADM_OPT_ACTIVE) == 0) 1091ae6aa22aSVenugopal Iyer return (DLADM_STATUS_LINKINVAL); 1092ae6aa22aSVenugopal Iyer } 1093da14cebeSEric Cheng 1094da14cebeSEric Cheng bzero(&ubuf, sizeof (ubuf)); 1095da14cebeSEric Cheng 1096da14cebeSEric Cheng (void) snprintf(ubuf.usage_link, sizeof (ubuf.usage_link), "%s", 1097da14cebeSEric Cheng usage->du_name); 1098da14cebeSEric Cheng (void) snprintf(ubuf.usage_duration, sizeof (ubuf.usage_duration), 1099da14cebeSEric Cheng "%llu", usage->du_duration); 1100da14cebeSEric Cheng (void) snprintf(ubuf.usage_ipackets, sizeof (ubuf.usage_ipackets), 1101da14cebeSEric Cheng "%llu", usage->du_ipackets); 1102da14cebeSEric Cheng (void) snprintf(ubuf.usage_rbytes, sizeof (ubuf.usage_rbytes), 1103da14cebeSEric Cheng "%llu", usage->du_rbytes); 1104da14cebeSEric Cheng (void) snprintf(ubuf.usage_opackets, sizeof (ubuf.usage_opackets), 1105da14cebeSEric Cheng "%llu", usage->du_opackets); 1106da14cebeSEric Cheng (void) snprintf(ubuf.usage_obytes, sizeof (ubuf.usage_obytes), 1107da14cebeSEric Cheng "%llu", usage->du_obytes); 1108da14cebeSEric Cheng (void) snprintf(ubuf.usage_bandwidth, sizeof (ubuf.usage_bandwidth), 1109da14cebeSEric Cheng "%s Mbps", dladm_bw2str(usage->du_bandwidth, buf)); 1110da14cebeSEric Cheng 1111*8002d411SSowmini Varadhan ofmt_print(state->us_ofmt, &ubuf); 1112da14cebeSEric Cheng 1113da14cebeSEric Cheng return (DLADM_STATUS_OK); 1114da14cebeSEric Cheng } 1115da14cebeSEric Cheng 1116da14cebeSEric Cheng static boolean_t 1117da14cebeSEric Cheng valid_formatspec(char *formatspec_str) 1118da14cebeSEric Cheng { 1119da14cebeSEric Cheng if (strcmp(formatspec_str, "gnuplot") == 0) 1120da14cebeSEric Cheng return (B_TRUE); 1121da14cebeSEric Cheng return (B_FALSE); 1122da14cebeSEric Cheng 1123da14cebeSEric Cheng } 1124da14cebeSEric Cheng 1125da14cebeSEric Cheng /*ARGSUSED*/ 1126da14cebeSEric Cheng static void 1127da14cebeSEric Cheng do_show_usage(int argc, char *argv[], const char *use) 1128da14cebeSEric Cheng { 1129da14cebeSEric Cheng char *file = NULL; 1130da14cebeSEric Cheng int opt; 1131da14cebeSEric Cheng dladm_status_t status; 1132da14cebeSEric Cheng boolean_t d_arg = B_FALSE; 1133da14cebeSEric Cheng char *stime = NULL; 1134da14cebeSEric Cheng char *etime = NULL; 1135da14cebeSEric Cheng char *resource = NULL; 1136da14cebeSEric Cheng show_usage_state_t state; 1137da14cebeSEric Cheng boolean_t o_arg = B_FALSE; 1138da14cebeSEric Cheng boolean_t F_arg = B_FALSE; 1139da14cebeSEric Cheng char *fields_str = NULL; 1140da14cebeSEric Cheng char *formatspec_str = NULL; 1141da14cebeSEric Cheng char *all_l_fields = 1142da14cebeSEric Cheng "link,start,end,rbytes,obytes,bandwidth"; 1143*8002d411SSowmini Varadhan ofmt_handle_t ofmt; 1144*8002d411SSowmini Varadhan ofmt_status_t oferr; 1145*8002d411SSowmini Varadhan uint_t ofmtflags = 0; 1146da14cebeSEric Cheng 1147da14cebeSEric Cheng bzero(&state, sizeof (show_usage_state_t)); 1148*8002d411SSowmini Varadhan state.us_parsable = B_FALSE; 1149da14cebeSEric Cheng state.us_printheader = B_FALSE; 1150da14cebeSEric Cheng state.us_plot = B_FALSE; 1151da14cebeSEric Cheng state.us_first = B_TRUE; 1152da14cebeSEric Cheng 1153ae6aa22aSVenugopal Iyer while ((opt = getopt_long(argc, argv, "das:e:o:f:F:", 1154ae6aa22aSVenugopal Iyer usage_opts, NULL)) != -1) { 1155da14cebeSEric Cheng switch (opt) { 1156da14cebeSEric Cheng case 'd': 1157da14cebeSEric Cheng d_arg = B_TRUE; 1158da14cebeSEric Cheng break; 1159ae6aa22aSVenugopal Iyer case 'a': 1160ae6aa22aSVenugopal Iyer state.us_showall = B_TRUE; 1161da14cebeSEric Cheng break; 1162da14cebeSEric Cheng case 'f': 1163da14cebeSEric Cheng file = optarg; 1164da14cebeSEric Cheng break; 1165da14cebeSEric Cheng case 's': 1166da14cebeSEric Cheng stime = optarg; 1167da14cebeSEric Cheng break; 1168da14cebeSEric Cheng case 'e': 1169da14cebeSEric Cheng etime = optarg; 1170da14cebeSEric Cheng break; 1171da14cebeSEric Cheng case 'o': 1172da14cebeSEric Cheng o_arg = B_TRUE; 1173da14cebeSEric Cheng fields_str = optarg; 1174da14cebeSEric Cheng break; 1175da14cebeSEric Cheng case 'F': 1176ae6aa22aSVenugopal Iyer state.us_plot = F_arg = B_TRUE; 1177da14cebeSEric Cheng formatspec_str = optarg; 1178da14cebeSEric Cheng break; 1179da14cebeSEric Cheng default: 1180da14cebeSEric Cheng die_opterr(optopt, opt, use); 1181da14cebeSEric Cheng break; 1182da14cebeSEric Cheng } 1183da14cebeSEric Cheng } 1184da14cebeSEric Cheng 1185da14cebeSEric Cheng if (file == NULL) 1186da14cebeSEric Cheng die("show-usage requires a file"); 1187da14cebeSEric Cheng 1188da14cebeSEric Cheng if (optind == (argc-1)) { 1189ae6aa22aSVenugopal Iyer uint32_t flags; 1190ae6aa22aSVenugopal Iyer 1191da14cebeSEric Cheng resource = argv[optind]; 1192ae6aa22aSVenugopal Iyer if (!state.us_showall && 1193ae6aa22aSVenugopal Iyer (((status = dladm_name2info(handle, resource, NULL, &flags, 1194ae6aa22aSVenugopal Iyer NULL, NULL)) != DLADM_STATUS_OK) || 1195ae6aa22aSVenugopal Iyer ((flags & DLADM_OPT_ACTIVE) == 0))) { 1196ae6aa22aSVenugopal Iyer die("invalid link: '%s'", resource); 1197ae6aa22aSVenugopal Iyer } 1198da14cebeSEric Cheng } 1199da14cebeSEric Cheng 1200ae6aa22aSVenugopal Iyer if (F_arg && d_arg) 1201ae6aa22aSVenugopal Iyer die("incompatible -d and -F options"); 1202da14cebeSEric Cheng 1203da14cebeSEric Cheng if (F_arg && valid_formatspec(formatspec_str) == B_FALSE) 1204da14cebeSEric Cheng die("Format specifier %s not supported", formatspec_str); 1205da14cebeSEric Cheng 1206*8002d411SSowmini Varadhan if (state.us_parsable) 1207*8002d411SSowmini Varadhan ofmtflags |= OFMT_PARSABLE; 1208*8002d411SSowmini Varadhan 1209*8002d411SSowmini Varadhan if (resource == NULL && stime == NULL && etime == NULL) { 1210*8002d411SSowmini Varadhan oferr = ofmt_open(fields_str, usage_fields, ofmtflags, 0, 1211*8002d411SSowmini Varadhan &ofmt); 1212*8002d411SSowmini Varadhan } else { 1213*8002d411SSowmini Varadhan if (!o_arg || (o_arg && strcasecmp(fields_str, "all") == 0)) 1214*8002d411SSowmini Varadhan fields_str = all_l_fields; 1215*8002d411SSowmini Varadhan oferr = ofmt_open(fields_str, usage_l_fields, ofmtflags, 0, 1216*8002d411SSowmini Varadhan &ofmt); 1217*8002d411SSowmini Varadhan 1218*8002d411SSowmini Varadhan } 1219*8002d411SSowmini Varadhan dladm_ofmt_check(oferr, state.us_parsable, ofmt); 1220*8002d411SSowmini Varadhan state.us_ofmt = ofmt; 1221*8002d411SSowmini Varadhan 1222da14cebeSEric Cheng if (d_arg) { 1223da14cebeSEric Cheng /* Print log dates */ 1224da14cebeSEric Cheng status = dladm_usage_dates(show_usage_date, 1225da14cebeSEric Cheng DLADM_LOGTYPE_LINK, file, resource, &state); 1226da14cebeSEric Cheng } else if (resource == NULL && stime == NULL && etime == NULL && 1227ae6aa22aSVenugopal Iyer !F_arg) { 1228da14cebeSEric Cheng /* Print summary */ 1229da14cebeSEric Cheng status = dladm_usage_summary(show_usage_res, 1230da14cebeSEric Cheng DLADM_LOGTYPE_LINK, file, &state); 1231da14cebeSEric Cheng } else if (resource != NULL) { 1232da14cebeSEric Cheng /* Print log entries for named resource */ 1233da14cebeSEric Cheng status = dladm_walk_usage_res(show_usage_time, 1234da14cebeSEric Cheng DLADM_LOGTYPE_LINK, file, resource, stime, etime, &state); 1235da14cebeSEric Cheng } else { 1236da14cebeSEric Cheng /* Print time and information for each link */ 1237da14cebeSEric Cheng status = dladm_walk_usage_time(show_usage_time, 1238da14cebeSEric Cheng DLADM_LOGTYPE_LINK, file, stime, etime, &state); 1239da14cebeSEric Cheng } 1240da14cebeSEric Cheng 1241da14cebeSEric Cheng if (status != DLADM_STATUS_OK) 1242da14cebeSEric Cheng die_dlerr(status, "show-usage"); 1243*8002d411SSowmini Varadhan ofmt_close(ofmt); 1244da14cebeSEric Cheng } 1245da14cebeSEric Cheng 12467c478bd9Sstevel@tonic-gate static void 12478d5c46e6Sam223141 do_create_aggr(int argc, char *argv[], const char *use) 12487c478bd9Sstevel@tonic-gate { 12497c478bd9Sstevel@tonic-gate char option; 1250d62bc4baSyz147064 int key = 0; 12517c478bd9Sstevel@tonic-gate uint32_t policy = AGGR_POLICY_L4; 12527c478bd9Sstevel@tonic-gate aggr_lacp_mode_t lacp_mode = AGGR_LACP_OFF; 12537c478bd9Sstevel@tonic-gate aggr_lacp_timer_t lacp_timer = AGGR_LACP_TIMER_SHORT; 1254f595a68aSyz147064 dladm_aggr_port_attr_db_t port[MAXPORT]; 1255d62bc4baSyz147064 uint_t n, ndev, nlink; 12567c478bd9Sstevel@tonic-gate uint8_t mac_addr[ETHERADDRL]; 12577c478bd9Sstevel@tonic-gate boolean_t mac_addr_fixed = B_FALSE; 12587c478bd9Sstevel@tonic-gate boolean_t P_arg = B_FALSE; 12597c478bd9Sstevel@tonic-gate boolean_t l_arg = B_FALSE; 12607c478bd9Sstevel@tonic-gate boolean_t u_arg = B_FALSE; 12617c478bd9Sstevel@tonic-gate boolean_t T_arg = B_FALSE; 1262d62bc4baSyz147064 uint32_t flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST; 12637c478bd9Sstevel@tonic-gate char *altroot = NULL; 1264d62bc4baSyz147064 char name[MAXLINKNAMELEN]; 1265d62bc4baSyz147064 char *devs[MAXPORT]; 1266d62bc4baSyz147064 char *links[MAXPORT]; 1267f595a68aSyz147064 dladm_status_t status; 1268da14cebeSEric Cheng dladm_status_t pstatus; 126963a6526dSMichael Lim char propstr[DLADM_STRSIZE]; 1270da14cebeSEric Cheng dladm_arg_list_t *proplist = NULL; 1271da14cebeSEric Cheng int i; 1272da14cebeSEric Cheng datalink_id_t linkid; 12737c478bd9Sstevel@tonic-gate 1274d62bc4baSyz147064 ndev = nlink = opterr = 0; 127563a6526dSMichael Lim bzero(propstr, DLADM_STRSIZE); 127663a6526dSMichael Lim 1277da14cebeSEric Cheng while ((option = getopt_long(argc, argv, ":d:l:L:P:R:tfu:T:p:", 1278d62bc4baSyz147064 lopts, NULL)) != -1) { 12797c478bd9Sstevel@tonic-gate switch (option) { 12807c478bd9Sstevel@tonic-gate case 'd': 1281d62bc4baSyz147064 if (ndev + nlink >= MAXPORT) 1282d62bc4baSyz147064 die("too many ports specified"); 12837c478bd9Sstevel@tonic-gate 1284d62bc4baSyz147064 devs[ndev++] = optarg; 12857c478bd9Sstevel@tonic-gate break; 12867c478bd9Sstevel@tonic-gate case 'P': 128733343a97Smeem if (P_arg) 128833343a97Smeem die_optdup(option); 12897c478bd9Sstevel@tonic-gate 12907c478bd9Sstevel@tonic-gate P_arg = B_TRUE; 1291f595a68aSyz147064 if (!dladm_aggr_str2policy(optarg, &policy)) 129233343a97Smeem die("invalid policy '%s'", optarg); 12937c478bd9Sstevel@tonic-gate break; 12947c478bd9Sstevel@tonic-gate case 'u': 129533343a97Smeem if (u_arg) 129633343a97Smeem die_optdup(option); 12977c478bd9Sstevel@tonic-gate 12987c478bd9Sstevel@tonic-gate u_arg = B_TRUE; 1299f595a68aSyz147064 if (!dladm_aggr_str2macaddr(optarg, &mac_addr_fixed, 130033343a97Smeem mac_addr)) 130133343a97Smeem die("invalid MAC address '%s'", optarg); 13027c478bd9Sstevel@tonic-gate break; 13037c478bd9Sstevel@tonic-gate case 'l': 1304d62bc4baSyz147064 if (isdigit(optarg[strlen(optarg) - 1])) { 1305d62bc4baSyz147064 1306d62bc4baSyz147064 /* 1307d62bc4baSyz147064 * Ended with digit, possibly a link name. 1308d62bc4baSyz147064 */ 1309d62bc4baSyz147064 if (ndev + nlink >= MAXPORT) 1310d62bc4baSyz147064 die("too many ports specified"); 1311d62bc4baSyz147064 1312d62bc4baSyz147064 links[nlink++] = optarg; 1313d62bc4baSyz147064 break; 1314d62bc4baSyz147064 } 1315d62bc4baSyz147064 /* FALLTHROUGH */ 1316d62bc4baSyz147064 case 'L': 131733343a97Smeem if (l_arg) 131833343a97Smeem die_optdup(option); 13197c478bd9Sstevel@tonic-gate 13207c478bd9Sstevel@tonic-gate l_arg = B_TRUE; 1321f595a68aSyz147064 if (!dladm_aggr_str2lacpmode(optarg, &lacp_mode)) 132233343a97Smeem die("invalid LACP mode '%s'", optarg); 13237c478bd9Sstevel@tonic-gate break; 13247c478bd9Sstevel@tonic-gate case 'T': 132533343a97Smeem if (T_arg) 132633343a97Smeem die_optdup(option); 13277c478bd9Sstevel@tonic-gate 13287c478bd9Sstevel@tonic-gate T_arg = B_TRUE; 1329f595a68aSyz147064 if (!dladm_aggr_str2lacptimer(optarg, &lacp_timer)) 133033343a97Smeem die("invalid LACP timer value '%s'", optarg); 13317c478bd9Sstevel@tonic-gate break; 13327c478bd9Sstevel@tonic-gate case 't': 1333d62bc4baSyz147064 flags &= ~DLADM_OPT_PERSIST; 1334d62bc4baSyz147064 break; 1335d62bc4baSyz147064 case 'f': 1336d62bc4baSyz147064 flags |= DLADM_OPT_FORCE; 13377c478bd9Sstevel@tonic-gate break; 13387c478bd9Sstevel@tonic-gate case 'R': 13397c478bd9Sstevel@tonic-gate altroot = optarg; 13407c478bd9Sstevel@tonic-gate break; 1341da14cebeSEric Cheng case 'p': 134263a6526dSMichael Lim (void) strlcat(propstr, optarg, DLADM_STRSIZE); 134363a6526dSMichael Lim if (strlcat(propstr, ",", DLADM_STRSIZE) >= 134463a6526dSMichael Lim DLADM_STRSIZE) 134563a6526dSMichael Lim die("property list too long '%s'", propstr); 1346da14cebeSEric Cheng break; 134763a6526dSMichael Lim 13487c478bd9Sstevel@tonic-gate default: 13498d5c46e6Sam223141 die_opterr(optopt, option, use); 135033343a97Smeem break; 13517c478bd9Sstevel@tonic-gate } 13527c478bd9Sstevel@tonic-gate } 13537c478bd9Sstevel@tonic-gate 1354d62bc4baSyz147064 if (ndev + nlink == 0) 13557c478bd9Sstevel@tonic-gate usage(); 13567c478bd9Sstevel@tonic-gate 1357d62bc4baSyz147064 /* get key value or the aggregation name (required last argument) */ 13587c478bd9Sstevel@tonic-gate if (optind != (argc-1)) 13597c478bd9Sstevel@tonic-gate usage(); 13607c478bd9Sstevel@tonic-gate 1361d62bc4baSyz147064 if (!str2int(argv[optind], &key)) { 1362d62bc4baSyz147064 if (strlcpy(name, argv[optind], MAXLINKNAMELEN) >= 1363d62bc4baSyz147064 MAXLINKNAMELEN) { 1364d62bc4baSyz147064 die("link name too long '%s'", argv[optind]); 1365d62bc4baSyz147064 } 13667c478bd9Sstevel@tonic-gate 1367d62bc4baSyz147064 if (!dladm_valid_linkname(name)) 1368d62bc4baSyz147064 die("invalid link name '%s'", argv[optind]); 1369d62bc4baSyz147064 } else { 1370d62bc4baSyz147064 (void) snprintf(name, MAXLINKNAMELEN, "aggr%d", key); 1371d62bc4baSyz147064 } 1372d62bc4baSyz147064 1373d62bc4baSyz147064 if (altroot != NULL) 1374d62bc4baSyz147064 altroot_cmd(altroot, argc, argv); 1375d62bc4baSyz147064 1376d62bc4baSyz147064 for (n = 0; n < ndev; n++) { 13774ac67f02SAnurag S. Maskey if ((status = dladm_dev2linkid(handle, devs[n], 13784ac67f02SAnurag S. Maskey &port[n].lp_linkid)) != DLADM_STATUS_OK) { 13794ac67f02SAnurag S. Maskey die_dlerr(status, "invalid dev name '%s'", devs[n]); 1380d62bc4baSyz147064 } 1381d62bc4baSyz147064 } 1382d62bc4baSyz147064 1383d62bc4baSyz147064 for (n = 0; n < nlink; n++) { 13844ac67f02SAnurag S. Maskey if ((status = dladm_name2info(handle, links[n], 13854ac67f02SAnurag S. Maskey &port[ndev + n].lp_linkid, NULL, NULL, NULL)) != 13864ac67f02SAnurag S. Maskey DLADM_STATUS_OK) { 13874ac67f02SAnurag S. Maskey die_dlerr(status, "invalid link name '%s'", links[n]); 1388d62bc4baSyz147064 } 1389d62bc4baSyz147064 } 1390d62bc4baSyz147064 13914ac67f02SAnurag S. Maskey status = dladm_aggr_create(handle, name, key, ndev + nlink, port, 13924ac67f02SAnurag S. Maskey policy, mac_addr_fixed, (const uchar_t *)mac_addr, lacp_mode, 1393d62bc4baSyz147064 lacp_timer, flags); 1394da14cebeSEric Cheng if (status != DLADM_STATUS_OK) 1395da14cebeSEric Cheng goto done; 1396da14cebeSEric Cheng 139763a6526dSMichael Lim if (dladm_parse_link_props(propstr, &proplist, B_FALSE) 139863a6526dSMichael Lim != DLADM_STATUS_OK) 139963a6526dSMichael Lim die("invalid aggregation property"); 140063a6526dSMichael Lim 1401da14cebeSEric Cheng if (proplist == NULL) 1402da14cebeSEric Cheng return; 1403da14cebeSEric Cheng 14044ac67f02SAnurag S. Maskey status = dladm_name2info(handle, name, &linkid, NULL, NULL, NULL); 1405da14cebeSEric Cheng if (status != DLADM_STATUS_OK) 1406da14cebeSEric Cheng goto done; 1407da14cebeSEric Cheng 1408da14cebeSEric Cheng for (i = 0; i < proplist->al_count; i++) { 1409da14cebeSEric Cheng dladm_arg_info_t *aip = &proplist->al_info[i]; 1410da14cebeSEric Cheng 14114ac67f02SAnurag S. Maskey pstatus = dladm_set_linkprop(handle, linkid, aip->ai_name, 1412da14cebeSEric Cheng aip->ai_val, aip->ai_count, flags); 1413da14cebeSEric Cheng 1414da14cebeSEric Cheng if (pstatus != DLADM_STATUS_OK) { 1415da14cebeSEric Cheng die_dlerr(pstatus, 1416da14cebeSEric Cheng "aggr creation succeeded but " 1417da14cebeSEric Cheng "could not set property '%s'", aip->ai_name); 1418da14cebeSEric Cheng } 1419da14cebeSEric Cheng } 1420d62bc4baSyz147064 done: 1421da14cebeSEric Cheng dladm_free_props(proplist); 1422d62bc4baSyz147064 if (status != DLADM_STATUS_OK) { 1423d62bc4baSyz147064 if (status == DLADM_STATUS_NONOTIF) { 1424d62bc4baSyz147064 die_dlerr(status, "not all links have link up/down " 1425d62bc4baSyz147064 "detection; must use -f (see dladm(1M))\n"); 1426d62bc4baSyz147064 } else { 1427f595a68aSyz147064 die_dlerr(status, "create operation failed"); 14287c478bd9Sstevel@tonic-gate } 1429d62bc4baSyz147064 } 1430d62bc4baSyz147064 } 1431d62bc4baSyz147064 1432d62bc4baSyz147064 /* 1433d62bc4baSyz147064 * arg is either the key or the aggr name. Validate it and convert it to 1434d62bc4baSyz147064 * the linkid if altroot is NULL. 1435d62bc4baSyz147064 */ 1436d62bc4baSyz147064 static dladm_status_t 1437d62bc4baSyz147064 i_dladm_aggr_get_linkid(const char *altroot, const char *arg, 1438d62bc4baSyz147064 datalink_id_t *linkidp, uint32_t flags) 1439d62bc4baSyz147064 { 1440d62bc4baSyz147064 int key = 0; 1441d62bc4baSyz147064 char *aggr = NULL; 1442d62bc4baSyz147064 dladm_status_t status; 1443d62bc4baSyz147064 1444d62bc4baSyz147064 if (!str2int(arg, &key)) 1445d62bc4baSyz147064 aggr = (char *)arg; 1446d62bc4baSyz147064 1447d62bc4baSyz147064 if (aggr == NULL && key == 0) 1448d62bc4baSyz147064 return (DLADM_STATUS_LINKINVAL); 1449d62bc4baSyz147064 1450d62bc4baSyz147064 if (altroot != NULL) 1451d62bc4baSyz147064 return (DLADM_STATUS_OK); 1452d62bc4baSyz147064 1453d62bc4baSyz147064 if (aggr != NULL) { 14544ac67f02SAnurag S. Maskey status = dladm_name2info(handle, aggr, linkidp, NULL, NULL, 14554ac67f02SAnurag S. Maskey NULL); 1456d62bc4baSyz147064 } else { 14574ac67f02SAnurag S. Maskey status = dladm_key2linkid(handle, key, linkidp, flags); 1458d62bc4baSyz147064 } 1459d62bc4baSyz147064 1460d62bc4baSyz147064 return (status); 1461d62bc4baSyz147064 } 14627c478bd9Sstevel@tonic-gate 14637c478bd9Sstevel@tonic-gate static void 14648d5c46e6Sam223141 do_delete_aggr(int argc, char *argv[], const char *use) 14657c478bd9Sstevel@tonic-gate { 14667c478bd9Sstevel@tonic-gate char option; 14677c478bd9Sstevel@tonic-gate char *altroot = NULL; 1468d62bc4baSyz147064 uint32_t flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST; 1469f595a68aSyz147064 dladm_status_t status; 1470d62bc4baSyz147064 datalink_id_t linkid; 14717c478bd9Sstevel@tonic-gate 14727c478bd9Sstevel@tonic-gate opterr = 0; 1473d62bc4baSyz147064 while ((option = getopt_long(argc, argv, ":R:t", lopts, NULL)) != -1) { 14747c478bd9Sstevel@tonic-gate switch (option) { 14757c478bd9Sstevel@tonic-gate case 't': 1476d62bc4baSyz147064 flags &= ~DLADM_OPT_PERSIST; 14777c478bd9Sstevel@tonic-gate break; 14787c478bd9Sstevel@tonic-gate case 'R': 14797c478bd9Sstevel@tonic-gate altroot = optarg; 14807c478bd9Sstevel@tonic-gate break; 14817c478bd9Sstevel@tonic-gate default: 14828d5c46e6Sam223141 die_opterr(optopt, option, use); 14837c478bd9Sstevel@tonic-gate break; 14847c478bd9Sstevel@tonic-gate } 14857c478bd9Sstevel@tonic-gate } 14867c478bd9Sstevel@tonic-gate 1487d62bc4baSyz147064 /* get key value or the aggregation name (required last argument) */ 14887c478bd9Sstevel@tonic-gate if (optind != (argc-1)) 14897c478bd9Sstevel@tonic-gate usage(); 14907c478bd9Sstevel@tonic-gate 1491d62bc4baSyz147064 status = i_dladm_aggr_get_linkid(altroot, argv[optind], &linkid, flags); 1492d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 1493d62bc4baSyz147064 goto done; 14947c478bd9Sstevel@tonic-gate 1495d62bc4baSyz147064 if (altroot != NULL) 1496d62bc4baSyz147064 altroot_cmd(altroot, argc, argv); 1497d62bc4baSyz147064 14984ac67f02SAnurag S. Maskey status = dladm_aggr_delete(handle, linkid, flags); 1499d62bc4baSyz147064 done: 1500f595a68aSyz147064 if (status != DLADM_STATUS_OK) 1501f595a68aSyz147064 die_dlerr(status, "delete operation failed"); 15027c478bd9Sstevel@tonic-gate } 15037c478bd9Sstevel@tonic-gate 15047c478bd9Sstevel@tonic-gate static void 15058d5c46e6Sam223141 do_add_aggr(int argc, char *argv[], const char *use) 15067c478bd9Sstevel@tonic-gate { 15077c478bd9Sstevel@tonic-gate char option; 1508d62bc4baSyz147064 uint_t n, ndev, nlink; 15097c478bd9Sstevel@tonic-gate char *altroot = NULL; 1510d62bc4baSyz147064 uint32_t flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST; 1511d62bc4baSyz147064 datalink_id_t linkid; 1512f595a68aSyz147064 dladm_status_t status; 1513d62bc4baSyz147064 dladm_aggr_port_attr_db_t port[MAXPORT]; 1514d62bc4baSyz147064 char *devs[MAXPORT]; 1515d62bc4baSyz147064 char *links[MAXPORT]; 15167c478bd9Sstevel@tonic-gate 1517d62bc4baSyz147064 ndev = nlink = opterr = 0; 1518d62bc4baSyz147064 while ((option = getopt_long(argc, argv, ":d:l:R:tf", lopts, 15197c478bd9Sstevel@tonic-gate NULL)) != -1) { 15207c478bd9Sstevel@tonic-gate switch (option) { 15217c478bd9Sstevel@tonic-gate case 'd': 1522d62bc4baSyz147064 if (ndev + nlink >= MAXPORT) 1523d62bc4baSyz147064 die("too many ports specified"); 15247c478bd9Sstevel@tonic-gate 1525d62bc4baSyz147064 devs[ndev++] = optarg; 1526d62bc4baSyz147064 break; 1527d62bc4baSyz147064 case 'l': 1528d62bc4baSyz147064 if (ndev + nlink >= MAXPORT) 1529d62bc4baSyz147064 die("too many ports specified"); 153033343a97Smeem 1531d62bc4baSyz147064 links[nlink++] = optarg; 15327c478bd9Sstevel@tonic-gate break; 15337c478bd9Sstevel@tonic-gate case 't': 1534d62bc4baSyz147064 flags &= ~DLADM_OPT_PERSIST; 1535d62bc4baSyz147064 break; 1536d62bc4baSyz147064 case 'f': 1537d62bc4baSyz147064 flags |= DLADM_OPT_FORCE; 15387c478bd9Sstevel@tonic-gate break; 15397c478bd9Sstevel@tonic-gate case 'R': 15407c478bd9Sstevel@tonic-gate altroot = optarg; 15417c478bd9Sstevel@tonic-gate break; 15427c478bd9Sstevel@tonic-gate default: 15438d5c46e6Sam223141 die_opterr(optopt, option, use); 154433343a97Smeem break; 15457c478bd9Sstevel@tonic-gate } 15467c478bd9Sstevel@tonic-gate } 15477c478bd9Sstevel@tonic-gate 1548d62bc4baSyz147064 if (ndev + nlink == 0) 15497c478bd9Sstevel@tonic-gate usage(); 15507c478bd9Sstevel@tonic-gate 1551d62bc4baSyz147064 /* get key value or the aggregation name (required last argument) */ 15527c478bd9Sstevel@tonic-gate if (optind != (argc-1)) 15537c478bd9Sstevel@tonic-gate usage(); 15547c478bd9Sstevel@tonic-gate 1555d62bc4baSyz147064 if ((status = i_dladm_aggr_get_linkid(altroot, argv[optind], &linkid, 1556d62bc4baSyz147064 flags & (DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST))) != 1557d62bc4baSyz147064 DLADM_STATUS_OK) { 1558d62bc4baSyz147064 goto done; 1559d62bc4baSyz147064 } 15607c478bd9Sstevel@tonic-gate 1561d62bc4baSyz147064 if (altroot != NULL) 1562d62bc4baSyz147064 altroot_cmd(altroot, argc, argv); 1563d62bc4baSyz147064 1564d62bc4baSyz147064 for (n = 0; n < ndev; n++) { 15654ac67f02SAnurag S. Maskey if ((status = dladm_dev2linkid(handle, devs[n], 15664ac67f02SAnurag S. Maskey &(port[n].lp_linkid))) != DLADM_STATUS_OK) { 15674ac67f02SAnurag S. Maskey die_dlerr(status, "invalid <dev> '%s'", devs[n]); 1568d62bc4baSyz147064 } 1569d62bc4baSyz147064 } 1570d62bc4baSyz147064 1571d62bc4baSyz147064 for (n = 0; n < nlink; n++) { 15724ac67f02SAnurag S. Maskey if ((status = dladm_name2info(handle, links[n], 15734ac67f02SAnurag S. Maskey &port[n + ndev].lp_linkid, NULL, NULL, NULL)) != 15744ac67f02SAnurag S. Maskey DLADM_STATUS_OK) { 15754ac67f02SAnurag S. Maskey die_dlerr(status, "invalid <link> '%s'", links[n]); 1576d62bc4baSyz147064 } 1577d62bc4baSyz147064 } 1578d62bc4baSyz147064 15794ac67f02SAnurag S. Maskey status = dladm_aggr_add(handle, linkid, ndev + nlink, port, flags); 1580d62bc4baSyz147064 done: 1581f595a68aSyz147064 if (status != DLADM_STATUS_OK) { 1582219a2a31Shl157128 /* 1583f595a68aSyz147064 * checking DLADM_STATUS_NOTSUP is a temporary workaround 1584219a2a31Shl157128 * and should be removed once 6399681 is fixed. 1585219a2a31Shl157128 */ 1586f595a68aSyz147064 if (status == DLADM_STATUS_NOTSUP) { 1587219a2a31Shl157128 (void) fprintf(stderr, 1588219a2a31Shl157128 gettext("%s: add operation failed: %s\n"), 1589219a2a31Shl157128 progname, 1590d62bc4baSyz147064 gettext("link capabilities don't match")); 15914ac67f02SAnurag S. Maskey dladm_close(handle); 1592219a2a31Shl157128 exit(ENOTSUP); 1593d62bc4baSyz147064 } else if (status == DLADM_STATUS_NONOTIF) { 1594d62bc4baSyz147064 die_dlerr(status, "not all links have link up/down " 1595d62bc4baSyz147064 "detection; must use -f (see dladm(1M))\n"); 1596d62bc4baSyz147064 } else { 1597f595a68aSyz147064 die_dlerr(status, "add operation failed"); 15987c478bd9Sstevel@tonic-gate } 15997c478bd9Sstevel@tonic-gate } 1600d62bc4baSyz147064 } 16017c478bd9Sstevel@tonic-gate 16027c478bd9Sstevel@tonic-gate static void 16038d5c46e6Sam223141 do_remove_aggr(int argc, char *argv[], const char *use) 16047c478bd9Sstevel@tonic-gate { 16057c478bd9Sstevel@tonic-gate char option; 1606f595a68aSyz147064 dladm_aggr_port_attr_db_t port[MAXPORT]; 1607d62bc4baSyz147064 uint_t n, ndev, nlink; 1608d62bc4baSyz147064 char *devs[MAXPORT]; 1609d62bc4baSyz147064 char *links[MAXPORT]; 16107c478bd9Sstevel@tonic-gate char *altroot = NULL; 1611d62bc4baSyz147064 uint32_t flags; 1612d62bc4baSyz147064 datalink_id_t linkid; 1613f595a68aSyz147064 dladm_status_t status; 16147c478bd9Sstevel@tonic-gate 1615d62bc4baSyz147064 flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST; 1616d62bc4baSyz147064 ndev = nlink = opterr = 0; 1617d62bc4baSyz147064 while ((option = getopt_long(argc, argv, ":d:l:R:t", 1618d62bc4baSyz147064 lopts, NULL)) != -1) { 16197c478bd9Sstevel@tonic-gate switch (option) { 16207c478bd9Sstevel@tonic-gate case 'd': 1621d62bc4baSyz147064 if (ndev + nlink >= MAXPORT) 1622d62bc4baSyz147064 die("too many ports specified"); 16237c478bd9Sstevel@tonic-gate 1624d62bc4baSyz147064 devs[ndev++] = optarg; 1625d62bc4baSyz147064 break; 1626d62bc4baSyz147064 case 'l': 1627d62bc4baSyz147064 if (ndev + nlink >= MAXPORT) 1628d62bc4baSyz147064 die("too many ports specified"); 162933343a97Smeem 1630d62bc4baSyz147064 links[nlink++] = optarg; 16317c478bd9Sstevel@tonic-gate break; 16327c478bd9Sstevel@tonic-gate case 't': 1633d62bc4baSyz147064 flags &= ~DLADM_OPT_PERSIST; 16347c478bd9Sstevel@tonic-gate break; 16357c478bd9Sstevel@tonic-gate case 'R': 16367c478bd9Sstevel@tonic-gate altroot = optarg; 16377c478bd9Sstevel@tonic-gate break; 16387c478bd9Sstevel@tonic-gate default: 16398d5c46e6Sam223141 die_opterr(optopt, option, use); 164033343a97Smeem break; 16417c478bd9Sstevel@tonic-gate } 16427c478bd9Sstevel@tonic-gate } 16437c478bd9Sstevel@tonic-gate 1644d62bc4baSyz147064 if (ndev + nlink == 0) 16457c478bd9Sstevel@tonic-gate usage(); 16467c478bd9Sstevel@tonic-gate 1647d62bc4baSyz147064 /* get key value or the aggregation name (required last argument) */ 16487c478bd9Sstevel@tonic-gate if (optind != (argc-1)) 16497c478bd9Sstevel@tonic-gate usage(); 16507c478bd9Sstevel@tonic-gate 1651d62bc4baSyz147064 status = i_dladm_aggr_get_linkid(altroot, argv[optind], &linkid, flags); 1652d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 1653d62bc4baSyz147064 goto done; 16547c478bd9Sstevel@tonic-gate 1655d62bc4baSyz147064 if (altroot != NULL) 1656d62bc4baSyz147064 altroot_cmd(altroot, argc, argv); 1657d62bc4baSyz147064 1658d62bc4baSyz147064 for (n = 0; n < ndev; n++) { 16594ac67f02SAnurag S. Maskey if ((status = dladm_dev2linkid(handle, devs[n], 16604ac67f02SAnurag S. Maskey &(port[n].lp_linkid))) != DLADM_STATUS_OK) { 16614ac67f02SAnurag S. Maskey die_dlerr(status, "invalid <dev> '%s'", devs[n]); 1662d62bc4baSyz147064 } 1663d62bc4baSyz147064 } 1664d62bc4baSyz147064 1665d62bc4baSyz147064 for (n = 0; n < nlink; n++) { 16664ac67f02SAnurag S. Maskey if ((status = dladm_name2info(handle, links[n], 16674ac67f02SAnurag S. Maskey &port[n + ndev].lp_linkid, NULL, NULL, NULL)) != 16684ac67f02SAnurag S. Maskey DLADM_STATUS_OK) { 16694ac67f02SAnurag S. Maskey die_dlerr(status, "invalid <link> '%s'", links[n]); 1670d62bc4baSyz147064 } 1671d62bc4baSyz147064 } 1672d62bc4baSyz147064 16734ac67f02SAnurag S. Maskey status = dladm_aggr_remove(handle, linkid, ndev + nlink, port, flags); 1674d62bc4baSyz147064 done: 1675f595a68aSyz147064 if (status != DLADM_STATUS_OK) 1676f595a68aSyz147064 die_dlerr(status, "remove operation failed"); 16777c478bd9Sstevel@tonic-gate } 16787c478bd9Sstevel@tonic-gate 16797c478bd9Sstevel@tonic-gate static void 16808d5c46e6Sam223141 do_modify_aggr(int argc, char *argv[], const char *use) 16817c478bd9Sstevel@tonic-gate { 16827c478bd9Sstevel@tonic-gate char option; 16837c478bd9Sstevel@tonic-gate uint32_t policy = AGGR_POLICY_L4; 16847c478bd9Sstevel@tonic-gate aggr_lacp_mode_t lacp_mode = AGGR_LACP_OFF; 16857c478bd9Sstevel@tonic-gate aggr_lacp_timer_t lacp_timer = AGGR_LACP_TIMER_SHORT; 16867c478bd9Sstevel@tonic-gate uint8_t mac_addr[ETHERADDRL]; 16877c478bd9Sstevel@tonic-gate boolean_t mac_addr_fixed = B_FALSE; 16887c478bd9Sstevel@tonic-gate uint8_t modify_mask = 0; 16897c478bd9Sstevel@tonic-gate char *altroot = NULL; 1690d62bc4baSyz147064 uint32_t flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST; 1691d62bc4baSyz147064 datalink_id_t linkid; 1692f595a68aSyz147064 dladm_status_t status; 16937c478bd9Sstevel@tonic-gate 16947c478bd9Sstevel@tonic-gate opterr = 0; 1695d62bc4baSyz147064 while ((option = getopt_long(argc, argv, ":L:l:P:R:tu:T:", lopts, 16967c478bd9Sstevel@tonic-gate NULL)) != -1) { 16977c478bd9Sstevel@tonic-gate switch (option) { 16987c478bd9Sstevel@tonic-gate case 'P': 1699f595a68aSyz147064 if (modify_mask & DLADM_AGGR_MODIFY_POLICY) 170033343a97Smeem die_optdup(option); 17017c478bd9Sstevel@tonic-gate 1702f595a68aSyz147064 modify_mask |= DLADM_AGGR_MODIFY_POLICY; 17037c478bd9Sstevel@tonic-gate 1704f595a68aSyz147064 if (!dladm_aggr_str2policy(optarg, &policy)) 170533343a97Smeem die("invalid policy '%s'", optarg); 17067c478bd9Sstevel@tonic-gate break; 17077c478bd9Sstevel@tonic-gate case 'u': 1708f595a68aSyz147064 if (modify_mask & DLADM_AGGR_MODIFY_MAC) 170933343a97Smeem die_optdup(option); 17107c478bd9Sstevel@tonic-gate 1711f595a68aSyz147064 modify_mask |= DLADM_AGGR_MODIFY_MAC; 17127c478bd9Sstevel@tonic-gate 1713f595a68aSyz147064 if (!dladm_aggr_str2macaddr(optarg, &mac_addr_fixed, 171433343a97Smeem mac_addr)) 171533343a97Smeem die("invalid MAC address '%s'", optarg); 17167c478bd9Sstevel@tonic-gate break; 17177c478bd9Sstevel@tonic-gate case 'l': 1718d62bc4baSyz147064 case 'L': 1719f595a68aSyz147064 if (modify_mask & DLADM_AGGR_MODIFY_LACP_MODE) 172033343a97Smeem die_optdup(option); 17217c478bd9Sstevel@tonic-gate 1722f595a68aSyz147064 modify_mask |= DLADM_AGGR_MODIFY_LACP_MODE; 17237c478bd9Sstevel@tonic-gate 1724f595a68aSyz147064 if (!dladm_aggr_str2lacpmode(optarg, &lacp_mode)) 172533343a97Smeem die("invalid LACP mode '%s'", optarg); 17267c478bd9Sstevel@tonic-gate break; 17277c478bd9Sstevel@tonic-gate case 'T': 1728f595a68aSyz147064 if (modify_mask & DLADM_AGGR_MODIFY_LACP_TIMER) 172933343a97Smeem die_optdup(option); 17307c478bd9Sstevel@tonic-gate 1731f595a68aSyz147064 modify_mask |= DLADM_AGGR_MODIFY_LACP_TIMER; 17327c478bd9Sstevel@tonic-gate 1733f595a68aSyz147064 if (!dladm_aggr_str2lacptimer(optarg, &lacp_timer)) 173433343a97Smeem die("invalid LACP timer value '%s'", optarg); 17357c478bd9Sstevel@tonic-gate break; 17367c478bd9Sstevel@tonic-gate case 't': 1737d62bc4baSyz147064 flags &= ~DLADM_OPT_PERSIST; 17387c478bd9Sstevel@tonic-gate break; 17397c478bd9Sstevel@tonic-gate case 'R': 17407c478bd9Sstevel@tonic-gate altroot = optarg; 17417c478bd9Sstevel@tonic-gate break; 17427c478bd9Sstevel@tonic-gate default: 17438d5c46e6Sam223141 die_opterr(optopt, option, use); 174433343a97Smeem break; 17457c478bd9Sstevel@tonic-gate } 17467c478bd9Sstevel@tonic-gate } 17477c478bd9Sstevel@tonic-gate 174833343a97Smeem if (modify_mask == 0) 174933343a97Smeem die("at least one of the -PulT options must be specified"); 17507c478bd9Sstevel@tonic-gate 1751d62bc4baSyz147064 /* get key value or the aggregation name (required last argument) */ 17527c478bd9Sstevel@tonic-gate if (optind != (argc-1)) 17537c478bd9Sstevel@tonic-gate usage(); 17547c478bd9Sstevel@tonic-gate 1755d62bc4baSyz147064 status = i_dladm_aggr_get_linkid(altroot, argv[optind], &linkid, flags); 1756d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 1757d62bc4baSyz147064 goto done; 17587c478bd9Sstevel@tonic-gate 1759d62bc4baSyz147064 if (altroot != NULL) 1760d62bc4baSyz147064 altroot_cmd(altroot, argc, argv); 1761d62bc4baSyz147064 17624ac67f02SAnurag S. Maskey status = dladm_aggr_modify(handle, linkid, modify_mask, policy, 17634ac67f02SAnurag S. Maskey mac_addr_fixed, (const uchar_t *)mac_addr, lacp_mode, lacp_timer, 17644ac67f02SAnurag S. Maskey flags); 1765d62bc4baSyz147064 1766d62bc4baSyz147064 done: 1767f595a68aSyz147064 if (status != DLADM_STATUS_OK) 1768f595a68aSyz147064 die_dlerr(status, "modify operation failed"); 17697c478bd9Sstevel@tonic-gate } 17707c478bd9Sstevel@tonic-gate 17718d5c46e6Sam223141 /*ARGSUSED*/ 17727c478bd9Sstevel@tonic-gate static void 17738d5c46e6Sam223141 do_up_aggr(int argc, char *argv[], const char *use) 17747c478bd9Sstevel@tonic-gate { 1775d62bc4baSyz147064 datalink_id_t linkid = DATALINK_ALL_LINKID; 1776f595a68aSyz147064 dladm_status_t status; 17777c478bd9Sstevel@tonic-gate 1778d62bc4baSyz147064 /* 1779d62bc4baSyz147064 * get the key or the name of the aggregation (optional last argument) 1780d62bc4baSyz147064 */ 17817c478bd9Sstevel@tonic-gate if (argc == 2) { 1782d62bc4baSyz147064 if ((status = i_dladm_aggr_get_linkid(NULL, argv[1], &linkid, 17834ac67f02SAnurag S. Maskey DLADM_OPT_PERSIST)) != DLADM_STATUS_OK) 1784d62bc4baSyz147064 goto done; 17857c478bd9Sstevel@tonic-gate } else if (argc > 2) { 17867c478bd9Sstevel@tonic-gate usage(); 17877c478bd9Sstevel@tonic-gate } 17887c478bd9Sstevel@tonic-gate 17894ac67f02SAnurag S. Maskey status = dladm_aggr_up(handle, linkid); 1790d62bc4baSyz147064 done: 1791d62bc4baSyz147064 if (status != DLADM_STATUS_OK) { 1792d62bc4baSyz147064 if (argc == 2) { 1793d62bc4baSyz147064 die_dlerr(status, 1794d62bc4baSyz147064 "could not bring up aggregation '%s'", argv[1]); 17957c478bd9Sstevel@tonic-gate } else { 1796f595a68aSyz147064 die_dlerr(status, "could not bring aggregations up"); 17977c478bd9Sstevel@tonic-gate } 17987c478bd9Sstevel@tonic-gate } 17997c478bd9Sstevel@tonic-gate } 18007c478bd9Sstevel@tonic-gate 18017c478bd9Sstevel@tonic-gate static void 18028d5c46e6Sam223141 do_create_vlan(int argc, char *argv[], const char *use) 18037c478bd9Sstevel@tonic-gate { 1804d62bc4baSyz147064 char *link = NULL; 1805d62bc4baSyz147064 char drv[DLPI_LINKNAME_MAX]; 1806d62bc4baSyz147064 uint_t ppa; 1807d62bc4baSyz147064 datalink_id_t linkid; 1808da14cebeSEric Cheng datalink_id_t dev_linkid; 1809d62bc4baSyz147064 int vid = 0; 1810d62bc4baSyz147064 char option; 1811d62bc4baSyz147064 uint32_t flags = (DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST); 1812d62bc4baSyz147064 char *altroot = NULL; 1813d62bc4baSyz147064 char vlan[MAXLINKNAMELEN]; 181463a6526dSMichael Lim char propstr[DLADM_STRSIZE]; 1815da14cebeSEric Cheng dladm_arg_list_t *proplist = NULL; 1816f595a68aSyz147064 dladm_status_t status; 18177c478bd9Sstevel@tonic-gate 1818d62bc4baSyz147064 opterr = 0; 181963a6526dSMichael Lim bzero(propstr, DLADM_STRSIZE); 182063a6526dSMichael Lim 1821da14cebeSEric Cheng while ((option = getopt_long(argc, argv, ":tfR:l:v:p:", 1822d62bc4baSyz147064 lopts, NULL)) != -1) { 1823d62bc4baSyz147064 switch (option) { 1824d62bc4baSyz147064 case 'v': 1825d62bc4baSyz147064 if (vid != 0) 1826d62bc4baSyz147064 die_optdup(option); 1827d62bc4baSyz147064 1828d62bc4baSyz147064 if (!str2int(optarg, &vid) || vid < 1 || vid > 4094) 1829d62bc4baSyz147064 die("invalid VLAN identifier '%s'", optarg); 1830d62bc4baSyz147064 1831d62bc4baSyz147064 break; 1832d62bc4baSyz147064 case 'l': 1833d62bc4baSyz147064 if (link != NULL) 1834d62bc4baSyz147064 die_optdup(option); 1835d62bc4baSyz147064 1836d62bc4baSyz147064 link = optarg; 1837d62bc4baSyz147064 break; 1838d62bc4baSyz147064 case 't': 1839d62bc4baSyz147064 flags &= ~DLADM_OPT_PERSIST; 1840d62bc4baSyz147064 break; 1841d62bc4baSyz147064 case 'R': 1842d62bc4baSyz147064 altroot = optarg; 1843d62bc4baSyz147064 break; 1844da14cebeSEric Cheng case 'p': 184563a6526dSMichael Lim (void) strlcat(propstr, optarg, DLADM_STRSIZE); 184663a6526dSMichael Lim if (strlcat(propstr, ",", DLADM_STRSIZE) >= 184763a6526dSMichael Lim DLADM_STRSIZE) 184863a6526dSMichael Lim die("property list too long '%s'", propstr); 1849da14cebeSEric Cheng break; 1850da14cebeSEric Cheng case 'f': 1851da14cebeSEric Cheng flags |= DLADM_OPT_FORCE; 1852da14cebeSEric Cheng break; 1853d62bc4baSyz147064 default: 18548d5c46e6Sam223141 die_opterr(optopt, option, use); 1855d62bc4baSyz147064 break; 1856d62bc4baSyz147064 } 1857d62bc4baSyz147064 } 1858d62bc4baSyz147064 1859d62bc4baSyz147064 /* get vlan name if there is any */ 1860d62bc4baSyz147064 if ((vid == 0) || (link == NULL) || (argc - optind > 1)) 18617c478bd9Sstevel@tonic-gate usage(); 1862d62bc4baSyz147064 1863d62bc4baSyz147064 if (optind == (argc - 1)) { 1864d62bc4baSyz147064 if (strlcpy(vlan, argv[optind], MAXLINKNAMELEN) >= 1865d62bc4baSyz147064 MAXLINKNAMELEN) { 1866d62bc4baSyz147064 die("vlan name too long '%s'", argv[optind]); 1867d62bc4baSyz147064 } 1868d62bc4baSyz147064 } else { 1869d62bc4baSyz147064 if ((dlpi_parselink(link, drv, &ppa) != DLPI_SUCCESS) || 1870d62bc4baSyz147064 (ppa >= 1000) || 1871d62bc4baSyz147064 (dlpi_makelink(vlan, drv, vid * 1000 + ppa) != 1872d62bc4baSyz147064 DLPI_SUCCESS)) { 1873d62bc4baSyz147064 die("invalid link name '%s'", link); 1874d62bc4baSyz147064 } 18757c478bd9Sstevel@tonic-gate } 18767c478bd9Sstevel@tonic-gate 1877d62bc4baSyz147064 if (altroot != NULL) 1878d62bc4baSyz147064 altroot_cmd(altroot, argc, argv); 1879d62bc4baSyz147064 18804ac67f02SAnurag S. Maskey if (dladm_name2info(handle, link, &dev_linkid, NULL, NULL, NULL) != 1881d62bc4baSyz147064 DLADM_STATUS_OK) { 1882d62bc4baSyz147064 die("invalid link name '%s'", link); 1883d62bc4baSyz147064 } 1884d62bc4baSyz147064 188563a6526dSMichael Lim if (dladm_parse_link_props(propstr, &proplist, B_FALSE) 188663a6526dSMichael Lim != DLADM_STATUS_OK) 188763a6526dSMichael Lim die("invalid vlan property"); 188863a6526dSMichael Lim 18894ac67f02SAnurag S. Maskey if ((status = dladm_vlan_create(handle, vlan, dev_linkid, vid, proplist, 18904ac67f02SAnurag S. Maskey flags, &linkid)) != DLADM_STATUS_OK) { 1891da14cebeSEric Cheng die_dlerr(status, "create operation over %s failed", link); 1892d62bc4baSyz147064 } 1893d62bc4baSyz147064 } 1894d62bc4baSyz147064 1895d62bc4baSyz147064 static void 18968d5c46e6Sam223141 do_delete_vlan(int argc, char *argv[], const char *use) 1897d62bc4baSyz147064 { 1898d62bc4baSyz147064 char option; 1899d62bc4baSyz147064 uint32_t flags = (DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST); 1900d62bc4baSyz147064 char *altroot = NULL; 1901d62bc4baSyz147064 datalink_id_t linkid; 1902d62bc4baSyz147064 dladm_status_t status; 1903d62bc4baSyz147064 1904d62bc4baSyz147064 opterr = 0; 1905d62bc4baSyz147064 while ((option = getopt_long(argc, argv, ":R:t", lopts, NULL)) != -1) { 1906d62bc4baSyz147064 switch (option) { 1907d62bc4baSyz147064 case 't': 1908d62bc4baSyz147064 flags &= ~DLADM_OPT_PERSIST; 1909d62bc4baSyz147064 break; 1910d62bc4baSyz147064 case 'R': 1911d62bc4baSyz147064 altroot = optarg; 1912d62bc4baSyz147064 break; 1913d62bc4baSyz147064 default: 19148d5c46e6Sam223141 die_opterr(optopt, option, use); 1915d62bc4baSyz147064 break; 1916d62bc4baSyz147064 } 1917d62bc4baSyz147064 } 1918d62bc4baSyz147064 1919d62bc4baSyz147064 /* get VLAN link name (required last argument) */ 1920d62bc4baSyz147064 if (optind != (argc - 1)) 1921d62bc4baSyz147064 usage(); 1922d62bc4baSyz147064 1923d62bc4baSyz147064 if (altroot != NULL) 1924d62bc4baSyz147064 altroot_cmd(altroot, argc, argv); 1925d62bc4baSyz147064 19264ac67f02SAnurag S. Maskey status = dladm_name2info(handle, argv[optind], &linkid, NULL, NULL, 19274ac67f02SAnurag S. Maskey NULL); 1928d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 1929d62bc4baSyz147064 goto done; 1930d62bc4baSyz147064 19314ac67f02SAnurag S. Maskey status = dladm_vlan_delete(handle, linkid, flags); 1932d62bc4baSyz147064 done: 1933d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 1934d62bc4baSyz147064 die_dlerr(status, "delete operation failed"); 1935d62bc4baSyz147064 } 1936d62bc4baSyz147064 19378d5c46e6Sam223141 /*ARGSUSED*/ 1938d62bc4baSyz147064 static void 19398d5c46e6Sam223141 do_up_vlan(int argc, char *argv[], const char *use) 1940d62bc4baSyz147064 { 1941da14cebeSEric Cheng do_up_vnic_common(argc, argv, use, B_TRUE); 19427c478bd9Sstevel@tonic-gate } 19437c478bd9Sstevel@tonic-gate 1944210db224Sericheng static void 19458d5c46e6Sam223141 do_rename_link(int argc, char *argv[], const char *use) 1946210db224Sericheng { 1947d62bc4baSyz147064 char option; 1948d62bc4baSyz147064 char *link1, *link2; 1949d62bc4baSyz147064 char *altroot = NULL; 1950d62bc4baSyz147064 dladm_status_t status; 1951210db224Sericheng 1952d62bc4baSyz147064 opterr = 0; 1953d62bc4baSyz147064 while ((option = getopt_long(argc, argv, ":R:", lopts, NULL)) != -1) { 1954d62bc4baSyz147064 switch (option) { 1955d62bc4baSyz147064 case 'R': 1956d62bc4baSyz147064 altroot = optarg; 1957d62bc4baSyz147064 break; 1958d62bc4baSyz147064 default: 19598d5c46e6Sam223141 die_opterr(optopt, option, use); 1960d62bc4baSyz147064 break; 1961210db224Sericheng } 1962210db224Sericheng } 1963210db224Sericheng 1964d62bc4baSyz147064 /* get link1 and link2 name (required the last 2 arguments) */ 1965d62bc4baSyz147064 if (optind != (argc - 2)) 1966d62bc4baSyz147064 usage(); 1967d62bc4baSyz147064 1968d62bc4baSyz147064 if (altroot != NULL) 1969d62bc4baSyz147064 altroot_cmd(altroot, argc, argv); 1970d62bc4baSyz147064 1971d62bc4baSyz147064 link1 = argv[optind++]; 1972d62bc4baSyz147064 link2 = argv[optind]; 19734ac67f02SAnurag S. Maskey if ((status = dladm_rename_link(handle, link1, link2)) != 19744ac67f02SAnurag S. Maskey DLADM_STATUS_OK) 1975d62bc4baSyz147064 die_dlerr(status, "rename operation failed"); 1976d62bc4baSyz147064 } 1977d62bc4baSyz147064 19788d5c46e6Sam223141 /*ARGSUSED*/ 1979d62bc4baSyz147064 static void 19808d5c46e6Sam223141 do_delete_phys(int argc, char *argv[], const char *use) 1981d62bc4baSyz147064 { 1982d62bc4baSyz147064 datalink_id_t linkid = DATALINK_ALL_LINKID; 1983d62bc4baSyz147064 dladm_status_t status; 1984d62bc4baSyz147064 1985d62bc4baSyz147064 /* get link name (required the last argument) */ 1986d62bc4baSyz147064 if (argc > 2) 1987d62bc4baSyz147064 usage(); 1988d62bc4baSyz147064 1989d62bc4baSyz147064 if (argc == 2) { 19904ac67f02SAnurag S. Maskey if ((status = dladm_name2info(handle, argv[1], &linkid, NULL, 19914ac67f02SAnurag S. Maskey NULL, NULL)) != DLADM_STATUS_OK) 1992d62bc4baSyz147064 die_dlerr(status, "cannot delete '%s'", argv[1]); 1993d62bc4baSyz147064 } 1994d62bc4baSyz147064 19954ac67f02SAnurag S. Maskey if ((status = dladm_phys_delete(handle, linkid)) != DLADM_STATUS_OK) { 1996d62bc4baSyz147064 if (argc == 2) 1997d62bc4baSyz147064 die_dlerr(status, "cannot delete '%s'", argv[1]); 1998d62bc4baSyz147064 else 1999d62bc4baSyz147064 die_dlerr(status, "delete operation failed"); 2000d62bc4baSyz147064 } 2001d62bc4baSyz147064 } 2002d62bc4baSyz147064 2003d62bc4baSyz147064 /*ARGSUSED*/ 2004210db224Sericheng static int 20054ac67f02SAnurag S. Maskey i_dladm_walk_linkmap(dladm_handle_t dh, datalink_id_t linkid, void *arg) 2006210db224Sericheng { 2007d62bc4baSyz147064 char name[MAXLINKNAMELEN]; 2008d62bc4baSyz147064 char mediabuf[DLADM_STRSIZE]; 2009d62bc4baSyz147064 char classbuf[DLADM_STRSIZE]; 2010d62bc4baSyz147064 datalink_class_t class; 2011d62bc4baSyz147064 uint32_t media; 2012d62bc4baSyz147064 uint32_t flags; 2013210db224Sericheng 20144ac67f02SAnurag S. Maskey if (dladm_datalink_id2info(dh, linkid, &flags, &class, &media, name, 2015d62bc4baSyz147064 MAXLINKNAMELEN) == DLADM_STATUS_OK) { 2016d62bc4baSyz147064 (void) dladm_class2str(class, classbuf); 2017d62bc4baSyz147064 (void) dladm_media2str(media, mediabuf); 2018d62bc4baSyz147064 (void) printf("%-12s%8d %-12s%-20s %6d\n", name, 2019d62bc4baSyz147064 linkid, classbuf, mediabuf, flags); 2020210db224Sericheng } 2021d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 2022210db224Sericheng } 20237c478bd9Sstevel@tonic-gate 20247c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 20257c478bd9Sstevel@tonic-gate static void 20268d5c46e6Sam223141 do_show_linkmap(int argc, char *argv[], const char *use) 20277c478bd9Sstevel@tonic-gate { 2028d62bc4baSyz147064 if (argc != 1) 2029d62bc4baSyz147064 die("invalid arguments"); 20307c478bd9Sstevel@tonic-gate 2031d62bc4baSyz147064 (void) printf("%-12s%8s %-12s%-20s %6s\n", "NAME", "LINKID", 2032d62bc4baSyz147064 "CLASS", "MEDIA", "FLAGS"); 20334ac67f02SAnurag S. Maskey 20344ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(i_dladm_walk_linkmap, handle, NULL, 2035d62bc4baSyz147064 DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE, 2036d62bc4baSyz147064 DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST); 20377c478bd9Sstevel@tonic-gate } 2038d62bc4baSyz147064 2039d62bc4baSyz147064 /* 2040d62bc4baSyz147064 * Delete inactive physical links. 2041d62bc4baSyz147064 */ 2042d62bc4baSyz147064 /*ARGSUSED*/ 2043d62bc4baSyz147064 static int 20444ac67f02SAnurag S. Maskey purge_phys(dladm_handle_t dh, datalink_id_t linkid, void *arg) 2045d62bc4baSyz147064 { 2046d62bc4baSyz147064 datalink_class_t class; 2047d62bc4baSyz147064 uint32_t flags; 2048d62bc4baSyz147064 20494ac67f02SAnurag S. Maskey if (dladm_datalink_id2info(dh, linkid, &flags, &class, NULL, NULL, 0) 20504ac67f02SAnurag S. Maskey != DLADM_STATUS_OK) { 2051d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 2052d62bc4baSyz147064 } 2053d62bc4baSyz147064 2054d62bc4baSyz147064 if (class == DATALINK_CLASS_PHYS && !(flags & DLADM_OPT_ACTIVE)) 20554ac67f02SAnurag S. Maskey (void) dladm_phys_delete(dh, linkid); 2056d62bc4baSyz147064 2057d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 2058d62bc4baSyz147064 } 2059d62bc4baSyz147064 2060d62bc4baSyz147064 /*ARGSUSED*/ 2061d62bc4baSyz147064 static void 20628d5c46e6Sam223141 do_init_phys(int argc, char *argv[], const char *use) 2063d62bc4baSyz147064 { 2064d62bc4baSyz147064 di_node_t devtree; 2065d62bc4baSyz147064 2066d62bc4baSyz147064 if (argc > 1) 2067d62bc4baSyz147064 usage(); 2068d62bc4baSyz147064 2069d62bc4baSyz147064 /* 2070d62bc4baSyz147064 * Force all the devices to attach, therefore all the network physical 2071d62bc4baSyz147064 * devices can be known to the dlmgmtd daemon. 2072d62bc4baSyz147064 */ 2073d62bc4baSyz147064 if ((devtree = di_init("/", DINFOFORCE | DINFOSUBTREE)) != DI_NODE_NIL) 2074d62bc4baSyz147064 di_fini(devtree); 2075d62bc4baSyz147064 20764ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(purge_phys, handle, NULL, 2077d62bc4baSyz147064 DATALINK_CLASS_PHYS, DATALINK_ANY_MEDIATYPE, DLADM_OPT_PERSIST); 20787c478bd9Sstevel@tonic-gate } 20797c478bd9Sstevel@tonic-gate 2080d62bc4baSyz147064 2081d62bc4baSyz147064 /* 2082d62bc4baSyz147064 * Print the active topology information. 2083d62bc4baSyz147064 */ 2084d62bc4baSyz147064 static dladm_status_t 2085d62bc4baSyz147064 print_link_topology(show_state_t *state, datalink_id_t linkid, 2086e7801d59Ssowmini datalink_class_t class, link_fields_buf_t *lbuf) 2087d62bc4baSyz147064 { 2088d62bc4baSyz147064 uint32_t flags = state->ls_flags; 2089d62bc4baSyz147064 dladm_status_t status = DLADM_STATUS_OK; 20906b9e797cSsowmini char tmpbuf[MAXLINKNAMELEN]; 2091d62bc4baSyz147064 2092e7801d59Ssowmini (void) sprintf(lbuf->link_over, ""); 2093d62bc4baSyz147064 if (class == DATALINK_CLASS_VLAN) { 2094d62bc4baSyz147064 dladm_vlan_attr_t vinfo; 2095d62bc4baSyz147064 20964ac67f02SAnurag S. Maskey status = dladm_vlan_info(handle, linkid, &vinfo, flags); 2097d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 2098d62bc4baSyz147064 goto done; 20994ac67f02SAnurag S. Maskey status = dladm_datalink_id2info(handle, vinfo.dv_linkid, NULL, 21004ac67f02SAnurag S. Maskey NULL, NULL, lbuf->link_over, sizeof (lbuf->link_over)); 2101d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 2102d62bc4baSyz147064 goto done; 2103d62bc4baSyz147064 } else if (class == DATALINK_CLASS_AGGR) { 2104d62bc4baSyz147064 dladm_aggr_grp_attr_t ginfo; 2105d62bc4baSyz147064 int i; 2106d62bc4baSyz147064 21076b9e797cSsowmini (void) sprintf(lbuf->link_over, ""); 21086b9e797cSsowmini 21094ac67f02SAnurag S. Maskey status = dladm_aggr_info(handle, linkid, &ginfo, flags); 2110d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 2111d62bc4baSyz147064 goto done; 2112d62bc4baSyz147064 2113d62bc4baSyz147064 if (ginfo.lg_nports == 0) { 2114d62bc4baSyz147064 status = DLADM_STATUS_BADVAL; 2115d62bc4baSyz147064 goto done; 2116d62bc4baSyz147064 } 2117d62bc4baSyz147064 for (i = 0; i < ginfo.lg_nports; i++) { 21184ac67f02SAnurag S. Maskey status = dladm_datalink_id2info(handle, 2119e7801d59Ssowmini ginfo.lg_ports[i].lp_linkid, NULL, NULL, NULL, 21206b9e797cSsowmini tmpbuf, sizeof (tmpbuf)); 2121d62bc4baSyz147064 if (status != DLADM_STATUS_OK) { 2122d62bc4baSyz147064 free(ginfo.lg_ports); 2123d62bc4baSyz147064 goto done; 2124d62bc4baSyz147064 } 21256b9e797cSsowmini (void) strlcat(lbuf->link_over, tmpbuf, 21266b9e797cSsowmini sizeof (lbuf->link_over)); 21276b9e797cSsowmini if (i != (ginfo.lg_nports - 1)) { 21286b9e797cSsowmini (void) strlcat(lbuf->link_over, " ", 21296b9e797cSsowmini sizeof (lbuf->link_over)); 21306b9e797cSsowmini } 2131d62bc4baSyz147064 } 2132d62bc4baSyz147064 free(ginfo.lg_ports); 2133d62bc4baSyz147064 } else if (class == DATALINK_CLASS_VNIC) { 2134da14cebeSEric Cheng dladm_vnic_attr_t vinfo; 2135d62bc4baSyz147064 21364ac67f02SAnurag S. Maskey if ((status = dladm_vnic_info(handle, linkid, &vinfo, flags)) != 21374ac67f02SAnurag S. Maskey DLADM_STATUS_OK || 21384ac67f02SAnurag S. Maskey (status = dladm_datalink_id2info(handle, vinfo.va_link_id, 21394ac67f02SAnurag S. Maskey NULL, NULL, NULL, lbuf->link_over, 2140e7801d59Ssowmini sizeof (lbuf->link_over)) != DLADM_STATUS_OK)) { 2141d62bc4baSyz147064 goto done; 2142d62bc4baSyz147064 } 2143d62bc4baSyz147064 } 2144d62bc4baSyz147064 done: 2145d62bc4baSyz147064 return (status); 2146d62bc4baSyz147064 } 2147d62bc4baSyz147064 2148d62bc4baSyz147064 static dladm_status_t 2149e7801d59Ssowmini print_link(show_state_t *state, datalink_id_t linkid, link_fields_buf_t *lbuf) 2150d62bc4baSyz147064 { 2151d62bc4baSyz147064 char link[MAXLINKNAMELEN]; 2152d62bc4baSyz147064 datalink_class_t class; 2153d62bc4baSyz147064 uint_t mtu; 2154d62bc4baSyz147064 uint32_t flags; 2155d62bc4baSyz147064 dladm_status_t status; 2156d62bc4baSyz147064 21574ac67f02SAnurag S. Maskey if ((status = dladm_datalink_id2info(handle, linkid, &flags, &class, 21584ac67f02SAnurag S. Maskey NULL, link, sizeof (link))) != DLADM_STATUS_OK) { 2159d62bc4baSyz147064 goto done; 2160d62bc4baSyz147064 } 2161d62bc4baSyz147064 2162d62bc4baSyz147064 if (!(state->ls_flags & flags)) { 2163d62bc4baSyz147064 status = DLADM_STATUS_NOTFOUND; 2164d62bc4baSyz147064 goto done; 2165d62bc4baSyz147064 } 2166d62bc4baSyz147064 2167d62bc4baSyz147064 if (state->ls_flags == DLADM_OPT_ACTIVE) { 2168d62bc4baSyz147064 dladm_attr_t dlattr; 2169d62bc4baSyz147064 2170d62bc4baSyz147064 if (class == DATALINK_CLASS_PHYS) { 2171d62bc4baSyz147064 dladm_phys_attr_t dpa; 2172d62bc4baSyz147064 dlpi_handle_t dh; 2173d62bc4baSyz147064 dlpi_info_t dlinfo; 2174d62bc4baSyz147064 21754ac67f02SAnurag S. Maskey if ((status = dladm_phys_info(handle, linkid, &dpa, 2176d62bc4baSyz147064 DLADM_OPT_ACTIVE)) != DLADM_STATUS_OK) { 2177d62bc4baSyz147064 goto done; 2178d62bc4baSyz147064 } 2179d62bc4baSyz147064 2180d62bc4baSyz147064 if (!dpa.dp_novanity) 2181d62bc4baSyz147064 goto link_mtu; 2182d62bc4baSyz147064 2183d62bc4baSyz147064 /* 2184d62bc4baSyz147064 * This is a physical link that does not have 2185d62bc4baSyz147064 * vanity naming support. 2186d62bc4baSyz147064 */ 2187d62bc4baSyz147064 if (dlpi_open(dpa.dp_dev, &dh, DLPI_DEVONLY) != 2188d62bc4baSyz147064 DLPI_SUCCESS) { 2189d62bc4baSyz147064 status = DLADM_STATUS_NOTFOUND; 2190d62bc4baSyz147064 goto done; 2191d62bc4baSyz147064 } 2192d62bc4baSyz147064 2193d62bc4baSyz147064 if (dlpi_info(dh, &dlinfo, 0) != DLPI_SUCCESS) { 2194d62bc4baSyz147064 dlpi_close(dh); 2195d62bc4baSyz147064 status = DLADM_STATUS_BADARG; 2196d62bc4baSyz147064 goto done; 2197d62bc4baSyz147064 } 2198d62bc4baSyz147064 2199d62bc4baSyz147064 dlpi_close(dh); 2200d62bc4baSyz147064 mtu = dlinfo.di_max_sdu; 2201d62bc4baSyz147064 } else { 2202d62bc4baSyz147064 link_mtu: 22034ac67f02SAnurag S. Maskey status = dladm_info(handle, linkid, &dlattr); 2204d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 2205d62bc4baSyz147064 goto done; 2206d62bc4baSyz147064 mtu = dlattr.da_max_sdu; 2207d62bc4baSyz147064 } 2208d62bc4baSyz147064 } 2209d62bc4baSyz147064 2210e7801d59Ssowmini (void) snprintf(lbuf->link_name, sizeof (lbuf->link_name), 2211e7801d59Ssowmini "%s", link); 2212e7801d59Ssowmini (void) dladm_class2str(class, lbuf->link_class); 2213d62bc4baSyz147064 if (state->ls_flags == DLADM_OPT_ACTIVE) { 2214e7801d59Ssowmini (void) snprintf(lbuf->link_mtu, sizeof (lbuf->link_mtu), 2215c08e5e1aSdr146992 "%u", mtu); 2216e7801d59Ssowmini (void) get_linkstate(link, B_TRUE, lbuf->link_state); 2217d62bc4baSyz147064 } 2218d62bc4baSyz147064 2219e7801d59Ssowmini status = print_link_topology(state, linkid, class, lbuf); 2220d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 2221d62bc4baSyz147064 goto done; 2222d62bc4baSyz147064 2223d62bc4baSyz147064 done: 2224d62bc4baSyz147064 return (status); 2225d62bc4baSyz147064 } 2226d62bc4baSyz147064 22274ac67f02SAnurag S. Maskey /* ARGSUSED */ 2228d62bc4baSyz147064 static int 22294ac67f02SAnurag S. Maskey show_link(dladm_handle_t dh, datalink_id_t linkid, void *arg) 2230d62bc4baSyz147064 { 2231e7801d59Ssowmini show_state_t *state = (show_state_t *)arg; 2232d62bc4baSyz147064 dladm_status_t status; 2233e7801d59Ssowmini link_fields_buf_t lbuf; 2234d62bc4baSyz147064 2235e7801d59Ssowmini /* 2236e7801d59Ssowmini * first get all the link attributes into lbuf; 2237e7801d59Ssowmini */ 22385f5c9f54SAnurag S. Maskey bzero(&lbuf, sizeof (link_fields_buf_t)); 2239e7801d59Ssowmini status = print_link(state, linkid, &lbuf); 2240e7801d59Ssowmini 2241d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 2242d62bc4baSyz147064 goto done; 2243e7801d59Ssowmini 2244*8002d411SSowmini Varadhan ofmt_print(state->ls_ofmt, &lbuf); 2245d62bc4baSyz147064 2246d62bc4baSyz147064 done: 2247d62bc4baSyz147064 state->ls_status = status; 2248d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 2249d62bc4baSyz147064 } 2250d62bc4baSyz147064 2251*8002d411SSowmini Varadhan static boolean_t 2252*8002d411SSowmini Varadhan print_link_stats_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize) 2253ae6aa22aSVenugopal Iyer { 2254*8002d411SSowmini Varadhan link_args_t *largs = ofarg->ofmt_cbarg; 2255ae6aa22aSVenugopal Iyer pktsum_t *diff_stats = largs->link_s_psum; 2256ae6aa22aSVenugopal Iyer 2257*8002d411SSowmini Varadhan switch (ofarg->ofmt_id) { 2258ae6aa22aSVenugopal Iyer case LINK_S_LINK: 2259*8002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%s", largs->link_s_link); 2260ae6aa22aSVenugopal Iyer break; 2261ae6aa22aSVenugopal Iyer case LINK_S_IPKTS: 2262*8002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%llu", diff_stats->ipackets); 2263ae6aa22aSVenugopal Iyer break; 2264ae6aa22aSVenugopal Iyer case LINK_S_RBYTES: 2265*8002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%llu", diff_stats->rbytes); 2266ae6aa22aSVenugopal Iyer break; 2267ae6aa22aSVenugopal Iyer case LINK_S_IERRORS: 2268*8002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%u", diff_stats->ierrors); 2269ae6aa22aSVenugopal Iyer break; 2270ae6aa22aSVenugopal Iyer case LINK_S_OPKTS: 2271*8002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%llu", diff_stats->opackets); 2272ae6aa22aSVenugopal Iyer break; 2273ae6aa22aSVenugopal Iyer case LINK_S_OBYTES: 2274*8002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%llu", diff_stats->obytes); 2275ae6aa22aSVenugopal Iyer break; 2276ae6aa22aSVenugopal Iyer case LINK_S_OERRORS: 2277*8002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%u", diff_stats->oerrors); 2278ae6aa22aSVenugopal Iyer break; 2279ae6aa22aSVenugopal Iyer default: 2280ae6aa22aSVenugopal Iyer die("invalid input"); 2281ae6aa22aSVenugopal Iyer break; 2282ae6aa22aSVenugopal Iyer } 2283*8002d411SSowmini Varadhan return (B_TRUE); 2284ae6aa22aSVenugopal Iyer } 2285ae6aa22aSVenugopal Iyer 2286d62bc4baSyz147064 static int 22874ac67f02SAnurag S. Maskey show_link_stats(dladm_handle_t dh, datalink_id_t linkid, void *arg) 2288d62bc4baSyz147064 { 2289e7801d59Ssowmini char link[DLPI_LINKNAME_MAX]; 2290d62bc4baSyz147064 datalink_class_t class; 2291e7801d59Ssowmini show_state_t *state = (show_state_t *)arg; 22927c478bd9Sstevel@tonic-gate pktsum_t stats, diff_stats; 2293d62bc4baSyz147064 dladm_phys_attr_t dpa; 2294ae6aa22aSVenugopal Iyer link_args_t largs; 22957c478bd9Sstevel@tonic-gate 22967c478bd9Sstevel@tonic-gate if (state->ls_firstonly) { 22977c478bd9Sstevel@tonic-gate if (state->ls_donefirst) 2298d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 22997c478bd9Sstevel@tonic-gate state->ls_donefirst = B_TRUE; 23007c478bd9Sstevel@tonic-gate } else { 23017c478bd9Sstevel@tonic-gate bzero(&state->ls_prevstats, sizeof (state->ls_prevstats)); 23027c478bd9Sstevel@tonic-gate } 23037c478bd9Sstevel@tonic-gate 23044ac67f02SAnurag S. Maskey if (dladm_datalink_id2info(dh, linkid, NULL, &class, NULL, link, 2305e7801d59Ssowmini DLPI_LINKNAME_MAX) != DLADM_STATUS_OK) { 2306d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 2307d62bc4baSyz147064 } 2308d62bc4baSyz147064 2309d62bc4baSyz147064 if (class == DATALINK_CLASS_PHYS) { 23104ac67f02SAnurag S. Maskey if (dladm_phys_info(dh, linkid, &dpa, DLADM_OPT_ACTIVE) != 2311d62bc4baSyz147064 DLADM_STATUS_OK) { 2312d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 2313d62bc4baSyz147064 } 2314d62bc4baSyz147064 if (dpa.dp_novanity) 2315d62bc4baSyz147064 get_mac_stats(dpa.dp_dev, &stats); 2316d62bc4baSyz147064 else 2317d62bc4baSyz147064 get_link_stats(link, &stats); 2318d62bc4baSyz147064 } else { 2319d62bc4baSyz147064 get_link_stats(link, &stats); 2320d62bc4baSyz147064 } 2321da14cebeSEric Cheng dladm_stats_diff(&diff_stats, &stats, &state->ls_prevstats); 23227c478bd9Sstevel@tonic-gate 2323ae6aa22aSVenugopal Iyer largs.link_s_link = link; 2324ae6aa22aSVenugopal Iyer largs.link_s_psum = &diff_stats; 2325*8002d411SSowmini Varadhan ofmt_print(state->ls_ofmt, &largs); 23267c478bd9Sstevel@tonic-gate 23277c478bd9Sstevel@tonic-gate state->ls_prevstats = stats; 2328d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 23297c478bd9Sstevel@tonic-gate } 23307c478bd9Sstevel@tonic-gate 2331d62bc4baSyz147064 2332d62bc4baSyz147064 static dladm_status_t 2333d62bc4baSyz147064 print_aggr_info(show_grp_state_t *state, const char *link, 2334e7801d59Ssowmini dladm_aggr_grp_attr_t *ginfop) 2335d62bc4baSyz147064 { 2336d62bc4baSyz147064 char addr_str[ETHERADDRL * 3]; 2337e7801d59Ssowmini laggr_fields_buf_t lbuf; 2338d62bc4baSyz147064 2339e7801d59Ssowmini (void) snprintf(lbuf.laggr_name, sizeof (lbuf.laggr_name), 2340e7801d59Ssowmini "%s", link); 2341e7801d59Ssowmini 2342e7801d59Ssowmini (void) dladm_aggr_policy2str(ginfop->lg_policy, 2343e7801d59Ssowmini lbuf.laggr_policy); 2344d62bc4baSyz147064 2345d62bc4baSyz147064 if (ginfop->lg_mac_fixed) { 2346d62bc4baSyz147064 (void) dladm_aggr_macaddr2str(ginfop->lg_mac, addr_str); 2347e7801d59Ssowmini (void) snprintf(lbuf.laggr_addrpolicy, 2348e7801d59Ssowmini sizeof (lbuf.laggr_addrpolicy), "fixed (%s)", addr_str); 2349d62bc4baSyz147064 } else { 2350e7801d59Ssowmini (void) snprintf(lbuf.laggr_addrpolicy, 2351e7801d59Ssowmini sizeof (lbuf.laggr_addrpolicy), "auto"); 2352d62bc4baSyz147064 } 2353d62bc4baSyz147064 2354d62bc4baSyz147064 2355e7801d59Ssowmini (void) dladm_aggr_lacpmode2str(ginfop->lg_lacp_mode, 2356e7801d59Ssowmini lbuf.laggr_lacpactivity); 2357e7801d59Ssowmini (void) dladm_aggr_lacptimer2str(ginfop->lg_lacp_timer, 2358e7801d59Ssowmini lbuf.laggr_lacptimer); 2359e7801d59Ssowmini (void) snprintf(lbuf.laggr_flags, sizeof (lbuf.laggr_flags), "%c----", 2360d62bc4baSyz147064 ginfop->lg_force ? 'f' : '-'); 2361e7801d59Ssowmini 2362*8002d411SSowmini Varadhan ofmt_print(state->gs_ofmt, &lbuf); 2363e7801d59Ssowmini 2364d62bc4baSyz147064 return (DLADM_STATUS_OK); 2365d62bc4baSyz147064 } 2366d62bc4baSyz147064 2367*8002d411SSowmini Varadhan static boolean_t 2368*8002d411SSowmini Varadhan print_xaggr_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize) 2369d62bc4baSyz147064 { 2370*8002d411SSowmini Varadhan const laggr_args_t *l = ofarg->ofmt_cbarg; 2371e7801d59Ssowmini int portnum; 2372e7801d59Ssowmini boolean_t is_port = (l->laggr_lport >= 0); 2373*8002d411SSowmini Varadhan static char tmpbuf[DLADM_STRSIZE]; 2374e7801d59Ssowmini dladm_aggr_port_attr_t *portp; 2375d62bc4baSyz147064 dladm_phys_attr_t dpa; 2376*8002d411SSowmini Varadhan dladm_status_t *stat, status = DLADM_STATUS_OK; 2377d62bc4baSyz147064 2378e7801d59Ssowmini stat = l->laggr_status; 2379d62bc4baSyz147064 2380e7801d59Ssowmini if (is_port) { 2381e7801d59Ssowmini portnum = l->laggr_lport; 2382e7801d59Ssowmini portp = &(l->laggr_ginfop->lg_ports[portnum]); 23834ac67f02SAnurag S. Maskey if ((status = dladm_datalink_id2info(handle, 2384*8002d411SSowmini Varadhan portp->lp_linkid, NULL, NULL, NULL, buf, bufsize)) != 2385e7801d59Ssowmini DLADM_STATUS_OK) { 2386e7801d59Ssowmini goto err; 2387d62bc4baSyz147064 } 23884ac67f02SAnurag S. Maskey 23894ac67f02SAnurag S. Maskey if ((status = dladm_phys_info(handle, portp->lp_linkid, 23904ac67f02SAnurag S. Maskey &dpa, DLADM_OPT_ACTIVE)) != DLADM_STATUS_OK) { 2391e7801d59Ssowmini goto err; 2392e7801d59Ssowmini } 2393d62bc4baSyz147064 } 2394d62bc4baSyz147064 2395*8002d411SSowmini Varadhan switch (ofarg->ofmt_id) { 2396e7801d59Ssowmini case AGGR_X_LINK: 2397*8002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%s", 2398*8002d411SSowmini Varadhan (is_port && !l->laggr_parsable ? " " : l->laggr_link)); 2399e7801d59Ssowmini break; 2400e7801d59Ssowmini case AGGR_X_PORT: 2401e7801d59Ssowmini if (is_port) 2402e7801d59Ssowmini break; 2403*8002d411SSowmini Varadhan *stat = DLADM_STATUS_OK; 2404*8002d411SSowmini Varadhan return (B_TRUE); 2405d62bc4baSyz147064 2406e7801d59Ssowmini case AGGR_X_SPEED: 2407e7801d59Ssowmini if (is_port) { 2408*8002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%uMb", 2409e7801d59Ssowmini (uint_t)((get_ifspeed(dpa.dp_dev, 2410e7801d59Ssowmini B_FALSE)) / 1000000ull)); 2411e7801d59Ssowmini } else { 2412*8002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%uMb", 2413e7801d59Ssowmini (uint_t)((get_ifspeed(l->laggr_link, 2414e7801d59Ssowmini B_TRUE)) / 1000000ull)); 2415e7801d59Ssowmini } 2416e7801d59Ssowmini break; 2417e7801d59Ssowmini 2418e7801d59Ssowmini case AGGR_X_DUPLEX: 2419e7801d59Ssowmini if (is_port) 2420*8002d411SSowmini Varadhan (void) get_linkduplex(dpa.dp_dev, B_FALSE, tmpbuf); 2421d62bc4baSyz147064 else 2422*8002d411SSowmini Varadhan (void) get_linkduplex(l->laggr_link, B_TRUE, tmpbuf); 2423*8002d411SSowmini Varadhan (void) strlcpy(buf, tmpbuf, bufsize); 2424e7801d59Ssowmini break; 2425d62bc4baSyz147064 2426e7801d59Ssowmini case AGGR_X_STATE: 24271a1811a0Svs226613 if (is_port) 2428*8002d411SSowmini Varadhan (void) get_linkstate(dpa.dp_dev, B_FALSE, tmpbuf); 24291a1811a0Svs226613 else 2430*8002d411SSowmini Varadhan (void) get_linkstate(l->laggr_link, B_TRUE, tmpbuf); 2431*8002d411SSowmini Varadhan (void) strlcpy(buf, tmpbuf, bufsize); 2432e7801d59Ssowmini break; 2433e7801d59Ssowmini case AGGR_X_ADDRESS: 2434e7801d59Ssowmini (void) dladm_aggr_macaddr2str( 2435e7801d59Ssowmini (is_port ? portp->lp_mac : l->laggr_ginfop->lg_mac), 2436*8002d411SSowmini Varadhan tmpbuf); 2437*8002d411SSowmini Varadhan (void) strlcpy(buf, tmpbuf, bufsize); 2438e7801d59Ssowmini break; 2439e7801d59Ssowmini case AGGR_X_PORTSTATE: 2440*8002d411SSowmini Varadhan if (is_port) { 2441*8002d411SSowmini Varadhan (void) dladm_aggr_portstate2str(portp->lp_state, 2442*8002d411SSowmini Varadhan tmpbuf); 2443*8002d411SSowmini Varadhan (void) strlcpy(buf, tmpbuf, bufsize); 2444*8002d411SSowmini Varadhan } 2445e7801d59Ssowmini break; 2446e7801d59Ssowmini } 2447e7801d59Ssowmini err: 2448e7801d59Ssowmini *stat = status; 2449*8002d411SSowmini Varadhan return (B_TRUE); 2450e7801d59Ssowmini } 2451e7801d59Ssowmini 2452e7801d59Ssowmini static dladm_status_t 2453e7801d59Ssowmini print_aggr_extended(show_grp_state_t *state, const char *link, 2454e7801d59Ssowmini dladm_aggr_grp_attr_t *ginfop) 2455e7801d59Ssowmini { 2456e7801d59Ssowmini int i; 2457e7801d59Ssowmini dladm_status_t status; 2458e7801d59Ssowmini laggr_args_t largs; 2459e7801d59Ssowmini 2460e7801d59Ssowmini largs.laggr_lport = -1; 2461e7801d59Ssowmini largs.laggr_link = link; 2462e7801d59Ssowmini largs.laggr_ginfop = ginfop; 2463e7801d59Ssowmini largs.laggr_status = &status; 2464*8002d411SSowmini Varadhan largs.laggr_parsable = state->gs_parsable; 2465e7801d59Ssowmini 2466*8002d411SSowmini Varadhan ofmt_print(state->gs_ofmt, &largs); 2467e7801d59Ssowmini 2468e7801d59Ssowmini if (status != DLADM_STATUS_OK) 2469e7801d59Ssowmini goto done; 2470e7801d59Ssowmini 2471e7801d59Ssowmini for (i = 0; i < ginfop->lg_nports; i++) { 2472e7801d59Ssowmini largs.laggr_lport = i; 2473*8002d411SSowmini Varadhan ofmt_print(state->gs_ofmt, &largs); 2474e7801d59Ssowmini if (status != DLADM_STATUS_OK) 2475e7801d59Ssowmini goto done; 2476d62bc4baSyz147064 } 2477d62bc4baSyz147064 2478d62bc4baSyz147064 status = DLADM_STATUS_OK; 2479d62bc4baSyz147064 done: 2480d62bc4baSyz147064 return (status); 2481d62bc4baSyz147064 } 2482d62bc4baSyz147064 2483*8002d411SSowmini Varadhan static boolean_t 2484*8002d411SSowmini Varadhan print_lacp_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize) 2485e7801d59Ssowmini { 2486*8002d411SSowmini Varadhan const laggr_args_t *l = ofarg->ofmt_cbarg; 2487e7801d59Ssowmini int portnum; 2488e7801d59Ssowmini boolean_t is_port = (l->laggr_lport >= 0); 2489e7801d59Ssowmini dladm_aggr_port_attr_t *portp; 2490e7801d59Ssowmini dladm_status_t *stat, status; 2491e7801d59Ssowmini aggr_lacp_state_t *lstate; 2492e7801d59Ssowmini 2493e7801d59Ssowmini if (!is_port) { 2494*8002d411SSowmini Varadhan return (B_FALSE); /* cannot happen! */ 2495e7801d59Ssowmini } 2496e7801d59Ssowmini 2497e7801d59Ssowmini stat = l->laggr_status; 2498e7801d59Ssowmini 2499e7801d59Ssowmini portnum = l->laggr_lport; 2500e7801d59Ssowmini portp = &(l->laggr_ginfop->lg_ports[portnum]); 25014ac67f02SAnurag S. Maskey 25024ac67f02SAnurag S. Maskey if ((status = dladm_datalink_id2info(handle, portp->lp_linkid, 2503*8002d411SSowmini Varadhan NULL, NULL, NULL, buf, bufsize)) != DLADM_STATUS_OK) { 2504e7801d59Ssowmini goto err; 2505e7801d59Ssowmini } 2506e7801d59Ssowmini lstate = &(portp->lp_lacp_state); 2507e7801d59Ssowmini 2508*8002d411SSowmini Varadhan switch (ofarg->ofmt_id) { 2509e7801d59Ssowmini case AGGR_L_LINK: 2510*8002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%s", 2511e7801d59Ssowmini (portnum > 0 ? "" : l->laggr_link)); 2512e7801d59Ssowmini break; 2513e7801d59Ssowmini 2514e7801d59Ssowmini case AGGR_L_PORT: 2515*8002d411SSowmini Varadhan /* 2516*8002d411SSowmini Varadhan * buf already contains portname as a result of the 2517*8002d411SSowmini Varadhan * earlier call to dladm_datalink_id2info(). 2518*8002d411SSowmini Varadhan */ 2519e7801d59Ssowmini break; 2520e7801d59Ssowmini 2521e7801d59Ssowmini case AGGR_L_AGGREGATABLE: 2522*8002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%s", 2523e7801d59Ssowmini (lstate->bit.aggregation ? "yes" : "no")); 2524e7801d59Ssowmini break; 2525e7801d59Ssowmini 2526e7801d59Ssowmini case AGGR_L_SYNC: 2527*8002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%s", 2528e7801d59Ssowmini (lstate->bit.sync ? "yes" : "no")); 2529e7801d59Ssowmini break; 2530e7801d59Ssowmini 2531e7801d59Ssowmini case AGGR_L_COLL: 2532*8002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%s", 2533e7801d59Ssowmini (lstate->bit.collecting ? "yes" : "no")); 2534e7801d59Ssowmini break; 2535e7801d59Ssowmini 2536e7801d59Ssowmini case AGGR_L_DIST: 2537*8002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%s", 2538e7801d59Ssowmini (lstate->bit.distributing ? "yes" : "no")); 2539e7801d59Ssowmini break; 2540e7801d59Ssowmini 2541e7801d59Ssowmini case AGGR_L_DEFAULTED: 2542*8002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%s", 2543e7801d59Ssowmini (lstate->bit.defaulted ? "yes" : "no")); 2544e7801d59Ssowmini break; 2545e7801d59Ssowmini 2546e7801d59Ssowmini case AGGR_L_EXPIRED: 2547*8002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%s", 2548e7801d59Ssowmini (lstate->bit.expired ? "yes" : "no")); 2549e7801d59Ssowmini break; 2550e7801d59Ssowmini } 2551e7801d59Ssowmini 2552e7801d59Ssowmini *stat = DLADM_STATUS_OK; 2553*8002d411SSowmini Varadhan return (B_TRUE); 2554e7801d59Ssowmini 2555e7801d59Ssowmini err: 2556e7801d59Ssowmini *stat = status; 2557*8002d411SSowmini Varadhan return (B_TRUE); 2558e7801d59Ssowmini } 2559e7801d59Ssowmini 2560d62bc4baSyz147064 static dladm_status_t 2561d62bc4baSyz147064 print_aggr_lacp(show_grp_state_t *state, const char *link, 2562e7801d59Ssowmini dladm_aggr_grp_attr_t *ginfop) 2563d62bc4baSyz147064 { 2564d62bc4baSyz147064 int i; 2565d62bc4baSyz147064 dladm_status_t status; 2566e7801d59Ssowmini laggr_args_t largs; 2567d62bc4baSyz147064 2568e7801d59Ssowmini largs.laggr_link = link; 2569e7801d59Ssowmini largs.laggr_ginfop = ginfop; 2570e7801d59Ssowmini largs.laggr_status = &status; 2571d62bc4baSyz147064 2572e7801d59Ssowmini for (i = 0; i < ginfop->lg_nports; i++) { 2573e7801d59Ssowmini largs.laggr_lport = i; 2574*8002d411SSowmini Varadhan ofmt_print(state->gs_ofmt, &largs); 2575d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 2576d62bc4baSyz147064 goto done; 2577d62bc4baSyz147064 } 2578d62bc4baSyz147064 2579d62bc4baSyz147064 status = DLADM_STATUS_OK; 2580d62bc4baSyz147064 done: 2581d62bc4baSyz147064 return (status); 2582d62bc4baSyz147064 } 2583d62bc4baSyz147064 2584*8002d411SSowmini Varadhan static boolean_t 2585*8002d411SSowmini Varadhan print_aggr_stats_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize) 2586e7801d59Ssowmini { 2587*8002d411SSowmini Varadhan const laggr_args_t *l = ofarg->ofmt_cbarg; 2588e7801d59Ssowmini int portnum; 2589e7801d59Ssowmini boolean_t is_port = (l->laggr_lport >= 0); 2590e7801d59Ssowmini dladm_aggr_port_attr_t *portp; 2591e7801d59Ssowmini dladm_phys_attr_t dpa; 2592e7801d59Ssowmini dladm_status_t *stat, status; 2593e7801d59Ssowmini pktsum_t port_stat, diff_stats; 2594e7801d59Ssowmini 2595e7801d59Ssowmini stat = l->laggr_status; 2596e7801d59Ssowmini *stat = DLADM_STATUS_OK; 2597e7801d59Ssowmini 2598e7801d59Ssowmini if (is_port) { 2599e7801d59Ssowmini portnum = l->laggr_lport; 2600e7801d59Ssowmini portp = &(l->laggr_ginfop->lg_ports[portnum]); 26014ac67f02SAnurag S. Maskey if ((status = dladm_phys_info(handle, portp->lp_linkid, 26024ac67f02SAnurag S. Maskey &dpa, DLADM_OPT_ACTIVE)) != DLADM_STATUS_OK) { 2603e7801d59Ssowmini goto err; 2604e7801d59Ssowmini } 2605e7801d59Ssowmini 2606e7801d59Ssowmini get_mac_stats(dpa.dp_dev, &port_stat); 2607e7801d59Ssowmini 26084ac67f02SAnurag S. Maskey if ((status = dladm_datalink_id2info(handle, 2609*8002d411SSowmini Varadhan portp->lp_linkid, NULL, NULL, NULL, buf, bufsize)) != 26104ac67f02SAnurag S. Maskey DLADM_STATUS_OK) { 2611e7801d59Ssowmini goto err; 2612e7801d59Ssowmini } 2613e7801d59Ssowmini 2614da14cebeSEric Cheng dladm_stats_diff(&diff_stats, &port_stat, l->laggr_prevstats); 2615e7801d59Ssowmini } 2616e7801d59Ssowmini 2617*8002d411SSowmini Varadhan switch (ofarg->ofmt_id) { 2618e7801d59Ssowmini case AGGR_S_LINK: 2619*8002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%s", 2620e7801d59Ssowmini (is_port ? "" : l->laggr_link)); 2621e7801d59Ssowmini break; 2622e7801d59Ssowmini case AGGR_S_PORT: 2623*8002d411SSowmini Varadhan /* 2624*8002d411SSowmini Varadhan * if (is_port), buf has port name. Otherwise we print 2625*8002d411SSowmini Varadhan * STR_UNDEF_VAL 2626*8002d411SSowmini Varadhan */ 2627e7801d59Ssowmini break; 2628e7801d59Ssowmini 2629e7801d59Ssowmini case AGGR_S_IPKTS: 2630e7801d59Ssowmini if (is_port) { 2631*8002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%llu", 2632e7801d59Ssowmini diff_stats.ipackets); 2633e7801d59Ssowmini } else { 2634*8002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%llu", 2635e7801d59Ssowmini l->laggr_pktsumtot->ipackets); 2636e7801d59Ssowmini } 2637e7801d59Ssowmini break; 2638e7801d59Ssowmini 2639e7801d59Ssowmini case AGGR_S_RBYTES: 2640e7801d59Ssowmini if (is_port) { 2641*8002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%llu", 2642e7801d59Ssowmini diff_stats.rbytes); 2643e7801d59Ssowmini } else { 2644*8002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%llu", 2645e7801d59Ssowmini l->laggr_pktsumtot->rbytes); 2646e7801d59Ssowmini } 2647e7801d59Ssowmini break; 2648e7801d59Ssowmini 2649e7801d59Ssowmini case AGGR_S_OPKTS: 2650e7801d59Ssowmini if (is_port) { 2651*8002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%llu", 2652e7801d59Ssowmini diff_stats.opackets); 2653e7801d59Ssowmini } else { 2654*8002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%llu", 2655e7801d59Ssowmini l->laggr_pktsumtot->opackets); 2656e7801d59Ssowmini } 2657e7801d59Ssowmini break; 2658e7801d59Ssowmini case AGGR_S_OBYTES: 2659e7801d59Ssowmini if (is_port) { 2660*8002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%llu", 2661e7801d59Ssowmini diff_stats.obytes); 2662e7801d59Ssowmini } else { 2663*8002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%llu", 2664e7801d59Ssowmini l->laggr_pktsumtot->obytes); 2665e7801d59Ssowmini } 2666e7801d59Ssowmini break; 2667e7801d59Ssowmini 2668e7801d59Ssowmini case AGGR_S_IPKTDIST: 2669e7801d59Ssowmini if (is_port) { 2670*8002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%-6.1f", 2671e7801d59Ssowmini (double)diff_stats.opackets/ 2672e7801d59Ssowmini (double)l->laggr_pktsumtot->ipackets * 100); 2673e7801d59Ssowmini } 2674e7801d59Ssowmini break; 2675e7801d59Ssowmini case AGGR_S_OPKTDIST: 2676e7801d59Ssowmini if (is_port) { 2677*8002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%-6.1f", 2678e7801d59Ssowmini (double)diff_stats.opackets/ 2679e7801d59Ssowmini (double)l->laggr_pktsumtot->opackets * 100); 2680e7801d59Ssowmini } 2681e7801d59Ssowmini break; 2682e7801d59Ssowmini } 2683*8002d411SSowmini Varadhan return (B_TRUE); 2684e7801d59Ssowmini 2685e7801d59Ssowmini err: 2686e7801d59Ssowmini *stat = status; 2687*8002d411SSowmini Varadhan return (B_TRUE); 2688e7801d59Ssowmini } 2689e7801d59Ssowmini 2690d62bc4baSyz147064 static dladm_status_t 2691d62bc4baSyz147064 print_aggr_stats(show_grp_state_t *state, const char *link, 2692e7801d59Ssowmini dladm_aggr_grp_attr_t *ginfop) 2693d62bc4baSyz147064 { 2694d62bc4baSyz147064 dladm_phys_attr_t dpa; 2695d62bc4baSyz147064 dladm_aggr_port_attr_t *portp; 2696d62bc4baSyz147064 pktsum_t pktsumtot, port_stat; 2697d62bc4baSyz147064 dladm_status_t status; 2698d62bc4baSyz147064 int i; 2699e7801d59Ssowmini laggr_args_t largs; 27007c478bd9Sstevel@tonic-gate 27017c478bd9Sstevel@tonic-gate /* sum the ports statistics */ 27027c478bd9Sstevel@tonic-gate bzero(&pktsumtot, sizeof (pktsumtot)); 2703d62bc4baSyz147064 2704d62bc4baSyz147064 for (i = 0; i < ginfop->lg_nports; i++) { 2705d62bc4baSyz147064 2706d62bc4baSyz147064 portp = &(ginfop->lg_ports[i]); 27074ac67f02SAnurag S. Maskey if ((status = dladm_phys_info(handle, portp->lp_linkid, &dpa, 2708d62bc4baSyz147064 DLADM_OPT_ACTIVE)) != DLADM_STATUS_OK) { 2709d62bc4baSyz147064 goto done; 27107c478bd9Sstevel@tonic-gate } 27117c478bd9Sstevel@tonic-gate 2712d62bc4baSyz147064 get_mac_stats(dpa.dp_dev, &port_stat); 2713da14cebeSEric Cheng dladm_stats_total(&pktsumtot, &port_stat, 2714da14cebeSEric Cheng &state->gs_prevstats[i]); 27157c478bd9Sstevel@tonic-gate } 27167c478bd9Sstevel@tonic-gate 2717e7801d59Ssowmini largs.laggr_lport = -1; 2718e7801d59Ssowmini largs.laggr_link = link; 2719e7801d59Ssowmini largs.laggr_ginfop = ginfop; 2720e7801d59Ssowmini largs.laggr_status = &status; 2721e7801d59Ssowmini largs.laggr_pktsumtot = &pktsumtot; 2722e7801d59Ssowmini 2723*8002d411SSowmini Varadhan ofmt_print(state->gs_ofmt, &largs); 2724e7801d59Ssowmini 2725e7801d59Ssowmini if (status != DLADM_STATUS_OK) 2726e7801d59Ssowmini goto done; 2727d62bc4baSyz147064 2728d62bc4baSyz147064 for (i = 0; i < ginfop->lg_nports; i++) { 2729e7801d59Ssowmini largs.laggr_lport = i; 2730e7801d59Ssowmini largs.laggr_prevstats = &state->gs_prevstats[i]; 2731*8002d411SSowmini Varadhan ofmt_print(state->gs_ofmt, &largs); 2732e7801d59Ssowmini if (status != DLADM_STATUS_OK) 2733d62bc4baSyz147064 goto done; 2734d62bc4baSyz147064 } 2735d62bc4baSyz147064 2736d62bc4baSyz147064 status = DLADM_STATUS_OK; 2737d62bc4baSyz147064 done: 2738d62bc4baSyz147064 return (status); 2739d62bc4baSyz147064 } 2740d62bc4baSyz147064 2741d62bc4baSyz147064 static dladm_status_t 2742e7801d59Ssowmini print_aggr(show_grp_state_t *state, datalink_id_t linkid) 2743d62bc4baSyz147064 { 2744d62bc4baSyz147064 char link[MAXLINKNAMELEN]; 2745d62bc4baSyz147064 dladm_aggr_grp_attr_t ginfo; 2746d62bc4baSyz147064 uint32_t flags; 2747d62bc4baSyz147064 dladm_status_t status; 2748d62bc4baSyz147064 27495f5c9f54SAnurag S. Maskey bzero(&ginfo, sizeof (dladm_aggr_grp_attr_t)); 27504ac67f02SAnurag S. Maskey if ((status = dladm_datalink_id2info(handle, linkid, &flags, NULL, 27514ac67f02SAnurag S. Maskey NULL, link, MAXLINKNAMELEN)) != DLADM_STATUS_OK) { 2752d62bc4baSyz147064 return (status); 2753d62bc4baSyz147064 } 2754d62bc4baSyz147064 2755d62bc4baSyz147064 if (!(state->gs_flags & flags)) 2756d62bc4baSyz147064 return (DLADM_STATUS_NOTFOUND); 2757d62bc4baSyz147064 27584ac67f02SAnurag S. Maskey status = dladm_aggr_info(handle, linkid, &ginfo, state->gs_flags); 2759d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 2760d62bc4baSyz147064 return (status); 2761d62bc4baSyz147064 2762d62bc4baSyz147064 if (state->gs_lacp) 2763e7801d59Ssowmini status = print_aggr_lacp(state, link, &ginfo); 2764d62bc4baSyz147064 else if (state->gs_extended) 2765e7801d59Ssowmini status = print_aggr_extended(state, link, &ginfo); 2766d62bc4baSyz147064 else if (state->gs_stats) 2767e7801d59Ssowmini status = print_aggr_stats(state, link, &ginfo); 27684ac67f02SAnurag S. Maskey else 2769e7801d59Ssowmini status = print_aggr_info(state, link, &ginfo); 2770d62bc4baSyz147064 2771d62bc4baSyz147064 done: 2772d62bc4baSyz147064 free(ginfo.lg_ports); 2773d62bc4baSyz147064 return (status); 2774d62bc4baSyz147064 } 2775d62bc4baSyz147064 27764ac67f02SAnurag S. Maskey /* ARGSUSED */ 2777d62bc4baSyz147064 static int 27784ac67f02SAnurag S. Maskey show_aggr(dladm_handle_t dh, datalink_id_t linkid, void *arg) 2779d62bc4baSyz147064 { 2780d62bc4baSyz147064 show_grp_state_t *state = arg; 2781d62bc4baSyz147064 2782*8002d411SSowmini Varadhan state->gs_status = print_aggr(state, linkid); 2783d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 27847c478bd9Sstevel@tonic-gate } 27857c478bd9Sstevel@tonic-gate 27867c478bd9Sstevel@tonic-gate static void 27878d5c46e6Sam223141 do_show_link(int argc, char *argv[], const char *use) 27887c478bd9Sstevel@tonic-gate { 27897c478bd9Sstevel@tonic-gate int option; 27907c478bd9Sstevel@tonic-gate boolean_t s_arg = B_FALSE; 2791da14cebeSEric Cheng boolean_t S_arg = B_FALSE; 27927c478bd9Sstevel@tonic-gate boolean_t i_arg = B_FALSE; 2793d62bc4baSyz147064 uint32_t flags = DLADM_OPT_ACTIVE; 2794d62bc4baSyz147064 boolean_t p_arg = B_FALSE; 2795d62bc4baSyz147064 datalink_id_t linkid = DATALINK_ALL_LINKID; 2796da14cebeSEric Cheng char linkname[MAXLINKNAMELEN]; 279763a6526dSMichael Lim uint32_t interval = 0; 2798d62bc4baSyz147064 show_state_t state; 2799d62bc4baSyz147064 dladm_status_t status; 2800e7801d59Ssowmini boolean_t o_arg = B_FALSE; 2801e7801d59Ssowmini char *fields_str = NULL; 2802e7801d59Ssowmini char *all_active_fields = "link,class,mtu,state,over"; 2803e7801d59Ssowmini char *all_inactive_fields = "link,class,over"; 28046be03d0bSVasumathi Sundaram - Sun Microsystems char *allstat_fields = 28056be03d0bSVasumathi Sundaram - Sun Microsystems "link,ipackets,rbytes,ierrors,opackets,obytes,oerrors"; 2806*8002d411SSowmini Varadhan ofmt_handle_t ofmt; 2807*8002d411SSowmini Varadhan ofmt_status_t oferr; 2808*8002d411SSowmini Varadhan uint_t ofmtflags = 0; 2809e7801d59Ssowmini 2810e7801d59Ssowmini bzero(&state, sizeof (state)); 28117c478bd9Sstevel@tonic-gate 28127c478bd9Sstevel@tonic-gate opterr = 0; 2813da14cebeSEric Cheng while ((option = getopt_long(argc, argv, ":pPsSi:o:", 2814d62bc4baSyz147064 show_lopts, NULL)) != -1) { 28157c478bd9Sstevel@tonic-gate switch (option) { 28167c478bd9Sstevel@tonic-gate case 'p': 2817d62bc4baSyz147064 if (p_arg) 2818d62bc4baSyz147064 die_optdup(option); 2819d62bc4baSyz147064 2820d62bc4baSyz147064 p_arg = B_TRUE; 28217c478bd9Sstevel@tonic-gate break; 28227c478bd9Sstevel@tonic-gate case 's': 282333343a97Smeem if (s_arg) 282433343a97Smeem die_optdup(option); 28257c478bd9Sstevel@tonic-gate 28267c478bd9Sstevel@tonic-gate s_arg = B_TRUE; 28277c478bd9Sstevel@tonic-gate break; 2828d62bc4baSyz147064 case 'P': 2829d62bc4baSyz147064 if (flags != DLADM_OPT_ACTIVE) 2830d62bc4baSyz147064 die_optdup(option); 2831d62bc4baSyz147064 2832d62bc4baSyz147064 flags = DLADM_OPT_PERSIST; 2833d62bc4baSyz147064 break; 2834da14cebeSEric Cheng case 'S': 2835da14cebeSEric Cheng if (S_arg) 2836da14cebeSEric Cheng die_optdup(option); 2837da14cebeSEric Cheng 2838da14cebeSEric Cheng S_arg = B_TRUE; 2839da14cebeSEric Cheng break; 2840e7801d59Ssowmini case 'o': 2841e7801d59Ssowmini o_arg = B_TRUE; 2842e7801d59Ssowmini fields_str = optarg; 2843e7801d59Ssowmini break; 28447c478bd9Sstevel@tonic-gate case 'i': 284533343a97Smeem if (i_arg) 284633343a97Smeem die_optdup(option); 28477c478bd9Sstevel@tonic-gate 28487c478bd9Sstevel@tonic-gate i_arg = B_TRUE; 284963a6526dSMichael Lim if (!dladm_str2interval(optarg, &interval)) 285033343a97Smeem die("invalid interval value '%s'", optarg); 28517c478bd9Sstevel@tonic-gate break; 28527c478bd9Sstevel@tonic-gate default: 28538d5c46e6Sam223141 die_opterr(optopt, option, use); 285433343a97Smeem break; 28557c478bd9Sstevel@tonic-gate } 28567c478bd9Sstevel@tonic-gate } 28577c478bd9Sstevel@tonic-gate 2858da14cebeSEric Cheng if (i_arg && !(s_arg || S_arg)) 2859da14cebeSEric Cheng die("the option -i can be used only with -s or -S"); 2860da14cebeSEric Cheng 2861da14cebeSEric Cheng if (s_arg && S_arg) 2862da14cebeSEric Cheng die("the -s option cannot be used with -S"); 28637c478bd9Sstevel@tonic-gate 28646be03d0bSVasumathi Sundaram - Sun Microsystems if (s_arg && flags != DLADM_OPT_ACTIVE) 28656be03d0bSVasumathi Sundaram - Sun Microsystems die("the option -P cannot be used with -s"); 2866d62bc4baSyz147064 2867da14cebeSEric Cheng if (S_arg && (p_arg || flags != DLADM_OPT_ACTIVE)) 2868da14cebeSEric Cheng die("the option -%c cannot be used with -S", p_arg ? 'p' : 'P'); 2869da14cebeSEric Cheng 28707c478bd9Sstevel@tonic-gate /* get link name (optional last argument) */ 2871d62bc4baSyz147064 if (optind == (argc-1)) { 2872d62bc4baSyz147064 uint32_t f; 2873d62bc4baSyz147064 2874da14cebeSEric Cheng if (strlcpy(linkname, argv[optind], MAXLINKNAMELEN) 2875da14cebeSEric Cheng >= MAXLINKNAMELEN) { 2876da14cebeSEric Cheng (void) fprintf(stderr, 2877da14cebeSEric Cheng gettext("%s: link name too long\n"), 2878da14cebeSEric Cheng progname); 28794ac67f02SAnurag S. Maskey dladm_close(handle); 2880da14cebeSEric Cheng exit(1); 2881da14cebeSEric Cheng } 28824ac67f02SAnurag S. Maskey if ((status = dladm_name2info(handle, linkname, &linkid, &f, 2883d62bc4baSyz147064 NULL, NULL)) != DLADM_STATUS_OK) { 2884da14cebeSEric Cheng die_dlerr(status, "link %s is not valid", linkname); 2885d62bc4baSyz147064 } 2886d62bc4baSyz147064 2887d62bc4baSyz147064 if (!(f & flags)) { 2888d62bc4baSyz147064 die_dlerr(DLADM_STATUS_BADARG, "link %s is %s", 2889d62bc4baSyz147064 argv[optind], flags == DLADM_OPT_PERSIST ? 2890d62bc4baSyz147064 "a temporary link" : "temporarily removed"); 2891d62bc4baSyz147064 } 2892d62bc4baSyz147064 } else if (optind != argc) { 28937c478bd9Sstevel@tonic-gate usage(); 2894d62bc4baSyz147064 } 28957c478bd9Sstevel@tonic-gate 28960d365605Sschuster if (p_arg && !o_arg) 28970d365605Sschuster die("-p requires -o"); 28980d365605Sschuster 2899da14cebeSEric Cheng if (S_arg) { 29004ac67f02SAnurag S. Maskey dladm_continuous(handle, linkid, NULL, interval, LINK_REPORT); 2901da14cebeSEric Cheng return; 2902da14cebeSEric Cheng } 2903da14cebeSEric Cheng 29040d365605Sschuster if (p_arg && strcasecmp(fields_str, "all") == 0) 29050d365605Sschuster die("\"-o all\" is invalid with -p"); 29060d365605Sschuster 2907e7801d59Ssowmini if (!o_arg || (o_arg && strcasecmp(fields_str, "all") == 0)) { 29086be03d0bSVasumathi Sundaram - Sun Microsystems if (s_arg) 29096be03d0bSVasumathi Sundaram - Sun Microsystems fields_str = allstat_fields; 29106be03d0bSVasumathi Sundaram - Sun Microsystems else if (flags & DLADM_OPT_ACTIVE) 2911e7801d59Ssowmini fields_str = all_active_fields; 2912e7801d59Ssowmini else 2913e7801d59Ssowmini fields_str = all_inactive_fields; 2914e7801d59Ssowmini } 2915e7801d59Ssowmini 2916*8002d411SSowmini Varadhan state.ls_parsable = p_arg; 29176be03d0bSVasumathi Sundaram - Sun Microsystems state.ls_flags = flags; 29186be03d0bSVasumathi Sundaram - Sun Microsystems state.ls_donefirst = B_FALSE; 29196be03d0bSVasumathi Sundaram - Sun Microsystems 29206be03d0bSVasumathi Sundaram - Sun Microsystems if (s_arg) { 29216be03d0bSVasumathi Sundaram - Sun Microsystems link_stats(linkid, interval, fields_str, &state); 29226be03d0bSVasumathi Sundaram - Sun Microsystems return; 29236be03d0bSVasumathi Sundaram - Sun Microsystems } 2924*8002d411SSowmini Varadhan if (state.ls_parsable) 2925*8002d411SSowmini Varadhan ofmtflags |= OFMT_PARSABLE; 2926*8002d411SSowmini Varadhan oferr = ofmt_open(fields_str, link_fields, ofmtflags, 0, &ofmt); 2927*8002d411SSowmini Varadhan dladm_ofmt_check(oferr, state.ls_parsable, ofmt); 2928*8002d411SSowmini Varadhan state.ls_ofmt = ofmt; 2929e7801d59Ssowmini 2930d62bc4baSyz147064 if (linkid == DATALINK_ALL_LINKID) { 29314ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(show_link, handle, &state, 2932d62bc4baSyz147064 DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE, flags); 2933210db224Sericheng } else { 29344ac67f02SAnurag S. Maskey (void) show_link(handle, linkid, &state); 2935d62bc4baSyz147064 if (state.ls_status != DLADM_STATUS_OK) { 2936d62bc4baSyz147064 die_dlerr(state.ls_status, "failed to show link %s", 2937d62bc4baSyz147064 argv[optind]); 2938d62bc4baSyz147064 } 29397c478bd9Sstevel@tonic-gate } 2940*8002d411SSowmini Varadhan ofmt_close(ofmt); 2941210db224Sericheng } 29427c478bd9Sstevel@tonic-gate 29437c478bd9Sstevel@tonic-gate static void 29448d5c46e6Sam223141 do_show_aggr(int argc, char *argv[], const char *use) 29457c478bd9Sstevel@tonic-gate { 29467c478bd9Sstevel@tonic-gate boolean_t L_arg = B_FALSE; 29477c478bd9Sstevel@tonic-gate boolean_t s_arg = B_FALSE; 29487c478bd9Sstevel@tonic-gate boolean_t i_arg = B_FALSE; 2949d62bc4baSyz147064 boolean_t p_arg = B_FALSE; 2950d62bc4baSyz147064 boolean_t x_arg = B_FALSE; 29517c478bd9Sstevel@tonic-gate show_grp_state_t state; 2952d62bc4baSyz147064 uint32_t flags = DLADM_OPT_ACTIVE; 2953d62bc4baSyz147064 datalink_id_t linkid = DATALINK_ALL_LINKID; 2954d62bc4baSyz147064 int option; 295563a6526dSMichael Lim uint32_t interval = 0; 2956d62bc4baSyz147064 int key; 2957d62bc4baSyz147064 dladm_status_t status; 2958e7801d59Ssowmini boolean_t o_arg = B_FALSE; 2959e7801d59Ssowmini char *fields_str = NULL; 2960e7801d59Ssowmini char *all_fields = 2961e7801d59Ssowmini "link,policy,addrpolicy,lacpactivity,lacptimer,flags"; 2962e7801d59Ssowmini char *all_lacp_fields = 2963e7801d59Ssowmini "link,port,aggregatable,sync,coll,dist,defaulted,expired"; 2964e7801d59Ssowmini char *all_stats_fields = 2965e7801d59Ssowmini "link,port,ipackets,rbytes,opackets,obytes,ipktdist,opktdist"; 2966e7801d59Ssowmini char *all_extended_fields = 2967e7801d59Ssowmini "link,port,speed,duplex,state,address,portstate"; 2968*8002d411SSowmini Varadhan ofmt_field_t *pf; 2969*8002d411SSowmini Varadhan ofmt_handle_t ofmt; 2970*8002d411SSowmini Varadhan ofmt_status_t oferr; 2971*8002d411SSowmini Varadhan uint_t ofmtflags = 0; 2972e7801d59Ssowmini 2973e7801d59Ssowmini bzero(&state, sizeof (state)); 29747c478bd9Sstevel@tonic-gate 29757c478bd9Sstevel@tonic-gate opterr = 0; 2976e7801d59Ssowmini while ((option = getopt_long(argc, argv, ":LpPxsi:o:", 2977d62bc4baSyz147064 show_lopts, NULL)) != -1) { 29787c478bd9Sstevel@tonic-gate switch (option) { 29797c478bd9Sstevel@tonic-gate case 'L': 298033343a97Smeem if (L_arg) 298133343a97Smeem die_optdup(option); 29827c478bd9Sstevel@tonic-gate 29837c478bd9Sstevel@tonic-gate L_arg = B_TRUE; 29847c478bd9Sstevel@tonic-gate break; 29857c478bd9Sstevel@tonic-gate case 'p': 2986d62bc4baSyz147064 if (p_arg) 2987d62bc4baSyz147064 die_optdup(option); 2988d62bc4baSyz147064 2989d62bc4baSyz147064 p_arg = B_TRUE; 2990d62bc4baSyz147064 break; 2991d62bc4baSyz147064 case 'x': 2992d62bc4baSyz147064 if (x_arg) 2993d62bc4baSyz147064 die_optdup(option); 2994d62bc4baSyz147064 2995d62bc4baSyz147064 x_arg = B_TRUE; 2996d62bc4baSyz147064 break; 2997d62bc4baSyz147064 case 'P': 2998d62bc4baSyz147064 if (flags != DLADM_OPT_ACTIVE) 2999d62bc4baSyz147064 die_optdup(option); 3000d62bc4baSyz147064 3001d62bc4baSyz147064 flags = DLADM_OPT_PERSIST; 30027c478bd9Sstevel@tonic-gate break; 30037c478bd9Sstevel@tonic-gate case 's': 300433343a97Smeem if (s_arg) 300533343a97Smeem die_optdup(option); 30067c478bd9Sstevel@tonic-gate 30077c478bd9Sstevel@tonic-gate s_arg = B_TRUE; 30087c478bd9Sstevel@tonic-gate break; 3009e7801d59Ssowmini case 'o': 3010e7801d59Ssowmini o_arg = B_TRUE; 3011e7801d59Ssowmini fields_str = optarg; 3012e7801d59Ssowmini break; 30137c478bd9Sstevel@tonic-gate case 'i': 301433343a97Smeem if (i_arg) 301533343a97Smeem die_optdup(option); 30167c478bd9Sstevel@tonic-gate 30177c478bd9Sstevel@tonic-gate i_arg = B_TRUE; 301863a6526dSMichael Lim if (!dladm_str2interval(optarg, &interval)) 301933343a97Smeem die("invalid interval value '%s'", optarg); 30207c478bd9Sstevel@tonic-gate break; 30217c478bd9Sstevel@tonic-gate default: 30228d5c46e6Sam223141 die_opterr(optopt, option, use); 302333343a97Smeem break; 30247c478bd9Sstevel@tonic-gate } 30257c478bd9Sstevel@tonic-gate } 30267c478bd9Sstevel@tonic-gate 30270d365605Sschuster if (p_arg && !o_arg) 30280d365605Sschuster die("-p requires -o"); 30290d365605Sschuster 30300d365605Sschuster if (p_arg && strcasecmp(fields_str, "all") == 0) 30310d365605Sschuster die("\"-o all\" is invalid with -p"); 30320d365605Sschuster 303333343a97Smeem if (i_arg && !s_arg) 303433343a97Smeem die("the option -i can be used only with -s"); 30357c478bd9Sstevel@tonic-gate 3036d62bc4baSyz147064 if (s_arg && (L_arg || p_arg || x_arg || flags != DLADM_OPT_ACTIVE)) { 3037d62bc4baSyz147064 die("the option -%c cannot be used with -s", 3038d62bc4baSyz147064 L_arg ? 'L' : (p_arg ? 'p' : (x_arg ? 'x' : 'P'))); 3039d62bc4baSyz147064 } 3040d62bc4baSyz147064 3041d62bc4baSyz147064 if (L_arg && flags != DLADM_OPT_ACTIVE) 3042d62bc4baSyz147064 die("the option -P cannot be used with -L"); 3043d62bc4baSyz147064 3044d62bc4baSyz147064 if (x_arg && (L_arg || flags != DLADM_OPT_ACTIVE)) 3045d62bc4baSyz147064 die("the option -%c cannot be used with -x", L_arg ? 'L' : 'P'); 3046d62bc4baSyz147064 3047d62bc4baSyz147064 /* get aggregation key or aggrname (optional last argument) */ 30487c478bd9Sstevel@tonic-gate if (optind == (argc-1)) { 3049d62bc4baSyz147064 if (!str2int(argv[optind], &key)) { 30504ac67f02SAnurag S. Maskey status = dladm_name2info(handle, argv[optind], 30514ac67f02SAnurag S. Maskey &linkid, NULL, NULL, NULL); 3052d62bc4baSyz147064 } else { 30534ac67f02SAnurag S. Maskey status = dladm_key2linkid(handle, (uint16_t)key, 3054d62bc4baSyz147064 &linkid, DLADM_OPT_ACTIVE); 3055d62bc4baSyz147064 } 3056d62bc4baSyz147064 3057d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 3058d62bc4baSyz147064 die("non-existent aggregation '%s'", argv[optind]); 3059d62bc4baSyz147064 30607c478bd9Sstevel@tonic-gate } else if (optind != argc) { 30617c478bd9Sstevel@tonic-gate usage(); 30627c478bd9Sstevel@tonic-gate } 30637c478bd9Sstevel@tonic-gate 3064d62bc4baSyz147064 bzero(&state, sizeof (state)); 3065d62bc4baSyz147064 state.gs_lacp = L_arg; 3066d62bc4baSyz147064 state.gs_stats = s_arg; 3067d62bc4baSyz147064 state.gs_flags = flags; 3068*8002d411SSowmini Varadhan state.gs_parsable = p_arg; 3069d62bc4baSyz147064 state.gs_extended = x_arg; 3070d62bc4baSyz147064 3071e7801d59Ssowmini if (!o_arg || (o_arg && strcasecmp(fields_str, "all") == 0)) { 3072e7801d59Ssowmini if (state.gs_lacp) 3073e7801d59Ssowmini fields_str = all_lacp_fields; 3074e7801d59Ssowmini else if (state.gs_stats) 3075e7801d59Ssowmini fields_str = all_stats_fields; 3076e7801d59Ssowmini else if (state.gs_extended) 3077e7801d59Ssowmini fields_str = all_extended_fields; 3078e7801d59Ssowmini else 3079e7801d59Ssowmini fields_str = all_fields; 3080e7801d59Ssowmini } 3081e7801d59Ssowmini 3082e7801d59Ssowmini if (state.gs_lacp) { 3083e7801d59Ssowmini pf = aggr_l_fields; 3084e7801d59Ssowmini } else if (state.gs_stats) { 3085e7801d59Ssowmini pf = aggr_s_fields; 3086e7801d59Ssowmini } else if (state.gs_extended) { 3087e7801d59Ssowmini pf = aggr_x_fields; 3088e7801d59Ssowmini } else { 3089e7801d59Ssowmini pf = laggr_fields; 3090e7801d59Ssowmini } 3091e7801d59Ssowmini 3092*8002d411SSowmini Varadhan if (state.gs_parsable) 3093*8002d411SSowmini Varadhan ofmtflags |= OFMT_PARSABLE; 3094*8002d411SSowmini Varadhan oferr = ofmt_open(fields_str, pf, ofmtflags, 0, &ofmt); 3095*8002d411SSowmini Varadhan dladm_ofmt_check(oferr, state.gs_parsable, ofmt); 3096*8002d411SSowmini Varadhan state.gs_ofmt = ofmt; 3097e7801d59Ssowmini 30987c478bd9Sstevel@tonic-gate if (s_arg) { 3099d62bc4baSyz147064 aggr_stats(linkid, &state, interval); 3100*8002d411SSowmini Varadhan ofmt_close(ofmt); 31017c478bd9Sstevel@tonic-gate return; 31027c478bd9Sstevel@tonic-gate } 31037c478bd9Sstevel@tonic-gate 3104d62bc4baSyz147064 if (linkid == DATALINK_ALL_LINKID) { 31054ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(show_aggr, handle, &state, 3106d62bc4baSyz147064 DATALINK_CLASS_AGGR, DATALINK_ANY_MEDIATYPE, flags); 3107d62bc4baSyz147064 } else { 31084ac67f02SAnurag S. Maskey (void) show_aggr(handle, linkid, &state); 3109d62bc4baSyz147064 if (state.gs_status != DLADM_STATUS_OK) { 3110d62bc4baSyz147064 die_dlerr(state.gs_status, "failed to show aggr %s", 3111d62bc4baSyz147064 argv[optind]); 3112d62bc4baSyz147064 } 3113d62bc4baSyz147064 } 3114*8002d411SSowmini Varadhan ofmt_close(ofmt); 31157c478bd9Sstevel@tonic-gate } 31167c478bd9Sstevel@tonic-gate 3117da14cebeSEric Cheng static dladm_status_t 3118da14cebeSEric Cheng print_phys_default(show_state_t *state, datalink_id_t linkid, 3119da14cebeSEric Cheng const char *link, uint32_t flags, uint32_t media) 31207c478bd9Sstevel@tonic-gate { 3121da14cebeSEric Cheng dladm_phys_attr_t dpa; 3122da14cebeSEric Cheng dladm_status_t status; 3123da14cebeSEric Cheng link_fields_buf_t pattr; 3124e7801d59Ssowmini 31254ac67f02SAnurag S. Maskey status = dladm_phys_info(handle, linkid, &dpa, state->ls_flags); 3126da14cebeSEric Cheng if (status != DLADM_STATUS_OK) 3127da14cebeSEric Cheng goto done; 31287c478bd9Sstevel@tonic-gate 3129da14cebeSEric Cheng (void) snprintf(pattr.link_phys_device, 3130da14cebeSEric Cheng sizeof (pattr.link_phys_device), "%s", dpa.dp_dev); 3131da14cebeSEric Cheng (void) dladm_media2str(media, pattr.link_phys_media); 3132da14cebeSEric Cheng if (state->ls_flags == DLADM_OPT_ACTIVE) { 3133da14cebeSEric Cheng boolean_t islink; 3134d62bc4baSyz147064 3135da14cebeSEric Cheng if (!dpa.dp_novanity) { 3136da14cebeSEric Cheng (void) strlcpy(pattr.link_name, link, 3137da14cebeSEric Cheng sizeof (pattr.link_name)); 3138da14cebeSEric Cheng islink = B_TRUE; 3139d62bc4baSyz147064 } else { 3140da14cebeSEric Cheng /* 3141da14cebeSEric Cheng * This is a physical link that does not have 3142da14cebeSEric Cheng * vanity naming support. 3143da14cebeSEric Cheng */ 3144da14cebeSEric Cheng (void) strlcpy(pattr.link_name, dpa.dp_dev, 3145da14cebeSEric Cheng sizeof (pattr.link_name)); 3146da14cebeSEric Cheng islink = B_FALSE; 31477c478bd9Sstevel@tonic-gate } 31487c478bd9Sstevel@tonic-gate 3149da14cebeSEric Cheng (void) get_linkstate(pattr.link_name, islink, 3150da14cebeSEric Cheng pattr.link_phys_state); 3151da14cebeSEric Cheng (void) snprintf(pattr.link_phys_speed, 3152da14cebeSEric Cheng sizeof (pattr.link_phys_speed), "%u", 3153da14cebeSEric Cheng (uint_t)((get_ifspeed(pattr.link_name, 3154da14cebeSEric Cheng islink)) / 1000000ull)); 3155da14cebeSEric Cheng (void) get_linkduplex(pattr.link_name, islink, 3156da14cebeSEric Cheng pattr.link_phys_duplex); 3157da14cebeSEric Cheng } else { 3158da14cebeSEric Cheng (void) snprintf(pattr.link_name, sizeof (pattr.link_name), 3159da14cebeSEric Cheng "%s", link); 3160da14cebeSEric Cheng (void) snprintf(pattr.link_flags, sizeof (pattr.link_flags), 3161da14cebeSEric Cheng "%c----", flags & DLADM_OPT_ACTIVE ? '-' : 'r'); 3162da14cebeSEric Cheng } 3163da14cebeSEric Cheng 3164*8002d411SSowmini Varadhan ofmt_print(state->ls_ofmt, &pattr); 3165da14cebeSEric Cheng 3166da14cebeSEric Cheng done: 3167da14cebeSEric Cheng return (status); 3168da14cebeSEric Cheng } 3169da14cebeSEric Cheng 3170da14cebeSEric Cheng typedef struct { 3171da14cebeSEric Cheng show_state_t *ms_state; 3172da14cebeSEric Cheng char *ms_link; 3173da14cebeSEric Cheng dladm_macaddr_attr_t *ms_mac_attr; 3174da14cebeSEric Cheng } print_phys_mac_state_t; 3175da14cebeSEric Cheng 3176*8002d411SSowmini Varadhan /* 3177*8002d411SSowmini Varadhan * callback for ofmt_print() 3178*8002d411SSowmini Varadhan */ 3179*8002d411SSowmini Varadhan static boolean_t 3180*8002d411SSowmini Varadhan print_phys_one_mac_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize) 3181da14cebeSEric Cheng { 3182*8002d411SSowmini Varadhan print_phys_mac_state_t *mac_state = ofarg->ofmt_cbarg; 3183da14cebeSEric Cheng dladm_macaddr_attr_t *attr = mac_state->ms_mac_attr; 3184da14cebeSEric Cheng boolean_t is_primary = (attr->ma_slot == 0); 3185*8002d411SSowmini Varadhan boolean_t is_parsable = mac_state->ms_state->ls_parsable; 3186da14cebeSEric Cheng 3187*8002d411SSowmini Varadhan switch (ofarg->ofmt_id) { 3188da14cebeSEric Cheng case PHYS_M_LINK: 3189*8002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%s", 3190*8002d411SSowmini Varadhan (is_primary || is_parsable) ? mac_state->ms_link : " "); 3191da14cebeSEric Cheng break; 3192da14cebeSEric Cheng case PHYS_M_SLOT: 3193da14cebeSEric Cheng if (is_primary) 3194*8002d411SSowmini Varadhan (void) snprintf(buf, bufsize, gettext("primary")); 3195da14cebeSEric Cheng else 3196*8002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%d", attr->ma_slot); 3197da14cebeSEric Cheng break; 3198da14cebeSEric Cheng case PHYS_M_ADDRESS: 3199da14cebeSEric Cheng (void) dladm_aggr_macaddr2str(attr->ma_addr, buf); 3200da14cebeSEric Cheng break; 3201da14cebeSEric Cheng case PHYS_M_INUSE: 3202*8002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%s", 3203da14cebeSEric Cheng attr->ma_flags & DLADM_MACADDR_USED ? gettext("yes") : 3204da14cebeSEric Cheng gettext("no")); 3205da14cebeSEric Cheng break; 3206da14cebeSEric Cheng case PHYS_M_CLIENT: 3207da14cebeSEric Cheng /* 3208da14cebeSEric Cheng * CR 6678526: resolve link id to actual link name if 3209da14cebeSEric Cheng * it is valid. 3210da14cebeSEric Cheng */ 3211*8002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%s", attr->ma_client_name); 3212da14cebeSEric Cheng break; 3213da14cebeSEric Cheng } 3214da14cebeSEric Cheng 3215*8002d411SSowmini Varadhan return (B_TRUE); 3216da14cebeSEric Cheng } 3217da14cebeSEric Cheng 3218da14cebeSEric Cheng typedef struct { 3219da14cebeSEric Cheng show_state_t *hs_state; 3220da14cebeSEric Cheng char *hs_link; 3221da14cebeSEric Cheng dladm_hwgrp_attr_t *hs_grp_attr; 3222da14cebeSEric Cheng } print_phys_hwgrp_state_t; 3223da14cebeSEric Cheng 3224*8002d411SSowmini Varadhan static boolean_t 3225*8002d411SSowmini Varadhan print_phys_one_hwgrp_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize) 3226da14cebeSEric Cheng { 3227*8002d411SSowmini Varadhan print_phys_hwgrp_state_t *hg_state = ofarg->ofmt_cbarg; 3228da14cebeSEric Cheng dladm_hwgrp_attr_t *attr = hg_state->hs_grp_attr; 3229da14cebeSEric Cheng 3230*8002d411SSowmini Varadhan switch (ofarg->ofmt_id) { 3231da14cebeSEric Cheng case PHYS_H_LINK: 3232*8002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%s", attr->hg_link_name); 3233da14cebeSEric Cheng break; 3234da14cebeSEric Cheng case PHYS_H_GROUP: 3235*8002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%d", attr->hg_grp_num); 3236da14cebeSEric Cheng break; 3237da14cebeSEric Cheng case PHYS_H_GRPTYPE: 3238*8002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%s", 3239da14cebeSEric Cheng attr->hg_grp_type == DLADM_HWGRP_TYPE_RX ? "RX" : "TX"); 3240da14cebeSEric Cheng break; 3241da14cebeSEric Cheng case PHYS_H_RINGS: 3242*8002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%d", attr->hg_n_rings); 3243da14cebeSEric Cheng break; 3244da14cebeSEric Cheng case PHYS_H_CLIENTS: 3245da14cebeSEric Cheng if (attr->hg_client_names[0] == '\0') { 3246*8002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "--"); 3247da14cebeSEric Cheng } else { 3248*8002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%s ", 3249da14cebeSEric Cheng attr->hg_client_names); 3250da14cebeSEric Cheng } 3251da14cebeSEric Cheng break; 3252da14cebeSEric Cheng } 3253da14cebeSEric Cheng 3254*8002d411SSowmini Varadhan return (B_TRUE); 3255da14cebeSEric Cheng } 3256da14cebeSEric Cheng 3257*8002d411SSowmini Varadhan /* 3258*8002d411SSowmini Varadhan * callback for dladm_walk_macaddr, invoked for each MAC address slot 3259*8002d411SSowmini Varadhan */ 3260da14cebeSEric Cheng static boolean_t 3261da14cebeSEric Cheng print_phys_mac_callback(void *arg, dladm_macaddr_attr_t *attr) 3262da14cebeSEric Cheng { 3263da14cebeSEric Cheng print_phys_mac_state_t *mac_state = arg; 3264da14cebeSEric Cheng show_state_t *state = mac_state->ms_state; 3265da14cebeSEric Cheng 3266da14cebeSEric Cheng mac_state->ms_mac_attr = attr; 3267*8002d411SSowmini Varadhan ofmt_print(state->ls_ofmt, mac_state); 3268da14cebeSEric Cheng 3269da14cebeSEric Cheng return (B_TRUE); 3270da14cebeSEric Cheng } 3271da14cebeSEric Cheng 3272*8002d411SSowmini Varadhan /* 3273*8002d411SSowmini Varadhan * invoked by show-phys -m for each physical data-link 3274*8002d411SSowmini Varadhan */ 3275da14cebeSEric Cheng static dladm_status_t 3276da14cebeSEric Cheng print_phys_mac(show_state_t *state, datalink_id_t linkid, char *link) 3277da14cebeSEric Cheng { 3278da14cebeSEric Cheng print_phys_mac_state_t mac_state; 3279da14cebeSEric Cheng 3280da14cebeSEric Cheng mac_state.ms_state = state; 3281da14cebeSEric Cheng mac_state.ms_link = link; 3282da14cebeSEric Cheng 32834ac67f02SAnurag S. Maskey return (dladm_walk_macaddr(handle, linkid, &mac_state, 3284da14cebeSEric Cheng print_phys_mac_callback)); 3285da14cebeSEric Cheng } 3286da14cebeSEric Cheng 3287*8002d411SSowmini Varadhan /* 3288*8002d411SSowmini Varadhan * callback for dladm_walk_hwgrp, invoked for each MAC hwgrp 3289*8002d411SSowmini Varadhan */ 3290da14cebeSEric Cheng static boolean_t 3291da14cebeSEric Cheng print_phys_hwgrp_callback(void *arg, dladm_hwgrp_attr_t *attr) 3292da14cebeSEric Cheng { 3293da14cebeSEric Cheng print_phys_hwgrp_state_t *hwgrp_state = arg; 3294da14cebeSEric Cheng show_state_t *state = hwgrp_state->hs_state; 3295da14cebeSEric Cheng 3296da14cebeSEric Cheng hwgrp_state->hs_grp_attr = attr; 3297*8002d411SSowmini Varadhan ofmt_print(state->ls_ofmt, hwgrp_state); 3298da14cebeSEric Cheng 3299da14cebeSEric Cheng return (B_TRUE); 3300da14cebeSEric Cheng } 3301da14cebeSEric Cheng 3302da14cebeSEric Cheng /* invoked by show-phys -H for each physical data-link */ 3303da14cebeSEric Cheng static dladm_status_t 3304da14cebeSEric Cheng print_phys_hwgrp(show_state_t *state, datalink_id_t linkid, char *link) 3305da14cebeSEric Cheng { 3306da14cebeSEric Cheng print_phys_hwgrp_state_t hwgrp_state; 3307da14cebeSEric Cheng 3308da14cebeSEric Cheng hwgrp_state.hs_state = state; 3309da14cebeSEric Cheng hwgrp_state.hs_link = link; 33104ac67f02SAnurag S. Maskey return (dladm_walk_hwgrp(handle, linkid, &hwgrp_state, 3311da14cebeSEric Cheng print_phys_hwgrp_callback)); 3312da14cebeSEric Cheng } 3313d62bc4baSyz147064 3314d62bc4baSyz147064 static dladm_status_t 3315da14cebeSEric Cheng print_phys(show_state_t *state, datalink_id_t linkid) 3316d62bc4baSyz147064 { 3317d62bc4baSyz147064 char link[MAXLINKNAMELEN]; 3318d62bc4baSyz147064 uint32_t flags; 3319da14cebeSEric Cheng dladm_status_t status; 3320d62bc4baSyz147064 datalink_class_t class; 3321d62bc4baSyz147064 uint32_t media; 3322d62bc4baSyz147064 33234ac67f02SAnurag S. Maskey if ((status = dladm_datalink_id2info(handle, linkid, &flags, &class, 33244ac67f02SAnurag S. Maskey &media, link, MAXLINKNAMELEN)) != DLADM_STATUS_OK) { 3325d62bc4baSyz147064 goto done; 3326d62bc4baSyz147064 } 3327d62bc4baSyz147064 3328d62bc4baSyz147064 if (class != DATALINK_CLASS_PHYS) { 3329d62bc4baSyz147064 status = DLADM_STATUS_BADARG; 3330d62bc4baSyz147064 goto done; 3331d62bc4baSyz147064 } 3332d62bc4baSyz147064 3333d62bc4baSyz147064 if (!(state->ls_flags & flags)) { 3334d62bc4baSyz147064 status = DLADM_STATUS_NOTFOUND; 3335d62bc4baSyz147064 goto done; 3336d62bc4baSyz147064 } 3337d62bc4baSyz147064 3338da14cebeSEric Cheng if (state->ls_mac) 3339da14cebeSEric Cheng status = print_phys_mac(state, linkid, link); 3340da14cebeSEric Cheng else if (state->ls_hwgrp) 3341da14cebeSEric Cheng status = print_phys_hwgrp(state, linkid, link); 3342da14cebeSEric Cheng else 3343da14cebeSEric Cheng status = print_phys_default(state, linkid, link, flags, media); 3344d62bc4baSyz147064 3345d62bc4baSyz147064 done: 3346d62bc4baSyz147064 return (status); 3347d62bc4baSyz147064 } 3348d62bc4baSyz147064 33494ac67f02SAnurag S. Maskey /* ARGSUSED */ 3350d62bc4baSyz147064 static int 33514ac67f02SAnurag S. Maskey show_phys(dladm_handle_t dh, datalink_id_t linkid, void *arg) 3352d62bc4baSyz147064 { 3353d62bc4baSyz147064 show_state_t *state = arg; 3354d62bc4baSyz147064 3355da14cebeSEric Cheng state->ls_status = print_phys(state, linkid); 3356d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 3357d62bc4baSyz147064 } 3358d62bc4baSyz147064 3359d62bc4baSyz147064 /* 3360d62bc4baSyz147064 * Print the active topology information. 3361d62bc4baSyz147064 */ 3362d62bc4baSyz147064 static dladm_status_t 3363e7801d59Ssowmini print_vlan(show_state_t *state, datalink_id_t linkid, link_fields_buf_t *l) 3364d62bc4baSyz147064 { 3365d62bc4baSyz147064 dladm_vlan_attr_t vinfo; 3366d62bc4baSyz147064 uint32_t flags; 3367d62bc4baSyz147064 dladm_status_t status; 3368d62bc4baSyz147064 33694ac67f02SAnurag S. Maskey if ((status = dladm_datalink_id2info(handle, linkid, &flags, NULL, NULL, 3370e7801d59Ssowmini l->link_name, sizeof (l->link_name))) != DLADM_STATUS_OK) { 3371d62bc4baSyz147064 goto done; 3372d62bc4baSyz147064 } 3373d62bc4baSyz147064 3374d62bc4baSyz147064 if (!(state->ls_flags & flags)) { 3375d62bc4baSyz147064 status = DLADM_STATUS_NOTFOUND; 3376d62bc4baSyz147064 goto done; 3377d62bc4baSyz147064 } 3378d62bc4baSyz147064 33794ac67f02SAnurag S. Maskey if ((status = dladm_vlan_info(handle, linkid, &vinfo, 33804ac67f02SAnurag S. Maskey state->ls_flags)) != DLADM_STATUS_OK || 33814ac67f02SAnurag S. Maskey (status = dladm_datalink_id2info(handle, vinfo.dv_linkid, NULL, 33824ac67f02SAnurag S. Maskey NULL, NULL, l->link_over, sizeof (l->link_over))) != 33834ac67f02SAnurag S. Maskey DLADM_STATUS_OK) { 3384d62bc4baSyz147064 goto done; 3385d62bc4baSyz147064 } 3386d62bc4baSyz147064 3387e7801d59Ssowmini (void) snprintf(l->link_vlan_vid, sizeof (l->link_vlan_vid), "%d", 3388e7801d59Ssowmini vinfo.dv_vid); 3389da14cebeSEric Cheng (void) snprintf(l->link_flags, sizeof (l->link_flags), "%c----", 3390da14cebeSEric Cheng vinfo.dv_force ? 'f' : '-'); 3391d62bc4baSyz147064 3392d62bc4baSyz147064 done: 3393d62bc4baSyz147064 return (status); 3394d62bc4baSyz147064 } 3395d62bc4baSyz147064 33964ac67f02SAnurag S. Maskey /* ARGSUSED */ 3397d62bc4baSyz147064 static int 33984ac67f02SAnurag S. Maskey show_vlan(dladm_handle_t dh, datalink_id_t linkid, void *arg) 3399d62bc4baSyz147064 { 3400d62bc4baSyz147064 show_state_t *state = arg; 3401d62bc4baSyz147064 dladm_status_t status; 3402e7801d59Ssowmini link_fields_buf_t lbuf; 3403d62bc4baSyz147064 34045f5c9f54SAnurag S. Maskey bzero(&lbuf, sizeof (link_fields_buf_t)); 3405e7801d59Ssowmini status = print_vlan(state, linkid, &lbuf); 3406d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 3407d62bc4baSyz147064 goto done; 3408e7801d59Ssowmini 3409*8002d411SSowmini Varadhan ofmt_print(state->ls_ofmt, &lbuf); 3410d62bc4baSyz147064 3411d62bc4baSyz147064 done: 3412d62bc4baSyz147064 state->ls_status = status; 3413d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 3414d62bc4baSyz147064 } 3415d62bc4baSyz147064 3416d62bc4baSyz147064 static void 34178d5c46e6Sam223141 do_show_phys(int argc, char *argv[], const char *use) 3418d62bc4baSyz147064 { 3419d62bc4baSyz147064 int option; 3420d62bc4baSyz147064 uint32_t flags = DLADM_OPT_ACTIVE; 3421d62bc4baSyz147064 boolean_t p_arg = B_FALSE; 3422e7801d59Ssowmini boolean_t o_arg = B_FALSE; 3423da14cebeSEric Cheng boolean_t m_arg = B_FALSE; 3424da14cebeSEric Cheng boolean_t H_arg = B_FALSE; 3425d62bc4baSyz147064 datalink_id_t linkid = DATALINK_ALL_LINKID; 3426d62bc4baSyz147064 show_state_t state; 3427d62bc4baSyz147064 dladm_status_t status; 3428e7801d59Ssowmini char *fields_str = NULL; 3429e7801d59Ssowmini char *all_active_fields = 3430e7801d59Ssowmini "link,media,state,speed,duplex,device"; 34315f5c9f54SAnurag S. Maskey char *all_inactive_fields = "link,device,media,flags"; 3432da14cebeSEric Cheng char *all_mac_fields = "link,slot,address,inuse,client"; 3433da14cebeSEric Cheng char *all_hwgrp_fields = 3434da14cebeSEric Cheng "link,group,grouptype,rings,clients"; 3435*8002d411SSowmini Varadhan ofmt_field_t *pf; 3436*8002d411SSowmini Varadhan ofmt_handle_t ofmt; 3437*8002d411SSowmini Varadhan ofmt_status_t oferr; 3438*8002d411SSowmini Varadhan uint_t ofmtflags = 0; 3439d62bc4baSyz147064 3440e7801d59Ssowmini bzero(&state, sizeof (state)); 3441d62bc4baSyz147064 opterr = 0; 3442da14cebeSEric Cheng while ((option = getopt_long(argc, argv, ":pPo:mH", 3443d62bc4baSyz147064 show_lopts, NULL)) != -1) { 3444d62bc4baSyz147064 switch (option) { 3445d62bc4baSyz147064 case 'p': 3446d62bc4baSyz147064 if (p_arg) 3447d62bc4baSyz147064 die_optdup(option); 3448d62bc4baSyz147064 3449d62bc4baSyz147064 p_arg = B_TRUE; 3450d62bc4baSyz147064 break; 3451d62bc4baSyz147064 case 'P': 3452d62bc4baSyz147064 if (flags != DLADM_OPT_ACTIVE) 3453d62bc4baSyz147064 die_optdup(option); 3454d62bc4baSyz147064 3455d62bc4baSyz147064 flags = DLADM_OPT_PERSIST; 3456d62bc4baSyz147064 break; 3457e7801d59Ssowmini case 'o': 3458e7801d59Ssowmini o_arg = B_TRUE; 3459e7801d59Ssowmini fields_str = optarg; 3460e7801d59Ssowmini break; 3461da14cebeSEric Cheng case 'm': 3462da14cebeSEric Cheng m_arg = B_TRUE; 3463da14cebeSEric Cheng break; 3464da14cebeSEric Cheng case 'H': 3465da14cebeSEric Cheng H_arg = B_TRUE; 3466da14cebeSEric Cheng break; 3467d62bc4baSyz147064 default: 34688d5c46e6Sam223141 die_opterr(optopt, option, use); 3469d62bc4baSyz147064 break; 3470d62bc4baSyz147064 } 3471d62bc4baSyz147064 } 3472d62bc4baSyz147064 34730d365605Sschuster if (p_arg && !o_arg) 34740d365605Sschuster die("-p requires -o"); 34750d365605Sschuster 3476da14cebeSEric Cheng if (m_arg && H_arg) 3477da14cebeSEric Cheng die("-m cannot combine with -H"); 3478da14cebeSEric Cheng 34790d365605Sschuster if (p_arg && strcasecmp(fields_str, "all") == 0) 34800d365605Sschuster die("\"-o all\" is invalid with -p"); 34810d365605Sschuster 3482d62bc4baSyz147064 /* get link name (optional last argument) */ 3483d62bc4baSyz147064 if (optind == (argc-1)) { 34844ac67f02SAnurag S. Maskey if ((status = dladm_name2info(handle, argv[optind], &linkid, 34854ac67f02SAnurag S. Maskey NULL, NULL, NULL)) != DLADM_STATUS_OK) { 3486d62bc4baSyz147064 die_dlerr(status, "link %s is not valid", argv[optind]); 3487d62bc4baSyz147064 } 3488d62bc4baSyz147064 } else if (optind != argc) { 3489d62bc4baSyz147064 usage(); 3490d62bc4baSyz147064 } 3491d62bc4baSyz147064 3492*8002d411SSowmini Varadhan state.ls_parsable = p_arg; 3493d62bc4baSyz147064 state.ls_flags = flags; 3494d62bc4baSyz147064 state.ls_donefirst = B_FALSE; 3495da14cebeSEric Cheng state.ls_mac = m_arg; 3496da14cebeSEric Cheng state.ls_hwgrp = H_arg; 3497d62bc4baSyz147064 3498da14cebeSEric Cheng if (m_arg && !(flags & DLADM_OPT_ACTIVE)) { 3499da14cebeSEric Cheng /* 3500da14cebeSEric Cheng * We can only display the factory MAC addresses of 3501da14cebeSEric Cheng * active data-links. 3502da14cebeSEric Cheng */ 3503da14cebeSEric Cheng die("-m not compatible with -P"); 3504e7801d59Ssowmini } 3505e7801d59Ssowmini 3506da14cebeSEric Cheng if (!o_arg || (o_arg && strcasecmp(fields_str, "all") == 0)) { 3507da14cebeSEric Cheng if (state.ls_mac) 3508da14cebeSEric Cheng fields_str = all_mac_fields; 3509da14cebeSEric Cheng else if (state.ls_hwgrp) 3510da14cebeSEric Cheng fields_str = all_hwgrp_fields; 3511da14cebeSEric Cheng else if (state.ls_flags & DLADM_OPT_ACTIVE) { 3512da14cebeSEric Cheng fields_str = all_active_fields; 3513da14cebeSEric Cheng } else { 3514da14cebeSEric Cheng fields_str = all_inactive_fields; 3515da14cebeSEric Cheng } 3516da14cebeSEric Cheng } 3517da14cebeSEric Cheng 3518da14cebeSEric Cheng if (state.ls_mac) { 3519da14cebeSEric Cheng pf = phys_m_fields; 3520da14cebeSEric Cheng } else if (state.ls_hwgrp) { 3521da14cebeSEric Cheng pf = phys_h_fields; 3522da14cebeSEric Cheng } else { 3523da14cebeSEric Cheng pf = phys_fields; 3524da14cebeSEric Cheng } 3525da14cebeSEric Cheng 3526*8002d411SSowmini Varadhan if (state.ls_parsable) 3527*8002d411SSowmini Varadhan ofmtflags |= OFMT_PARSABLE; 3528*8002d411SSowmini Varadhan oferr = ofmt_open(fields_str, pf, ofmtflags, 0, &ofmt); 3529*8002d411SSowmini Varadhan dladm_ofmt_check(oferr, state.ls_parsable, ofmt); 3530*8002d411SSowmini Varadhan state.ls_ofmt = ofmt; 3531e7801d59Ssowmini 3532d62bc4baSyz147064 if (linkid == DATALINK_ALL_LINKID) { 35334ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(show_phys, handle, &state, 3534d62bc4baSyz147064 DATALINK_CLASS_PHYS, DATALINK_ANY_MEDIATYPE, flags); 3535d62bc4baSyz147064 } else { 35364ac67f02SAnurag S. Maskey (void) show_phys(handle, linkid, &state); 3537d62bc4baSyz147064 if (state.ls_status != DLADM_STATUS_OK) { 3538d62bc4baSyz147064 die_dlerr(state.ls_status, 3539d62bc4baSyz147064 "failed to show physical link %s", argv[optind]); 3540d62bc4baSyz147064 } 3541d62bc4baSyz147064 } 3542*8002d411SSowmini Varadhan ofmt_close(ofmt); 3543d62bc4baSyz147064 } 3544d62bc4baSyz147064 3545d62bc4baSyz147064 static void 35468d5c46e6Sam223141 do_show_vlan(int argc, char *argv[], const char *use) 3547d62bc4baSyz147064 { 3548d62bc4baSyz147064 int option; 3549d62bc4baSyz147064 uint32_t flags = DLADM_OPT_ACTIVE; 3550d62bc4baSyz147064 boolean_t p_arg = B_FALSE; 3551d62bc4baSyz147064 datalink_id_t linkid = DATALINK_ALL_LINKID; 3552d62bc4baSyz147064 show_state_t state; 3553d62bc4baSyz147064 dladm_status_t status; 3554e7801d59Ssowmini boolean_t o_arg = B_FALSE; 3555e7801d59Ssowmini char *fields_str = NULL; 3556*8002d411SSowmini Varadhan ofmt_handle_t ofmt; 3557*8002d411SSowmini Varadhan ofmt_status_t oferr; 3558*8002d411SSowmini Varadhan uint_t ofmtflags = 0; 3559e7801d59Ssowmini 3560e7801d59Ssowmini bzero(&state, sizeof (state)); 3561d62bc4baSyz147064 3562d62bc4baSyz147064 opterr = 0; 3563e7801d59Ssowmini while ((option = getopt_long(argc, argv, ":pPo:", 3564d62bc4baSyz147064 show_lopts, NULL)) != -1) { 3565d62bc4baSyz147064 switch (option) { 3566d62bc4baSyz147064 case 'p': 3567d62bc4baSyz147064 if (p_arg) 3568d62bc4baSyz147064 die_optdup(option); 3569d62bc4baSyz147064 3570d62bc4baSyz147064 p_arg = B_TRUE; 3571d62bc4baSyz147064 break; 3572d62bc4baSyz147064 case 'P': 3573d62bc4baSyz147064 if (flags != DLADM_OPT_ACTIVE) 3574d62bc4baSyz147064 die_optdup(option); 3575d62bc4baSyz147064 3576d62bc4baSyz147064 flags = DLADM_OPT_PERSIST; 3577d62bc4baSyz147064 break; 3578e7801d59Ssowmini case 'o': 3579e7801d59Ssowmini o_arg = B_TRUE; 3580e7801d59Ssowmini fields_str = optarg; 3581e7801d59Ssowmini break; 3582d62bc4baSyz147064 default: 35838d5c46e6Sam223141 die_opterr(optopt, option, use); 3584d62bc4baSyz147064 break; 3585d62bc4baSyz147064 } 3586d62bc4baSyz147064 } 3587d62bc4baSyz147064 3588d62bc4baSyz147064 /* get link name (optional last argument) */ 3589d62bc4baSyz147064 if (optind == (argc-1)) { 35904ac67f02SAnurag S. Maskey if ((status = dladm_name2info(handle, argv[optind], &linkid, 35914ac67f02SAnurag S. Maskey NULL, NULL, NULL)) != DLADM_STATUS_OK) { 3592d62bc4baSyz147064 die_dlerr(status, "link %s is not valid", argv[optind]); 3593d62bc4baSyz147064 } 3594d62bc4baSyz147064 } else if (optind != argc) { 3595d62bc4baSyz147064 usage(); 3596d62bc4baSyz147064 } 3597d62bc4baSyz147064 3598*8002d411SSowmini Varadhan state.ls_parsable = p_arg; 3599d62bc4baSyz147064 state.ls_flags = flags; 3600d62bc4baSyz147064 state.ls_donefirst = B_FALSE; 3601d62bc4baSyz147064 3602e7801d59Ssowmini if (!o_arg || (o_arg && strcasecmp(fields_str, "all") == 0)) 3603*8002d411SSowmini Varadhan fields_str = NULL; 3604e7801d59Ssowmini 3605*8002d411SSowmini Varadhan if (state.ls_parsable) 3606*8002d411SSowmini Varadhan ofmtflags |= OFMT_PARSABLE; 3607*8002d411SSowmini Varadhan oferr = ofmt_open(fields_str, vlan_fields, ofmtflags, 0, &ofmt); 3608*8002d411SSowmini Varadhan dladm_ofmt_check(oferr, state.ls_parsable, ofmt); 3609*8002d411SSowmini Varadhan state.ls_ofmt = ofmt; 3610e7801d59Ssowmini 3611d62bc4baSyz147064 if (linkid == DATALINK_ALL_LINKID) { 36124ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(show_vlan, handle, &state, 3613d62bc4baSyz147064 DATALINK_CLASS_VLAN, DATALINK_ANY_MEDIATYPE, flags); 3614d62bc4baSyz147064 } else { 36154ac67f02SAnurag S. Maskey (void) show_vlan(handle, linkid, &state); 3616d62bc4baSyz147064 if (state.ls_status != DLADM_STATUS_OK) { 3617d62bc4baSyz147064 die_dlerr(state.ls_status, "failed to show vlan %s", 3618d62bc4baSyz147064 argv[optind]); 3619d62bc4baSyz147064 } 3620d62bc4baSyz147064 } 3621*8002d411SSowmini Varadhan ofmt_close(ofmt); 3622d62bc4baSyz147064 } 3623d62bc4baSyz147064 3624d62bc4baSyz147064 static void 3625da14cebeSEric Cheng do_create_vnic(int argc, char *argv[], const char *use) 3626da14cebeSEric Cheng { 3627da14cebeSEric Cheng datalink_id_t linkid, dev_linkid; 3628da14cebeSEric Cheng char devname[MAXLINKNAMELEN]; 3629da14cebeSEric Cheng char name[MAXLINKNAMELEN]; 3630da14cebeSEric Cheng boolean_t l_arg = B_FALSE; 3631da14cebeSEric Cheng uint32_t flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST; 3632da14cebeSEric Cheng char *altroot = NULL; 3633da14cebeSEric Cheng char option; 3634da14cebeSEric Cheng char *endp = NULL; 3635da14cebeSEric Cheng dladm_status_t status; 3636da14cebeSEric Cheng vnic_mac_addr_type_t mac_addr_type = VNIC_MAC_ADDR_TYPE_AUTO; 3637da14cebeSEric Cheng uchar_t *mac_addr; 3638da14cebeSEric Cheng int mac_slot = -1, maclen = 0, mac_prefix_len = 0; 363963a6526dSMichael Lim char propstr[DLADM_STRSIZE]; 3640da14cebeSEric Cheng dladm_arg_list_t *proplist = NULL; 3641285e94f9SMichael Lim int vid = 0; 3642da14cebeSEric Cheng 3643da14cebeSEric Cheng opterr = 0; 364463a6526dSMichael Lim bzero(propstr, DLADM_STRSIZE); 364563a6526dSMichael Lim 3646da14cebeSEric Cheng while ((option = getopt_long(argc, argv, ":tfR:l:m:n:p:r:v:H", 3647da14cebeSEric Cheng vnic_lopts, NULL)) != -1) { 3648da14cebeSEric Cheng switch (option) { 3649da14cebeSEric Cheng case 't': 3650da14cebeSEric Cheng flags &= ~DLADM_OPT_PERSIST; 3651da14cebeSEric Cheng break; 3652da14cebeSEric Cheng case 'R': 3653da14cebeSEric Cheng altroot = optarg; 3654da14cebeSEric Cheng break; 3655da14cebeSEric Cheng case 'l': 3656da14cebeSEric Cheng if (strlcpy(devname, optarg, MAXLINKNAMELEN) >= 3657da14cebeSEric Cheng MAXLINKNAMELEN) 3658da14cebeSEric Cheng die("link name too long"); 3659da14cebeSEric Cheng l_arg = B_TRUE; 3660da14cebeSEric Cheng break; 3661da14cebeSEric Cheng case 'm': 3662da14cebeSEric Cheng if (strcmp(optarg, "fixed") == 0) { 3663da14cebeSEric Cheng /* 3664da14cebeSEric Cheng * A fixed MAC address must be specified 3665da14cebeSEric Cheng * by its value, not by the keyword 'fixed'. 3666da14cebeSEric Cheng */ 3667da14cebeSEric Cheng die("'fixed' is not a valid MAC address"); 3668da14cebeSEric Cheng } 3669da14cebeSEric Cheng if (dladm_vnic_str2macaddrtype(optarg, 3670da14cebeSEric Cheng &mac_addr_type) != DLADM_STATUS_OK) { 3671da14cebeSEric Cheng mac_addr_type = VNIC_MAC_ADDR_TYPE_FIXED; 3672da14cebeSEric Cheng /* MAC address specified by value */ 3673da14cebeSEric Cheng mac_addr = _link_aton(optarg, &maclen); 3674da14cebeSEric Cheng if (mac_addr == NULL) { 3675da14cebeSEric Cheng if (maclen == -1) 3676da14cebeSEric Cheng die("invalid MAC address"); 3677da14cebeSEric Cheng else 3678da14cebeSEric Cheng die("out of memory"); 3679da14cebeSEric Cheng } 3680da14cebeSEric Cheng } 3681da14cebeSEric Cheng break; 3682da14cebeSEric Cheng case 'n': 3683da14cebeSEric Cheng errno = 0; 3684da14cebeSEric Cheng mac_slot = (int)strtol(optarg, &endp, 10); 3685da14cebeSEric Cheng if (errno != 0 || *endp != '\0') 3686da14cebeSEric Cheng die("invalid slot number"); 3687da14cebeSEric Cheng break; 3688da14cebeSEric Cheng case 'p': 368963a6526dSMichael Lim (void) strlcat(propstr, optarg, DLADM_STRSIZE); 369063a6526dSMichael Lim if (strlcat(propstr, ",", DLADM_STRSIZE) >= 369163a6526dSMichael Lim DLADM_STRSIZE) 369263a6526dSMichael Lim die("property list too long '%s'", propstr); 3693da14cebeSEric Cheng break; 3694da14cebeSEric Cheng case 'r': 3695da14cebeSEric Cheng mac_addr = _link_aton(optarg, &mac_prefix_len); 3696da14cebeSEric Cheng if (mac_addr == NULL) { 3697da14cebeSEric Cheng if (mac_prefix_len == -1) 3698da14cebeSEric Cheng die("invalid MAC address"); 3699da14cebeSEric Cheng else 3700da14cebeSEric Cheng die("out of memory"); 3701da14cebeSEric Cheng } 3702da14cebeSEric Cheng break; 3703da14cebeSEric Cheng case 'v': 3704285e94f9SMichael Lim if (vid != 0) 3705285e94f9SMichael Lim die_optdup(option); 3706285e94f9SMichael Lim 3707285e94f9SMichael Lim if (!str2int(optarg, &vid) || vid < 1 || vid > 4094) 3708285e94f9SMichael Lim die("invalid VLAN identifier '%s'", optarg); 3709285e94f9SMichael Lim 3710da14cebeSEric Cheng break; 3711da14cebeSEric Cheng case 'f': 3712da14cebeSEric Cheng flags |= DLADM_OPT_FORCE; 3713da14cebeSEric Cheng break; 3714da14cebeSEric Cheng case 'H': 3715da14cebeSEric Cheng flags |= DLADM_OPT_HWRINGS; 3716da14cebeSEric Cheng break; 3717da14cebeSEric Cheng default: 3718da14cebeSEric Cheng die_opterr(optopt, option, use); 3719da14cebeSEric Cheng } 3720da14cebeSEric Cheng } 3721da14cebeSEric Cheng 3722da14cebeSEric Cheng /* 3723da14cebeSEric Cheng * 'f' - force, flag can be specified only with 'v' - vlan. 3724da14cebeSEric Cheng */ 3725da14cebeSEric Cheng if ((flags & DLADM_OPT_FORCE) != 0 && vid == 0) 3726da14cebeSEric Cheng die("-f option can only be used with -v"); 3727da14cebeSEric Cheng 3728da14cebeSEric Cheng if (mac_prefix_len != 0 && mac_addr_type != VNIC_MAC_ADDR_TYPE_RANDOM && 3729da14cebeSEric Cheng mac_addr_type != VNIC_MAC_ADDR_TYPE_FIXED) 3730da14cebeSEric Cheng usage(); 3731da14cebeSEric Cheng 3732da14cebeSEric Cheng /* check required options */ 3733da14cebeSEric Cheng if (!l_arg) 3734da14cebeSEric Cheng usage(); 3735da14cebeSEric Cheng 3736da14cebeSEric Cheng if (mac_slot != -1 && mac_addr_type != VNIC_MAC_ADDR_TYPE_FACTORY) 3737da14cebeSEric Cheng usage(); 3738da14cebeSEric Cheng 3739da14cebeSEric Cheng /* the VNIC id is the required operand */ 3740da14cebeSEric Cheng if (optind != (argc - 1)) 3741da14cebeSEric Cheng usage(); 3742da14cebeSEric Cheng 3743da14cebeSEric Cheng if (strlcpy(name, argv[optind], MAXLINKNAMELEN) >= MAXLINKNAMELEN) 3744da14cebeSEric Cheng die("link name too long '%s'", argv[optind]); 3745da14cebeSEric Cheng 3746da14cebeSEric Cheng if (!dladm_valid_linkname(name)) 3747da14cebeSEric Cheng die("invalid link name '%s'", argv[optind]); 3748da14cebeSEric Cheng 3749da14cebeSEric Cheng if (altroot != NULL) 3750da14cebeSEric Cheng altroot_cmd(altroot, argc, argv); 3751da14cebeSEric Cheng 37524ac67f02SAnurag S. Maskey if (dladm_name2info(handle, devname, &dev_linkid, NULL, NULL, NULL) != 3753da14cebeSEric Cheng DLADM_STATUS_OK) 3754da14cebeSEric Cheng die("invalid link name '%s'", devname); 3755da14cebeSEric Cheng 375663a6526dSMichael Lim if (dladm_parse_link_props(propstr, &proplist, B_FALSE) 375763a6526dSMichael Lim != DLADM_STATUS_OK) 375863a6526dSMichael Lim die("invalid vnic property"); 375963a6526dSMichael Lim 37604ac67f02SAnurag S. Maskey status = dladm_vnic_create(handle, name, dev_linkid, mac_addr_type, 37614ac67f02SAnurag S. Maskey mac_addr, maclen, &mac_slot, mac_prefix_len, vid, &linkid, proplist, 37624ac67f02SAnurag S. Maskey flags); 3763da14cebeSEric Cheng if (status != DLADM_STATUS_OK) 3764da14cebeSEric Cheng die_dlerr(status, "vnic creation over %s failed", devname); 3765da14cebeSEric Cheng 3766da14cebeSEric Cheng dladm_free_props(proplist); 3767da14cebeSEric Cheng } 3768da14cebeSEric Cheng 3769da14cebeSEric Cheng static void 3770da14cebeSEric Cheng do_etherstub_check(const char *name, datalink_id_t linkid, boolean_t etherstub, 3771da14cebeSEric Cheng uint32_t flags) 3772da14cebeSEric Cheng { 3773da14cebeSEric Cheng boolean_t is_etherstub; 3774da14cebeSEric Cheng dladm_vnic_attr_t attr; 3775da14cebeSEric Cheng 37764ac67f02SAnurag S. Maskey if (dladm_vnic_info(handle, linkid, &attr, flags) != DLADM_STATUS_OK) { 3777da14cebeSEric Cheng /* 3778da14cebeSEric Cheng * Let the delete continue anyway. 3779da14cebeSEric Cheng */ 3780da14cebeSEric Cheng return; 3781da14cebeSEric Cheng } 3782da14cebeSEric Cheng is_etherstub = (attr.va_link_id == DATALINK_INVALID_LINKID); 3783da14cebeSEric Cheng if (is_etherstub != etherstub) { 3784da14cebeSEric Cheng die("'%s' is not %s", name, 3785da14cebeSEric Cheng (is_etherstub ? "a vnic" : "an etherstub")); 3786da14cebeSEric Cheng } 3787da14cebeSEric Cheng } 3788da14cebeSEric Cheng 3789da14cebeSEric Cheng static void 3790da14cebeSEric Cheng do_delete_vnic_common(int argc, char *argv[], const char *use, 3791da14cebeSEric Cheng boolean_t etherstub) 3792da14cebeSEric Cheng { 3793da14cebeSEric Cheng char option; 3794da14cebeSEric Cheng uint32_t flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST; 3795da14cebeSEric Cheng datalink_id_t linkid; 3796da14cebeSEric Cheng char *altroot = NULL; 3797da14cebeSEric Cheng dladm_status_t status; 3798da14cebeSEric Cheng 3799da14cebeSEric Cheng opterr = 0; 3800da14cebeSEric Cheng while ((option = getopt_long(argc, argv, ":R:t", lopts, 3801da14cebeSEric Cheng NULL)) != -1) { 3802da14cebeSEric Cheng switch (option) { 3803da14cebeSEric Cheng case 't': 3804da14cebeSEric Cheng flags &= ~DLADM_OPT_PERSIST; 3805da14cebeSEric Cheng break; 3806da14cebeSEric Cheng case 'R': 3807da14cebeSEric Cheng altroot = optarg; 3808da14cebeSEric Cheng break; 3809da14cebeSEric Cheng default: 3810da14cebeSEric Cheng die_opterr(optopt, option, use); 3811da14cebeSEric Cheng } 3812da14cebeSEric Cheng } 3813da14cebeSEric Cheng 3814da14cebeSEric Cheng /* get vnic name (required last argument) */ 3815da14cebeSEric Cheng if (optind != (argc - 1)) 3816da14cebeSEric Cheng usage(); 3817da14cebeSEric Cheng 3818da14cebeSEric Cheng if (altroot != NULL) 3819da14cebeSEric Cheng altroot_cmd(altroot, argc, argv); 3820da14cebeSEric Cheng 38214ac67f02SAnurag S. Maskey status = dladm_name2info(handle, argv[optind], &linkid, NULL, NULL, 38224ac67f02SAnurag S. Maskey NULL); 3823da14cebeSEric Cheng if (status != DLADM_STATUS_OK) 3824da14cebeSEric Cheng die("invalid link name '%s'", argv[optind]); 3825da14cebeSEric Cheng 3826da14cebeSEric Cheng if ((flags & DLADM_OPT_ACTIVE) != 0) { 3827da14cebeSEric Cheng do_etherstub_check(argv[optind], linkid, etherstub, 3828da14cebeSEric Cheng DLADM_OPT_ACTIVE); 3829da14cebeSEric Cheng } 3830da14cebeSEric Cheng if ((flags & DLADM_OPT_PERSIST) != 0) { 3831da14cebeSEric Cheng do_etherstub_check(argv[optind], linkid, etherstub, 3832da14cebeSEric Cheng DLADM_OPT_PERSIST); 3833da14cebeSEric Cheng } 3834da14cebeSEric Cheng 38354ac67f02SAnurag S. Maskey status = dladm_vnic_delete(handle, linkid, flags); 3836da14cebeSEric Cheng if (status != DLADM_STATUS_OK) 3837da14cebeSEric Cheng die_dlerr(status, "vnic deletion failed"); 3838da14cebeSEric Cheng } 3839da14cebeSEric Cheng 3840da14cebeSEric Cheng static void 3841da14cebeSEric Cheng do_delete_vnic(int argc, char *argv[], const char *use) 3842da14cebeSEric Cheng { 3843da14cebeSEric Cheng do_delete_vnic_common(argc, argv, use, B_FALSE); 3844da14cebeSEric Cheng } 3845da14cebeSEric Cheng 3846da14cebeSEric Cheng /* ARGSUSED */ 3847da14cebeSEric Cheng static void 3848da14cebeSEric Cheng do_up_vnic_common(int argc, char *argv[], const char *use, boolean_t vlan) 3849da14cebeSEric Cheng { 3850da14cebeSEric Cheng datalink_id_t linkid = DATALINK_ALL_LINKID; 3851da14cebeSEric Cheng dladm_status_t status; 3852da14cebeSEric Cheng char *type; 3853da14cebeSEric Cheng 3854da14cebeSEric Cheng type = vlan ? "vlan" : "vnic"; 3855da14cebeSEric Cheng 3856da14cebeSEric Cheng /* 3857da14cebeSEric Cheng * get the id or the name of the vnic/vlan (optional last argument) 3858da14cebeSEric Cheng */ 3859da14cebeSEric Cheng if (argc == 2) { 38604ac67f02SAnurag S. Maskey status = dladm_name2info(handle, argv[1], &linkid, NULL, NULL, 38614ac67f02SAnurag S. Maskey NULL); 3862da14cebeSEric Cheng if (status != DLADM_STATUS_OK) 3863da14cebeSEric Cheng goto done; 3864da14cebeSEric Cheng 3865da14cebeSEric Cheng } else if (argc > 2) { 3866da14cebeSEric Cheng usage(); 3867da14cebeSEric Cheng } 3868da14cebeSEric Cheng 3869da14cebeSEric Cheng if (vlan) 38704ac67f02SAnurag S. Maskey status = dladm_vlan_up(handle, linkid); 3871da14cebeSEric Cheng else 38724ac67f02SAnurag S. Maskey status = dladm_vnic_up(handle, linkid, 0); 3873da14cebeSEric Cheng 3874da14cebeSEric Cheng done: 3875da14cebeSEric Cheng if (status != DLADM_STATUS_OK) { 3876da14cebeSEric Cheng if (argc == 2) { 3877da14cebeSEric Cheng die_dlerr(status, 3878da14cebeSEric Cheng "could not bring up %s '%s'", type, argv[1]); 3879da14cebeSEric Cheng } else { 3880da14cebeSEric Cheng die_dlerr(status, "could not bring %ss up", type); 3881da14cebeSEric Cheng } 3882da14cebeSEric Cheng } 3883da14cebeSEric Cheng } 3884da14cebeSEric Cheng 3885da14cebeSEric Cheng static void 3886da14cebeSEric Cheng do_up_vnic(int argc, char *argv[], const char *use) 3887da14cebeSEric Cheng { 3888da14cebeSEric Cheng do_up_vnic_common(argc, argv, use, B_FALSE); 3889da14cebeSEric Cheng } 3890da14cebeSEric Cheng 3891da14cebeSEric Cheng static void 3892da14cebeSEric Cheng dump_vnics_head(const char *dev) 3893da14cebeSEric Cheng { 3894da14cebeSEric Cheng if (strlen(dev)) 3895da14cebeSEric Cheng (void) printf("%s", dev); 3896da14cebeSEric Cheng 3897da14cebeSEric Cheng (void) printf("\tipackets rbytes opackets obytes "); 3898da14cebeSEric Cheng 3899da14cebeSEric Cheng if (strlen(dev)) 3900da14cebeSEric Cheng (void) printf("%%ipkts %%opkts\n"); 3901da14cebeSEric Cheng else 3902da14cebeSEric Cheng (void) printf("\n"); 3903da14cebeSEric Cheng } 3904da14cebeSEric Cheng 3905da14cebeSEric Cheng static void 3906da14cebeSEric Cheng dump_vnic_stat(const char *name, datalink_id_t vnic_id, 3907da14cebeSEric Cheng show_vnic_state_t *state, pktsum_t *vnic_stats, pktsum_t *tot_stats) 3908da14cebeSEric Cheng { 3909da14cebeSEric Cheng pktsum_t diff_stats; 3910da14cebeSEric Cheng pktsum_t *old_stats = &state->vs_prevstats[vnic_id]; 3911da14cebeSEric Cheng 3912da14cebeSEric Cheng dladm_stats_diff(&diff_stats, vnic_stats, old_stats); 3913da14cebeSEric Cheng 3914da14cebeSEric Cheng (void) printf("%s", name); 3915da14cebeSEric Cheng 3916da14cebeSEric Cheng (void) printf("\t%-10llu", diff_stats.ipackets); 3917da14cebeSEric Cheng (void) printf("%-12llu", diff_stats.rbytes); 3918da14cebeSEric Cheng (void) printf("%-10llu", diff_stats.opackets); 3919da14cebeSEric Cheng (void) printf("%-12llu", diff_stats.obytes); 3920da14cebeSEric Cheng 3921da14cebeSEric Cheng if (tot_stats) { 3922da14cebeSEric Cheng if (tot_stats->ipackets == 0) { 3923da14cebeSEric Cheng (void) printf("\t-"); 3924da14cebeSEric Cheng } else { 3925da14cebeSEric Cheng (void) printf("\t%-6.1f", (double)diff_stats.ipackets/ 3926da14cebeSEric Cheng (double)tot_stats->ipackets * 100); 3927da14cebeSEric Cheng } 3928da14cebeSEric Cheng if (tot_stats->opackets == 0) { 3929da14cebeSEric Cheng (void) printf("\t-"); 3930da14cebeSEric Cheng } else { 3931da14cebeSEric Cheng (void) printf("\t%-6.1f", (double)diff_stats.opackets/ 3932da14cebeSEric Cheng (double)tot_stats->opackets * 100); 3933da14cebeSEric Cheng } 3934da14cebeSEric Cheng } 3935da14cebeSEric Cheng (void) printf("\n"); 3936da14cebeSEric Cheng 3937da14cebeSEric Cheng *old_stats = *vnic_stats; 3938da14cebeSEric Cheng } 3939da14cebeSEric Cheng 3940da14cebeSEric Cheng /* 3941da14cebeSEric Cheng * Called from the walker dladm_vnic_walk_sys() for each vnic to display 3942da14cebeSEric Cheng * vnic information or statistics. 3943da14cebeSEric Cheng */ 3944da14cebeSEric Cheng static dladm_status_t 3945da14cebeSEric Cheng print_vnic(show_vnic_state_t *state, datalink_id_t linkid) 3946da14cebeSEric Cheng { 3947da14cebeSEric Cheng dladm_vnic_attr_t attr, *vnic = &attr; 3948da14cebeSEric Cheng dladm_status_t status; 3949da14cebeSEric Cheng boolean_t is_etherstub; 3950da14cebeSEric Cheng char devname[MAXLINKNAMELEN]; 3951da14cebeSEric Cheng char vnic_name[MAXLINKNAMELEN]; 3952da14cebeSEric Cheng char mstr[MAXMACADDRLEN * 3]; 3953da14cebeSEric Cheng vnic_fields_buf_t vbuf; 3954da14cebeSEric Cheng 39554ac67f02SAnurag S. Maskey if ((status = dladm_vnic_info(handle, linkid, vnic, state->vs_flags)) != 3956da14cebeSEric Cheng DLADM_STATUS_OK) 3957da14cebeSEric Cheng return (status); 3958da14cebeSEric Cheng 3959da14cebeSEric Cheng is_etherstub = (vnic->va_link_id == DATALINK_INVALID_LINKID); 3960da14cebeSEric Cheng if (state->vs_etherstub != is_etherstub) { 3961da14cebeSEric Cheng /* 3962da14cebeSEric Cheng * Want all etherstub but it's not one, or want 3963da14cebeSEric Cheng * non-etherstub and it's one. 3964da14cebeSEric Cheng */ 3965da14cebeSEric Cheng return (DLADM_STATUS_OK); 3966da14cebeSEric Cheng } 3967da14cebeSEric Cheng 3968da14cebeSEric Cheng if (state->vs_link_id != DATALINK_ALL_LINKID) { 3969da14cebeSEric Cheng if (state->vs_link_id != vnic->va_link_id) 3970da14cebeSEric Cheng return (DLADM_STATUS_OK); 3971da14cebeSEric Cheng } 3972da14cebeSEric Cheng 39734ac67f02SAnurag S. Maskey if (dladm_datalink_id2info(handle, linkid, NULL, NULL, 3974da14cebeSEric Cheng NULL, vnic_name, sizeof (vnic_name)) != DLADM_STATUS_OK) 3975da14cebeSEric Cheng return (DLADM_STATUS_BADARG); 3976da14cebeSEric Cheng 3977da14cebeSEric Cheng bzero(devname, sizeof (devname)); 3978da14cebeSEric Cheng if (!is_etherstub && 39794ac67f02SAnurag S. Maskey dladm_datalink_id2info(handle, vnic->va_link_id, NULL, NULL, 3980da14cebeSEric Cheng NULL, devname, sizeof (devname)) != DLADM_STATUS_OK) 3981da14cebeSEric Cheng return (DLADM_STATUS_BADARG); 3982da14cebeSEric Cheng 3983da14cebeSEric Cheng state->vs_found = B_TRUE; 3984da14cebeSEric Cheng if (state->vs_stats) { 3985da14cebeSEric Cheng /* print vnic statistics */ 3986da14cebeSEric Cheng pktsum_t vnic_stats; 3987da14cebeSEric Cheng 3988da14cebeSEric Cheng if (state->vs_firstonly) { 3989da14cebeSEric Cheng if (state->vs_donefirst) 3990da14cebeSEric Cheng return (0); 3991da14cebeSEric Cheng state->vs_donefirst = B_TRUE; 3992da14cebeSEric Cheng } 3993da14cebeSEric Cheng 3994da14cebeSEric Cheng if (!state->vs_printstats) { 3995da14cebeSEric Cheng /* 3996da14cebeSEric Cheng * get vnic statistics and add to the sum for the 3997da14cebeSEric Cheng * named device. 3998da14cebeSEric Cheng */ 3999da14cebeSEric Cheng get_link_stats(vnic_name, &vnic_stats); 4000da14cebeSEric Cheng dladm_stats_total(&state->vs_totalstats, &vnic_stats, 4001da14cebeSEric Cheng &state->vs_prevstats[vnic->va_vnic_id]); 4002da14cebeSEric Cheng } else { 4003da14cebeSEric Cheng /* get and print vnic statistics */ 4004da14cebeSEric Cheng get_link_stats(vnic_name, &vnic_stats); 4005da14cebeSEric Cheng dump_vnic_stat(vnic_name, linkid, state, &vnic_stats, 4006da14cebeSEric Cheng &state->vs_totalstats); 4007da14cebeSEric Cheng } 4008da14cebeSEric Cheng return (DLADM_STATUS_OK); 4009da14cebeSEric Cheng } else { 4010da14cebeSEric Cheng (void) snprintf(vbuf.vnic_link, sizeof (vbuf.vnic_link), 4011da14cebeSEric Cheng "%s", vnic_name); 4012da14cebeSEric Cheng 4013da14cebeSEric Cheng if (!is_etherstub) { 4014da14cebeSEric Cheng 4015da14cebeSEric Cheng (void) snprintf(vbuf.vnic_over, sizeof (vbuf.vnic_over), 4016da14cebeSEric Cheng "%s", devname); 4017da14cebeSEric Cheng (void) snprintf(vbuf.vnic_speed, 4018da14cebeSEric Cheng sizeof (vbuf.vnic_speed), "%u", 4019da14cebeSEric Cheng (uint_t)((get_ifspeed(vnic_name, B_TRUE)) 4020da14cebeSEric Cheng / 1000000ull)); 4021da14cebeSEric Cheng 4022da14cebeSEric Cheng switch (vnic->va_mac_addr_type) { 4023da14cebeSEric Cheng case VNIC_MAC_ADDR_TYPE_FIXED: 4024da14cebeSEric Cheng case VNIC_MAC_ADDR_TYPE_PRIMARY: 4025da14cebeSEric Cheng (void) snprintf(vbuf.vnic_macaddrtype, 4026da14cebeSEric Cheng sizeof (vbuf.vnic_macaddrtype), 4027da14cebeSEric Cheng gettext("fixed")); 4028da14cebeSEric Cheng break; 4029da14cebeSEric Cheng case VNIC_MAC_ADDR_TYPE_RANDOM: 4030da14cebeSEric Cheng (void) snprintf(vbuf.vnic_macaddrtype, 4031da14cebeSEric Cheng sizeof (vbuf.vnic_macaddrtype), 4032da14cebeSEric Cheng gettext("random")); 4033da14cebeSEric Cheng break; 4034da14cebeSEric Cheng case VNIC_MAC_ADDR_TYPE_FACTORY: 4035da14cebeSEric Cheng (void) snprintf(vbuf.vnic_macaddrtype, 4036da14cebeSEric Cheng sizeof (vbuf.vnic_macaddrtype), 4037da14cebeSEric Cheng gettext("factory, slot %d"), 4038da14cebeSEric Cheng vnic->va_mac_slot); 4039da14cebeSEric Cheng break; 4040da14cebeSEric Cheng } 4041da14cebeSEric Cheng 4042da14cebeSEric Cheng if (strlen(vbuf.vnic_macaddrtype) > 0) { 4043da14cebeSEric Cheng (void) snprintf(vbuf.vnic_macaddr, 4044da14cebeSEric Cheng sizeof (vbuf.vnic_macaddr), "%s", 4045da14cebeSEric Cheng dladm_aggr_macaddr2str(vnic->va_mac_addr, 4046da14cebeSEric Cheng mstr)); 4047da14cebeSEric Cheng } 4048da14cebeSEric Cheng 4049da14cebeSEric Cheng (void) snprintf(vbuf.vnic_vid, sizeof (vbuf.vnic_vid), 4050da14cebeSEric Cheng "%d", vnic->va_vid); 4051da14cebeSEric Cheng } 4052da14cebeSEric Cheng 4053*8002d411SSowmini Varadhan ofmt_print(state->vs_ofmt, &vbuf); 4054da14cebeSEric Cheng 4055da14cebeSEric Cheng return (DLADM_STATUS_OK); 4056da14cebeSEric Cheng } 4057da14cebeSEric Cheng } 4058da14cebeSEric Cheng 40594ac67f02SAnurag S. Maskey /* ARGSUSED */ 4060da14cebeSEric Cheng static int 40614ac67f02SAnurag S. Maskey show_vnic(dladm_handle_t dh, datalink_id_t linkid, void *arg) 4062da14cebeSEric Cheng { 4063da14cebeSEric Cheng show_vnic_state_t *state = arg; 4064da14cebeSEric Cheng 4065da14cebeSEric Cheng state->vs_status = print_vnic(state, linkid); 4066da14cebeSEric Cheng return (DLADM_WALK_CONTINUE); 4067da14cebeSEric Cheng } 4068da14cebeSEric Cheng 4069da14cebeSEric Cheng static void 4070da14cebeSEric Cheng do_show_vnic_common(int argc, char *argv[], const char *use, 4071da14cebeSEric Cheng boolean_t etherstub) 4072da14cebeSEric Cheng { 4073da14cebeSEric Cheng int option; 4074da14cebeSEric Cheng boolean_t s_arg = B_FALSE; 4075da14cebeSEric Cheng boolean_t i_arg = B_FALSE; 4076da14cebeSEric Cheng boolean_t l_arg = B_FALSE; 4077da14cebeSEric Cheng uint32_t interval = 0, flags = DLADM_OPT_ACTIVE; 4078da14cebeSEric Cheng datalink_id_t linkid = DATALINK_ALL_LINKID; 4079da14cebeSEric Cheng datalink_id_t dev_linkid = DATALINK_ALL_LINKID; 4080da14cebeSEric Cheng show_vnic_state_t state; 4081da14cebeSEric Cheng dladm_status_t status; 4082da14cebeSEric Cheng boolean_t o_arg = B_FALSE; 4083da14cebeSEric Cheng char *fields_str = NULL; 4084*8002d411SSowmini Varadhan ofmt_field_t *pf; 4085*8002d411SSowmini Varadhan char *all_e_fields = "link"; 4086*8002d411SSowmini Varadhan ofmt_handle_t ofmt; 4087*8002d411SSowmini Varadhan ofmt_status_t oferr; 4088*8002d411SSowmini Varadhan uint_t ofmtflags = 0; 4089da14cebeSEric Cheng 4090da14cebeSEric Cheng bzero(&state, sizeof (state)); 4091da14cebeSEric Cheng opterr = 0; 4092da14cebeSEric Cheng while ((option = getopt_long(argc, argv, ":pPl:si:o:", lopts, 4093da14cebeSEric Cheng NULL)) != -1) { 4094da14cebeSEric Cheng switch (option) { 4095da14cebeSEric Cheng case 'p': 4096*8002d411SSowmini Varadhan state.vs_parsable = B_TRUE; 4097da14cebeSEric Cheng break; 4098da14cebeSEric Cheng case 'P': 4099da14cebeSEric Cheng flags = DLADM_OPT_PERSIST; 4100da14cebeSEric Cheng break; 4101da14cebeSEric Cheng case 'l': 4102da14cebeSEric Cheng if (etherstub) 4103da14cebeSEric Cheng die("option not supported for this command"); 4104da14cebeSEric Cheng 4105da14cebeSEric Cheng if (strlcpy(state.vs_link, optarg, MAXLINKNAMELEN) >= 4106da14cebeSEric Cheng MAXLINKNAMELEN) 4107da14cebeSEric Cheng die("link name too long"); 4108da14cebeSEric Cheng 4109da14cebeSEric Cheng l_arg = B_TRUE; 4110da14cebeSEric Cheng break; 4111da14cebeSEric Cheng case 's': 4112da14cebeSEric Cheng if (s_arg) { 4113da14cebeSEric Cheng die("the option -s cannot be specified " 4114da14cebeSEric Cheng "more than once"); 4115da14cebeSEric Cheng } 4116da14cebeSEric Cheng s_arg = B_TRUE; 4117da14cebeSEric Cheng break; 4118da14cebeSEric Cheng case 'i': 4119da14cebeSEric Cheng if (i_arg) { 4120da14cebeSEric Cheng die("the option -i cannot be specified " 4121da14cebeSEric Cheng "more than once"); 4122da14cebeSEric Cheng } 4123da14cebeSEric Cheng i_arg = B_TRUE; 412463a6526dSMichael Lim if (!dladm_str2interval(optarg, &interval)) 4125da14cebeSEric Cheng die("invalid interval value '%s'", optarg); 4126da14cebeSEric Cheng break; 4127da14cebeSEric Cheng case 'o': 4128da14cebeSEric Cheng o_arg = B_TRUE; 4129da14cebeSEric Cheng fields_str = optarg; 4130da14cebeSEric Cheng break; 4131da14cebeSEric Cheng default: 4132da14cebeSEric Cheng die_opterr(optopt, option, use); 4133da14cebeSEric Cheng } 4134da14cebeSEric Cheng } 4135da14cebeSEric Cheng 4136da14cebeSEric Cheng if (i_arg && !s_arg) 4137da14cebeSEric Cheng die("the option -i can be used only with -s"); 4138da14cebeSEric Cheng 4139da14cebeSEric Cheng /* get vnic ID (optional last argument) */ 4140da14cebeSEric Cheng if (optind == (argc - 1)) { 41414ac67f02SAnurag S. Maskey status = dladm_name2info(handle, argv[optind], &linkid, NULL, 4142da14cebeSEric Cheng NULL, NULL); 4143da14cebeSEric Cheng if (status != DLADM_STATUS_OK) { 4144da14cebeSEric Cheng die_dlerr(status, "invalid vnic name '%s'", 4145da14cebeSEric Cheng argv[optind]); 4146da14cebeSEric Cheng } 4147da14cebeSEric Cheng (void) strlcpy(state.vs_vnic, argv[optind], MAXLINKNAMELEN); 4148da14cebeSEric Cheng } else if (optind != argc) { 4149da14cebeSEric Cheng usage(); 4150da14cebeSEric Cheng } 4151da14cebeSEric Cheng 4152da14cebeSEric Cheng if (l_arg) { 41534ac67f02SAnurag S. Maskey status = dladm_name2info(handle, state.vs_link, &dev_linkid, 41544ac67f02SAnurag S. Maskey NULL, NULL, NULL); 4155da14cebeSEric Cheng if (status != DLADM_STATUS_OK) { 4156da14cebeSEric Cheng die_dlerr(status, "invalid link name '%s'", 4157da14cebeSEric Cheng state.vs_link); 4158da14cebeSEric Cheng } 4159da14cebeSEric Cheng } 4160da14cebeSEric Cheng 4161da14cebeSEric Cheng state.vs_vnic_id = linkid; 4162da14cebeSEric Cheng state.vs_link_id = dev_linkid; 4163da14cebeSEric Cheng state.vs_etherstub = etherstub; 4164da14cebeSEric Cheng state.vs_found = B_FALSE; 4165da14cebeSEric Cheng state.vs_flags = flags; 4166da14cebeSEric Cheng 4167da14cebeSEric Cheng if (!o_arg || (o_arg && strcasecmp(fields_str, "all") == 0)) { 4168da14cebeSEric Cheng if (etherstub) 4169da14cebeSEric Cheng fields_str = all_e_fields; 4170da14cebeSEric Cheng } 4171da14cebeSEric Cheng pf = vnic_fields; 4172da14cebeSEric Cheng 4173*8002d411SSowmini Varadhan if (state.vs_parsable) 4174*8002d411SSowmini Varadhan ofmtflags |= OFMT_PARSABLE; 4175*8002d411SSowmini Varadhan oferr = ofmt_open(fields_str, pf, ofmtflags, 0, &ofmt); 4176*8002d411SSowmini Varadhan dladm_ofmt_check(oferr, state.vs_parsable, ofmt); 4177*8002d411SSowmini Varadhan state.vs_ofmt = ofmt; 4178da14cebeSEric Cheng 4179da14cebeSEric Cheng if (s_arg) { 4180da14cebeSEric Cheng /* Display vnic statistics */ 4181da14cebeSEric Cheng vnic_stats(&state, interval); 4182*8002d411SSowmini Varadhan ofmt_close(ofmt); 4183da14cebeSEric Cheng return; 4184da14cebeSEric Cheng } 4185da14cebeSEric Cheng 4186da14cebeSEric Cheng /* Display vnic information */ 4187da14cebeSEric Cheng state.vs_donefirst = B_FALSE; 4188da14cebeSEric Cheng 4189da14cebeSEric Cheng if (linkid == DATALINK_ALL_LINKID) { 41904ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(show_vnic, handle, &state, 4191da14cebeSEric Cheng DATALINK_CLASS_VNIC | DATALINK_CLASS_ETHERSTUB, 4192da14cebeSEric Cheng DATALINK_ANY_MEDIATYPE, DLADM_OPT_ACTIVE); 4193da14cebeSEric Cheng } else { 41944ac67f02SAnurag S. Maskey (void) show_vnic(handle, linkid, &state); 4195da14cebeSEric Cheng if (state.vs_status != DLADM_STATUS_OK) { 4196*8002d411SSowmini Varadhan ofmt_close(ofmt); 4197da14cebeSEric Cheng die_dlerr(state.vs_status, "failed to show vnic '%s'", 4198da14cebeSEric Cheng state.vs_vnic); 4199da14cebeSEric Cheng } 4200da14cebeSEric Cheng } 4201*8002d411SSowmini Varadhan ofmt_close(ofmt); 4202da14cebeSEric Cheng } 4203da14cebeSEric Cheng 4204da14cebeSEric Cheng static void 4205da14cebeSEric Cheng do_show_vnic(int argc, char *argv[], const char *use) 4206da14cebeSEric Cheng { 4207da14cebeSEric Cheng do_show_vnic_common(argc, argv, use, B_FALSE); 4208da14cebeSEric Cheng } 4209da14cebeSEric Cheng 4210da14cebeSEric Cheng static void 4211da14cebeSEric Cheng do_create_etherstub(int argc, char *argv[], const char *use) 4212da14cebeSEric Cheng { 4213da14cebeSEric Cheng uint32_t flags; 4214da14cebeSEric Cheng char *altroot = NULL; 4215da14cebeSEric Cheng char option; 4216da14cebeSEric Cheng dladm_status_t status; 4217da14cebeSEric Cheng char name[MAXLINKNAMELEN]; 4218da14cebeSEric Cheng uchar_t mac_addr[ETHERADDRL]; 4219da14cebeSEric Cheng 4220da14cebeSEric Cheng name[0] = '\0'; 4221da14cebeSEric Cheng bzero(mac_addr, sizeof (mac_addr)); 4222da14cebeSEric Cheng flags = DLADM_OPT_ANCHOR | DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST; 4223da14cebeSEric Cheng 4224da14cebeSEric Cheng opterr = 0; 4225da14cebeSEric Cheng while ((option = getopt_long(argc, argv, "tR:", 4226da14cebeSEric Cheng etherstub_lopts, NULL)) != -1) { 4227da14cebeSEric Cheng switch (option) { 4228da14cebeSEric Cheng case 't': 4229da14cebeSEric Cheng flags &= ~DLADM_OPT_PERSIST; 4230da14cebeSEric Cheng break; 4231da14cebeSEric Cheng case 'R': 4232da14cebeSEric Cheng altroot = optarg; 4233da14cebeSEric Cheng break; 4234da14cebeSEric Cheng default: 4235da14cebeSEric Cheng die_opterr(optopt, option, use); 4236da14cebeSEric Cheng } 4237da14cebeSEric Cheng } 4238da14cebeSEric Cheng 4239da14cebeSEric Cheng /* the etherstub id is the required operand */ 4240da14cebeSEric Cheng if (optind != (argc - 1)) 4241da14cebeSEric Cheng usage(); 4242da14cebeSEric Cheng 4243da14cebeSEric Cheng if (strlcpy(name, argv[optind], MAXLINKNAMELEN) >= MAXLINKNAMELEN) 4244da14cebeSEric Cheng die("link name too long '%s'", argv[optind]); 4245da14cebeSEric Cheng 4246da14cebeSEric Cheng if (!dladm_valid_linkname(name)) 4247da14cebeSEric Cheng die("invalid link name '%s'", argv[optind]); 4248da14cebeSEric Cheng 4249da14cebeSEric Cheng if (altroot != NULL) 4250da14cebeSEric Cheng altroot_cmd(altroot, argc, argv); 4251da14cebeSEric Cheng 42524ac67f02SAnurag S. Maskey status = dladm_vnic_create(handle, name, DATALINK_INVALID_LINKID, 4253da14cebeSEric Cheng VNIC_MAC_ADDR_TYPE_AUTO, mac_addr, ETHERADDRL, NULL, 0, 0, NULL, 4254da14cebeSEric Cheng NULL, flags); 4255da14cebeSEric Cheng if (status != DLADM_STATUS_OK) 4256da14cebeSEric Cheng die_dlerr(status, "etherstub creation failed"); 4257da14cebeSEric Cheng 4258da14cebeSEric Cheng 4259da14cebeSEric Cheng } 4260da14cebeSEric Cheng 4261da14cebeSEric Cheng static void 4262da14cebeSEric Cheng do_delete_etherstub(int argc, char *argv[], const char *use) 4263da14cebeSEric Cheng { 4264da14cebeSEric Cheng do_delete_vnic_common(argc, argv, use, B_TRUE); 4265da14cebeSEric Cheng } 4266da14cebeSEric Cheng 4267da14cebeSEric Cheng /* ARGSUSED */ 4268da14cebeSEric Cheng static void 4269da14cebeSEric Cheng do_show_etherstub(int argc, char *argv[], const char *use) 4270da14cebeSEric Cheng { 4271da14cebeSEric Cheng do_show_vnic_common(argc, argv, use, B_TRUE); 4272da14cebeSEric Cheng } 4273da14cebeSEric Cheng 4274da14cebeSEric Cheng static void 42756be03d0bSVasumathi Sundaram - Sun Microsystems link_stats(datalink_id_t linkid, uint_t interval, char *fields_str, 42766be03d0bSVasumathi Sundaram - Sun Microsystems show_state_t *state) 4277d62bc4baSyz147064 { 4278*8002d411SSowmini Varadhan ofmt_handle_t ofmt; 4279*8002d411SSowmini Varadhan ofmt_status_t oferr; 4280*8002d411SSowmini Varadhan uint_t ofmtflags = 0; 428133343a97Smeem 4282*8002d411SSowmini Varadhan if (state->ls_parsable) 4283*8002d411SSowmini Varadhan ofmtflags |= OFMT_PARSABLE; 4284*8002d411SSowmini Varadhan oferr = ofmt_open(fields_str, link_s_fields, ofmtflags, 0, &ofmt); 4285*8002d411SSowmini Varadhan dladm_ofmt_check(oferr, state->ls_parsable, ofmt); 4286*8002d411SSowmini Varadhan state->ls_ofmt = ofmt; 42877c478bd9Sstevel@tonic-gate 42887c478bd9Sstevel@tonic-gate /* 42897c478bd9Sstevel@tonic-gate * If an interval is specified, continuously show the stats 42907c478bd9Sstevel@tonic-gate * only for the first MAC port. 42917c478bd9Sstevel@tonic-gate */ 42926be03d0bSVasumathi Sundaram - Sun Microsystems state->ls_firstonly = (interval != 0); 42937c478bd9Sstevel@tonic-gate 42947c478bd9Sstevel@tonic-gate for (;;) { 42956be03d0bSVasumathi Sundaram - Sun Microsystems state->ls_donefirst = B_FALSE; 4296d62bc4baSyz147064 if (linkid == DATALINK_ALL_LINKID) { 42974ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(show_link_stats, handle, 42984ac67f02SAnurag S. Maskey state, DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE, 4299d62bc4baSyz147064 DLADM_OPT_ACTIVE); 4300d62bc4baSyz147064 } else { 43014ac67f02SAnurag S. Maskey (void) show_link_stats(handle, linkid, state); 4302d62bc4baSyz147064 } 43037c478bd9Sstevel@tonic-gate 43047c478bd9Sstevel@tonic-gate if (interval == 0) 43057c478bd9Sstevel@tonic-gate break; 43067c478bd9Sstevel@tonic-gate 43077c478bd9Sstevel@tonic-gate (void) sleep(interval); 43087c478bd9Sstevel@tonic-gate } 4309*8002d411SSowmini Varadhan ofmt_close(ofmt); 43107c478bd9Sstevel@tonic-gate } 43117c478bd9Sstevel@tonic-gate 43127c478bd9Sstevel@tonic-gate static void 4313d62bc4baSyz147064 aggr_stats(datalink_id_t linkid, show_grp_state_t *state, uint_t interval) 43147c478bd9Sstevel@tonic-gate { 43157c478bd9Sstevel@tonic-gate /* 43167c478bd9Sstevel@tonic-gate * If an interval is specified, continuously show the stats 43177c478bd9Sstevel@tonic-gate * only for the first group. 43187c478bd9Sstevel@tonic-gate */ 4319d62bc4baSyz147064 state->gs_firstonly = (interval != 0); 43207c478bd9Sstevel@tonic-gate 43217c478bd9Sstevel@tonic-gate for (;;) { 4322d62bc4baSyz147064 state->gs_donefirst = B_FALSE; 4323d62bc4baSyz147064 if (linkid == DATALINK_ALL_LINKID) 43244ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(show_aggr, handle, state, 4325d62bc4baSyz147064 DATALINK_CLASS_AGGR, DATALINK_ANY_MEDIATYPE, 4326d62bc4baSyz147064 DLADM_OPT_ACTIVE); 4327d62bc4baSyz147064 else 43284ac67f02SAnurag S. Maskey (void) show_aggr(handle, linkid, state); 43297c478bd9Sstevel@tonic-gate 43307c478bd9Sstevel@tonic-gate if (interval == 0) 43317c478bd9Sstevel@tonic-gate break; 43327c478bd9Sstevel@tonic-gate 43337c478bd9Sstevel@tonic-gate (void) sleep(interval); 43347c478bd9Sstevel@tonic-gate } 43357c478bd9Sstevel@tonic-gate } 43367c478bd9Sstevel@tonic-gate 4337da14cebeSEric Cheng /* ARGSUSED */ 43387c478bd9Sstevel@tonic-gate static void 4339da14cebeSEric Cheng vnic_stats(show_vnic_state_t *sp, uint32_t interval) 43407c478bd9Sstevel@tonic-gate { 4341da14cebeSEric Cheng show_vnic_state_t state; 4342da14cebeSEric Cheng boolean_t specific_link, specific_dev; 43437c478bd9Sstevel@tonic-gate 4344da14cebeSEric Cheng /* Display vnic statistics */ 4345da14cebeSEric Cheng dump_vnics_head(sp->vs_link); 4346e7801d59Ssowmini 4347da14cebeSEric Cheng bzero(&state, sizeof (state)); 4348da14cebeSEric Cheng state.vs_stats = B_TRUE; 4349da14cebeSEric Cheng state.vs_vnic_id = sp->vs_vnic_id; 4350da14cebeSEric Cheng state.vs_link_id = sp->vs_link_id; 43517c478bd9Sstevel@tonic-gate 43527c478bd9Sstevel@tonic-gate /* 4353da14cebeSEric Cheng * If an interval is specified, and a vnic ID is not specified, 4354da14cebeSEric Cheng * continuously show the stats only for the first vnic. 43557c478bd9Sstevel@tonic-gate */ 4356da14cebeSEric Cheng specific_link = (sp->vs_vnic_id != DATALINK_ALL_LINKID); 4357da14cebeSEric Cheng specific_dev = (sp->vs_link_id != DATALINK_ALL_LINKID); 43587c478bd9Sstevel@tonic-gate 43597c478bd9Sstevel@tonic-gate for (;;) { 4360da14cebeSEric Cheng /* Get stats for each vnic */ 4361da14cebeSEric Cheng state.vs_found = B_FALSE; 4362da14cebeSEric Cheng state.vs_donefirst = B_FALSE; 4363da14cebeSEric Cheng state.vs_printstats = B_FALSE; 4364da14cebeSEric Cheng state.vs_flags = DLADM_OPT_ACTIVE; 43657c478bd9Sstevel@tonic-gate 4366da14cebeSEric Cheng if (!specific_link) { 43674ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(show_vnic, handle, &state, 4368da14cebeSEric Cheng DATALINK_CLASS_VNIC, DATALINK_ANY_MEDIATYPE, 4369da14cebeSEric Cheng DLADM_OPT_ACTIVE); 4370da14cebeSEric Cheng } else { 43714ac67f02SAnurag S. Maskey (void) show_vnic(handle, sp->vs_vnic_id, &state); 4372da14cebeSEric Cheng if (state.vs_status != DLADM_STATUS_OK) { 4373da14cebeSEric Cheng die_dlerr(state.vs_status, 4374da14cebeSEric Cheng "failed to show vnic '%s'", sp->vs_vnic); 4375da14cebeSEric Cheng } 4376da14cebeSEric Cheng } 43777c478bd9Sstevel@tonic-gate 4378da14cebeSEric Cheng if (specific_link && !state.vs_found) 4379da14cebeSEric Cheng die("non-existent vnic '%s'", sp->vs_vnic); 4380da14cebeSEric Cheng if (specific_dev && !state.vs_found) 4381da14cebeSEric Cheng die("device %s has no vnics", sp->vs_link); 4382da14cebeSEric Cheng 4383da14cebeSEric Cheng /* Show totals */ 4384da14cebeSEric Cheng if ((specific_link | specific_dev) && !interval) { 4385da14cebeSEric Cheng (void) printf("Total"); 4386da14cebeSEric Cheng (void) printf("\t%-10llu", 4387da14cebeSEric Cheng state.vs_totalstats.ipackets); 4388da14cebeSEric Cheng (void) printf("%-12llu", 4389da14cebeSEric Cheng state.vs_totalstats.rbytes); 4390da14cebeSEric Cheng (void) printf("%-10llu", 4391da14cebeSEric Cheng state.vs_totalstats.opackets); 4392da14cebeSEric Cheng (void) printf("%-12llu\n", 4393da14cebeSEric Cheng state.vs_totalstats.obytes); 4394da14cebeSEric Cheng } 4395da14cebeSEric Cheng 4396da14cebeSEric Cheng /* Show stats for each vnic */ 4397da14cebeSEric Cheng state.vs_donefirst = B_FALSE; 4398da14cebeSEric Cheng state.vs_printstats = B_TRUE; 4399da14cebeSEric Cheng 4400da14cebeSEric Cheng if (!specific_link) { 44014ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(show_vnic, handle, &state, 4402da14cebeSEric Cheng DATALINK_CLASS_VNIC, DATALINK_ANY_MEDIATYPE, 4403da14cebeSEric Cheng DLADM_OPT_ACTIVE); 4404da14cebeSEric Cheng } else { 44054ac67f02SAnurag S. Maskey (void) show_vnic(handle, sp->vs_vnic_id, &state); 4406da14cebeSEric Cheng if (state.vs_status != DLADM_STATUS_OK) { 4407da14cebeSEric Cheng die_dlerr(state.vs_status, 4408da14cebeSEric Cheng "failed to show vnic '%s'", sp->vs_vnic); 4409da14cebeSEric Cheng } 4410da14cebeSEric Cheng } 44117c478bd9Sstevel@tonic-gate 44127c478bd9Sstevel@tonic-gate if (interval == 0) 44137c478bd9Sstevel@tonic-gate break; 44147c478bd9Sstevel@tonic-gate 44157c478bd9Sstevel@tonic-gate (void) sleep(interval); 44167c478bd9Sstevel@tonic-gate } 44177c478bd9Sstevel@tonic-gate } 44187c478bd9Sstevel@tonic-gate 44197c478bd9Sstevel@tonic-gate static void 4420da14cebeSEric Cheng get_mac_stats(const char *dev, pktsum_t *stats) 44217c478bd9Sstevel@tonic-gate { 44227c478bd9Sstevel@tonic-gate kstat_ctl_t *kcp; 44237c478bd9Sstevel@tonic-gate kstat_t *ksp; 4424da14cebeSEric Cheng char module[DLPI_LINKNAME_MAX]; 4425da14cebeSEric Cheng uint_t instance; 4426da14cebeSEric Cheng 4427da14cebeSEric Cheng 4428da14cebeSEric Cheng bzero(stats, sizeof (*stats)); 4429da14cebeSEric Cheng 4430da14cebeSEric Cheng if (dlpi_parselink(dev, module, &instance) != DLPI_SUCCESS) 4431da14cebeSEric Cheng return; 44327c478bd9Sstevel@tonic-gate 44337c478bd9Sstevel@tonic-gate if ((kcp = kstat_open()) == NULL) { 443433343a97Smeem warn("kstat open operation failed"); 44357c478bd9Sstevel@tonic-gate return; 44367c478bd9Sstevel@tonic-gate } 44377c478bd9Sstevel@tonic-gate 4438da14cebeSEric Cheng ksp = dladm_kstat_lookup(kcp, module, instance, "mac", NULL); 4439da14cebeSEric Cheng if (ksp != NULL) 4440da14cebeSEric Cheng dladm_get_stats(kcp, ksp, stats); 4441da14cebeSEric Cheng 44427c478bd9Sstevel@tonic-gate (void) kstat_close(kcp); 44437c478bd9Sstevel@tonic-gate 44447c478bd9Sstevel@tonic-gate } 44457c478bd9Sstevel@tonic-gate 44467c478bd9Sstevel@tonic-gate static void 44477c478bd9Sstevel@tonic-gate get_link_stats(const char *link, pktsum_t *stats) 44487c478bd9Sstevel@tonic-gate { 4449da14cebeSEric Cheng kstat_ctl_t *kcp; 4450da14cebeSEric Cheng kstat_t *ksp; 4451da14cebeSEric Cheng 44527c478bd9Sstevel@tonic-gate bzero(stats, sizeof (*stats)); 4453da14cebeSEric Cheng 4454da14cebeSEric Cheng if ((kcp = kstat_open()) == NULL) { 4455da14cebeSEric Cheng warn("kstat_open operation failed"); 4456da14cebeSEric Cheng return; 4457da14cebeSEric Cheng } 4458da14cebeSEric Cheng 4459da14cebeSEric Cheng ksp = dladm_kstat_lookup(kcp, "link", 0, link, NULL); 4460da14cebeSEric Cheng 4461da14cebeSEric Cheng if (ksp != NULL) 4462da14cebeSEric Cheng dladm_get_stats(kcp, ksp, stats); 4463da14cebeSEric Cheng 4464da14cebeSEric Cheng (void) kstat_close(kcp); 44657c478bd9Sstevel@tonic-gate } 44667c478bd9Sstevel@tonic-gate 4467ba2e4443Sseb static int 4468d62bc4baSyz147064 query_kstat(char *module, int instance, const char *name, const char *stat, 4469d62bc4baSyz147064 uint8_t type, void *val) 44707c478bd9Sstevel@tonic-gate { 44717c478bd9Sstevel@tonic-gate kstat_ctl_t *kcp; 44727c478bd9Sstevel@tonic-gate kstat_t *ksp; 44737c478bd9Sstevel@tonic-gate 44747c478bd9Sstevel@tonic-gate if ((kcp = kstat_open()) == NULL) { 447533343a97Smeem warn("kstat open operation failed"); 4476ba2e4443Sseb return (-1); 44777c478bd9Sstevel@tonic-gate } 44787c478bd9Sstevel@tonic-gate 4479d62bc4baSyz147064 if ((ksp = kstat_lookup(kcp, module, instance, (char *)name)) == NULL) { 44807c478bd9Sstevel@tonic-gate /* 44817c478bd9Sstevel@tonic-gate * The kstat query could fail if the underlying MAC 44827c478bd9Sstevel@tonic-gate * driver was already detached. 44837c478bd9Sstevel@tonic-gate */ 44847c478bd9Sstevel@tonic-gate goto bail; 44857c478bd9Sstevel@tonic-gate } 44867c478bd9Sstevel@tonic-gate 44877c478bd9Sstevel@tonic-gate if (kstat_read(kcp, ksp, NULL) == -1) { 448833343a97Smeem warn("kstat read failed"); 44897c478bd9Sstevel@tonic-gate goto bail; 44907c478bd9Sstevel@tonic-gate } 44917c478bd9Sstevel@tonic-gate 4492e7801d59Ssowmini if (dladm_kstat_value(ksp, stat, type, val) < 0) 44937c478bd9Sstevel@tonic-gate goto bail; 4494ba2e4443Sseb 4495ba2e4443Sseb (void) kstat_close(kcp); 4496ba2e4443Sseb return (0); 44977c478bd9Sstevel@tonic-gate 44987c478bd9Sstevel@tonic-gate bail: 44997c478bd9Sstevel@tonic-gate (void) kstat_close(kcp); 4500ba2e4443Sseb return (-1); 4501ba2e4443Sseb } 4502ba2e4443Sseb 4503d62bc4baSyz147064 static int 4504d62bc4baSyz147064 get_one_kstat(const char *name, const char *stat, uint8_t type, 4505d62bc4baSyz147064 void *val, boolean_t islink) 4506d62bc4baSyz147064 { 4507d62bc4baSyz147064 char module[DLPI_LINKNAME_MAX]; 4508d62bc4baSyz147064 uint_t instance; 4509d62bc4baSyz147064 4510d62bc4baSyz147064 if (islink) { 4511d62bc4baSyz147064 return (query_kstat("link", 0, name, stat, type, val)); 4512d62bc4baSyz147064 } else { 4513d62bc4baSyz147064 if (dlpi_parselink(name, module, &instance) != DLPI_SUCCESS) 4514d62bc4baSyz147064 return (-1); 4515d62bc4baSyz147064 4516d62bc4baSyz147064 return (query_kstat(module, instance, "mac", stat, type, val)); 4517d62bc4baSyz147064 } 4518d62bc4baSyz147064 } 4519d62bc4baSyz147064 4520ba2e4443Sseb static uint64_t 4521d62bc4baSyz147064 get_ifspeed(const char *name, boolean_t islink) 4522ba2e4443Sseb { 4523ba2e4443Sseb uint64_t ifspeed = 0; 4524ba2e4443Sseb 4525d62bc4baSyz147064 (void) get_one_kstat(name, "ifspeed", KSTAT_DATA_UINT64, 4526d62bc4baSyz147064 &ifspeed, islink); 4527d62bc4baSyz147064 45287c478bd9Sstevel@tonic-gate return (ifspeed); 45297c478bd9Sstevel@tonic-gate } 45307c478bd9Sstevel@tonic-gate 4531f595a68aSyz147064 static const char * 4532d62bc4baSyz147064 get_linkstate(const char *name, boolean_t islink, char *buf) 45337c478bd9Sstevel@tonic-gate { 4534d62bc4baSyz147064 link_state_t linkstate; 45357c478bd9Sstevel@tonic-gate 4536d62bc4baSyz147064 if (get_one_kstat(name, "link_state", KSTAT_DATA_UINT32, 4537d62bc4baSyz147064 &linkstate, islink) != 0) { 4538da14cebeSEric Cheng (void) strlcpy(buf, "?", DLADM_STRSIZE); 45393a62633bSyz147064 return (buf); 45407c478bd9Sstevel@tonic-gate } 4541d62bc4baSyz147064 return (dladm_linkstate2str(linkstate, buf)); 45427c478bd9Sstevel@tonic-gate } 45437c478bd9Sstevel@tonic-gate 4544f595a68aSyz147064 static const char * 4545d62bc4baSyz147064 get_linkduplex(const char *name, boolean_t islink, char *buf) 45467c478bd9Sstevel@tonic-gate { 4547d62bc4baSyz147064 link_duplex_t linkduplex; 45487c478bd9Sstevel@tonic-gate 4549d62bc4baSyz147064 if (get_one_kstat(name, "link_duplex", KSTAT_DATA_UINT32, 4550d62bc4baSyz147064 &linkduplex, islink) != 0) { 45513a62633bSyz147064 (void) strlcpy(buf, "unknown", DLADM_STRSIZE); 45523a62633bSyz147064 return (buf); 45537c478bd9Sstevel@tonic-gate } 45547c478bd9Sstevel@tonic-gate 4555d62bc4baSyz147064 return (dladm_linkduplex2str(linkduplex, buf)); 45567c478bd9Sstevel@tonic-gate } 45570ba2cbe9Sxc151355 45580ba2cbe9Sxc151355 static int 4559*8002d411SSowmini Varadhan parse_wifi_fields(char *str, ofmt_handle_t *ofmt, uint_t cmdtype, 4560*8002d411SSowmini Varadhan boolean_t parsable) 45610ba2cbe9Sxc151355 { 4562*8002d411SSowmini Varadhan ofmt_field_t *template, *of; 4563*8002d411SSowmini Varadhan ofmt_cb_t *fn; 4564*8002d411SSowmini Varadhan ofmt_status_t oferr; 45650ba2cbe9Sxc151355 45660ba2cbe9Sxc151355 if (cmdtype == WIFI_CMD_SCAN) { 4567*8002d411SSowmini Varadhan template = wifi_common_fields; 45680ba2cbe9Sxc151355 if (str == NULL) 45690ba2cbe9Sxc151355 str = def_scan_wifi_fields; 45700ba2cbe9Sxc151355 if (strcasecmp(str, "all") == 0) 45710ba2cbe9Sxc151355 str = all_scan_wifi_fields; 4572*8002d411SSowmini Varadhan fn = print_wlan_attr_cb; 45730ba2cbe9Sxc151355 } else if (cmdtype == WIFI_CMD_SHOW) { 4574*8002d411SSowmini Varadhan bcopy(wifi_common_fields, &wifi_show_fields[2], 4575*8002d411SSowmini Varadhan sizeof (wifi_common_fields)); 4576*8002d411SSowmini Varadhan template = wifi_show_fields; 45770ba2cbe9Sxc151355 if (str == NULL) 45780ba2cbe9Sxc151355 str = def_show_wifi_fields; 45790ba2cbe9Sxc151355 if (strcasecmp(str, "all") == 0) 45800ba2cbe9Sxc151355 str = all_show_wifi_fields; 4581*8002d411SSowmini Varadhan fn = print_link_attr_cb; 45820ba2cbe9Sxc151355 } else { 45830ba2cbe9Sxc151355 return (-1); 45840ba2cbe9Sxc151355 } 4585*8002d411SSowmini Varadhan 4586*8002d411SSowmini Varadhan for (of = template; of->of_name != NULL; of++) { 4587*8002d411SSowmini Varadhan if (of->of_cb == NULL) 4588*8002d411SSowmini Varadhan of->of_cb = fn; 4589*8002d411SSowmini Varadhan } 4590*8002d411SSowmini Varadhan 4591*8002d411SSowmini Varadhan oferr = ofmt_open(str, template, (parsable ? OFMT_PARSABLE : 0), 4592*8002d411SSowmini Varadhan 0, ofmt); 4593*8002d411SSowmini Varadhan dladm_ofmt_check(oferr, parsable, *ofmt); 4594e7801d59Ssowmini return (0); 45950ba2cbe9Sxc151355 } 45960ba2cbe9Sxc151355 45970ba2cbe9Sxc151355 typedef struct print_wifi_state { 4598d62bc4baSyz147064 char *ws_link; 4599*8002d411SSowmini Varadhan boolean_t ws_parsable; 46000ba2cbe9Sxc151355 boolean_t ws_header; 4601*8002d411SSowmini Varadhan ofmt_handle_t ws_ofmt; 46020ba2cbe9Sxc151355 } print_wifi_state_t; 46030ba2cbe9Sxc151355 4604e7801d59Ssowmini typedef struct wlan_scan_args_s { 4605e7801d59Ssowmini print_wifi_state_t *ws_state; 4606e7801d59Ssowmini void *ws_attr; 4607e7801d59Ssowmini } wlan_scan_args_t; 46080ba2cbe9Sxc151355 4609*8002d411SSowmini Varadhan static boolean_t 4610*8002d411SSowmini Varadhan print_wlan_attr_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize) 46110ba2cbe9Sxc151355 { 4612*8002d411SSowmini Varadhan wlan_scan_args_t *w = ofarg->ofmt_cbarg; 4613e7801d59Ssowmini print_wifi_state_t *statep = w->ws_state; 4614e7801d59Ssowmini dladm_wlan_attr_t *attrp = w->ws_attr; 4615*8002d411SSowmini Varadhan char tmpbuf[DLADM_STRSIZE]; 46160ba2cbe9Sxc151355 4617*8002d411SSowmini Varadhan if (ofarg->ofmt_id == 0) { 4618*8002d411SSowmini Varadhan (void) strlcpy(buf, (char *)statep->ws_link, bufsize); 4619*8002d411SSowmini Varadhan return (B_TRUE); 46200ba2cbe9Sxc151355 } 46210ba2cbe9Sxc151355 4622*8002d411SSowmini Varadhan if ((ofarg->ofmt_id & attrp->wa_valid) == 0) 4623*8002d411SSowmini Varadhan return (B_TRUE); 46240ba2cbe9Sxc151355 4625*8002d411SSowmini Varadhan switch (ofarg->ofmt_id) { 4626f595a68aSyz147064 case DLADM_WLAN_ATTR_ESSID: 4627*8002d411SSowmini Varadhan (void) dladm_wlan_essid2str(&attrp->wa_essid, tmpbuf); 46280ba2cbe9Sxc151355 break; 4629f595a68aSyz147064 case DLADM_WLAN_ATTR_BSSID: 4630*8002d411SSowmini Varadhan (void) dladm_wlan_bssid2str(&attrp->wa_bssid, tmpbuf); 46310ba2cbe9Sxc151355 break; 4632f595a68aSyz147064 case DLADM_WLAN_ATTR_SECMODE: 4633*8002d411SSowmini Varadhan (void) dladm_wlan_secmode2str(&attrp->wa_secmode, tmpbuf); 46340ba2cbe9Sxc151355 break; 4635f595a68aSyz147064 case DLADM_WLAN_ATTR_STRENGTH: 4636*8002d411SSowmini Varadhan (void) dladm_wlan_strength2str(&attrp->wa_strength, tmpbuf); 46370ba2cbe9Sxc151355 break; 4638f595a68aSyz147064 case DLADM_WLAN_ATTR_MODE: 4639*8002d411SSowmini Varadhan (void) dladm_wlan_mode2str(&attrp->wa_mode, tmpbuf); 46400ba2cbe9Sxc151355 break; 4641f595a68aSyz147064 case DLADM_WLAN_ATTR_SPEED: 4642*8002d411SSowmini Varadhan (void) dladm_wlan_speed2str(&attrp->wa_speed, tmpbuf); 4643*8002d411SSowmini Varadhan (void) strlcat(tmpbuf, "Mb", sizeof (tmpbuf)); 46440ba2cbe9Sxc151355 break; 4645f595a68aSyz147064 case DLADM_WLAN_ATTR_AUTH: 4646*8002d411SSowmini Varadhan (void) dladm_wlan_auth2str(&attrp->wa_auth, tmpbuf); 46470ba2cbe9Sxc151355 break; 4648f595a68aSyz147064 case DLADM_WLAN_ATTR_BSSTYPE: 4649*8002d411SSowmini Varadhan (void) dladm_wlan_bsstype2str(&attrp->wa_bsstype, tmpbuf); 46500ba2cbe9Sxc151355 break; 46510ba2cbe9Sxc151355 } 4652*8002d411SSowmini Varadhan (void) strlcpy(buf, tmpbuf, bufsize); 46530ba2cbe9Sxc151355 4654*8002d411SSowmini Varadhan return (B_TRUE); 46550ba2cbe9Sxc151355 } 46560ba2cbe9Sxc151355 46570ba2cbe9Sxc151355 static boolean_t 4658f595a68aSyz147064 print_scan_results(void *arg, dladm_wlan_attr_t *attrp) 46590ba2cbe9Sxc151355 { 46600ba2cbe9Sxc151355 print_wifi_state_t *statep = arg; 4661e7801d59Ssowmini wlan_scan_args_t warg; 46620ba2cbe9Sxc151355 4663e7801d59Ssowmini bzero(&warg, sizeof (warg)); 4664e7801d59Ssowmini warg.ws_state = statep; 4665e7801d59Ssowmini warg.ws_attr = attrp; 4666*8002d411SSowmini Varadhan ofmt_print(statep->ws_ofmt, &warg); 46670ba2cbe9Sxc151355 return (B_TRUE); 46680ba2cbe9Sxc151355 } 46690ba2cbe9Sxc151355 4670d62bc4baSyz147064 static int 46714ac67f02SAnurag S. Maskey scan_wifi(dladm_handle_t dh, datalink_id_t linkid, void *arg) 46720ba2cbe9Sxc151355 { 46730ba2cbe9Sxc151355 print_wifi_state_t *statep = arg; 4674f595a68aSyz147064 dladm_status_t status; 4675d62bc4baSyz147064 char link[MAXLINKNAMELEN]; 4676d62bc4baSyz147064 46774ac67f02SAnurag S. Maskey if ((status = dladm_datalink_id2info(dh, linkid, NULL, NULL, NULL, link, 4678e7801d59Ssowmini sizeof (link))) != DLADM_STATUS_OK) { 4679d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 4680d62bc4baSyz147064 } 46810ba2cbe9Sxc151355 46820ba2cbe9Sxc151355 statep->ws_link = link; 46834ac67f02SAnurag S. Maskey status = dladm_wlan_scan(dh, linkid, statep, print_scan_results); 4684f595a68aSyz147064 if (status != DLADM_STATUS_OK) 4685d62bc4baSyz147064 die_dlerr(status, "cannot scan link '%s'", statep->ws_link); 468633343a97Smeem 4687d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 46880ba2cbe9Sxc151355 } 46890ba2cbe9Sxc151355 4690*8002d411SSowmini Varadhan static boolean_t 4691*8002d411SSowmini Varadhan print_wifi_status_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize) 46920ba2cbe9Sxc151355 { 4693*8002d411SSowmini Varadhan static char tmpbuf[DLADM_STRSIZE]; 4694*8002d411SSowmini Varadhan wlan_scan_args_t *w = ofarg->ofmt_cbarg; 4695*8002d411SSowmini Varadhan dladm_wlan_linkattr_t *attrp = w->ws_attr; 4696*8002d411SSowmini Varadhan 4697*8002d411SSowmini Varadhan if ((ofarg->ofmt_id & attrp->la_valid) != 0) { 4698*8002d411SSowmini Varadhan (void) dladm_wlan_linkstatus2str(&attrp->la_status, tmpbuf); 4699*8002d411SSowmini Varadhan (void) strlcpy(buf, tmpbuf, bufsize); 4700*8002d411SSowmini Varadhan } 4701*8002d411SSowmini Varadhan return (B_TRUE); 4702*8002d411SSowmini Varadhan } 4703*8002d411SSowmini Varadhan 4704*8002d411SSowmini Varadhan static boolean_t 4705*8002d411SSowmini Varadhan print_link_attr_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize) 4706*8002d411SSowmini Varadhan { 4707*8002d411SSowmini Varadhan wlan_scan_args_t *w = ofarg->ofmt_cbarg, w1; 4708e7801d59Ssowmini print_wifi_state_t *statep = w->ws_state; 4709e7801d59Ssowmini dladm_wlan_linkattr_t *attrp = w->ws_attr; 47100ba2cbe9Sxc151355 4711e7801d59Ssowmini bzero(&w1, sizeof (w1)); 4712e7801d59Ssowmini w1.ws_state = statep; 4713e7801d59Ssowmini w1.ws_attr = &attrp->la_wlan_attr; 4714*8002d411SSowmini Varadhan ofarg->ofmt_cbarg = &w1; 4715*8002d411SSowmini Varadhan return (print_wlan_attr_cb(ofarg, buf, bufsize)); 47160ba2cbe9Sxc151355 } 47170ba2cbe9Sxc151355 4718d62bc4baSyz147064 static int 47194ac67f02SAnurag S. Maskey show_wifi(dladm_handle_t dh, datalink_id_t linkid, void *arg) 47200ba2cbe9Sxc151355 { 47210ba2cbe9Sxc151355 print_wifi_state_t *statep = arg; 4722f595a68aSyz147064 dladm_wlan_linkattr_t attr; 4723f595a68aSyz147064 dladm_status_t status; 4724d62bc4baSyz147064 char link[MAXLINKNAMELEN]; 4725e7801d59Ssowmini wlan_scan_args_t warg; 47260ba2cbe9Sxc151355 47274ac67f02SAnurag S. Maskey if ((status = dladm_datalink_id2info(dh, linkid, NULL, NULL, NULL, link, 4728e7801d59Ssowmini sizeof (link))) != DLADM_STATUS_OK) { 4729d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 4730d62bc4baSyz147064 } 4731d62bc4baSyz147064 47325f5c9f54SAnurag S. Maskey /* dladm_wlan_get_linkattr() memsets attr with 0 */ 47334ac67f02SAnurag S. Maskey status = dladm_wlan_get_linkattr(dh, linkid, &attr); 4734f595a68aSyz147064 if (status != DLADM_STATUS_OK) 4735d62bc4baSyz147064 die_dlerr(status, "cannot get link attributes for %s", link); 4736d62bc4baSyz147064 4737d62bc4baSyz147064 statep->ws_link = link; 47380ba2cbe9Sxc151355 4739e7801d59Ssowmini bzero(&warg, sizeof (warg)); 4740e7801d59Ssowmini warg.ws_state = statep; 4741e7801d59Ssowmini warg.ws_attr = &attr; 4742*8002d411SSowmini Varadhan ofmt_print(statep->ws_ofmt, &warg); 4743d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 47440ba2cbe9Sxc151355 } 47450ba2cbe9Sxc151355 47460ba2cbe9Sxc151355 static void 47478d5c46e6Sam223141 do_display_wifi(int argc, char **argv, int cmd, const char *use) 47480ba2cbe9Sxc151355 { 47490ba2cbe9Sxc151355 int option; 47500ba2cbe9Sxc151355 char *fields_str = NULL; 47514ac67f02SAnurag S. Maskey int (*callback)(dladm_handle_t, datalink_id_t, void *); 47520ba2cbe9Sxc151355 print_wifi_state_t state; 4753d62bc4baSyz147064 datalink_id_t linkid = DATALINK_ALL_LINKID; 4754f595a68aSyz147064 dladm_status_t status; 47550ba2cbe9Sxc151355 47560ba2cbe9Sxc151355 if (cmd == WIFI_CMD_SCAN) 47570ba2cbe9Sxc151355 callback = scan_wifi; 47580ba2cbe9Sxc151355 else if (cmd == WIFI_CMD_SHOW) 47590ba2cbe9Sxc151355 callback = show_wifi; 47600ba2cbe9Sxc151355 else 47610ba2cbe9Sxc151355 return; 47620ba2cbe9Sxc151355 4763*8002d411SSowmini Varadhan state.ws_parsable = B_FALSE; 47640ba2cbe9Sxc151355 state.ws_header = B_TRUE; 47650ba2cbe9Sxc151355 opterr = 0; 47660ba2cbe9Sxc151355 while ((option = getopt_long(argc, argv, ":o:p", 47670ba2cbe9Sxc151355 wifi_longopts, NULL)) != -1) { 47680ba2cbe9Sxc151355 switch (option) { 47690ba2cbe9Sxc151355 case 'o': 47700ba2cbe9Sxc151355 fields_str = optarg; 47710ba2cbe9Sxc151355 break; 47720ba2cbe9Sxc151355 case 'p': 4773*8002d411SSowmini Varadhan state.ws_parsable = B_TRUE; 47740ba2cbe9Sxc151355 break; 47750ba2cbe9Sxc151355 default: 47768d5c46e6Sam223141 die_opterr(optopt, option, use); 47770ba2cbe9Sxc151355 } 47780ba2cbe9Sxc151355 } 47790ba2cbe9Sxc151355 4780*8002d411SSowmini Varadhan if (state.ws_parsable && fields_str == NULL) 47810d365605Sschuster die("-p requires -o"); 47820d365605Sschuster 4783*8002d411SSowmini Varadhan if (state.ws_parsable && strcasecmp(fields_str, "all") == 0) 47840d365605Sschuster die("\"-o all\" is invalid with -p"); 47850d365605Sschuster 4786d62bc4baSyz147064 if (optind == (argc - 1)) { 47874ac67f02SAnurag S. Maskey if ((status = dladm_name2info(handle, argv[optind], &linkid, 47884ac67f02SAnurag S. Maskey NULL, NULL, NULL)) != DLADM_STATUS_OK) { 4789d62bc4baSyz147064 die_dlerr(status, "link %s is not valid", argv[optind]); 4790d62bc4baSyz147064 } 4791d62bc4baSyz147064 } else if (optind != argc) { 47920ba2cbe9Sxc151355 usage(); 4793d62bc4baSyz147064 } 47940ba2cbe9Sxc151355 4795*8002d411SSowmini Varadhan if (parse_wifi_fields(fields_str, &state.ws_ofmt, cmd, 4796*8002d411SSowmini Varadhan state.ws_parsable) < 0) 479733343a97Smeem die("invalid field(s) specified"); 479833343a97Smeem 4799d62bc4baSyz147064 if (linkid == DATALINK_ALL_LINKID) { 48004ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(callback, handle, &state, 4801d62bc4baSyz147064 DATALINK_CLASS_PHYS, DL_WIFI, DLADM_OPT_ACTIVE); 48020ba2cbe9Sxc151355 } else { 48034ac67f02SAnurag S. Maskey (void) (*callback)(handle, linkid, &state); 48040ba2cbe9Sxc151355 } 4805*8002d411SSowmini Varadhan ofmt_close(state.ws_ofmt); 48060ba2cbe9Sxc151355 } 48070ba2cbe9Sxc151355 48080ba2cbe9Sxc151355 static void 48098d5c46e6Sam223141 do_scan_wifi(int argc, char **argv, const char *use) 48100ba2cbe9Sxc151355 { 48118d5c46e6Sam223141 do_display_wifi(argc, argv, WIFI_CMD_SCAN, use); 48120ba2cbe9Sxc151355 } 48130ba2cbe9Sxc151355 48140ba2cbe9Sxc151355 static void 48158d5c46e6Sam223141 do_show_wifi(int argc, char **argv, const char *use) 48160ba2cbe9Sxc151355 { 48178d5c46e6Sam223141 do_display_wifi(argc, argv, WIFI_CMD_SHOW, use); 48180ba2cbe9Sxc151355 } 48190ba2cbe9Sxc151355 48200ba2cbe9Sxc151355 typedef struct wlan_count_attr { 48210ba2cbe9Sxc151355 uint_t wc_count; 4822d62bc4baSyz147064 datalink_id_t wc_linkid; 48230ba2cbe9Sxc151355 } wlan_count_attr_t; 48240ba2cbe9Sxc151355 48254ac67f02SAnurag S. Maskey /* ARGSUSED */ 4826d62bc4baSyz147064 static int 48274ac67f02SAnurag S. Maskey do_count_wlan(dladm_handle_t dh, datalink_id_t linkid, void *arg) 48280ba2cbe9Sxc151355 { 482933343a97Smeem wlan_count_attr_t *cp = arg; 48300ba2cbe9Sxc151355 48310ba2cbe9Sxc151355 if (cp->wc_count == 0) 4832d62bc4baSyz147064 cp->wc_linkid = linkid; 48330ba2cbe9Sxc151355 cp->wc_count++; 4834d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 48350ba2cbe9Sxc151355 } 48360ba2cbe9Sxc151355 48370ba2cbe9Sxc151355 static int 4838a399b765Szf162725 parse_wlan_keys(char *str, dladm_wlan_key_t **keys, uint_t *key_countp) 48390ba2cbe9Sxc151355 { 48400ba2cbe9Sxc151355 uint_t i; 4841a399b765Szf162725 dladm_wlan_key_t *wk; 4842*8002d411SSowmini Varadhan int nfields = 1; 4843*8002d411SSowmini Varadhan char *field, *token, *lasts = NULL, c; 48440ba2cbe9Sxc151355 4845*8002d411SSowmini Varadhan token = str; 4846*8002d411SSowmini Varadhan while ((c = *token++) != NULL) { 4847*8002d411SSowmini Varadhan if (c == ',') 4848*8002d411SSowmini Varadhan nfields++; 4849*8002d411SSowmini Varadhan } 4850*8002d411SSowmini Varadhan token = strdup(str); 4851*8002d411SSowmini Varadhan if (token == NULL) 48520ba2cbe9Sxc151355 return (-1); 48530ba2cbe9Sxc151355 4854*8002d411SSowmini Varadhan wk = malloc(nfields * sizeof (dladm_wlan_key_t)); 48550ba2cbe9Sxc151355 if (wk == NULL) 48560ba2cbe9Sxc151355 goto fail; 48570ba2cbe9Sxc151355 4858*8002d411SSowmini Varadhan token = str; 4859*8002d411SSowmini Varadhan for (i = 0; i < nfields; i++) { 48600ba2cbe9Sxc151355 char *s; 48610ba2cbe9Sxc151355 dladm_secobj_class_t class; 48620ba2cbe9Sxc151355 dladm_status_t status; 48630ba2cbe9Sxc151355 4864*8002d411SSowmini Varadhan field = strtok_r(token, ",", &lasts); 4865*8002d411SSowmini Varadhan token = NULL; 4866*8002d411SSowmini Varadhan 4867*8002d411SSowmini Varadhan (void) strlcpy(wk[i].wk_name, field, 4868a399b765Szf162725 DLADM_WLAN_MAX_KEYNAME_LEN); 48690ba2cbe9Sxc151355 48700ba2cbe9Sxc151355 wk[i].wk_idx = 1; 48710ba2cbe9Sxc151355 if ((s = strrchr(wk[i].wk_name, ':')) != NULL) { 48720ba2cbe9Sxc151355 if (s[1] == '\0' || s[2] != '\0' || !isdigit(s[1])) 48730ba2cbe9Sxc151355 goto fail; 48740ba2cbe9Sxc151355 48750ba2cbe9Sxc151355 wk[i].wk_idx = (uint_t)(s[1] - '0'); 48760ba2cbe9Sxc151355 *s = '\0'; 48770ba2cbe9Sxc151355 } 4878a399b765Szf162725 wk[i].wk_len = DLADM_WLAN_MAX_KEY_LEN; 48790ba2cbe9Sxc151355 48804ac67f02SAnurag S. Maskey status = dladm_get_secobj(handle, wk[i].wk_name, &class, 48810ba2cbe9Sxc151355 wk[i].wk_val, &wk[i].wk_len, 0); 48820ba2cbe9Sxc151355 if (status != DLADM_STATUS_OK) { 48830ba2cbe9Sxc151355 if (status == DLADM_STATUS_NOTFOUND) { 48844ac67f02SAnurag S. Maskey status = dladm_get_secobj(handle, wk[i].wk_name, 48850ba2cbe9Sxc151355 &class, wk[i].wk_val, &wk[i].wk_len, 48860ba2cbe9Sxc151355 DLADM_OPT_PERSIST); 48870ba2cbe9Sxc151355 } 48880ba2cbe9Sxc151355 if (status != DLADM_STATUS_OK) 48890ba2cbe9Sxc151355 goto fail; 48900ba2cbe9Sxc151355 } 4891a399b765Szf162725 wk[i].wk_class = class; 48920ba2cbe9Sxc151355 } 48930ba2cbe9Sxc151355 *keys = wk; 48940ba2cbe9Sxc151355 *key_countp = i; 4895*8002d411SSowmini Varadhan free(token); 48960ba2cbe9Sxc151355 return (0); 48970ba2cbe9Sxc151355 fail: 48980ba2cbe9Sxc151355 free(wk); 4899*8002d411SSowmini Varadhan free(token); 49000ba2cbe9Sxc151355 return (-1); 49010ba2cbe9Sxc151355 } 49020ba2cbe9Sxc151355 49030ba2cbe9Sxc151355 static void 49048d5c46e6Sam223141 do_connect_wifi(int argc, char **argv, const char *use) 49050ba2cbe9Sxc151355 { 49060ba2cbe9Sxc151355 int option; 4907f595a68aSyz147064 dladm_wlan_attr_t attr, *attrp; 4908f595a68aSyz147064 dladm_status_t status = DLADM_STATUS_OK; 4909f595a68aSyz147064 int timeout = DLADM_WLAN_CONNECT_TIMEOUT_DEFAULT; 4910d62bc4baSyz147064 datalink_id_t linkid = DATALINK_ALL_LINKID; 4911a399b765Szf162725 dladm_wlan_key_t *keys = NULL; 49120ba2cbe9Sxc151355 uint_t key_count = 0; 49130ba2cbe9Sxc151355 uint_t flags = 0; 4914f595a68aSyz147064 dladm_wlan_secmode_t keysecmode = DLADM_WLAN_SECMODE_NONE; 4915a399b765Szf162725 char buf[DLADM_STRSIZE]; 49160ba2cbe9Sxc151355 49170ba2cbe9Sxc151355 opterr = 0; 49180ba2cbe9Sxc151355 (void) memset(&attr, 0, sizeof (attr)); 49190ba2cbe9Sxc151355 while ((option = getopt_long(argc, argv, ":e:i:a:m:b:s:k:T:c", 49200ba2cbe9Sxc151355 wifi_longopts, NULL)) != -1) { 49210ba2cbe9Sxc151355 switch (option) { 49220ba2cbe9Sxc151355 case 'e': 4923f595a68aSyz147064 status = dladm_wlan_str2essid(optarg, &attr.wa_essid); 4924f595a68aSyz147064 if (status != DLADM_STATUS_OK) 492533343a97Smeem die("invalid ESSID '%s'", optarg); 492633343a97Smeem 4927f595a68aSyz147064 attr.wa_valid |= DLADM_WLAN_ATTR_ESSID; 49280ba2cbe9Sxc151355 /* 49290ba2cbe9Sxc151355 * Try to connect without doing a scan. 49300ba2cbe9Sxc151355 */ 4931f595a68aSyz147064 flags |= DLADM_WLAN_CONNECT_NOSCAN; 49320ba2cbe9Sxc151355 break; 49330ba2cbe9Sxc151355 case 'i': 4934f595a68aSyz147064 status = dladm_wlan_str2bssid(optarg, &attr.wa_bssid); 4935f595a68aSyz147064 if (status != DLADM_STATUS_OK) 493633343a97Smeem die("invalid BSSID %s", optarg); 493733343a97Smeem 4938f595a68aSyz147064 attr.wa_valid |= DLADM_WLAN_ATTR_BSSID; 49390ba2cbe9Sxc151355 break; 49400ba2cbe9Sxc151355 case 'a': 4941f595a68aSyz147064 status = dladm_wlan_str2auth(optarg, &attr.wa_auth); 4942f595a68aSyz147064 if (status != DLADM_STATUS_OK) 494333343a97Smeem die("invalid authentication mode '%s'", optarg); 494433343a97Smeem 4945f595a68aSyz147064 attr.wa_valid |= DLADM_WLAN_ATTR_AUTH; 49460ba2cbe9Sxc151355 break; 49470ba2cbe9Sxc151355 case 'm': 4948f595a68aSyz147064 status = dladm_wlan_str2mode(optarg, &attr.wa_mode); 4949f595a68aSyz147064 if (status != DLADM_STATUS_OK) 495033343a97Smeem die("invalid mode '%s'", optarg); 495133343a97Smeem 4952f595a68aSyz147064 attr.wa_valid |= DLADM_WLAN_ATTR_MODE; 49530ba2cbe9Sxc151355 break; 49540ba2cbe9Sxc151355 case 'b': 4955f595a68aSyz147064 if ((status = dladm_wlan_str2bsstype(optarg, 4956f595a68aSyz147064 &attr.wa_bsstype)) != DLADM_STATUS_OK) { 495733343a97Smeem die("invalid bsstype '%s'", optarg); 4958f595a68aSyz147064 } 495933343a97Smeem 4960f595a68aSyz147064 attr.wa_valid |= DLADM_WLAN_ATTR_BSSTYPE; 49610ba2cbe9Sxc151355 break; 49620ba2cbe9Sxc151355 case 's': 4963f595a68aSyz147064 if ((status = dladm_wlan_str2secmode(optarg, 4964f595a68aSyz147064 &attr.wa_secmode)) != DLADM_STATUS_OK) { 496533343a97Smeem die("invalid security mode '%s'", optarg); 4966f595a68aSyz147064 } 496733343a97Smeem 4968f595a68aSyz147064 attr.wa_valid |= DLADM_WLAN_ATTR_SECMODE; 49690ba2cbe9Sxc151355 break; 49700ba2cbe9Sxc151355 case 'k': 4971a399b765Szf162725 if (parse_wlan_keys(optarg, &keys, &key_count) < 0) 497233343a97Smeem die("invalid key(s) '%s'", optarg); 497333343a97Smeem 4974a399b765Szf162725 if (keys[0].wk_class == DLADM_SECOBJ_CLASS_WEP) 4975f595a68aSyz147064 keysecmode = DLADM_WLAN_SECMODE_WEP; 4976a399b765Szf162725 else 4977a399b765Szf162725 keysecmode = DLADM_WLAN_SECMODE_WPA; 49780ba2cbe9Sxc151355 break; 49790ba2cbe9Sxc151355 case 'T': 49800ba2cbe9Sxc151355 if (strcasecmp(optarg, "forever") == 0) { 49810ba2cbe9Sxc151355 timeout = -1; 49820ba2cbe9Sxc151355 break; 49830ba2cbe9Sxc151355 } 498433343a97Smeem if (!str2int(optarg, &timeout) || timeout < 0) 498533343a97Smeem die("invalid timeout value '%s'", optarg); 49860ba2cbe9Sxc151355 break; 49870ba2cbe9Sxc151355 case 'c': 4988f595a68aSyz147064 flags |= DLADM_WLAN_CONNECT_CREATEIBSS; 4989a399b765Szf162725 flags |= DLADM_WLAN_CONNECT_CREATEIBSS; 49900ba2cbe9Sxc151355 break; 49910ba2cbe9Sxc151355 default: 49928d5c46e6Sam223141 die_opterr(optopt, option, use); 49930ba2cbe9Sxc151355 break; 49940ba2cbe9Sxc151355 } 49950ba2cbe9Sxc151355 } 49960ba2cbe9Sxc151355 4997f595a68aSyz147064 if (keysecmode == DLADM_WLAN_SECMODE_NONE) { 4998a399b765Szf162725 if ((attr.wa_valid & DLADM_WLAN_ATTR_SECMODE) != 0) { 4999a399b765Szf162725 die("key required for security mode '%s'", 5000a399b765Szf162725 dladm_wlan_secmode2str(&attr.wa_secmode, buf)); 5001a399b765Szf162725 } 50020ba2cbe9Sxc151355 } else { 5003f595a68aSyz147064 if ((attr.wa_valid & DLADM_WLAN_ATTR_SECMODE) != 0 && 500433343a97Smeem attr.wa_secmode != keysecmode) 500533343a97Smeem die("incompatible -s and -k options"); 5006f595a68aSyz147064 attr.wa_valid |= DLADM_WLAN_ATTR_SECMODE; 5007a399b765Szf162725 attr.wa_secmode = keysecmode; 5008a399b765Szf162725 } 50090ba2cbe9Sxc151355 5010d62bc4baSyz147064 if (optind == (argc - 1)) { 50114ac67f02SAnurag S. Maskey if ((status = dladm_name2info(handle, argv[optind], &linkid, 50124ac67f02SAnurag S. Maskey NULL, NULL, NULL)) != DLADM_STATUS_OK) { 5013d62bc4baSyz147064 die_dlerr(status, "link %s is not valid", argv[optind]); 5014d62bc4baSyz147064 } 5015d62bc4baSyz147064 } else if (optind != argc) { 50160ba2cbe9Sxc151355 usage(); 5017d62bc4baSyz147064 } 50180ba2cbe9Sxc151355 5019d62bc4baSyz147064 if (linkid == DATALINK_ALL_LINKID) { 50200ba2cbe9Sxc151355 wlan_count_attr_t wcattr; 50210ba2cbe9Sxc151355 5022d62bc4baSyz147064 wcattr.wc_linkid = DATALINK_INVALID_LINKID; 50230ba2cbe9Sxc151355 wcattr.wc_count = 0; 50244ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(do_count_wlan, handle, &wcattr, 5025d62bc4baSyz147064 DATALINK_CLASS_PHYS, DL_WIFI, DLADM_OPT_ACTIVE); 50260ba2cbe9Sxc151355 if (wcattr.wc_count == 0) { 502733343a97Smeem die("no wifi links are available"); 50280ba2cbe9Sxc151355 } else if (wcattr.wc_count > 1) { 502933343a97Smeem die("link name is required when more than one wifi " 503033343a97Smeem "link is available"); 50310ba2cbe9Sxc151355 } 5032d62bc4baSyz147064 linkid = wcattr.wc_linkid; 50330ba2cbe9Sxc151355 } 50340ba2cbe9Sxc151355 attrp = (attr.wa_valid == 0) ? NULL : &attr; 503533343a97Smeem again: 50364ac67f02SAnurag S. Maskey if ((status = dladm_wlan_connect(handle, linkid, attrp, timeout, keys, 5037f595a68aSyz147064 key_count, flags)) != DLADM_STATUS_OK) { 5038f595a68aSyz147064 if ((flags & DLADM_WLAN_CONNECT_NOSCAN) != 0) { 50390ba2cbe9Sxc151355 /* 504033343a97Smeem * Try again with scanning and filtering. 50410ba2cbe9Sxc151355 */ 5042f595a68aSyz147064 flags &= ~DLADM_WLAN_CONNECT_NOSCAN; 504333343a97Smeem goto again; 50440ba2cbe9Sxc151355 } 504533343a97Smeem 5046f595a68aSyz147064 if (status == DLADM_STATUS_NOTFOUND) { 50470ba2cbe9Sxc151355 if (attr.wa_valid == 0) { 504833343a97Smeem die("no wifi networks are available"); 50490ba2cbe9Sxc151355 } else { 505033343a97Smeem die("no wifi networks with the specified " 505133343a97Smeem "criteria are available"); 50520ba2cbe9Sxc151355 } 50530ba2cbe9Sxc151355 } 5054d62bc4baSyz147064 die_dlerr(status, "cannot connect"); 50550ba2cbe9Sxc151355 } 50560ba2cbe9Sxc151355 free(keys); 50570ba2cbe9Sxc151355 } 50580ba2cbe9Sxc151355 50590ba2cbe9Sxc151355 /* ARGSUSED */ 5060d62bc4baSyz147064 static int 50614ac67f02SAnurag S. Maskey do_all_disconnect_wifi(dladm_handle_t dh, datalink_id_t linkid, void *arg) 50620ba2cbe9Sxc151355 { 5063f595a68aSyz147064 dladm_status_t status; 50640ba2cbe9Sxc151355 50654ac67f02SAnurag S. Maskey status = dladm_wlan_disconnect(dh, linkid); 5066f595a68aSyz147064 if (status != DLADM_STATUS_OK) 5067d62bc4baSyz147064 warn_dlerr(status, "cannot disconnect link"); 506833343a97Smeem 5069d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 50700ba2cbe9Sxc151355 } 50710ba2cbe9Sxc151355 50720ba2cbe9Sxc151355 static void 50738d5c46e6Sam223141 do_disconnect_wifi(int argc, char **argv, const char *use) 50740ba2cbe9Sxc151355 { 50750ba2cbe9Sxc151355 int option; 5076d62bc4baSyz147064 datalink_id_t linkid = DATALINK_ALL_LINKID; 50770ba2cbe9Sxc151355 boolean_t all_links = B_FALSE; 5078f595a68aSyz147064 dladm_status_t status; 50790ba2cbe9Sxc151355 wlan_count_attr_t wcattr; 50800ba2cbe9Sxc151355 50810ba2cbe9Sxc151355 opterr = 0; 50820ba2cbe9Sxc151355 while ((option = getopt_long(argc, argv, ":a", 50830ba2cbe9Sxc151355 wifi_longopts, NULL)) != -1) { 50840ba2cbe9Sxc151355 switch (option) { 50850ba2cbe9Sxc151355 case 'a': 50860ba2cbe9Sxc151355 all_links = B_TRUE; 50870ba2cbe9Sxc151355 break; 50880ba2cbe9Sxc151355 default: 50898d5c46e6Sam223141 die_opterr(optopt, option, use); 50900ba2cbe9Sxc151355 break; 50910ba2cbe9Sxc151355 } 50920ba2cbe9Sxc151355 } 50930ba2cbe9Sxc151355 5094d62bc4baSyz147064 if (optind == (argc - 1)) { 50954ac67f02SAnurag S. Maskey if ((status = dladm_name2info(handle, argv[optind], &linkid, 50964ac67f02SAnurag S. Maskey NULL, NULL, NULL)) != DLADM_STATUS_OK) { 5097d62bc4baSyz147064 die_dlerr(status, "link %s is not valid", argv[optind]); 5098d62bc4baSyz147064 } 5099d62bc4baSyz147064 } else if (optind != argc) { 51000ba2cbe9Sxc151355 usage(); 5101d62bc4baSyz147064 } 51020ba2cbe9Sxc151355 5103d62bc4baSyz147064 if (linkid == DATALINK_ALL_LINKID) { 51040ba2cbe9Sxc151355 if (!all_links) { 5105d62bc4baSyz147064 wcattr.wc_linkid = linkid; 51060ba2cbe9Sxc151355 wcattr.wc_count = 0; 51074ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(do_count_wlan, handle, 51084ac67f02SAnurag S. Maskey &wcattr, DATALINK_CLASS_PHYS, DL_WIFI, 51094ac67f02SAnurag S. Maskey DLADM_OPT_ACTIVE); 51100ba2cbe9Sxc151355 if (wcattr.wc_count == 0) { 511133343a97Smeem die("no wifi links are available"); 51120ba2cbe9Sxc151355 } else if (wcattr.wc_count > 1) { 511333343a97Smeem die("link name is required when more than " 511433343a97Smeem "one wifi link is available"); 51150ba2cbe9Sxc151355 } 5116d62bc4baSyz147064 linkid = wcattr.wc_linkid; 51170ba2cbe9Sxc151355 } else { 5118d62bc4baSyz147064 (void) dladm_walk_datalink_id(do_all_disconnect_wifi, 51194ac67f02SAnurag S. Maskey handle, NULL, DATALINK_CLASS_PHYS, DL_WIFI, 5120d62bc4baSyz147064 DLADM_OPT_ACTIVE); 51210ba2cbe9Sxc151355 return; 51220ba2cbe9Sxc151355 } 51230ba2cbe9Sxc151355 } 51244ac67f02SAnurag S. Maskey status = dladm_wlan_disconnect(handle, linkid); 5125f595a68aSyz147064 if (status != DLADM_STATUS_OK) 5126d62bc4baSyz147064 die_dlerr(status, "cannot disconnect"); 51270ba2cbe9Sxc151355 } 51280ba2cbe9Sxc151355 51290ba2cbe9Sxc151355 static void 5130d62bc4baSyz147064 print_linkprop(datalink_id_t linkid, show_linkprop_state_t *statep, 51314ac67f02SAnurag S. Maskey const char *propname, dladm_prop_type_t type, const char *format, 51324ac67f02SAnurag S. Maskey char **pptr) 51330ba2cbe9Sxc151355 { 51340ba2cbe9Sxc151355 int i; 51350ba2cbe9Sxc151355 char *ptr, *lim; 51360ba2cbe9Sxc151355 char buf[DLADM_STRSIZE]; 5137da14cebeSEric Cheng char *unknown = "--", *notsup = ""; 51380ba2cbe9Sxc151355 char **propvals = statep->ls_propvals; 5139d62bc4baSyz147064 uint_t valcnt = DLADM_MAX_PROP_VALCNT; 51400ba2cbe9Sxc151355 dladm_status_t status; 51410ba2cbe9Sxc151355 51424ac67f02SAnurag S. Maskey status = dladm_get_linkprop(handle, linkid, type, propname, propvals, 51434ac67f02SAnurag S. Maskey &valcnt); 51440ba2cbe9Sxc151355 if (status != DLADM_STATUS_OK) { 5145f595a68aSyz147064 if (status == DLADM_STATUS_TEMPONLY) { 5146d62bc4baSyz147064 if (type == DLADM_PROP_VAL_MODIFIABLE && 5147d62bc4baSyz147064 statep->ls_persist) { 5148d62bc4baSyz147064 valcnt = 1; 5149d62bc4baSyz147064 propvals = &unknown; 5150d62bc4baSyz147064 } else { 5151f595a68aSyz147064 statep->ls_status = status; 5152e7801d59Ssowmini statep->ls_retstatus = status; 5153f595a68aSyz147064 return; 5154d62bc4baSyz147064 } 5155f595a68aSyz147064 } else if (status == DLADM_STATUS_NOTSUP || 5156f595a68aSyz147064 statep->ls_persist) { 51570ba2cbe9Sxc151355 valcnt = 1; 5158afdda45fSVasumathi Sundaram - Sun Microsystems if (type == DLADM_PROP_VAL_CURRENT || 5159afdda45fSVasumathi Sundaram - Sun Microsystems type == DLADM_PROP_VAL_PERM) 51600ba2cbe9Sxc151355 propvals = &unknown; 51610ba2cbe9Sxc151355 else 51620ba2cbe9Sxc151355 propvals = ¬sup; 5163149b7eb2SSowmini Varadhan } else if (status == DLADM_STATUS_NOTDEFINED) { 5164149b7eb2SSowmini Varadhan propvals = ¬sup; /* STR_UNDEF_VAL */ 51650ba2cbe9Sxc151355 } else { 5166e7801d59Ssowmini if (statep->ls_proplist && 5167e7801d59Ssowmini statep->ls_status == DLADM_STATUS_OK) { 5168f595a68aSyz147064 warn_dlerr(status, 5169f595a68aSyz147064 "cannot get link property '%s' for %s", 5170f595a68aSyz147064 propname, statep->ls_link); 5171d62bc4baSyz147064 } 5172e7801d59Ssowmini statep->ls_status = status; 5173e7801d59Ssowmini statep->ls_retstatus = status; 5174f595a68aSyz147064 return; 51750ba2cbe9Sxc151355 } 51760ba2cbe9Sxc151355 } 51770ba2cbe9Sxc151355 5178e7801d59Ssowmini statep->ls_status = DLADM_STATUS_OK; 5179e7801d59Ssowmini 51800ba2cbe9Sxc151355 ptr = buf; 51810ba2cbe9Sxc151355 lim = buf + DLADM_STRSIZE; 51820ba2cbe9Sxc151355 for (i = 0; i < valcnt; i++) { 5183*8002d411SSowmini Varadhan if (propvals[i][0] == '\0' && !statep->ls_parsable) 5184*8002d411SSowmini Varadhan ptr += snprintf(ptr, lim - ptr, "--,"); 51850ba2cbe9Sxc151355 else 51860ba2cbe9Sxc151355 ptr += snprintf(ptr, lim - ptr, "%s,", propvals[i]); 51870ba2cbe9Sxc151355 if (ptr >= lim) 51880ba2cbe9Sxc151355 break; 51890ba2cbe9Sxc151355 } 51900ba2cbe9Sxc151355 if (valcnt > 0) 51910ba2cbe9Sxc151355 buf[strlen(buf) - 1] = '\0'; 51920ba2cbe9Sxc151355 51930ba2cbe9Sxc151355 lim = statep->ls_line + MAX_PROP_LINE; 5194*8002d411SSowmini Varadhan if (statep->ls_parsable) { 51950ba2cbe9Sxc151355 *pptr += snprintf(*pptr, lim - *pptr, 5196e7801d59Ssowmini "%s", buf); 51970ba2cbe9Sxc151355 } else { 51980ba2cbe9Sxc151355 *pptr += snprintf(*pptr, lim - *pptr, format, buf); 51990ba2cbe9Sxc151355 } 52000ba2cbe9Sxc151355 } 52010ba2cbe9Sxc151355 5202*8002d411SSowmini Varadhan static boolean_t 5203*8002d411SSowmini Varadhan print_linkprop_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize) 5204e7801d59Ssowmini { 5205*8002d411SSowmini Varadhan linkprop_args_t *arg = ofarg->ofmt_cbarg; 5206e7801d59Ssowmini char *propname = arg->ls_propname; 5207e7801d59Ssowmini show_linkprop_state_t *statep = arg->ls_state; 5208e7801d59Ssowmini char *ptr = statep->ls_line; 5209e7801d59Ssowmini char *lim = ptr + MAX_PROP_LINE; 5210e7801d59Ssowmini datalink_id_t linkid = arg->ls_linkid; 5211e7801d59Ssowmini 5212*8002d411SSowmini Varadhan switch (ofarg->ofmt_id) { 5213e7801d59Ssowmini case LINKPROP_LINK: 5214e7801d59Ssowmini (void) snprintf(ptr, lim - ptr, "%s", statep->ls_link); 5215e7801d59Ssowmini break; 5216e7801d59Ssowmini case LINKPROP_PROPERTY: 5217e7801d59Ssowmini (void) snprintf(ptr, lim - ptr, "%s", propname); 5218e7801d59Ssowmini break; 5219e7801d59Ssowmini case LINKPROP_VALUE: 5220e7801d59Ssowmini print_linkprop(linkid, statep, propname, 5221e7801d59Ssowmini statep->ls_persist ? DLADM_PROP_VAL_PERSISTENT : 5222e7801d59Ssowmini DLADM_PROP_VAL_CURRENT, "%s", &ptr); 5223e7801d59Ssowmini /* 5224e7801d59Ssowmini * If we failed to query the link property, for example, query 5225e7801d59Ssowmini * the persistent value of a non-persistable link property, 5226e7801d59Ssowmini * simply skip the output. 5227e7801d59Ssowmini */ 5228e7801d59Ssowmini if (statep->ls_status != DLADM_STATUS_OK) 5229e7801d59Ssowmini goto skip; 5230e7801d59Ssowmini ptr = statep->ls_line; 5231e7801d59Ssowmini break; 5232afdda45fSVasumathi Sundaram - Sun Microsystems case LINKPROP_PERM: 5233afdda45fSVasumathi Sundaram - Sun Microsystems print_linkprop(linkid, statep, propname, 5234afdda45fSVasumathi Sundaram - Sun Microsystems DLADM_PROP_VAL_PERM, "%s", &ptr); 5235afdda45fSVasumathi Sundaram - Sun Microsystems if (statep->ls_status != DLADM_STATUS_OK) 5236afdda45fSVasumathi Sundaram - Sun Microsystems goto skip; 5237afdda45fSVasumathi Sundaram - Sun Microsystems ptr = statep->ls_line; 5238afdda45fSVasumathi Sundaram - Sun Microsystems break; 5239e7801d59Ssowmini case LINKPROP_DEFAULT: 5240e7801d59Ssowmini print_linkprop(linkid, statep, propname, 5241e7801d59Ssowmini DLADM_PROP_VAL_DEFAULT, "%s", &ptr); 5242e7801d59Ssowmini if (statep->ls_status != DLADM_STATUS_OK) 5243e7801d59Ssowmini goto skip; 5244e7801d59Ssowmini ptr = statep->ls_line; 5245e7801d59Ssowmini break; 5246e7801d59Ssowmini case LINKPROP_POSSIBLE: 5247e7801d59Ssowmini print_linkprop(linkid, statep, propname, 5248e7801d59Ssowmini DLADM_PROP_VAL_MODIFIABLE, "%s ", &ptr); 5249e7801d59Ssowmini if (statep->ls_status != DLADM_STATUS_OK) 5250e7801d59Ssowmini goto skip; 5251e7801d59Ssowmini ptr = statep->ls_line; 5252e7801d59Ssowmini break; 5253e7801d59Ssowmini default: 5254e7801d59Ssowmini die("invalid input"); 5255e7801d59Ssowmini break; 5256e7801d59Ssowmini } 5257*8002d411SSowmini Varadhan (void) strlcpy(buf, ptr, bufsize); 5258*8002d411SSowmini Varadhan return (B_TRUE); 5259e7801d59Ssowmini skip: 5260*8002d411SSowmini Varadhan return ((statep->ls_status == DLADM_STATUS_OK) ? 5261*8002d411SSowmini Varadhan B_TRUE : B_FALSE); 5262e7801d59Ssowmini } 5263e7801d59Ssowmini 5264bcb5c89dSSowmini Varadhan static boolean_t 5265bcb5c89dSSowmini Varadhan linkprop_is_supported(datalink_id_t linkid, const char *propname, 5266bcb5c89dSSowmini Varadhan show_linkprop_state_t *statep) 5267bcb5c89dSSowmini Varadhan { 5268bcb5c89dSSowmini Varadhan dladm_status_t status; 5269bcb5c89dSSowmini Varadhan uint_t valcnt = DLADM_MAX_PROP_VALCNT; 5270bcb5c89dSSowmini Varadhan 52714784fcbdSSowmini Varadhan /* if used with -p flag, always print output */ 52724784fcbdSSowmini Varadhan if (statep->ls_proplist != NULL) 52734784fcbdSSowmini Varadhan return (B_TRUE); 52744784fcbdSSowmini Varadhan 52754ac67f02SAnurag S. Maskey status = dladm_get_linkprop(handle, linkid, DLADM_PROP_VAL_DEFAULT, 5276bcb5c89dSSowmini Varadhan propname, statep->ls_propvals, &valcnt); 5277bcb5c89dSSowmini Varadhan 5278149b7eb2SSowmini Varadhan if (status == DLADM_STATUS_OK) 5279149b7eb2SSowmini Varadhan return (B_TRUE); 5280149b7eb2SSowmini Varadhan 5281149b7eb2SSowmini Varadhan /* 5282149b7eb2SSowmini Varadhan * A system wide default value is not available for the 5283149b7eb2SSowmini Varadhan * property. Check if current value can be retrieved. 5284149b7eb2SSowmini Varadhan */ 52854ac67f02SAnurag S. Maskey status = dladm_get_linkprop(handle, linkid, DLADM_PROP_VAL_CURRENT, 5286149b7eb2SSowmini Varadhan propname, statep->ls_propvals, &valcnt); 5287149b7eb2SSowmini Varadhan 5288149b7eb2SSowmini Varadhan return (status == DLADM_STATUS_OK); 5289bcb5c89dSSowmini Varadhan } 5290bcb5c89dSSowmini Varadhan 52914ac67f02SAnurag S. Maskey /* ARGSUSED */ 5292d62bc4baSyz147064 static int 52934ac67f02SAnurag S. Maskey show_linkprop(dladm_handle_t dh, datalink_id_t linkid, const char *propname, 52944ac67f02SAnurag S. Maskey void *arg) 52950ba2cbe9Sxc151355 { 52960ba2cbe9Sxc151355 show_linkprop_state_t *statep = arg; 5297e7801d59Ssowmini linkprop_args_t ls_arg; 52980ba2cbe9Sxc151355 5299e7801d59Ssowmini bzero(&ls_arg, sizeof (ls_arg)); 5300e7801d59Ssowmini ls_arg.ls_state = statep; 5301e7801d59Ssowmini ls_arg.ls_propname = (char *)propname; 5302e7801d59Ssowmini ls_arg.ls_linkid = linkid; 53030ba2cbe9Sxc151355 530462ee1d25SArtem Kachitchkine /* 530562ee1d25SArtem Kachitchkine * This will need to be fixed when kernel interfaces are added 530662ee1d25SArtem Kachitchkine * to enable walking of all known private properties. For now, 530762ee1d25SArtem Kachitchkine * we are limited to walking persistent private properties only. 530862ee1d25SArtem Kachitchkine */ 530962ee1d25SArtem Kachitchkine if ((propname[0] == '_') && !statep->ls_persist && 531062ee1d25SArtem Kachitchkine (statep->ls_proplist == NULL)) 531162ee1d25SArtem Kachitchkine return (DLADM_WALK_CONTINUE); 5312*8002d411SSowmini Varadhan if (!statep->ls_parsable && 5313149b7eb2SSowmini Varadhan !linkprop_is_supported(linkid, propname, statep)) 5314bcb5c89dSSowmini Varadhan return (DLADM_WALK_CONTINUE); 5315bcb5c89dSSowmini Varadhan 5316*8002d411SSowmini Varadhan ofmt_print(statep->ls_ofmt, &ls_arg); 5317e7801d59Ssowmini 5318d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 53190ba2cbe9Sxc151355 } 53200ba2cbe9Sxc151355 53210ba2cbe9Sxc151355 static void 53228d5c46e6Sam223141 do_show_linkprop(int argc, char **argv, const char *use) 53230ba2cbe9Sxc151355 { 5324f4b3ec61Sdh155122 int option; 532563a6526dSMichael Lim char propstr[DLADM_STRSIZE]; 5326da14cebeSEric Cheng dladm_arg_list_t *proplist = NULL; 5327d62bc4baSyz147064 datalink_id_t linkid = DATALINK_ALL_LINKID; 53280ba2cbe9Sxc151355 show_linkprop_state_t state; 5329d62bc4baSyz147064 uint32_t flags = DLADM_OPT_ACTIVE; 5330d62bc4baSyz147064 dladm_status_t status; 5331e7801d59Ssowmini char *fields_str = NULL; 5332*8002d411SSowmini Varadhan ofmt_handle_t ofmt; 5333*8002d411SSowmini Varadhan ofmt_status_t oferr; 5334*8002d411SSowmini Varadhan uint_t ofmtflags = 0; 53350ba2cbe9Sxc151355 533663a6526dSMichael Lim bzero(propstr, DLADM_STRSIZE); 53370ba2cbe9Sxc151355 opterr = 0; 53380ba2cbe9Sxc151355 state.ls_propvals = NULL; 53390ba2cbe9Sxc151355 state.ls_line = NULL; 5340*8002d411SSowmini Varadhan state.ls_parsable = B_FALSE; 53410ba2cbe9Sxc151355 state.ls_persist = B_FALSE; 53420ba2cbe9Sxc151355 state.ls_header = B_TRUE; 5343e7801d59Ssowmini state.ls_retstatus = DLADM_STATUS_OK; 534463a6526dSMichael Lim 5345e7801d59Ssowmini while ((option = getopt_long(argc, argv, ":p:cPo:", 53460ba2cbe9Sxc151355 prop_longopts, NULL)) != -1) { 53470ba2cbe9Sxc151355 switch (option) { 53480ba2cbe9Sxc151355 case 'p': 534963a6526dSMichael Lim (void) strlcat(propstr, optarg, DLADM_STRSIZE); 535063a6526dSMichael Lim if (strlcat(propstr, ",", DLADM_STRSIZE) >= 535163a6526dSMichael Lim DLADM_STRSIZE) 535263a6526dSMichael Lim die("property list too long '%s'", propstr); 53530ba2cbe9Sxc151355 break; 53540ba2cbe9Sxc151355 case 'c': 5355*8002d411SSowmini Varadhan state.ls_parsable = B_TRUE; 53560ba2cbe9Sxc151355 break; 53570ba2cbe9Sxc151355 case 'P': 53580ba2cbe9Sxc151355 state.ls_persist = B_TRUE; 5359d62bc4baSyz147064 flags = DLADM_OPT_PERSIST; 53600ba2cbe9Sxc151355 break; 5361e7801d59Ssowmini case 'o': 5362e7801d59Ssowmini fields_str = optarg; 5363e7801d59Ssowmini break; 53640ba2cbe9Sxc151355 default: 53658d5c46e6Sam223141 die_opterr(optopt, option, use); 53660ba2cbe9Sxc151355 break; 53670ba2cbe9Sxc151355 } 53680ba2cbe9Sxc151355 } 53690ba2cbe9Sxc151355 5370d62bc4baSyz147064 if (optind == (argc - 1)) { 53714ac67f02SAnurag S. Maskey if ((status = dladm_name2info(handle, argv[optind], &linkid, 53724ac67f02SAnurag S. Maskey NULL, NULL, NULL)) != DLADM_STATUS_OK) { 5373d62bc4baSyz147064 die_dlerr(status, "link %s is not valid", argv[optind]); 5374d62bc4baSyz147064 } 5375d62bc4baSyz147064 } else if (optind != argc) { 53760ba2cbe9Sxc151355 usage(); 5377d62bc4baSyz147064 } 53780ba2cbe9Sxc151355 537963a6526dSMichael Lim if (dladm_parse_link_props(propstr, &proplist, B_TRUE) 538063a6526dSMichael Lim != DLADM_STATUS_OK) 538163a6526dSMichael Lim die("invalid link properties specified"); 5382f4b3ec61Sdh155122 state.ls_proplist = proplist; 5383f595a68aSyz147064 state.ls_status = DLADM_STATUS_OK; 5384f4b3ec61Sdh155122 5385*8002d411SSowmini Varadhan if (state.ls_parsable) 5386*8002d411SSowmini Varadhan ofmtflags |= OFMT_PARSABLE; 5387*8002d411SSowmini Varadhan oferr = ofmt_open(fields_str, linkprop_fields, ofmtflags, 0, &ofmt); 5388*8002d411SSowmini Varadhan dladm_ofmt_check(oferr, state.ls_parsable, ofmt); 5389*8002d411SSowmini Varadhan state.ls_ofmt = ofmt; 5390e7801d59Ssowmini 5391d62bc4baSyz147064 if (linkid == DATALINK_ALL_LINKID) { 53924ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(show_linkprop_onelink, handle, 53934ac67f02SAnurag S. Maskey &state, DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE, flags); 5394f4b3ec61Sdh155122 } else { 53954ac67f02SAnurag S. Maskey (void) show_linkprop_onelink(handle, linkid, &state); 5396f4b3ec61Sdh155122 } 5397*8002d411SSowmini Varadhan ofmt_close(ofmt); 5398da14cebeSEric Cheng dladm_free_props(proplist); 5399f595a68aSyz147064 54004ac67f02SAnurag S. Maskey if (state.ls_retstatus != DLADM_STATUS_OK) { 54014ac67f02SAnurag S. Maskey dladm_close(handle); 5402f595a68aSyz147064 exit(EXIT_FAILURE); 5403f4b3ec61Sdh155122 } 54044ac67f02SAnurag S. Maskey } 5405f4b3ec61Sdh155122 5406d62bc4baSyz147064 static int 54074ac67f02SAnurag S. Maskey show_linkprop_onelink(dladm_handle_t hdl, datalink_id_t linkid, void *arg) 5408f4b3ec61Sdh155122 { 5409948f2876Sss150715 int i; 5410f4b3ec61Sdh155122 char *buf; 5411d62bc4baSyz147064 uint32_t flags; 5412da14cebeSEric Cheng dladm_arg_list_t *proplist = NULL; 5413d62bc4baSyz147064 show_linkprop_state_t *statep = arg; 5414d62bc4baSyz147064 dlpi_handle_t dh = NULL; 5415f4b3ec61Sdh155122 5416d62bc4baSyz147064 statep->ls_status = DLADM_STATUS_OK; 5417d62bc4baSyz147064 54184ac67f02SAnurag S. Maskey if (dladm_datalink_id2info(hdl, linkid, &flags, NULL, NULL, 54194ac67f02SAnurag S. Maskey statep->ls_link, MAXLINKNAMELEN) != DLADM_STATUS_OK) { 5420d62bc4baSyz147064 statep->ls_status = DLADM_STATUS_NOTFOUND; 5421d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 5422d62bc4baSyz147064 } 5423d62bc4baSyz147064 5424d62bc4baSyz147064 if ((statep->ls_persist && !(flags & DLADM_OPT_PERSIST)) || 5425d62bc4baSyz147064 (!statep->ls_persist && !(flags & DLADM_OPT_ACTIVE))) { 5426d62bc4baSyz147064 statep->ls_status = DLADM_STATUS_BADARG; 5427d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 5428d62bc4baSyz147064 } 5429d62bc4baSyz147064 5430f4b3ec61Sdh155122 proplist = statep->ls_proplist; 54310ba2cbe9Sxc151355 54320ba2cbe9Sxc151355 /* 54330ba2cbe9Sxc151355 * When some WiFi links are opened for the first time, their hardware 54340ba2cbe9Sxc151355 * automatically scans for APs and does other slow operations. Thus, 54350ba2cbe9Sxc151355 * if there are no open links, the retrieval of link properties 54360ba2cbe9Sxc151355 * (below) will proceed slowly unless we hold the link open. 5437d62bc4baSyz147064 * 5438d62bc4baSyz147064 * Note that failure of dlpi_open() does not necessarily mean invalid 5439d62bc4baSyz147064 * link properties, because dlpi_open() may fail because of incorrect 5440d62bc4baSyz147064 * autopush configuration. Therefore, we ingore the return value of 5441d62bc4baSyz147064 * dlpi_open(). 54420ba2cbe9Sxc151355 */ 5443d62bc4baSyz147064 if (!statep->ls_persist) 5444d62bc4baSyz147064 (void) dlpi_open(statep->ls_link, &dh, 0); 54450ba2cbe9Sxc151355 5446d62bc4baSyz147064 buf = malloc((sizeof (char *) + DLADM_PROP_VAL_MAX) * 5447d62bc4baSyz147064 DLADM_MAX_PROP_VALCNT + MAX_PROP_LINE); 544833343a97Smeem if (buf == NULL) 544933343a97Smeem die("insufficient memory"); 545033343a97Smeem 5451f4b3ec61Sdh155122 statep->ls_propvals = (char **)(void *)buf; 5452d62bc4baSyz147064 for (i = 0; i < DLADM_MAX_PROP_VALCNT; i++) { 5453d62bc4baSyz147064 statep->ls_propvals[i] = buf + 5454d62bc4baSyz147064 sizeof (char *) * DLADM_MAX_PROP_VALCNT + 54550ba2cbe9Sxc151355 i * DLADM_PROP_VAL_MAX; 54560ba2cbe9Sxc151355 } 5457f4b3ec61Sdh155122 statep->ls_line = buf + 5458d62bc4baSyz147064 (sizeof (char *) + DLADM_PROP_VAL_MAX) * DLADM_MAX_PROP_VALCNT; 54590ba2cbe9Sxc151355 54600ba2cbe9Sxc151355 if (proplist != NULL) { 5461da14cebeSEric Cheng for (i = 0; i < proplist->al_count; i++) { 54624ac67f02SAnurag S. Maskey (void) show_linkprop(hdl, linkid, 5463da14cebeSEric Cheng proplist->al_info[i].ai_name, statep); 54640ba2cbe9Sxc151355 } 5465d62bc4baSyz147064 } else { 54664ac67f02SAnurag S. Maskey (void) dladm_walk_linkprop(hdl, linkid, statep, 54674ac67f02SAnurag S. Maskey show_linkprop); 5468d62bc4baSyz147064 } 5469d62bc4baSyz147064 if (dh != NULL) 5470948f2876Sss150715 dlpi_close(dh); 54710ba2cbe9Sxc151355 free(buf); 5472d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 54730ba2cbe9Sxc151355 } 54740ba2cbe9Sxc151355 54750ba2cbe9Sxc151355 static dladm_status_t 5476d62bc4baSyz147064 set_linkprop_persist(datalink_id_t linkid, const char *prop_name, 5477d62bc4baSyz147064 char **prop_val, uint_t val_cnt, boolean_t reset) 54780ba2cbe9Sxc151355 { 54790ba2cbe9Sxc151355 dladm_status_t status; 54800ba2cbe9Sxc151355 54814ac67f02SAnurag S. Maskey status = dladm_set_linkprop(handle, linkid, prop_name, prop_val, 54824ac67f02SAnurag S. Maskey val_cnt, DLADM_OPT_PERSIST); 54830ba2cbe9Sxc151355 54840ba2cbe9Sxc151355 if (status != DLADM_STATUS_OK) { 5485da14cebeSEric Cheng warn_dlerr(status, "cannot persistently %s link property '%s'", 5486da14cebeSEric Cheng reset ? "reset" : "set", prop_name); 54870ba2cbe9Sxc151355 } 54880ba2cbe9Sxc151355 return (status); 54890ba2cbe9Sxc151355 } 54900ba2cbe9Sxc151355 5491da14cebeSEric Cheng static int 54924ac67f02SAnurag S. Maskey reset_one_linkprop(dladm_handle_t dh, datalink_id_t linkid, 54934ac67f02SAnurag S. Maskey const char *propname, void *arg) 5494da14cebeSEric Cheng { 5495da14cebeSEric Cheng set_linkprop_state_t *statep = arg; 5496da14cebeSEric Cheng dladm_status_t status; 5497da14cebeSEric Cheng 54984ac67f02SAnurag S. Maskey status = dladm_set_linkprop(dh, linkid, propname, NULL, 0, 5499da14cebeSEric Cheng DLADM_OPT_ACTIVE); 5500da14cebeSEric Cheng if (status != DLADM_STATUS_OK) { 5501da14cebeSEric Cheng warn_dlerr(status, "cannot reset link property '%s' on '%s'", 5502da14cebeSEric Cheng propname, statep->ls_name); 5503da14cebeSEric Cheng } 5504da14cebeSEric Cheng if (!statep->ls_temp) { 5505da14cebeSEric Cheng dladm_status_t s; 5506da14cebeSEric Cheng 5507da14cebeSEric Cheng s = set_linkprop_persist(linkid, propname, NULL, 0, 5508da14cebeSEric Cheng statep->ls_reset); 5509da14cebeSEric Cheng if (s != DLADM_STATUS_OK) 5510da14cebeSEric Cheng status = s; 5511da14cebeSEric Cheng } 5512da14cebeSEric Cheng if (status != DLADM_STATUS_OK) 5513da14cebeSEric Cheng statep->ls_status = status; 5514da14cebeSEric Cheng 5515da14cebeSEric Cheng return (DLADM_WALK_CONTINUE); 5516da14cebeSEric Cheng } 5517da14cebeSEric Cheng 55180ba2cbe9Sxc151355 static void 55198d5c46e6Sam223141 set_linkprop(int argc, char **argv, boolean_t reset, const char *use) 55200ba2cbe9Sxc151355 { 55210ba2cbe9Sxc151355 int i, option; 55220ba2cbe9Sxc151355 char errmsg[DLADM_STRSIZE]; 5523d62bc4baSyz147064 char *altroot = NULL; 5524d62bc4baSyz147064 datalink_id_t linkid; 55250ba2cbe9Sxc151355 boolean_t temp = B_FALSE; 55260ba2cbe9Sxc151355 dladm_status_t status = DLADM_STATUS_OK; 552763a6526dSMichael Lim char propstr[DLADM_STRSIZE]; 5528da14cebeSEric Cheng dladm_arg_list_t *proplist = NULL; 55290ba2cbe9Sxc151355 55300ba2cbe9Sxc151355 opterr = 0; 553163a6526dSMichael Lim bzero(propstr, DLADM_STRSIZE); 553263a6526dSMichael Lim 55330ba2cbe9Sxc151355 while ((option = getopt_long(argc, argv, ":p:R:t", 55340ba2cbe9Sxc151355 prop_longopts, NULL)) != -1) { 55350ba2cbe9Sxc151355 switch (option) { 55360ba2cbe9Sxc151355 case 'p': 553763a6526dSMichael Lim (void) strlcat(propstr, optarg, DLADM_STRSIZE); 553863a6526dSMichael Lim if (strlcat(propstr, ",", DLADM_STRSIZE) >= 553963a6526dSMichael Lim DLADM_STRSIZE) 554063a6526dSMichael Lim die("property list too long '%s'", propstr); 55410ba2cbe9Sxc151355 break; 55420ba2cbe9Sxc151355 case 't': 55430ba2cbe9Sxc151355 temp = B_TRUE; 55440ba2cbe9Sxc151355 break; 55450ba2cbe9Sxc151355 case 'R': 5546d62bc4baSyz147064 altroot = optarg; 55470ba2cbe9Sxc151355 break; 55480ba2cbe9Sxc151355 default: 55498d5c46e6Sam223141 die_opterr(optopt, option, use); 55508d5c46e6Sam223141 55510ba2cbe9Sxc151355 } 55520ba2cbe9Sxc151355 } 55530ba2cbe9Sxc151355 5554d62bc4baSyz147064 /* get link name (required last argument) */ 5555d62bc4baSyz147064 if (optind != (argc - 1)) 55560ba2cbe9Sxc151355 usage(); 55570ba2cbe9Sxc151355 555863a6526dSMichael Lim if (dladm_parse_link_props(propstr, &proplist, reset) != 555963a6526dSMichael Lim DLADM_STATUS_OK) 556063a6526dSMichael Lim die("invalid link properties specified"); 556163a6526dSMichael Lim 5562d62bc4baSyz147064 if (proplist == NULL && !reset) 556333343a97Smeem die("link property must be specified"); 556433343a97Smeem 5565d62bc4baSyz147064 if (altroot != NULL) { 5566da14cebeSEric Cheng dladm_free_props(proplist); 5567d62bc4baSyz147064 altroot_cmd(altroot, argc, argv); 5568d62bc4baSyz147064 } 5569d62bc4baSyz147064 55704ac67f02SAnurag S. Maskey status = dladm_name2info(handle, argv[optind], &linkid, NULL, NULL, 55714ac67f02SAnurag S. Maskey NULL); 5572d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 5573d62bc4baSyz147064 die_dlerr(status, "link %s is not valid", argv[optind]); 5574d62bc4baSyz147064 5575d62bc4baSyz147064 if (proplist == NULL) { 5576da14cebeSEric Cheng set_linkprop_state_t state; 557713994ee8Sxz162242 5578da14cebeSEric Cheng state.ls_name = argv[optind]; 5579da14cebeSEric Cheng state.ls_reset = reset; 5580da14cebeSEric Cheng state.ls_temp = temp; 5581da14cebeSEric Cheng state.ls_status = DLADM_STATUS_OK; 5582da14cebeSEric Cheng 55834ac67f02SAnurag S. Maskey (void) dladm_walk_linkprop(handle, linkid, &state, 55844ac67f02SAnurag S. Maskey reset_one_linkprop); 5585da14cebeSEric Cheng 5586da14cebeSEric Cheng status = state.ls_status; 55870ba2cbe9Sxc151355 goto done; 55880ba2cbe9Sxc151355 } 55890ba2cbe9Sxc151355 5590da14cebeSEric Cheng for (i = 0; i < proplist->al_count; i++) { 5591da14cebeSEric Cheng dladm_arg_info_t *aip = &proplist->al_info[i]; 55920ba2cbe9Sxc151355 char **val; 55930ba2cbe9Sxc151355 uint_t count; 55940ba2cbe9Sxc151355 dladm_status_t s; 55950ba2cbe9Sxc151355 55960ba2cbe9Sxc151355 if (reset) { 55970ba2cbe9Sxc151355 val = NULL; 55980ba2cbe9Sxc151355 count = 0; 55990ba2cbe9Sxc151355 } else { 5600da14cebeSEric Cheng val = aip->ai_val; 5601da14cebeSEric Cheng count = aip->ai_count; 56020ba2cbe9Sxc151355 if (count == 0) { 560333343a97Smeem warn("no value specified for '%s'", 5604da14cebeSEric Cheng aip->ai_name); 56050ba2cbe9Sxc151355 status = DLADM_STATUS_BADARG; 56060ba2cbe9Sxc151355 continue; 56070ba2cbe9Sxc151355 } 56080ba2cbe9Sxc151355 } 56094ac67f02SAnurag S. Maskey s = dladm_set_linkprop(handle, linkid, aip->ai_name, val, count, 5610d62bc4baSyz147064 DLADM_OPT_ACTIVE); 56110ba2cbe9Sxc151355 if (s == DLADM_STATUS_OK) { 56120ba2cbe9Sxc151355 if (!temp) { 5613d62bc4baSyz147064 s = set_linkprop_persist(linkid, 5614da14cebeSEric Cheng aip->ai_name, val, count, reset); 56150ba2cbe9Sxc151355 if (s != DLADM_STATUS_OK) 56160ba2cbe9Sxc151355 status = s; 56170ba2cbe9Sxc151355 } 56180ba2cbe9Sxc151355 continue; 56190ba2cbe9Sxc151355 } 56200ba2cbe9Sxc151355 status = s; 56210ba2cbe9Sxc151355 switch (s) { 56220ba2cbe9Sxc151355 case DLADM_STATUS_NOTFOUND: 5623da14cebeSEric Cheng warn("invalid link property '%s'", aip->ai_name); 56240ba2cbe9Sxc151355 break; 56250ba2cbe9Sxc151355 case DLADM_STATUS_BADVAL: { 56260ba2cbe9Sxc151355 int j; 56270ba2cbe9Sxc151355 char *ptr, *lim; 56280ba2cbe9Sxc151355 char **propvals = NULL; 5629d62bc4baSyz147064 uint_t valcnt = DLADM_MAX_PROP_VALCNT; 56300ba2cbe9Sxc151355 56310ba2cbe9Sxc151355 ptr = malloc((sizeof (char *) + 5632d62bc4baSyz147064 DLADM_PROP_VAL_MAX) * DLADM_MAX_PROP_VALCNT + 56330ba2cbe9Sxc151355 MAX_PROP_LINE); 56340ba2cbe9Sxc151355 56350ba2cbe9Sxc151355 propvals = (char **)(void *)ptr; 563633343a97Smeem if (propvals == NULL) 563733343a97Smeem die("insufficient memory"); 563833343a97Smeem 5639d62bc4baSyz147064 for (j = 0; j < DLADM_MAX_PROP_VALCNT; j++) { 56400ba2cbe9Sxc151355 propvals[j] = ptr + sizeof (char *) * 5641d62bc4baSyz147064 DLADM_MAX_PROP_VALCNT + 56420ba2cbe9Sxc151355 j * DLADM_PROP_VAL_MAX; 56430ba2cbe9Sxc151355 } 56444ac67f02SAnurag S. Maskey s = dladm_get_linkprop(handle, linkid, 5645da14cebeSEric Cheng DLADM_PROP_VAL_MODIFIABLE, aip->ai_name, propvals, 5646d62bc4baSyz147064 &valcnt); 5647d62bc4baSyz147064 5648d62bc4baSyz147064 if (s != DLADM_STATUS_OK) { 5649d62bc4baSyz147064 warn_dlerr(status, "cannot set link property " 5650da14cebeSEric Cheng "'%s' on '%s'", aip->ai_name, argv[optind]); 5651d62bc4baSyz147064 free(propvals); 5652d62bc4baSyz147064 break; 5653d62bc4baSyz147064 } 56540ba2cbe9Sxc151355 56550ba2cbe9Sxc151355 ptr = errmsg; 56560ba2cbe9Sxc151355 lim = ptr + DLADM_STRSIZE; 56570ba2cbe9Sxc151355 *ptr = '\0'; 5658d62bc4baSyz147064 for (j = 0; j < valcnt; j++) { 56590ba2cbe9Sxc151355 ptr += snprintf(ptr, lim - ptr, "%s,", 56600ba2cbe9Sxc151355 propvals[j]); 56610ba2cbe9Sxc151355 if (ptr >= lim) 56620ba2cbe9Sxc151355 break; 56630ba2cbe9Sxc151355 } 5664f4b3ec61Sdh155122 if (ptr > errmsg) { 56650ba2cbe9Sxc151355 *(ptr - 1) = '\0'; 566633343a97Smeem warn("link property '%s' must be one of: %s", 5667da14cebeSEric Cheng aip->ai_name, errmsg); 5668f4b3ec61Sdh155122 } else 5669f4b3ec61Sdh155122 warn("invalid link property '%s'", *val); 56700ba2cbe9Sxc151355 free(propvals); 56710ba2cbe9Sxc151355 break; 56720ba2cbe9Sxc151355 } 56730ba2cbe9Sxc151355 default: 56740ba2cbe9Sxc151355 if (reset) { 567533343a97Smeem warn_dlerr(status, "cannot reset link property " 5676da14cebeSEric Cheng "'%s' on '%s'", aip->ai_name, argv[optind]); 56770ba2cbe9Sxc151355 } else { 567833343a97Smeem warn_dlerr(status, "cannot set link property " 5679da14cebeSEric Cheng "'%s' on '%s'", aip->ai_name, argv[optind]); 56800ba2cbe9Sxc151355 } 56810ba2cbe9Sxc151355 break; 56820ba2cbe9Sxc151355 } 56830ba2cbe9Sxc151355 } 56840ba2cbe9Sxc151355 done: 5685da14cebeSEric Cheng dladm_free_props(proplist); 56864ac67f02SAnurag S. Maskey if (status != DLADM_STATUS_OK) { 56874ac67f02SAnurag S. Maskey dladm_close(handle); 56880ba2cbe9Sxc151355 exit(1); 56890ba2cbe9Sxc151355 } 56904ac67f02SAnurag S. Maskey } 56910ba2cbe9Sxc151355 56920ba2cbe9Sxc151355 static void 56938d5c46e6Sam223141 do_set_linkprop(int argc, char **argv, const char *use) 56940ba2cbe9Sxc151355 { 56958d5c46e6Sam223141 set_linkprop(argc, argv, B_FALSE, use); 56960ba2cbe9Sxc151355 } 56970ba2cbe9Sxc151355 56980ba2cbe9Sxc151355 static void 56998d5c46e6Sam223141 do_reset_linkprop(int argc, char **argv, const char *use) 57000ba2cbe9Sxc151355 { 57018d5c46e6Sam223141 set_linkprop(argc, argv, B_TRUE, use); 57020ba2cbe9Sxc151355 } 57030ba2cbe9Sxc151355 57040ba2cbe9Sxc151355 static int 57050ba2cbe9Sxc151355 convert_secobj(char *buf, uint_t len, uint8_t *obj_val, uint_t *obj_lenp, 57060ba2cbe9Sxc151355 dladm_secobj_class_t class) 57070ba2cbe9Sxc151355 { 57080ba2cbe9Sxc151355 int error = 0; 57090ba2cbe9Sxc151355 5710a399b765Szf162725 if (class == DLADM_SECOBJ_CLASS_WPA) { 5711a399b765Szf162725 if (len < 8 || len > 63) 5712a399b765Szf162725 return (EINVAL); 5713a399b765Szf162725 (void) memcpy(obj_val, buf, len); 5714a399b765Szf162725 *obj_lenp = len; 5715a399b765Szf162725 return (error); 5716a399b765Szf162725 } 57170ba2cbe9Sxc151355 5718a399b765Szf162725 if (class == DLADM_SECOBJ_CLASS_WEP) { 57190ba2cbe9Sxc151355 switch (len) { 57200ba2cbe9Sxc151355 case 5: /* ASCII key sizes */ 57210ba2cbe9Sxc151355 case 13: 57220ba2cbe9Sxc151355 (void) memcpy(obj_val, buf, len); 57230ba2cbe9Sxc151355 *obj_lenp = len; 57240ba2cbe9Sxc151355 break; 57250ba2cbe9Sxc151355 case 10: /* Hex key sizes, not preceded by 0x */ 57260ba2cbe9Sxc151355 case 26: 57270ba2cbe9Sxc151355 error = hexascii_to_octet(buf, len, obj_val, obj_lenp); 57280ba2cbe9Sxc151355 break; 57290ba2cbe9Sxc151355 case 12: /* Hex key sizes, preceded by 0x */ 57300ba2cbe9Sxc151355 case 28: 57310ba2cbe9Sxc151355 if (strncmp(buf, "0x", 2) != 0) 57320ba2cbe9Sxc151355 return (EINVAL); 5733a399b765Szf162725 error = hexascii_to_octet(buf + 2, len - 2, 5734a399b765Szf162725 obj_val, obj_lenp); 57350ba2cbe9Sxc151355 break; 57360ba2cbe9Sxc151355 default: 57370ba2cbe9Sxc151355 return (EINVAL); 57380ba2cbe9Sxc151355 } 57390ba2cbe9Sxc151355 return (error); 57400ba2cbe9Sxc151355 } 57410ba2cbe9Sxc151355 5742a399b765Szf162725 return (ENOENT); 5743a399b765Szf162725 } 5744a399b765Szf162725 57450ba2cbe9Sxc151355 static void 57460ba2cbe9Sxc151355 defersig(int sig) 57470ba2cbe9Sxc151355 { 57480ba2cbe9Sxc151355 signalled = sig; 57490ba2cbe9Sxc151355 } 57500ba2cbe9Sxc151355 57510ba2cbe9Sxc151355 static int 57520ba2cbe9Sxc151355 get_secobj_from_tty(uint_t try, const char *objname, char *buf) 57530ba2cbe9Sxc151355 { 57540ba2cbe9Sxc151355 uint_t len = 0; 57550ba2cbe9Sxc151355 int c; 57560ba2cbe9Sxc151355 struct termios stored, current; 57570ba2cbe9Sxc151355 void (*sigfunc)(int); 57580ba2cbe9Sxc151355 57590ba2cbe9Sxc151355 /* 57600ba2cbe9Sxc151355 * Turn off echo -- but before we do so, defer SIGINT handling 57610ba2cbe9Sxc151355 * so that a ^C doesn't leave the terminal corrupted. 57620ba2cbe9Sxc151355 */ 57630ba2cbe9Sxc151355 sigfunc = signal(SIGINT, defersig); 57640ba2cbe9Sxc151355 (void) fflush(stdin); 57650ba2cbe9Sxc151355 (void) tcgetattr(0, &stored); 57660ba2cbe9Sxc151355 current = stored; 57670ba2cbe9Sxc151355 current.c_lflag &= ~(ICANON|ECHO); 57680ba2cbe9Sxc151355 current.c_cc[VTIME] = 0; 57690ba2cbe9Sxc151355 current.c_cc[VMIN] = 1; 57700ba2cbe9Sxc151355 (void) tcsetattr(0, TCSANOW, ¤t); 57710ba2cbe9Sxc151355 again: 57720ba2cbe9Sxc151355 if (try == 1) 57730ba2cbe9Sxc151355 (void) printf(gettext("provide value for '%s': "), objname); 57740ba2cbe9Sxc151355 else 57750ba2cbe9Sxc151355 (void) printf(gettext("confirm value for '%s': "), objname); 57760ba2cbe9Sxc151355 57770ba2cbe9Sxc151355 (void) fflush(stdout); 57780ba2cbe9Sxc151355 while (signalled == 0) { 57790ba2cbe9Sxc151355 c = getchar(); 57800ba2cbe9Sxc151355 if (c == '\n' || c == '\r') { 57810ba2cbe9Sxc151355 if (len != 0) 57820ba2cbe9Sxc151355 break; 57830ba2cbe9Sxc151355 (void) putchar('\n'); 57840ba2cbe9Sxc151355 goto again; 57850ba2cbe9Sxc151355 } 57860ba2cbe9Sxc151355 57870ba2cbe9Sxc151355 buf[len++] = c; 57880ba2cbe9Sxc151355 if (len >= DLADM_SECOBJ_VAL_MAX - 1) 57890ba2cbe9Sxc151355 break; 57900ba2cbe9Sxc151355 (void) putchar('*'); 57910ba2cbe9Sxc151355 } 57920ba2cbe9Sxc151355 57930ba2cbe9Sxc151355 (void) putchar('\n'); 57940ba2cbe9Sxc151355 (void) fflush(stdin); 57950ba2cbe9Sxc151355 57960ba2cbe9Sxc151355 /* 57970ba2cbe9Sxc151355 * Restore terminal setting and handle deferred signals. 57980ba2cbe9Sxc151355 */ 57990ba2cbe9Sxc151355 (void) tcsetattr(0, TCSANOW, &stored); 58000ba2cbe9Sxc151355 58010ba2cbe9Sxc151355 (void) signal(SIGINT, sigfunc); 58020ba2cbe9Sxc151355 if (signalled != 0) 58030ba2cbe9Sxc151355 (void) kill(getpid(), signalled); 58040ba2cbe9Sxc151355 58050ba2cbe9Sxc151355 return (len); 58060ba2cbe9Sxc151355 } 58070ba2cbe9Sxc151355 58080ba2cbe9Sxc151355 static int 58090ba2cbe9Sxc151355 get_secobj_val(char *obj_name, uint8_t *obj_val, uint_t *obj_lenp, 58100ba2cbe9Sxc151355 dladm_secobj_class_t class, FILE *filep) 58110ba2cbe9Sxc151355 { 58120ba2cbe9Sxc151355 int rval; 58130ba2cbe9Sxc151355 uint_t len, len2; 58140ba2cbe9Sxc151355 char buf[DLADM_SECOBJ_VAL_MAX], buf2[DLADM_SECOBJ_VAL_MAX]; 58150ba2cbe9Sxc151355 58160ba2cbe9Sxc151355 if (filep == NULL) { 58170ba2cbe9Sxc151355 len = get_secobj_from_tty(1, obj_name, buf); 58180ba2cbe9Sxc151355 rval = convert_secobj(buf, len, obj_val, obj_lenp, class); 58190ba2cbe9Sxc151355 if (rval == 0) { 58200ba2cbe9Sxc151355 len2 = get_secobj_from_tty(2, obj_name, buf2); 58210ba2cbe9Sxc151355 if (len != len2 || memcmp(buf, buf2, len) != 0) 58220ba2cbe9Sxc151355 rval = ENOTSUP; 58230ba2cbe9Sxc151355 } 58240ba2cbe9Sxc151355 return (rval); 58250ba2cbe9Sxc151355 } else { 58260ba2cbe9Sxc151355 for (;;) { 58270ba2cbe9Sxc151355 if (fgets(buf, sizeof (buf), filep) == NULL) 58280ba2cbe9Sxc151355 break; 58290ba2cbe9Sxc151355 if (isspace(buf[0])) 58300ba2cbe9Sxc151355 continue; 58310ba2cbe9Sxc151355 58320ba2cbe9Sxc151355 len = strlen(buf); 58330ba2cbe9Sxc151355 if (buf[len - 1] == '\n') { 58340ba2cbe9Sxc151355 buf[len - 1] = '\0'; 58350ba2cbe9Sxc151355 len--; 58360ba2cbe9Sxc151355 } 58370ba2cbe9Sxc151355 break; 58380ba2cbe9Sxc151355 } 58390ba2cbe9Sxc151355 (void) fclose(filep); 58400ba2cbe9Sxc151355 } 58410ba2cbe9Sxc151355 return (convert_secobj(buf, len, obj_val, obj_lenp, class)); 58420ba2cbe9Sxc151355 } 58430ba2cbe9Sxc151355 58440ba2cbe9Sxc151355 static boolean_t 58450ba2cbe9Sxc151355 check_auth(const char *auth) 58460ba2cbe9Sxc151355 { 58470ba2cbe9Sxc151355 struct passwd *pw; 58480ba2cbe9Sxc151355 58490ba2cbe9Sxc151355 if ((pw = getpwuid(getuid())) == NULL) 58500ba2cbe9Sxc151355 return (B_FALSE); 58510ba2cbe9Sxc151355 58520ba2cbe9Sxc151355 return (chkauthattr(auth, pw->pw_name) != 0); 58530ba2cbe9Sxc151355 } 58540ba2cbe9Sxc151355 58550ba2cbe9Sxc151355 static void 58560ba2cbe9Sxc151355 audit_secobj(char *auth, char *class, char *obj, 58570ba2cbe9Sxc151355 boolean_t success, boolean_t create) 58580ba2cbe9Sxc151355 { 58590ba2cbe9Sxc151355 adt_session_data_t *ah; 58600ba2cbe9Sxc151355 adt_event_data_t *event; 58610ba2cbe9Sxc151355 au_event_t flag; 58620ba2cbe9Sxc151355 char *errstr; 58630ba2cbe9Sxc151355 58640ba2cbe9Sxc151355 if (create) { 58650ba2cbe9Sxc151355 flag = ADT_dladm_create_secobj; 58660ba2cbe9Sxc151355 errstr = "ADT_dladm_create_secobj"; 58670ba2cbe9Sxc151355 } else { 58680ba2cbe9Sxc151355 flag = ADT_dladm_delete_secobj; 58690ba2cbe9Sxc151355 errstr = "ADT_dladm_delete_secobj"; 58700ba2cbe9Sxc151355 } 58710ba2cbe9Sxc151355 587233343a97Smeem if (adt_start_session(&ah, NULL, ADT_USE_PROC_DATA) != 0) 587333343a97Smeem die("adt_start_session: %s", strerror(errno)); 58740ba2cbe9Sxc151355 587533343a97Smeem if ((event = adt_alloc_event(ah, flag)) == NULL) 587633343a97Smeem die("adt_alloc_event (%s): %s", errstr, strerror(errno)); 58770ba2cbe9Sxc151355 58780ba2cbe9Sxc151355 /* fill in audit info */ 58790ba2cbe9Sxc151355 if (create) { 58800ba2cbe9Sxc151355 event->adt_dladm_create_secobj.auth_used = auth; 58810ba2cbe9Sxc151355 event->adt_dladm_create_secobj.obj_class = class; 58820ba2cbe9Sxc151355 event->adt_dladm_create_secobj.obj_name = obj; 58830ba2cbe9Sxc151355 } else { 58840ba2cbe9Sxc151355 event->adt_dladm_delete_secobj.auth_used = auth; 58850ba2cbe9Sxc151355 event->adt_dladm_delete_secobj.obj_class = class; 58860ba2cbe9Sxc151355 event->adt_dladm_delete_secobj.obj_name = obj; 58870ba2cbe9Sxc151355 } 58880ba2cbe9Sxc151355 58890ba2cbe9Sxc151355 if (success) { 58900ba2cbe9Sxc151355 if (adt_put_event(event, ADT_SUCCESS, ADT_SUCCESS) != 0) { 589133343a97Smeem die("adt_put_event (%s, success): %s", errstr, 589233343a97Smeem strerror(errno)); 58930ba2cbe9Sxc151355 } 58940ba2cbe9Sxc151355 } else { 58950ba2cbe9Sxc151355 if (adt_put_event(event, ADT_FAILURE, 58960ba2cbe9Sxc151355 ADT_FAIL_VALUE_AUTH) != 0) { 589733343a97Smeem die("adt_put_event: (%s, failure): %s", errstr, 589833343a97Smeem strerror(errno)); 58990ba2cbe9Sxc151355 } 59000ba2cbe9Sxc151355 } 59010ba2cbe9Sxc151355 59020ba2cbe9Sxc151355 adt_free_event(event); 59030ba2cbe9Sxc151355 (void) adt_end_session(ah); 59040ba2cbe9Sxc151355 } 59050ba2cbe9Sxc151355 59060ba2cbe9Sxc151355 #define MAX_SECOBJS 32 59070ba2cbe9Sxc151355 #define MAX_SECOBJ_NAMELEN 32 59080ba2cbe9Sxc151355 static void 59098d5c46e6Sam223141 do_create_secobj(int argc, char **argv, const char *use) 59100ba2cbe9Sxc151355 { 59110ba2cbe9Sxc151355 int option, rval; 59120ba2cbe9Sxc151355 FILE *filep = NULL; 59130ba2cbe9Sxc151355 char *obj_name = NULL; 59140ba2cbe9Sxc151355 char *class_name = NULL; 59150ba2cbe9Sxc151355 uint8_t obj_val[DLADM_SECOBJ_VAL_MAX]; 59160ba2cbe9Sxc151355 uint_t obj_len; 59170ba2cbe9Sxc151355 boolean_t success, temp = B_FALSE; 59180ba2cbe9Sxc151355 dladm_status_t status; 59190ba2cbe9Sxc151355 dladm_secobj_class_t class = -1; 59200ba2cbe9Sxc151355 uid_t euid; 59210ba2cbe9Sxc151355 59220ba2cbe9Sxc151355 opterr = 0; 59230ba2cbe9Sxc151355 (void) memset(obj_val, 0, DLADM_SECOBJ_VAL_MAX); 59240ba2cbe9Sxc151355 while ((option = getopt_long(argc, argv, ":f:c:R:t", 59250ba2cbe9Sxc151355 wifi_longopts, NULL)) != -1) { 59260ba2cbe9Sxc151355 switch (option) { 59270ba2cbe9Sxc151355 case 'f': 59280ba2cbe9Sxc151355 euid = geteuid(); 59290ba2cbe9Sxc151355 (void) seteuid(getuid()); 59300ba2cbe9Sxc151355 filep = fopen(optarg, "r"); 59310ba2cbe9Sxc151355 if (filep == NULL) { 593233343a97Smeem die("cannot open %s: %s", optarg, 593333343a97Smeem strerror(errno)); 59340ba2cbe9Sxc151355 } 59350ba2cbe9Sxc151355 (void) seteuid(euid); 59360ba2cbe9Sxc151355 break; 59370ba2cbe9Sxc151355 case 'c': 59380ba2cbe9Sxc151355 class_name = optarg; 59390ba2cbe9Sxc151355 status = dladm_str2secobjclass(optarg, &class); 59400ba2cbe9Sxc151355 if (status != DLADM_STATUS_OK) { 594133343a97Smeem die("invalid secure object class '%s', " 5942a399b765Szf162725 "valid values are: wep, wpa", optarg); 59430ba2cbe9Sxc151355 } 59440ba2cbe9Sxc151355 break; 59450ba2cbe9Sxc151355 case 't': 59460ba2cbe9Sxc151355 temp = B_TRUE; 59470ba2cbe9Sxc151355 break; 59480ba2cbe9Sxc151355 case 'R': 59490ba2cbe9Sxc151355 status = dladm_set_rootdir(optarg); 59500ba2cbe9Sxc151355 if (status != DLADM_STATUS_OK) { 595133343a97Smeem die_dlerr(status, "invalid directory " 595233343a97Smeem "specified"); 59530ba2cbe9Sxc151355 } 59540ba2cbe9Sxc151355 break; 59550ba2cbe9Sxc151355 default: 59568d5c46e6Sam223141 die_opterr(optopt, option, use); 59570ba2cbe9Sxc151355 break; 59580ba2cbe9Sxc151355 } 59590ba2cbe9Sxc151355 } 59600ba2cbe9Sxc151355 59610ba2cbe9Sxc151355 if (optind == (argc - 1)) 59620ba2cbe9Sxc151355 obj_name = argv[optind]; 59630ba2cbe9Sxc151355 else if (optind != argc) 59640ba2cbe9Sxc151355 usage(); 59650ba2cbe9Sxc151355 596633343a97Smeem if (class == -1) 596733343a97Smeem die("secure object class required"); 59680ba2cbe9Sxc151355 596933343a97Smeem if (obj_name == NULL) 597033343a97Smeem die("secure object name required"); 59710ba2cbe9Sxc151355 5972a9489f61SAnurag S. Maskey if (!dladm_valid_secobj_name(obj_name)) 5973a9489f61SAnurag S. Maskey die("invalid secure object name '%s'", obj_name); 5974a9489f61SAnurag S. Maskey 59750ba2cbe9Sxc151355 success = check_auth(LINK_SEC_AUTH); 59760ba2cbe9Sxc151355 audit_secobj(LINK_SEC_AUTH, class_name, obj_name, success, B_TRUE); 597733343a97Smeem if (!success) 597833343a97Smeem die("authorization '%s' is required", LINK_SEC_AUTH); 59790ba2cbe9Sxc151355 598033343a97Smeem rval = get_secobj_val(obj_name, obj_val, &obj_len, class, filep); 598133343a97Smeem if (rval != 0) { 59820ba2cbe9Sxc151355 switch (rval) { 59830ba2cbe9Sxc151355 case ENOENT: 598433343a97Smeem die("invalid secure object class"); 59850ba2cbe9Sxc151355 break; 59860ba2cbe9Sxc151355 case EINVAL: 598733343a97Smeem die("invalid secure object value"); 59880ba2cbe9Sxc151355 break; 59890ba2cbe9Sxc151355 case ENOTSUP: 599033343a97Smeem die("verification failed"); 59910ba2cbe9Sxc151355 break; 59920ba2cbe9Sxc151355 default: 599333343a97Smeem die("invalid secure object: %s", strerror(rval)); 59940ba2cbe9Sxc151355 break; 59950ba2cbe9Sxc151355 } 59960ba2cbe9Sxc151355 } 59970ba2cbe9Sxc151355 59984ac67f02SAnurag S. Maskey status = dladm_set_secobj(handle, obj_name, class, obj_val, obj_len, 5999d62bc4baSyz147064 DLADM_OPT_CREATE | DLADM_OPT_ACTIVE); 60000ba2cbe9Sxc151355 if (status != DLADM_STATUS_OK) { 600133343a97Smeem die_dlerr(status, "could not create secure object '%s'", 600233343a97Smeem obj_name); 60030ba2cbe9Sxc151355 } 60040ba2cbe9Sxc151355 if (temp) 60050ba2cbe9Sxc151355 return; 60060ba2cbe9Sxc151355 60074ac67f02SAnurag S. Maskey status = dladm_set_secobj(handle, obj_name, class, obj_val, obj_len, 60080ba2cbe9Sxc151355 DLADM_OPT_PERSIST); 60090ba2cbe9Sxc151355 if (status != DLADM_STATUS_OK) { 601033343a97Smeem warn_dlerr(status, "could not persistently create secure " 601133343a97Smeem "object '%s'", obj_name); 60120ba2cbe9Sxc151355 } 60130ba2cbe9Sxc151355 } 60140ba2cbe9Sxc151355 60150ba2cbe9Sxc151355 static void 60168d5c46e6Sam223141 do_delete_secobj(int argc, char **argv, const char *use) 60170ba2cbe9Sxc151355 { 60180ba2cbe9Sxc151355 int i, option; 60190ba2cbe9Sxc151355 boolean_t temp = B_FALSE; 60200ba2cbe9Sxc151355 boolean_t success; 60210ba2cbe9Sxc151355 dladm_status_t status, pstatus; 6022*8002d411SSowmini Varadhan int nfields = 1; 6023*8002d411SSowmini Varadhan char *field, *token, *lasts = NULL, c; 60240ba2cbe9Sxc151355 60250ba2cbe9Sxc151355 opterr = 0; 60260ba2cbe9Sxc151355 status = pstatus = DLADM_STATUS_OK; 602733343a97Smeem while ((option = getopt_long(argc, argv, ":R:t", 60280ba2cbe9Sxc151355 wifi_longopts, NULL)) != -1) { 60290ba2cbe9Sxc151355 switch (option) { 60300ba2cbe9Sxc151355 case 't': 60310ba2cbe9Sxc151355 temp = B_TRUE; 60320ba2cbe9Sxc151355 break; 60330ba2cbe9Sxc151355 case 'R': 60340ba2cbe9Sxc151355 status = dladm_set_rootdir(optarg); 60350ba2cbe9Sxc151355 if (status != DLADM_STATUS_OK) { 603633343a97Smeem die_dlerr(status, "invalid directory " 603733343a97Smeem "specified"); 60380ba2cbe9Sxc151355 } 60390ba2cbe9Sxc151355 break; 60400ba2cbe9Sxc151355 default: 60418d5c46e6Sam223141 die_opterr(optopt, option, use); 60420ba2cbe9Sxc151355 break; 60430ba2cbe9Sxc151355 } 60440ba2cbe9Sxc151355 } 60450ba2cbe9Sxc151355 60460ba2cbe9Sxc151355 if (optind == (argc - 1)) { 6047*8002d411SSowmini Varadhan token = argv[optind]; 6048*8002d411SSowmini Varadhan if (token == NULL) 6049*8002d411SSowmini Varadhan die("secure object name required"); 6050*8002d411SSowmini Varadhan while ((c = *token++) != NULL) { 6051*8002d411SSowmini Varadhan if (c == ',') 6052*8002d411SSowmini Varadhan nfields++; 60530ba2cbe9Sxc151355 } 6054*8002d411SSowmini Varadhan token = strdup(argv[optind]); 6055*8002d411SSowmini Varadhan if (token == NULL) 6056*8002d411SSowmini Varadhan die("no memory"); 60570ba2cbe9Sxc151355 } else if (optind != argc) 60580ba2cbe9Sxc151355 usage(); 60590ba2cbe9Sxc151355 60600ba2cbe9Sxc151355 success = check_auth(LINK_SEC_AUTH); 6061a399b765Szf162725 audit_secobj(LINK_SEC_AUTH, "unknown", argv[optind], success, B_FALSE); 606233343a97Smeem if (!success) 606333343a97Smeem die("authorization '%s' is required", LINK_SEC_AUTH); 60640ba2cbe9Sxc151355 6065*8002d411SSowmini Varadhan for (i = 0; i < nfields; i++) { 6066*8002d411SSowmini Varadhan 6067*8002d411SSowmini Varadhan field = strtok_r(token, ",", &lasts); 6068*8002d411SSowmini Varadhan token = NULL; 6069*8002d411SSowmini Varadhan status = dladm_unset_secobj(handle, field, DLADM_OPT_ACTIVE); 60700ba2cbe9Sxc151355 if (!temp) { 6071*8002d411SSowmini Varadhan pstatus = dladm_unset_secobj(handle, field, 60720ba2cbe9Sxc151355 DLADM_OPT_PERSIST); 60730ba2cbe9Sxc151355 } else { 60740ba2cbe9Sxc151355 pstatus = DLADM_STATUS_OK; 60750ba2cbe9Sxc151355 } 60760ba2cbe9Sxc151355 60770ba2cbe9Sxc151355 if (status != DLADM_STATUS_OK) { 607833343a97Smeem warn_dlerr(status, "could not delete secure object " 6079*8002d411SSowmini Varadhan "'%s'", field); 60800ba2cbe9Sxc151355 } 60810ba2cbe9Sxc151355 if (pstatus != DLADM_STATUS_OK) { 608233343a97Smeem warn_dlerr(pstatus, "could not persistently delete " 6083*8002d411SSowmini Varadhan "secure object '%s'", field); 60840ba2cbe9Sxc151355 } 60850ba2cbe9Sxc151355 } 6086*8002d411SSowmini Varadhan free(token); 60874ac67f02SAnurag S. Maskey 60884ac67f02SAnurag S. Maskey if (status != DLADM_STATUS_OK || pstatus != DLADM_STATUS_OK) { 60894ac67f02SAnurag S. Maskey dladm_close(handle); 60900ba2cbe9Sxc151355 exit(1); 60910ba2cbe9Sxc151355 } 60924ac67f02SAnurag S. Maskey } 60930ba2cbe9Sxc151355 60940ba2cbe9Sxc151355 typedef struct show_secobj_state { 60950ba2cbe9Sxc151355 boolean_t ss_persist; 6096*8002d411SSowmini Varadhan boolean_t ss_parsable; 60970ba2cbe9Sxc151355 boolean_t ss_header; 6098*8002d411SSowmini Varadhan ofmt_handle_t ss_ofmt; 60990ba2cbe9Sxc151355 } show_secobj_state_t; 61000ba2cbe9Sxc151355 61010ba2cbe9Sxc151355 61020ba2cbe9Sxc151355 static boolean_t 61034ac67f02SAnurag S. Maskey show_secobj(dladm_handle_t dh, void *arg, const char *obj_name) 61040ba2cbe9Sxc151355 { 61050ba2cbe9Sxc151355 uint_t obj_len = DLADM_SECOBJ_VAL_MAX; 61060ba2cbe9Sxc151355 uint8_t obj_val[DLADM_SECOBJ_VAL_MAX]; 61070ba2cbe9Sxc151355 char buf[DLADM_STRSIZE]; 61080ba2cbe9Sxc151355 uint_t flags = 0; 61090ba2cbe9Sxc151355 dladm_secobj_class_t class; 61100ba2cbe9Sxc151355 show_secobj_state_t *statep = arg; 61110ba2cbe9Sxc151355 dladm_status_t status; 6112e7801d59Ssowmini secobj_fields_buf_t sbuf; 61130ba2cbe9Sxc151355 61145f5c9f54SAnurag S. Maskey bzero(&sbuf, sizeof (secobj_fields_buf_t)); 61150ba2cbe9Sxc151355 if (statep->ss_persist) 61160ba2cbe9Sxc151355 flags |= DLADM_OPT_PERSIST; 61170ba2cbe9Sxc151355 61184ac67f02SAnurag S. Maskey status = dladm_get_secobj(dh, obj_name, &class, obj_val, &obj_len, 61194ac67f02SAnurag S. Maskey flags); 612033343a97Smeem if (status != DLADM_STATUS_OK) 612133343a97Smeem die_dlerr(status, "cannot get secure object '%s'", obj_name); 61220ba2cbe9Sxc151355 6123e7801d59Ssowmini (void) snprintf(sbuf.ss_obj_name, sizeof (sbuf.ss_obj_name), 6124e7801d59Ssowmini obj_name); 6125e7801d59Ssowmini (void) dladm_secobjclass2str(class, buf); 6126e7801d59Ssowmini (void) snprintf(sbuf.ss_class, sizeof (sbuf.ss_class), "%s", buf); 6127e7801d59Ssowmini if (getuid() == 0) { 61280ba2cbe9Sxc151355 char val[DLADM_SECOBJ_VAL_MAX * 2]; 61290ba2cbe9Sxc151355 uint_t len = sizeof (val); 61300ba2cbe9Sxc151355 6131e7801d59Ssowmini if (octet_to_hexascii(obj_val, obj_len, val, &len) == 0) 6132e7801d59Ssowmini (void) snprintf(sbuf.ss_val, 6133e7801d59Ssowmini sizeof (sbuf.ss_val), "%s", val); 61340ba2cbe9Sxc151355 } 6135*8002d411SSowmini Varadhan ofmt_print(statep->ss_ofmt, &sbuf); 61360ba2cbe9Sxc151355 return (B_TRUE); 61370ba2cbe9Sxc151355 } 61380ba2cbe9Sxc151355 61390ba2cbe9Sxc151355 static void 61408d5c46e6Sam223141 do_show_secobj(int argc, char **argv, const char *use) 61410ba2cbe9Sxc151355 { 61420ba2cbe9Sxc151355 int option; 61430ba2cbe9Sxc151355 show_secobj_state_t state; 61440ba2cbe9Sxc151355 dladm_status_t status; 61450d365605Sschuster boolean_t o_arg = B_FALSE; 61460ba2cbe9Sxc151355 uint_t i; 61470ba2cbe9Sxc151355 uint_t flags; 6148e7801d59Ssowmini char *fields_str = NULL; 6149e7801d59Ssowmini char *def_fields = "object,class"; 6150e7801d59Ssowmini char *all_fields = "object,class,value"; 6151*8002d411SSowmini Varadhan char *field, *token, *lasts = NULL, c; 6152*8002d411SSowmini Varadhan ofmt_handle_t ofmt; 6153*8002d411SSowmini Varadhan ofmt_status_t oferr; 6154*8002d411SSowmini Varadhan uint_t ofmtflags = 0; 61550ba2cbe9Sxc151355 61560ba2cbe9Sxc151355 opterr = 0; 6157e7801d59Ssowmini bzero(&state, sizeof (state)); 6158*8002d411SSowmini Varadhan state.ss_parsable = B_FALSE; 6159e7801d59Ssowmini fields_str = def_fields; 61600ba2cbe9Sxc151355 state.ss_persist = B_FALSE; 6161*8002d411SSowmini Varadhan state.ss_parsable = B_FALSE; 61620ba2cbe9Sxc151355 state.ss_header = B_TRUE; 6163e7801d59Ssowmini while ((option = getopt_long(argc, argv, ":pPo:", 61640ba2cbe9Sxc151355 wifi_longopts, NULL)) != -1) { 61650ba2cbe9Sxc151355 switch (option) { 61660ba2cbe9Sxc151355 case 'p': 6167*8002d411SSowmini Varadhan state.ss_parsable = B_TRUE; 61680ba2cbe9Sxc151355 break; 61690ba2cbe9Sxc151355 case 'P': 61700ba2cbe9Sxc151355 state.ss_persist = B_TRUE; 61710ba2cbe9Sxc151355 break; 6172e7801d59Ssowmini case 'o': 61730d365605Sschuster o_arg = B_TRUE; 6174e7801d59Ssowmini if (strcasecmp(optarg, "all") == 0) 6175e7801d59Ssowmini fields_str = all_fields; 6176e7801d59Ssowmini else 6177e7801d59Ssowmini fields_str = optarg; 61780ba2cbe9Sxc151355 break; 61790ba2cbe9Sxc151355 default: 61808d5c46e6Sam223141 die_opterr(optopt, option, use); 61810ba2cbe9Sxc151355 break; 61820ba2cbe9Sxc151355 } 61830ba2cbe9Sxc151355 } 61840ba2cbe9Sxc151355 6185*8002d411SSowmini Varadhan if (state.ss_parsable && !o_arg) 61860d365605Sschuster die("option -c requires -o"); 61870d365605Sschuster 6188*8002d411SSowmini Varadhan if (state.ss_parsable && fields_str == all_fields) 61890d365605Sschuster die("\"-o all\" is invalid with -p"); 61900d365605Sschuster 6191*8002d411SSowmini Varadhan if (state.ss_parsable) 6192*8002d411SSowmini Varadhan ofmtflags |= OFMT_PARSABLE; 6193*8002d411SSowmini Varadhan oferr = ofmt_open(fields_str, secobj_fields, ofmtflags, 0, &ofmt); 6194*8002d411SSowmini Varadhan dladm_ofmt_check(oferr, state.ss_parsable, ofmt); 6195*8002d411SSowmini Varadhan state.ss_ofmt = ofmt; 6196e7801d59Ssowmini 6197e7801d59Ssowmini flags = state.ss_persist ? DLADM_OPT_PERSIST : 0; 61984ac67f02SAnurag S. Maskey 61990ba2cbe9Sxc151355 if (optind == (argc - 1)) { 6200*8002d411SSowmini Varadhan uint_t obj_fields = 1; 6201*8002d411SSowmini Varadhan 6202*8002d411SSowmini Varadhan token = argv[optind]; 6203*8002d411SSowmini Varadhan if (token == NULL) 6204*8002d411SSowmini Varadhan die("secure object name required"); 6205*8002d411SSowmini Varadhan while ((c = *token++) != NULL) { 6206*8002d411SSowmini Varadhan if (c == ',') 6207*8002d411SSowmini Varadhan obj_fields++; 62080ba2cbe9Sxc151355 } 6209*8002d411SSowmini Varadhan token = strdup(argv[optind]); 6210*8002d411SSowmini Varadhan if (token == NULL) 6211*8002d411SSowmini Varadhan die("no memory"); 6212*8002d411SSowmini Varadhan for (i = 0; i < obj_fields; i++) { 6213*8002d411SSowmini Varadhan field = strtok_r(token, ",", &lasts); 6214*8002d411SSowmini Varadhan token = NULL; 6215*8002d411SSowmini Varadhan if (!show_secobj(handle, &state, field)) 62160ba2cbe9Sxc151355 break; 62170ba2cbe9Sxc151355 } 6218*8002d411SSowmini Varadhan free(token); 6219*8002d411SSowmini Varadhan ofmt_close(ofmt); 62200ba2cbe9Sxc151355 return; 62210ba2cbe9Sxc151355 } else if (optind != argc) 62220ba2cbe9Sxc151355 usage(); 62230ba2cbe9Sxc151355 62244ac67f02SAnurag S. Maskey status = dladm_walk_secobj(handle, &state, show_secobj, flags); 62254ac67f02SAnurag S. Maskey 622633343a97Smeem if (status != DLADM_STATUS_OK) 622733343a97Smeem die_dlerr(status, "show-secobj"); 6228*8002d411SSowmini Varadhan ofmt_close(ofmt); 62290ba2cbe9Sxc151355 } 62300ba2cbe9Sxc151355 62310ba2cbe9Sxc151355 /*ARGSUSED*/ 6232d62bc4baSyz147064 static int 62334ac67f02SAnurag S. Maskey i_dladm_init_linkprop(dladm_handle_t dh, datalink_id_t linkid, void *arg) 6234d62bc4baSyz147064 { 62354ac67f02SAnurag S. Maskey (void) dladm_init_linkprop(dh, linkid, B_TRUE); 6236d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 6237d62bc4baSyz147064 } 6238d62bc4baSyz147064 62398d5c46e6Sam223141 /*ARGSUSED*/ 6240da14cebeSEric Cheng void 62418d5c46e6Sam223141 do_init_linkprop(int argc, char **argv, const char *use) 62420ba2cbe9Sxc151355 { 624330890389Sartem int option; 624430890389Sartem dladm_status_t status; 624530890389Sartem datalink_id_t linkid = DATALINK_ALL_LINKID; 624630890389Sartem datalink_media_t media = DATALINK_ANY_MEDIATYPE; 624730890389Sartem uint_t any_media = B_TRUE; 624830890389Sartem 624930890389Sartem opterr = 0; 625030890389Sartem while ((option = getopt(argc, argv, ":w")) != -1) { 625130890389Sartem switch (option) { 625230890389Sartem case 'w': 625330890389Sartem media = DL_WIFI; 625430890389Sartem any_media = B_FALSE; 625530890389Sartem break; 625630890389Sartem default: 62578d5c46e6Sam223141 /* 62588d5c46e6Sam223141 * Because init-linkprop is not a public command, 62598d5c46e6Sam223141 * print the usage instead. 62608d5c46e6Sam223141 */ 62618d5c46e6Sam223141 usage(); 626230890389Sartem break; 626330890389Sartem } 626430890389Sartem } 626530890389Sartem 626630890389Sartem if (optind == (argc - 1)) { 62674ac67f02SAnurag S. Maskey if ((status = dladm_name2info(handle, argv[optind], &linkid, 62684ac67f02SAnurag S. Maskey NULL, NULL, NULL)) != DLADM_STATUS_OK) 626930890389Sartem die_dlerr(status, "link %s is not valid", argv[optind]); 627030890389Sartem } else if (optind != argc) { 627130890389Sartem usage(); 627230890389Sartem } 627330890389Sartem 627430890389Sartem if (linkid == DATALINK_ALL_LINKID) { 6275d62bc4baSyz147064 /* 627630890389Sartem * linkprops of links of other classes have been initialized as 6277d62bc4baSyz147064 * part of the dladm up-xxx operation. 6278d62bc4baSyz147064 */ 62794ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(i_dladm_init_linkprop, handle, 62804ac67f02SAnurag S. Maskey NULL, DATALINK_CLASS_PHYS, media, DLADM_OPT_PERSIST); 628130890389Sartem } else { 62824ac67f02SAnurag S. Maskey (void) dladm_init_linkprop(handle, linkid, any_media); 628330890389Sartem } 62840ba2cbe9Sxc151355 } 62850ba2cbe9Sxc151355 62860ba2cbe9Sxc151355 static void 62878d5c46e6Sam223141 do_show_ether(int argc, char **argv, const char *use) 6288e7801d59Ssowmini { 6289e7801d59Ssowmini int option; 6290e7801d59Ssowmini datalink_id_t linkid; 6291e7801d59Ssowmini print_ether_state_t state; 6292*8002d411SSowmini Varadhan char *fields_str = NULL; 6293*8002d411SSowmini Varadhan ofmt_handle_t ofmt; 6294*8002d411SSowmini Varadhan ofmt_status_t oferr; 6295*8002d411SSowmini Varadhan uint_t ofmtflags = 0; 6296e7801d59Ssowmini 6297e7801d59Ssowmini bzero(&state, sizeof (state)); 6298e7801d59Ssowmini state.es_link = NULL; 6299*8002d411SSowmini Varadhan state.es_parsable = B_FALSE; 6300e7801d59Ssowmini 6301e7801d59Ssowmini while ((option = getopt_long(argc, argv, "o:px", 6302e7801d59Ssowmini showeth_lopts, NULL)) != -1) { 6303e7801d59Ssowmini switch (option) { 6304e7801d59Ssowmini case 'x': 6305e7801d59Ssowmini state.es_extended = B_TRUE; 6306e7801d59Ssowmini break; 6307e7801d59Ssowmini case 'p': 6308*8002d411SSowmini Varadhan state.es_parsable = B_TRUE; 6309e7801d59Ssowmini break; 6310e7801d59Ssowmini case 'o': 6311e7801d59Ssowmini fields_str = optarg; 6312e7801d59Ssowmini break; 6313e7801d59Ssowmini default: 63148d5c46e6Sam223141 die_opterr(optopt, option, use); 6315e7801d59Ssowmini break; 6316e7801d59Ssowmini } 6317e7801d59Ssowmini } 6318e7801d59Ssowmini 6319e7801d59Ssowmini if (optind == (argc - 1)) 6320e7801d59Ssowmini state.es_link = argv[optind]; 6321e7801d59Ssowmini 6322*8002d411SSowmini Varadhan if (state.es_parsable) 6323*8002d411SSowmini Varadhan ofmtflags |= OFMT_PARSABLE; 6324*8002d411SSowmini Varadhan oferr = ofmt_open(fields_str, ether_fields, ofmtflags, 6325*8002d411SSowmini Varadhan DLADM_DEFAULT_COL, &ofmt); 6326*8002d411SSowmini Varadhan dladm_ofmt_check(oferr, state.es_parsable, ofmt); 6327*8002d411SSowmini Varadhan state.es_ofmt = ofmt; 63284ac67f02SAnurag S. Maskey 6329e7801d59Ssowmini if (state.es_link == NULL) { 63304ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(show_etherprop, handle, &state, 6331e7801d59Ssowmini DATALINK_CLASS_PHYS, DL_ETHER, 6332e7801d59Ssowmini DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST); 6333e7801d59Ssowmini } else { 63344ac67f02SAnurag S. Maskey if (!link_is_ether(state.es_link, &linkid)) 6335e7801d59Ssowmini die("invalid link specified"); 63364ac67f02SAnurag S. Maskey (void) show_etherprop(handle, linkid, &state); 6337e7801d59Ssowmini } 6338*8002d411SSowmini Varadhan ofmt_close(ofmt); 6339e7801d59Ssowmini } 6340e7801d59Ssowmini 6341e7801d59Ssowmini static int 63424ac67f02SAnurag S. Maskey show_etherprop(dladm_handle_t dh, datalink_id_t linkid, void *arg) 6343e7801d59Ssowmini { 6344e7801d59Ssowmini print_ether_state_t *statep = arg; 6345e7801d59Ssowmini ether_fields_buf_t ebuf; 63464784fcbdSSowmini Varadhan dladm_ether_info_t eattr; 63474784fcbdSSowmini Varadhan dladm_status_t status; 6348e7801d59Ssowmini 63495f5c9f54SAnurag S. Maskey bzero(&ebuf, sizeof (ether_fields_buf_t)); 63504ac67f02SAnurag S. Maskey if (dladm_datalink_id2info(dh, linkid, NULL, NULL, NULL, 6351e7801d59Ssowmini ebuf.eth_link, sizeof (ebuf.eth_link)) != DLADM_STATUS_OK) { 6352e7801d59Ssowmini return (DLADM_WALK_CONTINUE); 6353e7801d59Ssowmini } 6354e7801d59Ssowmini 63554ac67f02SAnurag S. Maskey status = dladm_ether_info(dh, linkid, &eattr); 63564784fcbdSSowmini Varadhan if (status != DLADM_STATUS_OK) 63574784fcbdSSowmini Varadhan goto cleanup; 6358e7801d59Ssowmini 63594784fcbdSSowmini Varadhan (void) strlcpy(ebuf.eth_ptype, "current", sizeof (ebuf.eth_ptype)); 6360e7801d59Ssowmini 63614784fcbdSSowmini Varadhan (void) dladm_ether_autoneg2str(ebuf.eth_autoneg, 63624784fcbdSSowmini Varadhan sizeof (ebuf.eth_autoneg), &eattr, CURRENT); 63634784fcbdSSowmini Varadhan (void) dladm_ether_pause2str(ebuf.eth_pause, 63644784fcbdSSowmini Varadhan sizeof (ebuf.eth_pause), &eattr, CURRENT); 63654784fcbdSSowmini Varadhan (void) dladm_ether_spdx2str(ebuf.eth_spdx, 63664784fcbdSSowmini Varadhan sizeof (ebuf.eth_spdx), &eattr, CURRENT); 63674784fcbdSSowmini Varadhan (void) strlcpy(ebuf.eth_state, 63684784fcbdSSowmini Varadhan dladm_linkstate2str(eattr.lei_state, ebuf.eth_state), 63694784fcbdSSowmini Varadhan sizeof (ebuf.eth_state)); 63704784fcbdSSowmini Varadhan (void) strlcpy(ebuf.eth_rem_fault, 63714784fcbdSSowmini Varadhan (eattr.lei_attr[CURRENT].le_fault ? "fault" : "none"), 63724784fcbdSSowmini Varadhan sizeof (ebuf.eth_rem_fault)); 6373e7801d59Ssowmini 6374*8002d411SSowmini Varadhan ofmt_print(statep->es_ofmt, &ebuf); 6375e7801d59Ssowmini 6376e7801d59Ssowmini if (statep->es_extended) 63774784fcbdSSowmini Varadhan show_ether_xprop(arg, &eattr); 6378e7801d59Ssowmini 63794784fcbdSSowmini Varadhan cleanup: 63804784fcbdSSowmini Varadhan dladm_ether_info_done(&eattr); 6381e7801d59Ssowmini return (DLADM_WALK_CONTINUE); 6382e7801d59Ssowmini } 6383e7801d59Ssowmini 6384e7801d59Ssowmini /* ARGSUSED */ 6385e7801d59Ssowmini static void 63868d5c46e6Sam223141 do_init_secobj(int argc, char **argv, const char *use) 63870ba2cbe9Sxc151355 { 63880ba2cbe9Sxc151355 dladm_status_t status; 63890ba2cbe9Sxc151355 63904ac67f02SAnurag S. Maskey status = dladm_init_secobj(handle); 639133343a97Smeem if (status != DLADM_STATUS_OK) 639233343a97Smeem die_dlerr(status, "secure object initialization failed"); 639333343a97Smeem } 639433343a97Smeem 6395d62bc4baSyz147064 /* 6396d62bc4baSyz147064 * "-R" option support. It is used for live upgrading. Append dladm commands 6397d62bc4baSyz147064 * to a upgrade script which will be run when the alternative root boots up: 6398d62bc4baSyz147064 * 6399b9e076dcSyz147064 * - If the /etc/dladm/datalink.conf file exists on the alternative root, 6400b9e076dcSyz147064 * append dladm commands to the <altroot>/var/svc/profile/upgrade_datalink 6401b9e076dcSyz147064 * script. This script will be run as part of the network/physical service. 6402b9e076dcSyz147064 * We cannot defer this to /var/svc/profile/upgrade because then the 6403b9e076dcSyz147064 * configuration will not be able to take effect before network/physical 6404b9e076dcSyz147064 * plumbs various interfaces. 6405d62bc4baSyz147064 * 6406b9e076dcSyz147064 * - If the /etc/dladm/datalink.conf file does not exist on the alternative 6407b9e076dcSyz147064 * root, append dladm commands to the <altroot>/var/svc/profile/upgrade script, 6408b9e076dcSyz147064 * which will be run in the manifest-import service. 6409d62bc4baSyz147064 * 6410d62bc4baSyz147064 * Note that the SMF team is considering to move the manifest-import service 6411d62bc4baSyz147064 * to be run at the very begining of boot. Once that is done, the need for 6412d62bc4baSyz147064 * the /var/svc/profile/upgrade_datalink script will not exist any more. 6413d62bc4baSyz147064 */ 6414d62bc4baSyz147064 static void 6415d62bc4baSyz147064 altroot_cmd(char *altroot, int argc, char *argv[]) 6416d62bc4baSyz147064 { 6417d62bc4baSyz147064 char path[MAXPATHLEN]; 6418d62bc4baSyz147064 struct stat stbuf; 6419d62bc4baSyz147064 FILE *fp; 6420d62bc4baSyz147064 int i; 6421d62bc4baSyz147064 6422d62bc4baSyz147064 /* 6423b9e076dcSyz147064 * Check for the existence of the /etc/dladm/datalink.conf 6424b9e076dcSyz147064 * configuration file, and determine the name of script file. 6425d62bc4baSyz147064 */ 6426b9e076dcSyz147064 (void) snprintf(path, MAXPATHLEN, "/%s/etc/dladm/datalink.conf", 6427b9e076dcSyz147064 altroot); 6428d62bc4baSyz147064 if (stat(path, &stbuf) < 0) { 6429d62bc4baSyz147064 (void) snprintf(path, MAXPATHLEN, "/%s/%s", altroot, 6430d62bc4baSyz147064 SMF_UPGRADE_FILE); 6431d62bc4baSyz147064 } else { 6432d62bc4baSyz147064 (void) snprintf(path, MAXPATHLEN, "/%s/%s", altroot, 6433d62bc4baSyz147064 SMF_UPGRADEDATALINK_FILE); 6434d62bc4baSyz147064 } 6435d62bc4baSyz147064 6436d62bc4baSyz147064 if ((fp = fopen(path, "a+")) == NULL) 6437d62bc4baSyz147064 die("operation not supported on %s", altroot); 6438d62bc4baSyz147064 6439d62bc4baSyz147064 (void) fprintf(fp, "/sbin/dladm "); 6440d62bc4baSyz147064 for (i = 0; i < argc; i++) { 6441d62bc4baSyz147064 /* 6442d62bc4baSyz147064 * Directly write to the file if it is not the "-R <altroot>" 6443d62bc4baSyz147064 * option. In which case, skip it. 6444d62bc4baSyz147064 */ 6445d62bc4baSyz147064 if (strcmp(argv[i], "-R") != 0) 6446d62bc4baSyz147064 (void) fprintf(fp, "%s ", argv[i]); 6447d62bc4baSyz147064 else 6448d62bc4baSyz147064 i ++; 6449d62bc4baSyz147064 } 6450d62bc4baSyz147064 (void) fprintf(fp, "%s\n", SMF_DLADM_UPGRADE_MSG); 6451d62bc4baSyz147064 (void) fclose(fp); 64524ac67f02SAnurag S. Maskey dladm_close(handle); 6453d62bc4baSyz147064 exit(0); 6454d62bc4baSyz147064 } 6455d62bc4baSyz147064 6456d62bc4baSyz147064 /* 6457d62bc4baSyz147064 * Convert the string to an integer. Note that the string must not have any 6458d62bc4baSyz147064 * trailing non-integer characters. 6459d62bc4baSyz147064 */ 646033343a97Smeem static boolean_t 646133343a97Smeem str2int(const char *str, int *valp) 646233343a97Smeem { 646333343a97Smeem int val; 646433343a97Smeem char *endp = NULL; 646533343a97Smeem 646633343a97Smeem errno = 0; 646733343a97Smeem val = strtol(str, &endp, 10); 646833343a97Smeem if (errno != 0 || *endp != '\0') 646933343a97Smeem return (B_FALSE); 647033343a97Smeem 647133343a97Smeem *valp = val; 647233343a97Smeem return (B_TRUE); 647333343a97Smeem } 647433343a97Smeem 647533343a97Smeem /* PRINTFLIKE1 */ 647633343a97Smeem static void 647733343a97Smeem warn(const char *format, ...) 647833343a97Smeem { 647933343a97Smeem va_list alist; 648033343a97Smeem 648133343a97Smeem format = gettext(format); 648233343a97Smeem (void) fprintf(stderr, "%s: warning: ", progname); 648333343a97Smeem 648433343a97Smeem va_start(alist, format); 648533343a97Smeem (void) vfprintf(stderr, format, alist); 648633343a97Smeem va_end(alist); 648733343a97Smeem 648833343a97Smeem (void) putchar('\n'); 648933343a97Smeem } 649033343a97Smeem 649133343a97Smeem /* PRINTFLIKE2 */ 649233343a97Smeem static void 649333343a97Smeem warn_dlerr(dladm_status_t err, const char *format, ...) 649433343a97Smeem { 649533343a97Smeem va_list alist; 649633343a97Smeem char errmsg[DLADM_STRSIZE]; 649733343a97Smeem 649833343a97Smeem format = gettext(format); 649933343a97Smeem (void) fprintf(stderr, gettext("%s: warning: "), progname); 650033343a97Smeem 650133343a97Smeem va_start(alist, format); 650233343a97Smeem (void) vfprintf(stderr, format, alist); 650333343a97Smeem va_end(alist); 650433343a97Smeem (void) fprintf(stderr, ": %s\n", dladm_status2str(err, errmsg)); 650533343a97Smeem } 650633343a97Smeem 65074ac67f02SAnurag S. Maskey /* 65084ac67f02SAnurag S. Maskey * Also closes the dladm handle if it is not NULL. 65094ac67f02SAnurag S. Maskey */ 651033343a97Smeem /* PRINTFLIKE2 */ 651133343a97Smeem static void 651233343a97Smeem die_dlerr(dladm_status_t err, const char *format, ...) 651333343a97Smeem { 651433343a97Smeem va_list alist; 651533343a97Smeem char errmsg[DLADM_STRSIZE]; 651633343a97Smeem 651733343a97Smeem format = gettext(format); 651833343a97Smeem (void) fprintf(stderr, "%s: ", progname); 651933343a97Smeem 652033343a97Smeem va_start(alist, format); 652133343a97Smeem (void) vfprintf(stderr, format, alist); 652233343a97Smeem va_end(alist); 652333343a97Smeem (void) fprintf(stderr, ": %s\n", dladm_status2str(err, errmsg)); 652433343a97Smeem 65254ac67f02SAnurag S. Maskey /* close dladm handle if it was opened */ 65264ac67f02SAnurag S. Maskey if (handle != NULL) 65274ac67f02SAnurag S. Maskey dladm_close(handle); 65284ac67f02SAnurag S. Maskey 652933343a97Smeem exit(EXIT_FAILURE); 653033343a97Smeem } 653133343a97Smeem 653233343a97Smeem /* PRINTFLIKE1 */ 653333343a97Smeem static void 653433343a97Smeem die(const char *format, ...) 653533343a97Smeem { 653633343a97Smeem va_list alist; 653733343a97Smeem 653833343a97Smeem format = gettext(format); 653933343a97Smeem (void) fprintf(stderr, "%s: ", progname); 654033343a97Smeem 654133343a97Smeem va_start(alist, format); 654233343a97Smeem (void) vfprintf(stderr, format, alist); 654333343a97Smeem va_end(alist); 654433343a97Smeem 654533343a97Smeem (void) putchar('\n'); 65464ac67f02SAnurag S. Maskey 65474ac67f02SAnurag S. Maskey /* close dladm handle if it was opened */ 65484ac67f02SAnurag S. Maskey if (handle != NULL) 65494ac67f02SAnurag S. Maskey dladm_close(handle); 65504ac67f02SAnurag S. Maskey 655133343a97Smeem exit(EXIT_FAILURE); 655233343a97Smeem } 655333343a97Smeem 655433343a97Smeem static void 655533343a97Smeem die_optdup(int opt) 655633343a97Smeem { 655733343a97Smeem die("the option -%c cannot be specified more than once", opt); 655833343a97Smeem } 655933343a97Smeem 656033343a97Smeem static void 65618d5c46e6Sam223141 die_opterr(int opt, int opterr, const char *usage) 656233343a97Smeem { 656333343a97Smeem switch (opterr) { 656433343a97Smeem case ':': 65658d5c46e6Sam223141 die("option '-%c' requires a value\nusage: %s", opt, 65668d5c46e6Sam223141 gettext(usage)); 656733343a97Smeem break; 656833343a97Smeem case '?': 656933343a97Smeem default: 65708d5c46e6Sam223141 die("unrecognized option '-%c'\nusage: %s", opt, 65718d5c46e6Sam223141 gettext(usage)); 657233343a97Smeem break; 65730ba2cbe9Sxc151355 } 65740ba2cbe9Sxc151355 } 6575e7801d59Ssowmini 6576e7801d59Ssowmini static void 65774784fcbdSSowmini Varadhan show_ether_xprop(void *arg, dladm_ether_info_t *eattr) 6578e7801d59Ssowmini { 6579e7801d59Ssowmini print_ether_state_t *statep = arg; 6580e7801d59Ssowmini ether_fields_buf_t ebuf; 65814784fcbdSSowmini Varadhan int i; 6582e7801d59Ssowmini 65834784fcbdSSowmini Varadhan for (i = CAPABLE; i <= PEERADV; i++) { 6584e7801d59Ssowmini bzero(&ebuf, sizeof (ebuf)); 65854784fcbdSSowmini Varadhan (void) strlcpy(ebuf.eth_ptype, ptype[i], 65864784fcbdSSowmini Varadhan sizeof (ebuf.eth_ptype)); 65874784fcbdSSowmini Varadhan (void) dladm_ether_autoneg2str(ebuf.eth_autoneg, 65884784fcbdSSowmini Varadhan sizeof (ebuf.eth_autoneg), eattr, i); 65894784fcbdSSowmini Varadhan (void) dladm_ether_spdx2str(ebuf.eth_spdx, 65904784fcbdSSowmini Varadhan sizeof (ebuf.eth_spdx), eattr, i); 65914784fcbdSSowmini Varadhan (void) dladm_ether_pause2str(ebuf.eth_pause, 65924784fcbdSSowmini Varadhan sizeof (ebuf.eth_pause), eattr, i); 65934784fcbdSSowmini Varadhan (void) strlcpy(ebuf.eth_rem_fault, 65944784fcbdSSowmini Varadhan (eattr->lei_attr[i].le_fault ? "fault" : "none"), 65954784fcbdSSowmini Varadhan sizeof (ebuf.eth_rem_fault)); 6596*8002d411SSowmini Varadhan ofmt_print(statep->es_ofmt, &ebuf); 6597e7801d59Ssowmini } 6598e7801d59Ssowmini 6599e7801d59Ssowmini } 6600e7801d59Ssowmini 6601e7801d59Ssowmini static boolean_t 6602e7801d59Ssowmini link_is_ether(const char *link, datalink_id_t *linkid) 6603e7801d59Ssowmini { 6604e7801d59Ssowmini uint32_t media; 6605e7801d59Ssowmini datalink_class_t class; 6606e7801d59Ssowmini 66074ac67f02SAnurag S. Maskey if (dladm_name2info(handle, link, linkid, NULL, &class, &media) == 6608e7801d59Ssowmini DLADM_STATUS_OK) { 6609e7801d59Ssowmini if (class == DATALINK_CLASS_PHYS && media == DL_ETHER) 6610e7801d59Ssowmini return (B_TRUE); 6611e7801d59Ssowmini } 6612e7801d59Ssowmini return (B_FALSE); 6613e7801d59Ssowmini } 6614*8002d411SSowmini Varadhan 6615*8002d411SSowmini Varadhan /* 6616*8002d411SSowmini Varadhan * default output callback function that, when invoked, 6617*8002d411SSowmini Varadhan * prints string which is offset by ofmt_arg->ofmt_id within buf. 6618*8002d411SSowmini Varadhan */ 6619*8002d411SSowmini Varadhan static boolean_t 6620*8002d411SSowmini Varadhan print_default_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize) 6621*8002d411SSowmini Varadhan { 6622*8002d411SSowmini Varadhan char *value; 6623*8002d411SSowmini Varadhan 6624*8002d411SSowmini Varadhan value = (char *)ofarg->ofmt_cbarg + ofarg->ofmt_id; 6625*8002d411SSowmini Varadhan (void) strlcpy(buf, value, bufsize); 6626*8002d411SSowmini Varadhan return (B_TRUE); 6627*8002d411SSowmini Varadhan } 6628*8002d411SSowmini Varadhan 6629*8002d411SSowmini Varadhan static void 6630*8002d411SSowmini Varadhan dladm_ofmt_check(ofmt_status_t oferr, boolean_t parsable, 6631*8002d411SSowmini Varadhan ofmt_handle_t ofmt) 6632*8002d411SSowmini Varadhan { 6633*8002d411SSowmini Varadhan char buf[OFMT_BUFSIZE]; 6634*8002d411SSowmini Varadhan 6635*8002d411SSowmini Varadhan if (oferr == OFMT_SUCCESS) 6636*8002d411SSowmini Varadhan return; 6637*8002d411SSowmini Varadhan (void) ofmt_strerror(ofmt, oferr, buf, sizeof (buf)); 6638*8002d411SSowmini Varadhan /* 6639*8002d411SSowmini Varadhan * All errors are considered fatal in parsable mode. 6640*8002d411SSowmini Varadhan * NOMEM errors are always fatal, regardless of mode. 6641*8002d411SSowmini Varadhan * For other errors, we print diagnostics in human-readable 6642*8002d411SSowmini Varadhan * mode and processs what we can. 6643*8002d411SSowmini Varadhan */ 6644*8002d411SSowmini Varadhan if (parsable || oferr == OFMT_ENOFIELDS) { 6645*8002d411SSowmini Varadhan ofmt_close(ofmt); 6646*8002d411SSowmini Varadhan die(buf); 6647*8002d411SSowmini Varadhan } else { 6648*8002d411SSowmini Varadhan warn(buf); 6649*8002d411SSowmini Varadhan } 6650*8002d411SSowmini Varadhan } 6651