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> 688002d411SSowmini 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)" 778002d411SSowmini Varadhan #define DLADM_DEFAULT_COL 80 787c478bd9Sstevel@tonic-gate 798002d411SSowmini Varadhan /* 808002d411SSowmini Varadhan * used by the wifi show-* commands to set up ofmt_field_t structures. 818002d411SSowmini 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; 928002d411SSowmini Varadhan ofmt_handle_t ls_ofmt; 938002d411SSowmini 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; 1028002d411SSowmini 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; 1088002d411SSowmini 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]; 1168002d411SSowmini 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; 1278002d411SSowmini 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; 1328002d411SSowmini Varadhan boolean_t us_parsable; 133da14cebeSEric Cheng boolean_t us_printheader; 134da14cebeSEric Cheng boolean_t us_first; 135ae6aa22aSVenugopal Iyer boolean_t us_showall; 1368002d411SSowmini Varadhan ofmt_handle_t us_ofmt; 137da14cebeSEric Cheng } show_usage_state_t; 138da14cebeSEric Cheng 1398002d411SSowmini Varadhan /* 1408002d411SSowmini Varadhan * callback functions for printing output and error diagnostics. 1418002d411SSowmini Varadhan */ 1428002d411SSowmini Varadhan static ofmt_cb_t print_default_cb, print_link_stats_cb, print_linkprop_cb; 1438002d411SSowmini Varadhan static ofmt_cb_t print_lacp_cb, print_phys_one_mac_cb; 1448002d411SSowmini Varadhan static ofmt_cb_t print_xaggr_cb, print_aggr_stats_cb; 1458002d411SSowmini Varadhan static ofmt_cb_t print_phys_one_hwgrp_cb, print_wlan_attr_cb; 1468002d411SSowmini Varadhan static ofmt_cb_t print_wifi_status_cb, print_link_attr_cb; 1478002d411SSowmini Varadhan static void dladm_ofmt_check(ofmt_status_t, boolean_t, ofmt_handle_t); 1488002d411SSowmini 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'}, 3138002d411SSowmini 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' }, 3278002d411SSowmini 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[] = { 3348002d411SSowmini 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[] = { 3538002d411SSowmini 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 4028002d411SSowmini Varadhan static ofmt_field_t ether_fields[] = { 4038002d411SSowmini Varadhan /* name, field width, offset callback */ 4048002d411SSowmini Varadhan { "LINK", 16, 4058002d411SSowmini Varadhan offsetof(ether_fields_buf_t, eth_link), print_default_cb}, 4068002d411SSowmini Varadhan { "PTYPE", 9, 4078002d411SSowmini Varadhan offsetof(ether_fields_buf_t, eth_ptype), print_default_cb}, 4088002d411SSowmini Varadhan { "STATE", 9, 4098002d411SSowmini Varadhan offsetof(ether_fields_buf_t, eth_state), 4108002d411SSowmini Varadhan print_default_cb}, 4118002d411SSowmini Varadhan { "AUTO", 6, 4128002d411SSowmini Varadhan offsetof(ether_fields_buf_t, eth_autoneg), print_default_cb}, 4138002d411SSowmini Varadhan { "SPEED-DUPLEX", 32, 4148002d411SSowmini Varadhan offsetof(ether_fields_buf_t, eth_spdx), print_default_cb}, 4158002d411SSowmini Varadhan { "PAUSE", 7, 4168002d411SSowmini Varadhan offsetof(ether_fields_buf_t, eth_pause), print_default_cb}, 4178002d411SSowmini Varadhan { "REM_FAULT", 17, 4188002d411SSowmini Varadhan offsetof(ether_fields_buf_t, eth_rem_fault), print_default_cb}, 4198002d411SSowmini Varadhan {NULL, 0, 4208002d411SSowmini Varadhan 0, NULL}} 421e7801d59Ssowmini ; 422e7801d59Ssowmini 423e7801d59Ssowmini typedef struct print_ether_state { 424e7801d59Ssowmini const char *es_link; 4258002d411SSowmini Varadhan boolean_t es_parsable; 426e7801d59Ssowmini boolean_t es_header; 427e7801d59Ssowmini boolean_t es_extended; 4288002d411SSowmini 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 4448002d411SSowmini Varadhan static ofmt_field_t link_s_fields[] = { 4458002d411SSowmini Varadhan /* name, field width, index, callback */ 4468002d411SSowmini Varadhan { "LINK", 15, LINK_S_LINK, print_link_stats_cb}, 4478002d411SSowmini Varadhan { "IPACKETS", 10, LINK_S_IPKTS, print_link_stats_cb}, 4488002d411SSowmini Varadhan { "RBYTES", 8, LINK_S_RBYTES, print_link_stats_cb}, 4498002d411SSowmini Varadhan { "IERRORS", 10, LINK_S_IERRORS, print_link_stats_cb}, 4508002d411SSowmini Varadhan { "OPACKETS", 12, LINK_S_OPKTS, print_link_stats_cb}, 4518002d411SSowmini Varadhan { "OBYTES", 12, LINK_S_OBYTES, print_link_stats_cb}, 4528002d411SSowmini 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 */ 4818002d411SSowmini Varadhan static ofmt_field_t link_fields[] = { 4828002d411SSowmini Varadhan /* name, field width, index, callback */ 4838002d411SSowmini Varadhan { "LINK", 12, 4848002d411SSowmini Varadhan offsetof(link_fields_buf_t, link_name), print_default_cb}, 4858002d411SSowmini Varadhan { "CLASS", 9, 4868002d411SSowmini Varadhan offsetof(link_fields_buf_t, link_class), print_default_cb}, 4878002d411SSowmini Varadhan { "MTU", 7, 4888002d411SSowmini Varadhan offsetof(link_fields_buf_t, link_mtu), print_default_cb}, 4898002d411SSowmini Varadhan { "STATE", 9, 4908002d411SSowmini Varadhan offsetof(link_fields_buf_t, link_state), print_default_cb}, 4918002d411SSowmini Varadhan { "OVER", DLPI_LINKNAME_MAX, 4928002d411SSowmini Varadhan offsetof(link_fields_buf_t, link_over), print_default_cb}, 4938002d411SSowmini 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 */ 514*2d40c3b2SPrakash Jalan pktsum_t *laggr_diffstats; /* -s only */ 5158002d411SSowmini Varadhan boolean_t laggr_parsable; 516e7801d59Ssowmini } laggr_args_t; 517e7801d59Ssowmini 5188002d411SSowmini Varadhan static ofmt_field_t laggr_fields[] = { 5198002d411SSowmini Varadhan /* name, field width, offset, callback */ 5208002d411SSowmini Varadhan { "LINK", 16, 5218002d411SSowmini Varadhan offsetof(laggr_fields_buf_t, laggr_name), print_default_cb}, 5228002d411SSowmini Varadhan { "POLICY", 9, 5238002d411SSowmini Varadhan offsetof(laggr_fields_buf_t, laggr_policy), print_default_cb}, 5248002d411SSowmini Varadhan { "ADDRPOLICY", ETHERADDRL * 3 + 3, 5258002d411SSowmini Varadhan offsetof(laggr_fields_buf_t, laggr_addrpolicy), print_default_cb}, 5268002d411SSowmini Varadhan { "LACPACTIVITY", 14, 5278002d411SSowmini Varadhan offsetof(laggr_fields_buf_t, laggr_lacpactivity), print_default_cb}, 5288002d411SSowmini Varadhan { "LACPTIMER", 12, 5298002d411SSowmini Varadhan offsetof(laggr_fields_buf_t, laggr_lacptimer), print_default_cb}, 5308002d411SSowmini Varadhan { "FLAGS", 8, 5318002d411SSowmini Varadhan offsetof(laggr_fields_buf_t, laggr_flags), print_default_cb}, 5328002d411SSowmini 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 5488002d411SSowmini Varadhan static ofmt_field_t aggr_x_fields[] = { 5498002d411SSowmini Varadhan /* name, field width, index callback */ 5508002d411SSowmini Varadhan { "LINK", 12, AGGR_X_LINK, print_xaggr_cb}, 5518002d411SSowmini Varadhan { "PORT", 15, AGGR_X_PORT, print_xaggr_cb}, 5528002d411SSowmini Varadhan { "SPEED", 5, AGGR_X_SPEED, print_xaggr_cb}, 5538002d411SSowmini Varadhan { "DUPLEX", 10, AGGR_X_DUPLEX, print_xaggr_cb}, 5548002d411SSowmini Varadhan { "STATE", 10, AGGR_X_STATE, print_xaggr_cb}, 5558002d411SSowmini Varadhan { "ADDRESS", 19, AGGR_X_ADDRESS, print_xaggr_cb}, 5568002d411SSowmini Varadhan { "PORTSTATE", 16, AGGR_X_PORTSTATE, print_xaggr_cb}, 5578002d411SSowmini 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 5748002d411SSowmini Varadhan static ofmt_field_t aggr_s_fields[] = { 5758002d411SSowmini Varadhan { "LINK", 12, AGGR_S_LINK, print_aggr_stats_cb}, 5768002d411SSowmini Varadhan { "PORT", 10, AGGR_S_PORT, print_aggr_stats_cb}, 5778002d411SSowmini Varadhan { "IPACKETS", 8, AGGR_S_IPKTS, print_aggr_stats_cb}, 5788002d411SSowmini Varadhan { "RBYTES", 8, AGGR_S_RBYTES, print_aggr_stats_cb}, 5798002d411SSowmini Varadhan { "OPACKETS", 8, AGGR_S_OPKTS, print_aggr_stats_cb}, 5808002d411SSowmini Varadhan { "OBYTES", 8, AGGR_S_OBYTES, print_aggr_stats_cb}, 5818002d411SSowmini Varadhan { "IPKTDIST", 9, AGGR_S_IPKTDIST, print_aggr_stats_cb}, 5828002d411SSowmini Varadhan { "OPKTDIST", 15, AGGR_S_OPKTDIST, print_aggr_stats_cb}, 5838002d411SSowmini 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 6008002d411SSowmini Varadhan static ofmt_field_t aggr_l_fields[] = { 6018002d411SSowmini Varadhan /* name, field width, index */ 6028002d411SSowmini Varadhan { "LINK", 12, AGGR_L_LINK, print_lacp_cb}, 6038002d411SSowmini Varadhan { "PORT", 13, AGGR_L_PORT, print_lacp_cb}, 6048002d411SSowmini Varadhan { "AGGREGATABLE", 13, AGGR_L_AGGREGATABLE, print_lacp_cb}, 6058002d411SSowmini Varadhan { "SYNC", 5, AGGR_L_SYNC, print_lacp_cb}, 6068002d411SSowmini Varadhan { "COLL", 5, AGGR_L_COLL, print_lacp_cb}, 6078002d411SSowmini Varadhan { "DIST", 5, AGGR_L_DIST, print_lacp_cb}, 6088002d411SSowmini Varadhan { "DEFAULTED", 10, AGGR_L_DEFAULTED, print_lacp_cb}, 6098002d411SSowmini Varadhan { "EXPIRED", 15, AGGR_L_EXPIRED, print_lacp_cb}, 6108002d411SSowmini Varadhan { NULL, 0, 0, NULL}} 611e7801d59Ssowmini ; 612e7801d59Ssowmini 613e7801d59Ssowmini /* 614e7801d59Ssowmini * structures for 'dladm show-phys' 615e7801d59Ssowmini */ 616e7801d59Ssowmini 6178002d411SSowmini Varadhan static ofmt_field_t phys_fields[] = { 6188002d411SSowmini Varadhan /* name, field width, offset */ 6198002d411SSowmini Varadhan { "LINK", 13, 6208002d411SSowmini Varadhan offsetof(link_fields_buf_t, link_name), print_default_cb}, 6218002d411SSowmini Varadhan { "MEDIA", 21, 6228002d411SSowmini Varadhan offsetof(link_fields_buf_t, link_phys_media), print_default_cb}, 6238002d411SSowmini Varadhan { "STATE", 11, 6248002d411SSowmini Varadhan offsetof(link_fields_buf_t, link_phys_state), print_default_cb}, 6258002d411SSowmini Varadhan { "SPEED", 7, 6268002d411SSowmini Varadhan offsetof(link_fields_buf_t, link_phys_speed), print_default_cb}, 6278002d411SSowmini Varadhan { "DUPLEX", 10, 6288002d411SSowmini Varadhan offsetof(link_fields_buf_t, link_phys_duplex), print_default_cb}, 6298002d411SSowmini Varadhan { "DEVICE", 13, 6308002d411SSowmini Varadhan offsetof(link_fields_buf_t, link_phys_device), print_default_cb}, 6318002d411SSowmini Varadhan { "FLAGS", 7, 6328002d411SSowmini Varadhan offsetof(link_fields_buf_t, link_flags), print_default_cb}, 6338002d411SSowmini 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 6488002d411SSowmini Varadhan static ofmt_field_t phys_m_fields[] = { 6498002d411SSowmini Varadhan /* name, field width, offset */ 6508002d411SSowmini Varadhan { "LINK", 13, PHYS_M_LINK, print_phys_one_mac_cb}, 6518002d411SSowmini Varadhan { "SLOT", 9, PHYS_M_SLOT, print_phys_one_mac_cb}, 6528002d411SSowmini Varadhan { "ADDRESS", 19, PHYS_M_ADDRESS, print_phys_one_mac_cb}, 6538002d411SSowmini Varadhan { "INUSE", 5, PHYS_M_INUSE, print_phys_one_mac_cb}, 6548002d411SSowmini Varadhan { "CLIENT", 13, PHYS_M_CLIENT, print_phys_one_mac_cb}, 6558002d411SSowmini 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 6708002d411SSowmini Varadhan static ofmt_field_t phys_h_fields[] = { 6718002d411SSowmini Varadhan { "LINK", 13, PHYS_H_LINK, print_phys_one_hwgrp_cb}, 6728002d411SSowmini Varadhan { "GROUP", 9, PHYS_H_GROUP, print_phys_one_hwgrp_cb}, 6738002d411SSowmini Varadhan { "GROUPTYPE", 7, PHYS_H_GRPTYPE, print_phys_one_hwgrp_cb}, 6748002d411SSowmini Varadhan { "RINGS", 17, PHYS_H_RINGS, print_phys_one_hwgrp_cb}, 6758002d411SSowmini Varadhan { "CLIENTS", 21, PHYS_H_CLIENTS, print_phys_one_hwgrp_cb}, 6768002d411SSowmini Varadhan { NULL, 0, 0, NULL}} 677da14cebeSEric Cheng ; 678da14cebeSEric Cheng 679da14cebeSEric Cheng /* 680e7801d59Ssowmini * structures for 'dladm show-vlan' 681e7801d59Ssowmini */ 6828002d411SSowmini Varadhan static ofmt_field_t vlan_fields[] = { 6838002d411SSowmini Varadhan { "LINK", 16, 6848002d411SSowmini Varadhan offsetof(link_fields_buf_t, link_name), print_default_cb}, 6858002d411SSowmini Varadhan { "VID", 9, 6868002d411SSowmini Varadhan offsetof(link_fields_buf_t, link_vlan_vid), print_default_cb}, 6878002d411SSowmini Varadhan { "OVER", 13, 6888002d411SSowmini Varadhan offsetof(link_fields_buf_t, link_over), print_default_cb}, 6898002d411SSowmini Varadhan { "FLAGS", 7, 6908002d411SSowmini Varadhan offsetof(link_fields_buf_t, link_flags), print_default_cb}, 6918002d411SSowmini Varadhan { NULL, 0, 0, NULL}} 692e7801d59Ssowmini ; 693da14cebeSEric Cheng 694e7801d59Ssowmini /* 6958002d411SSowmini Varadhan * structures common to 'dladm scan-wifi' and 'dladm show-wifi' 6968002d411SSowmini Varadhan * callback will be determined in parse_wifi_fields. 697e7801d59Ssowmini */ 6988002d411SSowmini Varadhan static ofmt_field_t wifi_common_fields[] = { 6998002d411SSowmini Varadhan { "LINK", 11, 0, NULL}, 7008002d411SSowmini Varadhan { "ESSID", 20, DLADM_WLAN_ATTR_ESSID, NULL}, 7018002d411SSowmini Varadhan { "BSSID", 18, DLADM_WLAN_ATTR_BSSID, NULL}, 7028002d411SSowmini Varadhan { "IBSSID", 18, DLADM_WLAN_ATTR_BSSID, NULL}, 7038002d411SSowmini Varadhan { "MODE", 7, DLADM_WLAN_ATTR_MODE, NULL}, 7048002d411SSowmini Varadhan { "SPEED", 7, DLADM_WLAN_ATTR_SPEED, NULL}, 7058002d411SSowmini Varadhan { "BSSTYPE", 9, DLADM_WLAN_ATTR_BSSTYPE, NULL}, 7068002d411SSowmini Varadhan { "SEC", 7, DLADM_WLAN_ATTR_SECMODE, NULL}, 7078002d411SSowmini Varadhan { "STRENGTH", 11, DLADM_WLAN_ATTR_STRENGTH, NULL}, 7088002d411SSowmini Varadhan { NULL, 0, 0, NULL}}; 7098002d411SSowmini Varadhan 7108002d411SSowmini Varadhan /* 7118002d411SSowmini Varadhan * the 'show-wifi' command supports all the fields in wifi_common_fields 7128002d411SSowmini Varadhan * plus the AUTH and STATUS fields. 7138002d411SSowmini Varadhan */ 7148002d411SSowmini Varadhan static ofmt_field_t wifi_show_fields[A_CNT(wifi_common_fields) + 2] = { 7158002d411SSowmini Varadhan { "AUTH", 9, DLADM_WLAN_ATTR_AUTH, NULL}, 7168002d411SSowmini Varadhan { "STATUS", 18, DLADM_WLAN_LINKATTR_STATUS, print_wifi_status_cb}, 7178002d411SSowmini Varadhan /* copy wifi_common_fields here */ 7188002d411SSowmini 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 7418002d411SSowmini Varadhan static ofmt_field_t linkprop_fields[] = { 7428002d411SSowmini Varadhan /* name, field width, index */ 7438002d411SSowmini Varadhan { "LINK", 13, LINKPROP_LINK, print_linkprop_cb}, 7448002d411SSowmini Varadhan { "PROPERTY", 16, LINKPROP_PROPERTY, print_linkprop_cb}, 7458002d411SSowmini Varadhan { "PERM", 5, LINKPROP_PERM, print_linkprop_cb}, 7468002d411SSowmini Varadhan { "VALUE", 15, LINKPROP_VALUE, print_linkprop_cb}, 7478002d411SSowmini Varadhan { "DEFAULT", 15, LINKPROP_DEFAULT, print_linkprop_cb}, 7488002d411SSowmini Varadhan { "POSSIBLE", 21, LINKPROP_POSSIBLE, print_linkprop_cb}, 7498002d411SSowmini 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; 7598002d411SSowmini 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; 7648002d411SSowmini 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; 7888002d411SSowmini Varadhan 7898002d411SSowmini Varadhan static ofmt_field_t secobj_fields[] = { 7908002d411SSowmini Varadhan { "OBJECT", 21, 7918002d411SSowmini Varadhan offsetof(secobj_fields_buf_t, ss_obj_name), print_default_cb}, 7928002d411SSowmini Varadhan { "CLASS", 21, 7938002d411SSowmini Varadhan offsetof(secobj_fields_buf_t, ss_class), print_default_cb}, 7948002d411SSowmini Varadhan { "VALUE", 31, 7958002d411SSowmini Varadhan offsetof(secobj_fields_buf_t, ss_val), print_default_cb}, 7968002d411SSowmini 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 8128002d411SSowmini Varadhan static ofmt_field_t vnic_fields[] = { 8138002d411SSowmini Varadhan { "LINK", 13, 8148002d411SSowmini Varadhan offsetof(vnic_fields_buf_t, vnic_link), print_default_cb}, 8158002d411SSowmini Varadhan { "OVER", 13, 8168002d411SSowmini Varadhan offsetof(vnic_fields_buf_t, vnic_over), print_default_cb}, 8178002d411SSowmini Varadhan { "SPEED", 7, 8188002d411SSowmini Varadhan offsetof(vnic_fields_buf_t, vnic_speed), print_default_cb}, 8198002d411SSowmini Varadhan { "MACADDRESS", 21, 8208002d411SSowmini Varadhan offsetof(vnic_fields_buf_t, vnic_macaddr), print_default_cb}, 8218002d411SSowmini Varadhan { "MACADDRTYPE", 20, 8228002d411SSowmini Varadhan offsetof(vnic_fields_buf_t, vnic_macaddrtype), print_default_cb}, 8238002d411SSowmini Varadhan { "VID", 7, 8248002d411SSowmini Varadhan offsetof(vnic_fields_buf_t, vnic_vid), print_default_cb}, 8258002d411SSowmini 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 8428002d411SSowmini Varadhan static ofmt_field_t usage_fields[] = { 8438002d411SSowmini Varadhan { "LINK", 13, 8448002d411SSowmini Varadhan offsetof(usage_fields_buf_t, usage_link), print_default_cb}, 8458002d411SSowmini Varadhan { "DURATION", 11, 8468002d411SSowmini Varadhan offsetof(usage_fields_buf_t, usage_duration), print_default_cb}, 8478002d411SSowmini Varadhan { "IPACKETS", 10, 8488002d411SSowmini Varadhan offsetof(usage_fields_buf_t, usage_ipackets), print_default_cb}, 8498002d411SSowmini Varadhan { "RBYTES", 11, 8508002d411SSowmini Varadhan offsetof(usage_fields_buf_t, usage_rbytes), print_default_cb}, 8518002d411SSowmini Varadhan { "OPACKETS", 10, 8528002d411SSowmini Varadhan offsetof(usage_fields_buf_t, usage_opackets), print_default_cb}, 8538002d411SSowmini Varadhan { "OBYTES", 11, 8548002d411SSowmini Varadhan offsetof(usage_fields_buf_t, usage_obytes), print_default_cb}, 8558002d411SSowmini Varadhan { "BANDWIDTH", 15, 8568002d411SSowmini Varadhan offsetof(usage_fields_buf_t, usage_bandwidth), print_default_cb}, 8578002d411SSowmini 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 8748002d411SSowmini Varadhan static ofmt_field_t usage_l_fields[] = { 8758002d411SSowmini Varadhan /* name, field width, offset */ 8768002d411SSowmini Varadhan { "LINK", 13, 8778002d411SSowmini Varadhan offsetof(usage_l_fields_buf_t, usage_l_link), print_default_cb}, 8788002d411SSowmini Varadhan { "START", 14, 8798002d411SSowmini Varadhan offsetof(usage_l_fields_buf_t, usage_l_stime), print_default_cb}, 8808002d411SSowmini Varadhan { "END", 14, 8818002d411SSowmini Varadhan offsetof(usage_l_fields_buf_t, usage_l_etime), print_default_cb}, 8828002d411SSowmini Varadhan { "RBYTES", 9, 8838002d411SSowmini Varadhan offsetof(usage_l_fields_buf_t, usage_l_rbytes), print_default_cb}, 8848002d411SSowmini Varadhan { "OBYTES", 9, 8858002d411SSowmini Varadhan offsetof(usage_l_fields_buf_t, usage_l_obytes), print_default_cb}, 8868002d411SSowmini Varadhan { "BANDWIDTH", 15, 8878002d411SSowmini Varadhan offsetof(usage_l_fields_buf_t, usage_l_bandwidth), print_default_cb}, 8888002d411SSowmini 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 10688002d411SSowmini 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 11118002d411SSowmini 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"; 11438002d411SSowmini Varadhan ofmt_handle_t ofmt; 11448002d411SSowmini Varadhan ofmt_status_t oferr; 11458002d411SSowmini Varadhan uint_t ofmtflags = 0; 1146da14cebeSEric Cheng 1147da14cebeSEric Cheng bzero(&state, sizeof (show_usage_state_t)); 11488002d411SSowmini 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 12068002d411SSowmini Varadhan if (state.us_parsable) 12078002d411SSowmini Varadhan ofmtflags |= OFMT_PARSABLE; 12088002d411SSowmini Varadhan 12098002d411SSowmini Varadhan if (resource == NULL && stime == NULL && etime == NULL) { 12108002d411SSowmini Varadhan oferr = ofmt_open(fields_str, usage_fields, ofmtflags, 0, 12118002d411SSowmini Varadhan &ofmt); 12128002d411SSowmini Varadhan } else { 12138002d411SSowmini Varadhan if (!o_arg || (o_arg && strcasecmp(fields_str, "all") == 0)) 12148002d411SSowmini Varadhan fields_str = all_l_fields; 12158002d411SSowmini Varadhan oferr = ofmt_open(fields_str, usage_l_fields, ofmtflags, 0, 12168002d411SSowmini Varadhan &ofmt); 12178002d411SSowmini Varadhan 12188002d411SSowmini Varadhan } 12198002d411SSowmini Varadhan dladm_ofmt_check(oferr, state.us_parsable, ofmt); 12208002d411SSowmini Varadhan state.us_ofmt = ofmt; 12218002d411SSowmini 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"); 12438002d411SSowmini 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 22448002d411SSowmini Varadhan ofmt_print(state->ls_ofmt, &lbuf); 2245d62bc4baSyz147064 2246d62bc4baSyz147064 done: 2247d62bc4baSyz147064 state->ls_status = status; 2248d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 2249d62bc4baSyz147064 } 2250d62bc4baSyz147064 22518002d411SSowmini Varadhan static boolean_t 22528002d411SSowmini Varadhan print_link_stats_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize) 2253ae6aa22aSVenugopal Iyer { 22548002d411SSowmini Varadhan link_args_t *largs = ofarg->ofmt_cbarg; 2255ae6aa22aSVenugopal Iyer pktsum_t *diff_stats = largs->link_s_psum; 2256ae6aa22aSVenugopal Iyer 22578002d411SSowmini Varadhan switch (ofarg->ofmt_id) { 2258ae6aa22aSVenugopal Iyer case LINK_S_LINK: 22598002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%s", largs->link_s_link); 2260ae6aa22aSVenugopal Iyer break; 2261ae6aa22aSVenugopal Iyer case LINK_S_IPKTS: 22628002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%llu", diff_stats->ipackets); 2263ae6aa22aSVenugopal Iyer break; 2264ae6aa22aSVenugopal Iyer case LINK_S_RBYTES: 22658002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%llu", diff_stats->rbytes); 2266ae6aa22aSVenugopal Iyer break; 2267ae6aa22aSVenugopal Iyer case LINK_S_IERRORS: 22688002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%u", diff_stats->ierrors); 2269ae6aa22aSVenugopal Iyer break; 2270ae6aa22aSVenugopal Iyer case LINK_S_OPKTS: 22718002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%llu", diff_stats->opackets); 2272ae6aa22aSVenugopal Iyer break; 2273ae6aa22aSVenugopal Iyer case LINK_S_OBYTES: 22748002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%llu", diff_stats->obytes); 2275ae6aa22aSVenugopal Iyer break; 2276ae6aa22aSVenugopal Iyer case LINK_S_OERRORS: 22778002d411SSowmini 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 } 22838002d411SSowmini 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; 23258002d411SSowmini 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 23628002d411SSowmini Varadhan ofmt_print(state->gs_ofmt, &lbuf); 2363e7801d59Ssowmini 2364d62bc4baSyz147064 return (DLADM_STATUS_OK); 2365d62bc4baSyz147064 } 2366d62bc4baSyz147064 23678002d411SSowmini Varadhan static boolean_t 23688002d411SSowmini Varadhan print_xaggr_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize) 2369d62bc4baSyz147064 { 23708002d411SSowmini Varadhan const laggr_args_t *l = ofarg->ofmt_cbarg; 2371e7801d59Ssowmini int portnum; 2372e7801d59Ssowmini boolean_t is_port = (l->laggr_lport >= 0); 23738002d411SSowmini Varadhan static char tmpbuf[DLADM_STRSIZE]; 2374e7801d59Ssowmini dladm_aggr_port_attr_t *portp; 2375d62bc4baSyz147064 dladm_phys_attr_t dpa; 23768002d411SSowmini 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, 23848002d411SSowmini 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 23958002d411SSowmini Varadhan switch (ofarg->ofmt_id) { 2396e7801d59Ssowmini case AGGR_X_LINK: 23978002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%s", 23988002d411SSowmini Varadhan (is_port && !l->laggr_parsable ? " " : l->laggr_link)); 2399e7801d59Ssowmini break; 2400e7801d59Ssowmini case AGGR_X_PORT: 2401e7801d59Ssowmini if (is_port) 2402e7801d59Ssowmini break; 24038002d411SSowmini Varadhan *stat = DLADM_STATUS_OK; 24048002d411SSowmini Varadhan return (B_TRUE); 2405d62bc4baSyz147064 2406e7801d59Ssowmini case AGGR_X_SPEED: 2407e7801d59Ssowmini if (is_port) { 24088002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%uMb", 2409e7801d59Ssowmini (uint_t)((get_ifspeed(dpa.dp_dev, 2410e7801d59Ssowmini B_FALSE)) / 1000000ull)); 2411e7801d59Ssowmini } else { 24128002d411SSowmini 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) 24208002d411SSowmini Varadhan (void) get_linkduplex(dpa.dp_dev, B_FALSE, tmpbuf); 2421d62bc4baSyz147064 else 24228002d411SSowmini Varadhan (void) get_linkduplex(l->laggr_link, B_TRUE, tmpbuf); 24238002d411SSowmini Varadhan (void) strlcpy(buf, tmpbuf, bufsize); 2424e7801d59Ssowmini break; 2425d62bc4baSyz147064 2426e7801d59Ssowmini case AGGR_X_STATE: 24271a1811a0Svs226613 if (is_port) 24288002d411SSowmini Varadhan (void) get_linkstate(dpa.dp_dev, B_FALSE, tmpbuf); 24291a1811a0Svs226613 else 24308002d411SSowmini Varadhan (void) get_linkstate(l->laggr_link, B_TRUE, tmpbuf); 24318002d411SSowmini 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), 24368002d411SSowmini Varadhan tmpbuf); 24378002d411SSowmini Varadhan (void) strlcpy(buf, tmpbuf, bufsize); 2438e7801d59Ssowmini break; 2439e7801d59Ssowmini case AGGR_X_PORTSTATE: 24408002d411SSowmini Varadhan if (is_port) { 24418002d411SSowmini Varadhan (void) dladm_aggr_portstate2str(portp->lp_state, 24428002d411SSowmini Varadhan tmpbuf); 24438002d411SSowmini Varadhan (void) strlcpy(buf, tmpbuf, bufsize); 24448002d411SSowmini Varadhan } 2445e7801d59Ssowmini break; 2446e7801d59Ssowmini } 2447e7801d59Ssowmini err: 2448e7801d59Ssowmini *stat = status; 24498002d411SSowmini 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; 24648002d411SSowmini Varadhan largs.laggr_parsable = state->gs_parsable; 2465e7801d59Ssowmini 24668002d411SSowmini 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; 24738002d411SSowmini 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 24838002d411SSowmini Varadhan static boolean_t 24848002d411SSowmini Varadhan print_lacp_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize) 2485e7801d59Ssowmini { 24868002d411SSowmini 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) { 24948002d411SSowmini 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, 25038002d411SSowmini Varadhan NULL, NULL, NULL, buf, bufsize)) != DLADM_STATUS_OK) { 2504e7801d59Ssowmini goto err; 2505e7801d59Ssowmini } 2506e7801d59Ssowmini lstate = &(portp->lp_lacp_state); 2507e7801d59Ssowmini 25088002d411SSowmini Varadhan switch (ofarg->ofmt_id) { 2509e7801d59Ssowmini case AGGR_L_LINK: 25108002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%s", 2511e7801d59Ssowmini (portnum > 0 ? "" : l->laggr_link)); 2512e7801d59Ssowmini break; 2513e7801d59Ssowmini 2514e7801d59Ssowmini case AGGR_L_PORT: 25158002d411SSowmini Varadhan /* 25168002d411SSowmini Varadhan * buf already contains portname as a result of the 25178002d411SSowmini Varadhan * earlier call to dladm_datalink_id2info(). 25188002d411SSowmini Varadhan */ 2519e7801d59Ssowmini break; 2520e7801d59Ssowmini 2521e7801d59Ssowmini case AGGR_L_AGGREGATABLE: 25228002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%s", 2523e7801d59Ssowmini (lstate->bit.aggregation ? "yes" : "no")); 2524e7801d59Ssowmini break; 2525e7801d59Ssowmini 2526e7801d59Ssowmini case AGGR_L_SYNC: 25278002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%s", 2528e7801d59Ssowmini (lstate->bit.sync ? "yes" : "no")); 2529e7801d59Ssowmini break; 2530e7801d59Ssowmini 2531e7801d59Ssowmini case AGGR_L_COLL: 25328002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%s", 2533e7801d59Ssowmini (lstate->bit.collecting ? "yes" : "no")); 2534e7801d59Ssowmini break; 2535e7801d59Ssowmini 2536e7801d59Ssowmini case AGGR_L_DIST: 25378002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%s", 2538e7801d59Ssowmini (lstate->bit.distributing ? "yes" : "no")); 2539e7801d59Ssowmini break; 2540e7801d59Ssowmini 2541e7801d59Ssowmini case AGGR_L_DEFAULTED: 25428002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%s", 2543e7801d59Ssowmini (lstate->bit.defaulted ? "yes" : "no")); 2544e7801d59Ssowmini break; 2545e7801d59Ssowmini 2546e7801d59Ssowmini case AGGR_L_EXPIRED: 25478002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%s", 2548e7801d59Ssowmini (lstate->bit.expired ? "yes" : "no")); 2549e7801d59Ssowmini break; 2550e7801d59Ssowmini } 2551e7801d59Ssowmini 2552e7801d59Ssowmini *stat = DLADM_STATUS_OK; 25538002d411SSowmini Varadhan return (B_TRUE); 2554e7801d59Ssowmini 2555e7801d59Ssowmini err: 2556e7801d59Ssowmini *stat = status; 25578002d411SSowmini 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; 25748002d411SSowmini 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 25848002d411SSowmini Varadhan static boolean_t 25858002d411SSowmini Varadhan print_aggr_stats_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize) 2586e7801d59Ssowmini { 25878002d411SSowmini 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_status_t *stat, status; 2592*2d40c3b2SPrakash Jalan pktsum_t *diff_stats; 2593e7801d59Ssowmini 2594e7801d59Ssowmini stat = l->laggr_status; 2595e7801d59Ssowmini *stat = DLADM_STATUS_OK; 2596e7801d59Ssowmini 2597e7801d59Ssowmini if (is_port) { 2598e7801d59Ssowmini portnum = l->laggr_lport; 2599e7801d59Ssowmini portp = &(l->laggr_ginfop->lg_ports[portnum]); 2600e7801d59Ssowmini 26014ac67f02SAnurag S. Maskey if ((status = dladm_datalink_id2info(handle, 26028002d411SSowmini Varadhan portp->lp_linkid, NULL, NULL, NULL, buf, bufsize)) != 26034ac67f02SAnurag S. Maskey DLADM_STATUS_OK) { 2604e7801d59Ssowmini goto err; 2605e7801d59Ssowmini } 2606*2d40c3b2SPrakash Jalan diff_stats = l->laggr_diffstats; 2607e7801d59Ssowmini } 2608e7801d59Ssowmini 26098002d411SSowmini Varadhan switch (ofarg->ofmt_id) { 2610e7801d59Ssowmini case AGGR_S_LINK: 26118002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%s", 2612e7801d59Ssowmini (is_port ? "" : l->laggr_link)); 2613e7801d59Ssowmini break; 2614e7801d59Ssowmini case AGGR_S_PORT: 26158002d411SSowmini Varadhan /* 26168002d411SSowmini Varadhan * if (is_port), buf has port name. Otherwise we print 26178002d411SSowmini Varadhan * STR_UNDEF_VAL 26188002d411SSowmini Varadhan */ 2619e7801d59Ssowmini break; 2620e7801d59Ssowmini 2621e7801d59Ssowmini case AGGR_S_IPKTS: 2622e7801d59Ssowmini if (is_port) { 26238002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%llu", 2624*2d40c3b2SPrakash Jalan diff_stats->ipackets); 2625e7801d59Ssowmini } else { 26268002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%llu", 2627e7801d59Ssowmini l->laggr_pktsumtot->ipackets); 2628e7801d59Ssowmini } 2629e7801d59Ssowmini break; 2630e7801d59Ssowmini 2631e7801d59Ssowmini case AGGR_S_RBYTES: 2632e7801d59Ssowmini if (is_port) { 26338002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%llu", 2634*2d40c3b2SPrakash Jalan diff_stats->rbytes); 2635e7801d59Ssowmini } else { 26368002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%llu", 2637e7801d59Ssowmini l->laggr_pktsumtot->rbytes); 2638e7801d59Ssowmini } 2639e7801d59Ssowmini break; 2640e7801d59Ssowmini 2641e7801d59Ssowmini case AGGR_S_OPKTS: 2642e7801d59Ssowmini if (is_port) { 26438002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%llu", 2644*2d40c3b2SPrakash Jalan diff_stats->opackets); 2645e7801d59Ssowmini } else { 26468002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%llu", 2647e7801d59Ssowmini l->laggr_pktsumtot->opackets); 2648e7801d59Ssowmini } 2649e7801d59Ssowmini break; 2650e7801d59Ssowmini case AGGR_S_OBYTES: 2651e7801d59Ssowmini if (is_port) { 26528002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%llu", 2653*2d40c3b2SPrakash Jalan diff_stats->obytes); 2654e7801d59Ssowmini } else { 26558002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%llu", 2656e7801d59Ssowmini l->laggr_pktsumtot->obytes); 2657e7801d59Ssowmini } 2658e7801d59Ssowmini break; 2659e7801d59Ssowmini 2660e7801d59Ssowmini case AGGR_S_IPKTDIST: 2661e7801d59Ssowmini if (is_port) { 26628002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%-6.1f", 2663*2d40c3b2SPrakash Jalan (double)diff_stats->ipackets/ 2664e7801d59Ssowmini (double)l->laggr_pktsumtot->ipackets * 100); 2665e7801d59Ssowmini } 2666e7801d59Ssowmini break; 2667e7801d59Ssowmini case AGGR_S_OPKTDIST: 2668e7801d59Ssowmini if (is_port) { 26698002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%-6.1f", 2670*2d40c3b2SPrakash Jalan (double)diff_stats->opackets/ 2671e7801d59Ssowmini (double)l->laggr_pktsumtot->opackets * 100); 2672e7801d59Ssowmini } 2673e7801d59Ssowmini break; 2674e7801d59Ssowmini } 26758002d411SSowmini Varadhan return (B_TRUE); 2676e7801d59Ssowmini 2677e7801d59Ssowmini err: 2678e7801d59Ssowmini *stat = status; 26798002d411SSowmini Varadhan return (B_TRUE); 2680e7801d59Ssowmini } 2681e7801d59Ssowmini 2682d62bc4baSyz147064 static dladm_status_t 2683d62bc4baSyz147064 print_aggr_stats(show_grp_state_t *state, const char *link, 2684e7801d59Ssowmini dladm_aggr_grp_attr_t *ginfop) 2685d62bc4baSyz147064 { 2686d62bc4baSyz147064 dladm_phys_attr_t dpa; 2687d62bc4baSyz147064 dladm_aggr_port_attr_t *portp; 2688*2d40c3b2SPrakash Jalan pktsum_t pktsumtot, *port_stat; 2689d62bc4baSyz147064 dladm_status_t status; 2690d62bc4baSyz147064 int i; 2691e7801d59Ssowmini laggr_args_t largs; 26927c478bd9Sstevel@tonic-gate 26937c478bd9Sstevel@tonic-gate /* sum the ports statistics */ 26947c478bd9Sstevel@tonic-gate bzero(&pktsumtot, sizeof (pktsumtot)); 2695d62bc4baSyz147064 2696*2d40c3b2SPrakash Jalan /* Allocate memory to keep stats of each port */ 2697*2d40c3b2SPrakash Jalan port_stat = malloc(ginfop->lg_nports * sizeof (pktsum_t)); 2698*2d40c3b2SPrakash Jalan if (port_stat == NULL) { 2699*2d40c3b2SPrakash Jalan /* Bail out; no memory */ 2700*2d40c3b2SPrakash Jalan return (DLADM_STATUS_NOMEM); 2701*2d40c3b2SPrakash Jalan } 2702*2d40c3b2SPrakash Jalan 2703*2d40c3b2SPrakash Jalan 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 2712*2d40c3b2SPrakash Jalan get_mac_stats(dpa.dp_dev, &port_stat[i]); 2713*2d40c3b2SPrakash Jalan 2714*2d40c3b2SPrakash Jalan /* 2715*2d40c3b2SPrakash Jalan * Let's re-use gs_prevstats[] to store the difference of the 2716*2d40c3b2SPrakash Jalan * counters since last use. We will store the new stats from 2717*2d40c3b2SPrakash Jalan * port_stat[] once we have the stats displayed. 2718*2d40c3b2SPrakash Jalan */ 2719*2d40c3b2SPrakash Jalan 2720*2d40c3b2SPrakash Jalan dladm_stats_diff(&state->gs_prevstats[i], &port_stat[i], 2721*2d40c3b2SPrakash Jalan &state->gs_prevstats[i]); 2722*2d40c3b2SPrakash Jalan dladm_stats_total(&pktsumtot, &pktsumtot, 2723da14cebeSEric Cheng &state->gs_prevstats[i]); 27247c478bd9Sstevel@tonic-gate } 27257c478bd9Sstevel@tonic-gate 2726e7801d59Ssowmini largs.laggr_lport = -1; 2727e7801d59Ssowmini largs.laggr_link = link; 2728e7801d59Ssowmini largs.laggr_ginfop = ginfop; 2729e7801d59Ssowmini largs.laggr_status = &status; 2730e7801d59Ssowmini largs.laggr_pktsumtot = &pktsumtot; 2731e7801d59Ssowmini 27328002d411SSowmini Varadhan ofmt_print(state->gs_ofmt, &largs); 2733e7801d59Ssowmini 2734e7801d59Ssowmini if (status != DLADM_STATUS_OK) 2735e7801d59Ssowmini goto done; 2736d62bc4baSyz147064 2737d62bc4baSyz147064 for (i = 0; i < ginfop->lg_nports; i++) { 2738e7801d59Ssowmini largs.laggr_lport = i; 2739*2d40c3b2SPrakash Jalan largs.laggr_diffstats = &state->gs_prevstats[i]; 27408002d411SSowmini Varadhan ofmt_print(state->gs_ofmt, &largs); 2741e7801d59Ssowmini if (status != DLADM_STATUS_OK) 2742d62bc4baSyz147064 goto done; 2743d62bc4baSyz147064 } 2744d62bc4baSyz147064 2745d62bc4baSyz147064 status = DLADM_STATUS_OK; 2746*2d40c3b2SPrakash Jalan for (i = 0; i < ginfop->lg_nports; i++) 2747*2d40c3b2SPrakash Jalan state->gs_prevstats[i] = port_stat[i]; 2748*2d40c3b2SPrakash Jalan 2749d62bc4baSyz147064 done: 2750*2d40c3b2SPrakash Jalan free(port_stat); 2751d62bc4baSyz147064 return (status); 2752d62bc4baSyz147064 } 2753d62bc4baSyz147064 2754d62bc4baSyz147064 static dladm_status_t 2755e7801d59Ssowmini print_aggr(show_grp_state_t *state, datalink_id_t linkid) 2756d62bc4baSyz147064 { 2757d62bc4baSyz147064 char link[MAXLINKNAMELEN]; 2758d62bc4baSyz147064 dladm_aggr_grp_attr_t ginfo; 2759d62bc4baSyz147064 uint32_t flags; 2760d62bc4baSyz147064 dladm_status_t status; 2761d62bc4baSyz147064 27625f5c9f54SAnurag S. Maskey bzero(&ginfo, sizeof (dladm_aggr_grp_attr_t)); 27634ac67f02SAnurag S. Maskey if ((status = dladm_datalink_id2info(handle, linkid, &flags, NULL, 27644ac67f02SAnurag S. Maskey NULL, link, MAXLINKNAMELEN)) != DLADM_STATUS_OK) { 2765d62bc4baSyz147064 return (status); 2766d62bc4baSyz147064 } 2767d62bc4baSyz147064 2768d62bc4baSyz147064 if (!(state->gs_flags & flags)) 2769d62bc4baSyz147064 return (DLADM_STATUS_NOTFOUND); 2770d62bc4baSyz147064 27714ac67f02SAnurag S. Maskey status = dladm_aggr_info(handle, linkid, &ginfo, state->gs_flags); 2772d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 2773d62bc4baSyz147064 return (status); 2774d62bc4baSyz147064 2775d62bc4baSyz147064 if (state->gs_lacp) 2776e7801d59Ssowmini status = print_aggr_lacp(state, link, &ginfo); 2777d62bc4baSyz147064 else if (state->gs_extended) 2778e7801d59Ssowmini status = print_aggr_extended(state, link, &ginfo); 2779d62bc4baSyz147064 else if (state->gs_stats) 2780e7801d59Ssowmini status = print_aggr_stats(state, link, &ginfo); 27814ac67f02SAnurag S. Maskey else 2782e7801d59Ssowmini status = print_aggr_info(state, link, &ginfo); 2783d62bc4baSyz147064 2784d62bc4baSyz147064 done: 2785d62bc4baSyz147064 free(ginfo.lg_ports); 2786d62bc4baSyz147064 return (status); 2787d62bc4baSyz147064 } 2788d62bc4baSyz147064 27894ac67f02SAnurag S. Maskey /* ARGSUSED */ 2790d62bc4baSyz147064 static int 27914ac67f02SAnurag S. Maskey show_aggr(dladm_handle_t dh, datalink_id_t linkid, void *arg) 2792d62bc4baSyz147064 { 2793d62bc4baSyz147064 show_grp_state_t *state = arg; 2794d62bc4baSyz147064 27958002d411SSowmini Varadhan state->gs_status = print_aggr(state, linkid); 2796d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 27977c478bd9Sstevel@tonic-gate } 27987c478bd9Sstevel@tonic-gate 27997c478bd9Sstevel@tonic-gate static void 28008d5c46e6Sam223141 do_show_link(int argc, char *argv[], const char *use) 28017c478bd9Sstevel@tonic-gate { 28027c478bd9Sstevel@tonic-gate int option; 28037c478bd9Sstevel@tonic-gate boolean_t s_arg = B_FALSE; 2804da14cebeSEric Cheng boolean_t S_arg = B_FALSE; 28057c478bd9Sstevel@tonic-gate boolean_t i_arg = B_FALSE; 2806d62bc4baSyz147064 uint32_t flags = DLADM_OPT_ACTIVE; 2807d62bc4baSyz147064 boolean_t p_arg = B_FALSE; 2808d62bc4baSyz147064 datalink_id_t linkid = DATALINK_ALL_LINKID; 2809da14cebeSEric Cheng char linkname[MAXLINKNAMELEN]; 281063a6526dSMichael Lim uint32_t interval = 0; 2811d62bc4baSyz147064 show_state_t state; 2812d62bc4baSyz147064 dladm_status_t status; 2813e7801d59Ssowmini boolean_t o_arg = B_FALSE; 2814e7801d59Ssowmini char *fields_str = NULL; 2815e7801d59Ssowmini char *all_active_fields = "link,class,mtu,state,over"; 2816e7801d59Ssowmini char *all_inactive_fields = "link,class,over"; 28176be03d0bSVasumathi Sundaram - Sun Microsystems char *allstat_fields = 28186be03d0bSVasumathi Sundaram - Sun Microsystems "link,ipackets,rbytes,ierrors,opackets,obytes,oerrors"; 28198002d411SSowmini Varadhan ofmt_handle_t ofmt; 28208002d411SSowmini Varadhan ofmt_status_t oferr; 28218002d411SSowmini Varadhan uint_t ofmtflags = 0; 2822e7801d59Ssowmini 2823e7801d59Ssowmini bzero(&state, sizeof (state)); 28247c478bd9Sstevel@tonic-gate 28257c478bd9Sstevel@tonic-gate opterr = 0; 2826da14cebeSEric Cheng while ((option = getopt_long(argc, argv, ":pPsSi:o:", 2827d62bc4baSyz147064 show_lopts, NULL)) != -1) { 28287c478bd9Sstevel@tonic-gate switch (option) { 28297c478bd9Sstevel@tonic-gate case 'p': 2830d62bc4baSyz147064 if (p_arg) 2831d62bc4baSyz147064 die_optdup(option); 2832d62bc4baSyz147064 2833d62bc4baSyz147064 p_arg = B_TRUE; 28347c478bd9Sstevel@tonic-gate break; 28357c478bd9Sstevel@tonic-gate case 's': 283633343a97Smeem if (s_arg) 283733343a97Smeem die_optdup(option); 28387c478bd9Sstevel@tonic-gate 28397c478bd9Sstevel@tonic-gate s_arg = B_TRUE; 28407c478bd9Sstevel@tonic-gate break; 2841d62bc4baSyz147064 case 'P': 2842d62bc4baSyz147064 if (flags != DLADM_OPT_ACTIVE) 2843d62bc4baSyz147064 die_optdup(option); 2844d62bc4baSyz147064 2845d62bc4baSyz147064 flags = DLADM_OPT_PERSIST; 2846d62bc4baSyz147064 break; 2847da14cebeSEric Cheng case 'S': 2848da14cebeSEric Cheng if (S_arg) 2849da14cebeSEric Cheng die_optdup(option); 2850da14cebeSEric Cheng 2851da14cebeSEric Cheng S_arg = B_TRUE; 2852da14cebeSEric Cheng break; 2853e7801d59Ssowmini case 'o': 2854e7801d59Ssowmini o_arg = B_TRUE; 2855e7801d59Ssowmini fields_str = optarg; 2856e7801d59Ssowmini break; 28577c478bd9Sstevel@tonic-gate case 'i': 285833343a97Smeem if (i_arg) 285933343a97Smeem die_optdup(option); 28607c478bd9Sstevel@tonic-gate 28617c478bd9Sstevel@tonic-gate i_arg = B_TRUE; 286263a6526dSMichael Lim if (!dladm_str2interval(optarg, &interval)) 286333343a97Smeem die("invalid interval value '%s'", optarg); 28647c478bd9Sstevel@tonic-gate break; 28657c478bd9Sstevel@tonic-gate default: 28668d5c46e6Sam223141 die_opterr(optopt, option, use); 286733343a97Smeem break; 28687c478bd9Sstevel@tonic-gate } 28697c478bd9Sstevel@tonic-gate } 28707c478bd9Sstevel@tonic-gate 2871da14cebeSEric Cheng if (i_arg && !(s_arg || S_arg)) 2872da14cebeSEric Cheng die("the option -i can be used only with -s or -S"); 2873da14cebeSEric Cheng 2874da14cebeSEric Cheng if (s_arg && S_arg) 2875da14cebeSEric Cheng die("the -s option cannot be used with -S"); 28767c478bd9Sstevel@tonic-gate 28776be03d0bSVasumathi Sundaram - Sun Microsystems if (s_arg && flags != DLADM_OPT_ACTIVE) 28786be03d0bSVasumathi Sundaram - Sun Microsystems die("the option -P cannot be used with -s"); 2879d62bc4baSyz147064 2880da14cebeSEric Cheng if (S_arg && (p_arg || flags != DLADM_OPT_ACTIVE)) 2881da14cebeSEric Cheng die("the option -%c cannot be used with -S", p_arg ? 'p' : 'P'); 2882da14cebeSEric Cheng 28837c478bd9Sstevel@tonic-gate /* get link name (optional last argument) */ 2884d62bc4baSyz147064 if (optind == (argc-1)) { 2885d62bc4baSyz147064 uint32_t f; 2886d62bc4baSyz147064 2887da14cebeSEric Cheng if (strlcpy(linkname, argv[optind], MAXLINKNAMELEN) 2888da14cebeSEric Cheng >= MAXLINKNAMELEN) { 2889da14cebeSEric Cheng (void) fprintf(stderr, 2890da14cebeSEric Cheng gettext("%s: link name too long\n"), 2891da14cebeSEric Cheng progname); 28924ac67f02SAnurag S. Maskey dladm_close(handle); 2893da14cebeSEric Cheng exit(1); 2894da14cebeSEric Cheng } 28954ac67f02SAnurag S. Maskey if ((status = dladm_name2info(handle, linkname, &linkid, &f, 2896d62bc4baSyz147064 NULL, NULL)) != DLADM_STATUS_OK) { 2897da14cebeSEric Cheng die_dlerr(status, "link %s is not valid", linkname); 2898d62bc4baSyz147064 } 2899d62bc4baSyz147064 2900d62bc4baSyz147064 if (!(f & flags)) { 2901d62bc4baSyz147064 die_dlerr(DLADM_STATUS_BADARG, "link %s is %s", 2902d62bc4baSyz147064 argv[optind], flags == DLADM_OPT_PERSIST ? 2903d62bc4baSyz147064 "a temporary link" : "temporarily removed"); 2904d62bc4baSyz147064 } 2905d62bc4baSyz147064 } else if (optind != argc) { 29067c478bd9Sstevel@tonic-gate usage(); 2907d62bc4baSyz147064 } 29087c478bd9Sstevel@tonic-gate 29090d365605Sschuster if (p_arg && !o_arg) 29100d365605Sschuster die("-p requires -o"); 29110d365605Sschuster 2912da14cebeSEric Cheng if (S_arg) { 29134ac67f02SAnurag S. Maskey dladm_continuous(handle, linkid, NULL, interval, LINK_REPORT); 2914da14cebeSEric Cheng return; 2915da14cebeSEric Cheng } 2916da14cebeSEric Cheng 29170d365605Sschuster if (p_arg && strcasecmp(fields_str, "all") == 0) 29180d365605Sschuster die("\"-o all\" is invalid with -p"); 29190d365605Sschuster 2920e7801d59Ssowmini if (!o_arg || (o_arg && strcasecmp(fields_str, "all") == 0)) { 29216be03d0bSVasumathi Sundaram - Sun Microsystems if (s_arg) 29226be03d0bSVasumathi Sundaram - Sun Microsystems fields_str = allstat_fields; 29236be03d0bSVasumathi Sundaram - Sun Microsystems else if (flags & DLADM_OPT_ACTIVE) 2924e7801d59Ssowmini fields_str = all_active_fields; 2925e7801d59Ssowmini else 2926e7801d59Ssowmini fields_str = all_inactive_fields; 2927e7801d59Ssowmini } 2928e7801d59Ssowmini 29298002d411SSowmini Varadhan state.ls_parsable = p_arg; 29306be03d0bSVasumathi Sundaram - Sun Microsystems state.ls_flags = flags; 29316be03d0bSVasumathi Sundaram - Sun Microsystems state.ls_donefirst = B_FALSE; 29326be03d0bSVasumathi Sundaram - Sun Microsystems 29336be03d0bSVasumathi Sundaram - Sun Microsystems if (s_arg) { 29346be03d0bSVasumathi Sundaram - Sun Microsystems link_stats(linkid, interval, fields_str, &state); 29356be03d0bSVasumathi Sundaram - Sun Microsystems return; 29366be03d0bSVasumathi Sundaram - Sun Microsystems } 29378002d411SSowmini Varadhan if (state.ls_parsable) 29388002d411SSowmini Varadhan ofmtflags |= OFMT_PARSABLE; 29398002d411SSowmini Varadhan oferr = ofmt_open(fields_str, link_fields, ofmtflags, 0, &ofmt); 29408002d411SSowmini Varadhan dladm_ofmt_check(oferr, state.ls_parsable, ofmt); 29418002d411SSowmini Varadhan state.ls_ofmt = ofmt; 2942e7801d59Ssowmini 2943d62bc4baSyz147064 if (linkid == DATALINK_ALL_LINKID) { 29444ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(show_link, handle, &state, 2945d62bc4baSyz147064 DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE, flags); 2946210db224Sericheng } else { 29474ac67f02SAnurag S. Maskey (void) show_link(handle, linkid, &state); 2948d62bc4baSyz147064 if (state.ls_status != DLADM_STATUS_OK) { 2949d62bc4baSyz147064 die_dlerr(state.ls_status, "failed to show link %s", 2950d62bc4baSyz147064 argv[optind]); 2951d62bc4baSyz147064 } 29527c478bd9Sstevel@tonic-gate } 29538002d411SSowmini Varadhan ofmt_close(ofmt); 2954210db224Sericheng } 29557c478bd9Sstevel@tonic-gate 29567c478bd9Sstevel@tonic-gate static void 29578d5c46e6Sam223141 do_show_aggr(int argc, char *argv[], const char *use) 29587c478bd9Sstevel@tonic-gate { 29597c478bd9Sstevel@tonic-gate boolean_t L_arg = B_FALSE; 29607c478bd9Sstevel@tonic-gate boolean_t s_arg = B_FALSE; 29617c478bd9Sstevel@tonic-gate boolean_t i_arg = B_FALSE; 2962d62bc4baSyz147064 boolean_t p_arg = B_FALSE; 2963d62bc4baSyz147064 boolean_t x_arg = B_FALSE; 29647c478bd9Sstevel@tonic-gate show_grp_state_t state; 2965d62bc4baSyz147064 uint32_t flags = DLADM_OPT_ACTIVE; 2966d62bc4baSyz147064 datalink_id_t linkid = DATALINK_ALL_LINKID; 2967d62bc4baSyz147064 int option; 296863a6526dSMichael Lim uint32_t interval = 0; 2969d62bc4baSyz147064 int key; 2970d62bc4baSyz147064 dladm_status_t status; 2971e7801d59Ssowmini boolean_t o_arg = B_FALSE; 2972e7801d59Ssowmini char *fields_str = NULL; 2973e7801d59Ssowmini char *all_fields = 2974e7801d59Ssowmini "link,policy,addrpolicy,lacpactivity,lacptimer,flags"; 2975e7801d59Ssowmini char *all_lacp_fields = 2976e7801d59Ssowmini "link,port,aggregatable,sync,coll,dist,defaulted,expired"; 2977e7801d59Ssowmini char *all_stats_fields = 2978e7801d59Ssowmini "link,port,ipackets,rbytes,opackets,obytes,ipktdist,opktdist"; 2979e7801d59Ssowmini char *all_extended_fields = 2980e7801d59Ssowmini "link,port,speed,duplex,state,address,portstate"; 29818002d411SSowmini Varadhan ofmt_field_t *pf; 29828002d411SSowmini Varadhan ofmt_handle_t ofmt; 29838002d411SSowmini Varadhan ofmt_status_t oferr; 29848002d411SSowmini Varadhan uint_t ofmtflags = 0; 2985e7801d59Ssowmini 29867c478bd9Sstevel@tonic-gate opterr = 0; 2987e7801d59Ssowmini while ((option = getopt_long(argc, argv, ":LpPxsi:o:", 2988d62bc4baSyz147064 show_lopts, NULL)) != -1) { 29897c478bd9Sstevel@tonic-gate switch (option) { 29907c478bd9Sstevel@tonic-gate case 'L': 299133343a97Smeem if (L_arg) 299233343a97Smeem die_optdup(option); 29937c478bd9Sstevel@tonic-gate 29947c478bd9Sstevel@tonic-gate L_arg = B_TRUE; 29957c478bd9Sstevel@tonic-gate break; 29967c478bd9Sstevel@tonic-gate case 'p': 2997d62bc4baSyz147064 if (p_arg) 2998d62bc4baSyz147064 die_optdup(option); 2999d62bc4baSyz147064 3000d62bc4baSyz147064 p_arg = B_TRUE; 3001d62bc4baSyz147064 break; 3002d62bc4baSyz147064 case 'x': 3003d62bc4baSyz147064 if (x_arg) 3004d62bc4baSyz147064 die_optdup(option); 3005d62bc4baSyz147064 3006d62bc4baSyz147064 x_arg = B_TRUE; 3007d62bc4baSyz147064 break; 3008d62bc4baSyz147064 case 'P': 3009d62bc4baSyz147064 if (flags != DLADM_OPT_ACTIVE) 3010d62bc4baSyz147064 die_optdup(option); 3011d62bc4baSyz147064 3012d62bc4baSyz147064 flags = DLADM_OPT_PERSIST; 30137c478bd9Sstevel@tonic-gate break; 30147c478bd9Sstevel@tonic-gate case 's': 301533343a97Smeem if (s_arg) 301633343a97Smeem die_optdup(option); 30177c478bd9Sstevel@tonic-gate 30187c478bd9Sstevel@tonic-gate s_arg = B_TRUE; 30197c478bd9Sstevel@tonic-gate break; 3020e7801d59Ssowmini case 'o': 3021e7801d59Ssowmini o_arg = B_TRUE; 3022e7801d59Ssowmini fields_str = optarg; 3023e7801d59Ssowmini break; 30247c478bd9Sstevel@tonic-gate case 'i': 302533343a97Smeem if (i_arg) 302633343a97Smeem die_optdup(option); 30277c478bd9Sstevel@tonic-gate 30287c478bd9Sstevel@tonic-gate i_arg = B_TRUE; 302963a6526dSMichael Lim if (!dladm_str2interval(optarg, &interval)) 303033343a97Smeem die("invalid interval value '%s'", optarg); 30317c478bd9Sstevel@tonic-gate break; 30327c478bd9Sstevel@tonic-gate default: 30338d5c46e6Sam223141 die_opterr(optopt, option, use); 303433343a97Smeem break; 30357c478bd9Sstevel@tonic-gate } 30367c478bd9Sstevel@tonic-gate } 30377c478bd9Sstevel@tonic-gate 30380d365605Sschuster if (p_arg && !o_arg) 30390d365605Sschuster die("-p requires -o"); 30400d365605Sschuster 30410d365605Sschuster if (p_arg && strcasecmp(fields_str, "all") == 0) 30420d365605Sschuster die("\"-o all\" is invalid with -p"); 30430d365605Sschuster 304433343a97Smeem if (i_arg && !s_arg) 304533343a97Smeem die("the option -i can be used only with -s"); 30467c478bd9Sstevel@tonic-gate 3047d62bc4baSyz147064 if (s_arg && (L_arg || p_arg || x_arg || flags != DLADM_OPT_ACTIVE)) { 3048d62bc4baSyz147064 die("the option -%c cannot be used with -s", 3049d62bc4baSyz147064 L_arg ? 'L' : (p_arg ? 'p' : (x_arg ? 'x' : 'P'))); 3050d62bc4baSyz147064 } 3051d62bc4baSyz147064 3052d62bc4baSyz147064 if (L_arg && flags != DLADM_OPT_ACTIVE) 3053d62bc4baSyz147064 die("the option -P cannot be used with -L"); 3054d62bc4baSyz147064 3055d62bc4baSyz147064 if (x_arg && (L_arg || flags != DLADM_OPT_ACTIVE)) 3056d62bc4baSyz147064 die("the option -%c cannot be used with -x", L_arg ? 'L' : 'P'); 3057d62bc4baSyz147064 3058d62bc4baSyz147064 /* get aggregation key or aggrname (optional last argument) */ 30597c478bd9Sstevel@tonic-gate if (optind == (argc-1)) { 3060d62bc4baSyz147064 if (!str2int(argv[optind], &key)) { 30614ac67f02SAnurag S. Maskey status = dladm_name2info(handle, argv[optind], 30624ac67f02SAnurag S. Maskey &linkid, NULL, NULL, NULL); 3063d62bc4baSyz147064 } else { 30644ac67f02SAnurag S. Maskey status = dladm_key2linkid(handle, (uint16_t)key, 3065d62bc4baSyz147064 &linkid, DLADM_OPT_ACTIVE); 3066d62bc4baSyz147064 } 3067d62bc4baSyz147064 3068d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 3069d62bc4baSyz147064 die("non-existent aggregation '%s'", argv[optind]); 3070d62bc4baSyz147064 30717c478bd9Sstevel@tonic-gate } else if (optind != argc) { 30727c478bd9Sstevel@tonic-gate usage(); 30737c478bd9Sstevel@tonic-gate } 30747c478bd9Sstevel@tonic-gate 3075d62bc4baSyz147064 bzero(&state, sizeof (state)); 3076d62bc4baSyz147064 state.gs_lacp = L_arg; 3077d62bc4baSyz147064 state.gs_stats = s_arg; 3078d62bc4baSyz147064 state.gs_flags = flags; 30798002d411SSowmini Varadhan state.gs_parsable = p_arg; 3080d62bc4baSyz147064 state.gs_extended = x_arg; 3081d62bc4baSyz147064 3082e7801d59Ssowmini if (!o_arg || (o_arg && strcasecmp(fields_str, "all") == 0)) { 3083e7801d59Ssowmini if (state.gs_lacp) 3084e7801d59Ssowmini fields_str = all_lacp_fields; 3085e7801d59Ssowmini else if (state.gs_stats) 3086e7801d59Ssowmini fields_str = all_stats_fields; 3087e7801d59Ssowmini else if (state.gs_extended) 3088e7801d59Ssowmini fields_str = all_extended_fields; 3089e7801d59Ssowmini else 3090e7801d59Ssowmini fields_str = all_fields; 3091e7801d59Ssowmini } 3092e7801d59Ssowmini 3093e7801d59Ssowmini if (state.gs_lacp) { 3094e7801d59Ssowmini pf = aggr_l_fields; 3095e7801d59Ssowmini } else if (state.gs_stats) { 3096e7801d59Ssowmini pf = aggr_s_fields; 3097e7801d59Ssowmini } else if (state.gs_extended) { 3098e7801d59Ssowmini pf = aggr_x_fields; 3099e7801d59Ssowmini } else { 3100e7801d59Ssowmini pf = laggr_fields; 3101e7801d59Ssowmini } 3102e7801d59Ssowmini 31038002d411SSowmini Varadhan if (state.gs_parsable) 31048002d411SSowmini Varadhan ofmtflags |= OFMT_PARSABLE; 31058002d411SSowmini Varadhan oferr = ofmt_open(fields_str, pf, ofmtflags, 0, &ofmt); 31068002d411SSowmini Varadhan dladm_ofmt_check(oferr, state.gs_parsable, ofmt); 31078002d411SSowmini Varadhan state.gs_ofmt = ofmt; 3108e7801d59Ssowmini 31097c478bd9Sstevel@tonic-gate if (s_arg) { 3110d62bc4baSyz147064 aggr_stats(linkid, &state, interval); 31118002d411SSowmini Varadhan ofmt_close(ofmt); 31127c478bd9Sstevel@tonic-gate return; 31137c478bd9Sstevel@tonic-gate } 31147c478bd9Sstevel@tonic-gate 3115d62bc4baSyz147064 if (linkid == DATALINK_ALL_LINKID) { 31164ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(show_aggr, handle, &state, 3117d62bc4baSyz147064 DATALINK_CLASS_AGGR, DATALINK_ANY_MEDIATYPE, flags); 3118d62bc4baSyz147064 } else { 31194ac67f02SAnurag S. Maskey (void) show_aggr(handle, linkid, &state); 3120d62bc4baSyz147064 if (state.gs_status != DLADM_STATUS_OK) { 3121d62bc4baSyz147064 die_dlerr(state.gs_status, "failed to show aggr %s", 3122d62bc4baSyz147064 argv[optind]); 3123d62bc4baSyz147064 } 3124d62bc4baSyz147064 } 31258002d411SSowmini Varadhan ofmt_close(ofmt); 31267c478bd9Sstevel@tonic-gate } 31277c478bd9Sstevel@tonic-gate 3128da14cebeSEric Cheng static dladm_status_t 3129da14cebeSEric Cheng print_phys_default(show_state_t *state, datalink_id_t linkid, 3130da14cebeSEric Cheng const char *link, uint32_t flags, uint32_t media) 31317c478bd9Sstevel@tonic-gate { 3132da14cebeSEric Cheng dladm_phys_attr_t dpa; 3133da14cebeSEric Cheng dladm_status_t status; 3134da14cebeSEric Cheng link_fields_buf_t pattr; 3135e7801d59Ssowmini 31364ac67f02SAnurag S. Maskey status = dladm_phys_info(handle, linkid, &dpa, state->ls_flags); 3137da14cebeSEric Cheng if (status != DLADM_STATUS_OK) 3138da14cebeSEric Cheng goto done; 31397c478bd9Sstevel@tonic-gate 3140da14cebeSEric Cheng (void) snprintf(pattr.link_phys_device, 3141da14cebeSEric Cheng sizeof (pattr.link_phys_device), "%s", dpa.dp_dev); 3142da14cebeSEric Cheng (void) dladm_media2str(media, pattr.link_phys_media); 3143da14cebeSEric Cheng if (state->ls_flags == DLADM_OPT_ACTIVE) { 3144da14cebeSEric Cheng boolean_t islink; 3145d62bc4baSyz147064 3146da14cebeSEric Cheng if (!dpa.dp_novanity) { 3147da14cebeSEric Cheng (void) strlcpy(pattr.link_name, link, 3148da14cebeSEric Cheng sizeof (pattr.link_name)); 3149da14cebeSEric Cheng islink = B_TRUE; 3150d62bc4baSyz147064 } else { 3151da14cebeSEric Cheng /* 3152da14cebeSEric Cheng * This is a physical link that does not have 3153da14cebeSEric Cheng * vanity naming support. 3154da14cebeSEric Cheng */ 3155da14cebeSEric Cheng (void) strlcpy(pattr.link_name, dpa.dp_dev, 3156da14cebeSEric Cheng sizeof (pattr.link_name)); 3157da14cebeSEric Cheng islink = B_FALSE; 31587c478bd9Sstevel@tonic-gate } 31597c478bd9Sstevel@tonic-gate 3160da14cebeSEric Cheng (void) get_linkstate(pattr.link_name, islink, 3161da14cebeSEric Cheng pattr.link_phys_state); 3162da14cebeSEric Cheng (void) snprintf(pattr.link_phys_speed, 3163da14cebeSEric Cheng sizeof (pattr.link_phys_speed), "%u", 3164da14cebeSEric Cheng (uint_t)((get_ifspeed(pattr.link_name, 3165da14cebeSEric Cheng islink)) / 1000000ull)); 3166da14cebeSEric Cheng (void) get_linkduplex(pattr.link_name, islink, 3167da14cebeSEric Cheng pattr.link_phys_duplex); 3168da14cebeSEric Cheng } else { 3169da14cebeSEric Cheng (void) snprintf(pattr.link_name, sizeof (pattr.link_name), 3170da14cebeSEric Cheng "%s", link); 3171da14cebeSEric Cheng (void) snprintf(pattr.link_flags, sizeof (pattr.link_flags), 3172da14cebeSEric Cheng "%c----", flags & DLADM_OPT_ACTIVE ? '-' : 'r'); 3173da14cebeSEric Cheng } 3174da14cebeSEric Cheng 31758002d411SSowmini Varadhan ofmt_print(state->ls_ofmt, &pattr); 3176da14cebeSEric Cheng 3177da14cebeSEric Cheng done: 3178da14cebeSEric Cheng return (status); 3179da14cebeSEric Cheng } 3180da14cebeSEric Cheng 3181da14cebeSEric Cheng typedef struct { 3182da14cebeSEric Cheng show_state_t *ms_state; 3183da14cebeSEric Cheng char *ms_link; 3184da14cebeSEric Cheng dladm_macaddr_attr_t *ms_mac_attr; 3185da14cebeSEric Cheng } print_phys_mac_state_t; 3186da14cebeSEric Cheng 31878002d411SSowmini Varadhan /* 31888002d411SSowmini Varadhan * callback for ofmt_print() 31898002d411SSowmini Varadhan */ 31908002d411SSowmini Varadhan static boolean_t 31918002d411SSowmini Varadhan print_phys_one_mac_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize) 3192da14cebeSEric Cheng { 31938002d411SSowmini Varadhan print_phys_mac_state_t *mac_state = ofarg->ofmt_cbarg; 3194da14cebeSEric Cheng dladm_macaddr_attr_t *attr = mac_state->ms_mac_attr; 3195da14cebeSEric Cheng boolean_t is_primary = (attr->ma_slot == 0); 31968002d411SSowmini Varadhan boolean_t is_parsable = mac_state->ms_state->ls_parsable; 3197da14cebeSEric Cheng 31988002d411SSowmini Varadhan switch (ofarg->ofmt_id) { 3199da14cebeSEric Cheng case PHYS_M_LINK: 32008002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%s", 32018002d411SSowmini Varadhan (is_primary || is_parsable) ? mac_state->ms_link : " "); 3202da14cebeSEric Cheng break; 3203da14cebeSEric Cheng case PHYS_M_SLOT: 3204da14cebeSEric Cheng if (is_primary) 32058002d411SSowmini Varadhan (void) snprintf(buf, bufsize, gettext("primary")); 3206da14cebeSEric Cheng else 32078002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%d", attr->ma_slot); 3208da14cebeSEric Cheng break; 3209da14cebeSEric Cheng case PHYS_M_ADDRESS: 3210da14cebeSEric Cheng (void) dladm_aggr_macaddr2str(attr->ma_addr, buf); 3211da14cebeSEric Cheng break; 3212da14cebeSEric Cheng case PHYS_M_INUSE: 32138002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%s", 3214da14cebeSEric Cheng attr->ma_flags & DLADM_MACADDR_USED ? gettext("yes") : 3215da14cebeSEric Cheng gettext("no")); 3216da14cebeSEric Cheng break; 3217da14cebeSEric Cheng case PHYS_M_CLIENT: 3218da14cebeSEric Cheng /* 3219da14cebeSEric Cheng * CR 6678526: resolve link id to actual link name if 3220da14cebeSEric Cheng * it is valid. 3221da14cebeSEric Cheng */ 32228002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%s", attr->ma_client_name); 3223da14cebeSEric Cheng break; 3224da14cebeSEric Cheng } 3225da14cebeSEric Cheng 32268002d411SSowmini Varadhan return (B_TRUE); 3227da14cebeSEric Cheng } 3228da14cebeSEric Cheng 3229da14cebeSEric Cheng typedef struct { 3230da14cebeSEric Cheng show_state_t *hs_state; 3231da14cebeSEric Cheng char *hs_link; 3232da14cebeSEric Cheng dladm_hwgrp_attr_t *hs_grp_attr; 3233da14cebeSEric Cheng } print_phys_hwgrp_state_t; 3234da14cebeSEric Cheng 32358002d411SSowmini Varadhan static boolean_t 32368002d411SSowmini Varadhan print_phys_one_hwgrp_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize) 3237da14cebeSEric Cheng { 32388002d411SSowmini Varadhan print_phys_hwgrp_state_t *hg_state = ofarg->ofmt_cbarg; 3239da14cebeSEric Cheng dladm_hwgrp_attr_t *attr = hg_state->hs_grp_attr; 3240da14cebeSEric Cheng 32418002d411SSowmini Varadhan switch (ofarg->ofmt_id) { 3242da14cebeSEric Cheng case PHYS_H_LINK: 32438002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%s", attr->hg_link_name); 3244da14cebeSEric Cheng break; 3245da14cebeSEric Cheng case PHYS_H_GROUP: 32468002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%d", attr->hg_grp_num); 3247da14cebeSEric Cheng break; 3248da14cebeSEric Cheng case PHYS_H_GRPTYPE: 32498002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%s", 3250da14cebeSEric Cheng attr->hg_grp_type == DLADM_HWGRP_TYPE_RX ? "RX" : "TX"); 3251da14cebeSEric Cheng break; 3252da14cebeSEric Cheng case PHYS_H_RINGS: 32538002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%d", attr->hg_n_rings); 3254da14cebeSEric Cheng break; 3255da14cebeSEric Cheng case PHYS_H_CLIENTS: 3256da14cebeSEric Cheng if (attr->hg_client_names[0] == '\0') { 32578002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "--"); 3258da14cebeSEric Cheng } else { 32598002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%s ", 3260da14cebeSEric Cheng attr->hg_client_names); 3261da14cebeSEric Cheng } 3262da14cebeSEric Cheng break; 3263da14cebeSEric Cheng } 3264da14cebeSEric Cheng 32658002d411SSowmini Varadhan return (B_TRUE); 3266da14cebeSEric Cheng } 3267da14cebeSEric Cheng 32688002d411SSowmini Varadhan /* 32698002d411SSowmini Varadhan * callback for dladm_walk_macaddr, invoked for each MAC address slot 32708002d411SSowmini Varadhan */ 3271da14cebeSEric Cheng static boolean_t 3272da14cebeSEric Cheng print_phys_mac_callback(void *arg, dladm_macaddr_attr_t *attr) 3273da14cebeSEric Cheng { 3274da14cebeSEric Cheng print_phys_mac_state_t *mac_state = arg; 3275da14cebeSEric Cheng show_state_t *state = mac_state->ms_state; 3276da14cebeSEric Cheng 3277da14cebeSEric Cheng mac_state->ms_mac_attr = attr; 32788002d411SSowmini Varadhan ofmt_print(state->ls_ofmt, mac_state); 3279da14cebeSEric Cheng 3280da14cebeSEric Cheng return (B_TRUE); 3281da14cebeSEric Cheng } 3282da14cebeSEric Cheng 32838002d411SSowmini Varadhan /* 32848002d411SSowmini Varadhan * invoked by show-phys -m for each physical data-link 32858002d411SSowmini Varadhan */ 3286da14cebeSEric Cheng static dladm_status_t 3287da14cebeSEric Cheng print_phys_mac(show_state_t *state, datalink_id_t linkid, char *link) 3288da14cebeSEric Cheng { 3289da14cebeSEric Cheng print_phys_mac_state_t mac_state; 3290da14cebeSEric Cheng 3291da14cebeSEric Cheng mac_state.ms_state = state; 3292da14cebeSEric Cheng mac_state.ms_link = link; 3293da14cebeSEric Cheng 32944ac67f02SAnurag S. Maskey return (dladm_walk_macaddr(handle, linkid, &mac_state, 3295da14cebeSEric Cheng print_phys_mac_callback)); 3296da14cebeSEric Cheng } 3297da14cebeSEric Cheng 32988002d411SSowmini Varadhan /* 32998002d411SSowmini Varadhan * callback for dladm_walk_hwgrp, invoked for each MAC hwgrp 33008002d411SSowmini Varadhan */ 3301da14cebeSEric Cheng static boolean_t 3302da14cebeSEric Cheng print_phys_hwgrp_callback(void *arg, dladm_hwgrp_attr_t *attr) 3303da14cebeSEric Cheng { 3304da14cebeSEric Cheng print_phys_hwgrp_state_t *hwgrp_state = arg; 3305da14cebeSEric Cheng show_state_t *state = hwgrp_state->hs_state; 3306da14cebeSEric Cheng 3307da14cebeSEric Cheng hwgrp_state->hs_grp_attr = attr; 33088002d411SSowmini Varadhan ofmt_print(state->ls_ofmt, hwgrp_state); 3309da14cebeSEric Cheng 3310da14cebeSEric Cheng return (B_TRUE); 3311da14cebeSEric Cheng } 3312da14cebeSEric Cheng 3313da14cebeSEric Cheng /* invoked by show-phys -H for each physical data-link */ 3314da14cebeSEric Cheng static dladm_status_t 3315da14cebeSEric Cheng print_phys_hwgrp(show_state_t *state, datalink_id_t linkid, char *link) 3316da14cebeSEric Cheng { 3317da14cebeSEric Cheng print_phys_hwgrp_state_t hwgrp_state; 3318da14cebeSEric Cheng 3319da14cebeSEric Cheng hwgrp_state.hs_state = state; 3320da14cebeSEric Cheng hwgrp_state.hs_link = link; 33214ac67f02SAnurag S. Maskey return (dladm_walk_hwgrp(handle, linkid, &hwgrp_state, 3322da14cebeSEric Cheng print_phys_hwgrp_callback)); 3323da14cebeSEric Cheng } 3324d62bc4baSyz147064 3325d62bc4baSyz147064 static dladm_status_t 3326da14cebeSEric Cheng print_phys(show_state_t *state, datalink_id_t linkid) 3327d62bc4baSyz147064 { 3328d62bc4baSyz147064 char link[MAXLINKNAMELEN]; 3329d62bc4baSyz147064 uint32_t flags; 3330da14cebeSEric Cheng dladm_status_t status; 3331d62bc4baSyz147064 datalink_class_t class; 3332d62bc4baSyz147064 uint32_t media; 3333d62bc4baSyz147064 33344ac67f02SAnurag S. Maskey if ((status = dladm_datalink_id2info(handle, linkid, &flags, &class, 33354ac67f02SAnurag S. Maskey &media, link, MAXLINKNAMELEN)) != DLADM_STATUS_OK) { 3336d62bc4baSyz147064 goto done; 3337d62bc4baSyz147064 } 3338d62bc4baSyz147064 3339d62bc4baSyz147064 if (class != DATALINK_CLASS_PHYS) { 3340d62bc4baSyz147064 status = DLADM_STATUS_BADARG; 3341d62bc4baSyz147064 goto done; 3342d62bc4baSyz147064 } 3343d62bc4baSyz147064 3344d62bc4baSyz147064 if (!(state->ls_flags & flags)) { 3345d62bc4baSyz147064 status = DLADM_STATUS_NOTFOUND; 3346d62bc4baSyz147064 goto done; 3347d62bc4baSyz147064 } 3348d62bc4baSyz147064 3349da14cebeSEric Cheng if (state->ls_mac) 3350da14cebeSEric Cheng status = print_phys_mac(state, linkid, link); 3351da14cebeSEric Cheng else if (state->ls_hwgrp) 3352da14cebeSEric Cheng status = print_phys_hwgrp(state, linkid, link); 3353da14cebeSEric Cheng else 3354da14cebeSEric Cheng status = print_phys_default(state, linkid, link, flags, media); 3355d62bc4baSyz147064 3356d62bc4baSyz147064 done: 3357d62bc4baSyz147064 return (status); 3358d62bc4baSyz147064 } 3359d62bc4baSyz147064 33604ac67f02SAnurag S. Maskey /* ARGSUSED */ 3361d62bc4baSyz147064 static int 33624ac67f02SAnurag S. Maskey show_phys(dladm_handle_t dh, datalink_id_t linkid, void *arg) 3363d62bc4baSyz147064 { 3364d62bc4baSyz147064 show_state_t *state = arg; 3365d62bc4baSyz147064 3366da14cebeSEric Cheng state->ls_status = print_phys(state, linkid); 3367d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 3368d62bc4baSyz147064 } 3369d62bc4baSyz147064 3370d62bc4baSyz147064 /* 3371d62bc4baSyz147064 * Print the active topology information. 3372d62bc4baSyz147064 */ 3373d62bc4baSyz147064 static dladm_status_t 3374e7801d59Ssowmini print_vlan(show_state_t *state, datalink_id_t linkid, link_fields_buf_t *l) 3375d62bc4baSyz147064 { 3376d62bc4baSyz147064 dladm_vlan_attr_t vinfo; 3377d62bc4baSyz147064 uint32_t flags; 3378d62bc4baSyz147064 dladm_status_t status; 3379d62bc4baSyz147064 33804ac67f02SAnurag S. Maskey if ((status = dladm_datalink_id2info(handle, linkid, &flags, NULL, NULL, 3381e7801d59Ssowmini l->link_name, sizeof (l->link_name))) != DLADM_STATUS_OK) { 3382d62bc4baSyz147064 goto done; 3383d62bc4baSyz147064 } 3384d62bc4baSyz147064 3385d62bc4baSyz147064 if (!(state->ls_flags & flags)) { 3386d62bc4baSyz147064 status = DLADM_STATUS_NOTFOUND; 3387d62bc4baSyz147064 goto done; 3388d62bc4baSyz147064 } 3389d62bc4baSyz147064 33904ac67f02SAnurag S. Maskey if ((status = dladm_vlan_info(handle, linkid, &vinfo, 33914ac67f02SAnurag S. Maskey state->ls_flags)) != DLADM_STATUS_OK || 33924ac67f02SAnurag S. Maskey (status = dladm_datalink_id2info(handle, vinfo.dv_linkid, NULL, 33934ac67f02SAnurag S. Maskey NULL, NULL, l->link_over, sizeof (l->link_over))) != 33944ac67f02SAnurag S. Maskey DLADM_STATUS_OK) { 3395d62bc4baSyz147064 goto done; 3396d62bc4baSyz147064 } 3397d62bc4baSyz147064 3398e7801d59Ssowmini (void) snprintf(l->link_vlan_vid, sizeof (l->link_vlan_vid), "%d", 3399e7801d59Ssowmini vinfo.dv_vid); 3400da14cebeSEric Cheng (void) snprintf(l->link_flags, sizeof (l->link_flags), "%c----", 3401da14cebeSEric Cheng vinfo.dv_force ? 'f' : '-'); 3402d62bc4baSyz147064 3403d62bc4baSyz147064 done: 3404d62bc4baSyz147064 return (status); 3405d62bc4baSyz147064 } 3406d62bc4baSyz147064 34074ac67f02SAnurag S. Maskey /* ARGSUSED */ 3408d62bc4baSyz147064 static int 34094ac67f02SAnurag S. Maskey show_vlan(dladm_handle_t dh, datalink_id_t linkid, void *arg) 3410d62bc4baSyz147064 { 3411d62bc4baSyz147064 show_state_t *state = arg; 3412d62bc4baSyz147064 dladm_status_t status; 3413e7801d59Ssowmini link_fields_buf_t lbuf; 3414d62bc4baSyz147064 34155f5c9f54SAnurag S. Maskey bzero(&lbuf, sizeof (link_fields_buf_t)); 3416e7801d59Ssowmini status = print_vlan(state, linkid, &lbuf); 3417d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 3418d62bc4baSyz147064 goto done; 3419e7801d59Ssowmini 34208002d411SSowmini Varadhan ofmt_print(state->ls_ofmt, &lbuf); 3421d62bc4baSyz147064 3422d62bc4baSyz147064 done: 3423d62bc4baSyz147064 state->ls_status = status; 3424d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 3425d62bc4baSyz147064 } 3426d62bc4baSyz147064 3427d62bc4baSyz147064 static void 34288d5c46e6Sam223141 do_show_phys(int argc, char *argv[], const char *use) 3429d62bc4baSyz147064 { 3430d62bc4baSyz147064 int option; 3431d62bc4baSyz147064 uint32_t flags = DLADM_OPT_ACTIVE; 3432d62bc4baSyz147064 boolean_t p_arg = B_FALSE; 3433e7801d59Ssowmini boolean_t o_arg = B_FALSE; 3434da14cebeSEric Cheng boolean_t m_arg = B_FALSE; 3435da14cebeSEric Cheng boolean_t H_arg = B_FALSE; 3436d62bc4baSyz147064 datalink_id_t linkid = DATALINK_ALL_LINKID; 3437d62bc4baSyz147064 show_state_t state; 3438d62bc4baSyz147064 dladm_status_t status; 3439e7801d59Ssowmini char *fields_str = NULL; 3440e7801d59Ssowmini char *all_active_fields = 3441e7801d59Ssowmini "link,media,state,speed,duplex,device"; 34425f5c9f54SAnurag S. Maskey char *all_inactive_fields = "link,device,media,flags"; 3443da14cebeSEric Cheng char *all_mac_fields = "link,slot,address,inuse,client"; 3444da14cebeSEric Cheng char *all_hwgrp_fields = 3445da14cebeSEric Cheng "link,group,grouptype,rings,clients"; 34468002d411SSowmini Varadhan ofmt_field_t *pf; 34478002d411SSowmini Varadhan ofmt_handle_t ofmt; 34488002d411SSowmini Varadhan ofmt_status_t oferr; 34498002d411SSowmini Varadhan uint_t ofmtflags = 0; 3450d62bc4baSyz147064 3451e7801d59Ssowmini bzero(&state, sizeof (state)); 3452d62bc4baSyz147064 opterr = 0; 3453da14cebeSEric Cheng while ((option = getopt_long(argc, argv, ":pPo:mH", 3454d62bc4baSyz147064 show_lopts, NULL)) != -1) { 3455d62bc4baSyz147064 switch (option) { 3456d62bc4baSyz147064 case 'p': 3457d62bc4baSyz147064 if (p_arg) 3458d62bc4baSyz147064 die_optdup(option); 3459d62bc4baSyz147064 3460d62bc4baSyz147064 p_arg = B_TRUE; 3461d62bc4baSyz147064 break; 3462d62bc4baSyz147064 case 'P': 3463d62bc4baSyz147064 if (flags != DLADM_OPT_ACTIVE) 3464d62bc4baSyz147064 die_optdup(option); 3465d62bc4baSyz147064 3466d62bc4baSyz147064 flags = DLADM_OPT_PERSIST; 3467d62bc4baSyz147064 break; 3468e7801d59Ssowmini case 'o': 3469e7801d59Ssowmini o_arg = B_TRUE; 3470e7801d59Ssowmini fields_str = optarg; 3471e7801d59Ssowmini break; 3472da14cebeSEric Cheng case 'm': 3473da14cebeSEric Cheng m_arg = B_TRUE; 3474da14cebeSEric Cheng break; 3475da14cebeSEric Cheng case 'H': 3476da14cebeSEric Cheng H_arg = B_TRUE; 3477da14cebeSEric Cheng break; 3478d62bc4baSyz147064 default: 34798d5c46e6Sam223141 die_opterr(optopt, option, use); 3480d62bc4baSyz147064 break; 3481d62bc4baSyz147064 } 3482d62bc4baSyz147064 } 3483d62bc4baSyz147064 34840d365605Sschuster if (p_arg && !o_arg) 34850d365605Sschuster die("-p requires -o"); 34860d365605Sschuster 3487da14cebeSEric Cheng if (m_arg && H_arg) 3488da14cebeSEric Cheng die("-m cannot combine with -H"); 3489da14cebeSEric Cheng 34900d365605Sschuster if (p_arg && strcasecmp(fields_str, "all") == 0) 34910d365605Sschuster die("\"-o all\" is invalid with -p"); 34920d365605Sschuster 3493d62bc4baSyz147064 /* get link name (optional last argument) */ 3494d62bc4baSyz147064 if (optind == (argc-1)) { 34954ac67f02SAnurag S. Maskey if ((status = dladm_name2info(handle, argv[optind], &linkid, 34964ac67f02SAnurag S. Maskey NULL, NULL, NULL)) != DLADM_STATUS_OK) { 3497d62bc4baSyz147064 die_dlerr(status, "link %s is not valid", argv[optind]); 3498d62bc4baSyz147064 } 3499d62bc4baSyz147064 } else if (optind != argc) { 3500d62bc4baSyz147064 usage(); 3501d62bc4baSyz147064 } 3502d62bc4baSyz147064 35038002d411SSowmini Varadhan state.ls_parsable = p_arg; 3504d62bc4baSyz147064 state.ls_flags = flags; 3505d62bc4baSyz147064 state.ls_donefirst = B_FALSE; 3506da14cebeSEric Cheng state.ls_mac = m_arg; 3507da14cebeSEric Cheng state.ls_hwgrp = H_arg; 3508d62bc4baSyz147064 3509da14cebeSEric Cheng if (m_arg && !(flags & DLADM_OPT_ACTIVE)) { 3510da14cebeSEric Cheng /* 3511da14cebeSEric Cheng * We can only display the factory MAC addresses of 3512da14cebeSEric Cheng * active data-links. 3513da14cebeSEric Cheng */ 3514da14cebeSEric Cheng die("-m not compatible with -P"); 3515e7801d59Ssowmini } 3516e7801d59Ssowmini 3517da14cebeSEric Cheng if (!o_arg || (o_arg && strcasecmp(fields_str, "all") == 0)) { 3518da14cebeSEric Cheng if (state.ls_mac) 3519da14cebeSEric Cheng fields_str = all_mac_fields; 3520da14cebeSEric Cheng else if (state.ls_hwgrp) 3521da14cebeSEric Cheng fields_str = all_hwgrp_fields; 3522da14cebeSEric Cheng else if (state.ls_flags & DLADM_OPT_ACTIVE) { 3523da14cebeSEric Cheng fields_str = all_active_fields; 3524da14cebeSEric Cheng } else { 3525da14cebeSEric Cheng fields_str = all_inactive_fields; 3526da14cebeSEric Cheng } 3527da14cebeSEric Cheng } 3528da14cebeSEric Cheng 3529da14cebeSEric Cheng if (state.ls_mac) { 3530da14cebeSEric Cheng pf = phys_m_fields; 3531da14cebeSEric Cheng } else if (state.ls_hwgrp) { 3532da14cebeSEric Cheng pf = phys_h_fields; 3533da14cebeSEric Cheng } else { 3534da14cebeSEric Cheng pf = phys_fields; 3535da14cebeSEric Cheng } 3536da14cebeSEric Cheng 35378002d411SSowmini Varadhan if (state.ls_parsable) 35388002d411SSowmini Varadhan ofmtflags |= OFMT_PARSABLE; 35398002d411SSowmini Varadhan oferr = ofmt_open(fields_str, pf, ofmtflags, 0, &ofmt); 35408002d411SSowmini Varadhan dladm_ofmt_check(oferr, state.ls_parsable, ofmt); 35418002d411SSowmini Varadhan state.ls_ofmt = ofmt; 3542e7801d59Ssowmini 3543d62bc4baSyz147064 if (linkid == DATALINK_ALL_LINKID) { 35444ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(show_phys, handle, &state, 3545d62bc4baSyz147064 DATALINK_CLASS_PHYS, DATALINK_ANY_MEDIATYPE, flags); 3546d62bc4baSyz147064 } else { 35474ac67f02SAnurag S. Maskey (void) show_phys(handle, linkid, &state); 3548d62bc4baSyz147064 if (state.ls_status != DLADM_STATUS_OK) { 3549d62bc4baSyz147064 die_dlerr(state.ls_status, 3550d62bc4baSyz147064 "failed to show physical link %s", argv[optind]); 3551d62bc4baSyz147064 } 3552d62bc4baSyz147064 } 35538002d411SSowmini Varadhan ofmt_close(ofmt); 3554d62bc4baSyz147064 } 3555d62bc4baSyz147064 3556d62bc4baSyz147064 static void 35578d5c46e6Sam223141 do_show_vlan(int argc, char *argv[], const char *use) 3558d62bc4baSyz147064 { 3559d62bc4baSyz147064 int option; 3560d62bc4baSyz147064 uint32_t flags = DLADM_OPT_ACTIVE; 3561d62bc4baSyz147064 boolean_t p_arg = B_FALSE; 3562d62bc4baSyz147064 datalink_id_t linkid = DATALINK_ALL_LINKID; 3563d62bc4baSyz147064 show_state_t state; 3564d62bc4baSyz147064 dladm_status_t status; 3565e7801d59Ssowmini boolean_t o_arg = B_FALSE; 3566e7801d59Ssowmini char *fields_str = NULL; 35678002d411SSowmini Varadhan ofmt_handle_t ofmt; 35688002d411SSowmini Varadhan ofmt_status_t oferr; 35698002d411SSowmini Varadhan uint_t ofmtflags = 0; 3570e7801d59Ssowmini 3571e7801d59Ssowmini bzero(&state, sizeof (state)); 3572d62bc4baSyz147064 3573d62bc4baSyz147064 opterr = 0; 3574e7801d59Ssowmini while ((option = getopt_long(argc, argv, ":pPo:", 3575d62bc4baSyz147064 show_lopts, NULL)) != -1) { 3576d62bc4baSyz147064 switch (option) { 3577d62bc4baSyz147064 case 'p': 3578d62bc4baSyz147064 if (p_arg) 3579d62bc4baSyz147064 die_optdup(option); 3580d62bc4baSyz147064 3581d62bc4baSyz147064 p_arg = B_TRUE; 3582d62bc4baSyz147064 break; 3583d62bc4baSyz147064 case 'P': 3584d62bc4baSyz147064 if (flags != DLADM_OPT_ACTIVE) 3585d62bc4baSyz147064 die_optdup(option); 3586d62bc4baSyz147064 3587d62bc4baSyz147064 flags = DLADM_OPT_PERSIST; 3588d62bc4baSyz147064 break; 3589e7801d59Ssowmini case 'o': 3590e7801d59Ssowmini o_arg = B_TRUE; 3591e7801d59Ssowmini fields_str = optarg; 3592e7801d59Ssowmini break; 3593d62bc4baSyz147064 default: 35948d5c46e6Sam223141 die_opterr(optopt, option, use); 3595d62bc4baSyz147064 break; 3596d62bc4baSyz147064 } 3597d62bc4baSyz147064 } 3598d62bc4baSyz147064 3599d62bc4baSyz147064 /* get link name (optional last argument) */ 3600d62bc4baSyz147064 if (optind == (argc-1)) { 36014ac67f02SAnurag S. Maskey if ((status = dladm_name2info(handle, argv[optind], &linkid, 36024ac67f02SAnurag S. Maskey NULL, NULL, NULL)) != DLADM_STATUS_OK) { 3603d62bc4baSyz147064 die_dlerr(status, "link %s is not valid", argv[optind]); 3604d62bc4baSyz147064 } 3605d62bc4baSyz147064 } else if (optind != argc) { 3606d62bc4baSyz147064 usage(); 3607d62bc4baSyz147064 } 3608d62bc4baSyz147064 36098002d411SSowmini Varadhan state.ls_parsable = p_arg; 3610d62bc4baSyz147064 state.ls_flags = flags; 3611d62bc4baSyz147064 state.ls_donefirst = B_FALSE; 3612d62bc4baSyz147064 3613e7801d59Ssowmini if (!o_arg || (o_arg && strcasecmp(fields_str, "all") == 0)) 36148002d411SSowmini Varadhan fields_str = NULL; 3615e7801d59Ssowmini 36168002d411SSowmini Varadhan if (state.ls_parsable) 36178002d411SSowmini Varadhan ofmtflags |= OFMT_PARSABLE; 36188002d411SSowmini Varadhan oferr = ofmt_open(fields_str, vlan_fields, ofmtflags, 0, &ofmt); 36198002d411SSowmini Varadhan dladm_ofmt_check(oferr, state.ls_parsable, ofmt); 36208002d411SSowmini Varadhan state.ls_ofmt = ofmt; 3621e7801d59Ssowmini 3622d62bc4baSyz147064 if (linkid == DATALINK_ALL_LINKID) { 36234ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(show_vlan, handle, &state, 3624d62bc4baSyz147064 DATALINK_CLASS_VLAN, DATALINK_ANY_MEDIATYPE, flags); 3625d62bc4baSyz147064 } else { 36264ac67f02SAnurag S. Maskey (void) show_vlan(handle, linkid, &state); 3627d62bc4baSyz147064 if (state.ls_status != DLADM_STATUS_OK) { 3628d62bc4baSyz147064 die_dlerr(state.ls_status, "failed to show vlan %s", 3629d62bc4baSyz147064 argv[optind]); 3630d62bc4baSyz147064 } 3631d62bc4baSyz147064 } 36328002d411SSowmini Varadhan ofmt_close(ofmt); 3633d62bc4baSyz147064 } 3634d62bc4baSyz147064 3635d62bc4baSyz147064 static void 3636da14cebeSEric Cheng do_create_vnic(int argc, char *argv[], const char *use) 3637da14cebeSEric Cheng { 3638da14cebeSEric Cheng datalink_id_t linkid, dev_linkid; 3639da14cebeSEric Cheng char devname[MAXLINKNAMELEN]; 3640da14cebeSEric Cheng char name[MAXLINKNAMELEN]; 3641da14cebeSEric Cheng boolean_t l_arg = B_FALSE; 3642da14cebeSEric Cheng uint32_t flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST; 3643da14cebeSEric Cheng char *altroot = NULL; 3644da14cebeSEric Cheng char option; 3645da14cebeSEric Cheng char *endp = NULL; 3646da14cebeSEric Cheng dladm_status_t status; 3647da14cebeSEric Cheng vnic_mac_addr_type_t mac_addr_type = VNIC_MAC_ADDR_TYPE_AUTO; 3648da14cebeSEric Cheng uchar_t *mac_addr; 3649da14cebeSEric Cheng int mac_slot = -1, maclen = 0, mac_prefix_len = 0; 365063a6526dSMichael Lim char propstr[DLADM_STRSIZE]; 3651da14cebeSEric Cheng dladm_arg_list_t *proplist = NULL; 3652285e94f9SMichael Lim int vid = 0; 3653da14cebeSEric Cheng 3654da14cebeSEric Cheng opterr = 0; 365563a6526dSMichael Lim bzero(propstr, DLADM_STRSIZE); 365663a6526dSMichael Lim 3657da14cebeSEric Cheng while ((option = getopt_long(argc, argv, ":tfR:l:m:n:p:r:v:H", 3658da14cebeSEric Cheng vnic_lopts, NULL)) != -1) { 3659da14cebeSEric Cheng switch (option) { 3660da14cebeSEric Cheng case 't': 3661da14cebeSEric Cheng flags &= ~DLADM_OPT_PERSIST; 3662da14cebeSEric Cheng break; 3663da14cebeSEric Cheng case 'R': 3664da14cebeSEric Cheng altroot = optarg; 3665da14cebeSEric Cheng break; 3666da14cebeSEric Cheng case 'l': 3667da14cebeSEric Cheng if (strlcpy(devname, optarg, MAXLINKNAMELEN) >= 3668da14cebeSEric Cheng MAXLINKNAMELEN) 3669da14cebeSEric Cheng die("link name too long"); 3670da14cebeSEric Cheng l_arg = B_TRUE; 3671da14cebeSEric Cheng break; 3672da14cebeSEric Cheng case 'm': 3673da14cebeSEric Cheng if (strcmp(optarg, "fixed") == 0) { 3674da14cebeSEric Cheng /* 3675da14cebeSEric Cheng * A fixed MAC address must be specified 3676da14cebeSEric Cheng * by its value, not by the keyword 'fixed'. 3677da14cebeSEric Cheng */ 3678da14cebeSEric Cheng die("'fixed' is not a valid MAC address"); 3679da14cebeSEric Cheng } 3680da14cebeSEric Cheng if (dladm_vnic_str2macaddrtype(optarg, 3681da14cebeSEric Cheng &mac_addr_type) != DLADM_STATUS_OK) { 3682da14cebeSEric Cheng mac_addr_type = VNIC_MAC_ADDR_TYPE_FIXED; 3683da14cebeSEric Cheng /* MAC address specified by value */ 3684da14cebeSEric Cheng mac_addr = _link_aton(optarg, &maclen); 3685da14cebeSEric Cheng if (mac_addr == NULL) { 3686da14cebeSEric Cheng if (maclen == -1) 3687da14cebeSEric Cheng die("invalid MAC address"); 3688da14cebeSEric Cheng else 3689da14cebeSEric Cheng die("out of memory"); 3690da14cebeSEric Cheng } 3691da14cebeSEric Cheng } 3692da14cebeSEric Cheng break; 3693da14cebeSEric Cheng case 'n': 3694da14cebeSEric Cheng errno = 0; 3695da14cebeSEric Cheng mac_slot = (int)strtol(optarg, &endp, 10); 3696da14cebeSEric Cheng if (errno != 0 || *endp != '\0') 3697da14cebeSEric Cheng die("invalid slot number"); 3698da14cebeSEric Cheng break; 3699da14cebeSEric Cheng case 'p': 370063a6526dSMichael Lim (void) strlcat(propstr, optarg, DLADM_STRSIZE); 370163a6526dSMichael Lim if (strlcat(propstr, ",", DLADM_STRSIZE) >= 370263a6526dSMichael Lim DLADM_STRSIZE) 370363a6526dSMichael Lim die("property list too long '%s'", propstr); 3704da14cebeSEric Cheng break; 3705da14cebeSEric Cheng case 'r': 3706da14cebeSEric Cheng mac_addr = _link_aton(optarg, &mac_prefix_len); 3707da14cebeSEric Cheng if (mac_addr == NULL) { 3708da14cebeSEric Cheng if (mac_prefix_len == -1) 3709da14cebeSEric Cheng die("invalid MAC address"); 3710da14cebeSEric Cheng else 3711da14cebeSEric Cheng die("out of memory"); 3712da14cebeSEric Cheng } 3713da14cebeSEric Cheng break; 3714da14cebeSEric Cheng case 'v': 3715285e94f9SMichael Lim if (vid != 0) 3716285e94f9SMichael Lim die_optdup(option); 3717285e94f9SMichael Lim 3718285e94f9SMichael Lim if (!str2int(optarg, &vid) || vid < 1 || vid > 4094) 3719285e94f9SMichael Lim die("invalid VLAN identifier '%s'", optarg); 3720285e94f9SMichael Lim 3721da14cebeSEric Cheng break; 3722da14cebeSEric Cheng case 'f': 3723da14cebeSEric Cheng flags |= DLADM_OPT_FORCE; 3724da14cebeSEric Cheng break; 3725da14cebeSEric Cheng case 'H': 3726da14cebeSEric Cheng flags |= DLADM_OPT_HWRINGS; 3727da14cebeSEric Cheng break; 3728da14cebeSEric Cheng default: 3729da14cebeSEric Cheng die_opterr(optopt, option, use); 3730da14cebeSEric Cheng } 3731da14cebeSEric Cheng } 3732da14cebeSEric Cheng 3733da14cebeSEric Cheng /* 3734da14cebeSEric Cheng * 'f' - force, flag can be specified only with 'v' - vlan. 3735da14cebeSEric Cheng */ 3736da14cebeSEric Cheng if ((flags & DLADM_OPT_FORCE) != 0 && vid == 0) 3737da14cebeSEric Cheng die("-f option can only be used with -v"); 3738da14cebeSEric Cheng 3739da14cebeSEric Cheng if (mac_prefix_len != 0 && mac_addr_type != VNIC_MAC_ADDR_TYPE_RANDOM && 3740da14cebeSEric Cheng mac_addr_type != VNIC_MAC_ADDR_TYPE_FIXED) 3741da14cebeSEric Cheng usage(); 3742da14cebeSEric Cheng 3743da14cebeSEric Cheng /* check required options */ 3744da14cebeSEric Cheng if (!l_arg) 3745da14cebeSEric Cheng usage(); 3746da14cebeSEric Cheng 3747da14cebeSEric Cheng if (mac_slot != -1 && mac_addr_type != VNIC_MAC_ADDR_TYPE_FACTORY) 3748da14cebeSEric Cheng usage(); 3749da14cebeSEric Cheng 3750da14cebeSEric Cheng /* the VNIC id is the required operand */ 3751da14cebeSEric Cheng if (optind != (argc - 1)) 3752da14cebeSEric Cheng usage(); 3753da14cebeSEric Cheng 3754da14cebeSEric Cheng if (strlcpy(name, argv[optind], MAXLINKNAMELEN) >= MAXLINKNAMELEN) 3755da14cebeSEric Cheng die("link name too long '%s'", argv[optind]); 3756da14cebeSEric Cheng 3757da14cebeSEric Cheng if (!dladm_valid_linkname(name)) 3758da14cebeSEric Cheng die("invalid link name '%s'", argv[optind]); 3759da14cebeSEric Cheng 3760da14cebeSEric Cheng if (altroot != NULL) 3761da14cebeSEric Cheng altroot_cmd(altroot, argc, argv); 3762da14cebeSEric Cheng 37634ac67f02SAnurag S. Maskey if (dladm_name2info(handle, devname, &dev_linkid, NULL, NULL, NULL) != 3764da14cebeSEric Cheng DLADM_STATUS_OK) 3765da14cebeSEric Cheng die("invalid link name '%s'", devname); 3766da14cebeSEric Cheng 376763a6526dSMichael Lim if (dladm_parse_link_props(propstr, &proplist, B_FALSE) 376863a6526dSMichael Lim != DLADM_STATUS_OK) 376963a6526dSMichael Lim die("invalid vnic property"); 377063a6526dSMichael Lim 37714ac67f02SAnurag S. Maskey status = dladm_vnic_create(handle, name, dev_linkid, mac_addr_type, 37724ac67f02SAnurag S. Maskey mac_addr, maclen, &mac_slot, mac_prefix_len, vid, &linkid, proplist, 37734ac67f02SAnurag S. Maskey flags); 3774da14cebeSEric Cheng if (status != DLADM_STATUS_OK) 3775da14cebeSEric Cheng die_dlerr(status, "vnic creation over %s failed", devname); 3776da14cebeSEric Cheng 3777da14cebeSEric Cheng dladm_free_props(proplist); 3778da14cebeSEric Cheng } 3779da14cebeSEric Cheng 3780da14cebeSEric Cheng static void 3781da14cebeSEric Cheng do_etherstub_check(const char *name, datalink_id_t linkid, boolean_t etherstub, 3782da14cebeSEric Cheng uint32_t flags) 3783da14cebeSEric Cheng { 3784da14cebeSEric Cheng boolean_t is_etherstub; 3785da14cebeSEric Cheng dladm_vnic_attr_t attr; 3786da14cebeSEric Cheng 37874ac67f02SAnurag S. Maskey if (dladm_vnic_info(handle, linkid, &attr, flags) != DLADM_STATUS_OK) { 3788da14cebeSEric Cheng /* 3789da14cebeSEric Cheng * Let the delete continue anyway. 3790da14cebeSEric Cheng */ 3791da14cebeSEric Cheng return; 3792da14cebeSEric Cheng } 3793da14cebeSEric Cheng is_etherstub = (attr.va_link_id == DATALINK_INVALID_LINKID); 3794da14cebeSEric Cheng if (is_etherstub != etherstub) { 3795da14cebeSEric Cheng die("'%s' is not %s", name, 3796da14cebeSEric Cheng (is_etherstub ? "a vnic" : "an etherstub")); 3797da14cebeSEric Cheng } 3798da14cebeSEric Cheng } 3799da14cebeSEric Cheng 3800da14cebeSEric Cheng static void 3801da14cebeSEric Cheng do_delete_vnic_common(int argc, char *argv[], const char *use, 3802da14cebeSEric Cheng boolean_t etherstub) 3803da14cebeSEric Cheng { 3804da14cebeSEric Cheng char option; 3805da14cebeSEric Cheng uint32_t flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST; 3806da14cebeSEric Cheng datalink_id_t linkid; 3807da14cebeSEric Cheng char *altroot = NULL; 3808da14cebeSEric Cheng dladm_status_t status; 3809da14cebeSEric Cheng 3810da14cebeSEric Cheng opterr = 0; 3811da14cebeSEric Cheng while ((option = getopt_long(argc, argv, ":R:t", lopts, 3812da14cebeSEric Cheng NULL)) != -1) { 3813da14cebeSEric Cheng switch (option) { 3814da14cebeSEric Cheng case 't': 3815da14cebeSEric Cheng flags &= ~DLADM_OPT_PERSIST; 3816da14cebeSEric Cheng break; 3817da14cebeSEric Cheng case 'R': 3818da14cebeSEric Cheng altroot = optarg; 3819da14cebeSEric Cheng break; 3820da14cebeSEric Cheng default: 3821da14cebeSEric Cheng die_opterr(optopt, option, use); 3822da14cebeSEric Cheng } 3823da14cebeSEric Cheng } 3824da14cebeSEric Cheng 3825da14cebeSEric Cheng /* get vnic name (required last argument) */ 3826da14cebeSEric Cheng if (optind != (argc - 1)) 3827da14cebeSEric Cheng usage(); 3828da14cebeSEric Cheng 3829da14cebeSEric Cheng if (altroot != NULL) 3830da14cebeSEric Cheng altroot_cmd(altroot, argc, argv); 3831da14cebeSEric Cheng 38324ac67f02SAnurag S. Maskey status = dladm_name2info(handle, argv[optind], &linkid, NULL, NULL, 38334ac67f02SAnurag S. Maskey NULL); 3834da14cebeSEric Cheng if (status != DLADM_STATUS_OK) 3835da14cebeSEric Cheng die("invalid link name '%s'", argv[optind]); 3836da14cebeSEric Cheng 3837da14cebeSEric Cheng if ((flags & DLADM_OPT_ACTIVE) != 0) { 3838da14cebeSEric Cheng do_etherstub_check(argv[optind], linkid, etherstub, 3839da14cebeSEric Cheng DLADM_OPT_ACTIVE); 3840da14cebeSEric Cheng } 3841da14cebeSEric Cheng if ((flags & DLADM_OPT_PERSIST) != 0) { 3842da14cebeSEric Cheng do_etherstub_check(argv[optind], linkid, etherstub, 3843da14cebeSEric Cheng DLADM_OPT_PERSIST); 3844da14cebeSEric Cheng } 3845da14cebeSEric Cheng 38464ac67f02SAnurag S. Maskey status = dladm_vnic_delete(handle, linkid, flags); 3847da14cebeSEric Cheng if (status != DLADM_STATUS_OK) 3848da14cebeSEric Cheng die_dlerr(status, "vnic deletion failed"); 3849da14cebeSEric Cheng } 3850da14cebeSEric Cheng 3851da14cebeSEric Cheng static void 3852da14cebeSEric Cheng do_delete_vnic(int argc, char *argv[], const char *use) 3853da14cebeSEric Cheng { 3854da14cebeSEric Cheng do_delete_vnic_common(argc, argv, use, B_FALSE); 3855da14cebeSEric Cheng } 3856da14cebeSEric Cheng 3857da14cebeSEric Cheng /* ARGSUSED */ 3858da14cebeSEric Cheng static void 3859da14cebeSEric Cheng do_up_vnic_common(int argc, char *argv[], const char *use, boolean_t vlan) 3860da14cebeSEric Cheng { 3861da14cebeSEric Cheng datalink_id_t linkid = DATALINK_ALL_LINKID; 3862da14cebeSEric Cheng dladm_status_t status; 3863da14cebeSEric Cheng char *type; 3864da14cebeSEric Cheng 3865da14cebeSEric Cheng type = vlan ? "vlan" : "vnic"; 3866da14cebeSEric Cheng 3867da14cebeSEric Cheng /* 3868da14cebeSEric Cheng * get the id or the name of the vnic/vlan (optional last argument) 3869da14cebeSEric Cheng */ 3870da14cebeSEric Cheng if (argc == 2) { 38714ac67f02SAnurag S. Maskey status = dladm_name2info(handle, argv[1], &linkid, NULL, NULL, 38724ac67f02SAnurag S. Maskey NULL); 3873da14cebeSEric Cheng if (status != DLADM_STATUS_OK) 3874da14cebeSEric Cheng goto done; 3875da14cebeSEric Cheng 3876da14cebeSEric Cheng } else if (argc > 2) { 3877da14cebeSEric Cheng usage(); 3878da14cebeSEric Cheng } 3879da14cebeSEric Cheng 3880da14cebeSEric Cheng if (vlan) 38814ac67f02SAnurag S. Maskey status = dladm_vlan_up(handle, linkid); 3882da14cebeSEric Cheng else 38834ac67f02SAnurag S. Maskey status = dladm_vnic_up(handle, linkid, 0); 3884da14cebeSEric Cheng 3885da14cebeSEric Cheng done: 3886da14cebeSEric Cheng if (status != DLADM_STATUS_OK) { 3887da14cebeSEric Cheng if (argc == 2) { 3888da14cebeSEric Cheng die_dlerr(status, 3889da14cebeSEric Cheng "could not bring up %s '%s'", type, argv[1]); 3890da14cebeSEric Cheng } else { 3891da14cebeSEric Cheng die_dlerr(status, "could not bring %ss up", type); 3892da14cebeSEric Cheng } 3893da14cebeSEric Cheng } 3894da14cebeSEric Cheng } 3895da14cebeSEric Cheng 3896da14cebeSEric Cheng static void 3897da14cebeSEric Cheng do_up_vnic(int argc, char *argv[], const char *use) 3898da14cebeSEric Cheng { 3899da14cebeSEric Cheng do_up_vnic_common(argc, argv, use, B_FALSE); 3900da14cebeSEric Cheng } 3901da14cebeSEric Cheng 3902da14cebeSEric Cheng static void 3903da14cebeSEric Cheng dump_vnics_head(const char *dev) 3904da14cebeSEric Cheng { 3905da14cebeSEric Cheng if (strlen(dev)) 3906da14cebeSEric Cheng (void) printf("%s", dev); 3907da14cebeSEric Cheng 3908da14cebeSEric Cheng (void) printf("\tipackets rbytes opackets obytes "); 3909da14cebeSEric Cheng 3910da14cebeSEric Cheng if (strlen(dev)) 3911da14cebeSEric Cheng (void) printf("%%ipkts %%opkts\n"); 3912da14cebeSEric Cheng else 3913da14cebeSEric Cheng (void) printf("\n"); 3914da14cebeSEric Cheng } 3915da14cebeSEric Cheng 3916da14cebeSEric Cheng static void 3917da14cebeSEric Cheng dump_vnic_stat(const char *name, datalink_id_t vnic_id, 3918da14cebeSEric Cheng show_vnic_state_t *state, pktsum_t *vnic_stats, pktsum_t *tot_stats) 3919da14cebeSEric Cheng { 3920da14cebeSEric Cheng pktsum_t diff_stats; 3921da14cebeSEric Cheng pktsum_t *old_stats = &state->vs_prevstats[vnic_id]; 3922da14cebeSEric Cheng 3923da14cebeSEric Cheng dladm_stats_diff(&diff_stats, vnic_stats, old_stats); 3924da14cebeSEric Cheng 3925da14cebeSEric Cheng (void) printf("%s", name); 3926da14cebeSEric Cheng 3927da14cebeSEric Cheng (void) printf("\t%-10llu", diff_stats.ipackets); 3928da14cebeSEric Cheng (void) printf("%-12llu", diff_stats.rbytes); 3929da14cebeSEric Cheng (void) printf("%-10llu", diff_stats.opackets); 3930da14cebeSEric Cheng (void) printf("%-12llu", diff_stats.obytes); 3931da14cebeSEric Cheng 3932da14cebeSEric Cheng if (tot_stats) { 3933da14cebeSEric Cheng if (tot_stats->ipackets == 0) { 3934da14cebeSEric Cheng (void) printf("\t-"); 3935da14cebeSEric Cheng } else { 3936da14cebeSEric Cheng (void) printf("\t%-6.1f", (double)diff_stats.ipackets/ 3937da14cebeSEric Cheng (double)tot_stats->ipackets * 100); 3938da14cebeSEric Cheng } 3939da14cebeSEric Cheng if (tot_stats->opackets == 0) { 3940da14cebeSEric Cheng (void) printf("\t-"); 3941da14cebeSEric Cheng } else { 3942da14cebeSEric Cheng (void) printf("\t%-6.1f", (double)diff_stats.opackets/ 3943da14cebeSEric Cheng (double)tot_stats->opackets * 100); 3944da14cebeSEric Cheng } 3945da14cebeSEric Cheng } 3946da14cebeSEric Cheng (void) printf("\n"); 3947da14cebeSEric Cheng 3948da14cebeSEric Cheng *old_stats = *vnic_stats; 3949da14cebeSEric Cheng } 3950da14cebeSEric Cheng 3951da14cebeSEric Cheng /* 3952da14cebeSEric Cheng * Called from the walker dladm_vnic_walk_sys() for each vnic to display 3953da14cebeSEric Cheng * vnic information or statistics. 3954da14cebeSEric Cheng */ 3955da14cebeSEric Cheng static dladm_status_t 3956da14cebeSEric Cheng print_vnic(show_vnic_state_t *state, datalink_id_t linkid) 3957da14cebeSEric Cheng { 3958da14cebeSEric Cheng dladm_vnic_attr_t attr, *vnic = &attr; 3959da14cebeSEric Cheng dladm_status_t status; 3960da14cebeSEric Cheng boolean_t is_etherstub; 3961da14cebeSEric Cheng char devname[MAXLINKNAMELEN]; 3962da14cebeSEric Cheng char vnic_name[MAXLINKNAMELEN]; 3963da14cebeSEric Cheng char mstr[MAXMACADDRLEN * 3]; 3964da14cebeSEric Cheng vnic_fields_buf_t vbuf; 3965da14cebeSEric Cheng 39664ac67f02SAnurag S. Maskey if ((status = dladm_vnic_info(handle, linkid, vnic, state->vs_flags)) != 3967da14cebeSEric Cheng DLADM_STATUS_OK) 3968da14cebeSEric Cheng return (status); 3969da14cebeSEric Cheng 3970da14cebeSEric Cheng is_etherstub = (vnic->va_link_id == DATALINK_INVALID_LINKID); 3971da14cebeSEric Cheng if (state->vs_etherstub != is_etherstub) { 3972da14cebeSEric Cheng /* 3973da14cebeSEric Cheng * Want all etherstub but it's not one, or want 3974da14cebeSEric Cheng * non-etherstub and it's one. 3975da14cebeSEric Cheng */ 3976da14cebeSEric Cheng return (DLADM_STATUS_OK); 3977da14cebeSEric Cheng } 3978da14cebeSEric Cheng 3979da14cebeSEric Cheng if (state->vs_link_id != DATALINK_ALL_LINKID) { 3980da14cebeSEric Cheng if (state->vs_link_id != vnic->va_link_id) 3981da14cebeSEric Cheng return (DLADM_STATUS_OK); 3982da14cebeSEric Cheng } 3983da14cebeSEric Cheng 39844ac67f02SAnurag S. Maskey if (dladm_datalink_id2info(handle, linkid, NULL, NULL, 3985da14cebeSEric Cheng NULL, vnic_name, sizeof (vnic_name)) != DLADM_STATUS_OK) 3986da14cebeSEric Cheng return (DLADM_STATUS_BADARG); 3987da14cebeSEric Cheng 3988da14cebeSEric Cheng bzero(devname, sizeof (devname)); 3989da14cebeSEric Cheng if (!is_etherstub && 39904ac67f02SAnurag S. Maskey dladm_datalink_id2info(handle, vnic->va_link_id, NULL, NULL, 3991da14cebeSEric Cheng NULL, devname, sizeof (devname)) != DLADM_STATUS_OK) 3992da14cebeSEric Cheng return (DLADM_STATUS_BADARG); 3993da14cebeSEric Cheng 3994da14cebeSEric Cheng state->vs_found = B_TRUE; 3995da14cebeSEric Cheng if (state->vs_stats) { 3996da14cebeSEric Cheng /* print vnic statistics */ 3997da14cebeSEric Cheng pktsum_t vnic_stats; 3998da14cebeSEric Cheng 3999da14cebeSEric Cheng if (state->vs_firstonly) { 4000da14cebeSEric Cheng if (state->vs_donefirst) 4001da14cebeSEric Cheng return (0); 4002da14cebeSEric Cheng state->vs_donefirst = B_TRUE; 4003da14cebeSEric Cheng } 4004da14cebeSEric Cheng 4005da14cebeSEric Cheng if (!state->vs_printstats) { 4006da14cebeSEric Cheng /* 4007da14cebeSEric Cheng * get vnic statistics and add to the sum for the 4008da14cebeSEric Cheng * named device. 4009da14cebeSEric Cheng */ 4010da14cebeSEric Cheng get_link_stats(vnic_name, &vnic_stats); 4011da14cebeSEric Cheng dladm_stats_total(&state->vs_totalstats, &vnic_stats, 4012da14cebeSEric Cheng &state->vs_prevstats[vnic->va_vnic_id]); 4013da14cebeSEric Cheng } else { 4014da14cebeSEric Cheng /* get and print vnic statistics */ 4015da14cebeSEric Cheng get_link_stats(vnic_name, &vnic_stats); 4016da14cebeSEric Cheng dump_vnic_stat(vnic_name, linkid, state, &vnic_stats, 4017da14cebeSEric Cheng &state->vs_totalstats); 4018da14cebeSEric Cheng } 4019da14cebeSEric Cheng return (DLADM_STATUS_OK); 4020da14cebeSEric Cheng } else { 4021da14cebeSEric Cheng (void) snprintf(vbuf.vnic_link, sizeof (vbuf.vnic_link), 4022da14cebeSEric Cheng "%s", vnic_name); 4023da14cebeSEric Cheng 4024da14cebeSEric Cheng if (!is_etherstub) { 4025da14cebeSEric Cheng 4026da14cebeSEric Cheng (void) snprintf(vbuf.vnic_over, sizeof (vbuf.vnic_over), 4027da14cebeSEric Cheng "%s", devname); 4028da14cebeSEric Cheng (void) snprintf(vbuf.vnic_speed, 4029da14cebeSEric Cheng sizeof (vbuf.vnic_speed), "%u", 4030da14cebeSEric Cheng (uint_t)((get_ifspeed(vnic_name, B_TRUE)) 4031da14cebeSEric Cheng / 1000000ull)); 4032da14cebeSEric Cheng 4033da14cebeSEric Cheng switch (vnic->va_mac_addr_type) { 4034da14cebeSEric Cheng case VNIC_MAC_ADDR_TYPE_FIXED: 4035da14cebeSEric Cheng case VNIC_MAC_ADDR_TYPE_PRIMARY: 4036da14cebeSEric Cheng (void) snprintf(vbuf.vnic_macaddrtype, 4037da14cebeSEric Cheng sizeof (vbuf.vnic_macaddrtype), 4038da14cebeSEric Cheng gettext("fixed")); 4039da14cebeSEric Cheng break; 4040da14cebeSEric Cheng case VNIC_MAC_ADDR_TYPE_RANDOM: 4041da14cebeSEric Cheng (void) snprintf(vbuf.vnic_macaddrtype, 4042da14cebeSEric Cheng sizeof (vbuf.vnic_macaddrtype), 4043da14cebeSEric Cheng gettext("random")); 4044da14cebeSEric Cheng break; 4045da14cebeSEric Cheng case VNIC_MAC_ADDR_TYPE_FACTORY: 4046da14cebeSEric Cheng (void) snprintf(vbuf.vnic_macaddrtype, 4047da14cebeSEric Cheng sizeof (vbuf.vnic_macaddrtype), 4048da14cebeSEric Cheng gettext("factory, slot %d"), 4049da14cebeSEric Cheng vnic->va_mac_slot); 4050da14cebeSEric Cheng break; 4051da14cebeSEric Cheng } 4052da14cebeSEric Cheng 4053da14cebeSEric Cheng if (strlen(vbuf.vnic_macaddrtype) > 0) { 4054da14cebeSEric Cheng (void) snprintf(vbuf.vnic_macaddr, 4055da14cebeSEric Cheng sizeof (vbuf.vnic_macaddr), "%s", 4056da14cebeSEric Cheng dladm_aggr_macaddr2str(vnic->va_mac_addr, 4057da14cebeSEric Cheng mstr)); 4058da14cebeSEric Cheng } 4059da14cebeSEric Cheng 4060da14cebeSEric Cheng (void) snprintf(vbuf.vnic_vid, sizeof (vbuf.vnic_vid), 4061da14cebeSEric Cheng "%d", vnic->va_vid); 4062da14cebeSEric Cheng } 4063da14cebeSEric Cheng 40648002d411SSowmini Varadhan ofmt_print(state->vs_ofmt, &vbuf); 4065da14cebeSEric Cheng 4066da14cebeSEric Cheng return (DLADM_STATUS_OK); 4067da14cebeSEric Cheng } 4068da14cebeSEric Cheng } 4069da14cebeSEric Cheng 40704ac67f02SAnurag S. Maskey /* ARGSUSED */ 4071da14cebeSEric Cheng static int 40724ac67f02SAnurag S. Maskey show_vnic(dladm_handle_t dh, datalink_id_t linkid, void *arg) 4073da14cebeSEric Cheng { 4074da14cebeSEric Cheng show_vnic_state_t *state = arg; 4075da14cebeSEric Cheng 4076da14cebeSEric Cheng state->vs_status = print_vnic(state, linkid); 4077da14cebeSEric Cheng return (DLADM_WALK_CONTINUE); 4078da14cebeSEric Cheng } 4079da14cebeSEric Cheng 4080da14cebeSEric Cheng static void 4081da14cebeSEric Cheng do_show_vnic_common(int argc, char *argv[], const char *use, 4082da14cebeSEric Cheng boolean_t etherstub) 4083da14cebeSEric Cheng { 4084da14cebeSEric Cheng int option; 4085da14cebeSEric Cheng boolean_t s_arg = B_FALSE; 4086da14cebeSEric Cheng boolean_t i_arg = B_FALSE; 4087da14cebeSEric Cheng boolean_t l_arg = B_FALSE; 4088da14cebeSEric Cheng uint32_t interval = 0, flags = DLADM_OPT_ACTIVE; 4089da14cebeSEric Cheng datalink_id_t linkid = DATALINK_ALL_LINKID; 4090da14cebeSEric Cheng datalink_id_t dev_linkid = DATALINK_ALL_LINKID; 4091da14cebeSEric Cheng show_vnic_state_t state; 4092da14cebeSEric Cheng dladm_status_t status; 4093da14cebeSEric Cheng boolean_t o_arg = B_FALSE; 4094da14cebeSEric Cheng char *fields_str = NULL; 40958002d411SSowmini Varadhan ofmt_field_t *pf; 40968002d411SSowmini Varadhan char *all_e_fields = "link"; 40978002d411SSowmini Varadhan ofmt_handle_t ofmt; 40988002d411SSowmini Varadhan ofmt_status_t oferr; 40998002d411SSowmini Varadhan uint_t ofmtflags = 0; 4100da14cebeSEric Cheng 4101da14cebeSEric Cheng bzero(&state, sizeof (state)); 4102da14cebeSEric Cheng opterr = 0; 4103da14cebeSEric Cheng while ((option = getopt_long(argc, argv, ":pPl:si:o:", lopts, 4104da14cebeSEric Cheng NULL)) != -1) { 4105da14cebeSEric Cheng switch (option) { 4106da14cebeSEric Cheng case 'p': 41078002d411SSowmini Varadhan state.vs_parsable = B_TRUE; 4108da14cebeSEric Cheng break; 4109da14cebeSEric Cheng case 'P': 4110da14cebeSEric Cheng flags = DLADM_OPT_PERSIST; 4111da14cebeSEric Cheng break; 4112da14cebeSEric Cheng case 'l': 4113da14cebeSEric Cheng if (etherstub) 4114da14cebeSEric Cheng die("option not supported for this command"); 4115da14cebeSEric Cheng 4116da14cebeSEric Cheng if (strlcpy(state.vs_link, optarg, MAXLINKNAMELEN) >= 4117da14cebeSEric Cheng MAXLINKNAMELEN) 4118da14cebeSEric Cheng die("link name too long"); 4119da14cebeSEric Cheng 4120da14cebeSEric Cheng l_arg = B_TRUE; 4121da14cebeSEric Cheng break; 4122da14cebeSEric Cheng case 's': 4123da14cebeSEric Cheng if (s_arg) { 4124da14cebeSEric Cheng die("the option -s cannot be specified " 4125da14cebeSEric Cheng "more than once"); 4126da14cebeSEric Cheng } 4127da14cebeSEric Cheng s_arg = B_TRUE; 4128da14cebeSEric Cheng break; 4129da14cebeSEric Cheng case 'i': 4130da14cebeSEric Cheng if (i_arg) { 4131da14cebeSEric Cheng die("the option -i cannot be specified " 4132da14cebeSEric Cheng "more than once"); 4133da14cebeSEric Cheng } 4134da14cebeSEric Cheng i_arg = B_TRUE; 413563a6526dSMichael Lim if (!dladm_str2interval(optarg, &interval)) 4136da14cebeSEric Cheng die("invalid interval value '%s'", optarg); 4137da14cebeSEric Cheng break; 4138da14cebeSEric Cheng case 'o': 4139da14cebeSEric Cheng o_arg = B_TRUE; 4140da14cebeSEric Cheng fields_str = optarg; 4141da14cebeSEric Cheng break; 4142da14cebeSEric Cheng default: 4143da14cebeSEric Cheng die_opterr(optopt, option, use); 4144da14cebeSEric Cheng } 4145da14cebeSEric Cheng } 4146da14cebeSEric Cheng 4147da14cebeSEric Cheng if (i_arg && !s_arg) 4148da14cebeSEric Cheng die("the option -i can be used only with -s"); 4149da14cebeSEric Cheng 4150da14cebeSEric Cheng /* get vnic ID (optional last argument) */ 4151da14cebeSEric Cheng if (optind == (argc - 1)) { 41524ac67f02SAnurag S. Maskey status = dladm_name2info(handle, argv[optind], &linkid, NULL, 4153da14cebeSEric Cheng NULL, NULL); 4154da14cebeSEric Cheng if (status != DLADM_STATUS_OK) { 4155da14cebeSEric Cheng die_dlerr(status, "invalid vnic name '%s'", 4156da14cebeSEric Cheng argv[optind]); 4157da14cebeSEric Cheng } 4158da14cebeSEric Cheng (void) strlcpy(state.vs_vnic, argv[optind], MAXLINKNAMELEN); 4159da14cebeSEric Cheng } else if (optind != argc) { 4160da14cebeSEric Cheng usage(); 4161da14cebeSEric Cheng } 4162da14cebeSEric Cheng 4163da14cebeSEric Cheng if (l_arg) { 41644ac67f02SAnurag S. Maskey status = dladm_name2info(handle, state.vs_link, &dev_linkid, 41654ac67f02SAnurag S. Maskey NULL, NULL, NULL); 4166da14cebeSEric Cheng if (status != DLADM_STATUS_OK) { 4167da14cebeSEric Cheng die_dlerr(status, "invalid link name '%s'", 4168da14cebeSEric Cheng state.vs_link); 4169da14cebeSEric Cheng } 4170da14cebeSEric Cheng } 4171da14cebeSEric Cheng 4172da14cebeSEric Cheng state.vs_vnic_id = linkid; 4173da14cebeSEric Cheng state.vs_link_id = dev_linkid; 4174da14cebeSEric Cheng state.vs_etherstub = etherstub; 4175da14cebeSEric Cheng state.vs_found = B_FALSE; 4176da14cebeSEric Cheng state.vs_flags = flags; 4177da14cebeSEric Cheng 4178da14cebeSEric Cheng if (!o_arg || (o_arg && strcasecmp(fields_str, "all") == 0)) { 4179da14cebeSEric Cheng if (etherstub) 4180da14cebeSEric Cheng fields_str = all_e_fields; 4181da14cebeSEric Cheng } 4182da14cebeSEric Cheng pf = vnic_fields; 4183da14cebeSEric Cheng 41848002d411SSowmini Varadhan if (state.vs_parsable) 41858002d411SSowmini Varadhan ofmtflags |= OFMT_PARSABLE; 41868002d411SSowmini Varadhan oferr = ofmt_open(fields_str, pf, ofmtflags, 0, &ofmt); 41878002d411SSowmini Varadhan dladm_ofmt_check(oferr, state.vs_parsable, ofmt); 41888002d411SSowmini Varadhan state.vs_ofmt = ofmt; 4189da14cebeSEric Cheng 4190da14cebeSEric Cheng if (s_arg) { 4191da14cebeSEric Cheng /* Display vnic statistics */ 4192da14cebeSEric Cheng vnic_stats(&state, interval); 41938002d411SSowmini Varadhan ofmt_close(ofmt); 4194da14cebeSEric Cheng return; 4195da14cebeSEric Cheng } 4196da14cebeSEric Cheng 4197da14cebeSEric Cheng /* Display vnic information */ 4198da14cebeSEric Cheng state.vs_donefirst = B_FALSE; 4199da14cebeSEric Cheng 4200da14cebeSEric Cheng if (linkid == DATALINK_ALL_LINKID) { 42014ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(show_vnic, handle, &state, 4202da14cebeSEric Cheng DATALINK_CLASS_VNIC | DATALINK_CLASS_ETHERSTUB, 4203da14cebeSEric Cheng DATALINK_ANY_MEDIATYPE, DLADM_OPT_ACTIVE); 4204da14cebeSEric Cheng } else { 42054ac67f02SAnurag S. Maskey (void) show_vnic(handle, linkid, &state); 4206da14cebeSEric Cheng if (state.vs_status != DLADM_STATUS_OK) { 42078002d411SSowmini Varadhan ofmt_close(ofmt); 4208da14cebeSEric Cheng die_dlerr(state.vs_status, "failed to show vnic '%s'", 4209da14cebeSEric Cheng state.vs_vnic); 4210da14cebeSEric Cheng } 4211da14cebeSEric Cheng } 42128002d411SSowmini Varadhan ofmt_close(ofmt); 4213da14cebeSEric Cheng } 4214da14cebeSEric Cheng 4215da14cebeSEric Cheng static void 4216da14cebeSEric Cheng do_show_vnic(int argc, char *argv[], const char *use) 4217da14cebeSEric Cheng { 4218da14cebeSEric Cheng do_show_vnic_common(argc, argv, use, B_FALSE); 4219da14cebeSEric Cheng } 4220da14cebeSEric Cheng 4221da14cebeSEric Cheng static void 4222da14cebeSEric Cheng do_create_etherstub(int argc, char *argv[], const char *use) 4223da14cebeSEric Cheng { 4224da14cebeSEric Cheng uint32_t flags; 4225da14cebeSEric Cheng char *altroot = NULL; 4226da14cebeSEric Cheng char option; 4227da14cebeSEric Cheng dladm_status_t status; 4228da14cebeSEric Cheng char name[MAXLINKNAMELEN]; 4229da14cebeSEric Cheng uchar_t mac_addr[ETHERADDRL]; 4230da14cebeSEric Cheng 4231da14cebeSEric Cheng name[0] = '\0'; 4232da14cebeSEric Cheng bzero(mac_addr, sizeof (mac_addr)); 4233da14cebeSEric Cheng flags = DLADM_OPT_ANCHOR | DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST; 4234da14cebeSEric Cheng 4235da14cebeSEric Cheng opterr = 0; 4236da14cebeSEric Cheng while ((option = getopt_long(argc, argv, "tR:", 4237da14cebeSEric Cheng etherstub_lopts, NULL)) != -1) { 4238da14cebeSEric Cheng switch (option) { 4239da14cebeSEric Cheng case 't': 4240da14cebeSEric Cheng flags &= ~DLADM_OPT_PERSIST; 4241da14cebeSEric Cheng break; 4242da14cebeSEric Cheng case 'R': 4243da14cebeSEric Cheng altroot = optarg; 4244da14cebeSEric Cheng break; 4245da14cebeSEric Cheng default: 4246da14cebeSEric Cheng die_opterr(optopt, option, use); 4247da14cebeSEric Cheng } 4248da14cebeSEric Cheng } 4249da14cebeSEric Cheng 4250da14cebeSEric Cheng /* the etherstub id is the required operand */ 4251da14cebeSEric Cheng if (optind != (argc - 1)) 4252da14cebeSEric Cheng usage(); 4253da14cebeSEric Cheng 4254da14cebeSEric Cheng if (strlcpy(name, argv[optind], MAXLINKNAMELEN) >= MAXLINKNAMELEN) 4255da14cebeSEric Cheng die("link name too long '%s'", argv[optind]); 4256da14cebeSEric Cheng 4257da14cebeSEric Cheng if (!dladm_valid_linkname(name)) 4258da14cebeSEric Cheng die("invalid link name '%s'", argv[optind]); 4259da14cebeSEric Cheng 4260da14cebeSEric Cheng if (altroot != NULL) 4261da14cebeSEric Cheng altroot_cmd(altroot, argc, argv); 4262da14cebeSEric Cheng 42634ac67f02SAnurag S. Maskey status = dladm_vnic_create(handle, name, DATALINK_INVALID_LINKID, 4264da14cebeSEric Cheng VNIC_MAC_ADDR_TYPE_AUTO, mac_addr, ETHERADDRL, NULL, 0, 0, NULL, 4265da14cebeSEric Cheng NULL, flags); 4266da14cebeSEric Cheng if (status != DLADM_STATUS_OK) 4267da14cebeSEric Cheng die_dlerr(status, "etherstub creation failed"); 4268da14cebeSEric Cheng 4269da14cebeSEric Cheng 4270da14cebeSEric Cheng } 4271da14cebeSEric Cheng 4272da14cebeSEric Cheng static void 4273da14cebeSEric Cheng do_delete_etherstub(int argc, char *argv[], const char *use) 4274da14cebeSEric Cheng { 4275da14cebeSEric Cheng do_delete_vnic_common(argc, argv, use, B_TRUE); 4276da14cebeSEric Cheng } 4277da14cebeSEric Cheng 4278da14cebeSEric Cheng /* ARGSUSED */ 4279da14cebeSEric Cheng static void 4280da14cebeSEric Cheng do_show_etherstub(int argc, char *argv[], const char *use) 4281da14cebeSEric Cheng { 4282da14cebeSEric Cheng do_show_vnic_common(argc, argv, use, B_TRUE); 4283da14cebeSEric Cheng } 4284da14cebeSEric Cheng 4285da14cebeSEric Cheng static void 42866be03d0bSVasumathi Sundaram - Sun Microsystems link_stats(datalink_id_t linkid, uint_t interval, char *fields_str, 42876be03d0bSVasumathi Sundaram - Sun Microsystems show_state_t *state) 4288d62bc4baSyz147064 { 42898002d411SSowmini Varadhan ofmt_handle_t ofmt; 42908002d411SSowmini Varadhan ofmt_status_t oferr; 42918002d411SSowmini Varadhan uint_t ofmtflags = 0; 429233343a97Smeem 42938002d411SSowmini Varadhan if (state->ls_parsable) 42948002d411SSowmini Varadhan ofmtflags |= OFMT_PARSABLE; 42958002d411SSowmini Varadhan oferr = ofmt_open(fields_str, link_s_fields, ofmtflags, 0, &ofmt); 42968002d411SSowmini Varadhan dladm_ofmt_check(oferr, state->ls_parsable, ofmt); 42978002d411SSowmini Varadhan state->ls_ofmt = ofmt; 42987c478bd9Sstevel@tonic-gate 42997c478bd9Sstevel@tonic-gate /* 43007c478bd9Sstevel@tonic-gate * If an interval is specified, continuously show the stats 43017c478bd9Sstevel@tonic-gate * only for the first MAC port. 43027c478bd9Sstevel@tonic-gate */ 43036be03d0bSVasumathi Sundaram - Sun Microsystems state->ls_firstonly = (interval != 0); 43047c478bd9Sstevel@tonic-gate 43057c478bd9Sstevel@tonic-gate for (;;) { 43066be03d0bSVasumathi Sundaram - Sun Microsystems state->ls_donefirst = B_FALSE; 4307d62bc4baSyz147064 if (linkid == DATALINK_ALL_LINKID) { 43084ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(show_link_stats, handle, 43094ac67f02SAnurag S. Maskey state, DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE, 4310d62bc4baSyz147064 DLADM_OPT_ACTIVE); 4311d62bc4baSyz147064 } else { 43124ac67f02SAnurag S. Maskey (void) show_link_stats(handle, linkid, state); 4313d62bc4baSyz147064 } 43147c478bd9Sstevel@tonic-gate 43157c478bd9Sstevel@tonic-gate if (interval == 0) 43167c478bd9Sstevel@tonic-gate break; 43177c478bd9Sstevel@tonic-gate 43187c478bd9Sstevel@tonic-gate (void) sleep(interval); 43197c478bd9Sstevel@tonic-gate } 43208002d411SSowmini Varadhan ofmt_close(ofmt); 43217c478bd9Sstevel@tonic-gate } 43227c478bd9Sstevel@tonic-gate 43237c478bd9Sstevel@tonic-gate static void 4324d62bc4baSyz147064 aggr_stats(datalink_id_t linkid, show_grp_state_t *state, uint_t interval) 43257c478bd9Sstevel@tonic-gate { 43267c478bd9Sstevel@tonic-gate /* 43277c478bd9Sstevel@tonic-gate * If an interval is specified, continuously show the stats 43287c478bd9Sstevel@tonic-gate * only for the first group. 43297c478bd9Sstevel@tonic-gate */ 4330d62bc4baSyz147064 state->gs_firstonly = (interval != 0); 43317c478bd9Sstevel@tonic-gate 43327c478bd9Sstevel@tonic-gate for (;;) { 4333d62bc4baSyz147064 state->gs_donefirst = B_FALSE; 4334d62bc4baSyz147064 if (linkid == DATALINK_ALL_LINKID) 43354ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(show_aggr, handle, state, 4336d62bc4baSyz147064 DATALINK_CLASS_AGGR, DATALINK_ANY_MEDIATYPE, 4337d62bc4baSyz147064 DLADM_OPT_ACTIVE); 4338d62bc4baSyz147064 else 43394ac67f02SAnurag S. Maskey (void) show_aggr(handle, linkid, state); 43407c478bd9Sstevel@tonic-gate 43417c478bd9Sstevel@tonic-gate if (interval == 0) 43427c478bd9Sstevel@tonic-gate break; 43437c478bd9Sstevel@tonic-gate 43447c478bd9Sstevel@tonic-gate (void) sleep(interval); 43457c478bd9Sstevel@tonic-gate } 43467c478bd9Sstevel@tonic-gate } 43477c478bd9Sstevel@tonic-gate 4348da14cebeSEric Cheng /* ARGSUSED */ 43497c478bd9Sstevel@tonic-gate static void 4350da14cebeSEric Cheng vnic_stats(show_vnic_state_t *sp, uint32_t interval) 43517c478bd9Sstevel@tonic-gate { 4352da14cebeSEric Cheng show_vnic_state_t state; 4353da14cebeSEric Cheng boolean_t specific_link, specific_dev; 43547c478bd9Sstevel@tonic-gate 4355da14cebeSEric Cheng /* Display vnic statistics */ 4356da14cebeSEric Cheng dump_vnics_head(sp->vs_link); 4357e7801d59Ssowmini 4358da14cebeSEric Cheng bzero(&state, sizeof (state)); 4359da14cebeSEric Cheng state.vs_stats = B_TRUE; 4360da14cebeSEric Cheng state.vs_vnic_id = sp->vs_vnic_id; 4361da14cebeSEric Cheng state.vs_link_id = sp->vs_link_id; 43627c478bd9Sstevel@tonic-gate 43637c478bd9Sstevel@tonic-gate /* 4364da14cebeSEric Cheng * If an interval is specified, and a vnic ID is not specified, 4365da14cebeSEric Cheng * continuously show the stats only for the first vnic. 43667c478bd9Sstevel@tonic-gate */ 4367da14cebeSEric Cheng specific_link = (sp->vs_vnic_id != DATALINK_ALL_LINKID); 4368da14cebeSEric Cheng specific_dev = (sp->vs_link_id != DATALINK_ALL_LINKID); 43697c478bd9Sstevel@tonic-gate 43707c478bd9Sstevel@tonic-gate for (;;) { 4371da14cebeSEric Cheng /* Get stats for each vnic */ 4372da14cebeSEric Cheng state.vs_found = B_FALSE; 4373da14cebeSEric Cheng state.vs_donefirst = B_FALSE; 4374da14cebeSEric Cheng state.vs_printstats = B_FALSE; 4375da14cebeSEric Cheng state.vs_flags = DLADM_OPT_ACTIVE; 43767c478bd9Sstevel@tonic-gate 4377da14cebeSEric Cheng if (!specific_link) { 43784ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(show_vnic, handle, &state, 4379da14cebeSEric Cheng DATALINK_CLASS_VNIC, DATALINK_ANY_MEDIATYPE, 4380da14cebeSEric Cheng DLADM_OPT_ACTIVE); 4381da14cebeSEric Cheng } else { 43824ac67f02SAnurag S. Maskey (void) show_vnic(handle, sp->vs_vnic_id, &state); 4383da14cebeSEric Cheng if (state.vs_status != DLADM_STATUS_OK) { 4384da14cebeSEric Cheng die_dlerr(state.vs_status, 4385da14cebeSEric Cheng "failed to show vnic '%s'", sp->vs_vnic); 4386da14cebeSEric Cheng } 4387da14cebeSEric Cheng } 43887c478bd9Sstevel@tonic-gate 4389da14cebeSEric Cheng if (specific_link && !state.vs_found) 4390da14cebeSEric Cheng die("non-existent vnic '%s'", sp->vs_vnic); 4391da14cebeSEric Cheng if (specific_dev && !state.vs_found) 4392da14cebeSEric Cheng die("device %s has no vnics", sp->vs_link); 4393da14cebeSEric Cheng 4394da14cebeSEric Cheng /* Show totals */ 4395da14cebeSEric Cheng if ((specific_link | specific_dev) && !interval) { 4396da14cebeSEric Cheng (void) printf("Total"); 4397da14cebeSEric Cheng (void) printf("\t%-10llu", 4398da14cebeSEric Cheng state.vs_totalstats.ipackets); 4399da14cebeSEric Cheng (void) printf("%-12llu", 4400da14cebeSEric Cheng state.vs_totalstats.rbytes); 4401da14cebeSEric Cheng (void) printf("%-10llu", 4402da14cebeSEric Cheng state.vs_totalstats.opackets); 4403da14cebeSEric Cheng (void) printf("%-12llu\n", 4404da14cebeSEric Cheng state.vs_totalstats.obytes); 4405da14cebeSEric Cheng } 4406da14cebeSEric Cheng 4407da14cebeSEric Cheng /* Show stats for each vnic */ 4408da14cebeSEric Cheng state.vs_donefirst = B_FALSE; 4409da14cebeSEric Cheng state.vs_printstats = B_TRUE; 4410da14cebeSEric Cheng 4411da14cebeSEric Cheng if (!specific_link) { 44124ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(show_vnic, handle, &state, 4413da14cebeSEric Cheng DATALINK_CLASS_VNIC, DATALINK_ANY_MEDIATYPE, 4414da14cebeSEric Cheng DLADM_OPT_ACTIVE); 4415da14cebeSEric Cheng } else { 44164ac67f02SAnurag S. Maskey (void) show_vnic(handle, sp->vs_vnic_id, &state); 4417da14cebeSEric Cheng if (state.vs_status != DLADM_STATUS_OK) { 4418da14cebeSEric Cheng die_dlerr(state.vs_status, 4419da14cebeSEric Cheng "failed to show vnic '%s'", sp->vs_vnic); 4420da14cebeSEric Cheng } 4421da14cebeSEric Cheng } 44227c478bd9Sstevel@tonic-gate 44237c478bd9Sstevel@tonic-gate if (interval == 0) 44247c478bd9Sstevel@tonic-gate break; 44257c478bd9Sstevel@tonic-gate 44267c478bd9Sstevel@tonic-gate (void) sleep(interval); 44277c478bd9Sstevel@tonic-gate } 44287c478bd9Sstevel@tonic-gate } 44297c478bd9Sstevel@tonic-gate 44307c478bd9Sstevel@tonic-gate static void 4431da14cebeSEric Cheng get_mac_stats(const char *dev, pktsum_t *stats) 44327c478bd9Sstevel@tonic-gate { 44337c478bd9Sstevel@tonic-gate kstat_ctl_t *kcp; 44347c478bd9Sstevel@tonic-gate kstat_t *ksp; 4435da14cebeSEric Cheng char module[DLPI_LINKNAME_MAX]; 4436da14cebeSEric Cheng uint_t instance; 4437da14cebeSEric Cheng 4438da14cebeSEric Cheng 4439da14cebeSEric Cheng bzero(stats, sizeof (*stats)); 4440da14cebeSEric Cheng 4441da14cebeSEric Cheng if (dlpi_parselink(dev, module, &instance) != DLPI_SUCCESS) 4442da14cebeSEric Cheng return; 44437c478bd9Sstevel@tonic-gate 44447c478bd9Sstevel@tonic-gate if ((kcp = kstat_open()) == NULL) { 444533343a97Smeem warn("kstat open operation failed"); 44467c478bd9Sstevel@tonic-gate return; 44477c478bd9Sstevel@tonic-gate } 44487c478bd9Sstevel@tonic-gate 4449da14cebeSEric Cheng ksp = dladm_kstat_lookup(kcp, module, instance, "mac", NULL); 4450da14cebeSEric Cheng if (ksp != NULL) 4451da14cebeSEric Cheng dladm_get_stats(kcp, ksp, stats); 4452da14cebeSEric Cheng 44537c478bd9Sstevel@tonic-gate (void) kstat_close(kcp); 44547c478bd9Sstevel@tonic-gate 44557c478bd9Sstevel@tonic-gate } 44567c478bd9Sstevel@tonic-gate 44577c478bd9Sstevel@tonic-gate static void 44587c478bd9Sstevel@tonic-gate get_link_stats(const char *link, pktsum_t *stats) 44597c478bd9Sstevel@tonic-gate { 4460da14cebeSEric Cheng kstat_ctl_t *kcp; 4461da14cebeSEric Cheng kstat_t *ksp; 4462da14cebeSEric Cheng 44637c478bd9Sstevel@tonic-gate bzero(stats, sizeof (*stats)); 4464da14cebeSEric Cheng 4465da14cebeSEric Cheng if ((kcp = kstat_open()) == NULL) { 4466da14cebeSEric Cheng warn("kstat_open operation failed"); 4467da14cebeSEric Cheng return; 4468da14cebeSEric Cheng } 4469da14cebeSEric Cheng 4470da14cebeSEric Cheng ksp = dladm_kstat_lookup(kcp, "link", 0, link, NULL); 4471da14cebeSEric Cheng 4472da14cebeSEric Cheng if (ksp != NULL) 4473da14cebeSEric Cheng dladm_get_stats(kcp, ksp, stats); 4474da14cebeSEric Cheng 4475da14cebeSEric Cheng (void) kstat_close(kcp); 44767c478bd9Sstevel@tonic-gate } 44777c478bd9Sstevel@tonic-gate 4478ba2e4443Sseb static int 4479d62bc4baSyz147064 query_kstat(char *module, int instance, const char *name, const char *stat, 4480d62bc4baSyz147064 uint8_t type, void *val) 44817c478bd9Sstevel@tonic-gate { 44827c478bd9Sstevel@tonic-gate kstat_ctl_t *kcp; 44837c478bd9Sstevel@tonic-gate kstat_t *ksp; 44847c478bd9Sstevel@tonic-gate 44857c478bd9Sstevel@tonic-gate if ((kcp = kstat_open()) == NULL) { 448633343a97Smeem warn("kstat open operation failed"); 4487ba2e4443Sseb return (-1); 44887c478bd9Sstevel@tonic-gate } 44897c478bd9Sstevel@tonic-gate 4490d62bc4baSyz147064 if ((ksp = kstat_lookup(kcp, module, instance, (char *)name)) == NULL) { 44917c478bd9Sstevel@tonic-gate /* 44927c478bd9Sstevel@tonic-gate * The kstat query could fail if the underlying MAC 44937c478bd9Sstevel@tonic-gate * driver was already detached. 44947c478bd9Sstevel@tonic-gate */ 44957c478bd9Sstevel@tonic-gate goto bail; 44967c478bd9Sstevel@tonic-gate } 44977c478bd9Sstevel@tonic-gate 44987c478bd9Sstevel@tonic-gate if (kstat_read(kcp, ksp, NULL) == -1) { 449933343a97Smeem warn("kstat read failed"); 45007c478bd9Sstevel@tonic-gate goto bail; 45017c478bd9Sstevel@tonic-gate } 45027c478bd9Sstevel@tonic-gate 4503e7801d59Ssowmini if (dladm_kstat_value(ksp, stat, type, val) < 0) 45047c478bd9Sstevel@tonic-gate goto bail; 4505ba2e4443Sseb 4506ba2e4443Sseb (void) kstat_close(kcp); 4507ba2e4443Sseb return (0); 45087c478bd9Sstevel@tonic-gate 45097c478bd9Sstevel@tonic-gate bail: 45107c478bd9Sstevel@tonic-gate (void) kstat_close(kcp); 4511ba2e4443Sseb return (-1); 4512ba2e4443Sseb } 4513ba2e4443Sseb 4514d62bc4baSyz147064 static int 4515d62bc4baSyz147064 get_one_kstat(const char *name, const char *stat, uint8_t type, 4516d62bc4baSyz147064 void *val, boolean_t islink) 4517d62bc4baSyz147064 { 4518d62bc4baSyz147064 char module[DLPI_LINKNAME_MAX]; 4519d62bc4baSyz147064 uint_t instance; 4520d62bc4baSyz147064 4521d62bc4baSyz147064 if (islink) { 4522d62bc4baSyz147064 return (query_kstat("link", 0, name, stat, type, val)); 4523d62bc4baSyz147064 } else { 4524d62bc4baSyz147064 if (dlpi_parselink(name, module, &instance) != DLPI_SUCCESS) 4525d62bc4baSyz147064 return (-1); 4526d62bc4baSyz147064 4527d62bc4baSyz147064 return (query_kstat(module, instance, "mac", stat, type, val)); 4528d62bc4baSyz147064 } 4529d62bc4baSyz147064 } 4530d62bc4baSyz147064 4531ba2e4443Sseb static uint64_t 4532d62bc4baSyz147064 get_ifspeed(const char *name, boolean_t islink) 4533ba2e4443Sseb { 4534ba2e4443Sseb uint64_t ifspeed = 0; 4535ba2e4443Sseb 4536d62bc4baSyz147064 (void) get_one_kstat(name, "ifspeed", KSTAT_DATA_UINT64, 4537d62bc4baSyz147064 &ifspeed, islink); 4538d62bc4baSyz147064 45397c478bd9Sstevel@tonic-gate return (ifspeed); 45407c478bd9Sstevel@tonic-gate } 45417c478bd9Sstevel@tonic-gate 4542f595a68aSyz147064 static const char * 4543d62bc4baSyz147064 get_linkstate(const char *name, boolean_t islink, char *buf) 45447c478bd9Sstevel@tonic-gate { 4545d62bc4baSyz147064 link_state_t linkstate; 45467c478bd9Sstevel@tonic-gate 4547d62bc4baSyz147064 if (get_one_kstat(name, "link_state", KSTAT_DATA_UINT32, 4548d62bc4baSyz147064 &linkstate, islink) != 0) { 4549da14cebeSEric Cheng (void) strlcpy(buf, "?", DLADM_STRSIZE); 45503a62633bSyz147064 return (buf); 45517c478bd9Sstevel@tonic-gate } 4552d62bc4baSyz147064 return (dladm_linkstate2str(linkstate, buf)); 45537c478bd9Sstevel@tonic-gate } 45547c478bd9Sstevel@tonic-gate 4555f595a68aSyz147064 static const char * 4556d62bc4baSyz147064 get_linkduplex(const char *name, boolean_t islink, char *buf) 45577c478bd9Sstevel@tonic-gate { 4558d62bc4baSyz147064 link_duplex_t linkduplex; 45597c478bd9Sstevel@tonic-gate 4560d62bc4baSyz147064 if (get_one_kstat(name, "link_duplex", KSTAT_DATA_UINT32, 4561d62bc4baSyz147064 &linkduplex, islink) != 0) { 45623a62633bSyz147064 (void) strlcpy(buf, "unknown", DLADM_STRSIZE); 45633a62633bSyz147064 return (buf); 45647c478bd9Sstevel@tonic-gate } 45657c478bd9Sstevel@tonic-gate 4566d62bc4baSyz147064 return (dladm_linkduplex2str(linkduplex, buf)); 45677c478bd9Sstevel@tonic-gate } 45680ba2cbe9Sxc151355 45690ba2cbe9Sxc151355 static int 45708002d411SSowmini Varadhan parse_wifi_fields(char *str, ofmt_handle_t *ofmt, uint_t cmdtype, 45718002d411SSowmini Varadhan boolean_t parsable) 45720ba2cbe9Sxc151355 { 45738002d411SSowmini Varadhan ofmt_field_t *template, *of; 45748002d411SSowmini Varadhan ofmt_cb_t *fn; 45758002d411SSowmini Varadhan ofmt_status_t oferr; 45760ba2cbe9Sxc151355 45770ba2cbe9Sxc151355 if (cmdtype == WIFI_CMD_SCAN) { 45788002d411SSowmini Varadhan template = wifi_common_fields; 45790ba2cbe9Sxc151355 if (str == NULL) 45800ba2cbe9Sxc151355 str = def_scan_wifi_fields; 45810ba2cbe9Sxc151355 if (strcasecmp(str, "all") == 0) 45820ba2cbe9Sxc151355 str = all_scan_wifi_fields; 45838002d411SSowmini Varadhan fn = print_wlan_attr_cb; 45840ba2cbe9Sxc151355 } else if (cmdtype == WIFI_CMD_SHOW) { 45858002d411SSowmini Varadhan bcopy(wifi_common_fields, &wifi_show_fields[2], 45868002d411SSowmini Varadhan sizeof (wifi_common_fields)); 45878002d411SSowmini Varadhan template = wifi_show_fields; 45880ba2cbe9Sxc151355 if (str == NULL) 45890ba2cbe9Sxc151355 str = def_show_wifi_fields; 45900ba2cbe9Sxc151355 if (strcasecmp(str, "all") == 0) 45910ba2cbe9Sxc151355 str = all_show_wifi_fields; 45928002d411SSowmini Varadhan fn = print_link_attr_cb; 45930ba2cbe9Sxc151355 } else { 45940ba2cbe9Sxc151355 return (-1); 45950ba2cbe9Sxc151355 } 45968002d411SSowmini Varadhan 45978002d411SSowmini Varadhan for (of = template; of->of_name != NULL; of++) { 45988002d411SSowmini Varadhan if (of->of_cb == NULL) 45998002d411SSowmini Varadhan of->of_cb = fn; 46008002d411SSowmini Varadhan } 46018002d411SSowmini Varadhan 46028002d411SSowmini Varadhan oferr = ofmt_open(str, template, (parsable ? OFMT_PARSABLE : 0), 46038002d411SSowmini Varadhan 0, ofmt); 46048002d411SSowmini Varadhan dladm_ofmt_check(oferr, parsable, *ofmt); 4605e7801d59Ssowmini return (0); 46060ba2cbe9Sxc151355 } 46070ba2cbe9Sxc151355 46080ba2cbe9Sxc151355 typedef struct print_wifi_state { 4609d62bc4baSyz147064 char *ws_link; 46108002d411SSowmini Varadhan boolean_t ws_parsable; 46110ba2cbe9Sxc151355 boolean_t ws_header; 46128002d411SSowmini Varadhan ofmt_handle_t ws_ofmt; 46130ba2cbe9Sxc151355 } print_wifi_state_t; 46140ba2cbe9Sxc151355 4615e7801d59Ssowmini typedef struct wlan_scan_args_s { 4616e7801d59Ssowmini print_wifi_state_t *ws_state; 4617e7801d59Ssowmini void *ws_attr; 4618e7801d59Ssowmini } wlan_scan_args_t; 46190ba2cbe9Sxc151355 46208002d411SSowmini Varadhan static boolean_t 46218002d411SSowmini Varadhan print_wlan_attr_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize) 46220ba2cbe9Sxc151355 { 46238002d411SSowmini Varadhan wlan_scan_args_t *w = ofarg->ofmt_cbarg; 4624e7801d59Ssowmini print_wifi_state_t *statep = w->ws_state; 4625e7801d59Ssowmini dladm_wlan_attr_t *attrp = w->ws_attr; 46268002d411SSowmini Varadhan char tmpbuf[DLADM_STRSIZE]; 46270ba2cbe9Sxc151355 46288002d411SSowmini Varadhan if (ofarg->ofmt_id == 0) { 46298002d411SSowmini Varadhan (void) strlcpy(buf, (char *)statep->ws_link, bufsize); 46308002d411SSowmini Varadhan return (B_TRUE); 46310ba2cbe9Sxc151355 } 46320ba2cbe9Sxc151355 46338002d411SSowmini Varadhan if ((ofarg->ofmt_id & attrp->wa_valid) == 0) 46348002d411SSowmini Varadhan return (B_TRUE); 46350ba2cbe9Sxc151355 46368002d411SSowmini Varadhan switch (ofarg->ofmt_id) { 4637f595a68aSyz147064 case DLADM_WLAN_ATTR_ESSID: 46388002d411SSowmini Varadhan (void) dladm_wlan_essid2str(&attrp->wa_essid, tmpbuf); 46390ba2cbe9Sxc151355 break; 4640f595a68aSyz147064 case DLADM_WLAN_ATTR_BSSID: 46418002d411SSowmini Varadhan (void) dladm_wlan_bssid2str(&attrp->wa_bssid, tmpbuf); 46420ba2cbe9Sxc151355 break; 4643f595a68aSyz147064 case DLADM_WLAN_ATTR_SECMODE: 46448002d411SSowmini Varadhan (void) dladm_wlan_secmode2str(&attrp->wa_secmode, tmpbuf); 46450ba2cbe9Sxc151355 break; 4646f595a68aSyz147064 case DLADM_WLAN_ATTR_STRENGTH: 46478002d411SSowmini Varadhan (void) dladm_wlan_strength2str(&attrp->wa_strength, tmpbuf); 46480ba2cbe9Sxc151355 break; 4649f595a68aSyz147064 case DLADM_WLAN_ATTR_MODE: 46508002d411SSowmini Varadhan (void) dladm_wlan_mode2str(&attrp->wa_mode, tmpbuf); 46510ba2cbe9Sxc151355 break; 4652f595a68aSyz147064 case DLADM_WLAN_ATTR_SPEED: 46538002d411SSowmini Varadhan (void) dladm_wlan_speed2str(&attrp->wa_speed, tmpbuf); 46548002d411SSowmini Varadhan (void) strlcat(tmpbuf, "Mb", sizeof (tmpbuf)); 46550ba2cbe9Sxc151355 break; 4656f595a68aSyz147064 case DLADM_WLAN_ATTR_AUTH: 46578002d411SSowmini Varadhan (void) dladm_wlan_auth2str(&attrp->wa_auth, tmpbuf); 46580ba2cbe9Sxc151355 break; 4659f595a68aSyz147064 case DLADM_WLAN_ATTR_BSSTYPE: 46608002d411SSowmini Varadhan (void) dladm_wlan_bsstype2str(&attrp->wa_bsstype, tmpbuf); 46610ba2cbe9Sxc151355 break; 46620ba2cbe9Sxc151355 } 46638002d411SSowmini Varadhan (void) strlcpy(buf, tmpbuf, bufsize); 46640ba2cbe9Sxc151355 46658002d411SSowmini Varadhan return (B_TRUE); 46660ba2cbe9Sxc151355 } 46670ba2cbe9Sxc151355 46680ba2cbe9Sxc151355 static boolean_t 4669f595a68aSyz147064 print_scan_results(void *arg, dladm_wlan_attr_t *attrp) 46700ba2cbe9Sxc151355 { 46710ba2cbe9Sxc151355 print_wifi_state_t *statep = arg; 4672e7801d59Ssowmini wlan_scan_args_t warg; 46730ba2cbe9Sxc151355 4674e7801d59Ssowmini bzero(&warg, sizeof (warg)); 4675e7801d59Ssowmini warg.ws_state = statep; 4676e7801d59Ssowmini warg.ws_attr = attrp; 46778002d411SSowmini Varadhan ofmt_print(statep->ws_ofmt, &warg); 46780ba2cbe9Sxc151355 return (B_TRUE); 46790ba2cbe9Sxc151355 } 46800ba2cbe9Sxc151355 4681d62bc4baSyz147064 static int 46824ac67f02SAnurag S. Maskey scan_wifi(dladm_handle_t dh, datalink_id_t linkid, void *arg) 46830ba2cbe9Sxc151355 { 46840ba2cbe9Sxc151355 print_wifi_state_t *statep = arg; 4685f595a68aSyz147064 dladm_status_t status; 4686d62bc4baSyz147064 char link[MAXLINKNAMELEN]; 4687d62bc4baSyz147064 46884ac67f02SAnurag S. Maskey if ((status = dladm_datalink_id2info(dh, linkid, NULL, NULL, NULL, link, 4689e7801d59Ssowmini sizeof (link))) != DLADM_STATUS_OK) { 4690d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 4691d62bc4baSyz147064 } 46920ba2cbe9Sxc151355 46930ba2cbe9Sxc151355 statep->ws_link = link; 46944ac67f02SAnurag S. Maskey status = dladm_wlan_scan(dh, linkid, statep, print_scan_results); 4695f595a68aSyz147064 if (status != DLADM_STATUS_OK) 4696d62bc4baSyz147064 die_dlerr(status, "cannot scan link '%s'", statep->ws_link); 469733343a97Smeem 4698d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 46990ba2cbe9Sxc151355 } 47000ba2cbe9Sxc151355 47018002d411SSowmini Varadhan static boolean_t 47028002d411SSowmini Varadhan print_wifi_status_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize) 47030ba2cbe9Sxc151355 { 47048002d411SSowmini Varadhan static char tmpbuf[DLADM_STRSIZE]; 47058002d411SSowmini Varadhan wlan_scan_args_t *w = ofarg->ofmt_cbarg; 47068002d411SSowmini Varadhan dladm_wlan_linkattr_t *attrp = w->ws_attr; 47078002d411SSowmini Varadhan 47088002d411SSowmini Varadhan if ((ofarg->ofmt_id & attrp->la_valid) != 0) { 47098002d411SSowmini Varadhan (void) dladm_wlan_linkstatus2str(&attrp->la_status, tmpbuf); 47108002d411SSowmini Varadhan (void) strlcpy(buf, tmpbuf, bufsize); 47118002d411SSowmini Varadhan } 47128002d411SSowmini Varadhan return (B_TRUE); 47138002d411SSowmini Varadhan } 47148002d411SSowmini Varadhan 47158002d411SSowmini Varadhan static boolean_t 47168002d411SSowmini Varadhan print_link_attr_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize) 47178002d411SSowmini Varadhan { 47188002d411SSowmini Varadhan wlan_scan_args_t *w = ofarg->ofmt_cbarg, w1; 4719e7801d59Ssowmini print_wifi_state_t *statep = w->ws_state; 4720e7801d59Ssowmini dladm_wlan_linkattr_t *attrp = w->ws_attr; 47210ba2cbe9Sxc151355 4722e7801d59Ssowmini bzero(&w1, sizeof (w1)); 4723e7801d59Ssowmini w1.ws_state = statep; 4724e7801d59Ssowmini w1.ws_attr = &attrp->la_wlan_attr; 47258002d411SSowmini Varadhan ofarg->ofmt_cbarg = &w1; 47268002d411SSowmini Varadhan return (print_wlan_attr_cb(ofarg, buf, bufsize)); 47270ba2cbe9Sxc151355 } 47280ba2cbe9Sxc151355 4729d62bc4baSyz147064 static int 47304ac67f02SAnurag S. Maskey show_wifi(dladm_handle_t dh, datalink_id_t linkid, void *arg) 47310ba2cbe9Sxc151355 { 47320ba2cbe9Sxc151355 print_wifi_state_t *statep = arg; 4733f595a68aSyz147064 dladm_wlan_linkattr_t attr; 4734f595a68aSyz147064 dladm_status_t status; 4735d62bc4baSyz147064 char link[MAXLINKNAMELEN]; 4736e7801d59Ssowmini wlan_scan_args_t warg; 47370ba2cbe9Sxc151355 47384ac67f02SAnurag S. Maskey if ((status = dladm_datalink_id2info(dh, linkid, NULL, NULL, NULL, link, 4739e7801d59Ssowmini sizeof (link))) != DLADM_STATUS_OK) { 4740d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 4741d62bc4baSyz147064 } 4742d62bc4baSyz147064 47435f5c9f54SAnurag S. Maskey /* dladm_wlan_get_linkattr() memsets attr with 0 */ 47444ac67f02SAnurag S. Maskey status = dladm_wlan_get_linkattr(dh, linkid, &attr); 4745f595a68aSyz147064 if (status != DLADM_STATUS_OK) 4746d62bc4baSyz147064 die_dlerr(status, "cannot get link attributes for %s", link); 4747d62bc4baSyz147064 4748d62bc4baSyz147064 statep->ws_link = link; 47490ba2cbe9Sxc151355 4750e7801d59Ssowmini bzero(&warg, sizeof (warg)); 4751e7801d59Ssowmini warg.ws_state = statep; 4752e7801d59Ssowmini warg.ws_attr = &attr; 47538002d411SSowmini Varadhan ofmt_print(statep->ws_ofmt, &warg); 4754d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 47550ba2cbe9Sxc151355 } 47560ba2cbe9Sxc151355 47570ba2cbe9Sxc151355 static void 47588d5c46e6Sam223141 do_display_wifi(int argc, char **argv, int cmd, const char *use) 47590ba2cbe9Sxc151355 { 47600ba2cbe9Sxc151355 int option; 47610ba2cbe9Sxc151355 char *fields_str = NULL; 47624ac67f02SAnurag S. Maskey int (*callback)(dladm_handle_t, datalink_id_t, void *); 47630ba2cbe9Sxc151355 print_wifi_state_t state; 4764d62bc4baSyz147064 datalink_id_t linkid = DATALINK_ALL_LINKID; 4765f595a68aSyz147064 dladm_status_t status; 47660ba2cbe9Sxc151355 47670ba2cbe9Sxc151355 if (cmd == WIFI_CMD_SCAN) 47680ba2cbe9Sxc151355 callback = scan_wifi; 47690ba2cbe9Sxc151355 else if (cmd == WIFI_CMD_SHOW) 47700ba2cbe9Sxc151355 callback = show_wifi; 47710ba2cbe9Sxc151355 else 47720ba2cbe9Sxc151355 return; 47730ba2cbe9Sxc151355 47748002d411SSowmini Varadhan state.ws_parsable = B_FALSE; 47750ba2cbe9Sxc151355 state.ws_header = B_TRUE; 47760ba2cbe9Sxc151355 opterr = 0; 47770ba2cbe9Sxc151355 while ((option = getopt_long(argc, argv, ":o:p", 47780ba2cbe9Sxc151355 wifi_longopts, NULL)) != -1) { 47790ba2cbe9Sxc151355 switch (option) { 47800ba2cbe9Sxc151355 case 'o': 47810ba2cbe9Sxc151355 fields_str = optarg; 47820ba2cbe9Sxc151355 break; 47830ba2cbe9Sxc151355 case 'p': 47848002d411SSowmini Varadhan state.ws_parsable = B_TRUE; 47850ba2cbe9Sxc151355 break; 47860ba2cbe9Sxc151355 default: 47878d5c46e6Sam223141 die_opterr(optopt, option, use); 47880ba2cbe9Sxc151355 } 47890ba2cbe9Sxc151355 } 47900ba2cbe9Sxc151355 47918002d411SSowmini Varadhan if (state.ws_parsable && fields_str == NULL) 47920d365605Sschuster die("-p requires -o"); 47930d365605Sschuster 47948002d411SSowmini Varadhan if (state.ws_parsable && strcasecmp(fields_str, "all") == 0) 47950d365605Sschuster die("\"-o all\" is invalid with -p"); 47960d365605Sschuster 4797d62bc4baSyz147064 if (optind == (argc - 1)) { 47984ac67f02SAnurag S. Maskey if ((status = dladm_name2info(handle, argv[optind], &linkid, 47994ac67f02SAnurag S. Maskey NULL, NULL, NULL)) != DLADM_STATUS_OK) { 4800d62bc4baSyz147064 die_dlerr(status, "link %s is not valid", argv[optind]); 4801d62bc4baSyz147064 } 4802d62bc4baSyz147064 } else if (optind != argc) { 48030ba2cbe9Sxc151355 usage(); 4804d62bc4baSyz147064 } 48050ba2cbe9Sxc151355 48068002d411SSowmini Varadhan if (parse_wifi_fields(fields_str, &state.ws_ofmt, cmd, 48078002d411SSowmini Varadhan state.ws_parsable) < 0) 480833343a97Smeem die("invalid field(s) specified"); 480933343a97Smeem 4810d62bc4baSyz147064 if (linkid == DATALINK_ALL_LINKID) { 48114ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(callback, handle, &state, 4812d62bc4baSyz147064 DATALINK_CLASS_PHYS, DL_WIFI, DLADM_OPT_ACTIVE); 48130ba2cbe9Sxc151355 } else { 48144ac67f02SAnurag S. Maskey (void) (*callback)(handle, linkid, &state); 48150ba2cbe9Sxc151355 } 48168002d411SSowmini Varadhan ofmt_close(state.ws_ofmt); 48170ba2cbe9Sxc151355 } 48180ba2cbe9Sxc151355 48190ba2cbe9Sxc151355 static void 48208d5c46e6Sam223141 do_scan_wifi(int argc, char **argv, const char *use) 48210ba2cbe9Sxc151355 { 48228d5c46e6Sam223141 do_display_wifi(argc, argv, WIFI_CMD_SCAN, use); 48230ba2cbe9Sxc151355 } 48240ba2cbe9Sxc151355 48250ba2cbe9Sxc151355 static void 48268d5c46e6Sam223141 do_show_wifi(int argc, char **argv, const char *use) 48270ba2cbe9Sxc151355 { 48288d5c46e6Sam223141 do_display_wifi(argc, argv, WIFI_CMD_SHOW, use); 48290ba2cbe9Sxc151355 } 48300ba2cbe9Sxc151355 48310ba2cbe9Sxc151355 typedef struct wlan_count_attr { 48320ba2cbe9Sxc151355 uint_t wc_count; 4833d62bc4baSyz147064 datalink_id_t wc_linkid; 48340ba2cbe9Sxc151355 } wlan_count_attr_t; 48350ba2cbe9Sxc151355 48364ac67f02SAnurag S. Maskey /* ARGSUSED */ 4837d62bc4baSyz147064 static int 48384ac67f02SAnurag S. Maskey do_count_wlan(dladm_handle_t dh, datalink_id_t linkid, void *arg) 48390ba2cbe9Sxc151355 { 484033343a97Smeem wlan_count_attr_t *cp = arg; 48410ba2cbe9Sxc151355 48420ba2cbe9Sxc151355 if (cp->wc_count == 0) 4843d62bc4baSyz147064 cp->wc_linkid = linkid; 48440ba2cbe9Sxc151355 cp->wc_count++; 4845d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 48460ba2cbe9Sxc151355 } 48470ba2cbe9Sxc151355 48480ba2cbe9Sxc151355 static int 4849a399b765Szf162725 parse_wlan_keys(char *str, dladm_wlan_key_t **keys, uint_t *key_countp) 48500ba2cbe9Sxc151355 { 48510ba2cbe9Sxc151355 uint_t i; 4852a399b765Szf162725 dladm_wlan_key_t *wk; 48538002d411SSowmini Varadhan int nfields = 1; 48548002d411SSowmini Varadhan char *field, *token, *lasts = NULL, c; 48550ba2cbe9Sxc151355 48568002d411SSowmini Varadhan token = str; 48578002d411SSowmini Varadhan while ((c = *token++) != NULL) { 48588002d411SSowmini Varadhan if (c == ',') 48598002d411SSowmini Varadhan nfields++; 48608002d411SSowmini Varadhan } 48618002d411SSowmini Varadhan token = strdup(str); 48628002d411SSowmini Varadhan if (token == NULL) 48630ba2cbe9Sxc151355 return (-1); 48640ba2cbe9Sxc151355 48658002d411SSowmini Varadhan wk = malloc(nfields * sizeof (dladm_wlan_key_t)); 48660ba2cbe9Sxc151355 if (wk == NULL) 48670ba2cbe9Sxc151355 goto fail; 48680ba2cbe9Sxc151355 48698002d411SSowmini Varadhan token = str; 48708002d411SSowmini Varadhan for (i = 0; i < nfields; i++) { 48710ba2cbe9Sxc151355 char *s; 48720ba2cbe9Sxc151355 dladm_secobj_class_t class; 48730ba2cbe9Sxc151355 dladm_status_t status; 48740ba2cbe9Sxc151355 48758002d411SSowmini Varadhan field = strtok_r(token, ",", &lasts); 48768002d411SSowmini Varadhan token = NULL; 48778002d411SSowmini Varadhan 48788002d411SSowmini Varadhan (void) strlcpy(wk[i].wk_name, field, 4879a399b765Szf162725 DLADM_WLAN_MAX_KEYNAME_LEN); 48800ba2cbe9Sxc151355 48810ba2cbe9Sxc151355 wk[i].wk_idx = 1; 48820ba2cbe9Sxc151355 if ((s = strrchr(wk[i].wk_name, ':')) != NULL) { 48830ba2cbe9Sxc151355 if (s[1] == '\0' || s[2] != '\0' || !isdigit(s[1])) 48840ba2cbe9Sxc151355 goto fail; 48850ba2cbe9Sxc151355 48860ba2cbe9Sxc151355 wk[i].wk_idx = (uint_t)(s[1] - '0'); 48870ba2cbe9Sxc151355 *s = '\0'; 48880ba2cbe9Sxc151355 } 4889a399b765Szf162725 wk[i].wk_len = DLADM_WLAN_MAX_KEY_LEN; 48900ba2cbe9Sxc151355 48914ac67f02SAnurag S. Maskey status = dladm_get_secobj(handle, wk[i].wk_name, &class, 48920ba2cbe9Sxc151355 wk[i].wk_val, &wk[i].wk_len, 0); 48930ba2cbe9Sxc151355 if (status != DLADM_STATUS_OK) { 48940ba2cbe9Sxc151355 if (status == DLADM_STATUS_NOTFOUND) { 48954ac67f02SAnurag S. Maskey status = dladm_get_secobj(handle, wk[i].wk_name, 48960ba2cbe9Sxc151355 &class, wk[i].wk_val, &wk[i].wk_len, 48970ba2cbe9Sxc151355 DLADM_OPT_PERSIST); 48980ba2cbe9Sxc151355 } 48990ba2cbe9Sxc151355 if (status != DLADM_STATUS_OK) 49000ba2cbe9Sxc151355 goto fail; 49010ba2cbe9Sxc151355 } 4902a399b765Szf162725 wk[i].wk_class = class; 49030ba2cbe9Sxc151355 } 49040ba2cbe9Sxc151355 *keys = wk; 49050ba2cbe9Sxc151355 *key_countp = i; 49068002d411SSowmini Varadhan free(token); 49070ba2cbe9Sxc151355 return (0); 49080ba2cbe9Sxc151355 fail: 49090ba2cbe9Sxc151355 free(wk); 49108002d411SSowmini Varadhan free(token); 49110ba2cbe9Sxc151355 return (-1); 49120ba2cbe9Sxc151355 } 49130ba2cbe9Sxc151355 49140ba2cbe9Sxc151355 static void 49158d5c46e6Sam223141 do_connect_wifi(int argc, char **argv, const char *use) 49160ba2cbe9Sxc151355 { 49170ba2cbe9Sxc151355 int option; 4918f595a68aSyz147064 dladm_wlan_attr_t attr, *attrp; 4919f595a68aSyz147064 dladm_status_t status = DLADM_STATUS_OK; 4920f595a68aSyz147064 int timeout = DLADM_WLAN_CONNECT_TIMEOUT_DEFAULT; 4921d62bc4baSyz147064 datalink_id_t linkid = DATALINK_ALL_LINKID; 4922a399b765Szf162725 dladm_wlan_key_t *keys = NULL; 49230ba2cbe9Sxc151355 uint_t key_count = 0; 49240ba2cbe9Sxc151355 uint_t flags = 0; 4925f595a68aSyz147064 dladm_wlan_secmode_t keysecmode = DLADM_WLAN_SECMODE_NONE; 4926a399b765Szf162725 char buf[DLADM_STRSIZE]; 49270ba2cbe9Sxc151355 49280ba2cbe9Sxc151355 opterr = 0; 49290ba2cbe9Sxc151355 (void) memset(&attr, 0, sizeof (attr)); 49300ba2cbe9Sxc151355 while ((option = getopt_long(argc, argv, ":e:i:a:m:b:s:k:T:c", 49310ba2cbe9Sxc151355 wifi_longopts, NULL)) != -1) { 49320ba2cbe9Sxc151355 switch (option) { 49330ba2cbe9Sxc151355 case 'e': 4934f595a68aSyz147064 status = dladm_wlan_str2essid(optarg, &attr.wa_essid); 4935f595a68aSyz147064 if (status != DLADM_STATUS_OK) 493633343a97Smeem die("invalid ESSID '%s'", optarg); 493733343a97Smeem 4938f595a68aSyz147064 attr.wa_valid |= DLADM_WLAN_ATTR_ESSID; 49390ba2cbe9Sxc151355 /* 49400ba2cbe9Sxc151355 * Try to connect without doing a scan. 49410ba2cbe9Sxc151355 */ 4942f595a68aSyz147064 flags |= DLADM_WLAN_CONNECT_NOSCAN; 49430ba2cbe9Sxc151355 break; 49440ba2cbe9Sxc151355 case 'i': 4945f595a68aSyz147064 status = dladm_wlan_str2bssid(optarg, &attr.wa_bssid); 4946f595a68aSyz147064 if (status != DLADM_STATUS_OK) 494733343a97Smeem die("invalid BSSID %s", optarg); 494833343a97Smeem 4949f595a68aSyz147064 attr.wa_valid |= DLADM_WLAN_ATTR_BSSID; 49500ba2cbe9Sxc151355 break; 49510ba2cbe9Sxc151355 case 'a': 4952f595a68aSyz147064 status = dladm_wlan_str2auth(optarg, &attr.wa_auth); 4953f595a68aSyz147064 if (status != DLADM_STATUS_OK) 495433343a97Smeem die("invalid authentication mode '%s'", optarg); 495533343a97Smeem 4956f595a68aSyz147064 attr.wa_valid |= DLADM_WLAN_ATTR_AUTH; 49570ba2cbe9Sxc151355 break; 49580ba2cbe9Sxc151355 case 'm': 4959f595a68aSyz147064 status = dladm_wlan_str2mode(optarg, &attr.wa_mode); 4960f595a68aSyz147064 if (status != DLADM_STATUS_OK) 496133343a97Smeem die("invalid mode '%s'", optarg); 496233343a97Smeem 4963f595a68aSyz147064 attr.wa_valid |= DLADM_WLAN_ATTR_MODE; 49640ba2cbe9Sxc151355 break; 49650ba2cbe9Sxc151355 case 'b': 4966f595a68aSyz147064 if ((status = dladm_wlan_str2bsstype(optarg, 4967f595a68aSyz147064 &attr.wa_bsstype)) != DLADM_STATUS_OK) { 496833343a97Smeem die("invalid bsstype '%s'", optarg); 4969f595a68aSyz147064 } 497033343a97Smeem 4971f595a68aSyz147064 attr.wa_valid |= DLADM_WLAN_ATTR_BSSTYPE; 49720ba2cbe9Sxc151355 break; 49730ba2cbe9Sxc151355 case 's': 4974f595a68aSyz147064 if ((status = dladm_wlan_str2secmode(optarg, 4975f595a68aSyz147064 &attr.wa_secmode)) != DLADM_STATUS_OK) { 497633343a97Smeem die("invalid security mode '%s'", optarg); 4977f595a68aSyz147064 } 497833343a97Smeem 4979f595a68aSyz147064 attr.wa_valid |= DLADM_WLAN_ATTR_SECMODE; 49800ba2cbe9Sxc151355 break; 49810ba2cbe9Sxc151355 case 'k': 4982a399b765Szf162725 if (parse_wlan_keys(optarg, &keys, &key_count) < 0) 498333343a97Smeem die("invalid key(s) '%s'", optarg); 498433343a97Smeem 4985a399b765Szf162725 if (keys[0].wk_class == DLADM_SECOBJ_CLASS_WEP) 4986f595a68aSyz147064 keysecmode = DLADM_WLAN_SECMODE_WEP; 4987a399b765Szf162725 else 4988a399b765Szf162725 keysecmode = DLADM_WLAN_SECMODE_WPA; 49890ba2cbe9Sxc151355 break; 49900ba2cbe9Sxc151355 case 'T': 49910ba2cbe9Sxc151355 if (strcasecmp(optarg, "forever") == 0) { 49920ba2cbe9Sxc151355 timeout = -1; 49930ba2cbe9Sxc151355 break; 49940ba2cbe9Sxc151355 } 499533343a97Smeem if (!str2int(optarg, &timeout) || timeout < 0) 499633343a97Smeem die("invalid timeout value '%s'", optarg); 49970ba2cbe9Sxc151355 break; 49980ba2cbe9Sxc151355 case 'c': 4999f595a68aSyz147064 flags |= DLADM_WLAN_CONNECT_CREATEIBSS; 5000a399b765Szf162725 flags |= DLADM_WLAN_CONNECT_CREATEIBSS; 50010ba2cbe9Sxc151355 break; 50020ba2cbe9Sxc151355 default: 50038d5c46e6Sam223141 die_opterr(optopt, option, use); 50040ba2cbe9Sxc151355 break; 50050ba2cbe9Sxc151355 } 50060ba2cbe9Sxc151355 } 50070ba2cbe9Sxc151355 5008f595a68aSyz147064 if (keysecmode == DLADM_WLAN_SECMODE_NONE) { 5009a399b765Szf162725 if ((attr.wa_valid & DLADM_WLAN_ATTR_SECMODE) != 0) { 5010a399b765Szf162725 die("key required for security mode '%s'", 5011a399b765Szf162725 dladm_wlan_secmode2str(&attr.wa_secmode, buf)); 5012a399b765Szf162725 } 50130ba2cbe9Sxc151355 } else { 5014f595a68aSyz147064 if ((attr.wa_valid & DLADM_WLAN_ATTR_SECMODE) != 0 && 501533343a97Smeem attr.wa_secmode != keysecmode) 501633343a97Smeem die("incompatible -s and -k options"); 5017f595a68aSyz147064 attr.wa_valid |= DLADM_WLAN_ATTR_SECMODE; 5018a399b765Szf162725 attr.wa_secmode = keysecmode; 5019a399b765Szf162725 } 50200ba2cbe9Sxc151355 5021d62bc4baSyz147064 if (optind == (argc - 1)) { 50224ac67f02SAnurag S. Maskey if ((status = dladm_name2info(handle, argv[optind], &linkid, 50234ac67f02SAnurag S. Maskey NULL, NULL, NULL)) != DLADM_STATUS_OK) { 5024d62bc4baSyz147064 die_dlerr(status, "link %s is not valid", argv[optind]); 5025d62bc4baSyz147064 } 5026d62bc4baSyz147064 } else if (optind != argc) { 50270ba2cbe9Sxc151355 usage(); 5028d62bc4baSyz147064 } 50290ba2cbe9Sxc151355 5030d62bc4baSyz147064 if (linkid == DATALINK_ALL_LINKID) { 50310ba2cbe9Sxc151355 wlan_count_attr_t wcattr; 50320ba2cbe9Sxc151355 5033d62bc4baSyz147064 wcattr.wc_linkid = DATALINK_INVALID_LINKID; 50340ba2cbe9Sxc151355 wcattr.wc_count = 0; 50354ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(do_count_wlan, handle, &wcattr, 5036d62bc4baSyz147064 DATALINK_CLASS_PHYS, DL_WIFI, DLADM_OPT_ACTIVE); 50370ba2cbe9Sxc151355 if (wcattr.wc_count == 0) { 503833343a97Smeem die("no wifi links are available"); 50390ba2cbe9Sxc151355 } else if (wcattr.wc_count > 1) { 504033343a97Smeem die("link name is required when more than one wifi " 504133343a97Smeem "link is available"); 50420ba2cbe9Sxc151355 } 5043d62bc4baSyz147064 linkid = wcattr.wc_linkid; 50440ba2cbe9Sxc151355 } 50450ba2cbe9Sxc151355 attrp = (attr.wa_valid == 0) ? NULL : &attr; 504633343a97Smeem again: 50474ac67f02SAnurag S. Maskey if ((status = dladm_wlan_connect(handle, linkid, attrp, timeout, keys, 5048f595a68aSyz147064 key_count, flags)) != DLADM_STATUS_OK) { 5049f595a68aSyz147064 if ((flags & DLADM_WLAN_CONNECT_NOSCAN) != 0) { 50500ba2cbe9Sxc151355 /* 505133343a97Smeem * Try again with scanning and filtering. 50520ba2cbe9Sxc151355 */ 5053f595a68aSyz147064 flags &= ~DLADM_WLAN_CONNECT_NOSCAN; 505433343a97Smeem goto again; 50550ba2cbe9Sxc151355 } 505633343a97Smeem 5057f595a68aSyz147064 if (status == DLADM_STATUS_NOTFOUND) { 50580ba2cbe9Sxc151355 if (attr.wa_valid == 0) { 505933343a97Smeem die("no wifi networks are available"); 50600ba2cbe9Sxc151355 } else { 506133343a97Smeem die("no wifi networks with the specified " 506233343a97Smeem "criteria are available"); 50630ba2cbe9Sxc151355 } 50640ba2cbe9Sxc151355 } 5065d62bc4baSyz147064 die_dlerr(status, "cannot connect"); 50660ba2cbe9Sxc151355 } 50670ba2cbe9Sxc151355 free(keys); 50680ba2cbe9Sxc151355 } 50690ba2cbe9Sxc151355 50700ba2cbe9Sxc151355 /* ARGSUSED */ 5071d62bc4baSyz147064 static int 50724ac67f02SAnurag S. Maskey do_all_disconnect_wifi(dladm_handle_t dh, datalink_id_t linkid, void *arg) 50730ba2cbe9Sxc151355 { 5074f595a68aSyz147064 dladm_status_t status; 50750ba2cbe9Sxc151355 50764ac67f02SAnurag S. Maskey status = dladm_wlan_disconnect(dh, linkid); 5077f595a68aSyz147064 if (status != DLADM_STATUS_OK) 5078d62bc4baSyz147064 warn_dlerr(status, "cannot disconnect link"); 507933343a97Smeem 5080d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 50810ba2cbe9Sxc151355 } 50820ba2cbe9Sxc151355 50830ba2cbe9Sxc151355 static void 50848d5c46e6Sam223141 do_disconnect_wifi(int argc, char **argv, const char *use) 50850ba2cbe9Sxc151355 { 50860ba2cbe9Sxc151355 int option; 5087d62bc4baSyz147064 datalink_id_t linkid = DATALINK_ALL_LINKID; 50880ba2cbe9Sxc151355 boolean_t all_links = B_FALSE; 5089f595a68aSyz147064 dladm_status_t status; 50900ba2cbe9Sxc151355 wlan_count_attr_t wcattr; 50910ba2cbe9Sxc151355 50920ba2cbe9Sxc151355 opterr = 0; 50930ba2cbe9Sxc151355 while ((option = getopt_long(argc, argv, ":a", 50940ba2cbe9Sxc151355 wifi_longopts, NULL)) != -1) { 50950ba2cbe9Sxc151355 switch (option) { 50960ba2cbe9Sxc151355 case 'a': 50970ba2cbe9Sxc151355 all_links = B_TRUE; 50980ba2cbe9Sxc151355 break; 50990ba2cbe9Sxc151355 default: 51008d5c46e6Sam223141 die_opterr(optopt, option, use); 51010ba2cbe9Sxc151355 break; 51020ba2cbe9Sxc151355 } 51030ba2cbe9Sxc151355 } 51040ba2cbe9Sxc151355 5105d62bc4baSyz147064 if (optind == (argc - 1)) { 51064ac67f02SAnurag S. Maskey if ((status = dladm_name2info(handle, argv[optind], &linkid, 51074ac67f02SAnurag S. Maskey NULL, NULL, NULL)) != DLADM_STATUS_OK) { 5108d62bc4baSyz147064 die_dlerr(status, "link %s is not valid", argv[optind]); 5109d62bc4baSyz147064 } 5110d62bc4baSyz147064 } else if (optind != argc) { 51110ba2cbe9Sxc151355 usage(); 5112d62bc4baSyz147064 } 51130ba2cbe9Sxc151355 5114d62bc4baSyz147064 if (linkid == DATALINK_ALL_LINKID) { 51150ba2cbe9Sxc151355 if (!all_links) { 5116d62bc4baSyz147064 wcattr.wc_linkid = linkid; 51170ba2cbe9Sxc151355 wcattr.wc_count = 0; 51184ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(do_count_wlan, handle, 51194ac67f02SAnurag S. Maskey &wcattr, DATALINK_CLASS_PHYS, DL_WIFI, 51204ac67f02SAnurag S. Maskey DLADM_OPT_ACTIVE); 51210ba2cbe9Sxc151355 if (wcattr.wc_count == 0) { 512233343a97Smeem die("no wifi links are available"); 51230ba2cbe9Sxc151355 } else if (wcattr.wc_count > 1) { 512433343a97Smeem die("link name is required when more than " 512533343a97Smeem "one wifi link is available"); 51260ba2cbe9Sxc151355 } 5127d62bc4baSyz147064 linkid = wcattr.wc_linkid; 51280ba2cbe9Sxc151355 } else { 5129d62bc4baSyz147064 (void) dladm_walk_datalink_id(do_all_disconnect_wifi, 51304ac67f02SAnurag S. Maskey handle, NULL, DATALINK_CLASS_PHYS, DL_WIFI, 5131d62bc4baSyz147064 DLADM_OPT_ACTIVE); 51320ba2cbe9Sxc151355 return; 51330ba2cbe9Sxc151355 } 51340ba2cbe9Sxc151355 } 51354ac67f02SAnurag S. Maskey status = dladm_wlan_disconnect(handle, linkid); 5136f595a68aSyz147064 if (status != DLADM_STATUS_OK) 5137d62bc4baSyz147064 die_dlerr(status, "cannot disconnect"); 51380ba2cbe9Sxc151355 } 51390ba2cbe9Sxc151355 51400ba2cbe9Sxc151355 static void 5141d62bc4baSyz147064 print_linkprop(datalink_id_t linkid, show_linkprop_state_t *statep, 51424ac67f02SAnurag S. Maskey const char *propname, dladm_prop_type_t type, const char *format, 51434ac67f02SAnurag S. Maskey char **pptr) 51440ba2cbe9Sxc151355 { 51450ba2cbe9Sxc151355 int i; 51460ba2cbe9Sxc151355 char *ptr, *lim; 51470ba2cbe9Sxc151355 char buf[DLADM_STRSIZE]; 5148da14cebeSEric Cheng char *unknown = "--", *notsup = ""; 51490ba2cbe9Sxc151355 char **propvals = statep->ls_propvals; 5150d62bc4baSyz147064 uint_t valcnt = DLADM_MAX_PROP_VALCNT; 51510ba2cbe9Sxc151355 dladm_status_t status; 51520ba2cbe9Sxc151355 51534ac67f02SAnurag S. Maskey status = dladm_get_linkprop(handle, linkid, type, propname, propvals, 51544ac67f02SAnurag S. Maskey &valcnt); 51550ba2cbe9Sxc151355 if (status != DLADM_STATUS_OK) { 5156f595a68aSyz147064 if (status == DLADM_STATUS_TEMPONLY) { 5157d62bc4baSyz147064 if (type == DLADM_PROP_VAL_MODIFIABLE && 5158d62bc4baSyz147064 statep->ls_persist) { 5159d62bc4baSyz147064 valcnt = 1; 5160d62bc4baSyz147064 propvals = &unknown; 5161d62bc4baSyz147064 } else { 5162f595a68aSyz147064 statep->ls_status = status; 5163e7801d59Ssowmini statep->ls_retstatus = status; 5164f595a68aSyz147064 return; 5165d62bc4baSyz147064 } 5166f595a68aSyz147064 } else if (status == DLADM_STATUS_NOTSUP || 5167f595a68aSyz147064 statep->ls_persist) { 51680ba2cbe9Sxc151355 valcnt = 1; 5169afdda45fSVasumathi Sundaram - Sun Microsystems if (type == DLADM_PROP_VAL_CURRENT || 5170afdda45fSVasumathi Sundaram - Sun Microsystems type == DLADM_PROP_VAL_PERM) 51710ba2cbe9Sxc151355 propvals = &unknown; 51720ba2cbe9Sxc151355 else 51730ba2cbe9Sxc151355 propvals = ¬sup; 5174149b7eb2SSowmini Varadhan } else if (status == DLADM_STATUS_NOTDEFINED) { 5175149b7eb2SSowmini Varadhan propvals = ¬sup; /* STR_UNDEF_VAL */ 51760ba2cbe9Sxc151355 } else { 5177e7801d59Ssowmini if (statep->ls_proplist && 5178e7801d59Ssowmini statep->ls_status == DLADM_STATUS_OK) { 5179f595a68aSyz147064 warn_dlerr(status, 5180f595a68aSyz147064 "cannot get link property '%s' for %s", 5181f595a68aSyz147064 propname, statep->ls_link); 5182d62bc4baSyz147064 } 5183e7801d59Ssowmini statep->ls_status = status; 5184e7801d59Ssowmini statep->ls_retstatus = status; 5185f595a68aSyz147064 return; 51860ba2cbe9Sxc151355 } 51870ba2cbe9Sxc151355 } 51880ba2cbe9Sxc151355 5189e7801d59Ssowmini statep->ls_status = DLADM_STATUS_OK; 5190e7801d59Ssowmini 51910ba2cbe9Sxc151355 ptr = buf; 51920ba2cbe9Sxc151355 lim = buf + DLADM_STRSIZE; 51930ba2cbe9Sxc151355 for (i = 0; i < valcnt; i++) { 51948002d411SSowmini Varadhan if (propvals[i][0] == '\0' && !statep->ls_parsable) 51958002d411SSowmini Varadhan ptr += snprintf(ptr, lim - ptr, "--,"); 51960ba2cbe9Sxc151355 else 51970ba2cbe9Sxc151355 ptr += snprintf(ptr, lim - ptr, "%s,", propvals[i]); 51980ba2cbe9Sxc151355 if (ptr >= lim) 51990ba2cbe9Sxc151355 break; 52000ba2cbe9Sxc151355 } 52010ba2cbe9Sxc151355 if (valcnt > 0) 52020ba2cbe9Sxc151355 buf[strlen(buf) - 1] = '\0'; 52030ba2cbe9Sxc151355 52040ba2cbe9Sxc151355 lim = statep->ls_line + MAX_PROP_LINE; 52058002d411SSowmini Varadhan if (statep->ls_parsable) { 52060ba2cbe9Sxc151355 *pptr += snprintf(*pptr, lim - *pptr, 5207e7801d59Ssowmini "%s", buf); 52080ba2cbe9Sxc151355 } else { 52090ba2cbe9Sxc151355 *pptr += snprintf(*pptr, lim - *pptr, format, buf); 52100ba2cbe9Sxc151355 } 52110ba2cbe9Sxc151355 } 52120ba2cbe9Sxc151355 52138002d411SSowmini Varadhan static boolean_t 52148002d411SSowmini Varadhan print_linkprop_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize) 5215e7801d59Ssowmini { 52168002d411SSowmini Varadhan linkprop_args_t *arg = ofarg->ofmt_cbarg; 5217e7801d59Ssowmini char *propname = arg->ls_propname; 5218e7801d59Ssowmini show_linkprop_state_t *statep = arg->ls_state; 5219e7801d59Ssowmini char *ptr = statep->ls_line; 5220e7801d59Ssowmini char *lim = ptr + MAX_PROP_LINE; 5221e7801d59Ssowmini datalink_id_t linkid = arg->ls_linkid; 5222e7801d59Ssowmini 52238002d411SSowmini Varadhan switch (ofarg->ofmt_id) { 5224e7801d59Ssowmini case LINKPROP_LINK: 5225e7801d59Ssowmini (void) snprintf(ptr, lim - ptr, "%s", statep->ls_link); 5226e7801d59Ssowmini break; 5227e7801d59Ssowmini case LINKPROP_PROPERTY: 5228e7801d59Ssowmini (void) snprintf(ptr, lim - ptr, "%s", propname); 5229e7801d59Ssowmini break; 5230e7801d59Ssowmini case LINKPROP_VALUE: 5231e7801d59Ssowmini print_linkprop(linkid, statep, propname, 5232e7801d59Ssowmini statep->ls_persist ? DLADM_PROP_VAL_PERSISTENT : 5233e7801d59Ssowmini DLADM_PROP_VAL_CURRENT, "%s", &ptr); 5234e7801d59Ssowmini /* 5235e7801d59Ssowmini * If we failed to query the link property, for example, query 5236e7801d59Ssowmini * the persistent value of a non-persistable link property, 5237e7801d59Ssowmini * simply skip the output. 5238e7801d59Ssowmini */ 5239e7801d59Ssowmini if (statep->ls_status != DLADM_STATUS_OK) 5240e7801d59Ssowmini goto skip; 5241e7801d59Ssowmini ptr = statep->ls_line; 5242e7801d59Ssowmini break; 5243afdda45fSVasumathi Sundaram - Sun Microsystems case LINKPROP_PERM: 5244afdda45fSVasumathi Sundaram - Sun Microsystems print_linkprop(linkid, statep, propname, 5245afdda45fSVasumathi Sundaram - Sun Microsystems DLADM_PROP_VAL_PERM, "%s", &ptr); 5246afdda45fSVasumathi Sundaram - Sun Microsystems if (statep->ls_status != DLADM_STATUS_OK) 5247afdda45fSVasumathi Sundaram - Sun Microsystems goto skip; 5248afdda45fSVasumathi Sundaram - Sun Microsystems ptr = statep->ls_line; 5249afdda45fSVasumathi Sundaram - Sun Microsystems break; 5250e7801d59Ssowmini case LINKPROP_DEFAULT: 5251e7801d59Ssowmini print_linkprop(linkid, statep, propname, 5252e7801d59Ssowmini DLADM_PROP_VAL_DEFAULT, "%s", &ptr); 5253e7801d59Ssowmini if (statep->ls_status != DLADM_STATUS_OK) 5254e7801d59Ssowmini goto skip; 5255e7801d59Ssowmini ptr = statep->ls_line; 5256e7801d59Ssowmini break; 5257e7801d59Ssowmini case LINKPROP_POSSIBLE: 5258e7801d59Ssowmini print_linkprop(linkid, statep, propname, 5259e7801d59Ssowmini DLADM_PROP_VAL_MODIFIABLE, "%s ", &ptr); 5260e7801d59Ssowmini if (statep->ls_status != DLADM_STATUS_OK) 5261e7801d59Ssowmini goto skip; 5262e7801d59Ssowmini ptr = statep->ls_line; 5263e7801d59Ssowmini break; 5264e7801d59Ssowmini default: 5265e7801d59Ssowmini die("invalid input"); 5266e7801d59Ssowmini break; 5267e7801d59Ssowmini } 52688002d411SSowmini Varadhan (void) strlcpy(buf, ptr, bufsize); 52698002d411SSowmini Varadhan return (B_TRUE); 5270e7801d59Ssowmini skip: 52718002d411SSowmini Varadhan return ((statep->ls_status == DLADM_STATUS_OK) ? 52728002d411SSowmini Varadhan B_TRUE : B_FALSE); 5273e7801d59Ssowmini } 5274e7801d59Ssowmini 5275bcb5c89dSSowmini Varadhan static boolean_t 5276bcb5c89dSSowmini Varadhan linkprop_is_supported(datalink_id_t linkid, const char *propname, 5277bcb5c89dSSowmini Varadhan show_linkprop_state_t *statep) 5278bcb5c89dSSowmini Varadhan { 5279bcb5c89dSSowmini Varadhan dladm_status_t status; 5280bcb5c89dSSowmini Varadhan uint_t valcnt = DLADM_MAX_PROP_VALCNT; 5281bcb5c89dSSowmini Varadhan 52824784fcbdSSowmini Varadhan /* if used with -p flag, always print output */ 52834784fcbdSSowmini Varadhan if (statep->ls_proplist != NULL) 52844784fcbdSSowmini Varadhan return (B_TRUE); 52854784fcbdSSowmini Varadhan 52864ac67f02SAnurag S. Maskey status = dladm_get_linkprop(handle, linkid, DLADM_PROP_VAL_DEFAULT, 5287bcb5c89dSSowmini Varadhan propname, statep->ls_propvals, &valcnt); 5288bcb5c89dSSowmini Varadhan 5289149b7eb2SSowmini Varadhan if (status == DLADM_STATUS_OK) 5290149b7eb2SSowmini Varadhan return (B_TRUE); 5291149b7eb2SSowmini Varadhan 5292149b7eb2SSowmini Varadhan /* 5293149b7eb2SSowmini Varadhan * A system wide default value is not available for the 5294149b7eb2SSowmini Varadhan * property. Check if current value can be retrieved. 5295149b7eb2SSowmini Varadhan */ 52964ac67f02SAnurag S. Maskey status = dladm_get_linkprop(handle, linkid, DLADM_PROP_VAL_CURRENT, 5297149b7eb2SSowmini Varadhan propname, statep->ls_propvals, &valcnt); 5298149b7eb2SSowmini Varadhan 5299149b7eb2SSowmini Varadhan return (status == DLADM_STATUS_OK); 5300bcb5c89dSSowmini Varadhan } 5301bcb5c89dSSowmini Varadhan 53024ac67f02SAnurag S. Maskey /* ARGSUSED */ 5303d62bc4baSyz147064 static int 53044ac67f02SAnurag S. Maskey show_linkprop(dladm_handle_t dh, datalink_id_t linkid, const char *propname, 53054ac67f02SAnurag S. Maskey void *arg) 53060ba2cbe9Sxc151355 { 53070ba2cbe9Sxc151355 show_linkprop_state_t *statep = arg; 5308e7801d59Ssowmini linkprop_args_t ls_arg; 53090ba2cbe9Sxc151355 5310e7801d59Ssowmini bzero(&ls_arg, sizeof (ls_arg)); 5311e7801d59Ssowmini ls_arg.ls_state = statep; 5312e7801d59Ssowmini ls_arg.ls_propname = (char *)propname; 5313e7801d59Ssowmini ls_arg.ls_linkid = linkid; 53140ba2cbe9Sxc151355 531562ee1d25SArtem Kachitchkine /* 531662ee1d25SArtem Kachitchkine * This will need to be fixed when kernel interfaces are added 531762ee1d25SArtem Kachitchkine * to enable walking of all known private properties. For now, 531862ee1d25SArtem Kachitchkine * we are limited to walking persistent private properties only. 531962ee1d25SArtem Kachitchkine */ 532062ee1d25SArtem Kachitchkine if ((propname[0] == '_') && !statep->ls_persist && 532162ee1d25SArtem Kachitchkine (statep->ls_proplist == NULL)) 532262ee1d25SArtem Kachitchkine return (DLADM_WALK_CONTINUE); 53238002d411SSowmini Varadhan if (!statep->ls_parsable && 5324149b7eb2SSowmini Varadhan !linkprop_is_supported(linkid, propname, statep)) 5325bcb5c89dSSowmini Varadhan return (DLADM_WALK_CONTINUE); 5326bcb5c89dSSowmini Varadhan 53278002d411SSowmini Varadhan ofmt_print(statep->ls_ofmt, &ls_arg); 5328e7801d59Ssowmini 5329d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 53300ba2cbe9Sxc151355 } 53310ba2cbe9Sxc151355 53320ba2cbe9Sxc151355 static void 53338d5c46e6Sam223141 do_show_linkprop(int argc, char **argv, const char *use) 53340ba2cbe9Sxc151355 { 5335f4b3ec61Sdh155122 int option; 533663a6526dSMichael Lim char propstr[DLADM_STRSIZE]; 5337da14cebeSEric Cheng dladm_arg_list_t *proplist = NULL; 5338d62bc4baSyz147064 datalink_id_t linkid = DATALINK_ALL_LINKID; 53390ba2cbe9Sxc151355 show_linkprop_state_t state; 5340d62bc4baSyz147064 uint32_t flags = DLADM_OPT_ACTIVE; 5341d62bc4baSyz147064 dladm_status_t status; 5342e7801d59Ssowmini char *fields_str = NULL; 53438002d411SSowmini Varadhan ofmt_handle_t ofmt; 53448002d411SSowmini Varadhan ofmt_status_t oferr; 53458002d411SSowmini Varadhan uint_t ofmtflags = 0; 53460ba2cbe9Sxc151355 534763a6526dSMichael Lim bzero(propstr, DLADM_STRSIZE); 53480ba2cbe9Sxc151355 opterr = 0; 53490ba2cbe9Sxc151355 state.ls_propvals = NULL; 53500ba2cbe9Sxc151355 state.ls_line = NULL; 53518002d411SSowmini Varadhan state.ls_parsable = B_FALSE; 53520ba2cbe9Sxc151355 state.ls_persist = B_FALSE; 53530ba2cbe9Sxc151355 state.ls_header = B_TRUE; 5354e7801d59Ssowmini state.ls_retstatus = DLADM_STATUS_OK; 535563a6526dSMichael Lim 5356e7801d59Ssowmini while ((option = getopt_long(argc, argv, ":p:cPo:", 53570ba2cbe9Sxc151355 prop_longopts, NULL)) != -1) { 53580ba2cbe9Sxc151355 switch (option) { 53590ba2cbe9Sxc151355 case 'p': 536063a6526dSMichael Lim (void) strlcat(propstr, optarg, DLADM_STRSIZE); 536163a6526dSMichael Lim if (strlcat(propstr, ",", DLADM_STRSIZE) >= 536263a6526dSMichael Lim DLADM_STRSIZE) 536363a6526dSMichael Lim die("property list too long '%s'", propstr); 53640ba2cbe9Sxc151355 break; 53650ba2cbe9Sxc151355 case 'c': 53668002d411SSowmini Varadhan state.ls_parsable = B_TRUE; 53670ba2cbe9Sxc151355 break; 53680ba2cbe9Sxc151355 case 'P': 53690ba2cbe9Sxc151355 state.ls_persist = B_TRUE; 5370d62bc4baSyz147064 flags = DLADM_OPT_PERSIST; 53710ba2cbe9Sxc151355 break; 5372e7801d59Ssowmini case 'o': 5373e7801d59Ssowmini fields_str = optarg; 5374e7801d59Ssowmini break; 53750ba2cbe9Sxc151355 default: 53768d5c46e6Sam223141 die_opterr(optopt, option, use); 53770ba2cbe9Sxc151355 break; 53780ba2cbe9Sxc151355 } 53790ba2cbe9Sxc151355 } 53800ba2cbe9Sxc151355 5381d62bc4baSyz147064 if (optind == (argc - 1)) { 53824ac67f02SAnurag S. Maskey if ((status = dladm_name2info(handle, argv[optind], &linkid, 53834ac67f02SAnurag S. Maskey NULL, NULL, NULL)) != DLADM_STATUS_OK) { 5384d62bc4baSyz147064 die_dlerr(status, "link %s is not valid", argv[optind]); 5385d62bc4baSyz147064 } 5386d62bc4baSyz147064 } else if (optind != argc) { 53870ba2cbe9Sxc151355 usage(); 5388d62bc4baSyz147064 } 53890ba2cbe9Sxc151355 539063a6526dSMichael Lim if (dladm_parse_link_props(propstr, &proplist, B_TRUE) 539163a6526dSMichael Lim != DLADM_STATUS_OK) 539263a6526dSMichael Lim die("invalid link properties specified"); 5393f4b3ec61Sdh155122 state.ls_proplist = proplist; 5394f595a68aSyz147064 state.ls_status = DLADM_STATUS_OK; 5395f4b3ec61Sdh155122 53968002d411SSowmini Varadhan if (state.ls_parsable) 53978002d411SSowmini Varadhan ofmtflags |= OFMT_PARSABLE; 53988002d411SSowmini Varadhan oferr = ofmt_open(fields_str, linkprop_fields, ofmtflags, 0, &ofmt); 53998002d411SSowmini Varadhan dladm_ofmt_check(oferr, state.ls_parsable, ofmt); 54008002d411SSowmini Varadhan state.ls_ofmt = ofmt; 5401e7801d59Ssowmini 5402d62bc4baSyz147064 if (linkid == DATALINK_ALL_LINKID) { 54034ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(show_linkprop_onelink, handle, 54044ac67f02SAnurag S. Maskey &state, DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE, flags); 5405f4b3ec61Sdh155122 } else { 54064ac67f02SAnurag S. Maskey (void) show_linkprop_onelink(handle, linkid, &state); 5407f4b3ec61Sdh155122 } 54088002d411SSowmini Varadhan ofmt_close(ofmt); 5409da14cebeSEric Cheng dladm_free_props(proplist); 5410f595a68aSyz147064 54114ac67f02SAnurag S. Maskey if (state.ls_retstatus != DLADM_STATUS_OK) { 54124ac67f02SAnurag S. Maskey dladm_close(handle); 5413f595a68aSyz147064 exit(EXIT_FAILURE); 5414f4b3ec61Sdh155122 } 54154ac67f02SAnurag S. Maskey } 5416f4b3ec61Sdh155122 5417d62bc4baSyz147064 static int 54184ac67f02SAnurag S. Maskey show_linkprop_onelink(dladm_handle_t hdl, datalink_id_t linkid, void *arg) 5419f4b3ec61Sdh155122 { 5420948f2876Sss150715 int i; 5421f4b3ec61Sdh155122 char *buf; 5422d62bc4baSyz147064 uint32_t flags; 5423da14cebeSEric Cheng dladm_arg_list_t *proplist = NULL; 5424d62bc4baSyz147064 show_linkprop_state_t *statep = arg; 5425d62bc4baSyz147064 dlpi_handle_t dh = NULL; 5426f4b3ec61Sdh155122 5427d62bc4baSyz147064 statep->ls_status = DLADM_STATUS_OK; 5428d62bc4baSyz147064 54294ac67f02SAnurag S. Maskey if (dladm_datalink_id2info(hdl, linkid, &flags, NULL, NULL, 54304ac67f02SAnurag S. Maskey statep->ls_link, MAXLINKNAMELEN) != DLADM_STATUS_OK) { 5431d62bc4baSyz147064 statep->ls_status = DLADM_STATUS_NOTFOUND; 5432d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 5433d62bc4baSyz147064 } 5434d62bc4baSyz147064 5435d62bc4baSyz147064 if ((statep->ls_persist && !(flags & DLADM_OPT_PERSIST)) || 5436d62bc4baSyz147064 (!statep->ls_persist && !(flags & DLADM_OPT_ACTIVE))) { 5437d62bc4baSyz147064 statep->ls_status = DLADM_STATUS_BADARG; 5438d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 5439d62bc4baSyz147064 } 5440d62bc4baSyz147064 5441f4b3ec61Sdh155122 proplist = statep->ls_proplist; 54420ba2cbe9Sxc151355 54430ba2cbe9Sxc151355 /* 54440ba2cbe9Sxc151355 * When some WiFi links are opened for the first time, their hardware 54450ba2cbe9Sxc151355 * automatically scans for APs and does other slow operations. Thus, 54460ba2cbe9Sxc151355 * if there are no open links, the retrieval of link properties 54470ba2cbe9Sxc151355 * (below) will proceed slowly unless we hold the link open. 5448d62bc4baSyz147064 * 5449d62bc4baSyz147064 * Note that failure of dlpi_open() does not necessarily mean invalid 5450d62bc4baSyz147064 * link properties, because dlpi_open() may fail because of incorrect 5451d62bc4baSyz147064 * autopush configuration. Therefore, we ingore the return value of 5452d62bc4baSyz147064 * dlpi_open(). 54530ba2cbe9Sxc151355 */ 5454d62bc4baSyz147064 if (!statep->ls_persist) 5455d62bc4baSyz147064 (void) dlpi_open(statep->ls_link, &dh, 0); 54560ba2cbe9Sxc151355 5457d62bc4baSyz147064 buf = malloc((sizeof (char *) + DLADM_PROP_VAL_MAX) * 5458d62bc4baSyz147064 DLADM_MAX_PROP_VALCNT + MAX_PROP_LINE); 545933343a97Smeem if (buf == NULL) 546033343a97Smeem die("insufficient memory"); 546133343a97Smeem 5462f4b3ec61Sdh155122 statep->ls_propvals = (char **)(void *)buf; 5463d62bc4baSyz147064 for (i = 0; i < DLADM_MAX_PROP_VALCNT; i++) { 5464d62bc4baSyz147064 statep->ls_propvals[i] = buf + 5465d62bc4baSyz147064 sizeof (char *) * DLADM_MAX_PROP_VALCNT + 54660ba2cbe9Sxc151355 i * DLADM_PROP_VAL_MAX; 54670ba2cbe9Sxc151355 } 5468f4b3ec61Sdh155122 statep->ls_line = buf + 5469d62bc4baSyz147064 (sizeof (char *) + DLADM_PROP_VAL_MAX) * DLADM_MAX_PROP_VALCNT; 54700ba2cbe9Sxc151355 54710ba2cbe9Sxc151355 if (proplist != NULL) { 5472da14cebeSEric Cheng for (i = 0; i < proplist->al_count; i++) { 54734ac67f02SAnurag S. Maskey (void) show_linkprop(hdl, linkid, 5474da14cebeSEric Cheng proplist->al_info[i].ai_name, statep); 54750ba2cbe9Sxc151355 } 5476d62bc4baSyz147064 } else { 54774ac67f02SAnurag S. Maskey (void) dladm_walk_linkprop(hdl, linkid, statep, 54784ac67f02SAnurag S. Maskey show_linkprop); 5479d62bc4baSyz147064 } 5480d62bc4baSyz147064 if (dh != NULL) 5481948f2876Sss150715 dlpi_close(dh); 54820ba2cbe9Sxc151355 free(buf); 5483d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 54840ba2cbe9Sxc151355 } 54850ba2cbe9Sxc151355 54860ba2cbe9Sxc151355 static dladm_status_t 5487d62bc4baSyz147064 set_linkprop_persist(datalink_id_t linkid, const char *prop_name, 5488d62bc4baSyz147064 char **prop_val, uint_t val_cnt, boolean_t reset) 54890ba2cbe9Sxc151355 { 54900ba2cbe9Sxc151355 dladm_status_t status; 54910ba2cbe9Sxc151355 54924ac67f02SAnurag S. Maskey status = dladm_set_linkprop(handle, linkid, prop_name, prop_val, 54934ac67f02SAnurag S. Maskey val_cnt, DLADM_OPT_PERSIST); 54940ba2cbe9Sxc151355 54950ba2cbe9Sxc151355 if (status != DLADM_STATUS_OK) { 5496da14cebeSEric Cheng warn_dlerr(status, "cannot persistently %s link property '%s'", 5497da14cebeSEric Cheng reset ? "reset" : "set", prop_name); 54980ba2cbe9Sxc151355 } 54990ba2cbe9Sxc151355 return (status); 55000ba2cbe9Sxc151355 } 55010ba2cbe9Sxc151355 5502da14cebeSEric Cheng static int 55034ac67f02SAnurag S. Maskey reset_one_linkprop(dladm_handle_t dh, datalink_id_t linkid, 55044ac67f02SAnurag S. Maskey const char *propname, void *arg) 5505da14cebeSEric Cheng { 5506da14cebeSEric Cheng set_linkprop_state_t *statep = arg; 5507da14cebeSEric Cheng dladm_status_t status; 5508da14cebeSEric Cheng 55094ac67f02SAnurag S. Maskey status = dladm_set_linkprop(dh, linkid, propname, NULL, 0, 5510da14cebeSEric Cheng DLADM_OPT_ACTIVE); 5511da14cebeSEric Cheng if (status != DLADM_STATUS_OK) { 5512da14cebeSEric Cheng warn_dlerr(status, "cannot reset link property '%s' on '%s'", 5513da14cebeSEric Cheng propname, statep->ls_name); 5514da14cebeSEric Cheng } 5515da14cebeSEric Cheng if (!statep->ls_temp) { 5516da14cebeSEric Cheng dladm_status_t s; 5517da14cebeSEric Cheng 5518da14cebeSEric Cheng s = set_linkprop_persist(linkid, propname, NULL, 0, 5519da14cebeSEric Cheng statep->ls_reset); 5520da14cebeSEric Cheng if (s != DLADM_STATUS_OK) 5521da14cebeSEric Cheng status = s; 5522da14cebeSEric Cheng } 5523da14cebeSEric Cheng if (status != DLADM_STATUS_OK) 5524da14cebeSEric Cheng statep->ls_status = status; 5525da14cebeSEric Cheng 5526da14cebeSEric Cheng return (DLADM_WALK_CONTINUE); 5527da14cebeSEric Cheng } 5528da14cebeSEric Cheng 55290ba2cbe9Sxc151355 static void 55308d5c46e6Sam223141 set_linkprop(int argc, char **argv, boolean_t reset, const char *use) 55310ba2cbe9Sxc151355 { 55320ba2cbe9Sxc151355 int i, option; 55330ba2cbe9Sxc151355 char errmsg[DLADM_STRSIZE]; 5534d62bc4baSyz147064 char *altroot = NULL; 5535d62bc4baSyz147064 datalink_id_t linkid; 55360ba2cbe9Sxc151355 boolean_t temp = B_FALSE; 55370ba2cbe9Sxc151355 dladm_status_t status = DLADM_STATUS_OK; 553863a6526dSMichael Lim char propstr[DLADM_STRSIZE]; 5539da14cebeSEric Cheng dladm_arg_list_t *proplist = NULL; 55400ba2cbe9Sxc151355 55410ba2cbe9Sxc151355 opterr = 0; 554263a6526dSMichael Lim bzero(propstr, DLADM_STRSIZE); 554363a6526dSMichael Lim 55440ba2cbe9Sxc151355 while ((option = getopt_long(argc, argv, ":p:R:t", 55450ba2cbe9Sxc151355 prop_longopts, NULL)) != -1) { 55460ba2cbe9Sxc151355 switch (option) { 55470ba2cbe9Sxc151355 case 'p': 554863a6526dSMichael Lim (void) strlcat(propstr, optarg, DLADM_STRSIZE); 554963a6526dSMichael Lim if (strlcat(propstr, ",", DLADM_STRSIZE) >= 555063a6526dSMichael Lim DLADM_STRSIZE) 555163a6526dSMichael Lim die("property list too long '%s'", propstr); 55520ba2cbe9Sxc151355 break; 55530ba2cbe9Sxc151355 case 't': 55540ba2cbe9Sxc151355 temp = B_TRUE; 55550ba2cbe9Sxc151355 break; 55560ba2cbe9Sxc151355 case 'R': 5557d62bc4baSyz147064 altroot = optarg; 55580ba2cbe9Sxc151355 break; 55590ba2cbe9Sxc151355 default: 55608d5c46e6Sam223141 die_opterr(optopt, option, use); 55618d5c46e6Sam223141 55620ba2cbe9Sxc151355 } 55630ba2cbe9Sxc151355 } 55640ba2cbe9Sxc151355 5565d62bc4baSyz147064 /* get link name (required last argument) */ 5566d62bc4baSyz147064 if (optind != (argc - 1)) 55670ba2cbe9Sxc151355 usage(); 55680ba2cbe9Sxc151355 556963a6526dSMichael Lim if (dladm_parse_link_props(propstr, &proplist, reset) != 557063a6526dSMichael Lim DLADM_STATUS_OK) 557163a6526dSMichael Lim die("invalid link properties specified"); 557263a6526dSMichael Lim 5573d62bc4baSyz147064 if (proplist == NULL && !reset) 557433343a97Smeem die("link property must be specified"); 557533343a97Smeem 5576d62bc4baSyz147064 if (altroot != NULL) { 5577da14cebeSEric Cheng dladm_free_props(proplist); 5578d62bc4baSyz147064 altroot_cmd(altroot, argc, argv); 5579d62bc4baSyz147064 } 5580d62bc4baSyz147064 55814ac67f02SAnurag S. Maskey status = dladm_name2info(handle, argv[optind], &linkid, NULL, NULL, 55824ac67f02SAnurag S. Maskey NULL); 5583d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 5584d62bc4baSyz147064 die_dlerr(status, "link %s is not valid", argv[optind]); 5585d62bc4baSyz147064 5586d62bc4baSyz147064 if (proplist == NULL) { 5587da14cebeSEric Cheng set_linkprop_state_t state; 558813994ee8Sxz162242 5589da14cebeSEric Cheng state.ls_name = argv[optind]; 5590da14cebeSEric Cheng state.ls_reset = reset; 5591da14cebeSEric Cheng state.ls_temp = temp; 5592da14cebeSEric Cheng state.ls_status = DLADM_STATUS_OK; 5593da14cebeSEric Cheng 55944ac67f02SAnurag S. Maskey (void) dladm_walk_linkprop(handle, linkid, &state, 55954ac67f02SAnurag S. Maskey reset_one_linkprop); 5596da14cebeSEric Cheng 5597da14cebeSEric Cheng status = state.ls_status; 55980ba2cbe9Sxc151355 goto done; 55990ba2cbe9Sxc151355 } 56000ba2cbe9Sxc151355 5601da14cebeSEric Cheng for (i = 0; i < proplist->al_count; i++) { 5602da14cebeSEric Cheng dladm_arg_info_t *aip = &proplist->al_info[i]; 56030ba2cbe9Sxc151355 char **val; 56040ba2cbe9Sxc151355 uint_t count; 56050ba2cbe9Sxc151355 dladm_status_t s; 56060ba2cbe9Sxc151355 56070ba2cbe9Sxc151355 if (reset) { 56080ba2cbe9Sxc151355 val = NULL; 56090ba2cbe9Sxc151355 count = 0; 56100ba2cbe9Sxc151355 } else { 5611da14cebeSEric Cheng val = aip->ai_val; 5612da14cebeSEric Cheng count = aip->ai_count; 56130ba2cbe9Sxc151355 if (count == 0) { 561433343a97Smeem warn("no value specified for '%s'", 5615da14cebeSEric Cheng aip->ai_name); 56160ba2cbe9Sxc151355 status = DLADM_STATUS_BADARG; 56170ba2cbe9Sxc151355 continue; 56180ba2cbe9Sxc151355 } 56190ba2cbe9Sxc151355 } 56204ac67f02SAnurag S. Maskey s = dladm_set_linkprop(handle, linkid, aip->ai_name, val, count, 5621d62bc4baSyz147064 DLADM_OPT_ACTIVE); 56220ba2cbe9Sxc151355 if (s == DLADM_STATUS_OK) { 56230ba2cbe9Sxc151355 if (!temp) { 5624d62bc4baSyz147064 s = set_linkprop_persist(linkid, 5625da14cebeSEric Cheng aip->ai_name, val, count, reset); 56260ba2cbe9Sxc151355 if (s != DLADM_STATUS_OK) 56270ba2cbe9Sxc151355 status = s; 56280ba2cbe9Sxc151355 } 56290ba2cbe9Sxc151355 continue; 56300ba2cbe9Sxc151355 } 56310ba2cbe9Sxc151355 status = s; 56320ba2cbe9Sxc151355 switch (s) { 56330ba2cbe9Sxc151355 case DLADM_STATUS_NOTFOUND: 5634da14cebeSEric Cheng warn("invalid link property '%s'", aip->ai_name); 56350ba2cbe9Sxc151355 break; 56360ba2cbe9Sxc151355 case DLADM_STATUS_BADVAL: { 56370ba2cbe9Sxc151355 int j; 56380ba2cbe9Sxc151355 char *ptr, *lim; 56390ba2cbe9Sxc151355 char **propvals = NULL; 5640d62bc4baSyz147064 uint_t valcnt = DLADM_MAX_PROP_VALCNT; 56410ba2cbe9Sxc151355 56420ba2cbe9Sxc151355 ptr = malloc((sizeof (char *) + 5643d62bc4baSyz147064 DLADM_PROP_VAL_MAX) * DLADM_MAX_PROP_VALCNT + 56440ba2cbe9Sxc151355 MAX_PROP_LINE); 56450ba2cbe9Sxc151355 56460ba2cbe9Sxc151355 propvals = (char **)(void *)ptr; 564733343a97Smeem if (propvals == NULL) 564833343a97Smeem die("insufficient memory"); 564933343a97Smeem 5650d62bc4baSyz147064 for (j = 0; j < DLADM_MAX_PROP_VALCNT; j++) { 56510ba2cbe9Sxc151355 propvals[j] = ptr + sizeof (char *) * 5652d62bc4baSyz147064 DLADM_MAX_PROP_VALCNT + 56530ba2cbe9Sxc151355 j * DLADM_PROP_VAL_MAX; 56540ba2cbe9Sxc151355 } 56554ac67f02SAnurag S. Maskey s = dladm_get_linkprop(handle, linkid, 5656da14cebeSEric Cheng DLADM_PROP_VAL_MODIFIABLE, aip->ai_name, propvals, 5657d62bc4baSyz147064 &valcnt); 5658d62bc4baSyz147064 5659d62bc4baSyz147064 if (s != DLADM_STATUS_OK) { 5660d62bc4baSyz147064 warn_dlerr(status, "cannot set link property " 5661da14cebeSEric Cheng "'%s' on '%s'", aip->ai_name, argv[optind]); 5662d62bc4baSyz147064 free(propvals); 5663d62bc4baSyz147064 break; 5664d62bc4baSyz147064 } 56650ba2cbe9Sxc151355 56660ba2cbe9Sxc151355 ptr = errmsg; 56670ba2cbe9Sxc151355 lim = ptr + DLADM_STRSIZE; 56680ba2cbe9Sxc151355 *ptr = '\0'; 5669d62bc4baSyz147064 for (j = 0; j < valcnt; j++) { 56700ba2cbe9Sxc151355 ptr += snprintf(ptr, lim - ptr, "%s,", 56710ba2cbe9Sxc151355 propvals[j]); 56720ba2cbe9Sxc151355 if (ptr >= lim) 56730ba2cbe9Sxc151355 break; 56740ba2cbe9Sxc151355 } 5675f4b3ec61Sdh155122 if (ptr > errmsg) { 56760ba2cbe9Sxc151355 *(ptr - 1) = '\0'; 567733343a97Smeem warn("link property '%s' must be one of: %s", 5678da14cebeSEric Cheng aip->ai_name, errmsg); 5679f4b3ec61Sdh155122 } else 5680f4b3ec61Sdh155122 warn("invalid link property '%s'", *val); 56810ba2cbe9Sxc151355 free(propvals); 56820ba2cbe9Sxc151355 break; 56830ba2cbe9Sxc151355 } 56840ba2cbe9Sxc151355 default: 56850ba2cbe9Sxc151355 if (reset) { 568633343a97Smeem warn_dlerr(status, "cannot reset link property " 5687da14cebeSEric Cheng "'%s' on '%s'", aip->ai_name, argv[optind]); 56880ba2cbe9Sxc151355 } else { 568933343a97Smeem warn_dlerr(status, "cannot set link property " 5690da14cebeSEric Cheng "'%s' on '%s'", aip->ai_name, argv[optind]); 56910ba2cbe9Sxc151355 } 56920ba2cbe9Sxc151355 break; 56930ba2cbe9Sxc151355 } 56940ba2cbe9Sxc151355 } 56950ba2cbe9Sxc151355 done: 5696da14cebeSEric Cheng dladm_free_props(proplist); 56974ac67f02SAnurag S. Maskey if (status != DLADM_STATUS_OK) { 56984ac67f02SAnurag S. Maskey dladm_close(handle); 56990ba2cbe9Sxc151355 exit(1); 57000ba2cbe9Sxc151355 } 57014ac67f02SAnurag S. Maskey } 57020ba2cbe9Sxc151355 57030ba2cbe9Sxc151355 static void 57048d5c46e6Sam223141 do_set_linkprop(int argc, char **argv, const char *use) 57050ba2cbe9Sxc151355 { 57068d5c46e6Sam223141 set_linkprop(argc, argv, B_FALSE, use); 57070ba2cbe9Sxc151355 } 57080ba2cbe9Sxc151355 57090ba2cbe9Sxc151355 static void 57108d5c46e6Sam223141 do_reset_linkprop(int argc, char **argv, const char *use) 57110ba2cbe9Sxc151355 { 57128d5c46e6Sam223141 set_linkprop(argc, argv, B_TRUE, use); 57130ba2cbe9Sxc151355 } 57140ba2cbe9Sxc151355 57150ba2cbe9Sxc151355 static int 57160ba2cbe9Sxc151355 convert_secobj(char *buf, uint_t len, uint8_t *obj_val, uint_t *obj_lenp, 57170ba2cbe9Sxc151355 dladm_secobj_class_t class) 57180ba2cbe9Sxc151355 { 57190ba2cbe9Sxc151355 int error = 0; 57200ba2cbe9Sxc151355 5721a399b765Szf162725 if (class == DLADM_SECOBJ_CLASS_WPA) { 5722a399b765Szf162725 if (len < 8 || len > 63) 5723a399b765Szf162725 return (EINVAL); 5724a399b765Szf162725 (void) memcpy(obj_val, buf, len); 5725a399b765Szf162725 *obj_lenp = len; 5726a399b765Szf162725 return (error); 5727a399b765Szf162725 } 57280ba2cbe9Sxc151355 5729a399b765Szf162725 if (class == DLADM_SECOBJ_CLASS_WEP) { 57300ba2cbe9Sxc151355 switch (len) { 57310ba2cbe9Sxc151355 case 5: /* ASCII key sizes */ 57320ba2cbe9Sxc151355 case 13: 57330ba2cbe9Sxc151355 (void) memcpy(obj_val, buf, len); 57340ba2cbe9Sxc151355 *obj_lenp = len; 57350ba2cbe9Sxc151355 break; 57360ba2cbe9Sxc151355 case 10: /* Hex key sizes, not preceded by 0x */ 57370ba2cbe9Sxc151355 case 26: 57380ba2cbe9Sxc151355 error = hexascii_to_octet(buf, len, obj_val, obj_lenp); 57390ba2cbe9Sxc151355 break; 57400ba2cbe9Sxc151355 case 12: /* Hex key sizes, preceded by 0x */ 57410ba2cbe9Sxc151355 case 28: 57420ba2cbe9Sxc151355 if (strncmp(buf, "0x", 2) != 0) 57430ba2cbe9Sxc151355 return (EINVAL); 5744a399b765Szf162725 error = hexascii_to_octet(buf + 2, len - 2, 5745a399b765Szf162725 obj_val, obj_lenp); 57460ba2cbe9Sxc151355 break; 57470ba2cbe9Sxc151355 default: 57480ba2cbe9Sxc151355 return (EINVAL); 57490ba2cbe9Sxc151355 } 57500ba2cbe9Sxc151355 return (error); 57510ba2cbe9Sxc151355 } 57520ba2cbe9Sxc151355 5753a399b765Szf162725 return (ENOENT); 5754a399b765Szf162725 } 5755a399b765Szf162725 57560ba2cbe9Sxc151355 static void 57570ba2cbe9Sxc151355 defersig(int sig) 57580ba2cbe9Sxc151355 { 57590ba2cbe9Sxc151355 signalled = sig; 57600ba2cbe9Sxc151355 } 57610ba2cbe9Sxc151355 57620ba2cbe9Sxc151355 static int 57630ba2cbe9Sxc151355 get_secobj_from_tty(uint_t try, const char *objname, char *buf) 57640ba2cbe9Sxc151355 { 57650ba2cbe9Sxc151355 uint_t len = 0; 57660ba2cbe9Sxc151355 int c; 57670ba2cbe9Sxc151355 struct termios stored, current; 57680ba2cbe9Sxc151355 void (*sigfunc)(int); 57690ba2cbe9Sxc151355 57700ba2cbe9Sxc151355 /* 57710ba2cbe9Sxc151355 * Turn off echo -- but before we do so, defer SIGINT handling 57720ba2cbe9Sxc151355 * so that a ^C doesn't leave the terminal corrupted. 57730ba2cbe9Sxc151355 */ 57740ba2cbe9Sxc151355 sigfunc = signal(SIGINT, defersig); 57750ba2cbe9Sxc151355 (void) fflush(stdin); 57760ba2cbe9Sxc151355 (void) tcgetattr(0, &stored); 57770ba2cbe9Sxc151355 current = stored; 57780ba2cbe9Sxc151355 current.c_lflag &= ~(ICANON|ECHO); 57790ba2cbe9Sxc151355 current.c_cc[VTIME] = 0; 57800ba2cbe9Sxc151355 current.c_cc[VMIN] = 1; 57810ba2cbe9Sxc151355 (void) tcsetattr(0, TCSANOW, ¤t); 57820ba2cbe9Sxc151355 again: 57830ba2cbe9Sxc151355 if (try == 1) 57840ba2cbe9Sxc151355 (void) printf(gettext("provide value for '%s': "), objname); 57850ba2cbe9Sxc151355 else 57860ba2cbe9Sxc151355 (void) printf(gettext("confirm value for '%s': "), objname); 57870ba2cbe9Sxc151355 57880ba2cbe9Sxc151355 (void) fflush(stdout); 57890ba2cbe9Sxc151355 while (signalled == 0) { 57900ba2cbe9Sxc151355 c = getchar(); 57910ba2cbe9Sxc151355 if (c == '\n' || c == '\r') { 57920ba2cbe9Sxc151355 if (len != 0) 57930ba2cbe9Sxc151355 break; 57940ba2cbe9Sxc151355 (void) putchar('\n'); 57950ba2cbe9Sxc151355 goto again; 57960ba2cbe9Sxc151355 } 57970ba2cbe9Sxc151355 57980ba2cbe9Sxc151355 buf[len++] = c; 57990ba2cbe9Sxc151355 if (len >= DLADM_SECOBJ_VAL_MAX - 1) 58000ba2cbe9Sxc151355 break; 58010ba2cbe9Sxc151355 (void) putchar('*'); 58020ba2cbe9Sxc151355 } 58030ba2cbe9Sxc151355 58040ba2cbe9Sxc151355 (void) putchar('\n'); 58050ba2cbe9Sxc151355 (void) fflush(stdin); 58060ba2cbe9Sxc151355 58070ba2cbe9Sxc151355 /* 58080ba2cbe9Sxc151355 * Restore terminal setting and handle deferred signals. 58090ba2cbe9Sxc151355 */ 58100ba2cbe9Sxc151355 (void) tcsetattr(0, TCSANOW, &stored); 58110ba2cbe9Sxc151355 58120ba2cbe9Sxc151355 (void) signal(SIGINT, sigfunc); 58130ba2cbe9Sxc151355 if (signalled != 0) 58140ba2cbe9Sxc151355 (void) kill(getpid(), signalled); 58150ba2cbe9Sxc151355 58160ba2cbe9Sxc151355 return (len); 58170ba2cbe9Sxc151355 } 58180ba2cbe9Sxc151355 58190ba2cbe9Sxc151355 static int 58200ba2cbe9Sxc151355 get_secobj_val(char *obj_name, uint8_t *obj_val, uint_t *obj_lenp, 58210ba2cbe9Sxc151355 dladm_secobj_class_t class, FILE *filep) 58220ba2cbe9Sxc151355 { 58230ba2cbe9Sxc151355 int rval; 58240ba2cbe9Sxc151355 uint_t len, len2; 58250ba2cbe9Sxc151355 char buf[DLADM_SECOBJ_VAL_MAX], buf2[DLADM_SECOBJ_VAL_MAX]; 58260ba2cbe9Sxc151355 58270ba2cbe9Sxc151355 if (filep == NULL) { 58280ba2cbe9Sxc151355 len = get_secobj_from_tty(1, obj_name, buf); 58290ba2cbe9Sxc151355 rval = convert_secobj(buf, len, obj_val, obj_lenp, class); 58300ba2cbe9Sxc151355 if (rval == 0) { 58310ba2cbe9Sxc151355 len2 = get_secobj_from_tty(2, obj_name, buf2); 58320ba2cbe9Sxc151355 if (len != len2 || memcmp(buf, buf2, len) != 0) 58330ba2cbe9Sxc151355 rval = ENOTSUP; 58340ba2cbe9Sxc151355 } 58350ba2cbe9Sxc151355 return (rval); 58360ba2cbe9Sxc151355 } else { 58370ba2cbe9Sxc151355 for (;;) { 58380ba2cbe9Sxc151355 if (fgets(buf, sizeof (buf), filep) == NULL) 58390ba2cbe9Sxc151355 break; 58400ba2cbe9Sxc151355 if (isspace(buf[0])) 58410ba2cbe9Sxc151355 continue; 58420ba2cbe9Sxc151355 58430ba2cbe9Sxc151355 len = strlen(buf); 58440ba2cbe9Sxc151355 if (buf[len - 1] == '\n') { 58450ba2cbe9Sxc151355 buf[len - 1] = '\0'; 58460ba2cbe9Sxc151355 len--; 58470ba2cbe9Sxc151355 } 58480ba2cbe9Sxc151355 break; 58490ba2cbe9Sxc151355 } 58500ba2cbe9Sxc151355 (void) fclose(filep); 58510ba2cbe9Sxc151355 } 58520ba2cbe9Sxc151355 return (convert_secobj(buf, len, obj_val, obj_lenp, class)); 58530ba2cbe9Sxc151355 } 58540ba2cbe9Sxc151355 58550ba2cbe9Sxc151355 static boolean_t 58560ba2cbe9Sxc151355 check_auth(const char *auth) 58570ba2cbe9Sxc151355 { 58580ba2cbe9Sxc151355 struct passwd *pw; 58590ba2cbe9Sxc151355 58600ba2cbe9Sxc151355 if ((pw = getpwuid(getuid())) == NULL) 58610ba2cbe9Sxc151355 return (B_FALSE); 58620ba2cbe9Sxc151355 58630ba2cbe9Sxc151355 return (chkauthattr(auth, pw->pw_name) != 0); 58640ba2cbe9Sxc151355 } 58650ba2cbe9Sxc151355 58660ba2cbe9Sxc151355 static void 58670ba2cbe9Sxc151355 audit_secobj(char *auth, char *class, char *obj, 58680ba2cbe9Sxc151355 boolean_t success, boolean_t create) 58690ba2cbe9Sxc151355 { 58700ba2cbe9Sxc151355 adt_session_data_t *ah; 58710ba2cbe9Sxc151355 adt_event_data_t *event; 58720ba2cbe9Sxc151355 au_event_t flag; 58730ba2cbe9Sxc151355 char *errstr; 58740ba2cbe9Sxc151355 58750ba2cbe9Sxc151355 if (create) { 58760ba2cbe9Sxc151355 flag = ADT_dladm_create_secobj; 58770ba2cbe9Sxc151355 errstr = "ADT_dladm_create_secobj"; 58780ba2cbe9Sxc151355 } else { 58790ba2cbe9Sxc151355 flag = ADT_dladm_delete_secobj; 58800ba2cbe9Sxc151355 errstr = "ADT_dladm_delete_secobj"; 58810ba2cbe9Sxc151355 } 58820ba2cbe9Sxc151355 588333343a97Smeem if (adt_start_session(&ah, NULL, ADT_USE_PROC_DATA) != 0) 588433343a97Smeem die("adt_start_session: %s", strerror(errno)); 58850ba2cbe9Sxc151355 588633343a97Smeem if ((event = adt_alloc_event(ah, flag)) == NULL) 588733343a97Smeem die("adt_alloc_event (%s): %s", errstr, strerror(errno)); 58880ba2cbe9Sxc151355 58890ba2cbe9Sxc151355 /* fill in audit info */ 58900ba2cbe9Sxc151355 if (create) { 58910ba2cbe9Sxc151355 event->adt_dladm_create_secobj.auth_used = auth; 58920ba2cbe9Sxc151355 event->adt_dladm_create_secobj.obj_class = class; 58930ba2cbe9Sxc151355 event->adt_dladm_create_secobj.obj_name = obj; 58940ba2cbe9Sxc151355 } else { 58950ba2cbe9Sxc151355 event->adt_dladm_delete_secobj.auth_used = auth; 58960ba2cbe9Sxc151355 event->adt_dladm_delete_secobj.obj_class = class; 58970ba2cbe9Sxc151355 event->adt_dladm_delete_secobj.obj_name = obj; 58980ba2cbe9Sxc151355 } 58990ba2cbe9Sxc151355 59000ba2cbe9Sxc151355 if (success) { 59010ba2cbe9Sxc151355 if (adt_put_event(event, ADT_SUCCESS, ADT_SUCCESS) != 0) { 590233343a97Smeem die("adt_put_event (%s, success): %s", errstr, 590333343a97Smeem strerror(errno)); 59040ba2cbe9Sxc151355 } 59050ba2cbe9Sxc151355 } else { 59060ba2cbe9Sxc151355 if (adt_put_event(event, ADT_FAILURE, 59070ba2cbe9Sxc151355 ADT_FAIL_VALUE_AUTH) != 0) { 590833343a97Smeem die("adt_put_event: (%s, failure): %s", errstr, 590933343a97Smeem strerror(errno)); 59100ba2cbe9Sxc151355 } 59110ba2cbe9Sxc151355 } 59120ba2cbe9Sxc151355 59130ba2cbe9Sxc151355 adt_free_event(event); 59140ba2cbe9Sxc151355 (void) adt_end_session(ah); 59150ba2cbe9Sxc151355 } 59160ba2cbe9Sxc151355 59170ba2cbe9Sxc151355 #define MAX_SECOBJS 32 59180ba2cbe9Sxc151355 #define MAX_SECOBJ_NAMELEN 32 59190ba2cbe9Sxc151355 static void 59208d5c46e6Sam223141 do_create_secobj(int argc, char **argv, const char *use) 59210ba2cbe9Sxc151355 { 59220ba2cbe9Sxc151355 int option, rval; 59230ba2cbe9Sxc151355 FILE *filep = NULL; 59240ba2cbe9Sxc151355 char *obj_name = NULL; 59250ba2cbe9Sxc151355 char *class_name = NULL; 59260ba2cbe9Sxc151355 uint8_t obj_val[DLADM_SECOBJ_VAL_MAX]; 59270ba2cbe9Sxc151355 uint_t obj_len; 59280ba2cbe9Sxc151355 boolean_t success, temp = B_FALSE; 59290ba2cbe9Sxc151355 dladm_status_t status; 59300ba2cbe9Sxc151355 dladm_secobj_class_t class = -1; 59310ba2cbe9Sxc151355 uid_t euid; 59320ba2cbe9Sxc151355 59330ba2cbe9Sxc151355 opterr = 0; 59340ba2cbe9Sxc151355 (void) memset(obj_val, 0, DLADM_SECOBJ_VAL_MAX); 59350ba2cbe9Sxc151355 while ((option = getopt_long(argc, argv, ":f:c:R:t", 59360ba2cbe9Sxc151355 wifi_longopts, NULL)) != -1) { 59370ba2cbe9Sxc151355 switch (option) { 59380ba2cbe9Sxc151355 case 'f': 59390ba2cbe9Sxc151355 euid = geteuid(); 59400ba2cbe9Sxc151355 (void) seteuid(getuid()); 59410ba2cbe9Sxc151355 filep = fopen(optarg, "r"); 59420ba2cbe9Sxc151355 if (filep == NULL) { 594333343a97Smeem die("cannot open %s: %s", optarg, 594433343a97Smeem strerror(errno)); 59450ba2cbe9Sxc151355 } 59460ba2cbe9Sxc151355 (void) seteuid(euid); 59470ba2cbe9Sxc151355 break; 59480ba2cbe9Sxc151355 case 'c': 59490ba2cbe9Sxc151355 class_name = optarg; 59500ba2cbe9Sxc151355 status = dladm_str2secobjclass(optarg, &class); 59510ba2cbe9Sxc151355 if (status != DLADM_STATUS_OK) { 595233343a97Smeem die("invalid secure object class '%s', " 5953a399b765Szf162725 "valid values are: wep, wpa", optarg); 59540ba2cbe9Sxc151355 } 59550ba2cbe9Sxc151355 break; 59560ba2cbe9Sxc151355 case 't': 59570ba2cbe9Sxc151355 temp = B_TRUE; 59580ba2cbe9Sxc151355 break; 59590ba2cbe9Sxc151355 case 'R': 59600ba2cbe9Sxc151355 status = dladm_set_rootdir(optarg); 59610ba2cbe9Sxc151355 if (status != DLADM_STATUS_OK) { 596233343a97Smeem die_dlerr(status, "invalid directory " 596333343a97Smeem "specified"); 59640ba2cbe9Sxc151355 } 59650ba2cbe9Sxc151355 break; 59660ba2cbe9Sxc151355 default: 59678d5c46e6Sam223141 die_opterr(optopt, option, use); 59680ba2cbe9Sxc151355 break; 59690ba2cbe9Sxc151355 } 59700ba2cbe9Sxc151355 } 59710ba2cbe9Sxc151355 59720ba2cbe9Sxc151355 if (optind == (argc - 1)) 59730ba2cbe9Sxc151355 obj_name = argv[optind]; 59740ba2cbe9Sxc151355 else if (optind != argc) 59750ba2cbe9Sxc151355 usage(); 59760ba2cbe9Sxc151355 597733343a97Smeem if (class == -1) 597833343a97Smeem die("secure object class required"); 59790ba2cbe9Sxc151355 598033343a97Smeem if (obj_name == NULL) 598133343a97Smeem die("secure object name required"); 59820ba2cbe9Sxc151355 5983a9489f61SAnurag S. Maskey if (!dladm_valid_secobj_name(obj_name)) 5984a9489f61SAnurag S. Maskey die("invalid secure object name '%s'", obj_name); 5985a9489f61SAnurag S. Maskey 59860ba2cbe9Sxc151355 success = check_auth(LINK_SEC_AUTH); 59870ba2cbe9Sxc151355 audit_secobj(LINK_SEC_AUTH, class_name, obj_name, success, B_TRUE); 598833343a97Smeem if (!success) 598933343a97Smeem die("authorization '%s' is required", LINK_SEC_AUTH); 59900ba2cbe9Sxc151355 599133343a97Smeem rval = get_secobj_val(obj_name, obj_val, &obj_len, class, filep); 599233343a97Smeem if (rval != 0) { 59930ba2cbe9Sxc151355 switch (rval) { 59940ba2cbe9Sxc151355 case ENOENT: 599533343a97Smeem die("invalid secure object class"); 59960ba2cbe9Sxc151355 break; 59970ba2cbe9Sxc151355 case EINVAL: 599833343a97Smeem die("invalid secure object value"); 59990ba2cbe9Sxc151355 break; 60000ba2cbe9Sxc151355 case ENOTSUP: 600133343a97Smeem die("verification failed"); 60020ba2cbe9Sxc151355 break; 60030ba2cbe9Sxc151355 default: 600433343a97Smeem die("invalid secure object: %s", strerror(rval)); 60050ba2cbe9Sxc151355 break; 60060ba2cbe9Sxc151355 } 60070ba2cbe9Sxc151355 } 60080ba2cbe9Sxc151355 60094ac67f02SAnurag S. Maskey status = dladm_set_secobj(handle, obj_name, class, obj_val, obj_len, 6010d62bc4baSyz147064 DLADM_OPT_CREATE | DLADM_OPT_ACTIVE); 60110ba2cbe9Sxc151355 if (status != DLADM_STATUS_OK) { 601233343a97Smeem die_dlerr(status, "could not create secure object '%s'", 601333343a97Smeem obj_name); 60140ba2cbe9Sxc151355 } 60150ba2cbe9Sxc151355 if (temp) 60160ba2cbe9Sxc151355 return; 60170ba2cbe9Sxc151355 60184ac67f02SAnurag S. Maskey status = dladm_set_secobj(handle, obj_name, class, obj_val, obj_len, 60190ba2cbe9Sxc151355 DLADM_OPT_PERSIST); 60200ba2cbe9Sxc151355 if (status != DLADM_STATUS_OK) { 602133343a97Smeem warn_dlerr(status, "could not persistently create secure " 602233343a97Smeem "object '%s'", obj_name); 60230ba2cbe9Sxc151355 } 60240ba2cbe9Sxc151355 } 60250ba2cbe9Sxc151355 60260ba2cbe9Sxc151355 static void 60278d5c46e6Sam223141 do_delete_secobj(int argc, char **argv, const char *use) 60280ba2cbe9Sxc151355 { 60290ba2cbe9Sxc151355 int i, option; 60300ba2cbe9Sxc151355 boolean_t temp = B_FALSE; 60310ba2cbe9Sxc151355 boolean_t success; 60320ba2cbe9Sxc151355 dladm_status_t status, pstatus; 60338002d411SSowmini Varadhan int nfields = 1; 60348002d411SSowmini Varadhan char *field, *token, *lasts = NULL, c; 60350ba2cbe9Sxc151355 60360ba2cbe9Sxc151355 opterr = 0; 60370ba2cbe9Sxc151355 status = pstatus = DLADM_STATUS_OK; 603833343a97Smeem while ((option = getopt_long(argc, argv, ":R:t", 60390ba2cbe9Sxc151355 wifi_longopts, NULL)) != -1) { 60400ba2cbe9Sxc151355 switch (option) { 60410ba2cbe9Sxc151355 case 't': 60420ba2cbe9Sxc151355 temp = B_TRUE; 60430ba2cbe9Sxc151355 break; 60440ba2cbe9Sxc151355 case 'R': 60450ba2cbe9Sxc151355 status = dladm_set_rootdir(optarg); 60460ba2cbe9Sxc151355 if (status != DLADM_STATUS_OK) { 604733343a97Smeem die_dlerr(status, "invalid directory " 604833343a97Smeem "specified"); 60490ba2cbe9Sxc151355 } 60500ba2cbe9Sxc151355 break; 60510ba2cbe9Sxc151355 default: 60528d5c46e6Sam223141 die_opterr(optopt, option, use); 60530ba2cbe9Sxc151355 break; 60540ba2cbe9Sxc151355 } 60550ba2cbe9Sxc151355 } 60560ba2cbe9Sxc151355 60570ba2cbe9Sxc151355 if (optind == (argc - 1)) { 60588002d411SSowmini Varadhan token = argv[optind]; 60598002d411SSowmini Varadhan if (token == NULL) 60608002d411SSowmini Varadhan die("secure object name required"); 60618002d411SSowmini Varadhan while ((c = *token++) != NULL) { 60628002d411SSowmini Varadhan if (c == ',') 60638002d411SSowmini Varadhan nfields++; 60640ba2cbe9Sxc151355 } 60658002d411SSowmini Varadhan token = strdup(argv[optind]); 60668002d411SSowmini Varadhan if (token == NULL) 60678002d411SSowmini Varadhan die("no memory"); 60680ba2cbe9Sxc151355 } else if (optind != argc) 60690ba2cbe9Sxc151355 usage(); 60700ba2cbe9Sxc151355 60710ba2cbe9Sxc151355 success = check_auth(LINK_SEC_AUTH); 6072a399b765Szf162725 audit_secobj(LINK_SEC_AUTH, "unknown", argv[optind], success, B_FALSE); 607333343a97Smeem if (!success) 607433343a97Smeem die("authorization '%s' is required", LINK_SEC_AUTH); 60750ba2cbe9Sxc151355 60768002d411SSowmini Varadhan for (i = 0; i < nfields; i++) { 60778002d411SSowmini Varadhan 60788002d411SSowmini Varadhan field = strtok_r(token, ",", &lasts); 60798002d411SSowmini Varadhan token = NULL; 60808002d411SSowmini Varadhan status = dladm_unset_secobj(handle, field, DLADM_OPT_ACTIVE); 60810ba2cbe9Sxc151355 if (!temp) { 60828002d411SSowmini Varadhan pstatus = dladm_unset_secobj(handle, field, 60830ba2cbe9Sxc151355 DLADM_OPT_PERSIST); 60840ba2cbe9Sxc151355 } else { 60850ba2cbe9Sxc151355 pstatus = DLADM_STATUS_OK; 60860ba2cbe9Sxc151355 } 60870ba2cbe9Sxc151355 60880ba2cbe9Sxc151355 if (status != DLADM_STATUS_OK) { 608933343a97Smeem warn_dlerr(status, "could not delete secure object " 60908002d411SSowmini Varadhan "'%s'", field); 60910ba2cbe9Sxc151355 } 60920ba2cbe9Sxc151355 if (pstatus != DLADM_STATUS_OK) { 609333343a97Smeem warn_dlerr(pstatus, "could not persistently delete " 60948002d411SSowmini Varadhan "secure object '%s'", field); 60950ba2cbe9Sxc151355 } 60960ba2cbe9Sxc151355 } 60978002d411SSowmini Varadhan free(token); 60984ac67f02SAnurag S. Maskey 60994ac67f02SAnurag S. Maskey if (status != DLADM_STATUS_OK || pstatus != DLADM_STATUS_OK) { 61004ac67f02SAnurag S. Maskey dladm_close(handle); 61010ba2cbe9Sxc151355 exit(1); 61020ba2cbe9Sxc151355 } 61034ac67f02SAnurag S. Maskey } 61040ba2cbe9Sxc151355 61050ba2cbe9Sxc151355 typedef struct show_secobj_state { 61060ba2cbe9Sxc151355 boolean_t ss_persist; 61078002d411SSowmini Varadhan boolean_t ss_parsable; 61080ba2cbe9Sxc151355 boolean_t ss_header; 61098002d411SSowmini Varadhan ofmt_handle_t ss_ofmt; 61100ba2cbe9Sxc151355 } show_secobj_state_t; 61110ba2cbe9Sxc151355 61120ba2cbe9Sxc151355 61130ba2cbe9Sxc151355 static boolean_t 61144ac67f02SAnurag S. Maskey show_secobj(dladm_handle_t dh, void *arg, const char *obj_name) 61150ba2cbe9Sxc151355 { 61160ba2cbe9Sxc151355 uint_t obj_len = DLADM_SECOBJ_VAL_MAX; 61170ba2cbe9Sxc151355 uint8_t obj_val[DLADM_SECOBJ_VAL_MAX]; 61180ba2cbe9Sxc151355 char buf[DLADM_STRSIZE]; 61190ba2cbe9Sxc151355 uint_t flags = 0; 61200ba2cbe9Sxc151355 dladm_secobj_class_t class; 61210ba2cbe9Sxc151355 show_secobj_state_t *statep = arg; 61220ba2cbe9Sxc151355 dladm_status_t status; 6123e7801d59Ssowmini secobj_fields_buf_t sbuf; 61240ba2cbe9Sxc151355 61255f5c9f54SAnurag S. Maskey bzero(&sbuf, sizeof (secobj_fields_buf_t)); 61260ba2cbe9Sxc151355 if (statep->ss_persist) 61270ba2cbe9Sxc151355 flags |= DLADM_OPT_PERSIST; 61280ba2cbe9Sxc151355 61294ac67f02SAnurag S. Maskey status = dladm_get_secobj(dh, obj_name, &class, obj_val, &obj_len, 61304ac67f02SAnurag S. Maskey flags); 613133343a97Smeem if (status != DLADM_STATUS_OK) 613233343a97Smeem die_dlerr(status, "cannot get secure object '%s'", obj_name); 61330ba2cbe9Sxc151355 6134e7801d59Ssowmini (void) snprintf(sbuf.ss_obj_name, sizeof (sbuf.ss_obj_name), 6135e7801d59Ssowmini obj_name); 6136e7801d59Ssowmini (void) dladm_secobjclass2str(class, buf); 6137e7801d59Ssowmini (void) snprintf(sbuf.ss_class, sizeof (sbuf.ss_class), "%s", buf); 6138e7801d59Ssowmini if (getuid() == 0) { 61390ba2cbe9Sxc151355 char val[DLADM_SECOBJ_VAL_MAX * 2]; 61400ba2cbe9Sxc151355 uint_t len = sizeof (val); 61410ba2cbe9Sxc151355 6142e7801d59Ssowmini if (octet_to_hexascii(obj_val, obj_len, val, &len) == 0) 6143e7801d59Ssowmini (void) snprintf(sbuf.ss_val, 6144e7801d59Ssowmini sizeof (sbuf.ss_val), "%s", val); 61450ba2cbe9Sxc151355 } 61468002d411SSowmini Varadhan ofmt_print(statep->ss_ofmt, &sbuf); 61470ba2cbe9Sxc151355 return (B_TRUE); 61480ba2cbe9Sxc151355 } 61490ba2cbe9Sxc151355 61500ba2cbe9Sxc151355 static void 61518d5c46e6Sam223141 do_show_secobj(int argc, char **argv, const char *use) 61520ba2cbe9Sxc151355 { 61530ba2cbe9Sxc151355 int option; 61540ba2cbe9Sxc151355 show_secobj_state_t state; 61550ba2cbe9Sxc151355 dladm_status_t status; 61560d365605Sschuster boolean_t o_arg = B_FALSE; 61570ba2cbe9Sxc151355 uint_t i; 61580ba2cbe9Sxc151355 uint_t flags; 6159e7801d59Ssowmini char *fields_str = NULL; 6160e7801d59Ssowmini char *def_fields = "object,class"; 6161e7801d59Ssowmini char *all_fields = "object,class,value"; 61628002d411SSowmini Varadhan char *field, *token, *lasts = NULL, c; 61638002d411SSowmini Varadhan ofmt_handle_t ofmt; 61648002d411SSowmini Varadhan ofmt_status_t oferr; 61658002d411SSowmini Varadhan uint_t ofmtflags = 0; 61660ba2cbe9Sxc151355 61670ba2cbe9Sxc151355 opterr = 0; 6168e7801d59Ssowmini bzero(&state, sizeof (state)); 61698002d411SSowmini Varadhan state.ss_parsable = B_FALSE; 6170e7801d59Ssowmini fields_str = def_fields; 61710ba2cbe9Sxc151355 state.ss_persist = B_FALSE; 61728002d411SSowmini Varadhan state.ss_parsable = B_FALSE; 61730ba2cbe9Sxc151355 state.ss_header = B_TRUE; 6174e7801d59Ssowmini while ((option = getopt_long(argc, argv, ":pPo:", 61750ba2cbe9Sxc151355 wifi_longopts, NULL)) != -1) { 61760ba2cbe9Sxc151355 switch (option) { 61770ba2cbe9Sxc151355 case 'p': 61788002d411SSowmini Varadhan state.ss_parsable = B_TRUE; 61790ba2cbe9Sxc151355 break; 61800ba2cbe9Sxc151355 case 'P': 61810ba2cbe9Sxc151355 state.ss_persist = B_TRUE; 61820ba2cbe9Sxc151355 break; 6183e7801d59Ssowmini case 'o': 61840d365605Sschuster o_arg = B_TRUE; 6185e7801d59Ssowmini if (strcasecmp(optarg, "all") == 0) 6186e7801d59Ssowmini fields_str = all_fields; 6187e7801d59Ssowmini else 6188e7801d59Ssowmini fields_str = optarg; 61890ba2cbe9Sxc151355 break; 61900ba2cbe9Sxc151355 default: 61918d5c46e6Sam223141 die_opterr(optopt, option, use); 61920ba2cbe9Sxc151355 break; 61930ba2cbe9Sxc151355 } 61940ba2cbe9Sxc151355 } 61950ba2cbe9Sxc151355 61968002d411SSowmini Varadhan if (state.ss_parsable && !o_arg) 61970d365605Sschuster die("option -c requires -o"); 61980d365605Sschuster 61998002d411SSowmini Varadhan if (state.ss_parsable && fields_str == all_fields) 62000d365605Sschuster die("\"-o all\" is invalid with -p"); 62010d365605Sschuster 62028002d411SSowmini Varadhan if (state.ss_parsable) 62038002d411SSowmini Varadhan ofmtflags |= OFMT_PARSABLE; 62048002d411SSowmini Varadhan oferr = ofmt_open(fields_str, secobj_fields, ofmtflags, 0, &ofmt); 62058002d411SSowmini Varadhan dladm_ofmt_check(oferr, state.ss_parsable, ofmt); 62068002d411SSowmini Varadhan state.ss_ofmt = ofmt; 6207e7801d59Ssowmini 6208e7801d59Ssowmini flags = state.ss_persist ? DLADM_OPT_PERSIST : 0; 62094ac67f02SAnurag S. Maskey 62100ba2cbe9Sxc151355 if (optind == (argc - 1)) { 62118002d411SSowmini Varadhan uint_t obj_fields = 1; 62128002d411SSowmini Varadhan 62138002d411SSowmini Varadhan token = argv[optind]; 62148002d411SSowmini Varadhan if (token == NULL) 62158002d411SSowmini Varadhan die("secure object name required"); 62168002d411SSowmini Varadhan while ((c = *token++) != NULL) { 62178002d411SSowmini Varadhan if (c == ',') 62188002d411SSowmini Varadhan obj_fields++; 62190ba2cbe9Sxc151355 } 62208002d411SSowmini Varadhan token = strdup(argv[optind]); 62218002d411SSowmini Varadhan if (token == NULL) 62228002d411SSowmini Varadhan die("no memory"); 62238002d411SSowmini Varadhan for (i = 0; i < obj_fields; i++) { 62248002d411SSowmini Varadhan field = strtok_r(token, ",", &lasts); 62258002d411SSowmini Varadhan token = NULL; 62268002d411SSowmini Varadhan if (!show_secobj(handle, &state, field)) 62270ba2cbe9Sxc151355 break; 62280ba2cbe9Sxc151355 } 62298002d411SSowmini Varadhan free(token); 62308002d411SSowmini Varadhan ofmt_close(ofmt); 62310ba2cbe9Sxc151355 return; 62320ba2cbe9Sxc151355 } else if (optind != argc) 62330ba2cbe9Sxc151355 usage(); 62340ba2cbe9Sxc151355 62354ac67f02SAnurag S. Maskey status = dladm_walk_secobj(handle, &state, show_secobj, flags); 62364ac67f02SAnurag S. Maskey 623733343a97Smeem if (status != DLADM_STATUS_OK) 623833343a97Smeem die_dlerr(status, "show-secobj"); 62398002d411SSowmini Varadhan ofmt_close(ofmt); 62400ba2cbe9Sxc151355 } 62410ba2cbe9Sxc151355 62420ba2cbe9Sxc151355 /*ARGSUSED*/ 6243d62bc4baSyz147064 static int 62444ac67f02SAnurag S. Maskey i_dladm_init_linkprop(dladm_handle_t dh, datalink_id_t linkid, void *arg) 6245d62bc4baSyz147064 { 62464ac67f02SAnurag S. Maskey (void) dladm_init_linkprop(dh, linkid, B_TRUE); 6247d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 6248d62bc4baSyz147064 } 6249d62bc4baSyz147064 62508d5c46e6Sam223141 /*ARGSUSED*/ 6251da14cebeSEric Cheng void 62528d5c46e6Sam223141 do_init_linkprop(int argc, char **argv, const char *use) 62530ba2cbe9Sxc151355 { 625430890389Sartem int option; 625530890389Sartem dladm_status_t status; 625630890389Sartem datalink_id_t linkid = DATALINK_ALL_LINKID; 625730890389Sartem datalink_media_t media = DATALINK_ANY_MEDIATYPE; 625830890389Sartem uint_t any_media = B_TRUE; 625930890389Sartem 626030890389Sartem opterr = 0; 626130890389Sartem while ((option = getopt(argc, argv, ":w")) != -1) { 626230890389Sartem switch (option) { 626330890389Sartem case 'w': 626430890389Sartem media = DL_WIFI; 626530890389Sartem any_media = B_FALSE; 626630890389Sartem break; 626730890389Sartem default: 62688d5c46e6Sam223141 /* 62698d5c46e6Sam223141 * Because init-linkprop is not a public command, 62708d5c46e6Sam223141 * print the usage instead. 62718d5c46e6Sam223141 */ 62728d5c46e6Sam223141 usage(); 627330890389Sartem break; 627430890389Sartem } 627530890389Sartem } 627630890389Sartem 627730890389Sartem if (optind == (argc - 1)) { 62784ac67f02SAnurag S. Maskey if ((status = dladm_name2info(handle, argv[optind], &linkid, 62794ac67f02SAnurag S. Maskey NULL, NULL, NULL)) != DLADM_STATUS_OK) 628030890389Sartem die_dlerr(status, "link %s is not valid", argv[optind]); 628130890389Sartem } else if (optind != argc) { 628230890389Sartem usage(); 628330890389Sartem } 628430890389Sartem 628530890389Sartem if (linkid == DATALINK_ALL_LINKID) { 6286d62bc4baSyz147064 /* 628730890389Sartem * linkprops of links of other classes have been initialized as 6288d62bc4baSyz147064 * part of the dladm up-xxx operation. 6289d62bc4baSyz147064 */ 62904ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(i_dladm_init_linkprop, handle, 62914ac67f02SAnurag S. Maskey NULL, DATALINK_CLASS_PHYS, media, DLADM_OPT_PERSIST); 629230890389Sartem } else { 62934ac67f02SAnurag S. Maskey (void) dladm_init_linkprop(handle, linkid, any_media); 629430890389Sartem } 62950ba2cbe9Sxc151355 } 62960ba2cbe9Sxc151355 62970ba2cbe9Sxc151355 static void 62988d5c46e6Sam223141 do_show_ether(int argc, char **argv, const char *use) 6299e7801d59Ssowmini { 6300e7801d59Ssowmini int option; 6301e7801d59Ssowmini datalink_id_t linkid; 6302e7801d59Ssowmini print_ether_state_t state; 63038002d411SSowmini Varadhan char *fields_str = NULL; 63048002d411SSowmini Varadhan ofmt_handle_t ofmt; 63058002d411SSowmini Varadhan ofmt_status_t oferr; 63068002d411SSowmini Varadhan uint_t ofmtflags = 0; 6307e7801d59Ssowmini 6308e7801d59Ssowmini bzero(&state, sizeof (state)); 6309e7801d59Ssowmini state.es_link = NULL; 63108002d411SSowmini Varadhan state.es_parsable = B_FALSE; 6311e7801d59Ssowmini 6312e7801d59Ssowmini while ((option = getopt_long(argc, argv, "o:px", 6313e7801d59Ssowmini showeth_lopts, NULL)) != -1) { 6314e7801d59Ssowmini switch (option) { 6315e7801d59Ssowmini case 'x': 6316e7801d59Ssowmini state.es_extended = B_TRUE; 6317e7801d59Ssowmini break; 6318e7801d59Ssowmini case 'p': 63198002d411SSowmini Varadhan state.es_parsable = B_TRUE; 6320e7801d59Ssowmini break; 6321e7801d59Ssowmini case 'o': 6322e7801d59Ssowmini fields_str = optarg; 6323e7801d59Ssowmini break; 6324e7801d59Ssowmini default: 63258d5c46e6Sam223141 die_opterr(optopt, option, use); 6326e7801d59Ssowmini break; 6327e7801d59Ssowmini } 6328e7801d59Ssowmini } 6329e7801d59Ssowmini 6330e7801d59Ssowmini if (optind == (argc - 1)) 6331e7801d59Ssowmini state.es_link = argv[optind]; 6332e7801d59Ssowmini 63338002d411SSowmini Varadhan if (state.es_parsable) 63348002d411SSowmini Varadhan ofmtflags |= OFMT_PARSABLE; 63358002d411SSowmini Varadhan oferr = ofmt_open(fields_str, ether_fields, ofmtflags, 63368002d411SSowmini Varadhan DLADM_DEFAULT_COL, &ofmt); 63378002d411SSowmini Varadhan dladm_ofmt_check(oferr, state.es_parsable, ofmt); 63388002d411SSowmini Varadhan state.es_ofmt = ofmt; 63394ac67f02SAnurag S. Maskey 6340e7801d59Ssowmini if (state.es_link == NULL) { 63414ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(show_etherprop, handle, &state, 6342e7801d59Ssowmini DATALINK_CLASS_PHYS, DL_ETHER, 6343e7801d59Ssowmini DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST); 6344e7801d59Ssowmini } else { 63454ac67f02SAnurag S. Maskey if (!link_is_ether(state.es_link, &linkid)) 6346e7801d59Ssowmini die("invalid link specified"); 63474ac67f02SAnurag S. Maskey (void) show_etherprop(handle, linkid, &state); 6348e7801d59Ssowmini } 63498002d411SSowmini Varadhan ofmt_close(ofmt); 6350e7801d59Ssowmini } 6351e7801d59Ssowmini 6352e7801d59Ssowmini static int 63534ac67f02SAnurag S. Maskey show_etherprop(dladm_handle_t dh, datalink_id_t linkid, void *arg) 6354e7801d59Ssowmini { 6355e7801d59Ssowmini print_ether_state_t *statep = arg; 6356e7801d59Ssowmini ether_fields_buf_t ebuf; 63574784fcbdSSowmini Varadhan dladm_ether_info_t eattr; 63584784fcbdSSowmini Varadhan dladm_status_t status; 6359e7801d59Ssowmini 63605f5c9f54SAnurag S. Maskey bzero(&ebuf, sizeof (ether_fields_buf_t)); 63614ac67f02SAnurag S. Maskey if (dladm_datalink_id2info(dh, linkid, NULL, NULL, NULL, 6362e7801d59Ssowmini ebuf.eth_link, sizeof (ebuf.eth_link)) != DLADM_STATUS_OK) { 6363e7801d59Ssowmini return (DLADM_WALK_CONTINUE); 6364e7801d59Ssowmini } 6365e7801d59Ssowmini 63664ac67f02SAnurag S. Maskey status = dladm_ether_info(dh, linkid, &eattr); 63674784fcbdSSowmini Varadhan if (status != DLADM_STATUS_OK) 63684784fcbdSSowmini Varadhan goto cleanup; 6369e7801d59Ssowmini 63704784fcbdSSowmini Varadhan (void) strlcpy(ebuf.eth_ptype, "current", sizeof (ebuf.eth_ptype)); 6371e7801d59Ssowmini 63724784fcbdSSowmini Varadhan (void) dladm_ether_autoneg2str(ebuf.eth_autoneg, 63734784fcbdSSowmini Varadhan sizeof (ebuf.eth_autoneg), &eattr, CURRENT); 63744784fcbdSSowmini Varadhan (void) dladm_ether_pause2str(ebuf.eth_pause, 63754784fcbdSSowmini Varadhan sizeof (ebuf.eth_pause), &eattr, CURRENT); 63764784fcbdSSowmini Varadhan (void) dladm_ether_spdx2str(ebuf.eth_spdx, 63774784fcbdSSowmini Varadhan sizeof (ebuf.eth_spdx), &eattr, CURRENT); 63784784fcbdSSowmini Varadhan (void) strlcpy(ebuf.eth_state, 63794784fcbdSSowmini Varadhan dladm_linkstate2str(eattr.lei_state, ebuf.eth_state), 63804784fcbdSSowmini Varadhan sizeof (ebuf.eth_state)); 63814784fcbdSSowmini Varadhan (void) strlcpy(ebuf.eth_rem_fault, 63824784fcbdSSowmini Varadhan (eattr.lei_attr[CURRENT].le_fault ? "fault" : "none"), 63834784fcbdSSowmini Varadhan sizeof (ebuf.eth_rem_fault)); 6384e7801d59Ssowmini 63858002d411SSowmini Varadhan ofmt_print(statep->es_ofmt, &ebuf); 6386e7801d59Ssowmini 6387e7801d59Ssowmini if (statep->es_extended) 63884784fcbdSSowmini Varadhan show_ether_xprop(arg, &eattr); 6389e7801d59Ssowmini 63904784fcbdSSowmini Varadhan cleanup: 63914784fcbdSSowmini Varadhan dladm_ether_info_done(&eattr); 6392e7801d59Ssowmini return (DLADM_WALK_CONTINUE); 6393e7801d59Ssowmini } 6394e7801d59Ssowmini 6395e7801d59Ssowmini /* ARGSUSED */ 6396e7801d59Ssowmini static void 63978d5c46e6Sam223141 do_init_secobj(int argc, char **argv, const char *use) 63980ba2cbe9Sxc151355 { 63990ba2cbe9Sxc151355 dladm_status_t status; 64000ba2cbe9Sxc151355 64014ac67f02SAnurag S. Maskey status = dladm_init_secobj(handle); 640233343a97Smeem if (status != DLADM_STATUS_OK) 640333343a97Smeem die_dlerr(status, "secure object initialization failed"); 640433343a97Smeem } 640533343a97Smeem 6406d62bc4baSyz147064 /* 6407d62bc4baSyz147064 * "-R" option support. It is used for live upgrading. Append dladm commands 6408d62bc4baSyz147064 * to a upgrade script which will be run when the alternative root boots up: 6409d62bc4baSyz147064 * 6410b9e076dcSyz147064 * - If the /etc/dladm/datalink.conf file exists on the alternative root, 6411b9e076dcSyz147064 * append dladm commands to the <altroot>/var/svc/profile/upgrade_datalink 6412b9e076dcSyz147064 * script. This script will be run as part of the network/physical service. 6413b9e076dcSyz147064 * We cannot defer this to /var/svc/profile/upgrade because then the 6414b9e076dcSyz147064 * configuration will not be able to take effect before network/physical 6415b9e076dcSyz147064 * plumbs various interfaces. 6416d62bc4baSyz147064 * 6417b9e076dcSyz147064 * - If the /etc/dladm/datalink.conf file does not exist on the alternative 6418b9e076dcSyz147064 * root, append dladm commands to the <altroot>/var/svc/profile/upgrade script, 6419b9e076dcSyz147064 * which will be run in the manifest-import service. 6420d62bc4baSyz147064 * 6421d62bc4baSyz147064 * Note that the SMF team is considering to move the manifest-import service 6422d62bc4baSyz147064 * to be run at the very begining of boot. Once that is done, the need for 6423d62bc4baSyz147064 * the /var/svc/profile/upgrade_datalink script will not exist any more. 6424d62bc4baSyz147064 */ 6425d62bc4baSyz147064 static void 6426d62bc4baSyz147064 altroot_cmd(char *altroot, int argc, char *argv[]) 6427d62bc4baSyz147064 { 6428d62bc4baSyz147064 char path[MAXPATHLEN]; 6429d62bc4baSyz147064 struct stat stbuf; 6430d62bc4baSyz147064 FILE *fp; 6431d62bc4baSyz147064 int i; 6432d62bc4baSyz147064 6433d62bc4baSyz147064 /* 6434b9e076dcSyz147064 * Check for the existence of the /etc/dladm/datalink.conf 6435b9e076dcSyz147064 * configuration file, and determine the name of script file. 6436d62bc4baSyz147064 */ 6437b9e076dcSyz147064 (void) snprintf(path, MAXPATHLEN, "/%s/etc/dladm/datalink.conf", 6438b9e076dcSyz147064 altroot); 6439d62bc4baSyz147064 if (stat(path, &stbuf) < 0) { 6440d62bc4baSyz147064 (void) snprintf(path, MAXPATHLEN, "/%s/%s", altroot, 6441d62bc4baSyz147064 SMF_UPGRADE_FILE); 6442d62bc4baSyz147064 } else { 6443d62bc4baSyz147064 (void) snprintf(path, MAXPATHLEN, "/%s/%s", altroot, 6444d62bc4baSyz147064 SMF_UPGRADEDATALINK_FILE); 6445d62bc4baSyz147064 } 6446d62bc4baSyz147064 6447d62bc4baSyz147064 if ((fp = fopen(path, "a+")) == NULL) 6448d62bc4baSyz147064 die("operation not supported on %s", altroot); 6449d62bc4baSyz147064 6450d62bc4baSyz147064 (void) fprintf(fp, "/sbin/dladm "); 6451d62bc4baSyz147064 for (i = 0; i < argc; i++) { 6452d62bc4baSyz147064 /* 6453d62bc4baSyz147064 * Directly write to the file if it is not the "-R <altroot>" 6454d62bc4baSyz147064 * option. In which case, skip it. 6455d62bc4baSyz147064 */ 6456d62bc4baSyz147064 if (strcmp(argv[i], "-R") != 0) 6457d62bc4baSyz147064 (void) fprintf(fp, "%s ", argv[i]); 6458d62bc4baSyz147064 else 6459d62bc4baSyz147064 i ++; 6460d62bc4baSyz147064 } 6461d62bc4baSyz147064 (void) fprintf(fp, "%s\n", SMF_DLADM_UPGRADE_MSG); 6462d62bc4baSyz147064 (void) fclose(fp); 64634ac67f02SAnurag S. Maskey dladm_close(handle); 6464d62bc4baSyz147064 exit(0); 6465d62bc4baSyz147064 } 6466d62bc4baSyz147064 6467d62bc4baSyz147064 /* 6468d62bc4baSyz147064 * Convert the string to an integer. Note that the string must not have any 6469d62bc4baSyz147064 * trailing non-integer characters. 6470d62bc4baSyz147064 */ 647133343a97Smeem static boolean_t 647233343a97Smeem str2int(const char *str, int *valp) 647333343a97Smeem { 647433343a97Smeem int val; 647533343a97Smeem char *endp = NULL; 647633343a97Smeem 647733343a97Smeem errno = 0; 647833343a97Smeem val = strtol(str, &endp, 10); 647933343a97Smeem if (errno != 0 || *endp != '\0') 648033343a97Smeem return (B_FALSE); 648133343a97Smeem 648233343a97Smeem *valp = val; 648333343a97Smeem return (B_TRUE); 648433343a97Smeem } 648533343a97Smeem 648633343a97Smeem /* PRINTFLIKE1 */ 648733343a97Smeem static void 648833343a97Smeem warn(const char *format, ...) 648933343a97Smeem { 649033343a97Smeem va_list alist; 649133343a97Smeem 649233343a97Smeem format = gettext(format); 649333343a97Smeem (void) fprintf(stderr, "%s: warning: ", progname); 649433343a97Smeem 649533343a97Smeem va_start(alist, format); 649633343a97Smeem (void) vfprintf(stderr, format, alist); 649733343a97Smeem va_end(alist); 649833343a97Smeem 649933343a97Smeem (void) putchar('\n'); 650033343a97Smeem } 650133343a97Smeem 650233343a97Smeem /* PRINTFLIKE2 */ 650333343a97Smeem static void 650433343a97Smeem warn_dlerr(dladm_status_t err, const char *format, ...) 650533343a97Smeem { 650633343a97Smeem va_list alist; 650733343a97Smeem char errmsg[DLADM_STRSIZE]; 650833343a97Smeem 650933343a97Smeem format = gettext(format); 651033343a97Smeem (void) fprintf(stderr, gettext("%s: warning: "), progname); 651133343a97Smeem 651233343a97Smeem va_start(alist, format); 651333343a97Smeem (void) vfprintf(stderr, format, alist); 651433343a97Smeem va_end(alist); 651533343a97Smeem (void) fprintf(stderr, ": %s\n", dladm_status2str(err, errmsg)); 651633343a97Smeem } 651733343a97Smeem 65184ac67f02SAnurag S. Maskey /* 65194ac67f02SAnurag S. Maskey * Also closes the dladm handle if it is not NULL. 65204ac67f02SAnurag S. Maskey */ 652133343a97Smeem /* PRINTFLIKE2 */ 652233343a97Smeem static void 652333343a97Smeem die_dlerr(dladm_status_t err, const char *format, ...) 652433343a97Smeem { 652533343a97Smeem va_list alist; 652633343a97Smeem char errmsg[DLADM_STRSIZE]; 652733343a97Smeem 652833343a97Smeem format = gettext(format); 652933343a97Smeem (void) fprintf(stderr, "%s: ", progname); 653033343a97Smeem 653133343a97Smeem va_start(alist, format); 653233343a97Smeem (void) vfprintf(stderr, format, alist); 653333343a97Smeem va_end(alist); 653433343a97Smeem (void) fprintf(stderr, ": %s\n", dladm_status2str(err, errmsg)); 653533343a97Smeem 65364ac67f02SAnurag S. Maskey /* close dladm handle if it was opened */ 65374ac67f02SAnurag S. Maskey if (handle != NULL) 65384ac67f02SAnurag S. Maskey dladm_close(handle); 65394ac67f02SAnurag S. Maskey 654033343a97Smeem exit(EXIT_FAILURE); 654133343a97Smeem } 654233343a97Smeem 654333343a97Smeem /* PRINTFLIKE1 */ 654433343a97Smeem static void 654533343a97Smeem die(const char *format, ...) 654633343a97Smeem { 654733343a97Smeem va_list alist; 654833343a97Smeem 654933343a97Smeem format = gettext(format); 655033343a97Smeem (void) fprintf(stderr, "%s: ", progname); 655133343a97Smeem 655233343a97Smeem va_start(alist, format); 655333343a97Smeem (void) vfprintf(stderr, format, alist); 655433343a97Smeem va_end(alist); 655533343a97Smeem 655633343a97Smeem (void) putchar('\n'); 65574ac67f02SAnurag S. Maskey 65584ac67f02SAnurag S. Maskey /* close dladm handle if it was opened */ 65594ac67f02SAnurag S. Maskey if (handle != NULL) 65604ac67f02SAnurag S. Maskey dladm_close(handle); 65614ac67f02SAnurag S. Maskey 656233343a97Smeem exit(EXIT_FAILURE); 656333343a97Smeem } 656433343a97Smeem 656533343a97Smeem static void 656633343a97Smeem die_optdup(int opt) 656733343a97Smeem { 656833343a97Smeem die("the option -%c cannot be specified more than once", opt); 656933343a97Smeem } 657033343a97Smeem 657133343a97Smeem static void 65728d5c46e6Sam223141 die_opterr(int opt, int opterr, const char *usage) 657333343a97Smeem { 657433343a97Smeem switch (opterr) { 657533343a97Smeem case ':': 65768d5c46e6Sam223141 die("option '-%c' requires a value\nusage: %s", opt, 65778d5c46e6Sam223141 gettext(usage)); 657833343a97Smeem break; 657933343a97Smeem case '?': 658033343a97Smeem default: 65818d5c46e6Sam223141 die("unrecognized option '-%c'\nusage: %s", opt, 65828d5c46e6Sam223141 gettext(usage)); 658333343a97Smeem break; 65840ba2cbe9Sxc151355 } 65850ba2cbe9Sxc151355 } 6586e7801d59Ssowmini 6587e7801d59Ssowmini static void 65884784fcbdSSowmini Varadhan show_ether_xprop(void *arg, dladm_ether_info_t *eattr) 6589e7801d59Ssowmini { 6590e7801d59Ssowmini print_ether_state_t *statep = arg; 6591e7801d59Ssowmini ether_fields_buf_t ebuf; 65924784fcbdSSowmini Varadhan int i; 6593e7801d59Ssowmini 65944784fcbdSSowmini Varadhan for (i = CAPABLE; i <= PEERADV; i++) { 6595e7801d59Ssowmini bzero(&ebuf, sizeof (ebuf)); 65964784fcbdSSowmini Varadhan (void) strlcpy(ebuf.eth_ptype, ptype[i], 65974784fcbdSSowmini Varadhan sizeof (ebuf.eth_ptype)); 65984784fcbdSSowmini Varadhan (void) dladm_ether_autoneg2str(ebuf.eth_autoneg, 65994784fcbdSSowmini Varadhan sizeof (ebuf.eth_autoneg), eattr, i); 66004784fcbdSSowmini Varadhan (void) dladm_ether_spdx2str(ebuf.eth_spdx, 66014784fcbdSSowmini Varadhan sizeof (ebuf.eth_spdx), eattr, i); 66024784fcbdSSowmini Varadhan (void) dladm_ether_pause2str(ebuf.eth_pause, 66034784fcbdSSowmini Varadhan sizeof (ebuf.eth_pause), eattr, i); 66044784fcbdSSowmini Varadhan (void) strlcpy(ebuf.eth_rem_fault, 66054784fcbdSSowmini Varadhan (eattr->lei_attr[i].le_fault ? "fault" : "none"), 66064784fcbdSSowmini Varadhan sizeof (ebuf.eth_rem_fault)); 66078002d411SSowmini Varadhan ofmt_print(statep->es_ofmt, &ebuf); 6608e7801d59Ssowmini } 6609e7801d59Ssowmini 6610e7801d59Ssowmini } 6611e7801d59Ssowmini 6612e7801d59Ssowmini static boolean_t 6613e7801d59Ssowmini link_is_ether(const char *link, datalink_id_t *linkid) 6614e7801d59Ssowmini { 6615e7801d59Ssowmini uint32_t media; 6616e7801d59Ssowmini datalink_class_t class; 6617e7801d59Ssowmini 66184ac67f02SAnurag S. Maskey if (dladm_name2info(handle, link, linkid, NULL, &class, &media) == 6619e7801d59Ssowmini DLADM_STATUS_OK) { 6620e7801d59Ssowmini if (class == DATALINK_CLASS_PHYS && media == DL_ETHER) 6621e7801d59Ssowmini return (B_TRUE); 6622e7801d59Ssowmini } 6623e7801d59Ssowmini return (B_FALSE); 6624e7801d59Ssowmini } 66258002d411SSowmini Varadhan 66268002d411SSowmini Varadhan /* 66278002d411SSowmini Varadhan * default output callback function that, when invoked, 66288002d411SSowmini Varadhan * prints string which is offset by ofmt_arg->ofmt_id within buf. 66298002d411SSowmini Varadhan */ 66308002d411SSowmini Varadhan static boolean_t 66318002d411SSowmini Varadhan print_default_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize) 66328002d411SSowmini Varadhan { 66338002d411SSowmini Varadhan char *value; 66348002d411SSowmini Varadhan 66358002d411SSowmini Varadhan value = (char *)ofarg->ofmt_cbarg + ofarg->ofmt_id; 66368002d411SSowmini Varadhan (void) strlcpy(buf, value, bufsize); 66378002d411SSowmini Varadhan return (B_TRUE); 66388002d411SSowmini Varadhan } 66398002d411SSowmini Varadhan 66408002d411SSowmini Varadhan static void 66418002d411SSowmini Varadhan dladm_ofmt_check(ofmt_status_t oferr, boolean_t parsable, 66428002d411SSowmini Varadhan ofmt_handle_t ofmt) 66438002d411SSowmini Varadhan { 66448002d411SSowmini Varadhan char buf[OFMT_BUFSIZE]; 66458002d411SSowmini Varadhan 66468002d411SSowmini Varadhan if (oferr == OFMT_SUCCESS) 66478002d411SSowmini Varadhan return; 66488002d411SSowmini Varadhan (void) ofmt_strerror(ofmt, oferr, buf, sizeof (buf)); 66498002d411SSowmini Varadhan /* 66508002d411SSowmini Varadhan * All errors are considered fatal in parsable mode. 66518002d411SSowmini Varadhan * NOMEM errors are always fatal, regardless of mode. 66528002d411SSowmini Varadhan * For other errors, we print diagnostics in human-readable 66538002d411SSowmini Varadhan * mode and processs what we can. 66548002d411SSowmini Varadhan */ 66558002d411SSowmini Varadhan if (parsable || oferr == OFMT_ENOFIELDS) { 66568002d411SSowmini Varadhan ofmt_close(ofmt); 66578002d411SSowmini Varadhan die(buf); 66588002d411SSowmini Varadhan } else { 66598002d411SSowmini Varadhan warn(buf); 66608002d411SSowmini Varadhan } 66618002d411SSowmini Varadhan } 6662