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 /* 22d62bc4baSyz147064 * Copyright 2008 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> 49f595a68aSyz147064 #include <libdllink.h> 50f595a68aSyz147064 #include <libdlaggr.h> 51f595a68aSyz147064 #include <libdlwlan.h> 52d62bc4baSyz147064 #include <libdlvlan.h> 53d62bc4baSyz147064 #include <libdlvnic.h> 540ba2cbe9Sxc151355 #include <libinetutil.h> 550ba2cbe9Sxc151355 #include <bsm/adt.h> 560ba2cbe9Sxc151355 #include <bsm/adt_event.h> 57e7801d59Ssowmini #include <stddef.h> 587c478bd9Sstevel@tonic-gate 59ba2e4443Sseb #define AGGR_DRV "aggr" 60e7801d59Ssowmini #define STR_UNDEF_VAL "--" 617c478bd9Sstevel@tonic-gate #define MAXPORT 256 62d62bc4baSyz147064 #define BUFLEN(lim, ptr) (((lim) > (ptr)) ? ((lim) - (ptr)) : 0) 63d62bc4baSyz147064 #define MAXLINELEN 1024 64d62bc4baSyz147064 #define SMF_UPGRADE_FILE "/var/svc/profile/upgrade" 65d62bc4baSyz147064 #define SMF_UPGRADEDATALINK_FILE "/var/svc/profile/upgrade_datalink" 66d62bc4baSyz147064 #define SMF_DLADM_UPGRADE_MSG " # added by dladm(1M)" 677c478bd9Sstevel@tonic-gate 68e7801d59Ssowmini #define CMD_TYPE_ANY 0xffffffff 69e7801d59Ssowmini #define WIFI_CMD_SCAN 0x00000001 70e7801d59Ssowmini #define WIFI_CMD_SHOW 0x00000002 71e7801d59Ssowmini #define WIFI_CMD_ALL (WIFI_CMD_SCAN | WIFI_CMD_SHOW) 72e7801d59Ssowmini 73e7801d59Ssowmini /* 740d365605Sschuster * Data structures and routines for printing output. 75e7801d59Ssowmini * All non-parseable output is assumed to be in a columnar format. 760d365605Sschuster * Multiple fields in parsable output are separated by ':'; single 770d365605Sschuster * field output is printed as-is. 78e7801d59Ssowmini * 79e7801d59Ssowmini * Each sub-command is associated with a global array of pointers, 80e7801d59Ssowmini * print_field_t *fields[], where the print_field_t contains information 81e7801d59Ssowmini * about the format in which the output is to be printed. 82e7801d59Ssowmini * 83e7801d59Ssowmini * Sub-commands may be implemented in one of two ways: 84e7801d59Ssowmini * (i) the implementation could get all field values into a character 85e7801d59Ssowmini * buffer, with pf_offset containing the offset (for pf_name) within 86e7801d59Ssowmini * the buffer. The sub-command would make the needed system calls 87e7801d59Ssowmini * to obtain all possible column values and then invoke the 88e7801d59Ssowmini * dladm_print_field() function to print the specific fields 89e7801d59Ssowmini * requested in the command line. See the comments for dladm_print_field 90e7801d59Ssowmini * for further details. 91e7801d59Ssowmini * (ii) Alternatively, each fields[i] entry could store a pf_index value 92e7801d59Ssowmini * that uniquely identifies the column to be printed. The implementation 93e7801d59Ssowmini * of the sub-command would then invoke dladm_print_output() with a 94e7801d59Ssowmini * callback function whose semantics are described below (see comments 95e7801d59Ssowmini * for dladm_print_output()) 96e7801d59Ssowmini * 97e7801d59Ssowmini * Thus, an implementation of a sub-command must provide the following: 98e7801d59Ssowmini * 99e7801d59Ssowmini * static print_field_t sub_command_fields[] = { 100e7801d59Ssowmini * {<name>, <header>,<field width>, <offset_or_index>, cmdtype}, 101e7801d59Ssowmini * : 102e7801d59Ssowmini * {<name>, <header>,<field width>, <offset_or_index>, cmdtype} 103e7801d59Ssowmini * }; 104e7801d59Ssowmini * 105e7801d59Ssowmini * #define SUB_COMMAND_MAX_FIELDS sizeof \ 106e7801d59Ssowmini * (sub_comand_fields) / sizeof (print_field_t)) 107e7801d59Ssowmini * 108e7801d59Ssowmini * print_state_t sub_command_print_state; 109e7801d59Ssowmini * 110e7801d59Ssowmini * The function that parses command line arguments (typically 111e7801d59Ssowmini * do_sub_command()) should then contain an invocation like: 112e7801d59Ssowmini * 113e7801d59Ssowmini * fields = parse_output_fields(fields_str, sub_command_fields, 114e7801d59Ssowmini * SUB_COMMAND_MAX_FIELDS, CMD_TYPE_ANY, &nfields); 115e7801d59Ssowmini * 116e7801d59Ssowmini * and store the resulting fields and nfields value in a print_state_t 117e7801d59Ssowmini * structure tracked for the command. 118e7801d59Ssowmini * 119e7801d59Ssowmini * sub_command_print_state.ps_fields = fields; 120e7801d59Ssowmini * sub_command_print_state.ps_nfields = nfields; 121e7801d59Ssowmini * 122e7801d59Ssowmini * To print the column header for the output, the print_header() 123e7801d59Ssowmini * function must then be invoked by do_sub_command(). 124e7801d59Ssowmini * 125e7801d59Ssowmini * Then if method (i) is used for the sub_command, the do_sub_command() 126e7801d59Ssowmini * function should make the necessary system calls to fill up the buffer 127e7801d59Ssowmini * and then invoke dladm_print_field(). An example of this method is 128e7801d59Ssowmini * the implementation of do_show_link() and show_link(); 129e7801d59Ssowmini * 130e7801d59Ssowmini * If method (ii) is used, do_sub_command should invoke dladm_print_output() 131e7801d59Ssowmini * with a callback function that will be called for each field to be printed. 132e7801d59Ssowmini * The callback function will be passed a pointer to the print_field_t 133e7801d59Ssowmini * for the field, and the pf_index may then be used to identify the 134e7801d59Ssowmini * system call required to find the value to be printed. An example of 135e7801d59Ssowmini * this implementation may be found in the do_show_dev() and print_dev() 136e7801d59Ssowmini * invocation. 137e7801d59Ssowmini */ 138e7801d59Ssowmini 139e7801d59Ssowmini typedef struct print_field_s { 140e7801d59Ssowmini const char *pf_name; /* name of column to be printed */ 141e7801d59Ssowmini const char *pf_header; /* header for this column */ 142e7801d59Ssowmini uint_t pf_width; 143e7801d59Ssowmini union { 144e7801d59Ssowmini uint_t _pf_index; /* private index for sub-command */ 145e7801d59Ssowmini size_t _pf_offset; 146e7801d59Ssowmini }_pf_un; 147e7801d59Ssowmini #define pf_index _pf_un._pf_index 148e7801d59Ssowmini #define pf_offset _pf_un._pf_offset; 149e7801d59Ssowmini uint_t pf_cmdtype; 150e7801d59Ssowmini } print_field_t; 151e7801d59Ssowmini 152e7801d59Ssowmini /* 153e7801d59Ssowmini * The state of the output is tracked in a print_state_t structure. 154e7801d59Ssowmini * Each ps_fields[i] entry points at the global print_field_t array for 155e7801d59Ssowmini * the sub-command, where ps_nfields is the number of requested fields. 156e7801d59Ssowmini */ 157e7801d59Ssowmini typedef struct print_state_s { 158e7801d59Ssowmini print_field_t **ps_fields; 159e7801d59Ssowmini uint_t ps_nfields; 160e7801d59Ssowmini boolean_t ps_lastfield; 161e7801d59Ssowmini uint_t ps_overflow; 162e7801d59Ssowmini } print_state_t; 163e7801d59Ssowmini 164e7801d59Ssowmini typedef char *(*print_callback_t)(print_field_t *, void *); 165e7801d59Ssowmini static print_field_t **parse_output_fields(char *, print_field_t *, int, 166e7801d59Ssowmini uint_t, uint_t *); 167e7801d59Ssowmini /* 168e7801d59Ssowmini * print the header for the output 169e7801d59Ssowmini */ 170e7801d59Ssowmini static void print_header(print_state_t *); 171e7801d59Ssowmini static void print_field(print_state_t *, print_field_t *, const char *, 172e7801d59Ssowmini boolean_t); 173e7801d59Ssowmini 174e7801d59Ssowmini /* 175e7801d59Ssowmini * to print output values, call dladm_print_output with a callback 176e7801d59Ssowmini * function (*func)() that should parse the args and return an 177e7801d59Ssowmini * unformatted character buffer with the value to be printed. 178e7801d59Ssowmini * 179e7801d59Ssowmini * dladm_print_output() prints the character buffer using the formatting 180e7801d59Ssowmini * information provided in the print_field_t for that column. 181e7801d59Ssowmini */ 182e7801d59Ssowmini static void dladm_print_output(print_state_t *, boolean_t, 183e7801d59Ssowmini print_callback_t, void *); 184e7801d59Ssowmini 185e7801d59Ssowmini /* 186e7801d59Ssowmini * helper function that, when invoked as dladm_print_field(pf, buf) 187e7801d59Ssowmini * prints string which is offset by pf->pf_offset within buf 188e7801d59Ssowmini */ 189e7801d59Ssowmini static char *dladm_print_field(print_field_t *, void *); 190e7801d59Ssowmini 191e7801d59Ssowmini 192e7801d59Ssowmini #define MAX_FIELD_LEN 32 193e7801d59Ssowmini 194e7801d59Ssowmini 1957c478bd9Sstevel@tonic-gate typedef struct pktsum_s { 1967c478bd9Sstevel@tonic-gate uint64_t ipackets; 1977c478bd9Sstevel@tonic-gate uint64_t opackets; 1987c478bd9Sstevel@tonic-gate uint64_t rbytes; 1997c478bd9Sstevel@tonic-gate uint64_t obytes; 2007c478bd9Sstevel@tonic-gate uint32_t ierrors; 2017c478bd9Sstevel@tonic-gate uint32_t oerrors; 2027c478bd9Sstevel@tonic-gate } pktsum_t; 2037c478bd9Sstevel@tonic-gate 204d62bc4baSyz147064 typedef struct show_state { 2057c478bd9Sstevel@tonic-gate boolean_t ls_firstonly; 2067c478bd9Sstevel@tonic-gate boolean_t ls_donefirst; 2077c478bd9Sstevel@tonic-gate pktsum_t ls_prevstats; 208d62bc4baSyz147064 uint32_t ls_flags; 209d62bc4baSyz147064 dladm_status_t ls_status; 210e7801d59Ssowmini print_state_t ls_print; 211e7801d59Ssowmini boolean_t ls_parseable; 212e7801d59Ssowmini boolean_t ls_printheader; 213d62bc4baSyz147064 } show_state_t; 2147c478bd9Sstevel@tonic-gate 2157c478bd9Sstevel@tonic-gate typedef struct show_grp_state { 216e7801d59Ssowmini pktsum_t gs_prevstats[MAXPORT]; 217e7801d59Ssowmini uint32_t gs_flags; 218e7801d59Ssowmini dladm_status_t gs_status; 219e7801d59Ssowmini boolean_t gs_parseable; 2207c478bd9Sstevel@tonic-gate boolean_t gs_lacp; 221d62bc4baSyz147064 boolean_t gs_extended; 2227c478bd9Sstevel@tonic-gate boolean_t gs_stats; 2237c478bd9Sstevel@tonic-gate boolean_t gs_firstonly; 224d62bc4baSyz147064 boolean_t gs_donefirst; 225e7801d59Ssowmini boolean_t gs_printheader; 226e7801d59Ssowmini print_state_t gs_print; 2277c478bd9Sstevel@tonic-gate } show_grp_state_t; 2287c478bd9Sstevel@tonic-gate 2298d5c46e6Sam223141 typedef void cmdfunc_t(int, char **, const char *); 2300ba2cbe9Sxc151355 231d62bc4baSyz147064 static cmdfunc_t do_show_link, do_show_dev, do_show_wifi, do_show_phys; 2320ba2cbe9Sxc151355 static cmdfunc_t do_create_aggr, do_delete_aggr, do_add_aggr, do_remove_aggr; 233d62bc4baSyz147064 static cmdfunc_t do_modify_aggr, do_show_aggr, do_up_aggr; 2340ba2cbe9Sxc151355 static cmdfunc_t do_scan_wifi, do_connect_wifi, do_disconnect_wifi; 2350ba2cbe9Sxc151355 static cmdfunc_t do_show_linkprop, do_set_linkprop, do_reset_linkprop; 2360ba2cbe9Sxc151355 static cmdfunc_t do_create_secobj, do_delete_secobj, do_show_secobj; 2370ba2cbe9Sxc151355 static cmdfunc_t do_init_linkprop, do_init_secobj; 238d62bc4baSyz147064 static cmdfunc_t do_create_vlan, do_delete_vlan, do_up_vlan, do_show_vlan; 239d62bc4baSyz147064 static cmdfunc_t do_rename_link, do_delete_phys, do_init_phys; 240d62bc4baSyz147064 static cmdfunc_t do_show_linkmap; 241e7801d59Ssowmini static cmdfunc_t do_show_ether; 2427c478bd9Sstevel@tonic-gate 243d62bc4baSyz147064 static void altroot_cmd(char *, int, char **); 244d62bc4baSyz147064 static int show_linkprop_onelink(datalink_id_t, void *); 245f4b3ec61Sdh155122 2466be03d0bSVasumathi Sundaram - Sun Microsystems static void link_stats(datalink_id_t, uint_t, char *, show_state_t *); 247d62bc4baSyz147064 static void aggr_stats(datalink_id_t, show_grp_state_t *, uint_t); 248e7801d59Ssowmini static void dev_stats(const char *dev, uint32_t, char *, show_state_t *); 2497c478bd9Sstevel@tonic-gate 250d62bc4baSyz147064 static int get_one_kstat(const char *, const char *, uint8_t, 251d62bc4baSyz147064 void *, boolean_t); 252ba2e4443Sseb static void get_mac_stats(const char *, pktsum_t *); 2537c478bd9Sstevel@tonic-gate static void get_link_stats(const char *, pktsum_t *); 254d62bc4baSyz147064 static uint64_t get_ifspeed(const char *, boolean_t); 2557c478bd9Sstevel@tonic-gate static void stats_total(pktsum_t *, pktsum_t *, pktsum_t *); 2567c478bd9Sstevel@tonic-gate static void stats_diff(pktsum_t *, pktsum_t *, pktsum_t *); 257d62bc4baSyz147064 static const char *get_linkstate(const char *, boolean_t, char *); 258d62bc4baSyz147064 static const char *get_linkduplex(const char *, boolean_t, char *); 2597c478bd9Sstevel@tonic-gate 260e7801d59Ssowmini static int show_etherprop(datalink_id_t, void *); 261e7801d59Ssowmini static void show_ether_xprop(datalink_id_t, void *); 262e7801d59Ssowmini static boolean_t get_speed_duplex(datalink_id_t, const char *, char *, 263e7801d59Ssowmini char *, boolean_t); 264e7801d59Ssowmini static char *pause_str(int, int); 265e7801d59Ssowmini static boolean_t link_is_ether(const char *, datalink_id_t *); 266e7801d59Ssowmini 267e7801d59Ssowmini #define IS_FDX 0x10 268e7801d59Ssowmini #define IS_HDX 0x01 269e7801d59Ssowmini 27033343a97Smeem static boolean_t str2int(const char *, int *); 27133343a97Smeem static void die(const char *, ...); 27233343a97Smeem static void die_optdup(int); 2738d5c46e6Sam223141 static void die_opterr(int, int, const char *); 27433343a97Smeem static void die_dlerr(dladm_status_t, const char *, ...); 27533343a97Smeem static void warn(const char *, ...); 27633343a97Smeem static void warn_dlerr(dladm_status_t, const char *, ...); 27733343a97Smeem 2787c478bd9Sstevel@tonic-gate typedef struct cmd { 2797c478bd9Sstevel@tonic-gate char *c_name; 2800ba2cbe9Sxc151355 cmdfunc_t *c_fn; 2818d5c46e6Sam223141 const char *c_usage; 2827c478bd9Sstevel@tonic-gate } cmd_t; 2837c478bd9Sstevel@tonic-gate 2847c478bd9Sstevel@tonic-gate static cmd_t cmds[] = { 2858d5c46e6Sam223141 { "show-link", do_show_link, 2868d5c46e6Sam223141 "\tshow-link\t[-pP] [-o <field>,..] [-s [-i <interval>]] [<link>]"}, 2878d5c46e6Sam223141 { "rename-link", do_rename_link, 2888d5c46e6Sam223141 "\trename-link\t[-R <root-dir>] <oldlink> <newlink>\n" }, 2898d5c46e6Sam223141 { "show-dev", do_show_dev, 2908d5c46e6Sam223141 "\tshow-dev\t[-p] [-o <field>,..] [-s [-i <interval>]] [<dev>]\n" }, 2918d5c46e6Sam223141 { "create-aggr", do_create_aggr, 2928d5c46e6Sam223141 "\tcreate-aggr\t[-t] [-R <root-dir>] [-P <policy>] [-L <mode>]\n" 2938d5c46e6Sam223141 "\t\t\t[-T <time>] [-u <address>] [-l <link>] ... <link>" }, 2948d5c46e6Sam223141 { "delete-aggr", do_delete_aggr, 2958d5c46e6Sam223141 "\tdelete-aggr\t[-t] [-R <root-dir>] <link>" }, 2968d5c46e6Sam223141 { "add-aggr", do_add_aggr, 2978d5c46e6Sam223141 "\tadd-aggr\t[-t] [-R <root-dir>] [-l <link>] ... <link>" }, 2988d5c46e6Sam223141 { "remove-aggr", do_remove_aggr, 2998d5c46e6Sam223141 "\tremove-aggr\t[-t] [-R <root-dir>] [-l <link>] ... <link>"}, 3008d5c46e6Sam223141 { "modify-aggr", do_modify_aggr, 3018d5c46e6Sam223141 "\tmodify-aggr\t[-t] [-R <root-dir>] [-P <policy>] [-L <mode>]\n" 3028d5c46e6Sam223141 "\t\t\t[-T <time>] [-u <address>] <link>" }, 3038d5c46e6Sam223141 { "show-aggr", do_show_aggr, 3048d5c46e6Sam223141 "\tshow-aggr\t[-pPLx] [-o <field>,..] [-s [-i <interval>]] " 3058d5c46e6Sam223141 "[<link>]\n" }, 3068d5c46e6Sam223141 { "up-aggr", do_up_aggr, NULL }, 3078d5c46e6Sam223141 { "scan-wifi", do_scan_wifi, 3088d5c46e6Sam223141 "\tscan-wifi\t[-p] [-o <field>,...] [<link>]" }, 3098d5c46e6Sam223141 { "connect-wifi", do_connect_wifi, 3108d5c46e6Sam223141 "\tconnect-wifi\t[-e <essid>] [-i <bssid>] [-k <key>,...] " 3118d5c46e6Sam223141 "[-s wep|wpa]\n" 3128d5c46e6Sam223141 "\t\t\t[-a open|shared] [-b bss|ibss] [-c] [-m a|b|g]\n" 3138d5c46e6Sam223141 "\t\t\t[-T <time>] [<link>]" }, 3148d5c46e6Sam223141 { "disconnect-wifi", do_disconnect_wifi, 3158d5c46e6Sam223141 "\tdisconnect-wifi\t[-a] [<link>]" }, 3168d5c46e6Sam223141 { "show-wifi", do_show_wifi, 3178d5c46e6Sam223141 "\tshow-wifi\t[-p] [-o <field>,...] [<link>]\n" }, 3188d5c46e6Sam223141 { "show-linkprop", do_show_linkprop, 3198d5c46e6Sam223141 "\tshow-linkprop\t[-cP] [-o <field>,...] [-p <prop>,...] <name>"}, 3208d5c46e6Sam223141 { "set-linkprop", do_set_linkprop, 3218d5c46e6Sam223141 "\tset-linkprop\t[-t] [-R <root-dir>] -p <prop>=<value>[,...] " 3228d5c46e6Sam223141 "<name>" }, 3238d5c46e6Sam223141 { "reset-linkprop", do_reset_linkprop, 3248d5c46e6Sam223141 "\treset-linkprop\t[-t] [-R <root-dir>] [-p <prop>,...] <name>\n" }, 3258d5c46e6Sam223141 { "show-ether", do_show_ether, 3268d5c46e6Sam223141 "\tshow-ether\t[-px][-o <field>,...] <link>\n" }, 3278d5c46e6Sam223141 { "create-secobj", do_create_secobj, 3288d5c46e6Sam223141 "\tcreate-secobj\t[-t] [-R <root-dir>] [-f <file>] -c <class> " 3298d5c46e6Sam223141 "<secobj>" }, 3308d5c46e6Sam223141 { "delete-secobj", do_delete_secobj, 3318d5c46e6Sam223141 "\tdelete-secobj\t[-t] [-R <root-dir>] <secobj>[,...]" }, 3328d5c46e6Sam223141 { "show-secobj", do_show_secobj, 3338d5c46e6Sam223141 "\tshow-secobj\t[-pP] [-o <field>,...] [<secobj>,...]\n" }, 3348d5c46e6Sam223141 { "init-linkprop", do_init_linkprop, NULL }, 3358d5c46e6Sam223141 { "init-secobj", do_init_secobj, NULL }, 3368d5c46e6Sam223141 { "create-vlan", do_create_vlan, 3378d5c46e6Sam223141 "\tcreate-vlan\t[-ft] [-R <root-dir>] -l <link> -v <vid> [link]" }, 3388d5c46e6Sam223141 { "delete-vlan", do_delete_vlan, 3398d5c46e6Sam223141 "\tdelete-vlan\t[-t] [-R <root-dir>] <link>" }, 3408d5c46e6Sam223141 { "show-vlan", do_show_vlan, 3418d5c46e6Sam223141 "\tshow-vlan\t[-pP] [-o <field>,..] [<link>]\n" }, 3428d5c46e6Sam223141 { "up-vlan", do_up_vlan, NULL }, 3438d5c46e6Sam223141 { "delete-phys", do_delete_phys, 3448d5c46e6Sam223141 "\tdelete-phys\t<link>" }, 3458d5c46e6Sam223141 { "show-phys", do_show_phys, 3468d5c46e6Sam223141 "\tshow-phys\t[-pP] [-o <field>,..] [<link>]" }, 3478d5c46e6Sam223141 { "init-phys", do_init_phys, NULL }, 3488d5c46e6Sam223141 { "show-linkmap", do_show_linkmap, NULL } 3497c478bd9Sstevel@tonic-gate }; 3507c478bd9Sstevel@tonic-gate 351d62bc4baSyz147064 static const struct option lopts[] = { 3527c478bd9Sstevel@tonic-gate {"vlan-id", required_argument, 0, 'v'}, 353e7801d59Ssowmini {"output", required_argument, 0, 'o'}, 3547c478bd9Sstevel@tonic-gate {"dev", required_argument, 0, 'd'}, 3557c478bd9Sstevel@tonic-gate {"policy", required_argument, 0, 'P'}, 356d62bc4baSyz147064 {"lacp-mode", required_argument, 0, 'L'}, 3577c478bd9Sstevel@tonic-gate {"lacp-timer", required_argument, 0, 'T'}, 3587c478bd9Sstevel@tonic-gate {"unicast", required_argument, 0, 'u'}, 359d62bc4baSyz147064 {"temporary", no_argument, 0, 't'}, 360d62bc4baSyz147064 {"root-dir", required_argument, 0, 'R'}, 361d62bc4baSyz147064 {"link", required_argument, 0, 'l'}, 362d62bc4baSyz147064 {"forcible", no_argument, 0, 'f'}, 363d62bc4baSyz147064 { 0, 0, 0, 0 } 364d62bc4baSyz147064 }; 365d62bc4baSyz147064 366d62bc4baSyz147064 static const struct option show_lopts[] = { 3677c478bd9Sstevel@tonic-gate {"statistics", no_argument, 0, 's'}, 3687c478bd9Sstevel@tonic-gate {"interval", required_argument, 0, 'i'}, 3697c478bd9Sstevel@tonic-gate {"parseable", no_argument, 0, 'p'}, 370d62bc4baSyz147064 {"extended", no_argument, 0, 'x'}, 371e7801d59Ssowmini {"output", required_argument, 0, 'o'}, 372d62bc4baSyz147064 {"persistent", no_argument, 0, 'P'}, 373d62bc4baSyz147064 {"lacp", no_argument, 0, 'L'}, 3747c478bd9Sstevel@tonic-gate { 0, 0, 0, 0 } 3757c478bd9Sstevel@tonic-gate }; 3767c478bd9Sstevel@tonic-gate 3770ba2cbe9Sxc151355 static const struct option prop_longopts[] = { 3780ba2cbe9Sxc151355 {"temporary", no_argument, 0, 't' }, 379e7801d59Ssowmini {"output", required_argument, 0, 'o' }, 3800ba2cbe9Sxc151355 {"root-dir", required_argument, 0, 'R' }, 3810ba2cbe9Sxc151355 {"prop", required_argument, 0, 'p' }, 3820ba2cbe9Sxc151355 {"parseable", no_argument, 0, 'c' }, 3830ba2cbe9Sxc151355 {"persistent", no_argument, 0, 'P' }, 3840ba2cbe9Sxc151355 { 0, 0, 0, 0 } 3850ba2cbe9Sxc151355 }; 3860ba2cbe9Sxc151355 3870ba2cbe9Sxc151355 static const struct option wifi_longopts[] = { 3880ba2cbe9Sxc151355 {"parseable", no_argument, 0, 'p' }, 3890ba2cbe9Sxc151355 {"output", required_argument, 0, 'o' }, 3900ba2cbe9Sxc151355 {"essid", required_argument, 0, 'e' }, 3910ba2cbe9Sxc151355 {"bsstype", required_argument, 0, 'b' }, 3920ba2cbe9Sxc151355 {"mode", required_argument, 0, 'm' }, 3930ba2cbe9Sxc151355 {"key", required_argument, 0, 'k' }, 3940ba2cbe9Sxc151355 {"sec", required_argument, 0, 's' }, 3950ba2cbe9Sxc151355 {"auth", required_argument, 0, 'a' }, 3960ba2cbe9Sxc151355 {"create-ibss", required_argument, 0, 'c' }, 3970ba2cbe9Sxc151355 {"timeout", required_argument, 0, 'T' }, 3980ba2cbe9Sxc151355 {"all-links", no_argument, 0, 'a' }, 3990ba2cbe9Sxc151355 {"temporary", no_argument, 0, 't' }, 4000ba2cbe9Sxc151355 {"root-dir", required_argument, 0, 'R' }, 4010ba2cbe9Sxc151355 {"persistent", no_argument, 0, 'P' }, 4020ba2cbe9Sxc151355 {"file", required_argument, 0, 'f' }, 4030ba2cbe9Sxc151355 { 0, 0, 0, 0 } 4040ba2cbe9Sxc151355 }; 405e7801d59Ssowmini static const struct option showeth_lopts[] = { 406e7801d59Ssowmini {"parseable", no_argument, 0, 'p' }, 407e7801d59Ssowmini {"extended", no_argument, 0, 'x' }, 408e7801d59Ssowmini {"output", required_argument, 0, 'o' }, 409e7801d59Ssowmini { 0, 0, 0, 0 } 410e7801d59Ssowmini }; 411e7801d59Ssowmini 412e7801d59Ssowmini /* 413e7801d59Ssowmini * structures for 'dladm show-ether' 414e7801d59Ssowmini */ 415e7801d59Ssowmini typedef struct ether_fields_buf_s 416e7801d59Ssowmini { 417e7801d59Ssowmini char eth_link[15]; 418e7801d59Ssowmini char eth_ptype[8]; 419e7801d59Ssowmini char eth_state[8]; 420e7801d59Ssowmini char eth_autoneg[5]; 421e7801d59Ssowmini char eth_spdx[31]; 422e7801d59Ssowmini char eth_pause[6]; 423e7801d59Ssowmini char eth_rem_fault[16]; 424e7801d59Ssowmini } ether_fields_buf_t; 425e7801d59Ssowmini 426e7801d59Ssowmini static print_field_t ether_fields[] = { 427e7801d59Ssowmini /* name, header, field width, offset, cmdtype */ 428e7801d59Ssowmini { "link", "LINK", 15, 429e7801d59Ssowmini offsetof(ether_fields_buf_t, eth_link), CMD_TYPE_ANY}, 430e7801d59Ssowmini { "ptype", "PTYPE", 8, 431e7801d59Ssowmini offsetof(ether_fields_buf_t, eth_ptype), CMD_TYPE_ANY}, 432e7801d59Ssowmini { "state", "STATE", 8, 433e7801d59Ssowmini offsetof(ether_fields_buf_t, eth_state), CMD_TYPE_ANY}, 434e7801d59Ssowmini { "auto", "AUTO", 5, 435e7801d59Ssowmini offsetof(ether_fields_buf_t, eth_autoneg), CMD_TYPE_ANY}, 436e7801d59Ssowmini { "speed-duplex", "SPEED-DUPLEX", 31, 437e7801d59Ssowmini offsetof(ether_fields_buf_t, eth_spdx), CMD_TYPE_ANY}, 438e7801d59Ssowmini { "pause", "PAUSE", 6, 439e7801d59Ssowmini offsetof(ether_fields_buf_t, eth_pause), CMD_TYPE_ANY}, 440e7801d59Ssowmini { "rem_fault", "REM_FAULT", 16, 441e7801d59Ssowmini offsetof(ether_fields_buf_t, eth_rem_fault), CMD_TYPE_ANY}} 442e7801d59Ssowmini ; 443e7801d59Ssowmini #define ETHER_MAX_FIELDS (sizeof (ether_fields) / sizeof (print_field_t)) 444e7801d59Ssowmini 445e7801d59Ssowmini typedef struct print_ether_state { 446e7801d59Ssowmini const char *es_link; 447e7801d59Ssowmini boolean_t es_parseable; 448e7801d59Ssowmini boolean_t es_header; 449e7801d59Ssowmini boolean_t es_extended; 450e7801d59Ssowmini print_state_t es_print; 451e7801d59Ssowmini } print_ether_state_t; 452e7801d59Ssowmini 453e7801d59Ssowmini /* 454e7801d59Ssowmini * structures for 'dladm show-dev'. 455e7801d59Ssowmini */ 456e7801d59Ssowmini typedef enum { 457e7801d59Ssowmini DEV_LINK, 458e7801d59Ssowmini DEV_STATE, 459e7801d59Ssowmini DEV_SPEED, 460e7801d59Ssowmini DEV_DUPLEX 461e7801d59Ssowmini } dev_field_index_t; 462e7801d59Ssowmini 463e7801d59Ssowmini static print_field_t dev_fields[] = { 464e7801d59Ssowmini /* name, header, field width, index, cmdtype */ 465e7801d59Ssowmini { "link", "LINK", 15, DEV_LINK, CMD_TYPE_ANY}, 466e7801d59Ssowmini { "state", "STATE", 6, DEV_STATE, CMD_TYPE_ANY}, 467e7801d59Ssowmini { "speed", "SPEED", 8, DEV_SPEED, CMD_TYPE_ANY}, 468e7801d59Ssowmini { "duplex", "DUPLEX", 8, DEV_DUPLEX, CMD_TYPE_ANY}} 469e7801d59Ssowmini ; 470e7801d59Ssowmini #define DEV_MAX_FIELDS (sizeof (dev_fields) / sizeof (print_field_t)) 471e7801d59Ssowmini 472e7801d59Ssowmini /* 473e7801d59Ssowmini * structures for 'dladm show-dev -s' (print statistics) 474e7801d59Ssowmini */ 475e7801d59Ssowmini typedef enum { 476e7801d59Ssowmini DEVS_LINK, 477e7801d59Ssowmini DEVS_IPKTS, 478e7801d59Ssowmini DEVS_RBYTES, 479e7801d59Ssowmini DEVS_IERRORS, 480e7801d59Ssowmini DEVS_OPKTS, 481e7801d59Ssowmini DEVS_OBYTES, 482e7801d59Ssowmini DEVS_OERRORS 483e7801d59Ssowmini } devs_field_index_t; 484e7801d59Ssowmini 485e7801d59Ssowmini static print_field_t devs_fields[] = { 486e7801d59Ssowmini /* name, header, field width, index, cmdtype */ 487e7801d59Ssowmini { "link", "LINK", 15, DEVS_LINK, CMD_TYPE_ANY}, 488e7801d59Ssowmini { "ipackets", "IPACKETS", 10, DEVS_IPKTS, CMD_TYPE_ANY}, 489e7801d59Ssowmini { "rbytes", "RBYTES", 8, DEVS_RBYTES, CMD_TYPE_ANY}, 490e7801d59Ssowmini { "ierrors", "IERRORS", 10, DEVS_IERRORS, CMD_TYPE_ANY}, 491e7801d59Ssowmini { "opackets", "OPACKETS", 12, DEVS_OPKTS, CMD_TYPE_ANY}, 492e7801d59Ssowmini { "obytes", "OBYTES", 12, DEVS_OBYTES, CMD_TYPE_ANY}, 493e7801d59Ssowmini { "oerrors", "OERRORS", 8, DEVS_OERRORS, CMD_TYPE_ANY}} 494e7801d59Ssowmini ; 495e7801d59Ssowmini #define DEVS_MAX_FIELDS (sizeof (devs_fields) / sizeof (print_field_t)) 496e7801d59Ssowmini typedef struct dev_args_s { 497e7801d59Ssowmini char *devs_link; 498e7801d59Ssowmini pktsum_t *devs_psum; 499e7801d59Ssowmini } dev_args_t; 500e7801d59Ssowmini static char *print_dev_stats(print_field_t *, void *); 501e7801d59Ssowmini static char *print_dev(print_field_t *, void *); 502e7801d59Ssowmini 503e7801d59Ssowmini /* 504e7801d59Ssowmini * buffer used by print functions for show-{link,phys,vlan} commands. 505e7801d59Ssowmini */ 506e7801d59Ssowmini typedef struct link_fields_buf_s { 507e7801d59Ssowmini char link_name[MAXLINKNAMELEN]; 508e7801d59Ssowmini char link_class[DLADM_STRSIZE]; 509c08e5e1aSdr146992 char link_mtu[11]; 510e7801d59Ssowmini char link_state[DLADM_STRSIZE]; 511e7801d59Ssowmini char link_over[MAXLINKNAMELEN]; 5124045d941Ssowmini char link_phys_state[DLADM_STRSIZE]; 513e7801d59Ssowmini char link_phys_media[DLADM_STRSIZE]; 514e7801d59Ssowmini char link_phys_speed[DLADM_STRSIZE]; 515e7801d59Ssowmini char link_phys_duplex[DLPI_LINKNAME_MAX]; 516e7801d59Ssowmini char link_phys_device[DLPI_LINKNAME_MAX]; 517e7801d59Ssowmini char link_flags[6]; 518e7801d59Ssowmini char link_vlan_vid[6]; 519e7801d59Ssowmini } link_fields_buf_t; 520e7801d59Ssowmini 521e7801d59Ssowmini /* 522e7801d59Ssowmini * structures for 'dladm show-link' 523e7801d59Ssowmini */ 524e7801d59Ssowmini static print_field_t link_fields[] = { 525e7801d59Ssowmini /* name, header, field width, offset, cmdtype */ 526e7801d59Ssowmini { "link", "LINK", 11, 527e7801d59Ssowmini offsetof(link_fields_buf_t, link_name), CMD_TYPE_ANY}, 528e7801d59Ssowmini { "class", "CLASS", 8, 529e7801d59Ssowmini offsetof(link_fields_buf_t, link_class), CMD_TYPE_ANY}, 530e7801d59Ssowmini { "mtu", "MTU", 6, 531e7801d59Ssowmini offsetof(link_fields_buf_t, link_mtu), CMD_TYPE_ANY}, 532e7801d59Ssowmini { "state", "STATE", 8, 533e7801d59Ssowmini offsetof(link_fields_buf_t, link_state), CMD_TYPE_ANY}, 534e7801d59Ssowmini { "over", "OVER", DLPI_LINKNAME_MAX, 535e7801d59Ssowmini offsetof(link_fields_buf_t, link_over), CMD_TYPE_ANY}} 536e7801d59Ssowmini ; 537e7801d59Ssowmini #define DEV_LINK_FIELDS (sizeof (link_fields) / sizeof (print_field_t)) 538e7801d59Ssowmini 539e7801d59Ssowmini /* 540e7801d59Ssowmini * structures for 'dladm show-aggr' 541e7801d59Ssowmini */ 542e7801d59Ssowmini typedef struct laggr_fields_buf_s { 543e7801d59Ssowmini char laggr_name[DLPI_LINKNAME_MAX]; 544e7801d59Ssowmini char laggr_policy[9]; 545e7801d59Ssowmini char laggr_addrpolicy[ETHERADDRL * 3 + 3]; 546e7801d59Ssowmini char laggr_lacpactivity[14]; 547e7801d59Ssowmini char laggr_lacptimer[DLADM_STRSIZE]; 548e7801d59Ssowmini char laggr_flags[7]; 549e7801d59Ssowmini } laggr_fields_buf_t; 550e7801d59Ssowmini 551e7801d59Ssowmini typedef struct laggr_args_s { 552e7801d59Ssowmini int laggr_lport; /* -1 indicates the aggr itself */ 553e7801d59Ssowmini const char *laggr_link; 554e7801d59Ssowmini dladm_aggr_grp_attr_t *laggr_ginfop; 555e7801d59Ssowmini dladm_status_t *laggr_status; 556e7801d59Ssowmini pktsum_t *laggr_pktsumtot; /* -s only */ 557e7801d59Ssowmini pktsum_t *laggr_prevstats; /* -s only */ 558e7801d59Ssowmini boolean_t laggr_parseable; 559e7801d59Ssowmini } laggr_args_t; 560e7801d59Ssowmini 561e7801d59Ssowmini static print_field_t laggr_fields[] = { 562e7801d59Ssowmini /* name, header, field width, offset, cmdtype */ 563e7801d59Ssowmini { "link", "LINK", 15, 564e7801d59Ssowmini offsetof(laggr_fields_buf_t, laggr_name), CMD_TYPE_ANY}, 565e7801d59Ssowmini { "policy", "POLICY", 8, 566e7801d59Ssowmini offsetof(laggr_fields_buf_t, laggr_policy), CMD_TYPE_ANY}, 567e7801d59Ssowmini { "addrpolicy", "ADDRPOLICY", ETHERADDRL * 3 + 2, 568e7801d59Ssowmini offsetof(laggr_fields_buf_t, laggr_addrpolicy), CMD_TYPE_ANY}, 569e7801d59Ssowmini { "lacpactivity", "LACPACTIVITY", 13, 570e7801d59Ssowmini offsetof(laggr_fields_buf_t, laggr_lacpactivity), CMD_TYPE_ANY}, 571e7801d59Ssowmini { "lacptimer", "LACPTIMER", 11, 572e7801d59Ssowmini offsetof(laggr_fields_buf_t, laggr_lacptimer), CMD_TYPE_ANY}, 573e7801d59Ssowmini { "flags", "FLAGS", 7, 574e7801d59Ssowmini offsetof(laggr_fields_buf_t, laggr_flags), CMD_TYPE_ANY}} 575e7801d59Ssowmini ; 576e7801d59Ssowmini #define LAGGR_MAX_FIELDS (sizeof (laggr_fields) / sizeof (print_field_t)) 577e7801d59Ssowmini 578e7801d59Ssowmini /* 579e7801d59Ssowmini * structures for 'dladm show-aggr -x'. 580e7801d59Ssowmini */ 581e7801d59Ssowmini typedef enum { 582e7801d59Ssowmini AGGR_X_LINK, 583e7801d59Ssowmini AGGR_X_PORT, 584e7801d59Ssowmini AGGR_X_SPEED, 585e7801d59Ssowmini AGGR_X_DUPLEX, 586e7801d59Ssowmini AGGR_X_STATE, 587e7801d59Ssowmini AGGR_X_ADDRESS, 588e7801d59Ssowmini AGGR_X_PORTSTATE 589e7801d59Ssowmini } aggr_x_field_index_t; 590e7801d59Ssowmini 591e7801d59Ssowmini static print_field_t aggr_x_fields[] = { 592e7801d59Ssowmini /* name, header, field width, index, cmdtype */ 593e7801d59Ssowmini { "link", "LINK", 11, AGGR_X_LINK, CMD_TYPE_ANY}, 594e7801d59Ssowmini { "port", "PORT", 14, AGGR_X_PORT, CMD_TYPE_ANY}, 595e7801d59Ssowmini { "speed", "SPEED", 4, AGGR_X_SPEED, CMD_TYPE_ANY}, 596e7801d59Ssowmini { "duplex", "DUPLEX", 9, AGGR_X_DUPLEX, CMD_TYPE_ANY}, 597e7801d59Ssowmini { "state", "STATE", 9, AGGR_X_STATE, CMD_TYPE_ANY}, 598e7801d59Ssowmini { "address", "ADDRESS", 18, AGGR_X_ADDRESS, CMD_TYPE_ANY}, 599e7801d59Ssowmini { "portstate", "PORTSTATE", 15, AGGR_X_PORTSTATE, CMD_TYPE_ANY}} 600e7801d59Ssowmini ; 601e7801d59Ssowmini #define AGGR_X_MAX_FIELDS \ 602e7801d59Ssowmini (sizeof (aggr_x_fields) / sizeof (print_field_t)) 603e7801d59Ssowmini 604e7801d59Ssowmini /* 605e7801d59Ssowmini * structures for 'dladm show-aggr -s'. 606e7801d59Ssowmini */ 607e7801d59Ssowmini typedef enum { 608e7801d59Ssowmini AGGR_S_LINK, 609e7801d59Ssowmini AGGR_S_PORT, 610e7801d59Ssowmini AGGR_S_IPKTS, 611e7801d59Ssowmini AGGR_S_RBYTES, 612e7801d59Ssowmini AGGR_S_OPKTS, 613e7801d59Ssowmini AGGR_S_OBYTES, 614e7801d59Ssowmini AGGR_S_IPKTDIST, 615e7801d59Ssowmini AGGR_S_OPKTDIST 616e7801d59Ssowmini } aggr_s_field_index_t; 617e7801d59Ssowmini 618e7801d59Ssowmini static print_field_t aggr_s_fields[] = { 619e7801d59Ssowmini /* name, header, field width, index, cmdtype */ 620e7801d59Ssowmini { "link", "LINK", 11, AGGR_S_LINK, 621e7801d59Ssowmini CMD_TYPE_ANY}, 622e7801d59Ssowmini { "port", "PORT", 9, AGGR_S_PORT, 623e7801d59Ssowmini CMD_TYPE_ANY}, 624e7801d59Ssowmini { "ipackets", "IPACKETS", 7, AGGR_S_IPKTS, 625e7801d59Ssowmini CMD_TYPE_ANY}, 626e7801d59Ssowmini { "rbytes", "RBYTES", 7, AGGR_S_RBYTES, 627e7801d59Ssowmini CMD_TYPE_ANY}, 628e7801d59Ssowmini { "opackets", "OPACKETS", 7, AGGR_S_OPKTS, 629e7801d59Ssowmini CMD_TYPE_ANY}, 630e7801d59Ssowmini { "obytes", "OBYTES", 7, AGGR_S_OBYTES, 631e7801d59Ssowmini CMD_TYPE_ANY}, 632e7801d59Ssowmini { "ipktdist", "IPKTDIST", 8, AGGR_S_IPKTDIST, 633e7801d59Ssowmini CMD_TYPE_ANY}, 634e7801d59Ssowmini { "opktdist", "OPKTDIST", 14, AGGR_S_OPKTDIST, 635e7801d59Ssowmini CMD_TYPE_ANY}} 636e7801d59Ssowmini ; 637e7801d59Ssowmini #define AGGR_S_MAX_FIELDS \ 638e7801d59Ssowmini (sizeof (aggr_l_fields) / sizeof (print_field_t)) 639e7801d59Ssowmini 640e7801d59Ssowmini /* 641e7801d59Ssowmini * structures for 'dladm show-dev -L'. 642e7801d59Ssowmini */ 643e7801d59Ssowmini typedef enum { 644e7801d59Ssowmini AGGR_L_LINK, 645e7801d59Ssowmini AGGR_L_PORT, 646e7801d59Ssowmini AGGR_L_AGGREGATABLE, 647e7801d59Ssowmini AGGR_L_SYNC, 648e7801d59Ssowmini AGGR_L_COLL, 649e7801d59Ssowmini AGGR_L_DIST, 650e7801d59Ssowmini AGGR_L_DEFAULTED, 651e7801d59Ssowmini AGGR_L_EXPIRED 652e7801d59Ssowmini } aggr_l_field_index_t; 653e7801d59Ssowmini 654e7801d59Ssowmini static print_field_t aggr_l_fields[] = { 655e7801d59Ssowmini /* name, header, field width, index, cmdtype */ 656e7801d59Ssowmini { "link", "LINK", 11, AGGR_L_LINK, 657e7801d59Ssowmini CMD_TYPE_ANY}, 658e7801d59Ssowmini { "port", "PORT", 12, AGGR_L_PORT, 659e7801d59Ssowmini CMD_TYPE_ANY}, 660e7801d59Ssowmini { "aggregatable", "AGGREGATABLE", 12, AGGR_L_AGGREGATABLE, 661e7801d59Ssowmini CMD_TYPE_ANY}, 662e7801d59Ssowmini { "sync", "SYNC", 4, AGGR_L_SYNC, 663e7801d59Ssowmini CMD_TYPE_ANY}, 664e7801d59Ssowmini { "coll", "COLL", 4, AGGR_L_COLL, 665e7801d59Ssowmini CMD_TYPE_ANY}, 666e7801d59Ssowmini { "dist", "DIST", 4, AGGR_L_DIST, 667e7801d59Ssowmini CMD_TYPE_ANY}, 668e7801d59Ssowmini { "defaulted", "DEFAULTED", 9, AGGR_L_DEFAULTED, 669e7801d59Ssowmini CMD_TYPE_ANY}, 670e7801d59Ssowmini { "expired", "EXPIRED", 14, AGGR_L_EXPIRED, 671e7801d59Ssowmini CMD_TYPE_ANY}} 672e7801d59Ssowmini ; 673e7801d59Ssowmini #define AGGR_L_MAX_FIELDS \ 674e7801d59Ssowmini (sizeof (aggr_l_fields) / sizeof (print_field_t)) 675e7801d59Ssowmini 676e7801d59Ssowmini /* 677e7801d59Ssowmini * structures for 'dladm show-phys' 678e7801d59Ssowmini */ 679e7801d59Ssowmini 680e7801d59Ssowmini static print_field_t phys_fields[] = { 681e7801d59Ssowmini /* name, header, field width, offset, cmdtype */ 682e7801d59Ssowmini { "link", "LINK", 12, 683e7801d59Ssowmini offsetof(link_fields_buf_t, link_name), CMD_TYPE_ANY}, 684e7801d59Ssowmini { "media", "MEDIA", 20, 685e7801d59Ssowmini offsetof(link_fields_buf_t, link_phys_media), CMD_TYPE_ANY}, 686e7801d59Ssowmini { "state", "STATE", 10, 687e7801d59Ssowmini offsetof(link_fields_buf_t, link_phys_state), CMD_TYPE_ANY}, 6886be03d0bSVasumathi Sundaram - Sun Microsystems { "speed", "SPEED", 6, 689e7801d59Ssowmini offsetof(link_fields_buf_t, link_phys_speed), CMD_TYPE_ANY}, 690e7801d59Ssowmini { "duplex", "DUPLEX", 9, 691e7801d59Ssowmini offsetof(link_fields_buf_t, link_phys_duplex), CMD_TYPE_ANY}, 692e7801d59Ssowmini { "device", "DEVICE", 12, 693e7801d59Ssowmini offsetof(link_fields_buf_t, link_phys_device), CMD_TYPE_ANY}, 694e7801d59Ssowmini { "flags", "FLAGS", 6, 695e7801d59Ssowmini offsetof(link_fields_buf_t, link_flags), CMD_TYPE_ANY}} 696e7801d59Ssowmini ; 697e7801d59Ssowmini #define PHYS_MAX_FIELDS (sizeof (phys_fields) / sizeof (print_field_t)) 698e7801d59Ssowmini 699e7801d59Ssowmini /* 700e7801d59Ssowmini * structures for 'dladm show-vlan' 701e7801d59Ssowmini */ 702e7801d59Ssowmini static print_field_t vlan_fields[] = { 703e7801d59Ssowmini /* name, header, field width, offset, cmdtype */ 704e7801d59Ssowmini { "link", "LINK", 15, 705e7801d59Ssowmini offsetof(link_fields_buf_t, link_name), CMD_TYPE_ANY}, 706e7801d59Ssowmini { "vid", "VID", 8, 707e7801d59Ssowmini offsetof(link_fields_buf_t, link_vlan_vid), CMD_TYPE_ANY}, 708e7801d59Ssowmini { "over", "OVER", 12, 709e7801d59Ssowmini offsetof(link_fields_buf_t, link_over), CMD_TYPE_ANY}, 710e7801d59Ssowmini { "flags", "FLAGS", 6, 711e7801d59Ssowmini offsetof(link_fields_buf_t, link_flags), CMD_TYPE_ANY}} 712e7801d59Ssowmini ; 713e7801d59Ssowmini #define VLAN_MAX_FIELDS (sizeof (vlan_fields) / sizeof (print_field_t)) 714e7801d59Ssowmini 715e7801d59Ssowmini /* 716e7801d59Ssowmini * structures for 'dladm show-wifi' 717e7801d59Ssowmini */ 718e7801d59Ssowmini static print_field_t wifi_fields[] = { 719e7801d59Ssowmini { "link", "LINK", 10, 0, WIFI_CMD_ALL}, 720e7801d59Ssowmini { "essid", "ESSID", 19, DLADM_WLAN_ATTR_ESSID, WIFI_CMD_ALL}, 721e7801d59Ssowmini { "bssid", "BSSID/IBSSID", 17, DLADM_WLAN_ATTR_BSSID, WIFI_CMD_ALL}, 722e7801d59Ssowmini { "ibssid", "BSSID/IBSSID", 17, DLADM_WLAN_ATTR_BSSID, WIFI_CMD_ALL}, 723e7801d59Ssowmini { "mode", "MODE", 6, DLADM_WLAN_ATTR_MODE, WIFI_CMD_ALL}, 724e7801d59Ssowmini { "speed", "SPEED", 6, DLADM_WLAN_ATTR_SPEED, WIFI_CMD_ALL}, 725e7801d59Ssowmini { "auth", "AUTH", 8, DLADM_WLAN_ATTR_AUTH, WIFI_CMD_SHOW}, 726e7801d59Ssowmini { "bsstype", "BSSTYPE", 8, DLADM_WLAN_ATTR_BSSTYPE, WIFI_CMD_ALL}, 727e7801d59Ssowmini { "sec", "SEC", 6, DLADM_WLAN_ATTR_SECMODE, WIFI_CMD_ALL}, 728e7801d59Ssowmini { "status", "STATUS", 17, DLADM_WLAN_LINKATTR_STATUS, WIFI_CMD_SHOW}, 729e7801d59Ssowmini { "strength", "STRENGTH", 10, DLADM_WLAN_ATTR_STRENGTH, WIFI_CMD_ALL}} 730e7801d59Ssowmini ; 731e7801d59Ssowmini 732e7801d59Ssowmini static char *all_scan_wifi_fields = 733e7801d59Ssowmini "link,essid,bssid,sec,strength,mode,speed,bsstype"; 734e7801d59Ssowmini static char *all_show_wifi_fields = 735e7801d59Ssowmini "link,status,essid,sec,strength,mode,speed,auth,bssid,bsstype"; 736e7801d59Ssowmini static char *def_scan_wifi_fields = 737e7801d59Ssowmini "link,essid,bssid,sec,strength,mode,speed"; 738e7801d59Ssowmini static char *def_show_wifi_fields = 739e7801d59Ssowmini "link,status,essid,sec,strength,mode,speed"; 740e7801d59Ssowmini 741e7801d59Ssowmini #define WIFI_MAX_FIELDS (sizeof (wifi_fields) / sizeof (print_field_t)) 742e7801d59Ssowmini 743e7801d59Ssowmini /* 744e7801d59Ssowmini * structures for 'dladm show-linkprop' 745e7801d59Ssowmini */ 746e7801d59Ssowmini typedef enum { 747e7801d59Ssowmini LINKPROP_LINK, 748e7801d59Ssowmini LINKPROP_PROPERTY, 749*afdda45fSVasumathi Sundaram - Sun Microsystems LINKPROP_PERM, 750e7801d59Ssowmini LINKPROP_VALUE, 751e7801d59Ssowmini LINKPROP_DEFAULT, 752e7801d59Ssowmini LINKPROP_POSSIBLE 753e7801d59Ssowmini } linkprop_field_index_t; 754e7801d59Ssowmini 755e7801d59Ssowmini static print_field_t linkprop_fields[] = { 756e7801d59Ssowmini /* name, header, field width, index, cmdtype */ 757e7801d59Ssowmini { "link", "LINK", 12, LINKPROP_LINK, CMD_TYPE_ANY}, 758e7801d59Ssowmini { "property", "PROPERTY", 15, LINKPROP_PROPERTY, CMD_TYPE_ANY}, 759*afdda45fSVasumathi Sundaram - Sun Microsystems { "perm", "PERM", 4, LINKPROP_PERM, CMD_TYPE_ANY}, 760e7801d59Ssowmini { "value", "VALUE", 14, LINKPROP_VALUE, CMD_TYPE_ANY}, 761e7801d59Ssowmini { "default", "DEFAULT", 14, LINKPROP_DEFAULT, CMD_TYPE_ANY}, 762e7801d59Ssowmini { "possible", "POSSIBLE", 20, LINKPROP_POSSIBLE, CMD_TYPE_ANY}} 763e7801d59Ssowmini ; 764e7801d59Ssowmini #define LINKPROP_MAX_FIELDS \ 765e7801d59Ssowmini (sizeof (linkprop_fields) / sizeof (print_field_t)) 766e7801d59Ssowmini 767e7801d59Ssowmini #define MAX_PROPS 32 768e7801d59Ssowmini #define MAX_PROP_LINE 512 769e7801d59Ssowmini 770e7801d59Ssowmini typedef struct prop_info { 771e7801d59Ssowmini char *pi_name; 772e7801d59Ssowmini char *pi_val[DLADM_MAX_PROP_VALCNT]; 773e7801d59Ssowmini uint_t pi_count; 774e7801d59Ssowmini } prop_info_t; 775e7801d59Ssowmini 776e7801d59Ssowmini typedef struct prop_list { 777e7801d59Ssowmini prop_info_t pl_info[MAX_PROPS]; 778e7801d59Ssowmini uint_t pl_count; 779e7801d59Ssowmini char *pl_buf; 780e7801d59Ssowmini } prop_list_t; 781e7801d59Ssowmini 782e7801d59Ssowmini typedef struct show_linkprop_state { 783e7801d59Ssowmini char ls_link[MAXLINKNAMELEN]; 784e7801d59Ssowmini char *ls_line; 785e7801d59Ssowmini char **ls_propvals; 786e7801d59Ssowmini prop_list_t *ls_proplist; 787e7801d59Ssowmini boolean_t ls_parseable; 788e7801d59Ssowmini boolean_t ls_persist; 789e7801d59Ssowmini boolean_t ls_header; 790e7801d59Ssowmini dladm_status_t ls_status; 791e7801d59Ssowmini dladm_status_t ls_retstatus; 792e7801d59Ssowmini print_state_t ls_print; 793e7801d59Ssowmini } show_linkprop_state_t; 794e7801d59Ssowmini 795e7801d59Ssowmini typedef struct linkprop_args_s { 796e7801d59Ssowmini show_linkprop_state_t *ls_state; 797e7801d59Ssowmini char *ls_propname; 798e7801d59Ssowmini datalink_id_t ls_linkid; 799e7801d59Ssowmini } linkprop_args_t; 800e7801d59Ssowmini 801e7801d59Ssowmini /* 802e7801d59Ssowmini * structures for 'dladm show-secobj' 803e7801d59Ssowmini */ 804e7801d59Ssowmini typedef struct secobj_fields_buf_s { 805e7801d59Ssowmini char ss_obj_name[DLADM_SECOBJ_VAL_MAX]; 806e7801d59Ssowmini char ss_class[20]; 807e7801d59Ssowmini char ss_val[30]; 808e7801d59Ssowmini } secobj_fields_buf_t; 809e7801d59Ssowmini static print_field_t secobj_fields[] = { 810e7801d59Ssowmini /* name, header, field width, offset, cmdtype */ 811e7801d59Ssowmini { "object", "OBJECT", 20, 812e7801d59Ssowmini offsetof(secobj_fields_buf_t, ss_obj_name), CMD_TYPE_ANY}, 813e7801d59Ssowmini { "class", "CLASS", 20, 814e7801d59Ssowmini offsetof(secobj_fields_buf_t, ss_class), CMD_TYPE_ANY}, 815e7801d59Ssowmini { "value", "VALUE", 30, 816e7801d59Ssowmini offsetof(secobj_fields_buf_t, ss_val), CMD_TYPE_ANY}} 817e7801d59Ssowmini ; 818e7801d59Ssowmini #define DEV_SOBJ_FIELDS (sizeof (secobj_fields) / sizeof (print_field_t)) 8190ba2cbe9Sxc151355 8207c478bd9Sstevel@tonic-gate static char *progname; 8210ba2cbe9Sxc151355 static sig_atomic_t signalled; 8227c478bd9Sstevel@tonic-gate 8237c478bd9Sstevel@tonic-gate static void 8247c478bd9Sstevel@tonic-gate usage(void) 8257c478bd9Sstevel@tonic-gate { 8268d5c46e6Sam223141 int i; 8278d5c46e6Sam223141 cmd_t *cmdp; 8288d5c46e6Sam223141 (void) fprintf(stderr, gettext("usage: dladm <subcommand> <args> ..." 8298d5c46e6Sam223141 "\n")); 8308d5c46e6Sam223141 for (i = 0; i < sizeof (cmds) / sizeof (cmds[0]); i++) { 8318d5c46e6Sam223141 cmdp = &cmds[i]; 8328d5c46e6Sam223141 if (cmdp->c_usage != NULL) 8338d5c46e6Sam223141 (void) fprintf(stderr, "%s\n", gettext(cmdp->c_usage)); 8348d5c46e6Sam223141 } 8357c478bd9Sstevel@tonic-gate exit(1); 8367c478bd9Sstevel@tonic-gate } 8377c478bd9Sstevel@tonic-gate 8387c478bd9Sstevel@tonic-gate int 8397c478bd9Sstevel@tonic-gate main(int argc, char *argv[]) 8407c478bd9Sstevel@tonic-gate { 8417c478bd9Sstevel@tonic-gate int i; 8427c478bd9Sstevel@tonic-gate cmd_t *cmdp; 8437c478bd9Sstevel@tonic-gate 8447c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, ""); 8457c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN) 8467c478bd9Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST" 8477c478bd9Sstevel@tonic-gate #endif 8487c478bd9Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN); 8497c478bd9Sstevel@tonic-gate 8507c478bd9Sstevel@tonic-gate progname = argv[0]; 8517c478bd9Sstevel@tonic-gate 8527c478bd9Sstevel@tonic-gate if (argc < 2) 8537c478bd9Sstevel@tonic-gate usage(); 8547c478bd9Sstevel@tonic-gate 8557c478bd9Sstevel@tonic-gate for (i = 0; i < sizeof (cmds) / sizeof (cmds[0]); i++) { 8567c478bd9Sstevel@tonic-gate cmdp = &cmds[i]; 8577c478bd9Sstevel@tonic-gate if (strcmp(argv[1], cmdp->c_name) == 0) { 8588d5c46e6Sam223141 cmdp->c_fn(argc - 1, &argv[1], cmdp->c_usage); 8597c478bd9Sstevel@tonic-gate exit(0); 8607c478bd9Sstevel@tonic-gate } 8617c478bd9Sstevel@tonic-gate } 8627c478bd9Sstevel@tonic-gate 8637c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("%s: unknown subcommand '%s'\n"), 8647c478bd9Sstevel@tonic-gate progname, argv[1]); 8657c478bd9Sstevel@tonic-gate usage(); 8667c478bd9Sstevel@tonic-gate 8677c478bd9Sstevel@tonic-gate return (0); 8687c478bd9Sstevel@tonic-gate } 8697c478bd9Sstevel@tonic-gate 8707c478bd9Sstevel@tonic-gate static void 8718d5c46e6Sam223141 do_create_aggr(int argc, char *argv[], const char *use) 8727c478bd9Sstevel@tonic-gate { 8737c478bd9Sstevel@tonic-gate char option; 874d62bc4baSyz147064 int key = 0; 8757c478bd9Sstevel@tonic-gate uint32_t policy = AGGR_POLICY_L4; 8767c478bd9Sstevel@tonic-gate aggr_lacp_mode_t lacp_mode = AGGR_LACP_OFF; 8777c478bd9Sstevel@tonic-gate aggr_lacp_timer_t lacp_timer = AGGR_LACP_TIMER_SHORT; 878f595a68aSyz147064 dladm_aggr_port_attr_db_t port[MAXPORT]; 879d62bc4baSyz147064 uint_t n, ndev, nlink; 8807c478bd9Sstevel@tonic-gate uint8_t mac_addr[ETHERADDRL]; 8817c478bd9Sstevel@tonic-gate boolean_t mac_addr_fixed = B_FALSE; 8827c478bd9Sstevel@tonic-gate boolean_t P_arg = B_FALSE; 8837c478bd9Sstevel@tonic-gate boolean_t l_arg = B_FALSE; 8847c478bd9Sstevel@tonic-gate boolean_t u_arg = B_FALSE; 8857c478bd9Sstevel@tonic-gate boolean_t T_arg = B_FALSE; 886d62bc4baSyz147064 uint32_t flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST; 8877c478bd9Sstevel@tonic-gate char *altroot = NULL; 888d62bc4baSyz147064 char name[MAXLINKNAMELEN]; 889d62bc4baSyz147064 char *devs[MAXPORT]; 890d62bc4baSyz147064 char *links[MAXPORT]; 891f595a68aSyz147064 dladm_status_t status; 8927c478bd9Sstevel@tonic-gate 893d62bc4baSyz147064 ndev = nlink = opterr = 0; 894d62bc4baSyz147064 while ((option = getopt_long(argc, argv, ":d:l:L:P:R:tfu:T:", 895d62bc4baSyz147064 lopts, NULL)) != -1) { 8967c478bd9Sstevel@tonic-gate switch (option) { 8977c478bd9Sstevel@tonic-gate case 'd': 898d62bc4baSyz147064 if (ndev + nlink >= MAXPORT) 899d62bc4baSyz147064 die("too many ports specified"); 9007c478bd9Sstevel@tonic-gate 901d62bc4baSyz147064 devs[ndev++] = optarg; 9027c478bd9Sstevel@tonic-gate break; 9037c478bd9Sstevel@tonic-gate case 'P': 90433343a97Smeem if (P_arg) 90533343a97Smeem die_optdup(option); 9067c478bd9Sstevel@tonic-gate 9077c478bd9Sstevel@tonic-gate P_arg = B_TRUE; 908f595a68aSyz147064 if (!dladm_aggr_str2policy(optarg, &policy)) 90933343a97Smeem die("invalid policy '%s'", optarg); 9107c478bd9Sstevel@tonic-gate break; 9117c478bd9Sstevel@tonic-gate case 'u': 91233343a97Smeem if (u_arg) 91333343a97Smeem die_optdup(option); 9147c478bd9Sstevel@tonic-gate 9157c478bd9Sstevel@tonic-gate u_arg = B_TRUE; 916f595a68aSyz147064 if (!dladm_aggr_str2macaddr(optarg, &mac_addr_fixed, 91733343a97Smeem mac_addr)) 91833343a97Smeem die("invalid MAC address '%s'", optarg); 9197c478bd9Sstevel@tonic-gate break; 9207c478bd9Sstevel@tonic-gate case 'l': 921d62bc4baSyz147064 if (isdigit(optarg[strlen(optarg) - 1])) { 922d62bc4baSyz147064 923d62bc4baSyz147064 /* 924d62bc4baSyz147064 * Ended with digit, possibly a link name. 925d62bc4baSyz147064 */ 926d62bc4baSyz147064 if (ndev + nlink >= MAXPORT) 927d62bc4baSyz147064 die("too many ports specified"); 928d62bc4baSyz147064 929d62bc4baSyz147064 links[nlink++] = optarg; 930d62bc4baSyz147064 break; 931d62bc4baSyz147064 } 932d62bc4baSyz147064 /* FALLTHROUGH */ 933d62bc4baSyz147064 case 'L': 93433343a97Smeem if (l_arg) 93533343a97Smeem die_optdup(option); 9367c478bd9Sstevel@tonic-gate 9377c478bd9Sstevel@tonic-gate l_arg = B_TRUE; 938f595a68aSyz147064 if (!dladm_aggr_str2lacpmode(optarg, &lacp_mode)) 93933343a97Smeem die("invalid LACP mode '%s'", optarg); 9407c478bd9Sstevel@tonic-gate break; 9417c478bd9Sstevel@tonic-gate case 'T': 94233343a97Smeem if (T_arg) 94333343a97Smeem die_optdup(option); 9447c478bd9Sstevel@tonic-gate 9457c478bd9Sstevel@tonic-gate T_arg = B_TRUE; 946f595a68aSyz147064 if (!dladm_aggr_str2lacptimer(optarg, &lacp_timer)) 94733343a97Smeem die("invalid LACP timer value '%s'", optarg); 9487c478bd9Sstevel@tonic-gate break; 9497c478bd9Sstevel@tonic-gate case 't': 950d62bc4baSyz147064 flags &= ~DLADM_OPT_PERSIST; 951d62bc4baSyz147064 break; 952d62bc4baSyz147064 case 'f': 953d62bc4baSyz147064 flags |= DLADM_OPT_FORCE; 9547c478bd9Sstevel@tonic-gate break; 9557c478bd9Sstevel@tonic-gate case 'R': 9567c478bd9Sstevel@tonic-gate altroot = optarg; 9577c478bd9Sstevel@tonic-gate break; 9587c478bd9Sstevel@tonic-gate default: 9598d5c46e6Sam223141 die_opterr(optopt, option, use); 96033343a97Smeem break; 9617c478bd9Sstevel@tonic-gate } 9627c478bd9Sstevel@tonic-gate } 9637c478bd9Sstevel@tonic-gate 964d62bc4baSyz147064 if (ndev + nlink == 0) 9657c478bd9Sstevel@tonic-gate usage(); 9667c478bd9Sstevel@tonic-gate 967d62bc4baSyz147064 /* get key value or the aggregation name (required last argument) */ 9687c478bd9Sstevel@tonic-gate if (optind != (argc-1)) 9697c478bd9Sstevel@tonic-gate usage(); 9707c478bd9Sstevel@tonic-gate 971d62bc4baSyz147064 if (!str2int(argv[optind], &key)) { 972d62bc4baSyz147064 if (strlcpy(name, argv[optind], MAXLINKNAMELEN) >= 973d62bc4baSyz147064 MAXLINKNAMELEN) { 974d62bc4baSyz147064 die("link name too long '%s'", argv[optind]); 975d62bc4baSyz147064 } 9767c478bd9Sstevel@tonic-gate 977d62bc4baSyz147064 if (!dladm_valid_linkname(name)) 978d62bc4baSyz147064 die("invalid link name '%s'", argv[optind]); 979d62bc4baSyz147064 } else { 980d62bc4baSyz147064 (void) snprintf(name, MAXLINKNAMELEN, "aggr%d", key); 981d62bc4baSyz147064 } 982d62bc4baSyz147064 983d62bc4baSyz147064 if (altroot != NULL) 984d62bc4baSyz147064 altroot_cmd(altroot, argc, argv); 985d62bc4baSyz147064 986d62bc4baSyz147064 for (n = 0; n < ndev; n++) { 987d62bc4baSyz147064 if (dladm_dev2linkid(devs[n], &port[n].lp_linkid) != 988d62bc4baSyz147064 DLADM_STATUS_OK) { 989d62bc4baSyz147064 die("invalid dev name '%s'", devs[n]); 990d62bc4baSyz147064 } 991d62bc4baSyz147064 } 992d62bc4baSyz147064 993d62bc4baSyz147064 for (n = 0; n < nlink; n++) { 994d62bc4baSyz147064 if (dladm_name2info(links[n], &port[ndev + n].lp_linkid, 995d62bc4baSyz147064 NULL, NULL, NULL) != DLADM_STATUS_OK) { 996d62bc4baSyz147064 die("invalid link name '%s'", links[n]); 997d62bc4baSyz147064 } 998d62bc4baSyz147064 } 999d62bc4baSyz147064 1000d62bc4baSyz147064 status = dladm_aggr_create(name, key, ndev + nlink, port, policy, 1001d62bc4baSyz147064 mac_addr_fixed, (const uchar_t *)mac_addr, lacp_mode, 1002d62bc4baSyz147064 lacp_timer, flags); 1003d62bc4baSyz147064 done: 1004d62bc4baSyz147064 if (status != DLADM_STATUS_OK) { 1005d62bc4baSyz147064 if (status == DLADM_STATUS_NONOTIF) { 1006d62bc4baSyz147064 die_dlerr(status, "not all links have link up/down " 1007d62bc4baSyz147064 "detection; must use -f (see dladm(1M))\n"); 1008d62bc4baSyz147064 } else { 1009f595a68aSyz147064 die_dlerr(status, "create operation failed"); 10107c478bd9Sstevel@tonic-gate } 1011d62bc4baSyz147064 } 1012d62bc4baSyz147064 } 1013d62bc4baSyz147064 1014d62bc4baSyz147064 /* 1015d62bc4baSyz147064 * arg is either the key or the aggr name. Validate it and convert it to 1016d62bc4baSyz147064 * the linkid if altroot is NULL. 1017d62bc4baSyz147064 */ 1018d62bc4baSyz147064 static dladm_status_t 1019d62bc4baSyz147064 i_dladm_aggr_get_linkid(const char *altroot, const char *arg, 1020d62bc4baSyz147064 datalink_id_t *linkidp, uint32_t flags) 1021d62bc4baSyz147064 { 1022d62bc4baSyz147064 int key = 0; 1023d62bc4baSyz147064 char *aggr = NULL; 1024d62bc4baSyz147064 dladm_status_t status; 1025d62bc4baSyz147064 1026d62bc4baSyz147064 if (!str2int(arg, &key)) 1027d62bc4baSyz147064 aggr = (char *)arg; 1028d62bc4baSyz147064 1029d62bc4baSyz147064 if (aggr == NULL && key == 0) 1030d62bc4baSyz147064 return (DLADM_STATUS_LINKINVAL); 1031d62bc4baSyz147064 1032d62bc4baSyz147064 if (altroot != NULL) 1033d62bc4baSyz147064 return (DLADM_STATUS_OK); 1034d62bc4baSyz147064 1035d62bc4baSyz147064 if (aggr != NULL) { 1036d62bc4baSyz147064 status = dladm_name2info(aggr, linkidp, NULL, NULL, NULL); 1037d62bc4baSyz147064 } else { 1038d62bc4baSyz147064 status = dladm_key2linkid(key, linkidp, flags); 1039d62bc4baSyz147064 } 1040d62bc4baSyz147064 1041d62bc4baSyz147064 return (status); 1042d62bc4baSyz147064 } 10437c478bd9Sstevel@tonic-gate 10447c478bd9Sstevel@tonic-gate static void 10458d5c46e6Sam223141 do_delete_aggr(int argc, char *argv[], const char *use) 10467c478bd9Sstevel@tonic-gate { 10477c478bd9Sstevel@tonic-gate char option; 10487c478bd9Sstevel@tonic-gate char *altroot = NULL; 1049d62bc4baSyz147064 uint32_t flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST; 1050f595a68aSyz147064 dladm_status_t status; 1051d62bc4baSyz147064 datalink_id_t linkid; 10527c478bd9Sstevel@tonic-gate 10537c478bd9Sstevel@tonic-gate opterr = 0; 1054d62bc4baSyz147064 while ((option = getopt_long(argc, argv, ":R:t", lopts, NULL)) != -1) { 10557c478bd9Sstevel@tonic-gate switch (option) { 10567c478bd9Sstevel@tonic-gate case 't': 1057d62bc4baSyz147064 flags &= ~DLADM_OPT_PERSIST; 10587c478bd9Sstevel@tonic-gate break; 10597c478bd9Sstevel@tonic-gate case 'R': 10607c478bd9Sstevel@tonic-gate altroot = optarg; 10617c478bd9Sstevel@tonic-gate break; 10627c478bd9Sstevel@tonic-gate default: 10638d5c46e6Sam223141 die_opterr(optopt, option, use); 10647c478bd9Sstevel@tonic-gate break; 10657c478bd9Sstevel@tonic-gate } 10667c478bd9Sstevel@tonic-gate } 10677c478bd9Sstevel@tonic-gate 1068d62bc4baSyz147064 /* get key value or the aggregation name (required last argument) */ 10697c478bd9Sstevel@tonic-gate if (optind != (argc-1)) 10707c478bd9Sstevel@tonic-gate usage(); 10717c478bd9Sstevel@tonic-gate 1072d62bc4baSyz147064 status = i_dladm_aggr_get_linkid(altroot, argv[optind], &linkid, flags); 1073d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 1074d62bc4baSyz147064 goto done; 10757c478bd9Sstevel@tonic-gate 1076d62bc4baSyz147064 if (altroot != NULL) 1077d62bc4baSyz147064 altroot_cmd(altroot, argc, argv); 1078d62bc4baSyz147064 1079d62bc4baSyz147064 status = dladm_aggr_delete(linkid, flags); 1080d62bc4baSyz147064 done: 1081f595a68aSyz147064 if (status != DLADM_STATUS_OK) 1082f595a68aSyz147064 die_dlerr(status, "delete operation failed"); 10837c478bd9Sstevel@tonic-gate } 10847c478bd9Sstevel@tonic-gate 10857c478bd9Sstevel@tonic-gate static void 10868d5c46e6Sam223141 do_add_aggr(int argc, char *argv[], const char *use) 10877c478bd9Sstevel@tonic-gate { 10887c478bd9Sstevel@tonic-gate char option; 1089d62bc4baSyz147064 uint_t n, ndev, nlink; 10907c478bd9Sstevel@tonic-gate char *altroot = NULL; 1091d62bc4baSyz147064 uint32_t flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST; 1092d62bc4baSyz147064 datalink_id_t linkid; 1093f595a68aSyz147064 dladm_status_t status; 1094d62bc4baSyz147064 dladm_aggr_port_attr_db_t port[MAXPORT]; 1095d62bc4baSyz147064 char *devs[MAXPORT]; 1096d62bc4baSyz147064 char *links[MAXPORT]; 10977c478bd9Sstevel@tonic-gate 1098d62bc4baSyz147064 ndev = nlink = opterr = 0; 1099d62bc4baSyz147064 while ((option = getopt_long(argc, argv, ":d:l:R:tf", lopts, 11007c478bd9Sstevel@tonic-gate NULL)) != -1) { 11017c478bd9Sstevel@tonic-gate switch (option) { 11027c478bd9Sstevel@tonic-gate case 'd': 1103d62bc4baSyz147064 if (ndev + nlink >= MAXPORT) 1104d62bc4baSyz147064 die("too many ports specified"); 11057c478bd9Sstevel@tonic-gate 1106d62bc4baSyz147064 devs[ndev++] = optarg; 1107d62bc4baSyz147064 break; 1108d62bc4baSyz147064 case 'l': 1109d62bc4baSyz147064 if (ndev + nlink >= MAXPORT) 1110d62bc4baSyz147064 die("too many ports specified"); 111133343a97Smeem 1112d62bc4baSyz147064 links[nlink++] = optarg; 11137c478bd9Sstevel@tonic-gate break; 11147c478bd9Sstevel@tonic-gate case 't': 1115d62bc4baSyz147064 flags &= ~DLADM_OPT_PERSIST; 1116d62bc4baSyz147064 break; 1117d62bc4baSyz147064 case 'f': 1118d62bc4baSyz147064 flags |= DLADM_OPT_FORCE; 11197c478bd9Sstevel@tonic-gate break; 11207c478bd9Sstevel@tonic-gate case 'R': 11217c478bd9Sstevel@tonic-gate altroot = optarg; 11227c478bd9Sstevel@tonic-gate break; 11237c478bd9Sstevel@tonic-gate default: 11248d5c46e6Sam223141 die_opterr(optopt, option, use); 112533343a97Smeem break; 11267c478bd9Sstevel@tonic-gate } 11277c478bd9Sstevel@tonic-gate } 11287c478bd9Sstevel@tonic-gate 1129d62bc4baSyz147064 if (ndev + nlink == 0) 11307c478bd9Sstevel@tonic-gate usage(); 11317c478bd9Sstevel@tonic-gate 1132d62bc4baSyz147064 /* get key value or the aggregation name (required last argument) */ 11337c478bd9Sstevel@tonic-gate if (optind != (argc-1)) 11347c478bd9Sstevel@tonic-gate usage(); 11357c478bd9Sstevel@tonic-gate 1136d62bc4baSyz147064 if ((status = i_dladm_aggr_get_linkid(altroot, argv[optind], &linkid, 1137d62bc4baSyz147064 flags & (DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST))) != 1138d62bc4baSyz147064 DLADM_STATUS_OK) { 1139d62bc4baSyz147064 goto done; 1140d62bc4baSyz147064 } 11417c478bd9Sstevel@tonic-gate 1142d62bc4baSyz147064 if (altroot != NULL) 1143d62bc4baSyz147064 altroot_cmd(altroot, argc, argv); 1144d62bc4baSyz147064 1145d62bc4baSyz147064 for (n = 0; n < ndev; n++) { 1146d62bc4baSyz147064 if (dladm_dev2linkid(devs[n], &(port[n].lp_linkid)) != 1147d62bc4baSyz147064 DLADM_STATUS_OK) { 1148d62bc4baSyz147064 die("invalid <dev> '%s'", devs[n]); 1149d62bc4baSyz147064 } 1150d62bc4baSyz147064 } 1151d62bc4baSyz147064 1152d62bc4baSyz147064 for (n = 0; n < nlink; n++) { 1153d62bc4baSyz147064 if (dladm_name2info(links[n], &port[n + ndev].lp_linkid, 1154d62bc4baSyz147064 NULL, NULL, NULL) != DLADM_STATUS_OK) { 1155d62bc4baSyz147064 die("invalid <link> '%s'", links[n]); 1156d62bc4baSyz147064 } 1157d62bc4baSyz147064 } 1158d62bc4baSyz147064 1159d62bc4baSyz147064 status = dladm_aggr_add(linkid, ndev + nlink, port, flags); 1160d62bc4baSyz147064 done: 1161f595a68aSyz147064 if (status != DLADM_STATUS_OK) { 1162219a2a31Shl157128 /* 1163f595a68aSyz147064 * checking DLADM_STATUS_NOTSUP is a temporary workaround 1164219a2a31Shl157128 * and should be removed once 6399681 is fixed. 1165219a2a31Shl157128 */ 1166f595a68aSyz147064 if (status == DLADM_STATUS_NOTSUP) { 1167219a2a31Shl157128 (void) fprintf(stderr, 1168219a2a31Shl157128 gettext("%s: add operation failed: %s\n"), 1169219a2a31Shl157128 progname, 1170d62bc4baSyz147064 gettext("link capabilities don't match")); 1171219a2a31Shl157128 exit(ENOTSUP); 1172d62bc4baSyz147064 } else if (status == DLADM_STATUS_NONOTIF) { 1173d62bc4baSyz147064 die_dlerr(status, "not all links have link up/down " 1174d62bc4baSyz147064 "detection; must use -f (see dladm(1M))\n"); 1175d62bc4baSyz147064 } else { 1176f595a68aSyz147064 die_dlerr(status, "add operation failed"); 11777c478bd9Sstevel@tonic-gate } 11787c478bd9Sstevel@tonic-gate } 1179d62bc4baSyz147064 } 11807c478bd9Sstevel@tonic-gate 11817c478bd9Sstevel@tonic-gate static void 11828d5c46e6Sam223141 do_remove_aggr(int argc, char *argv[], const char *use) 11837c478bd9Sstevel@tonic-gate { 11847c478bd9Sstevel@tonic-gate char option; 1185f595a68aSyz147064 dladm_aggr_port_attr_db_t port[MAXPORT]; 1186d62bc4baSyz147064 uint_t n, ndev, nlink; 1187d62bc4baSyz147064 char *devs[MAXPORT]; 1188d62bc4baSyz147064 char *links[MAXPORT]; 11897c478bd9Sstevel@tonic-gate char *altroot = NULL; 1190d62bc4baSyz147064 uint32_t flags; 1191d62bc4baSyz147064 datalink_id_t linkid; 1192f595a68aSyz147064 dladm_status_t status; 11937c478bd9Sstevel@tonic-gate 1194d62bc4baSyz147064 flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST; 1195d62bc4baSyz147064 ndev = nlink = opterr = 0; 1196d62bc4baSyz147064 while ((option = getopt_long(argc, argv, ":d:l:R:t", 1197d62bc4baSyz147064 lopts, NULL)) != -1) { 11987c478bd9Sstevel@tonic-gate switch (option) { 11997c478bd9Sstevel@tonic-gate case 'd': 1200d62bc4baSyz147064 if (ndev + nlink >= MAXPORT) 1201d62bc4baSyz147064 die("too many ports specified"); 12027c478bd9Sstevel@tonic-gate 1203d62bc4baSyz147064 devs[ndev++] = optarg; 1204d62bc4baSyz147064 break; 1205d62bc4baSyz147064 case 'l': 1206d62bc4baSyz147064 if (ndev + nlink >= MAXPORT) 1207d62bc4baSyz147064 die("too many ports specified"); 120833343a97Smeem 1209d62bc4baSyz147064 links[nlink++] = optarg; 12107c478bd9Sstevel@tonic-gate break; 12117c478bd9Sstevel@tonic-gate case 't': 1212d62bc4baSyz147064 flags &= ~DLADM_OPT_PERSIST; 12137c478bd9Sstevel@tonic-gate break; 12147c478bd9Sstevel@tonic-gate case 'R': 12157c478bd9Sstevel@tonic-gate altroot = optarg; 12167c478bd9Sstevel@tonic-gate break; 12177c478bd9Sstevel@tonic-gate default: 12188d5c46e6Sam223141 die_opterr(optopt, option, use); 121933343a97Smeem break; 12207c478bd9Sstevel@tonic-gate } 12217c478bd9Sstevel@tonic-gate } 12227c478bd9Sstevel@tonic-gate 1223d62bc4baSyz147064 if (ndev + nlink == 0) 12247c478bd9Sstevel@tonic-gate usage(); 12257c478bd9Sstevel@tonic-gate 1226d62bc4baSyz147064 /* get key value or the aggregation name (required last argument) */ 12277c478bd9Sstevel@tonic-gate if (optind != (argc-1)) 12287c478bd9Sstevel@tonic-gate usage(); 12297c478bd9Sstevel@tonic-gate 1230d62bc4baSyz147064 status = i_dladm_aggr_get_linkid(altroot, argv[optind], &linkid, flags); 1231d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 1232d62bc4baSyz147064 goto done; 12337c478bd9Sstevel@tonic-gate 1234d62bc4baSyz147064 if (altroot != NULL) 1235d62bc4baSyz147064 altroot_cmd(altroot, argc, argv); 1236d62bc4baSyz147064 1237d62bc4baSyz147064 for (n = 0; n < ndev; n++) { 1238d62bc4baSyz147064 if (dladm_dev2linkid(devs[n], &(port[n].lp_linkid)) != 1239d62bc4baSyz147064 DLADM_STATUS_OK) { 1240d62bc4baSyz147064 die("invalid <dev> '%s'", devs[n]); 1241d62bc4baSyz147064 } 1242d62bc4baSyz147064 } 1243d62bc4baSyz147064 1244d62bc4baSyz147064 for (n = 0; n < nlink; n++) { 1245d62bc4baSyz147064 if (dladm_name2info(links[n], &port[n + ndev].lp_linkid, 1246d62bc4baSyz147064 NULL, NULL, NULL) != DLADM_STATUS_OK) { 1247d62bc4baSyz147064 die("invalid <link> '%s'", links[n]); 1248d62bc4baSyz147064 } 1249d62bc4baSyz147064 } 1250d62bc4baSyz147064 1251d62bc4baSyz147064 status = dladm_aggr_remove(linkid, ndev + nlink, port, flags); 1252d62bc4baSyz147064 done: 1253f595a68aSyz147064 if (status != DLADM_STATUS_OK) 1254f595a68aSyz147064 die_dlerr(status, "remove operation failed"); 12557c478bd9Sstevel@tonic-gate } 12567c478bd9Sstevel@tonic-gate 12577c478bd9Sstevel@tonic-gate static void 12588d5c46e6Sam223141 do_modify_aggr(int argc, char *argv[], const char *use) 12597c478bd9Sstevel@tonic-gate { 12607c478bd9Sstevel@tonic-gate char option; 12617c478bd9Sstevel@tonic-gate uint32_t policy = AGGR_POLICY_L4; 12627c478bd9Sstevel@tonic-gate aggr_lacp_mode_t lacp_mode = AGGR_LACP_OFF; 12637c478bd9Sstevel@tonic-gate aggr_lacp_timer_t lacp_timer = AGGR_LACP_TIMER_SHORT; 12647c478bd9Sstevel@tonic-gate uint8_t mac_addr[ETHERADDRL]; 12657c478bd9Sstevel@tonic-gate boolean_t mac_addr_fixed = B_FALSE; 12667c478bd9Sstevel@tonic-gate uint8_t modify_mask = 0; 12677c478bd9Sstevel@tonic-gate char *altroot = NULL; 1268d62bc4baSyz147064 uint32_t flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST; 1269d62bc4baSyz147064 datalink_id_t linkid; 1270f595a68aSyz147064 dladm_status_t status; 12717c478bd9Sstevel@tonic-gate 12727c478bd9Sstevel@tonic-gate opterr = 0; 1273d62bc4baSyz147064 while ((option = getopt_long(argc, argv, ":L:l:P:R:tu:T:", lopts, 12747c478bd9Sstevel@tonic-gate NULL)) != -1) { 12757c478bd9Sstevel@tonic-gate switch (option) { 12767c478bd9Sstevel@tonic-gate case 'P': 1277f595a68aSyz147064 if (modify_mask & DLADM_AGGR_MODIFY_POLICY) 127833343a97Smeem die_optdup(option); 12797c478bd9Sstevel@tonic-gate 1280f595a68aSyz147064 modify_mask |= DLADM_AGGR_MODIFY_POLICY; 12817c478bd9Sstevel@tonic-gate 1282f595a68aSyz147064 if (!dladm_aggr_str2policy(optarg, &policy)) 128333343a97Smeem die("invalid policy '%s'", optarg); 12847c478bd9Sstevel@tonic-gate break; 12857c478bd9Sstevel@tonic-gate case 'u': 1286f595a68aSyz147064 if (modify_mask & DLADM_AGGR_MODIFY_MAC) 128733343a97Smeem die_optdup(option); 12887c478bd9Sstevel@tonic-gate 1289f595a68aSyz147064 modify_mask |= DLADM_AGGR_MODIFY_MAC; 12907c478bd9Sstevel@tonic-gate 1291f595a68aSyz147064 if (!dladm_aggr_str2macaddr(optarg, &mac_addr_fixed, 129233343a97Smeem mac_addr)) 129333343a97Smeem die("invalid MAC address '%s'", optarg); 12947c478bd9Sstevel@tonic-gate break; 12957c478bd9Sstevel@tonic-gate case 'l': 1296d62bc4baSyz147064 case 'L': 1297f595a68aSyz147064 if (modify_mask & DLADM_AGGR_MODIFY_LACP_MODE) 129833343a97Smeem die_optdup(option); 12997c478bd9Sstevel@tonic-gate 1300f595a68aSyz147064 modify_mask |= DLADM_AGGR_MODIFY_LACP_MODE; 13017c478bd9Sstevel@tonic-gate 1302f595a68aSyz147064 if (!dladm_aggr_str2lacpmode(optarg, &lacp_mode)) 130333343a97Smeem die("invalid LACP mode '%s'", optarg); 13047c478bd9Sstevel@tonic-gate break; 13057c478bd9Sstevel@tonic-gate case 'T': 1306f595a68aSyz147064 if (modify_mask & DLADM_AGGR_MODIFY_LACP_TIMER) 130733343a97Smeem die_optdup(option); 13087c478bd9Sstevel@tonic-gate 1309f595a68aSyz147064 modify_mask |= DLADM_AGGR_MODIFY_LACP_TIMER; 13107c478bd9Sstevel@tonic-gate 1311f595a68aSyz147064 if (!dladm_aggr_str2lacptimer(optarg, &lacp_timer)) 131233343a97Smeem die("invalid LACP timer value '%s'", optarg); 13137c478bd9Sstevel@tonic-gate break; 13147c478bd9Sstevel@tonic-gate case 't': 1315d62bc4baSyz147064 flags &= ~DLADM_OPT_PERSIST; 13167c478bd9Sstevel@tonic-gate break; 13177c478bd9Sstevel@tonic-gate case 'R': 13187c478bd9Sstevel@tonic-gate altroot = optarg; 13197c478bd9Sstevel@tonic-gate break; 13207c478bd9Sstevel@tonic-gate default: 13218d5c46e6Sam223141 die_opterr(optopt, option, use); 132233343a97Smeem break; 13237c478bd9Sstevel@tonic-gate } 13247c478bd9Sstevel@tonic-gate } 13257c478bd9Sstevel@tonic-gate 132633343a97Smeem if (modify_mask == 0) 132733343a97Smeem die("at least one of the -PulT options must be specified"); 13287c478bd9Sstevel@tonic-gate 1329d62bc4baSyz147064 /* get key value or the aggregation name (required last argument) */ 13307c478bd9Sstevel@tonic-gate if (optind != (argc-1)) 13317c478bd9Sstevel@tonic-gate usage(); 13327c478bd9Sstevel@tonic-gate 1333d62bc4baSyz147064 status = i_dladm_aggr_get_linkid(altroot, argv[optind], &linkid, flags); 1334d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 1335d62bc4baSyz147064 goto done; 13367c478bd9Sstevel@tonic-gate 1337d62bc4baSyz147064 if (altroot != NULL) 1338d62bc4baSyz147064 altroot_cmd(altroot, argc, argv); 1339d62bc4baSyz147064 1340d62bc4baSyz147064 status = dladm_aggr_modify(linkid, modify_mask, policy, mac_addr_fixed, 1341d62bc4baSyz147064 (const uchar_t *)mac_addr, lacp_mode, lacp_timer, flags); 1342d62bc4baSyz147064 1343d62bc4baSyz147064 done: 1344f595a68aSyz147064 if (status != DLADM_STATUS_OK) 1345f595a68aSyz147064 die_dlerr(status, "modify operation failed"); 13467c478bd9Sstevel@tonic-gate } 13477c478bd9Sstevel@tonic-gate 13488d5c46e6Sam223141 /*ARGSUSED*/ 13497c478bd9Sstevel@tonic-gate static void 13508d5c46e6Sam223141 do_up_aggr(int argc, char *argv[], const char *use) 13517c478bd9Sstevel@tonic-gate { 1352d62bc4baSyz147064 datalink_id_t linkid = DATALINK_ALL_LINKID; 1353f595a68aSyz147064 dladm_status_t status; 13547c478bd9Sstevel@tonic-gate 1355d62bc4baSyz147064 /* 1356d62bc4baSyz147064 * get the key or the name of the aggregation (optional last argument) 1357d62bc4baSyz147064 */ 13587c478bd9Sstevel@tonic-gate if (argc == 2) { 1359d62bc4baSyz147064 if ((status = i_dladm_aggr_get_linkid(NULL, argv[1], &linkid, 1360d62bc4baSyz147064 DLADM_OPT_PERSIST)) != DLADM_STATUS_OK) { 1361d62bc4baSyz147064 goto done; 1362d62bc4baSyz147064 } 13637c478bd9Sstevel@tonic-gate } else if (argc > 2) { 13647c478bd9Sstevel@tonic-gate usage(); 13657c478bd9Sstevel@tonic-gate } 13667c478bd9Sstevel@tonic-gate 1367d62bc4baSyz147064 status = dladm_aggr_up(linkid); 1368d62bc4baSyz147064 done: 1369d62bc4baSyz147064 if (status != DLADM_STATUS_OK) { 1370d62bc4baSyz147064 if (argc == 2) { 1371d62bc4baSyz147064 die_dlerr(status, 1372d62bc4baSyz147064 "could not bring up aggregation '%s'", argv[1]); 13737c478bd9Sstevel@tonic-gate } else { 1374f595a68aSyz147064 die_dlerr(status, "could not bring aggregations up"); 13757c478bd9Sstevel@tonic-gate } 13767c478bd9Sstevel@tonic-gate } 13777c478bd9Sstevel@tonic-gate } 13787c478bd9Sstevel@tonic-gate 13797c478bd9Sstevel@tonic-gate static void 13808d5c46e6Sam223141 do_create_vlan(int argc, char *argv[], const char *use) 13817c478bd9Sstevel@tonic-gate { 1382d62bc4baSyz147064 char *link = NULL; 1383d62bc4baSyz147064 char drv[DLPI_LINKNAME_MAX]; 1384d62bc4baSyz147064 uint_t ppa; 1385d62bc4baSyz147064 datalink_id_t linkid; 1386d62bc4baSyz147064 int vid = 0; 1387d62bc4baSyz147064 char option; 1388d62bc4baSyz147064 uint32_t flags = (DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST); 1389d62bc4baSyz147064 char *altroot = NULL; 1390d62bc4baSyz147064 char vlan[MAXLINKNAMELEN]; 1391f595a68aSyz147064 dladm_status_t status; 13927c478bd9Sstevel@tonic-gate 1393d62bc4baSyz147064 opterr = 0; 1394d62bc4baSyz147064 while ((option = getopt_long(argc, argv, ":tfl:v:", 1395d62bc4baSyz147064 lopts, NULL)) != -1) { 1396d62bc4baSyz147064 switch (option) { 1397d62bc4baSyz147064 case 'v': 1398d62bc4baSyz147064 if (vid != 0) 1399d62bc4baSyz147064 die_optdup(option); 1400d62bc4baSyz147064 1401d62bc4baSyz147064 if (!str2int(optarg, &vid) || vid < 1 || vid > 4094) 1402d62bc4baSyz147064 die("invalid VLAN identifier '%s'", optarg); 1403d62bc4baSyz147064 1404d62bc4baSyz147064 break; 1405d62bc4baSyz147064 case 'l': 1406d62bc4baSyz147064 if (link != NULL) 1407d62bc4baSyz147064 die_optdup(option); 1408d62bc4baSyz147064 1409d62bc4baSyz147064 link = optarg; 1410d62bc4baSyz147064 break; 1411d62bc4baSyz147064 case 'f': 1412d62bc4baSyz147064 flags |= DLADM_OPT_FORCE; 1413d62bc4baSyz147064 break; 1414d62bc4baSyz147064 case 't': 1415d62bc4baSyz147064 flags &= ~DLADM_OPT_PERSIST; 1416d62bc4baSyz147064 break; 1417d62bc4baSyz147064 case 'R': 1418d62bc4baSyz147064 altroot = optarg; 1419d62bc4baSyz147064 break; 1420d62bc4baSyz147064 default: 14218d5c46e6Sam223141 die_opterr(optopt, option, use); 1422d62bc4baSyz147064 break; 1423d62bc4baSyz147064 } 1424d62bc4baSyz147064 } 1425d62bc4baSyz147064 1426d62bc4baSyz147064 /* get vlan name if there is any */ 1427d62bc4baSyz147064 if ((vid == 0) || (link == NULL) || (argc - optind > 1)) 14287c478bd9Sstevel@tonic-gate usage(); 1429d62bc4baSyz147064 1430d62bc4baSyz147064 if (optind == (argc - 1)) { 1431d62bc4baSyz147064 if (strlcpy(vlan, argv[optind], MAXLINKNAMELEN) >= 1432d62bc4baSyz147064 MAXLINKNAMELEN) { 1433d62bc4baSyz147064 die("vlan name too long '%s'", argv[optind]); 1434d62bc4baSyz147064 } 1435d62bc4baSyz147064 } else { 1436d62bc4baSyz147064 if ((dlpi_parselink(link, drv, &ppa) != DLPI_SUCCESS) || 1437d62bc4baSyz147064 (ppa >= 1000) || 1438d62bc4baSyz147064 (dlpi_makelink(vlan, drv, vid * 1000 + ppa) != 1439d62bc4baSyz147064 DLPI_SUCCESS)) { 1440d62bc4baSyz147064 die("invalid link name '%s'", link); 1441d62bc4baSyz147064 } 14427c478bd9Sstevel@tonic-gate } 14437c478bd9Sstevel@tonic-gate 1444d62bc4baSyz147064 if (altroot != NULL) 1445d62bc4baSyz147064 altroot_cmd(altroot, argc, argv); 1446d62bc4baSyz147064 1447d62bc4baSyz147064 if (dladm_name2info(link, &linkid, NULL, NULL, NULL) != 1448d62bc4baSyz147064 DLADM_STATUS_OK) { 1449d62bc4baSyz147064 die("invalid link name '%s'", link); 1450d62bc4baSyz147064 } 1451d62bc4baSyz147064 1452d62bc4baSyz147064 if ((status = dladm_vlan_create(vlan, linkid, vid, flags)) != 1453d62bc4baSyz147064 DLADM_STATUS_OK) { 1454d62bc4baSyz147064 if (status == DLADM_STATUS_NOTSUP) { 14556b9e797cSsowmini die_dlerr(status, "VLAN over '%s' may require lowered " 14566b9e797cSsowmini "MTU; must use -f (see dladm(1M))\n", link); 1457d62bc4baSyz147064 } else { 1458d62bc4baSyz147064 die_dlerr(status, "create operation failed"); 1459d62bc4baSyz147064 } 1460d62bc4baSyz147064 } 1461d62bc4baSyz147064 } 1462d62bc4baSyz147064 1463d62bc4baSyz147064 static void 14648d5c46e6Sam223141 do_delete_vlan(int argc, char *argv[], const char *use) 1465d62bc4baSyz147064 { 1466d62bc4baSyz147064 char option; 1467d62bc4baSyz147064 uint32_t flags = (DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST); 1468d62bc4baSyz147064 char *altroot = NULL; 1469d62bc4baSyz147064 datalink_id_t linkid; 1470d62bc4baSyz147064 dladm_status_t status; 1471d62bc4baSyz147064 1472d62bc4baSyz147064 opterr = 0; 1473d62bc4baSyz147064 while ((option = getopt_long(argc, argv, ":R:t", lopts, NULL)) != -1) { 1474d62bc4baSyz147064 switch (option) { 1475d62bc4baSyz147064 case 't': 1476d62bc4baSyz147064 flags &= ~DLADM_OPT_PERSIST; 1477d62bc4baSyz147064 break; 1478d62bc4baSyz147064 case 'R': 1479d62bc4baSyz147064 altroot = optarg; 1480d62bc4baSyz147064 break; 1481d62bc4baSyz147064 default: 14828d5c46e6Sam223141 die_opterr(optopt, option, use); 1483d62bc4baSyz147064 break; 1484d62bc4baSyz147064 } 1485d62bc4baSyz147064 } 1486d62bc4baSyz147064 1487d62bc4baSyz147064 /* get VLAN link name (required last argument) */ 1488d62bc4baSyz147064 if (optind != (argc - 1)) 1489d62bc4baSyz147064 usage(); 1490d62bc4baSyz147064 1491d62bc4baSyz147064 if (altroot != NULL) 1492d62bc4baSyz147064 altroot_cmd(altroot, argc, argv); 1493d62bc4baSyz147064 1494d62bc4baSyz147064 status = dladm_name2info(argv[optind], &linkid, NULL, NULL, NULL); 1495d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 1496d62bc4baSyz147064 goto done; 1497d62bc4baSyz147064 1498d62bc4baSyz147064 status = dladm_vlan_delete(linkid, flags); 1499d62bc4baSyz147064 done: 1500d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 1501d62bc4baSyz147064 die_dlerr(status, "delete operation failed"); 1502d62bc4baSyz147064 } 1503d62bc4baSyz147064 15048d5c46e6Sam223141 /*ARGSUSED*/ 1505d62bc4baSyz147064 static void 15068d5c46e6Sam223141 do_up_vlan(int argc, char *argv[], const char *use) 1507d62bc4baSyz147064 { 1508d62bc4baSyz147064 datalink_id_t linkid = DATALINK_ALL_LINKID; 1509d62bc4baSyz147064 dladm_status_t status; 1510d62bc4baSyz147064 1511d62bc4baSyz147064 /* 1512d62bc4baSyz147064 * get the name of the VLAN (optional last argument) 1513d62bc4baSyz147064 */ 1514d62bc4baSyz147064 if (argc > 2) 1515d62bc4baSyz147064 usage(); 1516d62bc4baSyz147064 1517d62bc4baSyz147064 if (argc == 2) { 1518d62bc4baSyz147064 status = dladm_name2info(argv[1], &linkid, NULL, NULL, NULL); 1519d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 1520d62bc4baSyz147064 goto done; 1521d62bc4baSyz147064 } 1522d62bc4baSyz147064 1523d62bc4baSyz147064 status = dladm_vlan_up(linkid); 1524d62bc4baSyz147064 done: 1525d62bc4baSyz147064 if (status != DLADM_STATUS_OK) { 1526d62bc4baSyz147064 if (argc == 2) { 1527f595a68aSyz147064 die_dlerr(status, 1528d62bc4baSyz147064 "could not bring up VLAN '%s'", argv[1]); 15297c478bd9Sstevel@tonic-gate } else { 1530d62bc4baSyz147064 die_dlerr(status, "could not bring VLANs up"); 15317c478bd9Sstevel@tonic-gate } 15327c478bd9Sstevel@tonic-gate } 15337c478bd9Sstevel@tonic-gate } 15347c478bd9Sstevel@tonic-gate 1535210db224Sericheng static void 15368d5c46e6Sam223141 do_rename_link(int argc, char *argv[], const char *use) 1537210db224Sericheng { 1538d62bc4baSyz147064 char option; 1539d62bc4baSyz147064 char *link1, *link2; 1540d62bc4baSyz147064 char *altroot = NULL; 1541d62bc4baSyz147064 dladm_status_t status; 1542210db224Sericheng 1543d62bc4baSyz147064 opterr = 0; 1544d62bc4baSyz147064 while ((option = getopt_long(argc, argv, ":R:", lopts, NULL)) != -1) { 1545d62bc4baSyz147064 switch (option) { 1546d62bc4baSyz147064 case 'R': 1547d62bc4baSyz147064 altroot = optarg; 1548d62bc4baSyz147064 break; 1549d62bc4baSyz147064 default: 15508d5c46e6Sam223141 die_opterr(optopt, option, use); 1551d62bc4baSyz147064 break; 1552210db224Sericheng } 1553210db224Sericheng } 1554210db224Sericheng 1555d62bc4baSyz147064 /* get link1 and link2 name (required the last 2 arguments) */ 1556d62bc4baSyz147064 if (optind != (argc - 2)) 1557d62bc4baSyz147064 usage(); 1558d62bc4baSyz147064 1559d62bc4baSyz147064 if (altroot != NULL) 1560d62bc4baSyz147064 altroot_cmd(altroot, argc, argv); 1561d62bc4baSyz147064 1562d62bc4baSyz147064 link1 = argv[optind++]; 1563d62bc4baSyz147064 link2 = argv[optind]; 1564d62bc4baSyz147064 if ((status = dladm_rename_link(link1, link2)) != DLADM_STATUS_OK) 1565d62bc4baSyz147064 die_dlerr(status, "rename operation failed"); 1566d62bc4baSyz147064 } 1567d62bc4baSyz147064 15688d5c46e6Sam223141 /*ARGSUSED*/ 1569d62bc4baSyz147064 static void 15708d5c46e6Sam223141 do_delete_phys(int argc, char *argv[], const char *use) 1571d62bc4baSyz147064 { 1572d62bc4baSyz147064 datalink_id_t linkid = DATALINK_ALL_LINKID; 1573d62bc4baSyz147064 dladm_status_t status; 1574d62bc4baSyz147064 1575d62bc4baSyz147064 /* get link name (required the last argument) */ 1576d62bc4baSyz147064 if (argc > 2) 1577d62bc4baSyz147064 usage(); 1578d62bc4baSyz147064 1579d62bc4baSyz147064 if (argc == 2) { 1580d62bc4baSyz147064 status = dladm_name2info(argv[1], &linkid, NULL, NULL, NULL); 1581d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 1582d62bc4baSyz147064 die_dlerr(status, "cannot delete '%s'", argv[1]); 1583d62bc4baSyz147064 } 1584d62bc4baSyz147064 1585d62bc4baSyz147064 if ((status = dladm_phys_delete(linkid)) != DLADM_STATUS_OK) { 1586d62bc4baSyz147064 if (argc == 2) 1587d62bc4baSyz147064 die_dlerr(status, "cannot delete '%s'", argv[1]); 1588d62bc4baSyz147064 else 1589d62bc4baSyz147064 die_dlerr(status, "delete operation failed"); 1590d62bc4baSyz147064 } 1591d62bc4baSyz147064 } 1592d62bc4baSyz147064 1593d62bc4baSyz147064 /*ARGSUSED*/ 1594210db224Sericheng static int 1595d62bc4baSyz147064 i_dladm_walk_linkmap(datalink_id_t linkid, void *arg) 1596210db224Sericheng { 1597d62bc4baSyz147064 char name[MAXLINKNAMELEN]; 1598d62bc4baSyz147064 char mediabuf[DLADM_STRSIZE]; 1599d62bc4baSyz147064 char classbuf[DLADM_STRSIZE]; 1600d62bc4baSyz147064 datalink_class_t class; 1601d62bc4baSyz147064 uint32_t media; 1602d62bc4baSyz147064 uint32_t flags; 1603210db224Sericheng 1604d62bc4baSyz147064 if (dladm_datalink_id2info(linkid, &flags, &class, &media, name, 1605d62bc4baSyz147064 MAXLINKNAMELEN) == DLADM_STATUS_OK) { 1606d62bc4baSyz147064 (void) dladm_class2str(class, classbuf); 1607d62bc4baSyz147064 (void) dladm_media2str(media, mediabuf); 1608d62bc4baSyz147064 (void) printf("%-12s%8d %-12s%-20s %6d\n", name, 1609d62bc4baSyz147064 linkid, classbuf, mediabuf, flags); 1610210db224Sericheng } 1611d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 1612210db224Sericheng } 16137c478bd9Sstevel@tonic-gate 16147c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 16157c478bd9Sstevel@tonic-gate static void 16168d5c46e6Sam223141 do_show_linkmap(int argc, char *argv[], const char *use) 16177c478bd9Sstevel@tonic-gate { 1618d62bc4baSyz147064 if (argc != 1) 1619d62bc4baSyz147064 die("invalid arguments"); 16207c478bd9Sstevel@tonic-gate 1621d62bc4baSyz147064 (void) printf("%-12s%8s %-12s%-20s %6s\n", "NAME", "LINKID", 1622d62bc4baSyz147064 "CLASS", "MEDIA", "FLAGS"); 1623d62bc4baSyz147064 (void) dladm_walk_datalink_id(i_dladm_walk_linkmap, NULL, 1624d62bc4baSyz147064 DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE, 1625d62bc4baSyz147064 DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST); 16267c478bd9Sstevel@tonic-gate } 1627d62bc4baSyz147064 1628d62bc4baSyz147064 /* 1629d62bc4baSyz147064 * Delete inactive physical links. 1630d62bc4baSyz147064 */ 1631d62bc4baSyz147064 /*ARGSUSED*/ 1632d62bc4baSyz147064 static int 1633d62bc4baSyz147064 purge_phys(datalink_id_t linkid, void *arg) 1634d62bc4baSyz147064 { 1635d62bc4baSyz147064 datalink_class_t class; 1636d62bc4baSyz147064 uint32_t flags; 1637d62bc4baSyz147064 1638d62bc4baSyz147064 if (dladm_datalink_id2info(linkid, &flags, &class, NULL, 1639d62bc4baSyz147064 NULL, 0) != DLADM_STATUS_OK) { 1640d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 1641d62bc4baSyz147064 } 1642d62bc4baSyz147064 1643d62bc4baSyz147064 if (class == DATALINK_CLASS_PHYS && !(flags & DLADM_OPT_ACTIVE)) 1644d62bc4baSyz147064 (void) dladm_phys_delete(linkid); 1645d62bc4baSyz147064 1646d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 1647d62bc4baSyz147064 } 1648d62bc4baSyz147064 1649d62bc4baSyz147064 /*ARGSUSED*/ 1650d62bc4baSyz147064 static void 16518d5c46e6Sam223141 do_init_phys(int argc, char *argv[], const char *use) 1652d62bc4baSyz147064 { 1653d62bc4baSyz147064 di_node_t devtree; 1654d62bc4baSyz147064 1655d62bc4baSyz147064 if (argc > 1) 1656d62bc4baSyz147064 usage(); 1657d62bc4baSyz147064 1658d62bc4baSyz147064 /* 1659d62bc4baSyz147064 * Force all the devices to attach, therefore all the network physical 1660d62bc4baSyz147064 * devices can be known to the dlmgmtd daemon. 1661d62bc4baSyz147064 */ 1662d62bc4baSyz147064 if ((devtree = di_init("/", DINFOFORCE | DINFOSUBTREE)) != DI_NODE_NIL) 1663d62bc4baSyz147064 di_fini(devtree); 1664d62bc4baSyz147064 1665d62bc4baSyz147064 (void) dladm_walk_datalink_id(purge_phys, NULL, 1666d62bc4baSyz147064 DATALINK_CLASS_PHYS, DATALINK_ANY_MEDIATYPE, DLADM_OPT_PERSIST); 16677c478bd9Sstevel@tonic-gate } 16687c478bd9Sstevel@tonic-gate 1669d62bc4baSyz147064 1670d62bc4baSyz147064 /* 1671d62bc4baSyz147064 * Print the active topology information. 1672d62bc4baSyz147064 */ 1673d62bc4baSyz147064 static dladm_status_t 1674d62bc4baSyz147064 print_link_topology(show_state_t *state, datalink_id_t linkid, 1675e7801d59Ssowmini datalink_class_t class, link_fields_buf_t *lbuf) 1676d62bc4baSyz147064 { 1677d62bc4baSyz147064 uint32_t flags = state->ls_flags; 1678d62bc4baSyz147064 dladm_status_t status = DLADM_STATUS_OK; 16796b9e797cSsowmini char tmpbuf[MAXLINKNAMELEN]; 1680d62bc4baSyz147064 1681e7801d59Ssowmini if (!state->ls_parseable) 1682e7801d59Ssowmini (void) sprintf(lbuf->link_over, STR_UNDEF_VAL); 1683d62bc4baSyz147064 else 1684e7801d59Ssowmini (void) sprintf(lbuf->link_over, ""); 1685d62bc4baSyz147064 1686d62bc4baSyz147064 if (class == DATALINK_CLASS_VLAN) { 1687d62bc4baSyz147064 dladm_vlan_attr_t vinfo; 1688d62bc4baSyz147064 1689d62bc4baSyz147064 status = dladm_vlan_info(linkid, &vinfo, flags); 1690d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 1691d62bc4baSyz147064 goto done; 1692d62bc4baSyz147064 status = dladm_datalink_id2info(vinfo.dv_linkid, NULL, NULL, 1693e7801d59Ssowmini NULL, lbuf->link_over, sizeof (lbuf->link_over)); 1694d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 1695d62bc4baSyz147064 goto done; 1696d62bc4baSyz147064 } else if (class == DATALINK_CLASS_AGGR) { 1697d62bc4baSyz147064 dladm_aggr_grp_attr_t ginfo; 1698d62bc4baSyz147064 int i; 1699d62bc4baSyz147064 17006b9e797cSsowmini (void) sprintf(lbuf->link_over, ""); 17016b9e797cSsowmini 1702d62bc4baSyz147064 status = dladm_aggr_info(linkid, &ginfo, flags); 1703d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 1704d62bc4baSyz147064 goto done; 1705d62bc4baSyz147064 1706d62bc4baSyz147064 if (ginfo.lg_nports == 0) { 1707d62bc4baSyz147064 status = DLADM_STATUS_BADVAL; 1708d62bc4baSyz147064 goto done; 1709d62bc4baSyz147064 } 1710d62bc4baSyz147064 for (i = 0; i < ginfo.lg_nports; i++) { 1711d62bc4baSyz147064 status = dladm_datalink_id2info( 1712e7801d59Ssowmini ginfo.lg_ports[i].lp_linkid, NULL, NULL, NULL, 17136b9e797cSsowmini tmpbuf, sizeof (tmpbuf)); 1714d62bc4baSyz147064 if (status != DLADM_STATUS_OK) { 1715d62bc4baSyz147064 free(ginfo.lg_ports); 1716d62bc4baSyz147064 goto done; 1717d62bc4baSyz147064 } 17186b9e797cSsowmini (void) strlcat(lbuf->link_over, tmpbuf, 17196b9e797cSsowmini sizeof (lbuf->link_over)); 17206b9e797cSsowmini if (i != (ginfo.lg_nports - 1)) { 17216b9e797cSsowmini (void) strlcat(lbuf->link_over, " ", 17226b9e797cSsowmini sizeof (lbuf->link_over)); 17236b9e797cSsowmini } 1724d62bc4baSyz147064 } 1725d62bc4baSyz147064 free(ginfo.lg_ports); 1726d62bc4baSyz147064 } else if (class == DATALINK_CLASS_VNIC) { 1727d62bc4baSyz147064 dladm_vnic_attr_sys_t vinfo; 1728d62bc4baSyz147064 1729d62bc4baSyz147064 if ((status = dladm_vnic_info(linkid, &vinfo, flags)) != 1730d62bc4baSyz147064 DLADM_STATUS_OK || (status = dladm_datalink_id2info( 1731e7801d59Ssowmini vinfo.va_link_id, NULL, NULL, NULL, lbuf->link_over, 1732e7801d59Ssowmini sizeof (lbuf->link_over)) != DLADM_STATUS_OK)) { 1733d62bc4baSyz147064 goto done; 1734d62bc4baSyz147064 } 1735d62bc4baSyz147064 } 1736d62bc4baSyz147064 done: 1737d62bc4baSyz147064 return (status); 1738d62bc4baSyz147064 } 1739d62bc4baSyz147064 1740d62bc4baSyz147064 static dladm_status_t 1741e7801d59Ssowmini print_link(show_state_t *state, datalink_id_t linkid, link_fields_buf_t *lbuf) 1742d62bc4baSyz147064 { 1743d62bc4baSyz147064 char link[MAXLINKNAMELEN]; 1744d62bc4baSyz147064 datalink_class_t class; 1745d62bc4baSyz147064 uint_t mtu; 1746d62bc4baSyz147064 uint32_t flags; 1747d62bc4baSyz147064 dladm_status_t status; 1748d62bc4baSyz147064 1749d62bc4baSyz147064 if ((status = dladm_datalink_id2info(linkid, &flags, &class, NULL, 1750d62bc4baSyz147064 link, sizeof (link))) != DLADM_STATUS_OK) { 1751d62bc4baSyz147064 goto done; 1752d62bc4baSyz147064 } 1753d62bc4baSyz147064 1754d62bc4baSyz147064 if (!(state->ls_flags & flags)) { 1755d62bc4baSyz147064 status = DLADM_STATUS_NOTFOUND; 1756d62bc4baSyz147064 goto done; 1757d62bc4baSyz147064 } 1758d62bc4baSyz147064 1759d62bc4baSyz147064 if (state->ls_flags == DLADM_OPT_ACTIVE) { 1760d62bc4baSyz147064 dladm_attr_t dlattr; 1761d62bc4baSyz147064 1762d62bc4baSyz147064 if (class == DATALINK_CLASS_PHYS) { 1763d62bc4baSyz147064 dladm_phys_attr_t dpa; 1764d62bc4baSyz147064 dlpi_handle_t dh; 1765d62bc4baSyz147064 dlpi_info_t dlinfo; 1766d62bc4baSyz147064 1767d62bc4baSyz147064 if ((status = dladm_phys_info(linkid, &dpa, 1768d62bc4baSyz147064 DLADM_OPT_ACTIVE)) != DLADM_STATUS_OK) { 1769d62bc4baSyz147064 goto done; 1770d62bc4baSyz147064 } 1771d62bc4baSyz147064 1772d62bc4baSyz147064 if (!dpa.dp_novanity) 1773d62bc4baSyz147064 goto link_mtu; 1774d62bc4baSyz147064 1775d62bc4baSyz147064 /* 1776d62bc4baSyz147064 * This is a physical link that does not have 1777d62bc4baSyz147064 * vanity naming support. 1778d62bc4baSyz147064 */ 1779d62bc4baSyz147064 if (dlpi_open(dpa.dp_dev, &dh, DLPI_DEVONLY) != 1780d62bc4baSyz147064 DLPI_SUCCESS) { 1781d62bc4baSyz147064 status = DLADM_STATUS_NOTFOUND; 1782d62bc4baSyz147064 goto done; 1783d62bc4baSyz147064 } 1784d62bc4baSyz147064 1785d62bc4baSyz147064 if (dlpi_info(dh, &dlinfo, 0) != DLPI_SUCCESS) { 1786d62bc4baSyz147064 dlpi_close(dh); 1787d62bc4baSyz147064 status = DLADM_STATUS_BADARG; 1788d62bc4baSyz147064 goto done; 1789d62bc4baSyz147064 } 1790d62bc4baSyz147064 1791d62bc4baSyz147064 dlpi_close(dh); 1792d62bc4baSyz147064 mtu = dlinfo.di_max_sdu; 1793d62bc4baSyz147064 } else { 1794d62bc4baSyz147064 link_mtu: 1795d62bc4baSyz147064 status = dladm_info(linkid, &dlattr); 1796d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 1797d62bc4baSyz147064 goto done; 1798d62bc4baSyz147064 mtu = dlattr.da_max_sdu; 1799d62bc4baSyz147064 } 1800d62bc4baSyz147064 } 1801d62bc4baSyz147064 1802e7801d59Ssowmini (void) snprintf(lbuf->link_name, sizeof (lbuf->link_name), 1803e7801d59Ssowmini "%s", link); 1804e7801d59Ssowmini (void) dladm_class2str(class, lbuf->link_class); 1805d62bc4baSyz147064 if (state->ls_flags == DLADM_OPT_ACTIVE) { 1806e7801d59Ssowmini (void) snprintf(lbuf->link_mtu, sizeof (lbuf->link_mtu), 1807c08e5e1aSdr146992 "%u", mtu); 1808e7801d59Ssowmini (void) get_linkstate(link, B_TRUE, lbuf->link_state); 1809d62bc4baSyz147064 } 1810d62bc4baSyz147064 1811e7801d59Ssowmini status = print_link_topology(state, linkid, class, lbuf); 1812d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 1813d62bc4baSyz147064 goto done; 1814d62bc4baSyz147064 1815d62bc4baSyz147064 done: 1816d62bc4baSyz147064 return (status); 1817d62bc4baSyz147064 } 1818d62bc4baSyz147064 1819e7801d59Ssowmini 1820d62bc4baSyz147064 static int 1821d62bc4baSyz147064 show_link(datalink_id_t linkid, void *arg) 1822d62bc4baSyz147064 { 1823e7801d59Ssowmini show_state_t *state = (show_state_t *)arg; 1824d62bc4baSyz147064 dladm_status_t status; 1825e7801d59Ssowmini link_fields_buf_t lbuf; 1826d62bc4baSyz147064 1827e7801d59Ssowmini /* 1828e7801d59Ssowmini * first get all the link attributes into lbuf; 1829e7801d59Ssowmini */ 18305f5c9f54SAnurag S. Maskey bzero(&lbuf, sizeof (link_fields_buf_t)); 1831e7801d59Ssowmini status = print_link(state, linkid, &lbuf); 1832e7801d59Ssowmini 1833d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 1834d62bc4baSyz147064 goto done; 1835e7801d59Ssowmini 1836e7801d59Ssowmini if (!state->ls_parseable && !state->ls_printheader) { 1837e7801d59Ssowmini print_header(&state->ls_print); 1838e7801d59Ssowmini state->ls_printheader = B_TRUE; 1839e7801d59Ssowmini } 1840e7801d59Ssowmini 1841e7801d59Ssowmini dladm_print_output(&state->ls_print, state->ls_parseable, 1842e7801d59Ssowmini dladm_print_field, (void *)&lbuf); 1843d62bc4baSyz147064 1844d62bc4baSyz147064 done: 1845d62bc4baSyz147064 state->ls_status = status; 1846d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 1847d62bc4baSyz147064 } 1848d62bc4baSyz147064 1849d62bc4baSyz147064 static int 1850d62bc4baSyz147064 show_link_stats(datalink_id_t linkid, void *arg) 1851d62bc4baSyz147064 { 1852e7801d59Ssowmini char link[DLPI_LINKNAME_MAX]; 1853d62bc4baSyz147064 datalink_class_t class; 1854e7801d59Ssowmini show_state_t *state = (show_state_t *)arg; 18557c478bd9Sstevel@tonic-gate pktsum_t stats, diff_stats; 1856d62bc4baSyz147064 dladm_phys_attr_t dpa; 18576be03d0bSVasumathi Sundaram - Sun Microsystems dev_args_t largs; 18587c478bd9Sstevel@tonic-gate 18597c478bd9Sstevel@tonic-gate if (state->ls_firstonly) { 18607c478bd9Sstevel@tonic-gate if (state->ls_donefirst) 1861d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 18627c478bd9Sstevel@tonic-gate state->ls_donefirst = B_TRUE; 18637c478bd9Sstevel@tonic-gate } else { 18647c478bd9Sstevel@tonic-gate bzero(&state->ls_prevstats, sizeof (state->ls_prevstats)); 18657c478bd9Sstevel@tonic-gate } 18667c478bd9Sstevel@tonic-gate 1867d62bc4baSyz147064 if (dladm_datalink_id2info(linkid, NULL, &class, NULL, link, 1868e7801d59Ssowmini DLPI_LINKNAME_MAX) != DLADM_STATUS_OK) { 1869d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 1870d62bc4baSyz147064 } 1871d62bc4baSyz147064 1872d62bc4baSyz147064 if (class == DATALINK_CLASS_PHYS) { 1873d62bc4baSyz147064 if (dladm_phys_info(linkid, &dpa, DLADM_OPT_ACTIVE) != 1874d62bc4baSyz147064 DLADM_STATUS_OK) { 1875d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 1876d62bc4baSyz147064 } 1877d62bc4baSyz147064 if (dpa.dp_novanity) 1878d62bc4baSyz147064 get_mac_stats(dpa.dp_dev, &stats); 1879d62bc4baSyz147064 else 1880d62bc4baSyz147064 get_link_stats(link, &stats); 1881d62bc4baSyz147064 } else { 1882d62bc4baSyz147064 get_link_stats(link, &stats); 1883d62bc4baSyz147064 } 18847c478bd9Sstevel@tonic-gate stats_diff(&diff_stats, &stats, &state->ls_prevstats); 18857c478bd9Sstevel@tonic-gate 18866be03d0bSVasumathi Sundaram - Sun Microsystems largs.devs_link = link; 18876be03d0bSVasumathi Sundaram - Sun Microsystems largs.devs_psum = &diff_stats; 18886be03d0bSVasumathi Sundaram - Sun Microsystems dladm_print_output(&state->ls_print, state->ls_parseable, 18896be03d0bSVasumathi Sundaram - Sun Microsystems print_dev_stats, &largs); 18907c478bd9Sstevel@tonic-gate 18917c478bd9Sstevel@tonic-gate state->ls_prevstats = stats; 1892d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 18937c478bd9Sstevel@tonic-gate } 18947c478bd9Sstevel@tonic-gate 1895d62bc4baSyz147064 1896d62bc4baSyz147064 static dladm_status_t 1897d62bc4baSyz147064 print_aggr_info(show_grp_state_t *state, const char *link, 1898e7801d59Ssowmini dladm_aggr_grp_attr_t *ginfop) 1899d62bc4baSyz147064 { 1900d62bc4baSyz147064 char addr_str[ETHERADDRL * 3]; 1901e7801d59Ssowmini laggr_fields_buf_t lbuf; 1902d62bc4baSyz147064 1903e7801d59Ssowmini (void) snprintf(lbuf.laggr_name, sizeof (lbuf.laggr_name), 1904e7801d59Ssowmini "%s", link); 1905e7801d59Ssowmini 1906e7801d59Ssowmini (void) dladm_aggr_policy2str(ginfop->lg_policy, 1907e7801d59Ssowmini lbuf.laggr_policy); 1908d62bc4baSyz147064 1909d62bc4baSyz147064 if (ginfop->lg_mac_fixed) { 1910d62bc4baSyz147064 (void) dladm_aggr_macaddr2str(ginfop->lg_mac, addr_str); 1911e7801d59Ssowmini (void) snprintf(lbuf.laggr_addrpolicy, 1912e7801d59Ssowmini sizeof (lbuf.laggr_addrpolicy), "fixed (%s)", addr_str); 1913d62bc4baSyz147064 } else { 1914e7801d59Ssowmini (void) snprintf(lbuf.laggr_addrpolicy, 1915e7801d59Ssowmini sizeof (lbuf.laggr_addrpolicy), "auto"); 1916d62bc4baSyz147064 } 1917d62bc4baSyz147064 1918d62bc4baSyz147064 1919e7801d59Ssowmini (void) dladm_aggr_lacpmode2str(ginfop->lg_lacp_mode, 1920e7801d59Ssowmini lbuf.laggr_lacpactivity); 1921e7801d59Ssowmini (void) dladm_aggr_lacptimer2str(ginfop->lg_lacp_timer, 1922e7801d59Ssowmini lbuf.laggr_lacptimer); 1923e7801d59Ssowmini (void) snprintf(lbuf.laggr_flags, sizeof (lbuf.laggr_flags), "%c----", 1924d62bc4baSyz147064 ginfop->lg_force ? 'f' : '-'); 1925e7801d59Ssowmini 1926e7801d59Ssowmini if (!state->gs_parseable && !state->gs_printheader) { 1927e7801d59Ssowmini print_header(&state->gs_print); 1928e7801d59Ssowmini state->gs_printheader = B_TRUE; 1929d62bc4baSyz147064 } 1930d62bc4baSyz147064 1931e7801d59Ssowmini dladm_print_output(&state->gs_print, state->gs_parseable, 1932e7801d59Ssowmini dladm_print_field, (void *)&lbuf); 1933e7801d59Ssowmini 1934d62bc4baSyz147064 return (DLADM_STATUS_OK); 1935d62bc4baSyz147064 } 1936d62bc4baSyz147064 1937e7801d59Ssowmini static char * 1938e7801d59Ssowmini print_xaggr_callback(print_field_t *pf, void *arg) 1939d62bc4baSyz147064 { 1940e7801d59Ssowmini const laggr_args_t *l = arg; 1941e7801d59Ssowmini int portnum; 1942e7801d59Ssowmini static char buf[DLADM_STRSIZE]; 1943e7801d59Ssowmini boolean_t is_port = (l->laggr_lport >= 0); 1944e7801d59Ssowmini dladm_aggr_port_attr_t *portp; 1945d62bc4baSyz147064 dladm_phys_attr_t dpa; 1946e7801d59Ssowmini dladm_status_t *stat, status; 1947d62bc4baSyz147064 1948e7801d59Ssowmini stat = l->laggr_status; 1949e7801d59Ssowmini *stat = DLADM_STATUS_OK; 1950d62bc4baSyz147064 1951e7801d59Ssowmini if (is_port) { 1952e7801d59Ssowmini portnum = l->laggr_lport; 1953e7801d59Ssowmini portp = &(l->laggr_ginfop->lg_ports[portnum]); 1954e7801d59Ssowmini if ((status = dladm_datalink_id2info(portp->lp_linkid, 1955e7801d59Ssowmini NULL, NULL, NULL, buf, sizeof (buf))) != 1956e7801d59Ssowmini DLADM_STATUS_OK) { 1957e7801d59Ssowmini goto err; 1958d62bc4baSyz147064 } 1959d62bc4baSyz147064 if ((status = dladm_phys_info(portp->lp_linkid, &dpa, 1960d62bc4baSyz147064 DLADM_OPT_ACTIVE)) != DLADM_STATUS_OK) { 1961e7801d59Ssowmini goto err; 1962e7801d59Ssowmini } 1963d62bc4baSyz147064 } 1964d62bc4baSyz147064 1965e7801d59Ssowmini switch (pf->pf_index) { 1966e7801d59Ssowmini case AGGR_X_LINK: 1967e7801d59Ssowmini (void) snprintf(buf, sizeof (buf), "%s", 1968e7801d59Ssowmini (is_port && !l->laggr_parseable ? " " : l->laggr_link)); 1969e7801d59Ssowmini break; 1970e7801d59Ssowmini case AGGR_X_PORT: 1971e7801d59Ssowmini if (is_port) 1972e7801d59Ssowmini break; 1973e7801d59Ssowmini return (""); 1974e7801d59Ssowmini break; 1975d62bc4baSyz147064 1976e7801d59Ssowmini case AGGR_X_SPEED: 1977e7801d59Ssowmini if (is_port) { 1978e7801d59Ssowmini (void) snprintf(buf, sizeof (buf), "%uMb", 1979e7801d59Ssowmini (uint_t)((get_ifspeed(dpa.dp_dev, 1980e7801d59Ssowmini B_FALSE)) / 1000000ull)); 1981e7801d59Ssowmini } else { 1982e7801d59Ssowmini (void) snprintf(buf, sizeof (buf), "%uMb", 1983e7801d59Ssowmini (uint_t)((get_ifspeed(l->laggr_link, 1984e7801d59Ssowmini B_TRUE)) / 1000000ull)); 1985e7801d59Ssowmini } 1986e7801d59Ssowmini break; 1987e7801d59Ssowmini 1988e7801d59Ssowmini case AGGR_X_DUPLEX: 1989e7801d59Ssowmini if (is_port) 1990e7801d59Ssowmini (void) get_linkduplex(dpa.dp_dev, B_FALSE, buf); 1991d62bc4baSyz147064 else 1992e7801d59Ssowmini (void) get_linkduplex(l->laggr_link, B_TRUE, buf); 1993e7801d59Ssowmini break; 1994d62bc4baSyz147064 1995e7801d59Ssowmini case AGGR_X_STATE: 19961a1811a0Svs226613 if (is_port) 19971a1811a0Svs226613 (void) get_linkstate(dpa.dp_dev, B_FALSE, buf); 19981a1811a0Svs226613 else 19991a1811a0Svs226613 (void) get_linkstate(l->laggr_link, B_TRUE, buf); 2000e7801d59Ssowmini break; 2001e7801d59Ssowmini case AGGR_X_ADDRESS: 2002e7801d59Ssowmini (void) dladm_aggr_macaddr2str( 2003e7801d59Ssowmini (is_port ? portp->lp_mac : l->laggr_ginfop->lg_mac), 2004e7801d59Ssowmini buf); 2005e7801d59Ssowmini break; 2006e7801d59Ssowmini case AGGR_X_PORTSTATE: 20070d365605Sschuster if (is_port) 20080d365605Sschuster (void) dladm_aggr_portstate2str( 20090d365605Sschuster portp->lp_state, buf); 20100d365605Sschuster else 20110d365605Sschuster return (""); 2012e7801d59Ssowmini break; 2013e7801d59Ssowmini } 2014e7801d59Ssowmini return (buf); 2015e7801d59Ssowmini 2016e7801d59Ssowmini err: 2017e7801d59Ssowmini *stat = status; 2018e7801d59Ssowmini buf[0] = '\0'; 2019e7801d59Ssowmini return (buf); 2020e7801d59Ssowmini } 2021e7801d59Ssowmini 2022e7801d59Ssowmini static dladm_status_t 2023e7801d59Ssowmini print_aggr_extended(show_grp_state_t *state, const char *link, 2024e7801d59Ssowmini dladm_aggr_grp_attr_t *ginfop) 2025e7801d59Ssowmini { 2026e7801d59Ssowmini int i; 2027e7801d59Ssowmini dladm_status_t status; 2028e7801d59Ssowmini laggr_args_t largs; 2029e7801d59Ssowmini 2030e7801d59Ssowmini if (!state->gs_parseable && !state->gs_printheader) { 2031e7801d59Ssowmini print_header(&state->gs_print); 2032e7801d59Ssowmini state->gs_printheader = B_TRUE; 2033e7801d59Ssowmini } 2034e7801d59Ssowmini 2035e7801d59Ssowmini largs.laggr_lport = -1; 2036e7801d59Ssowmini largs.laggr_link = link; 2037e7801d59Ssowmini largs.laggr_ginfop = ginfop; 2038e7801d59Ssowmini largs.laggr_status = &status; 2039e7801d59Ssowmini largs.laggr_parseable = state->gs_parseable; 2040e7801d59Ssowmini 2041e7801d59Ssowmini dladm_print_output(&state->gs_print, state->gs_parseable, 2042e7801d59Ssowmini print_xaggr_callback, &largs); 2043e7801d59Ssowmini 2044e7801d59Ssowmini if (status != DLADM_STATUS_OK) 2045e7801d59Ssowmini goto done; 2046e7801d59Ssowmini 2047e7801d59Ssowmini for (i = 0; i < ginfop->lg_nports; i++) { 2048e7801d59Ssowmini largs.laggr_lport = i; 2049e7801d59Ssowmini dladm_print_output(&state->gs_print, state->gs_parseable, 2050e7801d59Ssowmini print_xaggr_callback, &largs); 2051e7801d59Ssowmini if (status != DLADM_STATUS_OK) 2052e7801d59Ssowmini goto done; 2053d62bc4baSyz147064 } 2054d62bc4baSyz147064 2055d62bc4baSyz147064 status = DLADM_STATUS_OK; 2056d62bc4baSyz147064 done: 2057d62bc4baSyz147064 return (status); 2058d62bc4baSyz147064 } 2059d62bc4baSyz147064 2060e7801d59Ssowmini 2061e7801d59Ssowmini static char * 2062e7801d59Ssowmini print_lacp_callback(print_field_t *pf, void *arg) 2063e7801d59Ssowmini { 2064e7801d59Ssowmini const laggr_args_t *l = arg; 2065e7801d59Ssowmini int portnum; 2066e7801d59Ssowmini static char buf[DLADM_STRSIZE]; 2067e7801d59Ssowmini boolean_t is_port = (l->laggr_lport >= 0); 2068e7801d59Ssowmini dladm_aggr_port_attr_t *portp; 2069e7801d59Ssowmini dladm_status_t *stat, status; 2070e7801d59Ssowmini aggr_lacp_state_t *lstate; 2071e7801d59Ssowmini 2072e7801d59Ssowmini if (!is_port) { 2073e7801d59Ssowmini return (NULL); /* cannot happen! */ 2074e7801d59Ssowmini } 2075e7801d59Ssowmini 2076e7801d59Ssowmini stat = l->laggr_status; 2077e7801d59Ssowmini 2078e7801d59Ssowmini portnum = l->laggr_lport; 2079e7801d59Ssowmini portp = &(l->laggr_ginfop->lg_ports[portnum]); 2080e7801d59Ssowmini if ((status = dladm_datalink_id2info(portp->lp_linkid, 2081e7801d59Ssowmini NULL, NULL, NULL, buf, sizeof (buf))) != DLADM_STATUS_OK) { 2082e7801d59Ssowmini goto err; 2083e7801d59Ssowmini } 2084e7801d59Ssowmini lstate = &(portp->lp_lacp_state); 2085e7801d59Ssowmini 2086e7801d59Ssowmini switch (pf->pf_index) { 2087e7801d59Ssowmini case AGGR_L_LINK: 2088e7801d59Ssowmini (void) snprintf(buf, sizeof (buf), "%s", 2089e7801d59Ssowmini (portnum > 0 ? "" : l->laggr_link)); 2090e7801d59Ssowmini break; 2091e7801d59Ssowmini 2092e7801d59Ssowmini case AGGR_L_PORT: 2093e7801d59Ssowmini break; 2094e7801d59Ssowmini 2095e7801d59Ssowmini case AGGR_L_AGGREGATABLE: 2096e7801d59Ssowmini (void) snprintf(buf, sizeof (buf), "%s", 2097e7801d59Ssowmini (lstate->bit.aggregation ? "yes" : "no")); 2098e7801d59Ssowmini break; 2099e7801d59Ssowmini 2100e7801d59Ssowmini case AGGR_L_SYNC: 2101e7801d59Ssowmini (void) snprintf(buf, sizeof (buf), "%s", 2102e7801d59Ssowmini (lstate->bit.sync ? "yes" : "no")); 2103e7801d59Ssowmini break; 2104e7801d59Ssowmini 2105e7801d59Ssowmini case AGGR_L_COLL: 2106e7801d59Ssowmini (void) snprintf(buf, sizeof (buf), "%s", 2107e7801d59Ssowmini (lstate->bit.collecting ? "yes" : "no")); 2108e7801d59Ssowmini break; 2109e7801d59Ssowmini 2110e7801d59Ssowmini case AGGR_L_DIST: 2111e7801d59Ssowmini (void) snprintf(buf, sizeof (buf), "%s", 2112e7801d59Ssowmini (lstate->bit.distributing ? "yes" : "no")); 2113e7801d59Ssowmini break; 2114e7801d59Ssowmini 2115e7801d59Ssowmini case AGGR_L_DEFAULTED: 2116e7801d59Ssowmini (void) snprintf(buf, sizeof (buf), "%s", 2117e7801d59Ssowmini (lstate->bit.defaulted ? "yes" : "no")); 2118e7801d59Ssowmini break; 2119e7801d59Ssowmini 2120e7801d59Ssowmini case AGGR_L_EXPIRED: 2121e7801d59Ssowmini (void) snprintf(buf, sizeof (buf), "%s", 2122e7801d59Ssowmini (lstate->bit.expired ? "yes" : "no")); 2123e7801d59Ssowmini break; 2124e7801d59Ssowmini } 2125e7801d59Ssowmini 2126e7801d59Ssowmini *stat = DLADM_STATUS_OK; 2127e7801d59Ssowmini return (buf); 2128e7801d59Ssowmini 2129e7801d59Ssowmini err: 2130e7801d59Ssowmini *stat = status; 2131e7801d59Ssowmini buf[0] = '\0'; 2132e7801d59Ssowmini return (buf); 2133e7801d59Ssowmini } 2134e7801d59Ssowmini 2135d62bc4baSyz147064 static dladm_status_t 2136d62bc4baSyz147064 print_aggr_lacp(show_grp_state_t *state, const char *link, 2137e7801d59Ssowmini dladm_aggr_grp_attr_t *ginfop) 2138d62bc4baSyz147064 { 2139d62bc4baSyz147064 int i; 2140d62bc4baSyz147064 dladm_status_t status; 2141e7801d59Ssowmini laggr_args_t largs; 2142d62bc4baSyz147064 2143e7801d59Ssowmini if (!state->gs_parseable && !state->gs_printheader) { 2144e7801d59Ssowmini print_header(&state->gs_print); 2145e7801d59Ssowmini state->gs_printheader = B_TRUE; 2146d62bc4baSyz147064 } 2147d62bc4baSyz147064 2148e7801d59Ssowmini largs.laggr_link = link; 2149e7801d59Ssowmini largs.laggr_ginfop = ginfop; 2150e7801d59Ssowmini largs.laggr_status = &status; 2151d62bc4baSyz147064 2152e7801d59Ssowmini for (i = 0; i < ginfop->lg_nports; i++) { 2153e7801d59Ssowmini largs.laggr_lport = i; 2154e7801d59Ssowmini dladm_print_output(&state->gs_print, state->gs_parseable, 2155e7801d59Ssowmini print_lacp_callback, &largs); 2156d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 2157d62bc4baSyz147064 goto done; 2158d62bc4baSyz147064 } 2159d62bc4baSyz147064 2160d62bc4baSyz147064 status = DLADM_STATUS_OK; 2161d62bc4baSyz147064 done: 2162d62bc4baSyz147064 return (status); 2163d62bc4baSyz147064 } 2164d62bc4baSyz147064 2165e7801d59Ssowmini static char * 2166e7801d59Ssowmini print_aggr_stats_callback(print_field_t *pf, void *arg) 2167e7801d59Ssowmini { 2168e7801d59Ssowmini const laggr_args_t *l = arg; 2169e7801d59Ssowmini int portnum; 2170e7801d59Ssowmini static char buf[DLADM_STRSIZE]; 2171e7801d59Ssowmini boolean_t is_port = (l->laggr_lport >= 0); 2172e7801d59Ssowmini dladm_aggr_port_attr_t *portp; 2173e7801d59Ssowmini dladm_phys_attr_t dpa; 2174e7801d59Ssowmini dladm_status_t *stat, status; 2175e7801d59Ssowmini pktsum_t port_stat, diff_stats; 2176e7801d59Ssowmini 2177e7801d59Ssowmini stat = l->laggr_status; 2178e7801d59Ssowmini *stat = DLADM_STATUS_OK; 2179e7801d59Ssowmini 2180e7801d59Ssowmini if (is_port) { 2181e7801d59Ssowmini portnum = l->laggr_lport; 2182e7801d59Ssowmini portp = &(l->laggr_ginfop->lg_ports[portnum]); 2183e7801d59Ssowmini if ((status = dladm_phys_info(portp->lp_linkid, &dpa, 2184e7801d59Ssowmini DLADM_OPT_ACTIVE)) != DLADM_STATUS_OK) { 2185e7801d59Ssowmini goto err; 2186e7801d59Ssowmini } 2187e7801d59Ssowmini 2188e7801d59Ssowmini get_mac_stats(dpa.dp_dev, &port_stat); 2189e7801d59Ssowmini 2190e7801d59Ssowmini if ((status = dladm_datalink_id2info(portp->lp_linkid, NULL, 2191e7801d59Ssowmini NULL, NULL, buf, sizeof (buf))) != DLADM_STATUS_OK) { 2192e7801d59Ssowmini goto err; 2193e7801d59Ssowmini } 2194e7801d59Ssowmini 2195e7801d59Ssowmini stats_diff(&diff_stats, &port_stat, l->laggr_prevstats); 2196e7801d59Ssowmini } 2197e7801d59Ssowmini 2198e7801d59Ssowmini switch (pf->pf_index) { 2199e7801d59Ssowmini case AGGR_S_LINK: 2200e7801d59Ssowmini (void) snprintf(buf, sizeof (buf), "%s", 2201e7801d59Ssowmini (is_port ? "" : l->laggr_link)); 2202e7801d59Ssowmini break; 2203e7801d59Ssowmini case AGGR_S_PORT: 2204e7801d59Ssowmini if (is_port) 2205e7801d59Ssowmini break; 22060d365605Sschuster return (""); 2207e7801d59Ssowmini break; 2208e7801d59Ssowmini 2209e7801d59Ssowmini case AGGR_S_IPKTS: 2210e7801d59Ssowmini if (is_port) { 2211e7801d59Ssowmini (void) snprintf(buf, sizeof (buf), "%llu", 2212e7801d59Ssowmini diff_stats.ipackets); 2213e7801d59Ssowmini } else { 2214e7801d59Ssowmini (void) snprintf(buf, sizeof (buf), "%llu", 2215e7801d59Ssowmini l->laggr_pktsumtot->ipackets); 2216e7801d59Ssowmini } 2217e7801d59Ssowmini break; 2218e7801d59Ssowmini 2219e7801d59Ssowmini case AGGR_S_RBYTES: 2220e7801d59Ssowmini if (is_port) { 2221e7801d59Ssowmini (void) snprintf(buf, sizeof (buf), "%llu", 2222e7801d59Ssowmini diff_stats.rbytes); 2223e7801d59Ssowmini } else { 2224e7801d59Ssowmini (void) snprintf(buf, sizeof (buf), "%llu", 2225e7801d59Ssowmini l->laggr_pktsumtot->rbytes); 2226e7801d59Ssowmini } 2227e7801d59Ssowmini break; 2228e7801d59Ssowmini 2229e7801d59Ssowmini case AGGR_S_OPKTS: 2230e7801d59Ssowmini if (is_port) { 2231e7801d59Ssowmini (void) snprintf(buf, sizeof (buf), "%llu", 2232e7801d59Ssowmini diff_stats.opackets); 2233e7801d59Ssowmini } else { 2234e7801d59Ssowmini (void) snprintf(buf, sizeof (buf), "%llu", 2235e7801d59Ssowmini l->laggr_pktsumtot->opackets); 2236e7801d59Ssowmini } 2237e7801d59Ssowmini break; 2238e7801d59Ssowmini case AGGR_S_OBYTES: 2239e7801d59Ssowmini if (is_port) { 2240e7801d59Ssowmini (void) snprintf(buf, sizeof (buf), "%llu", 2241e7801d59Ssowmini diff_stats.obytes); 2242e7801d59Ssowmini } else { 2243e7801d59Ssowmini (void) snprintf(buf, sizeof (buf), "%llu", 2244e7801d59Ssowmini l->laggr_pktsumtot->obytes); 2245e7801d59Ssowmini 2246e7801d59Ssowmini } 2247e7801d59Ssowmini break; 2248e7801d59Ssowmini 2249e7801d59Ssowmini case AGGR_S_IPKTDIST: 2250e7801d59Ssowmini if (is_port) { 2251e7801d59Ssowmini (void) snprintf(buf, sizeof (buf), "%-6.1f", 2252e7801d59Ssowmini (double)diff_stats.opackets/ 2253e7801d59Ssowmini (double)l->laggr_pktsumtot->ipackets * 100); 2254e7801d59Ssowmini } else { 22550d365605Sschuster return (""); 2256e7801d59Ssowmini } 2257e7801d59Ssowmini break; 2258e7801d59Ssowmini case AGGR_S_OPKTDIST: 2259e7801d59Ssowmini if (is_port) { 2260e7801d59Ssowmini (void) snprintf(buf, sizeof (buf), "%-6.1f", 2261e7801d59Ssowmini (double)diff_stats.opackets/ 2262e7801d59Ssowmini (double)l->laggr_pktsumtot->opackets * 100); 2263e7801d59Ssowmini } else { 22640d365605Sschuster return (""); 2265e7801d59Ssowmini } 2266e7801d59Ssowmini break; 2267e7801d59Ssowmini } 2268e7801d59Ssowmini return (buf); 2269e7801d59Ssowmini 2270e7801d59Ssowmini err: 2271e7801d59Ssowmini *stat = status; 2272e7801d59Ssowmini buf[0] = '\0'; 2273e7801d59Ssowmini return (buf); 2274e7801d59Ssowmini } 2275e7801d59Ssowmini 2276d62bc4baSyz147064 static dladm_status_t 2277d62bc4baSyz147064 print_aggr_stats(show_grp_state_t *state, const char *link, 2278e7801d59Ssowmini dladm_aggr_grp_attr_t *ginfop) 2279d62bc4baSyz147064 { 2280d62bc4baSyz147064 dladm_phys_attr_t dpa; 2281d62bc4baSyz147064 dladm_aggr_port_attr_t *portp; 2282d62bc4baSyz147064 pktsum_t pktsumtot, port_stat; 2283d62bc4baSyz147064 dladm_status_t status; 2284d62bc4baSyz147064 int i; 2285e7801d59Ssowmini laggr_args_t largs; 22867c478bd9Sstevel@tonic-gate 22877c478bd9Sstevel@tonic-gate /* sum the ports statistics */ 22887c478bd9Sstevel@tonic-gate bzero(&pktsumtot, sizeof (pktsumtot)); 2289d62bc4baSyz147064 2290d62bc4baSyz147064 for (i = 0; i < ginfop->lg_nports; i++) { 2291d62bc4baSyz147064 2292d62bc4baSyz147064 portp = &(ginfop->lg_ports[i]); 2293d62bc4baSyz147064 if ((status = dladm_phys_info(portp->lp_linkid, &dpa, 2294d62bc4baSyz147064 DLADM_OPT_ACTIVE)) != DLADM_STATUS_OK) { 2295d62bc4baSyz147064 goto done; 22967c478bd9Sstevel@tonic-gate } 22977c478bd9Sstevel@tonic-gate 2298d62bc4baSyz147064 get_mac_stats(dpa.dp_dev, &port_stat); 2299d62bc4baSyz147064 stats_total(&pktsumtot, &port_stat, &state->gs_prevstats[i]); 23007c478bd9Sstevel@tonic-gate } 23017c478bd9Sstevel@tonic-gate 2302e7801d59Ssowmini if (!state->gs_parseable && !state->gs_printheader) { 2303e7801d59Ssowmini print_header(&state->gs_print); 2304e7801d59Ssowmini state->gs_printheader = B_TRUE; 2305e7801d59Ssowmini } 2306e7801d59Ssowmini 2307e7801d59Ssowmini largs.laggr_lport = -1; 2308e7801d59Ssowmini largs.laggr_link = link; 2309e7801d59Ssowmini largs.laggr_ginfop = ginfop; 2310e7801d59Ssowmini largs.laggr_status = &status; 2311e7801d59Ssowmini largs.laggr_pktsumtot = &pktsumtot; 2312e7801d59Ssowmini 2313e7801d59Ssowmini dladm_print_output(&state->gs_print, state->gs_parseable, 2314e7801d59Ssowmini print_aggr_stats_callback, &largs); 2315e7801d59Ssowmini 2316e7801d59Ssowmini if (status != DLADM_STATUS_OK) 2317e7801d59Ssowmini goto done; 2318d62bc4baSyz147064 2319d62bc4baSyz147064 for (i = 0; i < ginfop->lg_nports; i++) { 2320e7801d59Ssowmini largs.laggr_lport = i; 2321e7801d59Ssowmini largs.laggr_prevstats = &state->gs_prevstats[i]; 2322e7801d59Ssowmini dladm_print_output(&state->gs_print, state->gs_parseable, 2323e7801d59Ssowmini print_aggr_stats_callback, &largs); 2324e7801d59Ssowmini if (status != DLADM_STATUS_OK) 2325d62bc4baSyz147064 goto done; 2326d62bc4baSyz147064 } 2327d62bc4baSyz147064 2328d62bc4baSyz147064 status = DLADM_STATUS_OK; 2329d62bc4baSyz147064 done: 2330d62bc4baSyz147064 return (status); 2331d62bc4baSyz147064 } 2332d62bc4baSyz147064 2333d62bc4baSyz147064 static dladm_status_t 2334e7801d59Ssowmini print_aggr(show_grp_state_t *state, datalink_id_t linkid) 2335d62bc4baSyz147064 { 2336d62bc4baSyz147064 char link[MAXLINKNAMELEN]; 2337d62bc4baSyz147064 dladm_aggr_grp_attr_t ginfo; 2338d62bc4baSyz147064 uint32_t flags; 2339d62bc4baSyz147064 dladm_status_t status; 2340d62bc4baSyz147064 23415f5c9f54SAnurag S. Maskey bzero(&ginfo, sizeof (dladm_aggr_grp_attr_t)); 2342d62bc4baSyz147064 if ((status = dladm_datalink_id2info(linkid, &flags, NULL, NULL, link, 2343e7801d59Ssowmini MAXLINKNAMELEN)) != DLADM_STATUS_OK) { 2344d62bc4baSyz147064 return (status); 2345d62bc4baSyz147064 } 2346d62bc4baSyz147064 2347d62bc4baSyz147064 if (!(state->gs_flags & flags)) 2348d62bc4baSyz147064 return (DLADM_STATUS_NOTFOUND); 2349d62bc4baSyz147064 2350d62bc4baSyz147064 status = dladm_aggr_info(linkid, &ginfo, state->gs_flags); 2351d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 2352d62bc4baSyz147064 return (status); 2353d62bc4baSyz147064 2354d62bc4baSyz147064 if (state->gs_lacp) 2355e7801d59Ssowmini status = print_aggr_lacp(state, link, &ginfo); 2356d62bc4baSyz147064 else if (state->gs_extended) 2357e7801d59Ssowmini status = print_aggr_extended(state, link, &ginfo); 2358d62bc4baSyz147064 else if (state->gs_stats) 2359e7801d59Ssowmini status = print_aggr_stats(state, link, &ginfo); 2360e7801d59Ssowmini else { 2361e7801d59Ssowmini status = print_aggr_info(state, link, &ginfo); 2362e7801d59Ssowmini } 2363d62bc4baSyz147064 2364d62bc4baSyz147064 done: 2365d62bc4baSyz147064 free(ginfo.lg_ports); 2366d62bc4baSyz147064 return (status); 2367d62bc4baSyz147064 } 2368d62bc4baSyz147064 2369d62bc4baSyz147064 static int 2370d62bc4baSyz147064 show_aggr(datalink_id_t linkid, void *arg) 2371d62bc4baSyz147064 { 2372d62bc4baSyz147064 show_grp_state_t *state = arg; 2373d62bc4baSyz147064 dladm_status_t status; 2374d62bc4baSyz147064 2375e7801d59Ssowmini status = print_aggr(state, linkid); 2376d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 2377d62bc4baSyz147064 goto done; 2378d62bc4baSyz147064 2379d62bc4baSyz147064 done: 2380d62bc4baSyz147064 state->gs_status = status; 2381d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 23827c478bd9Sstevel@tonic-gate } 23837c478bd9Sstevel@tonic-gate 2384e7801d59Ssowmini static char * 2385e7801d59Ssowmini print_dev(print_field_t *pf, void *arg) 23867c478bd9Sstevel@tonic-gate { 2387e7801d59Ssowmini const char *dev = arg; 2388e7801d59Ssowmini static char buf[DLADM_STRSIZE]; 23897c478bd9Sstevel@tonic-gate 2390e7801d59Ssowmini switch (pf->pf_index) { 2391e7801d59Ssowmini case DEV_LINK: 2392e7801d59Ssowmini (void) snprintf(buf, sizeof (buf), "%s", dev); 23937c478bd9Sstevel@tonic-gate break; 2394e7801d59Ssowmini case DEV_STATE: 2395e7801d59Ssowmini (void) get_linkstate(dev, B_FALSE, buf); 2396e7801d59Ssowmini break; 2397e7801d59Ssowmini case DEV_SPEED: 2398e7801d59Ssowmini (void) snprintf(buf, sizeof (buf), "%uMb", 2399e7801d59Ssowmini (unsigned int)(get_ifspeed(dev, B_FALSE) / 1000000ull)); 2400e7801d59Ssowmini break; 2401e7801d59Ssowmini case DEV_DUPLEX: 2402e7801d59Ssowmini (void) get_linkduplex(dev, B_FALSE, buf); 24037c478bd9Sstevel@tonic-gate break; 24047c478bd9Sstevel@tonic-gate default: 2405e7801d59Ssowmini die("invalid index '%d'", pf->pf_index); 2406e7801d59Ssowmini break; 24077c478bd9Sstevel@tonic-gate } 2408e7801d59Ssowmini return (buf); 24097c478bd9Sstevel@tonic-gate } 24107c478bd9Sstevel@tonic-gate 2411d62bc4baSyz147064 static int 2412d62bc4baSyz147064 show_dev(const char *dev, void *arg) 24137c478bd9Sstevel@tonic-gate { 2414d62bc4baSyz147064 show_state_t *state = arg; 24157c478bd9Sstevel@tonic-gate 2416e7801d59Ssowmini if (!state->ls_parseable && !state->ls_printheader) { 2417e7801d59Ssowmini print_header(&state->ls_print); 2418e7801d59Ssowmini state->ls_printheader = B_TRUE; 24197c478bd9Sstevel@tonic-gate } 24207c478bd9Sstevel@tonic-gate 2421e7801d59Ssowmini dladm_print_output(&state->ls_print, state->ls_parseable, 2422e7801d59Ssowmini print_dev, (void *)dev); 2423d62bc4baSyz147064 2424d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 2425d62bc4baSyz147064 } 2426d62bc4baSyz147064 2427e7801d59Ssowmini static char * 2428e7801d59Ssowmini print_dev_stats(print_field_t *pf, void *arg) 2429e7801d59Ssowmini { 2430e7801d59Ssowmini dev_args_t *dargs = arg; 2431e7801d59Ssowmini pktsum_t *diff_stats = dargs->devs_psum; 2432e7801d59Ssowmini static char buf[DLADM_STRSIZE]; 2433e7801d59Ssowmini 2434e7801d59Ssowmini switch (pf->pf_index) { 2435e7801d59Ssowmini case DEVS_LINK: 2436e7801d59Ssowmini (void) snprintf(buf, sizeof (buf), "%s", dargs->devs_link); 2437e7801d59Ssowmini break; 2438e7801d59Ssowmini case DEVS_IPKTS: 2439e7801d59Ssowmini (void) snprintf(buf, sizeof (buf), "%llu", 2440e7801d59Ssowmini diff_stats->ipackets); 2441e7801d59Ssowmini break; 2442e7801d59Ssowmini case DEVS_RBYTES: 2443e7801d59Ssowmini (void) snprintf(buf, sizeof (buf), "%llu", 2444e7801d59Ssowmini diff_stats->rbytes); 2445e7801d59Ssowmini break; 2446e7801d59Ssowmini case DEVS_IERRORS: 2447e7801d59Ssowmini (void) snprintf(buf, sizeof (buf), "%u", 2448e7801d59Ssowmini diff_stats->ierrors); 2449e7801d59Ssowmini break; 2450e7801d59Ssowmini case DEVS_OPKTS: 2451e7801d59Ssowmini (void) snprintf(buf, sizeof (buf), "%llu", 2452e7801d59Ssowmini diff_stats->opackets); 2453e7801d59Ssowmini break; 2454e7801d59Ssowmini case DEVS_OBYTES: 2455e7801d59Ssowmini (void) snprintf(buf, sizeof (buf), "%llu", 2456e7801d59Ssowmini diff_stats->obytes); 2457e7801d59Ssowmini break; 2458e7801d59Ssowmini case DEVS_OERRORS: 2459e7801d59Ssowmini (void) snprintf(buf, sizeof (buf), "%u", 2460e7801d59Ssowmini diff_stats->oerrors); 2461e7801d59Ssowmini break; 2462e7801d59Ssowmini default: 2463e7801d59Ssowmini die("invalid input"); 2464e7801d59Ssowmini break; 2465e7801d59Ssowmini } 2466e7801d59Ssowmini return (buf); 2467e7801d59Ssowmini } 2468e7801d59Ssowmini 2469d62bc4baSyz147064 static int 2470d62bc4baSyz147064 show_dev_stats(const char *dev, void *arg) 24717c478bd9Sstevel@tonic-gate { 2472d62bc4baSyz147064 show_state_t *state = arg; 24737c478bd9Sstevel@tonic-gate pktsum_t stats, diff_stats; 2474e7801d59Ssowmini dev_args_t dargs; 24757c478bd9Sstevel@tonic-gate 2476d62bc4baSyz147064 if (state->ls_firstonly) { 2477d62bc4baSyz147064 if (state->ls_donefirst) 2478d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 2479d62bc4baSyz147064 state->ls_donefirst = B_TRUE; 24807c478bd9Sstevel@tonic-gate } else { 2481d62bc4baSyz147064 bzero(&state->ls_prevstats, sizeof (state->ls_prevstats)); 24827c478bd9Sstevel@tonic-gate } 24837c478bd9Sstevel@tonic-gate 2484ba2e4443Sseb get_mac_stats(dev, &stats); 2485d62bc4baSyz147064 stats_diff(&diff_stats, &stats, &state->ls_prevstats); 24867c478bd9Sstevel@tonic-gate 2487e7801d59Ssowmini dargs.devs_link = (char *)dev; 2488e7801d59Ssowmini dargs.devs_psum = &diff_stats; 2489e7801d59Ssowmini dladm_print_output(&state->ls_print, state->ls_parseable, 2490e7801d59Ssowmini print_dev_stats, &dargs); 24917c478bd9Sstevel@tonic-gate 2492d62bc4baSyz147064 state->ls_prevstats = stats; 2493d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 24947c478bd9Sstevel@tonic-gate } 24957c478bd9Sstevel@tonic-gate 24967c478bd9Sstevel@tonic-gate static void 24978d5c46e6Sam223141 do_show_link(int argc, char *argv[], const char *use) 24987c478bd9Sstevel@tonic-gate { 24997c478bd9Sstevel@tonic-gate int option; 25007c478bd9Sstevel@tonic-gate boolean_t s_arg = B_FALSE; 25017c478bd9Sstevel@tonic-gate boolean_t i_arg = B_FALSE; 2502d62bc4baSyz147064 uint32_t flags = DLADM_OPT_ACTIVE; 2503d62bc4baSyz147064 boolean_t p_arg = B_FALSE; 2504d62bc4baSyz147064 datalink_id_t linkid = DATALINK_ALL_LINKID; 250533343a97Smeem int interval = 0; 2506d62bc4baSyz147064 show_state_t state; 2507d62bc4baSyz147064 dladm_status_t status; 2508e7801d59Ssowmini boolean_t o_arg = B_FALSE; 2509e7801d59Ssowmini char *fields_str = NULL; 2510e7801d59Ssowmini print_field_t **fields; 2511e7801d59Ssowmini uint_t nfields; 2512e7801d59Ssowmini char *all_active_fields = "link,class,mtu,state,over"; 2513e7801d59Ssowmini char *all_inactive_fields = "link,class,over"; 25146be03d0bSVasumathi Sundaram - Sun Microsystems char *allstat_fields = 25156be03d0bSVasumathi Sundaram - Sun Microsystems "link,ipackets,rbytes,ierrors,opackets,obytes,oerrors"; 2516e7801d59Ssowmini 2517e7801d59Ssowmini bzero(&state, sizeof (state)); 25187c478bd9Sstevel@tonic-gate 25197c478bd9Sstevel@tonic-gate opterr = 0; 2520e7801d59Ssowmini while ((option = getopt_long(argc, argv, ":pPsi:o:", 2521d62bc4baSyz147064 show_lopts, NULL)) != -1) { 25227c478bd9Sstevel@tonic-gate switch (option) { 25237c478bd9Sstevel@tonic-gate case 'p': 2524d62bc4baSyz147064 if (p_arg) 2525d62bc4baSyz147064 die_optdup(option); 2526d62bc4baSyz147064 2527d62bc4baSyz147064 p_arg = B_TRUE; 25287c478bd9Sstevel@tonic-gate break; 25297c478bd9Sstevel@tonic-gate case 's': 253033343a97Smeem if (s_arg) 253133343a97Smeem die_optdup(option); 25327c478bd9Sstevel@tonic-gate 25337c478bd9Sstevel@tonic-gate s_arg = B_TRUE; 25347c478bd9Sstevel@tonic-gate break; 2535d62bc4baSyz147064 case 'P': 2536d62bc4baSyz147064 if (flags != DLADM_OPT_ACTIVE) 2537d62bc4baSyz147064 die_optdup(option); 2538d62bc4baSyz147064 2539d62bc4baSyz147064 flags = DLADM_OPT_PERSIST; 2540d62bc4baSyz147064 break; 2541e7801d59Ssowmini case 'o': 2542e7801d59Ssowmini o_arg = B_TRUE; 2543e7801d59Ssowmini fields_str = optarg; 2544e7801d59Ssowmini break; 25457c478bd9Sstevel@tonic-gate case 'i': 254633343a97Smeem if (i_arg) 254733343a97Smeem die_optdup(option); 25487c478bd9Sstevel@tonic-gate 25497c478bd9Sstevel@tonic-gate i_arg = B_TRUE; 255033343a97Smeem if (!str2int(optarg, &interval) || interval == 0) 255133343a97Smeem die("invalid interval value '%s'", optarg); 25527c478bd9Sstevel@tonic-gate break; 25537c478bd9Sstevel@tonic-gate default: 25548d5c46e6Sam223141 die_opterr(optopt, option, use); 255533343a97Smeem break; 25567c478bd9Sstevel@tonic-gate } 25577c478bd9Sstevel@tonic-gate } 25587c478bd9Sstevel@tonic-gate 255933343a97Smeem if (i_arg && !s_arg) 256033343a97Smeem die("the option -i can be used only with -s"); 25617c478bd9Sstevel@tonic-gate 25626be03d0bSVasumathi Sundaram - Sun Microsystems if (s_arg && flags != DLADM_OPT_ACTIVE) 25636be03d0bSVasumathi Sundaram - Sun Microsystems die("the option -P cannot be used with -s"); 2564d62bc4baSyz147064 25657c478bd9Sstevel@tonic-gate /* get link name (optional last argument) */ 2566d62bc4baSyz147064 if (optind == (argc-1)) { 2567d62bc4baSyz147064 uint32_t f; 2568d62bc4baSyz147064 2569d62bc4baSyz147064 if ((status = dladm_name2info(argv[optind], &linkid, &f, 2570d62bc4baSyz147064 NULL, NULL)) != DLADM_STATUS_OK) { 2571d62bc4baSyz147064 die_dlerr(status, "link %s is not valid", argv[optind]); 2572d62bc4baSyz147064 } 2573d62bc4baSyz147064 2574d62bc4baSyz147064 if (!(f & flags)) { 2575d62bc4baSyz147064 die_dlerr(DLADM_STATUS_BADARG, "link %s is %s", 2576d62bc4baSyz147064 argv[optind], flags == DLADM_OPT_PERSIST ? 2577d62bc4baSyz147064 "a temporary link" : "temporarily removed"); 2578d62bc4baSyz147064 } 2579d62bc4baSyz147064 } else if (optind != argc) { 25807c478bd9Sstevel@tonic-gate usage(); 2581d62bc4baSyz147064 } 25827c478bd9Sstevel@tonic-gate 25830d365605Sschuster if (p_arg && !o_arg) 25840d365605Sschuster die("-p requires -o"); 25850d365605Sschuster 25860d365605Sschuster if (p_arg && strcasecmp(fields_str, "all") == 0) 25870d365605Sschuster die("\"-o all\" is invalid with -p"); 25880d365605Sschuster 2589e7801d59Ssowmini if (!o_arg || (o_arg && strcasecmp(fields_str, "all") == 0)) { 25906be03d0bSVasumathi Sundaram - Sun Microsystems if (s_arg) 25916be03d0bSVasumathi Sundaram - Sun Microsystems fields_str = allstat_fields; 25926be03d0bSVasumathi Sundaram - Sun Microsystems else if (flags & DLADM_OPT_ACTIVE) 2593e7801d59Ssowmini fields_str = all_active_fields; 2594e7801d59Ssowmini else 2595e7801d59Ssowmini fields_str = all_inactive_fields; 2596e7801d59Ssowmini } 2597e7801d59Ssowmini 25986be03d0bSVasumathi Sundaram - Sun Microsystems state.ls_parseable = p_arg; 25996be03d0bSVasumathi Sundaram - Sun Microsystems state.ls_flags = flags; 26006be03d0bSVasumathi Sundaram - Sun Microsystems state.ls_donefirst = B_FALSE; 26016be03d0bSVasumathi Sundaram - Sun Microsystems 26026be03d0bSVasumathi Sundaram - Sun Microsystems if (s_arg) { 26036be03d0bSVasumathi Sundaram - Sun Microsystems link_stats(linkid, interval, fields_str, &state); 26046be03d0bSVasumathi Sundaram - Sun Microsystems return; 26056be03d0bSVasumathi Sundaram - Sun Microsystems } 26066be03d0bSVasumathi Sundaram - Sun Microsystems 2607e7801d59Ssowmini 2608e7801d59Ssowmini fields = parse_output_fields(fields_str, link_fields, DEV_LINK_FIELDS, 2609e7801d59Ssowmini CMD_TYPE_ANY, &nfields); 2610e7801d59Ssowmini 26110d365605Sschuster if (fields == NULL) 2612e7801d59Ssowmini die("invalid field(s) specified"); 2613e7801d59Ssowmini 2614e7801d59Ssowmini state.ls_print.ps_fields = fields; 2615e7801d59Ssowmini state.ls_print.ps_nfields = nfields; 2616e7801d59Ssowmini 2617d62bc4baSyz147064 if (linkid == DATALINK_ALL_LINKID) { 2618d62bc4baSyz147064 (void) dladm_walk_datalink_id(show_link, &state, 2619d62bc4baSyz147064 DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE, flags); 2620210db224Sericheng } else { 2621d62bc4baSyz147064 (void) show_link(linkid, &state); 2622d62bc4baSyz147064 if (state.ls_status != DLADM_STATUS_OK) { 2623d62bc4baSyz147064 die_dlerr(state.ls_status, "failed to show link %s", 2624d62bc4baSyz147064 argv[optind]); 2625d62bc4baSyz147064 } 26267c478bd9Sstevel@tonic-gate } 2627210db224Sericheng } 26287c478bd9Sstevel@tonic-gate 26297c478bd9Sstevel@tonic-gate static void 26308d5c46e6Sam223141 do_show_aggr(int argc, char *argv[], const char *use) 26317c478bd9Sstevel@tonic-gate { 26327c478bd9Sstevel@tonic-gate boolean_t L_arg = B_FALSE; 26337c478bd9Sstevel@tonic-gate boolean_t s_arg = B_FALSE; 26347c478bd9Sstevel@tonic-gate boolean_t i_arg = B_FALSE; 2635d62bc4baSyz147064 boolean_t p_arg = B_FALSE; 2636d62bc4baSyz147064 boolean_t x_arg = B_FALSE; 26377c478bd9Sstevel@tonic-gate show_grp_state_t state; 2638d62bc4baSyz147064 uint32_t flags = DLADM_OPT_ACTIVE; 2639d62bc4baSyz147064 datalink_id_t linkid = DATALINK_ALL_LINKID; 2640d62bc4baSyz147064 int option; 264133343a97Smeem int interval = 0; 2642d62bc4baSyz147064 int key; 2643d62bc4baSyz147064 dladm_status_t status; 2644e7801d59Ssowmini boolean_t o_arg = B_FALSE; 2645e7801d59Ssowmini char *fields_str = NULL; 2646e7801d59Ssowmini print_field_t **fields; 2647e7801d59Ssowmini uint_t nfields; 2648e7801d59Ssowmini char *all_fields = 2649e7801d59Ssowmini "link,policy,addrpolicy,lacpactivity,lacptimer,flags"; 2650e7801d59Ssowmini char *all_lacp_fields = 2651e7801d59Ssowmini "link,port,aggregatable,sync,coll,dist,defaulted,expired"; 2652e7801d59Ssowmini char *all_stats_fields = 2653e7801d59Ssowmini "link,port,ipackets,rbytes,opackets,obytes,ipktdist,opktdist"; 2654e7801d59Ssowmini char *all_extended_fields = 2655e7801d59Ssowmini "link,port,speed,duplex,state,address,portstate"; 2656e7801d59Ssowmini print_field_t *pf; 2657e7801d59Ssowmini int pfmax; 2658e7801d59Ssowmini 2659e7801d59Ssowmini bzero(&state, sizeof (state)); 26607c478bd9Sstevel@tonic-gate 26617c478bd9Sstevel@tonic-gate opterr = 0; 2662e7801d59Ssowmini while ((option = getopt_long(argc, argv, ":LpPxsi:o:", 2663d62bc4baSyz147064 show_lopts, NULL)) != -1) { 26647c478bd9Sstevel@tonic-gate switch (option) { 26657c478bd9Sstevel@tonic-gate case 'L': 266633343a97Smeem if (L_arg) 266733343a97Smeem die_optdup(option); 26687c478bd9Sstevel@tonic-gate 26697c478bd9Sstevel@tonic-gate L_arg = B_TRUE; 26707c478bd9Sstevel@tonic-gate break; 26717c478bd9Sstevel@tonic-gate case 'p': 2672d62bc4baSyz147064 if (p_arg) 2673d62bc4baSyz147064 die_optdup(option); 2674d62bc4baSyz147064 2675d62bc4baSyz147064 p_arg = B_TRUE; 2676d62bc4baSyz147064 break; 2677d62bc4baSyz147064 case 'x': 2678d62bc4baSyz147064 if (x_arg) 2679d62bc4baSyz147064 die_optdup(option); 2680d62bc4baSyz147064 2681d62bc4baSyz147064 x_arg = B_TRUE; 2682d62bc4baSyz147064 break; 2683d62bc4baSyz147064 case 'P': 2684d62bc4baSyz147064 if (flags != DLADM_OPT_ACTIVE) 2685d62bc4baSyz147064 die_optdup(option); 2686d62bc4baSyz147064 2687d62bc4baSyz147064 flags = DLADM_OPT_PERSIST; 26887c478bd9Sstevel@tonic-gate break; 26897c478bd9Sstevel@tonic-gate case 's': 269033343a97Smeem if (s_arg) 269133343a97Smeem die_optdup(option); 26927c478bd9Sstevel@tonic-gate 26937c478bd9Sstevel@tonic-gate s_arg = B_TRUE; 26947c478bd9Sstevel@tonic-gate break; 2695e7801d59Ssowmini case 'o': 2696e7801d59Ssowmini o_arg = B_TRUE; 2697e7801d59Ssowmini fields_str = optarg; 2698e7801d59Ssowmini break; 26997c478bd9Sstevel@tonic-gate case 'i': 270033343a97Smeem if (i_arg) 270133343a97Smeem die_optdup(option); 27027c478bd9Sstevel@tonic-gate 27037c478bd9Sstevel@tonic-gate i_arg = B_TRUE; 270433343a97Smeem if (!str2int(optarg, &interval) || interval == 0) 270533343a97Smeem die("invalid interval value '%s'", optarg); 27067c478bd9Sstevel@tonic-gate break; 27077c478bd9Sstevel@tonic-gate default: 27088d5c46e6Sam223141 die_opterr(optopt, option, use); 270933343a97Smeem break; 27107c478bd9Sstevel@tonic-gate } 27117c478bd9Sstevel@tonic-gate } 27127c478bd9Sstevel@tonic-gate 27130d365605Sschuster if (p_arg && !o_arg) 27140d365605Sschuster die("-p requires -o"); 27150d365605Sschuster 27160d365605Sschuster if (p_arg && strcasecmp(fields_str, "all") == 0) 27170d365605Sschuster die("\"-o all\" is invalid with -p"); 27180d365605Sschuster 271933343a97Smeem if (i_arg && !s_arg) 272033343a97Smeem die("the option -i can be used only with -s"); 27217c478bd9Sstevel@tonic-gate 2722d62bc4baSyz147064 if (s_arg && (L_arg || p_arg || x_arg || flags != DLADM_OPT_ACTIVE)) { 2723d62bc4baSyz147064 die("the option -%c cannot be used with -s", 2724d62bc4baSyz147064 L_arg ? 'L' : (p_arg ? 'p' : (x_arg ? 'x' : 'P'))); 2725d62bc4baSyz147064 } 2726d62bc4baSyz147064 2727d62bc4baSyz147064 if (L_arg && flags != DLADM_OPT_ACTIVE) 2728d62bc4baSyz147064 die("the option -P cannot be used with -L"); 2729d62bc4baSyz147064 2730d62bc4baSyz147064 if (x_arg && (L_arg || flags != DLADM_OPT_ACTIVE)) 2731d62bc4baSyz147064 die("the option -%c cannot be used with -x", L_arg ? 'L' : 'P'); 2732d62bc4baSyz147064 2733d62bc4baSyz147064 /* get aggregation key or aggrname (optional last argument) */ 27347c478bd9Sstevel@tonic-gate if (optind == (argc-1)) { 2735d62bc4baSyz147064 if (!str2int(argv[optind], &key)) { 2736d62bc4baSyz147064 status = dladm_name2info(argv[optind], &linkid, NULL, 2737d62bc4baSyz147064 NULL, NULL); 2738d62bc4baSyz147064 } else { 2739d62bc4baSyz147064 status = dladm_key2linkid((uint16_t)key, 2740d62bc4baSyz147064 &linkid, DLADM_OPT_ACTIVE); 2741d62bc4baSyz147064 } 2742d62bc4baSyz147064 2743d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 2744d62bc4baSyz147064 die("non-existent aggregation '%s'", argv[optind]); 2745d62bc4baSyz147064 27467c478bd9Sstevel@tonic-gate } else if (optind != argc) { 27477c478bd9Sstevel@tonic-gate usage(); 27487c478bd9Sstevel@tonic-gate } 27497c478bd9Sstevel@tonic-gate 2750d62bc4baSyz147064 bzero(&state, sizeof (state)); 2751d62bc4baSyz147064 state.gs_lacp = L_arg; 2752d62bc4baSyz147064 state.gs_stats = s_arg; 2753d62bc4baSyz147064 state.gs_flags = flags; 2754d62bc4baSyz147064 state.gs_parseable = p_arg; 2755d62bc4baSyz147064 state.gs_extended = x_arg; 2756d62bc4baSyz147064 2757e7801d59Ssowmini if (!o_arg || (o_arg && strcasecmp(fields_str, "all") == 0)) { 2758e7801d59Ssowmini if (state.gs_lacp) 2759e7801d59Ssowmini fields_str = all_lacp_fields; 2760e7801d59Ssowmini else if (state.gs_stats) 2761e7801d59Ssowmini fields_str = all_stats_fields; 2762e7801d59Ssowmini else if (state.gs_extended) 2763e7801d59Ssowmini fields_str = all_extended_fields; 2764e7801d59Ssowmini else 2765e7801d59Ssowmini fields_str = all_fields; 2766e7801d59Ssowmini } 2767e7801d59Ssowmini 2768e7801d59Ssowmini if (state.gs_lacp) { 2769e7801d59Ssowmini pf = aggr_l_fields; 2770e7801d59Ssowmini pfmax = AGGR_L_MAX_FIELDS; 2771e7801d59Ssowmini } else if (state.gs_stats) { 2772e7801d59Ssowmini pf = aggr_s_fields; 2773e7801d59Ssowmini pfmax = AGGR_S_MAX_FIELDS; 2774e7801d59Ssowmini } else if (state.gs_extended) { 2775e7801d59Ssowmini pf = aggr_x_fields; 2776e7801d59Ssowmini pfmax = AGGR_X_MAX_FIELDS; 2777e7801d59Ssowmini } else { 2778e7801d59Ssowmini pf = laggr_fields; 2779e7801d59Ssowmini pfmax = LAGGR_MAX_FIELDS; 2780e7801d59Ssowmini } 2781e7801d59Ssowmini fields = parse_output_fields(fields_str, pf, pfmax, CMD_TYPE_ANY, 2782e7801d59Ssowmini &nfields); 2783e7801d59Ssowmini 2784e7801d59Ssowmini if (fields == NULL) { 2785e7801d59Ssowmini die("invalid field(s) specified"); 2786e7801d59Ssowmini return; 2787e7801d59Ssowmini } 2788e7801d59Ssowmini 2789e7801d59Ssowmini state.gs_print.ps_fields = fields; 2790e7801d59Ssowmini state.gs_print.ps_nfields = nfields; 2791e7801d59Ssowmini 27927c478bd9Sstevel@tonic-gate if (s_arg) { 2793d62bc4baSyz147064 aggr_stats(linkid, &state, interval); 27947c478bd9Sstevel@tonic-gate return; 27957c478bd9Sstevel@tonic-gate } 27967c478bd9Sstevel@tonic-gate 2797d62bc4baSyz147064 if (linkid == DATALINK_ALL_LINKID) { 2798d62bc4baSyz147064 (void) dladm_walk_datalink_id(show_aggr, &state, 2799d62bc4baSyz147064 DATALINK_CLASS_AGGR, DATALINK_ANY_MEDIATYPE, flags); 2800d62bc4baSyz147064 } else { 2801d62bc4baSyz147064 (void) show_aggr(linkid, &state); 2802d62bc4baSyz147064 if (state.gs_status != DLADM_STATUS_OK) { 2803d62bc4baSyz147064 die_dlerr(state.gs_status, "failed to show aggr %s", 2804d62bc4baSyz147064 argv[optind]); 2805d62bc4baSyz147064 } 2806d62bc4baSyz147064 } 28077c478bd9Sstevel@tonic-gate } 28087c478bd9Sstevel@tonic-gate 28097c478bd9Sstevel@tonic-gate static void 28108d5c46e6Sam223141 do_show_dev(int argc, char *argv[], const char *use) 28117c478bd9Sstevel@tonic-gate { 28127c478bd9Sstevel@tonic-gate int option; 28137c478bd9Sstevel@tonic-gate char *dev = NULL; 28147c478bd9Sstevel@tonic-gate boolean_t s_arg = B_FALSE; 28157c478bd9Sstevel@tonic-gate boolean_t i_arg = B_FALSE; 2816e7801d59Ssowmini boolean_t o_arg = B_FALSE; 2817d62bc4baSyz147064 boolean_t p_arg = B_FALSE; 2818d62bc4baSyz147064 datalink_id_t linkid; 281933343a97Smeem int interval = 0; 2820d62bc4baSyz147064 show_state_t state; 2821e7801d59Ssowmini char *fields_str = NULL; 2822e7801d59Ssowmini print_field_t **fields; 2823e7801d59Ssowmini uint_t nfields; 2824e7801d59Ssowmini char *all_fields = "link,state,speed,duplex"; 2825e7801d59Ssowmini static char *allstat_fields = 2826e7801d59Ssowmini "link,ipackets,rbytes,ierrors,opackets,obytes,oerrors"; 2827e7801d59Ssowmini 2828e7801d59Ssowmini bzero(&state, sizeof (state)); 2829e7801d59Ssowmini fields_str = all_fields; 28307c478bd9Sstevel@tonic-gate 28317c478bd9Sstevel@tonic-gate opterr = 0; 2832e7801d59Ssowmini while ((option = getopt_long(argc, argv, ":psi:o:", 2833d62bc4baSyz147064 show_lopts, NULL)) != -1) { 28347c478bd9Sstevel@tonic-gate switch (option) { 28357c478bd9Sstevel@tonic-gate case 'p': 2836d62bc4baSyz147064 if (p_arg) 2837d62bc4baSyz147064 die_optdup(option); 2838d62bc4baSyz147064 2839d62bc4baSyz147064 p_arg = B_TRUE; 28407c478bd9Sstevel@tonic-gate break; 28417c478bd9Sstevel@tonic-gate case 's': 284233343a97Smeem if (s_arg) 284333343a97Smeem die_optdup(option); 28447c478bd9Sstevel@tonic-gate 28457c478bd9Sstevel@tonic-gate s_arg = B_TRUE; 28467c478bd9Sstevel@tonic-gate break; 2847e7801d59Ssowmini case 'o': 2848e7801d59Ssowmini o_arg = B_TRUE; 2849e7801d59Ssowmini fields_str = optarg; 2850e7801d59Ssowmini break; 28517c478bd9Sstevel@tonic-gate case 'i': 285233343a97Smeem if (i_arg) 285333343a97Smeem die_optdup(option); 28547c478bd9Sstevel@tonic-gate 28557c478bd9Sstevel@tonic-gate i_arg = B_TRUE; 285633343a97Smeem if (!str2int(optarg, &interval) || interval == 0) 285733343a97Smeem die("invalid interval value '%s'", optarg); 28587c478bd9Sstevel@tonic-gate break; 28597c478bd9Sstevel@tonic-gate default: 28608d5c46e6Sam223141 die_opterr(optopt, option, use); 286133343a97Smeem break; 28627c478bd9Sstevel@tonic-gate } 28637c478bd9Sstevel@tonic-gate } 28647c478bd9Sstevel@tonic-gate 28650d365605Sschuster if (p_arg && !o_arg) 28660d365605Sschuster die("-p requires -o"); 28670d365605Sschuster 28680d365605Sschuster if (p_arg && strcasecmp(fields_str, "all") == 0) 28690d365605Sschuster die("\"-o all\" is invalid with -p"); 28700d365605Sschuster 287133343a97Smeem if (i_arg && !s_arg) 287233343a97Smeem die("the option -i can be used only with -s"); 28737c478bd9Sstevel@tonic-gate 2874e7801d59Ssowmini if (o_arg && strcasecmp(fields_str, "all") == 0) { 2875e7801d59Ssowmini if (!s_arg) 2876e7801d59Ssowmini fields_str = all_fields; 2877e7801d59Ssowmini else 2878e7801d59Ssowmini fields_str = allstat_fields; 2879e7801d59Ssowmini } 2880e7801d59Ssowmini 2881e7801d59Ssowmini if (!o_arg && s_arg) 2882e7801d59Ssowmini fields_str = allstat_fields; 2883e7801d59Ssowmini 2884d62bc4baSyz147064 if (s_arg && p_arg) 2885d62bc4baSyz147064 die("the option -s cannot be used with -p"); 2886d62bc4baSyz147064 28877c478bd9Sstevel@tonic-gate /* get dev name (optional last argument) */ 2888d62bc4baSyz147064 if (optind == (argc-1)) { 2889d62bc4baSyz147064 uint32_t flags; 2890d62bc4baSyz147064 28917c478bd9Sstevel@tonic-gate dev = argv[optind]; 2892d62bc4baSyz147064 2893d62bc4baSyz147064 if (dladm_dev2linkid(dev, &linkid) != DLADM_STATUS_OK) 2894d62bc4baSyz147064 die("invalid device %s", dev); 2895d62bc4baSyz147064 2896d62bc4baSyz147064 if ((dladm_datalink_id2info(linkid, &flags, NULL, NULL, 2897d62bc4baSyz147064 NULL, 0) != DLADM_STATUS_OK) || 2898d62bc4baSyz147064 !(flags & DLADM_OPT_ACTIVE)) { 2899d62bc4baSyz147064 die("device %s has been removed", dev); 2900d62bc4baSyz147064 } 2901d62bc4baSyz147064 } else if (optind != argc) { 29027c478bd9Sstevel@tonic-gate usage(); 2903cd93090eSericheng } 29047c478bd9Sstevel@tonic-gate 2905e7801d59Ssowmini state.ls_parseable = p_arg; 2906e7801d59Ssowmini state.ls_donefirst = B_FALSE; 2907e7801d59Ssowmini 29087c478bd9Sstevel@tonic-gate if (s_arg) { 2909e7801d59Ssowmini dev_stats(dev, interval, fields_str, &state); 29107c478bd9Sstevel@tonic-gate return; 29117c478bd9Sstevel@tonic-gate } 29127c478bd9Sstevel@tonic-gate 2913e7801d59Ssowmini fields = parse_output_fields(fields_str, dev_fields, DEV_MAX_FIELDS, 2914e7801d59Ssowmini CMD_TYPE_ANY, &nfields); 2915e7801d59Ssowmini 2916e7801d59Ssowmini if (fields == NULL) { 2917e7801d59Ssowmini die("invalid field(s) specified"); 2918e7801d59Ssowmini return; 2919e7801d59Ssowmini } 2920e7801d59Ssowmini 2921e7801d59Ssowmini state.ls_print.ps_fields = fields; 2922e7801d59Ssowmini state.ls_print.ps_nfields = nfields; 2923e7801d59Ssowmini 2924d62bc4baSyz147064 if (dev == NULL) { 2925f595a68aSyz147064 (void) dladm_mac_walk(show_dev, &state); 2926d62bc4baSyz147064 } else { 2927d62bc4baSyz147064 (void) show_dev(dev, &state); 2928d62bc4baSyz147064 } 29297c478bd9Sstevel@tonic-gate } 29307c478bd9Sstevel@tonic-gate 2931d62bc4baSyz147064 2932d62bc4baSyz147064 static dladm_status_t 2933e7801d59Ssowmini print_phys(show_state_t *state, datalink_id_t linkid, link_fields_buf_t *pattr) 2934d62bc4baSyz147064 { 2935d62bc4baSyz147064 char link[MAXLINKNAMELEN]; 2936d62bc4baSyz147064 dladm_phys_attr_t dpa; 2937d62bc4baSyz147064 uint32_t flags; 2938d62bc4baSyz147064 datalink_class_t class; 2939d62bc4baSyz147064 uint32_t media; 2940d62bc4baSyz147064 dladm_status_t status; 2941d62bc4baSyz147064 2942d62bc4baSyz147064 if ((status = dladm_datalink_id2info(linkid, &flags, &class, &media, 2943e7801d59Ssowmini link, MAXLINKNAMELEN)) != DLADM_STATUS_OK) { 2944d62bc4baSyz147064 goto done; 2945d62bc4baSyz147064 } 2946d62bc4baSyz147064 2947d62bc4baSyz147064 if (class != DATALINK_CLASS_PHYS) { 2948d62bc4baSyz147064 status = DLADM_STATUS_BADARG; 2949d62bc4baSyz147064 goto done; 2950d62bc4baSyz147064 } 2951d62bc4baSyz147064 2952d62bc4baSyz147064 if (!(state->ls_flags & flags)) { 2953d62bc4baSyz147064 status = DLADM_STATUS_NOTFOUND; 2954d62bc4baSyz147064 goto done; 2955d62bc4baSyz147064 } 2956d62bc4baSyz147064 2957d62bc4baSyz147064 status = dladm_phys_info(linkid, &dpa, state->ls_flags); 2958d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 2959d62bc4baSyz147064 goto done; 2960d62bc4baSyz147064 2961e7801d59Ssowmini (void) snprintf(pattr->link_phys_device, 2962e7801d59Ssowmini sizeof (pattr->link_phys_device), "%s", dpa.dp_dev); 2963e7801d59Ssowmini (void) dladm_media2str(media, pattr->link_phys_media); 2964d62bc4baSyz147064 if (state->ls_flags == DLADM_OPT_ACTIVE) { 2965d62bc4baSyz147064 boolean_t islink; 2966d62bc4baSyz147064 2967d62bc4baSyz147064 if (!dpa.dp_novanity) { 2968e7801d59Ssowmini (void) strlcpy(pattr->link_name, link, 2969e7801d59Ssowmini sizeof (pattr->link_name)); 2970d62bc4baSyz147064 islink = B_TRUE; 2971d62bc4baSyz147064 } else { 2972d62bc4baSyz147064 /* 2973d62bc4baSyz147064 * This is a physical link that does not have 2974d62bc4baSyz147064 * vanity naming support. 2975d62bc4baSyz147064 */ 2976e7801d59Ssowmini (void) strlcpy(pattr->link_name, dpa.dp_dev, 2977e7801d59Ssowmini sizeof (pattr->link_name)); 2978d62bc4baSyz147064 islink = B_FALSE; 2979d62bc4baSyz147064 } 2980d62bc4baSyz147064 2981e7801d59Ssowmini (void) get_linkstate(pattr->link_name, islink, 2982e7801d59Ssowmini pattr->link_phys_state); 2983e7801d59Ssowmini (void) snprintf(pattr->link_phys_speed, 2984e7801d59Ssowmini sizeof (pattr->link_phys_speed), "%u", 2985e7801d59Ssowmini (uint_t)((get_ifspeed(pattr->link_name, 2986e7801d59Ssowmini islink)) / 1000000ull)); 2987e7801d59Ssowmini (void) get_linkduplex(pattr->link_name, islink, 2988e7801d59Ssowmini pattr->link_phys_duplex); 2989d62bc4baSyz147064 } else { 2990e7801d59Ssowmini (void) snprintf(pattr->link_name, sizeof (pattr->link_name), 2991e7801d59Ssowmini "%s", link); 2992e7801d59Ssowmini (void) snprintf(pattr->link_flags, sizeof (pattr->link_flags), 2993e7801d59Ssowmini "%c----", flags & DLADM_OPT_ACTIVE ? '-' : 'r'); 2994d62bc4baSyz147064 } 2995d62bc4baSyz147064 2996d62bc4baSyz147064 done: 2997d62bc4baSyz147064 return (status); 2998d62bc4baSyz147064 } 2999d62bc4baSyz147064 3000d62bc4baSyz147064 static int 3001d62bc4baSyz147064 show_phys(datalink_id_t linkid, void *arg) 3002d62bc4baSyz147064 { 3003d62bc4baSyz147064 show_state_t *state = arg; 3004d62bc4baSyz147064 dladm_status_t status; 3005e7801d59Ssowmini link_fields_buf_t pattr; 3006d62bc4baSyz147064 30075f5c9f54SAnurag S. Maskey bzero(&pattr, sizeof (link_fields_buf_t)); 3008e7801d59Ssowmini status = print_phys(state, linkid, &pattr); 3009d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 3010d62bc4baSyz147064 goto done; 3011e7801d59Ssowmini 3012e7801d59Ssowmini if (!state->ls_parseable && !state->ls_printheader) { 3013e7801d59Ssowmini print_header(&state->ls_print); 3014e7801d59Ssowmini state->ls_printheader = B_TRUE; 3015e7801d59Ssowmini } 3016e7801d59Ssowmini 3017e7801d59Ssowmini dladm_print_output(&state->ls_print, state->ls_parseable, 3018e7801d59Ssowmini dladm_print_field, (void *)&pattr); 3019d62bc4baSyz147064 3020d62bc4baSyz147064 done: 3021d62bc4baSyz147064 state->ls_status = status; 3022d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 3023d62bc4baSyz147064 } 3024d62bc4baSyz147064 3025d62bc4baSyz147064 3026d62bc4baSyz147064 /* 3027d62bc4baSyz147064 * Print the active topology information. 3028d62bc4baSyz147064 */ 3029d62bc4baSyz147064 static dladm_status_t 3030e7801d59Ssowmini print_vlan(show_state_t *state, datalink_id_t linkid, link_fields_buf_t *l) 3031d62bc4baSyz147064 { 3032d62bc4baSyz147064 dladm_vlan_attr_t vinfo; 3033d62bc4baSyz147064 uint32_t flags; 3034d62bc4baSyz147064 dladm_status_t status; 3035d62bc4baSyz147064 3036e7801d59Ssowmini if ((status = dladm_datalink_id2info(linkid, &flags, NULL, NULL, 3037e7801d59Ssowmini l->link_name, sizeof (l->link_name))) != DLADM_STATUS_OK) { 3038d62bc4baSyz147064 goto done; 3039d62bc4baSyz147064 } 3040d62bc4baSyz147064 3041d62bc4baSyz147064 if (!(state->ls_flags & flags)) { 3042d62bc4baSyz147064 status = DLADM_STATUS_NOTFOUND; 3043d62bc4baSyz147064 goto done; 3044d62bc4baSyz147064 } 3045d62bc4baSyz147064 3046d62bc4baSyz147064 if ((status = dladm_vlan_info(linkid, &vinfo, state->ls_flags)) != 3047d62bc4baSyz147064 DLADM_STATUS_OK || (status = dladm_datalink_id2info( 3048e7801d59Ssowmini vinfo.dv_linkid, NULL, NULL, NULL, l->link_over, 3049e7801d59Ssowmini sizeof (l->link_over))) != DLADM_STATUS_OK) { 3050d62bc4baSyz147064 goto done; 3051d62bc4baSyz147064 } 3052d62bc4baSyz147064 3053e7801d59Ssowmini (void) snprintf(l->link_vlan_vid, sizeof (l->link_vlan_vid), "%d", 3054e7801d59Ssowmini vinfo.dv_vid); 3055e7801d59Ssowmini (void) snprintf(l->link_flags, sizeof (l->link_flags), "%c%c---", 3056e7801d59Ssowmini vinfo.dv_force ? 'f' : '-', vinfo.dv_implicit ? 'i' : '-'); 3057d62bc4baSyz147064 3058d62bc4baSyz147064 done: 3059d62bc4baSyz147064 return (status); 3060d62bc4baSyz147064 } 3061d62bc4baSyz147064 3062d62bc4baSyz147064 static int 3063d62bc4baSyz147064 show_vlan(datalink_id_t linkid, void *arg) 3064d62bc4baSyz147064 { 3065d62bc4baSyz147064 show_state_t *state = arg; 3066d62bc4baSyz147064 dladm_status_t status; 3067e7801d59Ssowmini link_fields_buf_t lbuf; 3068d62bc4baSyz147064 30695f5c9f54SAnurag S. Maskey bzero(&lbuf, sizeof (link_fields_buf_t)); 3070e7801d59Ssowmini status = print_vlan(state, linkid, &lbuf); 3071d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 3072d62bc4baSyz147064 goto done; 3073e7801d59Ssowmini 3074e7801d59Ssowmini if (!state->ls_parseable && !state->ls_printheader) { 3075e7801d59Ssowmini print_header(&state->ls_print); 3076e7801d59Ssowmini state->ls_printheader = B_TRUE; 3077e7801d59Ssowmini } 3078e7801d59Ssowmini 3079e7801d59Ssowmini dladm_print_output(&state->ls_print, state->ls_parseable, 3080e7801d59Ssowmini dladm_print_field, (void *)&lbuf); 3081d62bc4baSyz147064 3082d62bc4baSyz147064 done: 3083d62bc4baSyz147064 state->ls_status = status; 3084d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 3085d62bc4baSyz147064 } 3086d62bc4baSyz147064 3087d62bc4baSyz147064 static void 30888d5c46e6Sam223141 do_show_phys(int argc, char *argv[], const char *use) 3089d62bc4baSyz147064 { 3090d62bc4baSyz147064 int option; 3091d62bc4baSyz147064 uint32_t flags = DLADM_OPT_ACTIVE; 3092d62bc4baSyz147064 boolean_t p_arg = B_FALSE; 3093e7801d59Ssowmini boolean_t o_arg = B_FALSE; 3094d62bc4baSyz147064 datalink_id_t linkid = DATALINK_ALL_LINKID; 3095d62bc4baSyz147064 show_state_t state; 3096d62bc4baSyz147064 dladm_status_t status; 3097e7801d59Ssowmini char *fields_str = NULL; 3098e7801d59Ssowmini print_field_t **fields; 3099e7801d59Ssowmini uint_t nfields; 3100e7801d59Ssowmini char *all_active_fields = 3101e7801d59Ssowmini "link,media,state,speed,duplex,device"; 31025f5c9f54SAnurag S. Maskey char *all_inactive_fields = "link,device,media,flags"; 3103d62bc4baSyz147064 3104e7801d59Ssowmini bzero(&state, sizeof (state)); 3105d62bc4baSyz147064 opterr = 0; 3106e7801d59Ssowmini while ((option = getopt_long(argc, argv, ":pPo:", 3107d62bc4baSyz147064 show_lopts, NULL)) != -1) { 3108d62bc4baSyz147064 switch (option) { 3109d62bc4baSyz147064 case 'p': 3110d62bc4baSyz147064 if (p_arg) 3111d62bc4baSyz147064 die_optdup(option); 3112d62bc4baSyz147064 3113d62bc4baSyz147064 p_arg = B_TRUE; 3114d62bc4baSyz147064 break; 3115d62bc4baSyz147064 case 'P': 3116d62bc4baSyz147064 if (flags != DLADM_OPT_ACTIVE) 3117d62bc4baSyz147064 die_optdup(option); 3118d62bc4baSyz147064 3119d62bc4baSyz147064 flags = DLADM_OPT_PERSIST; 3120d62bc4baSyz147064 break; 3121e7801d59Ssowmini case 'o': 3122e7801d59Ssowmini o_arg = B_TRUE; 3123e7801d59Ssowmini fields_str = optarg; 3124e7801d59Ssowmini break; 3125d62bc4baSyz147064 default: 31268d5c46e6Sam223141 die_opterr(optopt, option, use); 3127d62bc4baSyz147064 break; 3128d62bc4baSyz147064 } 3129d62bc4baSyz147064 } 3130d62bc4baSyz147064 31310d365605Sschuster if (p_arg && !o_arg) 31320d365605Sschuster die("-p requires -o"); 31330d365605Sschuster 31340d365605Sschuster if (p_arg && strcasecmp(fields_str, "all") == 0) 31350d365605Sschuster die("\"-o all\" is invalid with -p"); 31360d365605Sschuster 3137d62bc4baSyz147064 /* get link name (optional last argument) */ 3138d62bc4baSyz147064 if (optind == (argc-1)) { 3139d62bc4baSyz147064 if ((status = dladm_name2info(argv[optind], &linkid, NULL, 3140d62bc4baSyz147064 NULL, NULL)) != DLADM_STATUS_OK) { 3141d62bc4baSyz147064 die_dlerr(status, "link %s is not valid", argv[optind]); 3142d62bc4baSyz147064 } 3143d62bc4baSyz147064 } else if (optind != argc) { 3144d62bc4baSyz147064 usage(); 3145d62bc4baSyz147064 } 3146d62bc4baSyz147064 3147d62bc4baSyz147064 state.ls_parseable = p_arg; 3148d62bc4baSyz147064 state.ls_flags = flags; 3149d62bc4baSyz147064 state.ls_donefirst = B_FALSE; 3150d62bc4baSyz147064 3151e7801d59Ssowmini if (!o_arg || (o_arg && strcasecmp(fields_str, "all") == 0)) { 3152e7801d59Ssowmini if (state.ls_flags & DLADM_OPT_ACTIVE) 3153e7801d59Ssowmini fields_str = all_active_fields; 3154e7801d59Ssowmini else 3155e7801d59Ssowmini fields_str = all_inactive_fields; 3156e7801d59Ssowmini } 3157e7801d59Ssowmini 3158e7801d59Ssowmini fields = parse_output_fields(fields_str, phys_fields, 3159e7801d59Ssowmini PHYS_MAX_FIELDS, CMD_TYPE_ANY, &nfields); 3160e7801d59Ssowmini 3161e7801d59Ssowmini if (fields == NULL) { 3162e7801d59Ssowmini die("invalid field(s) specified"); 3163e7801d59Ssowmini return; 3164e7801d59Ssowmini } 3165e7801d59Ssowmini 3166e7801d59Ssowmini state.ls_print.ps_fields = fields; 3167e7801d59Ssowmini state.ls_print.ps_nfields = nfields; 3168e7801d59Ssowmini 3169d62bc4baSyz147064 if (linkid == DATALINK_ALL_LINKID) { 3170d62bc4baSyz147064 (void) dladm_walk_datalink_id(show_phys, &state, 3171d62bc4baSyz147064 DATALINK_CLASS_PHYS, DATALINK_ANY_MEDIATYPE, flags); 3172d62bc4baSyz147064 } else { 3173d62bc4baSyz147064 (void) show_phys(linkid, &state); 3174d62bc4baSyz147064 if (state.ls_status != DLADM_STATUS_OK) { 3175d62bc4baSyz147064 die_dlerr(state.ls_status, 3176d62bc4baSyz147064 "failed to show physical link %s", argv[optind]); 3177d62bc4baSyz147064 } 3178d62bc4baSyz147064 } 3179d62bc4baSyz147064 } 3180d62bc4baSyz147064 3181d62bc4baSyz147064 static void 31828d5c46e6Sam223141 do_show_vlan(int argc, char *argv[], const char *use) 3183d62bc4baSyz147064 { 3184d62bc4baSyz147064 int option; 3185d62bc4baSyz147064 uint32_t flags = DLADM_OPT_ACTIVE; 3186d62bc4baSyz147064 boolean_t p_arg = B_FALSE; 3187d62bc4baSyz147064 datalink_id_t linkid = DATALINK_ALL_LINKID; 3188d62bc4baSyz147064 show_state_t state; 3189d62bc4baSyz147064 dladm_status_t status; 3190e7801d59Ssowmini boolean_t o_arg = B_FALSE; 3191e7801d59Ssowmini char *fields_str = NULL; 3192e7801d59Ssowmini print_field_t **fields; 3193e7801d59Ssowmini uint_t nfields; 3194e7801d59Ssowmini char *all_fields = "link,vid,over,flags"; 3195e7801d59Ssowmini 3196e7801d59Ssowmini bzero(&state, sizeof (state)); 3197d62bc4baSyz147064 3198d62bc4baSyz147064 opterr = 0; 3199e7801d59Ssowmini while ((option = getopt_long(argc, argv, ":pPo:", 3200d62bc4baSyz147064 show_lopts, NULL)) != -1) { 3201d62bc4baSyz147064 switch (option) { 3202d62bc4baSyz147064 case 'p': 3203d62bc4baSyz147064 if (p_arg) 3204d62bc4baSyz147064 die_optdup(option); 3205d62bc4baSyz147064 3206d62bc4baSyz147064 p_arg = B_TRUE; 3207d62bc4baSyz147064 break; 3208d62bc4baSyz147064 case 'P': 3209d62bc4baSyz147064 if (flags != DLADM_OPT_ACTIVE) 3210d62bc4baSyz147064 die_optdup(option); 3211d62bc4baSyz147064 3212d62bc4baSyz147064 flags = DLADM_OPT_PERSIST; 3213d62bc4baSyz147064 break; 3214e7801d59Ssowmini case 'o': 3215e7801d59Ssowmini o_arg = B_TRUE; 3216e7801d59Ssowmini fields_str = optarg; 3217e7801d59Ssowmini break; 3218d62bc4baSyz147064 default: 32198d5c46e6Sam223141 die_opterr(optopt, option, use); 3220d62bc4baSyz147064 break; 3221d62bc4baSyz147064 } 3222d62bc4baSyz147064 } 3223d62bc4baSyz147064 32240d365605Sschuster if (p_arg && !o_arg) 32250d365605Sschuster die("-p requires -o"); 32260d365605Sschuster 32270d365605Sschuster if (p_arg && strcasecmp(fields_str, "all") == 0) 32280d365605Sschuster die("\"-o all\" is invalid with -p"); 32290d365605Sschuster 3230d62bc4baSyz147064 /* get link name (optional last argument) */ 3231d62bc4baSyz147064 if (optind == (argc-1)) { 3232d62bc4baSyz147064 if ((status = dladm_name2info(argv[optind], &linkid, NULL, 3233d62bc4baSyz147064 NULL, NULL)) != DLADM_STATUS_OK) { 3234d62bc4baSyz147064 die_dlerr(status, "link %s is not valid", argv[optind]); 3235d62bc4baSyz147064 } 3236d62bc4baSyz147064 } else if (optind != argc) { 3237d62bc4baSyz147064 usage(); 3238d62bc4baSyz147064 } 3239d62bc4baSyz147064 3240d62bc4baSyz147064 state.ls_parseable = p_arg; 3241d62bc4baSyz147064 state.ls_flags = flags; 3242d62bc4baSyz147064 state.ls_donefirst = B_FALSE; 3243d62bc4baSyz147064 3244e7801d59Ssowmini if (!o_arg || (o_arg && strcasecmp(fields_str, "all") == 0)) 3245e7801d59Ssowmini fields_str = all_fields; 3246e7801d59Ssowmini 3247e7801d59Ssowmini fields = parse_output_fields(fields_str, vlan_fields, VLAN_MAX_FIELDS, 3248e7801d59Ssowmini CMD_TYPE_ANY, &nfields); 3249e7801d59Ssowmini 3250e7801d59Ssowmini if (fields == NULL) { 3251e7801d59Ssowmini die("invalid field(s) specified"); 3252e7801d59Ssowmini return; 3253e7801d59Ssowmini } 3254e7801d59Ssowmini state.ls_print.ps_fields = fields; 3255e7801d59Ssowmini state.ls_print.ps_nfields = nfields; 3256e7801d59Ssowmini 3257d62bc4baSyz147064 if (linkid == DATALINK_ALL_LINKID) { 3258d62bc4baSyz147064 (void) dladm_walk_datalink_id(show_vlan, &state, 3259d62bc4baSyz147064 DATALINK_CLASS_VLAN, DATALINK_ANY_MEDIATYPE, flags); 3260d62bc4baSyz147064 } else { 3261d62bc4baSyz147064 (void) show_vlan(linkid, &state); 3262d62bc4baSyz147064 if (state.ls_status != DLADM_STATUS_OK) { 3263d62bc4baSyz147064 die_dlerr(state.ls_status, "failed to show vlan %s", 3264d62bc4baSyz147064 argv[optind]); 3265d62bc4baSyz147064 } 3266d62bc4baSyz147064 } 3267d62bc4baSyz147064 } 3268d62bc4baSyz147064 3269d62bc4baSyz147064 static void 32706be03d0bSVasumathi Sundaram - Sun Microsystems link_stats(datalink_id_t linkid, uint_t interval, char *fields_str, 32716be03d0bSVasumathi Sundaram - Sun Microsystems show_state_t *state) 3272d62bc4baSyz147064 { 32736be03d0bSVasumathi Sundaram - Sun Microsystems print_field_t **fields; 32746be03d0bSVasumathi Sundaram - Sun Microsystems uint_t nfields; 327533343a97Smeem 32766be03d0bSVasumathi Sundaram - Sun Microsystems fields = parse_output_fields(fields_str, devs_fields, DEVS_MAX_FIELDS, 32776be03d0bSVasumathi Sundaram - Sun Microsystems CMD_TYPE_ANY, &nfields); 32786be03d0bSVasumathi Sundaram - Sun Microsystems if (fields == NULL) { 32796be03d0bSVasumathi Sundaram - Sun Microsystems die("invalid field(s) specified"); 32806be03d0bSVasumathi Sundaram - Sun Microsystems return; 32816be03d0bSVasumathi Sundaram - Sun Microsystems } 32826be03d0bSVasumathi Sundaram - Sun Microsystems 32836be03d0bSVasumathi Sundaram - Sun Microsystems state->ls_print.ps_fields = fields; 32846be03d0bSVasumathi Sundaram - Sun Microsystems state->ls_print.ps_nfields = nfields; 32857c478bd9Sstevel@tonic-gate 32867c478bd9Sstevel@tonic-gate /* 32877c478bd9Sstevel@tonic-gate * If an interval is specified, continuously show the stats 32887c478bd9Sstevel@tonic-gate * only for the first MAC port. 32897c478bd9Sstevel@tonic-gate */ 32906be03d0bSVasumathi Sundaram - Sun Microsystems state->ls_firstonly = (interval != 0); 32917c478bd9Sstevel@tonic-gate 32926be03d0bSVasumathi Sundaram - Sun Microsystems if (!state->ls_parseable) 32936be03d0bSVasumathi Sundaram - Sun Microsystems print_header(&state->ls_print); 32947c478bd9Sstevel@tonic-gate for (;;) { 32956be03d0bSVasumathi Sundaram - Sun Microsystems state->ls_donefirst = B_FALSE; 3296d62bc4baSyz147064 if (linkid == DATALINK_ALL_LINKID) { 32976be03d0bSVasumathi Sundaram - Sun Microsystems (void) dladm_walk_datalink_id(show_link_stats, state, 3298d62bc4baSyz147064 DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE, 3299d62bc4baSyz147064 DLADM_OPT_ACTIVE); 3300d62bc4baSyz147064 } else { 33016be03d0bSVasumathi Sundaram - Sun Microsystems (void) show_link_stats(linkid, state); 3302d62bc4baSyz147064 } 33037c478bd9Sstevel@tonic-gate 33047c478bd9Sstevel@tonic-gate if (interval == 0) 33057c478bd9Sstevel@tonic-gate break; 33067c478bd9Sstevel@tonic-gate 33077c478bd9Sstevel@tonic-gate (void) sleep(interval); 33087c478bd9Sstevel@tonic-gate } 33097c478bd9Sstevel@tonic-gate } 33107c478bd9Sstevel@tonic-gate 33117c478bd9Sstevel@tonic-gate static void 3312d62bc4baSyz147064 aggr_stats(datalink_id_t linkid, show_grp_state_t *state, uint_t interval) 33137c478bd9Sstevel@tonic-gate { 33147c478bd9Sstevel@tonic-gate /* 33157c478bd9Sstevel@tonic-gate * If an interval is specified, continuously show the stats 33167c478bd9Sstevel@tonic-gate * only for the first group. 33177c478bd9Sstevel@tonic-gate */ 3318d62bc4baSyz147064 state->gs_firstonly = (interval != 0); 33197c478bd9Sstevel@tonic-gate 33207c478bd9Sstevel@tonic-gate for (;;) { 3321d62bc4baSyz147064 state->gs_donefirst = B_FALSE; 3322d62bc4baSyz147064 if (linkid == DATALINK_ALL_LINKID) 3323d62bc4baSyz147064 (void) dladm_walk_datalink_id(show_aggr, state, 3324d62bc4baSyz147064 DATALINK_CLASS_AGGR, DATALINK_ANY_MEDIATYPE, 3325d62bc4baSyz147064 DLADM_OPT_ACTIVE); 3326d62bc4baSyz147064 else 3327d62bc4baSyz147064 (void) show_aggr(linkid, state); 33287c478bd9Sstevel@tonic-gate 33297c478bd9Sstevel@tonic-gate if (interval == 0) 33307c478bd9Sstevel@tonic-gate break; 33317c478bd9Sstevel@tonic-gate 33327c478bd9Sstevel@tonic-gate (void) sleep(interval); 33337c478bd9Sstevel@tonic-gate } 33347c478bd9Sstevel@tonic-gate } 33357c478bd9Sstevel@tonic-gate 33367c478bd9Sstevel@tonic-gate static void 3337e7801d59Ssowmini dev_stats(const char *dev, uint32_t interval, char *fields_str, 3338e7801d59Ssowmini show_state_t *state) 33397c478bd9Sstevel@tonic-gate { 3340e7801d59Ssowmini print_field_t **fields; 3341e7801d59Ssowmini uint_t nfields; 33427c478bd9Sstevel@tonic-gate 3343e7801d59Ssowmini fields = parse_output_fields(fields_str, devs_fields, DEVS_MAX_FIELDS, 3344e7801d59Ssowmini CMD_TYPE_ANY, &nfields); 3345e7801d59Ssowmini 3346e7801d59Ssowmini if (fields == NULL) { 3347e7801d59Ssowmini die("invalid field(s) specified"); 3348e7801d59Ssowmini return; 3349e7801d59Ssowmini } 3350e7801d59Ssowmini 3351e7801d59Ssowmini state->ls_print.ps_fields = fields; 3352e7801d59Ssowmini state->ls_print.ps_nfields = nfields; 3353e7801d59Ssowmini 33547c478bd9Sstevel@tonic-gate 33557c478bd9Sstevel@tonic-gate /* 33567c478bd9Sstevel@tonic-gate * If an interval is specified, continuously show the stats 33577c478bd9Sstevel@tonic-gate * only for the first MAC port. 33587c478bd9Sstevel@tonic-gate */ 3359e7801d59Ssowmini state->ls_firstonly = (interval != 0); 33607c478bd9Sstevel@tonic-gate 33617c478bd9Sstevel@tonic-gate for (;;) { 33627c478bd9Sstevel@tonic-gate 3363e7801d59Ssowmini if (!state->ls_parseable) 3364e7801d59Ssowmini print_header(&state->ls_print); 3365e7801d59Ssowmini state->ls_donefirst = B_FALSE; 33667c478bd9Sstevel@tonic-gate 3367210db224Sericheng if (dev == NULL) 3368e7801d59Ssowmini (void) dladm_mac_walk(show_dev_stats, state); 3369210db224Sericheng else 3370e7801d59Ssowmini (void) show_dev_stats(dev, state); 33717c478bd9Sstevel@tonic-gate 33727c478bd9Sstevel@tonic-gate if (interval == 0) 33737c478bd9Sstevel@tonic-gate break; 33747c478bd9Sstevel@tonic-gate 33757c478bd9Sstevel@tonic-gate (void) sleep(interval); 33767c478bd9Sstevel@tonic-gate } 3377d62bc4baSyz147064 3378e7801d59Ssowmini if (dev != NULL && state->ls_status != DLADM_STATUS_OK) 3379e7801d59Ssowmini die_dlerr(state->ls_status, "cannot show device '%s'", dev); 33807c478bd9Sstevel@tonic-gate } 33817c478bd9Sstevel@tonic-gate 33827c478bd9Sstevel@tonic-gate /* accumulate stats (s1 += (s2 - s3)) */ 33837c478bd9Sstevel@tonic-gate static void 33847c478bd9Sstevel@tonic-gate stats_total(pktsum_t *s1, pktsum_t *s2, pktsum_t *s3) 33857c478bd9Sstevel@tonic-gate { 33867c478bd9Sstevel@tonic-gate s1->ipackets += (s2->ipackets - s3->ipackets); 33877c478bd9Sstevel@tonic-gate s1->opackets += (s2->opackets - s3->opackets); 33887c478bd9Sstevel@tonic-gate s1->rbytes += (s2->rbytes - s3->rbytes); 33897c478bd9Sstevel@tonic-gate s1->obytes += (s2->obytes - s3->obytes); 33907c478bd9Sstevel@tonic-gate s1->ierrors += (s2->ierrors - s3->ierrors); 33917c478bd9Sstevel@tonic-gate s1->oerrors += (s2->oerrors - s3->oerrors); 33927c478bd9Sstevel@tonic-gate } 33937c478bd9Sstevel@tonic-gate 33947c478bd9Sstevel@tonic-gate /* compute stats differences (s1 = s2 - s3) */ 33957c478bd9Sstevel@tonic-gate static void 33967c478bd9Sstevel@tonic-gate stats_diff(pktsum_t *s1, pktsum_t *s2, pktsum_t *s3) 33977c478bd9Sstevel@tonic-gate { 33987c478bd9Sstevel@tonic-gate s1->ipackets = s2->ipackets - s3->ipackets; 33997c478bd9Sstevel@tonic-gate s1->opackets = s2->opackets - s3->opackets; 34007c478bd9Sstevel@tonic-gate s1->rbytes = s2->rbytes - s3->rbytes; 34017c478bd9Sstevel@tonic-gate s1->obytes = s2->obytes - s3->obytes; 34027c478bd9Sstevel@tonic-gate s1->ierrors = s2->ierrors - s3->ierrors; 34037c478bd9Sstevel@tonic-gate s1->oerrors = s2->oerrors - s3->oerrors; 34047c478bd9Sstevel@tonic-gate } 34057c478bd9Sstevel@tonic-gate 34067c478bd9Sstevel@tonic-gate static void 3407d62bc4baSyz147064 get_stats(char *module, int instance, const char *name, pktsum_t *stats) 34087c478bd9Sstevel@tonic-gate { 34097c478bd9Sstevel@tonic-gate kstat_ctl_t *kcp; 34107c478bd9Sstevel@tonic-gate kstat_t *ksp; 34117c478bd9Sstevel@tonic-gate 34127c478bd9Sstevel@tonic-gate if ((kcp = kstat_open()) == NULL) { 341333343a97Smeem warn("kstat open operation failed"); 34147c478bd9Sstevel@tonic-gate return; 34157c478bd9Sstevel@tonic-gate } 34167c478bd9Sstevel@tonic-gate 3417d62bc4baSyz147064 if ((ksp = kstat_lookup(kcp, module, instance, (char *)name)) == NULL) { 34187c478bd9Sstevel@tonic-gate /* 34197c478bd9Sstevel@tonic-gate * The kstat query could fail if the underlying MAC 34207c478bd9Sstevel@tonic-gate * driver was already detached. 34217c478bd9Sstevel@tonic-gate */ 34227c478bd9Sstevel@tonic-gate (void) kstat_close(kcp); 34237c478bd9Sstevel@tonic-gate return; 34247c478bd9Sstevel@tonic-gate } 34257c478bd9Sstevel@tonic-gate 34267c478bd9Sstevel@tonic-gate if (kstat_read(kcp, ksp, NULL) == -1) 34277c478bd9Sstevel@tonic-gate goto bail; 34287c478bd9Sstevel@tonic-gate 3429e7801d59Ssowmini if (dladm_kstat_value(ksp, "ipackets64", KSTAT_DATA_UINT64, 34307c478bd9Sstevel@tonic-gate &stats->ipackets) < 0) 34317c478bd9Sstevel@tonic-gate goto bail; 34327c478bd9Sstevel@tonic-gate 3433e7801d59Ssowmini if (dladm_kstat_value(ksp, "opackets64", KSTAT_DATA_UINT64, 34347c478bd9Sstevel@tonic-gate &stats->opackets) < 0) 34357c478bd9Sstevel@tonic-gate goto bail; 34367c478bd9Sstevel@tonic-gate 3437e7801d59Ssowmini if (dladm_kstat_value(ksp, "rbytes64", KSTAT_DATA_UINT64, 34387c478bd9Sstevel@tonic-gate &stats->rbytes) < 0) 34397c478bd9Sstevel@tonic-gate goto bail; 34407c478bd9Sstevel@tonic-gate 3441e7801d59Ssowmini if (dladm_kstat_value(ksp, "obytes64", KSTAT_DATA_UINT64, 34427c478bd9Sstevel@tonic-gate &stats->obytes) < 0) 34437c478bd9Sstevel@tonic-gate goto bail; 34447c478bd9Sstevel@tonic-gate 3445e7801d59Ssowmini if (dladm_kstat_value(ksp, "ierrors", KSTAT_DATA_UINT32, 34467c478bd9Sstevel@tonic-gate &stats->ierrors) < 0) 34477c478bd9Sstevel@tonic-gate goto bail; 34487c478bd9Sstevel@tonic-gate 3449e7801d59Ssowmini if (dladm_kstat_value(ksp, "oerrors", KSTAT_DATA_UINT32, 34507c478bd9Sstevel@tonic-gate &stats->oerrors) < 0) 34517c478bd9Sstevel@tonic-gate goto bail; 34527c478bd9Sstevel@tonic-gate 3453d62bc4baSyz147064 bail: 34547c478bd9Sstevel@tonic-gate (void) kstat_close(kcp); 34557c478bd9Sstevel@tonic-gate return; 34567c478bd9Sstevel@tonic-gate 34577c478bd9Sstevel@tonic-gate } 34587c478bd9Sstevel@tonic-gate 34597c478bd9Sstevel@tonic-gate static void 3460ba2e4443Sseb get_mac_stats(const char *dev, pktsum_t *stats) 34617c478bd9Sstevel@tonic-gate { 3462c7e4935fSss150715 char module[DLPI_LINKNAME_MAX]; 3463c7e4935fSss150715 uint_t instance; 34647c478bd9Sstevel@tonic-gate 3465d62bc4baSyz147064 bzero(stats, sizeof (*stats)); 3466c7e4935fSss150715 if (dlpi_parselink(dev, module, &instance) != DLPI_SUCCESS) 3467ba2e4443Sseb return; 3468d62bc4baSyz147064 3469ba2e4443Sseb get_stats(module, instance, "mac", stats); 34707c478bd9Sstevel@tonic-gate } 34717c478bd9Sstevel@tonic-gate 34727c478bd9Sstevel@tonic-gate static void 34737c478bd9Sstevel@tonic-gate get_link_stats(const char *link, pktsum_t *stats) 34747c478bd9Sstevel@tonic-gate { 34757c478bd9Sstevel@tonic-gate bzero(stats, sizeof (*stats)); 3476d62bc4baSyz147064 get_stats("link", 0, link, stats); 34777c478bd9Sstevel@tonic-gate } 34787c478bd9Sstevel@tonic-gate 3479ba2e4443Sseb static int 3480d62bc4baSyz147064 query_kstat(char *module, int instance, const char *name, const char *stat, 3481d62bc4baSyz147064 uint8_t type, void *val) 34827c478bd9Sstevel@tonic-gate { 34837c478bd9Sstevel@tonic-gate kstat_ctl_t *kcp; 34847c478bd9Sstevel@tonic-gate kstat_t *ksp; 34857c478bd9Sstevel@tonic-gate 34867c478bd9Sstevel@tonic-gate if ((kcp = kstat_open()) == NULL) { 348733343a97Smeem warn("kstat open operation failed"); 3488ba2e4443Sseb return (-1); 34897c478bd9Sstevel@tonic-gate } 34907c478bd9Sstevel@tonic-gate 3491d62bc4baSyz147064 if ((ksp = kstat_lookup(kcp, module, instance, (char *)name)) == NULL) { 34927c478bd9Sstevel@tonic-gate /* 34937c478bd9Sstevel@tonic-gate * The kstat query could fail if the underlying MAC 34947c478bd9Sstevel@tonic-gate * driver was already detached. 34957c478bd9Sstevel@tonic-gate */ 34967c478bd9Sstevel@tonic-gate goto bail; 34977c478bd9Sstevel@tonic-gate } 34987c478bd9Sstevel@tonic-gate 34997c478bd9Sstevel@tonic-gate if (kstat_read(kcp, ksp, NULL) == -1) { 350033343a97Smeem warn("kstat read failed"); 35017c478bd9Sstevel@tonic-gate goto bail; 35027c478bd9Sstevel@tonic-gate } 35037c478bd9Sstevel@tonic-gate 3504e7801d59Ssowmini if (dladm_kstat_value(ksp, stat, type, val) < 0) 35057c478bd9Sstevel@tonic-gate goto bail; 3506ba2e4443Sseb 3507ba2e4443Sseb (void) kstat_close(kcp); 3508ba2e4443Sseb return (0); 35097c478bd9Sstevel@tonic-gate 35107c478bd9Sstevel@tonic-gate bail: 35117c478bd9Sstevel@tonic-gate (void) kstat_close(kcp); 3512ba2e4443Sseb return (-1); 3513ba2e4443Sseb } 3514ba2e4443Sseb 3515d62bc4baSyz147064 static int 3516d62bc4baSyz147064 get_one_kstat(const char *name, const char *stat, uint8_t type, 3517d62bc4baSyz147064 void *val, boolean_t islink) 3518d62bc4baSyz147064 { 3519d62bc4baSyz147064 char module[DLPI_LINKNAME_MAX]; 3520d62bc4baSyz147064 uint_t instance; 3521d62bc4baSyz147064 3522d62bc4baSyz147064 if (islink) { 3523d62bc4baSyz147064 return (query_kstat("link", 0, name, stat, type, val)); 3524d62bc4baSyz147064 } else { 3525d62bc4baSyz147064 if (dlpi_parselink(name, module, &instance) != DLPI_SUCCESS) 3526d62bc4baSyz147064 return (-1); 3527d62bc4baSyz147064 3528d62bc4baSyz147064 return (query_kstat(module, instance, "mac", stat, type, val)); 3529d62bc4baSyz147064 } 3530d62bc4baSyz147064 } 3531d62bc4baSyz147064 3532ba2e4443Sseb static uint64_t 3533d62bc4baSyz147064 get_ifspeed(const char *name, boolean_t islink) 3534ba2e4443Sseb { 3535ba2e4443Sseb uint64_t ifspeed = 0; 3536ba2e4443Sseb 3537d62bc4baSyz147064 (void) get_one_kstat(name, "ifspeed", KSTAT_DATA_UINT64, 3538d62bc4baSyz147064 &ifspeed, islink); 3539d62bc4baSyz147064 35407c478bd9Sstevel@tonic-gate return (ifspeed); 35417c478bd9Sstevel@tonic-gate } 35427c478bd9Sstevel@tonic-gate 3543f595a68aSyz147064 static const char * 3544d62bc4baSyz147064 get_linkstate(const char *name, boolean_t islink, char *buf) 35457c478bd9Sstevel@tonic-gate { 3546d62bc4baSyz147064 link_state_t linkstate; 35477c478bd9Sstevel@tonic-gate 3548d62bc4baSyz147064 if (get_one_kstat(name, "link_state", KSTAT_DATA_UINT32, 3549d62bc4baSyz147064 &linkstate, islink) != 0) { 35503a62633bSyz147064 (void) strlcpy(buf, "unknown", DLADM_STRSIZE); 35513a62633bSyz147064 return (buf); 35527c478bd9Sstevel@tonic-gate } 3553d62bc4baSyz147064 return (dladm_linkstate2str(linkstate, buf)); 35547c478bd9Sstevel@tonic-gate } 35557c478bd9Sstevel@tonic-gate 3556f595a68aSyz147064 static const char * 3557d62bc4baSyz147064 get_linkduplex(const char *name, boolean_t islink, char *buf) 35587c478bd9Sstevel@tonic-gate { 3559d62bc4baSyz147064 link_duplex_t linkduplex; 35607c478bd9Sstevel@tonic-gate 3561d62bc4baSyz147064 if (get_one_kstat(name, "link_duplex", KSTAT_DATA_UINT32, 3562d62bc4baSyz147064 &linkduplex, islink) != 0) { 35633a62633bSyz147064 (void) strlcpy(buf, "unknown", DLADM_STRSIZE); 35643a62633bSyz147064 return (buf); 35657c478bd9Sstevel@tonic-gate } 35667c478bd9Sstevel@tonic-gate 3567d62bc4baSyz147064 return (dladm_linkduplex2str(linkduplex, buf)); 35687c478bd9Sstevel@tonic-gate } 35690ba2cbe9Sxc151355 35700ba2cbe9Sxc151355 typedef struct { 35710ba2cbe9Sxc151355 char *s_buf; 35720ba2cbe9Sxc151355 char **s_fields; /* array of pointer to the fields in s_buf */ 35730ba2cbe9Sxc151355 uint_t s_nfields; /* the number of fields in s_buf */ 35740ba2cbe9Sxc151355 } split_t; 35750ba2cbe9Sxc151355 35760ba2cbe9Sxc151355 /* 35770ba2cbe9Sxc151355 * Free the split_t structure pointed to by `sp'. 35780ba2cbe9Sxc151355 */ 35790ba2cbe9Sxc151355 static void 35800ba2cbe9Sxc151355 splitfree(split_t *sp) 35810ba2cbe9Sxc151355 { 35820ba2cbe9Sxc151355 free(sp->s_buf); 35830ba2cbe9Sxc151355 free(sp->s_fields); 35840ba2cbe9Sxc151355 free(sp); 35850ba2cbe9Sxc151355 } 35860ba2cbe9Sxc151355 35870ba2cbe9Sxc151355 /* 35880ba2cbe9Sxc151355 * Split `str' into at most `maxfields' fields, each field at most `maxlen' in 35890ba2cbe9Sxc151355 * length. Return a pointer to a split_t containing the split fields, or NULL 35900ba2cbe9Sxc151355 * on failure. 35910ba2cbe9Sxc151355 */ 35920ba2cbe9Sxc151355 static split_t * 35930ba2cbe9Sxc151355 split(const char *str, uint_t maxfields, uint_t maxlen) 35940ba2cbe9Sxc151355 { 35950ba2cbe9Sxc151355 char *field, *token, *lasts = NULL; 35960ba2cbe9Sxc151355 split_t *sp; 35970ba2cbe9Sxc151355 35980ba2cbe9Sxc151355 if (*str == '\0' || maxfields == 0 || maxlen == 0) 35990ba2cbe9Sxc151355 return (NULL); 36000ba2cbe9Sxc151355 36010ba2cbe9Sxc151355 sp = calloc(sizeof (split_t), 1); 36020ba2cbe9Sxc151355 if (sp == NULL) 36030ba2cbe9Sxc151355 return (NULL); 36040ba2cbe9Sxc151355 36050ba2cbe9Sxc151355 sp->s_buf = strdup(str); 36060ba2cbe9Sxc151355 sp->s_fields = malloc(sizeof (char *) * maxfields); 36070ba2cbe9Sxc151355 if (sp->s_buf == NULL || sp->s_fields == NULL) 36080ba2cbe9Sxc151355 goto fail; 36090ba2cbe9Sxc151355 36100ba2cbe9Sxc151355 token = sp->s_buf; 36110ba2cbe9Sxc151355 while ((field = strtok_r(token, ",", &lasts)) != NULL) { 36120ba2cbe9Sxc151355 if (sp->s_nfields == maxfields || strlen(field) > maxlen) 36130ba2cbe9Sxc151355 goto fail; 36140ba2cbe9Sxc151355 token = NULL; 36150ba2cbe9Sxc151355 sp->s_fields[sp->s_nfields++] = field; 36160ba2cbe9Sxc151355 } 36170ba2cbe9Sxc151355 return (sp); 36180ba2cbe9Sxc151355 fail: 36190ba2cbe9Sxc151355 splitfree(sp); 36200ba2cbe9Sxc151355 return (NULL); 36210ba2cbe9Sxc151355 } 36220ba2cbe9Sxc151355 36230ba2cbe9Sxc151355 static int 3624e7801d59Ssowmini parse_wifi_fields(char *str, print_field_t ***fields, uint_t *countp, 36250ba2cbe9Sxc151355 uint_t cmdtype) 36260ba2cbe9Sxc151355 { 36270ba2cbe9Sxc151355 36280ba2cbe9Sxc151355 if (cmdtype == WIFI_CMD_SCAN) { 36290ba2cbe9Sxc151355 if (str == NULL) 36300ba2cbe9Sxc151355 str = def_scan_wifi_fields; 36310ba2cbe9Sxc151355 if (strcasecmp(str, "all") == 0) 36320ba2cbe9Sxc151355 str = all_scan_wifi_fields; 36330ba2cbe9Sxc151355 } else if (cmdtype == WIFI_CMD_SHOW) { 36340ba2cbe9Sxc151355 if (str == NULL) 36350ba2cbe9Sxc151355 str = def_show_wifi_fields; 36360ba2cbe9Sxc151355 if (strcasecmp(str, "all") == 0) 36370ba2cbe9Sxc151355 str = all_show_wifi_fields; 36380ba2cbe9Sxc151355 } else { 36390ba2cbe9Sxc151355 return (-1); 36400ba2cbe9Sxc151355 } 3641e7801d59Ssowmini *fields = parse_output_fields(str, wifi_fields, WIFI_MAX_FIELDS, 3642e7801d59Ssowmini cmdtype, countp); 3643e7801d59Ssowmini if (*fields != NULL) 3644e7801d59Ssowmini return (0); 36450ba2cbe9Sxc151355 return (-1); 3646e7801d59Ssowmini } 3647e7801d59Ssowmini static print_field_t ** 3648e7801d59Ssowmini parse_output_fields(char *str, print_field_t *template, int max_fields, 3649e7801d59Ssowmini uint_t cmdtype, uint_t *countp) 3650e7801d59Ssowmini { 3651e7801d59Ssowmini split_t *sp; 3652e7801d59Ssowmini boolean_t good_match = B_FALSE; 3653e7801d59Ssowmini uint_t i, j; 3654e7801d59Ssowmini print_field_t **pf = NULL; 36550ba2cbe9Sxc151355 3656e7801d59Ssowmini sp = split(str, max_fields, MAX_FIELD_LEN); 3657e7801d59Ssowmini 3658e7801d59Ssowmini if (sp == NULL) 3659e7801d59Ssowmini return (NULL); 3660e7801d59Ssowmini 3661e7801d59Ssowmini pf = malloc(sp->s_nfields * sizeof (print_field_t *)); 3662e7801d59Ssowmini if (pf == NULL) 36630ba2cbe9Sxc151355 goto fail; 36640ba2cbe9Sxc151355 36650ba2cbe9Sxc151355 for (i = 0; i < sp->s_nfields; i++) { 3666e7801d59Ssowmini for (j = 0; j < max_fields; j++) { 36670ba2cbe9Sxc151355 if (strcasecmp(sp->s_fields[i], 3668e7801d59Ssowmini template[j].pf_name) == 0) { 3669e7801d59Ssowmini good_match = template[j]. pf_cmdtype & cmdtype; 36700ba2cbe9Sxc151355 break; 36710ba2cbe9Sxc151355 } 36720ba2cbe9Sxc151355 } 36730ba2cbe9Sxc151355 if (!good_match) 36740ba2cbe9Sxc151355 goto fail; 36750ba2cbe9Sxc151355 36760ba2cbe9Sxc151355 good_match = B_FALSE; 3677e7801d59Ssowmini pf[i] = &template[j]; 36780ba2cbe9Sxc151355 } 36790ba2cbe9Sxc151355 *countp = i; 36800ba2cbe9Sxc151355 splitfree(sp); 3681e7801d59Ssowmini return (pf); 36820ba2cbe9Sxc151355 fail: 3683e7801d59Ssowmini free(pf); 36840ba2cbe9Sxc151355 splitfree(sp); 3685e7801d59Ssowmini return (NULL); 36860ba2cbe9Sxc151355 } 36870ba2cbe9Sxc151355 36880ba2cbe9Sxc151355 typedef struct print_wifi_state { 3689d62bc4baSyz147064 char *ws_link; 36900ba2cbe9Sxc151355 boolean_t ws_parseable; 36910ba2cbe9Sxc151355 boolean_t ws_header; 3692e7801d59Ssowmini print_state_t ws_print_state; 36930ba2cbe9Sxc151355 } print_wifi_state_t; 36940ba2cbe9Sxc151355 3695e7801d59Ssowmini typedef struct wlan_scan_args_s { 3696e7801d59Ssowmini print_wifi_state_t *ws_state; 3697e7801d59Ssowmini void *ws_attr; 3698e7801d59Ssowmini } wlan_scan_args_t; 36990ba2cbe9Sxc151355 37000ba2cbe9Sxc151355 static void 3701e7801d59Ssowmini print_field(print_state_t *statep, print_field_t *pfp, const char *value, 3702e7801d59Ssowmini boolean_t parseable) 37030ba2cbe9Sxc151355 { 3704e7801d59Ssowmini uint_t width = pfp->pf_width; 37056be03d0bSVasumathi Sundaram - Sun Microsystems uint_t valwidth; 37060ba2cbe9Sxc151355 uint_t compress; 37070ba2cbe9Sxc151355 37080d365605Sschuster /* 37090d365605Sschuster * Parsable fields are separated by ':'. If such a field contains 37100d365605Sschuster * a ':' or '\', this character is prefixed by a '\'. 37110d365605Sschuster */ 3712e7801d59Ssowmini if (parseable) { 37130d365605Sschuster char c; 37140d365605Sschuster 37150d365605Sschuster if (statep->ps_nfields == 1) { 37160d365605Sschuster (void) printf("%s", value); 37170d365605Sschuster return; 37180d365605Sschuster } 37190d365605Sschuster while ((c = *value++) != '\0') { 37200d365605Sschuster if (c == ':' || c == '\\') 37210d365605Sschuster (void) putchar('\\'); 37220d365605Sschuster (void) putchar(c); 37230d365605Sschuster } 37240d365605Sschuster if (!statep->ps_lastfield) 37250d365605Sschuster (void) putchar(':'); 37260d365605Sschuster return; 37270ba2cbe9Sxc151355 } else { 37280ba2cbe9Sxc151355 if (value[0] == '\0') 3729e7801d59Ssowmini value = STR_UNDEF_VAL; 3730e7801d59Ssowmini if (statep->ps_lastfield) { 37310ba2cbe9Sxc151355 (void) printf("%s", value); 37326be03d0bSVasumathi Sundaram - Sun Microsystems statep->ps_overflow = 0; 37330ba2cbe9Sxc151355 return; 37340ba2cbe9Sxc151355 } 37350ba2cbe9Sxc151355 37366be03d0bSVasumathi Sundaram - Sun Microsystems valwidth = strlen(value); 37370ba2cbe9Sxc151355 if (valwidth > width) { 3738e7801d59Ssowmini statep->ps_overflow += valwidth - width; 3739e7801d59Ssowmini } else if (valwidth < width && statep->ps_overflow > 0) { 3740e7801d59Ssowmini compress = min(statep->ps_overflow, width - valwidth); 3741e7801d59Ssowmini statep->ps_overflow -= compress; 37420ba2cbe9Sxc151355 width -= compress; 37430ba2cbe9Sxc151355 } 37440ba2cbe9Sxc151355 (void) printf("%-*s", width, value); 37450ba2cbe9Sxc151355 } 37460ba2cbe9Sxc151355 3747e7801d59Ssowmini if (!statep->ps_lastfield) 37480ba2cbe9Sxc151355 (void) putchar(' '); 37490ba2cbe9Sxc151355 } 37500ba2cbe9Sxc151355 3751e7801d59Ssowmini static char * 3752e7801d59Ssowmini print_wlan_attr(print_field_t *wfp, void *warg) 37530ba2cbe9Sxc151355 { 3754e7801d59Ssowmini static char buf[DLADM_STRSIZE]; 3755e7801d59Ssowmini wlan_scan_args_t *w = warg; 3756e7801d59Ssowmini print_wifi_state_t *statep = w->ws_state; 3757e7801d59Ssowmini dladm_wlan_attr_t *attrp = w->ws_attr; 37580ba2cbe9Sxc151355 3759e7801d59Ssowmini if (wfp->pf_index == 0) { 3760e7801d59Ssowmini return ((char *)statep->ws_link); 37610ba2cbe9Sxc151355 } 37620ba2cbe9Sxc151355 3763e7801d59Ssowmini if ((wfp->pf_index & attrp->wa_valid) == 0) { 3764e7801d59Ssowmini return (""); 37650ba2cbe9Sxc151355 } 37660ba2cbe9Sxc151355 3767e7801d59Ssowmini switch (wfp->pf_index) { 3768f595a68aSyz147064 case DLADM_WLAN_ATTR_ESSID: 3769e7801d59Ssowmini (void) dladm_wlan_essid2str(&attrp->wa_essid, buf); 37700ba2cbe9Sxc151355 break; 3771f595a68aSyz147064 case DLADM_WLAN_ATTR_BSSID: 3772e7801d59Ssowmini (void) dladm_wlan_bssid2str(&attrp->wa_bssid, buf); 37730ba2cbe9Sxc151355 break; 3774f595a68aSyz147064 case DLADM_WLAN_ATTR_SECMODE: 3775e7801d59Ssowmini (void) dladm_wlan_secmode2str(&attrp->wa_secmode, buf); 37760ba2cbe9Sxc151355 break; 3777f595a68aSyz147064 case DLADM_WLAN_ATTR_STRENGTH: 3778e7801d59Ssowmini (void) dladm_wlan_strength2str(&attrp->wa_strength, buf); 37790ba2cbe9Sxc151355 break; 3780f595a68aSyz147064 case DLADM_WLAN_ATTR_MODE: 3781e7801d59Ssowmini (void) dladm_wlan_mode2str(&attrp->wa_mode, buf); 37820ba2cbe9Sxc151355 break; 3783f595a68aSyz147064 case DLADM_WLAN_ATTR_SPEED: 3784e7801d59Ssowmini (void) dladm_wlan_speed2str(&attrp->wa_speed, buf); 37850ba2cbe9Sxc151355 (void) strlcat(buf, "Mb", sizeof (buf)); 37860ba2cbe9Sxc151355 break; 3787f595a68aSyz147064 case DLADM_WLAN_ATTR_AUTH: 3788e7801d59Ssowmini (void) dladm_wlan_auth2str(&attrp->wa_auth, buf); 37890ba2cbe9Sxc151355 break; 3790f595a68aSyz147064 case DLADM_WLAN_ATTR_BSSTYPE: 3791e7801d59Ssowmini (void) dladm_wlan_bsstype2str(&attrp->wa_bsstype, buf); 37920ba2cbe9Sxc151355 break; 37930ba2cbe9Sxc151355 } 37940ba2cbe9Sxc151355 3795e7801d59Ssowmini return (buf); 37960ba2cbe9Sxc151355 } 37970ba2cbe9Sxc151355 37980ba2cbe9Sxc151355 static boolean_t 3799f595a68aSyz147064 print_scan_results(void *arg, dladm_wlan_attr_t *attrp) 38000ba2cbe9Sxc151355 { 38010ba2cbe9Sxc151355 print_wifi_state_t *statep = arg; 3802e7801d59Ssowmini wlan_scan_args_t warg; 38030ba2cbe9Sxc151355 38040ba2cbe9Sxc151355 if (statep->ws_header) { 38050ba2cbe9Sxc151355 statep->ws_header = B_FALSE; 38060ba2cbe9Sxc151355 if (!statep->ws_parseable) 3807e7801d59Ssowmini print_header(&statep->ws_print_state); 38080ba2cbe9Sxc151355 } 38090ba2cbe9Sxc151355 3810e7801d59Ssowmini statep->ws_print_state.ps_overflow = 0; 3811e7801d59Ssowmini bzero(&warg, sizeof (warg)); 3812e7801d59Ssowmini warg.ws_state = statep; 3813e7801d59Ssowmini warg.ws_attr = attrp; 3814e7801d59Ssowmini dladm_print_output(&statep->ws_print_state, statep->ws_parseable, 3815e7801d59Ssowmini print_wlan_attr, &warg); 38160ba2cbe9Sxc151355 return (B_TRUE); 38170ba2cbe9Sxc151355 } 38180ba2cbe9Sxc151355 3819d62bc4baSyz147064 static int 3820d62bc4baSyz147064 scan_wifi(datalink_id_t linkid, void *arg) 38210ba2cbe9Sxc151355 { 38220ba2cbe9Sxc151355 print_wifi_state_t *statep = arg; 3823f595a68aSyz147064 dladm_status_t status; 3824d62bc4baSyz147064 char link[MAXLINKNAMELEN]; 3825d62bc4baSyz147064 3826e7801d59Ssowmini if ((status = dladm_datalink_id2info(linkid, NULL, NULL, NULL, link, 3827e7801d59Ssowmini sizeof (link))) != DLADM_STATUS_OK) { 3828d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 3829d62bc4baSyz147064 } 38300ba2cbe9Sxc151355 38310ba2cbe9Sxc151355 statep->ws_link = link; 3832d62bc4baSyz147064 status = dladm_wlan_scan(linkid, statep, print_scan_results); 3833f595a68aSyz147064 if (status != DLADM_STATUS_OK) 3834d62bc4baSyz147064 die_dlerr(status, "cannot scan link '%s'", statep->ws_link); 383533343a97Smeem 3836d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 38370ba2cbe9Sxc151355 } 38380ba2cbe9Sxc151355 3839e7801d59Ssowmini static char * 3840e7801d59Ssowmini print_link_attr(print_field_t *wfp, void *warg) 38410ba2cbe9Sxc151355 { 3842e7801d59Ssowmini static char buf[DLADM_STRSIZE]; 3843e7801d59Ssowmini char *ptr; 3844e7801d59Ssowmini wlan_scan_args_t *w = warg, w1; 3845e7801d59Ssowmini print_wifi_state_t *statep = w->ws_state; 3846e7801d59Ssowmini dladm_wlan_linkattr_t *attrp = w->ws_attr; 38470ba2cbe9Sxc151355 3848e7801d59Ssowmini if (strcmp(wfp->pf_name, "status") == 0) { 3849e7801d59Ssowmini if ((wfp->pf_index & attrp->la_valid) != 0) 3850e7801d59Ssowmini (void) dladm_wlan_linkstatus2str( 3851e7801d59Ssowmini &attrp->la_status, buf); 3852e7801d59Ssowmini return (buf); 38530ba2cbe9Sxc151355 } 3854e7801d59Ssowmini statep->ws_print_state.ps_overflow = 0; 3855e7801d59Ssowmini bzero(&w1, sizeof (w1)); 3856e7801d59Ssowmini w1.ws_state = statep; 3857e7801d59Ssowmini w1.ws_attr = &attrp->la_wlan_attr; 3858e7801d59Ssowmini ptr = print_wlan_attr(wfp, &w1); 3859e7801d59Ssowmini return (ptr); 38600ba2cbe9Sxc151355 } 38610ba2cbe9Sxc151355 3862d62bc4baSyz147064 static int 3863d62bc4baSyz147064 show_wifi(datalink_id_t linkid, void *arg) 38640ba2cbe9Sxc151355 { 38650ba2cbe9Sxc151355 print_wifi_state_t *statep = arg; 3866f595a68aSyz147064 dladm_wlan_linkattr_t attr; 3867f595a68aSyz147064 dladm_status_t status; 3868d62bc4baSyz147064 char link[MAXLINKNAMELEN]; 3869e7801d59Ssowmini wlan_scan_args_t warg; 38700ba2cbe9Sxc151355 3871e7801d59Ssowmini if ((status = dladm_datalink_id2info(linkid, NULL, NULL, NULL, link, 3872e7801d59Ssowmini sizeof (link))) != DLADM_STATUS_OK) { 3873d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 3874d62bc4baSyz147064 } 3875d62bc4baSyz147064 38765f5c9f54SAnurag S. Maskey /* dladm_wlan_get_linkattr() memsets attr with 0 */ 3877d62bc4baSyz147064 status = dladm_wlan_get_linkattr(linkid, &attr); 3878f595a68aSyz147064 if (status != DLADM_STATUS_OK) 3879d62bc4baSyz147064 die_dlerr(status, "cannot get link attributes for %s", link); 3880d62bc4baSyz147064 3881d62bc4baSyz147064 statep->ws_link = link; 38820ba2cbe9Sxc151355 38830ba2cbe9Sxc151355 if (statep->ws_header) { 38840ba2cbe9Sxc151355 statep->ws_header = B_FALSE; 38850ba2cbe9Sxc151355 if (!statep->ws_parseable) 3886e7801d59Ssowmini print_header(&statep->ws_print_state); 38870ba2cbe9Sxc151355 } 38880ba2cbe9Sxc151355 3889e7801d59Ssowmini statep->ws_print_state.ps_overflow = 0; 3890e7801d59Ssowmini bzero(&warg, sizeof (warg)); 3891e7801d59Ssowmini warg.ws_state = statep; 3892e7801d59Ssowmini warg.ws_attr = &attr; 3893e7801d59Ssowmini dladm_print_output(&statep->ws_print_state, statep->ws_parseable, 3894e7801d59Ssowmini print_link_attr, &warg); 3895d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 38960ba2cbe9Sxc151355 } 38970ba2cbe9Sxc151355 38980ba2cbe9Sxc151355 static void 38998d5c46e6Sam223141 do_display_wifi(int argc, char **argv, int cmd, const char *use) 39000ba2cbe9Sxc151355 { 39010ba2cbe9Sxc151355 int option; 39020ba2cbe9Sxc151355 char *fields_str = NULL; 3903e7801d59Ssowmini print_field_t **fields; 3904d62bc4baSyz147064 int (*callback)(datalink_id_t, void *); 39050ba2cbe9Sxc151355 uint_t nfields; 39060ba2cbe9Sxc151355 print_wifi_state_t state; 3907d62bc4baSyz147064 datalink_id_t linkid = DATALINK_ALL_LINKID; 3908f595a68aSyz147064 dladm_status_t status; 39090ba2cbe9Sxc151355 39100ba2cbe9Sxc151355 if (cmd == WIFI_CMD_SCAN) 39110ba2cbe9Sxc151355 callback = scan_wifi; 39120ba2cbe9Sxc151355 else if (cmd == WIFI_CMD_SHOW) 39130ba2cbe9Sxc151355 callback = show_wifi; 39140ba2cbe9Sxc151355 else 39150ba2cbe9Sxc151355 return; 39160ba2cbe9Sxc151355 39170ba2cbe9Sxc151355 state.ws_parseable = B_FALSE; 39180ba2cbe9Sxc151355 state.ws_header = B_TRUE; 39190ba2cbe9Sxc151355 opterr = 0; 39200ba2cbe9Sxc151355 while ((option = getopt_long(argc, argv, ":o:p", 39210ba2cbe9Sxc151355 wifi_longopts, NULL)) != -1) { 39220ba2cbe9Sxc151355 switch (option) { 39230ba2cbe9Sxc151355 case 'o': 39240ba2cbe9Sxc151355 fields_str = optarg; 39250ba2cbe9Sxc151355 break; 39260ba2cbe9Sxc151355 case 'p': 39270ba2cbe9Sxc151355 state.ws_parseable = B_TRUE; 39280ba2cbe9Sxc151355 break; 39290ba2cbe9Sxc151355 default: 39308d5c46e6Sam223141 die_opterr(optopt, option, use); 39310ba2cbe9Sxc151355 } 39320ba2cbe9Sxc151355 } 39330ba2cbe9Sxc151355 39340d365605Sschuster if (state.ws_parseable && fields_str == NULL) 39350d365605Sschuster die("-p requires -o"); 39360d365605Sschuster 39370d365605Sschuster if (state.ws_parseable && strcasecmp(fields_str, "all") == 0) 39380d365605Sschuster die("\"-o all\" is invalid with -p"); 39390d365605Sschuster 3940d62bc4baSyz147064 if (optind == (argc - 1)) { 3941d62bc4baSyz147064 if ((status = dladm_name2info(argv[optind], &linkid, NULL, 3942d62bc4baSyz147064 NULL, NULL)) != DLADM_STATUS_OK) { 3943d62bc4baSyz147064 die_dlerr(status, "link %s is not valid", argv[optind]); 3944d62bc4baSyz147064 } 3945d62bc4baSyz147064 } else if (optind != argc) { 39460ba2cbe9Sxc151355 usage(); 3947d62bc4baSyz147064 } 39480ba2cbe9Sxc151355 394933343a97Smeem if (parse_wifi_fields(fields_str, &fields, &nfields, cmd) < 0) 395033343a97Smeem die("invalid field(s) specified"); 395133343a97Smeem 3952e7801d59Ssowmini bzero(&state.ws_print_state, sizeof (state.ws_print_state)); 3953e7801d59Ssowmini state.ws_print_state.ps_fields = fields; 3954e7801d59Ssowmini state.ws_print_state.ps_nfields = nfields; 39550ba2cbe9Sxc151355 3956d62bc4baSyz147064 if (linkid == DATALINK_ALL_LINKID) { 3957d62bc4baSyz147064 (void) dladm_walk_datalink_id(callback, &state, 3958d62bc4baSyz147064 DATALINK_CLASS_PHYS, DL_WIFI, DLADM_OPT_ACTIVE); 39590ba2cbe9Sxc151355 } else { 3960d62bc4baSyz147064 (void) (*callback)(linkid, &state); 39610ba2cbe9Sxc151355 } 39620ba2cbe9Sxc151355 free(fields); 39630ba2cbe9Sxc151355 } 39640ba2cbe9Sxc151355 39650ba2cbe9Sxc151355 static void 39668d5c46e6Sam223141 do_scan_wifi(int argc, char **argv, const char *use) 39670ba2cbe9Sxc151355 { 39688d5c46e6Sam223141 do_display_wifi(argc, argv, WIFI_CMD_SCAN, use); 39690ba2cbe9Sxc151355 } 39700ba2cbe9Sxc151355 39710ba2cbe9Sxc151355 static void 39728d5c46e6Sam223141 do_show_wifi(int argc, char **argv, const char *use) 39730ba2cbe9Sxc151355 { 39748d5c46e6Sam223141 do_display_wifi(argc, argv, WIFI_CMD_SHOW, use); 39750ba2cbe9Sxc151355 } 39760ba2cbe9Sxc151355 39770ba2cbe9Sxc151355 typedef struct wlan_count_attr { 39780ba2cbe9Sxc151355 uint_t wc_count; 3979d62bc4baSyz147064 datalink_id_t wc_linkid; 39800ba2cbe9Sxc151355 } wlan_count_attr_t; 39810ba2cbe9Sxc151355 3982d62bc4baSyz147064 static int 3983d62bc4baSyz147064 do_count_wlan(datalink_id_t linkid, void *arg) 39840ba2cbe9Sxc151355 { 398533343a97Smeem wlan_count_attr_t *cp = arg; 39860ba2cbe9Sxc151355 39870ba2cbe9Sxc151355 if (cp->wc_count == 0) 3988d62bc4baSyz147064 cp->wc_linkid = linkid; 39890ba2cbe9Sxc151355 cp->wc_count++; 3990d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 39910ba2cbe9Sxc151355 } 39920ba2cbe9Sxc151355 39930ba2cbe9Sxc151355 static int 3994a399b765Szf162725 parse_wlan_keys(char *str, dladm_wlan_key_t **keys, uint_t *key_countp) 39950ba2cbe9Sxc151355 { 39960ba2cbe9Sxc151355 uint_t i; 39970ba2cbe9Sxc151355 split_t *sp; 3998a399b765Szf162725 dladm_wlan_key_t *wk; 39990ba2cbe9Sxc151355 4000a399b765Szf162725 sp = split(str, DLADM_WLAN_MAX_WEPKEYS, DLADM_WLAN_MAX_KEYNAME_LEN); 40010ba2cbe9Sxc151355 if (sp == NULL) 40020ba2cbe9Sxc151355 return (-1); 40030ba2cbe9Sxc151355 4004a399b765Szf162725 wk = malloc(sp->s_nfields * sizeof (dladm_wlan_key_t)); 40050ba2cbe9Sxc151355 if (wk == NULL) 40060ba2cbe9Sxc151355 goto fail; 40070ba2cbe9Sxc151355 40080ba2cbe9Sxc151355 for (i = 0; i < sp->s_nfields; i++) { 40090ba2cbe9Sxc151355 char *s; 40100ba2cbe9Sxc151355 dladm_secobj_class_t class; 40110ba2cbe9Sxc151355 dladm_status_t status; 40120ba2cbe9Sxc151355 40130ba2cbe9Sxc151355 (void) strlcpy(wk[i].wk_name, sp->s_fields[i], 4014a399b765Szf162725 DLADM_WLAN_MAX_KEYNAME_LEN); 40150ba2cbe9Sxc151355 40160ba2cbe9Sxc151355 wk[i].wk_idx = 1; 40170ba2cbe9Sxc151355 if ((s = strrchr(wk[i].wk_name, ':')) != NULL) { 40180ba2cbe9Sxc151355 if (s[1] == '\0' || s[2] != '\0' || !isdigit(s[1])) 40190ba2cbe9Sxc151355 goto fail; 40200ba2cbe9Sxc151355 40210ba2cbe9Sxc151355 wk[i].wk_idx = (uint_t)(s[1] - '0'); 40220ba2cbe9Sxc151355 *s = '\0'; 40230ba2cbe9Sxc151355 } 4024a399b765Szf162725 wk[i].wk_len = DLADM_WLAN_MAX_KEY_LEN; 40250ba2cbe9Sxc151355 40260ba2cbe9Sxc151355 status = dladm_get_secobj(wk[i].wk_name, &class, 40270ba2cbe9Sxc151355 wk[i].wk_val, &wk[i].wk_len, 0); 40280ba2cbe9Sxc151355 if (status != DLADM_STATUS_OK) { 40290ba2cbe9Sxc151355 if (status == DLADM_STATUS_NOTFOUND) { 40300ba2cbe9Sxc151355 status = dladm_get_secobj(wk[i].wk_name, 40310ba2cbe9Sxc151355 &class, wk[i].wk_val, &wk[i].wk_len, 40320ba2cbe9Sxc151355 DLADM_OPT_PERSIST); 40330ba2cbe9Sxc151355 } 40340ba2cbe9Sxc151355 if (status != DLADM_STATUS_OK) 40350ba2cbe9Sxc151355 goto fail; 40360ba2cbe9Sxc151355 } 4037a399b765Szf162725 wk[i].wk_class = class; 40380ba2cbe9Sxc151355 } 40390ba2cbe9Sxc151355 *keys = wk; 40400ba2cbe9Sxc151355 *key_countp = i; 40410ba2cbe9Sxc151355 splitfree(sp); 40420ba2cbe9Sxc151355 return (0); 40430ba2cbe9Sxc151355 fail: 40440ba2cbe9Sxc151355 free(wk); 40450ba2cbe9Sxc151355 splitfree(sp); 40460ba2cbe9Sxc151355 return (-1); 40470ba2cbe9Sxc151355 } 40480ba2cbe9Sxc151355 40490ba2cbe9Sxc151355 static void 40508d5c46e6Sam223141 do_connect_wifi(int argc, char **argv, const char *use) 40510ba2cbe9Sxc151355 { 40520ba2cbe9Sxc151355 int option; 4053f595a68aSyz147064 dladm_wlan_attr_t attr, *attrp; 4054f595a68aSyz147064 dladm_status_t status = DLADM_STATUS_OK; 4055f595a68aSyz147064 int timeout = DLADM_WLAN_CONNECT_TIMEOUT_DEFAULT; 4056d62bc4baSyz147064 datalink_id_t linkid = DATALINK_ALL_LINKID; 4057a399b765Szf162725 dladm_wlan_key_t *keys = NULL; 40580ba2cbe9Sxc151355 uint_t key_count = 0; 40590ba2cbe9Sxc151355 uint_t flags = 0; 4060f595a68aSyz147064 dladm_wlan_secmode_t keysecmode = DLADM_WLAN_SECMODE_NONE; 4061a399b765Szf162725 char buf[DLADM_STRSIZE]; 40620ba2cbe9Sxc151355 40630ba2cbe9Sxc151355 opterr = 0; 40640ba2cbe9Sxc151355 (void) memset(&attr, 0, sizeof (attr)); 40650ba2cbe9Sxc151355 while ((option = getopt_long(argc, argv, ":e:i:a:m:b:s:k:T:c", 40660ba2cbe9Sxc151355 wifi_longopts, NULL)) != -1) { 40670ba2cbe9Sxc151355 switch (option) { 40680ba2cbe9Sxc151355 case 'e': 4069f595a68aSyz147064 status = dladm_wlan_str2essid(optarg, &attr.wa_essid); 4070f595a68aSyz147064 if (status != DLADM_STATUS_OK) 407133343a97Smeem die("invalid ESSID '%s'", optarg); 407233343a97Smeem 4073f595a68aSyz147064 attr.wa_valid |= DLADM_WLAN_ATTR_ESSID; 40740ba2cbe9Sxc151355 /* 40750ba2cbe9Sxc151355 * Try to connect without doing a scan. 40760ba2cbe9Sxc151355 */ 4077f595a68aSyz147064 flags |= DLADM_WLAN_CONNECT_NOSCAN; 40780ba2cbe9Sxc151355 break; 40790ba2cbe9Sxc151355 case 'i': 4080f595a68aSyz147064 status = dladm_wlan_str2bssid(optarg, &attr.wa_bssid); 4081f595a68aSyz147064 if (status != DLADM_STATUS_OK) 408233343a97Smeem die("invalid BSSID %s", optarg); 408333343a97Smeem 4084f595a68aSyz147064 attr.wa_valid |= DLADM_WLAN_ATTR_BSSID; 40850ba2cbe9Sxc151355 break; 40860ba2cbe9Sxc151355 case 'a': 4087f595a68aSyz147064 status = dladm_wlan_str2auth(optarg, &attr.wa_auth); 4088f595a68aSyz147064 if (status != DLADM_STATUS_OK) 408933343a97Smeem die("invalid authentication mode '%s'", optarg); 409033343a97Smeem 4091f595a68aSyz147064 attr.wa_valid |= DLADM_WLAN_ATTR_AUTH; 40920ba2cbe9Sxc151355 break; 40930ba2cbe9Sxc151355 case 'm': 4094f595a68aSyz147064 status = dladm_wlan_str2mode(optarg, &attr.wa_mode); 4095f595a68aSyz147064 if (status != DLADM_STATUS_OK) 409633343a97Smeem die("invalid mode '%s'", optarg); 409733343a97Smeem 4098f595a68aSyz147064 attr.wa_valid |= DLADM_WLAN_ATTR_MODE; 40990ba2cbe9Sxc151355 break; 41000ba2cbe9Sxc151355 case 'b': 4101f595a68aSyz147064 if ((status = dladm_wlan_str2bsstype(optarg, 4102f595a68aSyz147064 &attr.wa_bsstype)) != DLADM_STATUS_OK) { 410333343a97Smeem die("invalid bsstype '%s'", optarg); 4104f595a68aSyz147064 } 410533343a97Smeem 4106f595a68aSyz147064 attr.wa_valid |= DLADM_WLAN_ATTR_BSSTYPE; 41070ba2cbe9Sxc151355 break; 41080ba2cbe9Sxc151355 case 's': 4109f595a68aSyz147064 if ((status = dladm_wlan_str2secmode(optarg, 4110f595a68aSyz147064 &attr.wa_secmode)) != DLADM_STATUS_OK) { 411133343a97Smeem die("invalid security mode '%s'", optarg); 4112f595a68aSyz147064 } 411333343a97Smeem 4114f595a68aSyz147064 attr.wa_valid |= DLADM_WLAN_ATTR_SECMODE; 41150ba2cbe9Sxc151355 break; 41160ba2cbe9Sxc151355 case 'k': 4117a399b765Szf162725 if (parse_wlan_keys(optarg, &keys, &key_count) < 0) 411833343a97Smeem die("invalid key(s) '%s'", optarg); 411933343a97Smeem 4120a399b765Szf162725 if (keys[0].wk_class == DLADM_SECOBJ_CLASS_WEP) 4121f595a68aSyz147064 keysecmode = DLADM_WLAN_SECMODE_WEP; 4122a399b765Szf162725 else 4123a399b765Szf162725 keysecmode = DLADM_WLAN_SECMODE_WPA; 41240ba2cbe9Sxc151355 break; 41250ba2cbe9Sxc151355 case 'T': 41260ba2cbe9Sxc151355 if (strcasecmp(optarg, "forever") == 0) { 41270ba2cbe9Sxc151355 timeout = -1; 41280ba2cbe9Sxc151355 break; 41290ba2cbe9Sxc151355 } 413033343a97Smeem if (!str2int(optarg, &timeout) || timeout < 0) 413133343a97Smeem die("invalid timeout value '%s'", optarg); 41320ba2cbe9Sxc151355 break; 41330ba2cbe9Sxc151355 case 'c': 4134f595a68aSyz147064 flags |= DLADM_WLAN_CONNECT_CREATEIBSS; 4135a399b765Szf162725 flags |= DLADM_WLAN_CONNECT_CREATEIBSS; 41360ba2cbe9Sxc151355 break; 41370ba2cbe9Sxc151355 default: 41388d5c46e6Sam223141 die_opterr(optopt, option, use); 41390ba2cbe9Sxc151355 break; 41400ba2cbe9Sxc151355 } 41410ba2cbe9Sxc151355 } 41420ba2cbe9Sxc151355 4143f595a68aSyz147064 if (keysecmode == DLADM_WLAN_SECMODE_NONE) { 4144a399b765Szf162725 if ((attr.wa_valid & DLADM_WLAN_ATTR_SECMODE) != 0) { 4145a399b765Szf162725 die("key required for security mode '%s'", 4146a399b765Szf162725 dladm_wlan_secmode2str(&attr.wa_secmode, buf)); 4147a399b765Szf162725 } 41480ba2cbe9Sxc151355 } else { 4149f595a68aSyz147064 if ((attr.wa_valid & DLADM_WLAN_ATTR_SECMODE) != 0 && 415033343a97Smeem attr.wa_secmode != keysecmode) 415133343a97Smeem die("incompatible -s and -k options"); 4152f595a68aSyz147064 attr.wa_valid |= DLADM_WLAN_ATTR_SECMODE; 4153a399b765Szf162725 attr.wa_secmode = keysecmode; 4154a399b765Szf162725 } 41550ba2cbe9Sxc151355 4156d62bc4baSyz147064 if (optind == (argc - 1)) { 4157d62bc4baSyz147064 if ((status = dladm_name2info(argv[optind], &linkid, NULL, 4158d62bc4baSyz147064 NULL, NULL)) != DLADM_STATUS_OK) { 4159d62bc4baSyz147064 die_dlerr(status, "link %s is not valid", argv[optind]); 4160d62bc4baSyz147064 } 4161d62bc4baSyz147064 } else if (optind != argc) { 41620ba2cbe9Sxc151355 usage(); 4163d62bc4baSyz147064 } 41640ba2cbe9Sxc151355 4165d62bc4baSyz147064 if (linkid == DATALINK_ALL_LINKID) { 41660ba2cbe9Sxc151355 wlan_count_attr_t wcattr; 41670ba2cbe9Sxc151355 4168d62bc4baSyz147064 wcattr.wc_linkid = DATALINK_INVALID_LINKID; 41690ba2cbe9Sxc151355 wcattr.wc_count = 0; 4170d62bc4baSyz147064 (void) dladm_walk_datalink_id(do_count_wlan, &wcattr, 4171d62bc4baSyz147064 DATALINK_CLASS_PHYS, DL_WIFI, DLADM_OPT_ACTIVE); 41720ba2cbe9Sxc151355 if (wcattr.wc_count == 0) { 417333343a97Smeem die("no wifi links are available"); 41740ba2cbe9Sxc151355 } else if (wcattr.wc_count > 1) { 417533343a97Smeem die("link name is required when more than one wifi " 417633343a97Smeem "link is available"); 41770ba2cbe9Sxc151355 } 4178d62bc4baSyz147064 linkid = wcattr.wc_linkid; 41790ba2cbe9Sxc151355 } 41800ba2cbe9Sxc151355 attrp = (attr.wa_valid == 0) ? NULL : &attr; 418133343a97Smeem again: 4182d62bc4baSyz147064 if ((status = dladm_wlan_connect(linkid, attrp, timeout, keys, 4183f595a68aSyz147064 key_count, flags)) != DLADM_STATUS_OK) { 4184f595a68aSyz147064 if ((flags & DLADM_WLAN_CONNECT_NOSCAN) != 0) { 41850ba2cbe9Sxc151355 /* 418633343a97Smeem * Try again with scanning and filtering. 41870ba2cbe9Sxc151355 */ 4188f595a68aSyz147064 flags &= ~DLADM_WLAN_CONNECT_NOSCAN; 418933343a97Smeem goto again; 41900ba2cbe9Sxc151355 } 419133343a97Smeem 4192f595a68aSyz147064 if (status == DLADM_STATUS_NOTFOUND) { 41930ba2cbe9Sxc151355 if (attr.wa_valid == 0) { 419433343a97Smeem die("no wifi networks are available"); 41950ba2cbe9Sxc151355 } else { 419633343a97Smeem die("no wifi networks with the specified " 419733343a97Smeem "criteria are available"); 41980ba2cbe9Sxc151355 } 41990ba2cbe9Sxc151355 } 4200d62bc4baSyz147064 die_dlerr(status, "cannot connect"); 42010ba2cbe9Sxc151355 } 42020ba2cbe9Sxc151355 free(keys); 42030ba2cbe9Sxc151355 } 42040ba2cbe9Sxc151355 42050ba2cbe9Sxc151355 /* ARGSUSED */ 4206d62bc4baSyz147064 static int 4207d62bc4baSyz147064 do_all_disconnect_wifi(datalink_id_t linkid, void *arg) 42080ba2cbe9Sxc151355 { 4209f595a68aSyz147064 dladm_status_t status; 42100ba2cbe9Sxc151355 4211d62bc4baSyz147064 status = dladm_wlan_disconnect(linkid); 4212f595a68aSyz147064 if (status != DLADM_STATUS_OK) 4213d62bc4baSyz147064 warn_dlerr(status, "cannot disconnect link"); 421433343a97Smeem 4215d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 42160ba2cbe9Sxc151355 } 42170ba2cbe9Sxc151355 42180ba2cbe9Sxc151355 static void 42198d5c46e6Sam223141 do_disconnect_wifi(int argc, char **argv, const char *use) 42200ba2cbe9Sxc151355 { 42210ba2cbe9Sxc151355 int option; 4222d62bc4baSyz147064 datalink_id_t linkid = DATALINK_ALL_LINKID; 42230ba2cbe9Sxc151355 boolean_t all_links = B_FALSE; 4224f595a68aSyz147064 dladm_status_t status; 42250ba2cbe9Sxc151355 wlan_count_attr_t wcattr; 42260ba2cbe9Sxc151355 42270ba2cbe9Sxc151355 opterr = 0; 42280ba2cbe9Sxc151355 while ((option = getopt_long(argc, argv, ":a", 42290ba2cbe9Sxc151355 wifi_longopts, NULL)) != -1) { 42300ba2cbe9Sxc151355 switch (option) { 42310ba2cbe9Sxc151355 case 'a': 42320ba2cbe9Sxc151355 all_links = B_TRUE; 42330ba2cbe9Sxc151355 break; 42340ba2cbe9Sxc151355 default: 42358d5c46e6Sam223141 die_opterr(optopt, option, use); 42360ba2cbe9Sxc151355 break; 42370ba2cbe9Sxc151355 } 42380ba2cbe9Sxc151355 } 42390ba2cbe9Sxc151355 4240d62bc4baSyz147064 if (optind == (argc - 1)) { 4241d62bc4baSyz147064 if ((status = dladm_name2info(argv[optind], &linkid, NULL, 4242d62bc4baSyz147064 NULL, NULL)) != DLADM_STATUS_OK) { 4243d62bc4baSyz147064 die_dlerr(status, "link %s is not valid", argv[optind]); 4244d62bc4baSyz147064 } 4245d62bc4baSyz147064 } else if (optind != argc) { 42460ba2cbe9Sxc151355 usage(); 4247d62bc4baSyz147064 } 42480ba2cbe9Sxc151355 4249d62bc4baSyz147064 if (linkid == DATALINK_ALL_LINKID) { 42500ba2cbe9Sxc151355 if (!all_links) { 4251d62bc4baSyz147064 wcattr.wc_linkid = linkid; 42520ba2cbe9Sxc151355 wcattr.wc_count = 0; 4253d62bc4baSyz147064 (void) dladm_walk_datalink_id(do_count_wlan, &wcattr, 4254d62bc4baSyz147064 DATALINK_CLASS_PHYS, DL_WIFI, DLADM_OPT_ACTIVE); 42550ba2cbe9Sxc151355 if (wcattr.wc_count == 0) { 425633343a97Smeem die("no wifi links are available"); 42570ba2cbe9Sxc151355 } else if (wcattr.wc_count > 1) { 425833343a97Smeem die("link name is required when more than " 425933343a97Smeem "one wifi link is available"); 42600ba2cbe9Sxc151355 } 4261d62bc4baSyz147064 linkid = wcattr.wc_linkid; 42620ba2cbe9Sxc151355 } else { 4263d62bc4baSyz147064 (void) dladm_walk_datalink_id(do_all_disconnect_wifi, 4264d62bc4baSyz147064 NULL, DATALINK_CLASS_PHYS, DL_WIFI, 4265d62bc4baSyz147064 DLADM_OPT_ACTIVE); 42660ba2cbe9Sxc151355 return; 42670ba2cbe9Sxc151355 } 42680ba2cbe9Sxc151355 } 4269d62bc4baSyz147064 status = dladm_wlan_disconnect(linkid); 4270f595a68aSyz147064 if (status != DLADM_STATUS_OK) 4271d62bc4baSyz147064 die_dlerr(status, "cannot disconnect"); 42720ba2cbe9Sxc151355 } 42730ba2cbe9Sxc151355 42740ba2cbe9Sxc151355 42750ba2cbe9Sxc151355 static void 42760ba2cbe9Sxc151355 free_props(prop_list_t *list) 42770ba2cbe9Sxc151355 { 42780ba2cbe9Sxc151355 if (list != NULL) { 42790ba2cbe9Sxc151355 free(list->pl_buf); 42800ba2cbe9Sxc151355 free(list); 42810ba2cbe9Sxc151355 } 42820ba2cbe9Sxc151355 } 42830ba2cbe9Sxc151355 42840ba2cbe9Sxc151355 static int 42850ba2cbe9Sxc151355 parse_props(char *str, prop_list_t **listp, boolean_t novalues) 42860ba2cbe9Sxc151355 { 42870ba2cbe9Sxc151355 prop_list_t *list; 42880ba2cbe9Sxc151355 prop_info_t *pip; 42890ba2cbe9Sxc151355 char *buf, *curr; 42900ba2cbe9Sxc151355 int len, i; 42910ba2cbe9Sxc151355 42920ba2cbe9Sxc151355 list = malloc(sizeof (prop_list_t)); 42930ba2cbe9Sxc151355 if (list == NULL) 42940ba2cbe9Sxc151355 return (-1); 42950ba2cbe9Sxc151355 42960ba2cbe9Sxc151355 list->pl_count = 0; 42970ba2cbe9Sxc151355 list->pl_buf = buf = strdup(str); 42980ba2cbe9Sxc151355 if (buf == NULL) 42990ba2cbe9Sxc151355 goto fail; 43000ba2cbe9Sxc151355 4301e7801d59Ssowmini /* 4302e7801d59Ssowmini * buf is a string of form [<propname>=<value>][,<propname>=<value>]+ 4303e7801d59Ssowmini * where each <value> string itself could be a comma-separated array. 4304e7801d59Ssowmini * The loop below will count the number of propname assignments 4305e7801d59Ssowmini * in pl_count; for each property, there is a pip entry with 4306e7801d59Ssowmini * pi_name == <propname>, pi_count == # of elements in <value> array. 4307e7801d59Ssowmini * pi_val[] contains the actual values. 4308e7801d59Ssowmini * 4309e7801d59Ssowmini * This could really be a combination of calls to 4310e7801d59Ssowmini * strtok (token delimiter is ",") and strchr (chr '=') 4311e7801d59Ssowmini * with appropriate null/string-bound-checks. 4312e7801d59Ssowmini */ 4313e7801d59Ssowmini 43140ba2cbe9Sxc151355 curr = buf; 43150ba2cbe9Sxc151355 len = strlen(buf); 43160ba2cbe9Sxc151355 pip = NULL; 43170ba2cbe9Sxc151355 for (i = 0; i < len; i++) { 43180ba2cbe9Sxc151355 char c = buf[i]; 43190ba2cbe9Sxc151355 boolean_t match = (c == '=' || c == ','); 43200ba2cbe9Sxc151355 43210ba2cbe9Sxc151355 if (!match && i != len - 1) 43220ba2cbe9Sxc151355 continue; 43230ba2cbe9Sxc151355 43240ba2cbe9Sxc151355 if (match) { 43250ba2cbe9Sxc151355 buf[i] = '\0'; 43260ba2cbe9Sxc151355 if (*curr == '\0') 43270ba2cbe9Sxc151355 goto fail; 43280ba2cbe9Sxc151355 } 43290ba2cbe9Sxc151355 43300ba2cbe9Sxc151355 if (pip != NULL && c != '=') { 4331d62bc4baSyz147064 if (pip->pi_count > DLADM_MAX_PROP_VALCNT) 43320ba2cbe9Sxc151355 goto fail; 43330ba2cbe9Sxc151355 43340ba2cbe9Sxc151355 if (novalues) 43350ba2cbe9Sxc151355 goto fail; 43360ba2cbe9Sxc151355 43370ba2cbe9Sxc151355 pip->pi_val[pip->pi_count] = curr; 43380ba2cbe9Sxc151355 pip->pi_count++; 43390ba2cbe9Sxc151355 } else { 43400ba2cbe9Sxc151355 if (list->pl_count > MAX_PROPS) 43410ba2cbe9Sxc151355 goto fail; 43420ba2cbe9Sxc151355 43430ba2cbe9Sxc151355 pip = &list->pl_info[list->pl_count]; 43440ba2cbe9Sxc151355 pip->pi_name = curr; 43450ba2cbe9Sxc151355 pip->pi_count = 0; 43460ba2cbe9Sxc151355 list->pl_count++; 43470ba2cbe9Sxc151355 if (c == ',') 43480ba2cbe9Sxc151355 pip = NULL; 43490ba2cbe9Sxc151355 } 43500ba2cbe9Sxc151355 curr = buf + i + 1; 43510ba2cbe9Sxc151355 } 43520ba2cbe9Sxc151355 *listp = list; 43530ba2cbe9Sxc151355 return (0); 43540ba2cbe9Sxc151355 43550ba2cbe9Sxc151355 fail: 43560ba2cbe9Sxc151355 free_props(list); 43570ba2cbe9Sxc151355 return (-1); 43580ba2cbe9Sxc151355 } 43590ba2cbe9Sxc151355 43600ba2cbe9Sxc151355 static void 4361d62bc4baSyz147064 print_linkprop(datalink_id_t linkid, show_linkprop_state_t *statep, 4362e7801d59Ssowmini const char *propname, dladm_prop_type_t type, 4363d62bc4baSyz147064 const char *format, char **pptr) 43640ba2cbe9Sxc151355 { 43650ba2cbe9Sxc151355 int i; 43660ba2cbe9Sxc151355 char *ptr, *lim; 43670ba2cbe9Sxc151355 char buf[DLADM_STRSIZE]; 43680ba2cbe9Sxc151355 char *unknown = "?", *notsup = ""; 43690ba2cbe9Sxc151355 char **propvals = statep->ls_propvals; 4370d62bc4baSyz147064 uint_t valcnt = DLADM_MAX_PROP_VALCNT; 43710ba2cbe9Sxc151355 dladm_status_t status; 43720ba2cbe9Sxc151355 4373d62bc4baSyz147064 status = dladm_get_linkprop(linkid, type, propname, propvals, &valcnt); 43740ba2cbe9Sxc151355 if (status != DLADM_STATUS_OK) { 4375f595a68aSyz147064 if (status == DLADM_STATUS_TEMPONLY) { 4376d62bc4baSyz147064 if (type == DLADM_PROP_VAL_MODIFIABLE && 4377d62bc4baSyz147064 statep->ls_persist) { 4378d62bc4baSyz147064 valcnt = 1; 4379d62bc4baSyz147064 propvals = &unknown; 4380d62bc4baSyz147064 } else { 4381f595a68aSyz147064 statep->ls_status = status; 4382e7801d59Ssowmini statep->ls_retstatus = status; 4383f595a68aSyz147064 return; 4384d62bc4baSyz147064 } 4385f595a68aSyz147064 } else if (status == DLADM_STATUS_NOTSUP || 4386f595a68aSyz147064 statep->ls_persist) { 43870ba2cbe9Sxc151355 valcnt = 1; 4388*afdda45fSVasumathi Sundaram - Sun Microsystems if (type == DLADM_PROP_VAL_CURRENT || 4389*afdda45fSVasumathi Sundaram - Sun Microsystems type == DLADM_PROP_VAL_PERM) 43900ba2cbe9Sxc151355 propvals = &unknown; 43910ba2cbe9Sxc151355 else 43920ba2cbe9Sxc151355 propvals = ¬sup; 4393149b7eb2SSowmini Varadhan } else if (status == DLADM_STATUS_NOTDEFINED) { 4394149b7eb2SSowmini Varadhan propvals = ¬sup; /* STR_UNDEF_VAL */ 43950ba2cbe9Sxc151355 } else { 4396e7801d59Ssowmini if (statep->ls_proplist && 4397e7801d59Ssowmini statep->ls_status == DLADM_STATUS_OK) { 4398f595a68aSyz147064 warn_dlerr(status, 4399f595a68aSyz147064 "cannot get link property '%s' for %s", 4400f595a68aSyz147064 propname, statep->ls_link); 4401d62bc4baSyz147064 } 4402e7801d59Ssowmini statep->ls_status = status; 4403e7801d59Ssowmini statep->ls_retstatus = status; 4404f595a68aSyz147064 return; 44050ba2cbe9Sxc151355 } 44060ba2cbe9Sxc151355 } 44070ba2cbe9Sxc151355 4408e7801d59Ssowmini statep->ls_status = DLADM_STATUS_OK; 4409e7801d59Ssowmini 44100ba2cbe9Sxc151355 ptr = buf; 44110ba2cbe9Sxc151355 lim = buf + DLADM_STRSIZE; 44120ba2cbe9Sxc151355 for (i = 0; i < valcnt; i++) { 44130ba2cbe9Sxc151355 if (propvals[i][0] == '\0' && !statep->ls_parseable) 4414e7801d59Ssowmini ptr += snprintf(ptr, lim - ptr, STR_UNDEF_VAL","); 44150ba2cbe9Sxc151355 else 44160ba2cbe9Sxc151355 ptr += snprintf(ptr, lim - ptr, "%s,", propvals[i]); 44170ba2cbe9Sxc151355 if (ptr >= lim) 44180ba2cbe9Sxc151355 break; 44190ba2cbe9Sxc151355 } 44200ba2cbe9Sxc151355 if (valcnt > 0) 44210ba2cbe9Sxc151355 buf[strlen(buf) - 1] = '\0'; 44220ba2cbe9Sxc151355 44230ba2cbe9Sxc151355 lim = statep->ls_line + MAX_PROP_LINE; 44240ba2cbe9Sxc151355 if (statep->ls_parseable) { 44250ba2cbe9Sxc151355 *pptr += snprintf(*pptr, lim - *pptr, 4426e7801d59Ssowmini "%s", buf); 44270ba2cbe9Sxc151355 } else { 44280ba2cbe9Sxc151355 *pptr += snprintf(*pptr, lim - *pptr, format, buf); 44290ba2cbe9Sxc151355 } 44300ba2cbe9Sxc151355 } 44310ba2cbe9Sxc151355 4432e7801d59Ssowmini static char * 4433e7801d59Ssowmini linkprop_callback(print_field_t *pf, void *ls_arg) 4434e7801d59Ssowmini { 4435e7801d59Ssowmini linkprop_args_t *arg = ls_arg; 4436e7801d59Ssowmini char *propname = arg->ls_propname; 4437e7801d59Ssowmini show_linkprop_state_t *statep = arg->ls_state; 4438e7801d59Ssowmini char *ptr = statep->ls_line; 4439e7801d59Ssowmini char *lim = ptr + MAX_PROP_LINE; 4440e7801d59Ssowmini datalink_id_t linkid = arg->ls_linkid; 4441e7801d59Ssowmini 4442e7801d59Ssowmini switch (pf->pf_index) { 4443e7801d59Ssowmini case LINKPROP_LINK: 4444e7801d59Ssowmini (void) snprintf(ptr, lim - ptr, "%s", statep->ls_link); 4445e7801d59Ssowmini break; 4446e7801d59Ssowmini case LINKPROP_PROPERTY: 4447e7801d59Ssowmini (void) snprintf(ptr, lim - ptr, "%s", propname); 4448e7801d59Ssowmini break; 4449e7801d59Ssowmini case LINKPROP_VALUE: 4450e7801d59Ssowmini print_linkprop(linkid, statep, propname, 4451e7801d59Ssowmini statep->ls_persist ? DLADM_PROP_VAL_PERSISTENT : 4452e7801d59Ssowmini DLADM_PROP_VAL_CURRENT, "%s", &ptr); 4453e7801d59Ssowmini /* 4454e7801d59Ssowmini * If we failed to query the link property, for example, query 4455e7801d59Ssowmini * the persistent value of a non-persistable link property, 4456e7801d59Ssowmini * simply skip the output. 4457e7801d59Ssowmini */ 4458e7801d59Ssowmini if (statep->ls_status != DLADM_STATUS_OK) 4459e7801d59Ssowmini goto skip; 4460e7801d59Ssowmini ptr = statep->ls_line; 4461e7801d59Ssowmini break; 4462*afdda45fSVasumathi Sundaram - Sun Microsystems case LINKPROP_PERM: 4463*afdda45fSVasumathi Sundaram - Sun Microsystems print_linkprop(linkid, statep, propname, 4464*afdda45fSVasumathi Sundaram - Sun Microsystems DLADM_PROP_VAL_PERM, "%s", &ptr); 4465*afdda45fSVasumathi Sundaram - Sun Microsystems if (statep->ls_status != DLADM_STATUS_OK) 4466*afdda45fSVasumathi Sundaram - Sun Microsystems goto skip; 4467*afdda45fSVasumathi Sundaram - Sun Microsystems ptr = statep->ls_line; 4468*afdda45fSVasumathi Sundaram - Sun Microsystems break; 4469e7801d59Ssowmini case LINKPROP_DEFAULT: 4470e7801d59Ssowmini print_linkprop(linkid, statep, propname, 4471e7801d59Ssowmini DLADM_PROP_VAL_DEFAULT, "%s", &ptr); 4472e7801d59Ssowmini if (statep->ls_status != DLADM_STATUS_OK) 4473e7801d59Ssowmini goto skip; 4474e7801d59Ssowmini ptr = statep->ls_line; 4475e7801d59Ssowmini break; 4476e7801d59Ssowmini case LINKPROP_POSSIBLE: 4477e7801d59Ssowmini print_linkprop(linkid, statep, propname, 4478e7801d59Ssowmini DLADM_PROP_VAL_MODIFIABLE, "%s ", &ptr); 4479e7801d59Ssowmini if (statep->ls_status != DLADM_STATUS_OK) 4480e7801d59Ssowmini goto skip; 4481e7801d59Ssowmini ptr = statep->ls_line; 4482e7801d59Ssowmini break; 4483e7801d59Ssowmini default: 4484e7801d59Ssowmini die("invalid input"); 4485e7801d59Ssowmini break; 4486e7801d59Ssowmini } 4487e7801d59Ssowmini return (ptr); 4488e7801d59Ssowmini skip: 4489e7801d59Ssowmini if (statep->ls_status != DLADM_STATUS_OK) 4490e7801d59Ssowmini return (NULL); 4491e7801d59Ssowmini else 4492e7801d59Ssowmini return (""); 4493e7801d59Ssowmini } 4494e7801d59Ssowmini 4495bcb5c89dSSowmini Varadhan static boolean_t 4496bcb5c89dSSowmini Varadhan linkprop_is_supported(datalink_id_t linkid, const char *propname, 4497bcb5c89dSSowmini Varadhan show_linkprop_state_t *statep) 4498bcb5c89dSSowmini Varadhan { 4499bcb5c89dSSowmini Varadhan dladm_status_t status; 4500bcb5c89dSSowmini Varadhan uint_t valcnt = DLADM_MAX_PROP_VALCNT; 4501bcb5c89dSSowmini Varadhan 4502bcb5c89dSSowmini Varadhan status = dladm_get_linkprop(linkid, DLADM_PROP_VAL_DEFAULT, 4503bcb5c89dSSowmini Varadhan propname, statep->ls_propvals, &valcnt); 4504bcb5c89dSSowmini Varadhan 4505149b7eb2SSowmini Varadhan if (status == DLADM_STATUS_OK) 4506149b7eb2SSowmini Varadhan return (B_TRUE); 4507149b7eb2SSowmini Varadhan 4508149b7eb2SSowmini Varadhan /* 4509149b7eb2SSowmini Varadhan * A system wide default value is not available for the 4510149b7eb2SSowmini Varadhan * property. Check if current value can be retrieved. 4511149b7eb2SSowmini Varadhan */ 4512149b7eb2SSowmini Varadhan status = dladm_get_linkprop(linkid, DLADM_PROP_VAL_CURRENT, 4513149b7eb2SSowmini Varadhan propname, statep->ls_propvals, &valcnt); 4514149b7eb2SSowmini Varadhan 4515149b7eb2SSowmini Varadhan return (status == DLADM_STATUS_OK); 4516bcb5c89dSSowmini Varadhan } 4517bcb5c89dSSowmini Varadhan 4518d62bc4baSyz147064 static int 4519d62bc4baSyz147064 show_linkprop(datalink_id_t linkid, const char *propname, void *arg) 45200ba2cbe9Sxc151355 { 45210ba2cbe9Sxc151355 show_linkprop_state_t *statep = arg; 4522e7801d59Ssowmini linkprop_args_t ls_arg; 45230ba2cbe9Sxc151355 4524e7801d59Ssowmini bzero(&ls_arg, sizeof (ls_arg)); 4525e7801d59Ssowmini ls_arg.ls_state = statep; 4526e7801d59Ssowmini ls_arg.ls_propname = (char *)propname; 4527e7801d59Ssowmini ls_arg.ls_linkid = linkid; 45280ba2cbe9Sxc151355 45290ba2cbe9Sxc151355 if (statep->ls_header) { 45300ba2cbe9Sxc151355 statep->ls_header = B_FALSE; 45310ba2cbe9Sxc151355 if (!statep->ls_parseable) 4532e7801d59Ssowmini print_header(&statep->ls_print); 45330ba2cbe9Sxc151355 } 4534149b7eb2SSowmini Varadhan if (!statep->ls_parseable && 4535149b7eb2SSowmini Varadhan !linkprop_is_supported(linkid, propname, statep)) 4536bcb5c89dSSowmini Varadhan return (DLADM_WALK_CONTINUE); 4537bcb5c89dSSowmini Varadhan 4538e7801d59Ssowmini dladm_print_output(&statep->ls_print, statep->ls_parseable, 4539e7801d59Ssowmini linkprop_callback, (void *)&ls_arg); 4540e7801d59Ssowmini 4541d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 45420ba2cbe9Sxc151355 } 45430ba2cbe9Sxc151355 45440ba2cbe9Sxc151355 static void 45458d5c46e6Sam223141 do_show_linkprop(int argc, char **argv, const char *use) 45460ba2cbe9Sxc151355 { 4547f4b3ec61Sdh155122 int option; 45480ba2cbe9Sxc151355 prop_list_t *proplist = NULL; 4549d62bc4baSyz147064 datalink_id_t linkid = DATALINK_ALL_LINKID; 45500ba2cbe9Sxc151355 show_linkprop_state_t state; 4551d62bc4baSyz147064 uint32_t flags = DLADM_OPT_ACTIVE; 4552d62bc4baSyz147064 dladm_status_t status; 4553e7801d59Ssowmini char *fields_str = NULL; 4554e7801d59Ssowmini print_field_t **fields; 4555e7801d59Ssowmini uint_t nfields; 45560d365605Sschuster boolean_t o_arg = B_FALSE; 4557e7801d59Ssowmini char *all_fields = 4558*afdda45fSVasumathi Sundaram - Sun Microsystems "link,property,perm,value,default,possible"; 4559e7801d59Ssowmini 4560e7801d59Ssowmini fields_str = all_fields; 45610ba2cbe9Sxc151355 45620ba2cbe9Sxc151355 opterr = 0; 45630ba2cbe9Sxc151355 state.ls_propvals = NULL; 45640ba2cbe9Sxc151355 state.ls_line = NULL; 45650ba2cbe9Sxc151355 state.ls_parseable = B_FALSE; 45660ba2cbe9Sxc151355 state.ls_persist = B_FALSE; 45670ba2cbe9Sxc151355 state.ls_header = B_TRUE; 4568e7801d59Ssowmini state.ls_retstatus = DLADM_STATUS_OK; 4569e7801d59Ssowmini while ((option = getopt_long(argc, argv, ":p:cPo:", 45700ba2cbe9Sxc151355 prop_longopts, NULL)) != -1) { 45710ba2cbe9Sxc151355 switch (option) { 45720ba2cbe9Sxc151355 case 'p': 457333343a97Smeem if (parse_props(optarg, &proplist, B_TRUE) < 0) 457413994ee8Sxz162242 die("invalid link properties specified"); 45750ba2cbe9Sxc151355 break; 45760ba2cbe9Sxc151355 case 'c': 45770ba2cbe9Sxc151355 state.ls_parseable = B_TRUE; 45780ba2cbe9Sxc151355 break; 45790ba2cbe9Sxc151355 case 'P': 45800ba2cbe9Sxc151355 state.ls_persist = B_TRUE; 4581d62bc4baSyz147064 flags = DLADM_OPT_PERSIST; 45820ba2cbe9Sxc151355 break; 4583e7801d59Ssowmini case 'o': 45840d365605Sschuster o_arg = B_TRUE; 4585e7801d59Ssowmini if (strcasecmp(optarg, "all") == 0) 4586e7801d59Ssowmini fields_str = all_fields; 4587e7801d59Ssowmini else 4588e7801d59Ssowmini fields_str = optarg; 4589e7801d59Ssowmini break; 45900ba2cbe9Sxc151355 default: 45918d5c46e6Sam223141 die_opterr(optopt, option, use); 45920ba2cbe9Sxc151355 break; 45930ba2cbe9Sxc151355 } 45940ba2cbe9Sxc151355 } 45950ba2cbe9Sxc151355 45960d365605Sschuster if (state.ls_parseable && !o_arg) 45970d365605Sschuster die("-c requires -o"); 45980d365605Sschuster 45990d365605Sschuster if (state.ls_parseable && fields_str == all_fields) 46000d365605Sschuster die("\"-o all\" is invalid with -c"); 46010d365605Sschuster 4602d62bc4baSyz147064 if (optind == (argc - 1)) { 4603d62bc4baSyz147064 if ((status = dladm_name2info(argv[optind], &linkid, NULL, 4604d62bc4baSyz147064 NULL, NULL)) != DLADM_STATUS_OK) { 4605d62bc4baSyz147064 die_dlerr(status, "link %s is not valid", argv[optind]); 4606d62bc4baSyz147064 } 4607d62bc4baSyz147064 } else if (optind != argc) { 46080ba2cbe9Sxc151355 usage(); 4609d62bc4baSyz147064 } 46100ba2cbe9Sxc151355 4611e7801d59Ssowmini bzero(&state.ls_print, sizeof (print_state_t)); 4612f4b3ec61Sdh155122 state.ls_proplist = proplist; 4613f595a68aSyz147064 state.ls_status = DLADM_STATUS_OK; 4614f4b3ec61Sdh155122 4615e7801d59Ssowmini fields = parse_output_fields(fields_str, linkprop_fields, 4616e7801d59Ssowmini LINKPROP_MAX_FIELDS, CMD_TYPE_ANY, &nfields); 4617e7801d59Ssowmini 4618e7801d59Ssowmini if (fields == NULL) { 4619e7801d59Ssowmini die("invalid field(s) specified"); 4620e7801d59Ssowmini return; 4621e7801d59Ssowmini } 4622e7801d59Ssowmini 4623e7801d59Ssowmini state.ls_print.ps_fields = fields; 4624e7801d59Ssowmini state.ls_print.ps_nfields = nfields; 4625d62bc4baSyz147064 if (linkid == DATALINK_ALL_LINKID) { 4626d62bc4baSyz147064 (void) dladm_walk_datalink_id(show_linkprop_onelink, &state, 4627d62bc4baSyz147064 DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE, flags); 4628f4b3ec61Sdh155122 } else { 4629d62bc4baSyz147064 (void) show_linkprop_onelink(linkid, &state); 4630f4b3ec61Sdh155122 } 4631f4b3ec61Sdh155122 free_props(proplist); 4632f595a68aSyz147064 4633e7801d59Ssowmini if (state.ls_retstatus != DLADM_STATUS_OK) 4634f595a68aSyz147064 exit(EXIT_FAILURE); 4635f4b3ec61Sdh155122 } 4636f4b3ec61Sdh155122 4637d62bc4baSyz147064 static int 4638d62bc4baSyz147064 show_linkprop_onelink(datalink_id_t linkid, void *arg) 4639f4b3ec61Sdh155122 { 4640948f2876Sss150715 int i; 4641f4b3ec61Sdh155122 char *buf; 4642d62bc4baSyz147064 uint32_t flags; 4643f4b3ec61Sdh155122 prop_list_t *proplist = NULL; 4644d62bc4baSyz147064 show_linkprop_state_t *statep = arg; 4645d62bc4baSyz147064 dlpi_handle_t dh = NULL; 4646f4b3ec61Sdh155122 4647d62bc4baSyz147064 statep->ls_status = DLADM_STATUS_OK; 4648d62bc4baSyz147064 4649d62bc4baSyz147064 if (dladm_datalink_id2info(linkid, &flags, NULL, NULL, statep->ls_link, 4650d62bc4baSyz147064 MAXLINKNAMELEN) != DLADM_STATUS_OK) { 4651d62bc4baSyz147064 statep->ls_status = DLADM_STATUS_NOTFOUND; 4652d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 4653d62bc4baSyz147064 } 4654d62bc4baSyz147064 4655d62bc4baSyz147064 if ((statep->ls_persist && !(flags & DLADM_OPT_PERSIST)) || 4656d62bc4baSyz147064 (!statep->ls_persist && !(flags & DLADM_OPT_ACTIVE))) { 4657d62bc4baSyz147064 statep->ls_status = DLADM_STATUS_BADARG; 4658d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 4659d62bc4baSyz147064 } 4660d62bc4baSyz147064 4661f4b3ec61Sdh155122 proplist = statep->ls_proplist; 46620ba2cbe9Sxc151355 46630ba2cbe9Sxc151355 /* 46640ba2cbe9Sxc151355 * When some WiFi links are opened for the first time, their hardware 46650ba2cbe9Sxc151355 * automatically scans for APs and does other slow operations. Thus, 46660ba2cbe9Sxc151355 * if there are no open links, the retrieval of link properties 46670ba2cbe9Sxc151355 * (below) will proceed slowly unless we hold the link open. 4668d62bc4baSyz147064 * 4669d62bc4baSyz147064 * Note that failure of dlpi_open() does not necessarily mean invalid 4670d62bc4baSyz147064 * link properties, because dlpi_open() may fail because of incorrect 4671d62bc4baSyz147064 * autopush configuration. Therefore, we ingore the return value of 4672d62bc4baSyz147064 * dlpi_open(). 46730ba2cbe9Sxc151355 */ 4674d62bc4baSyz147064 if (!statep->ls_persist) 4675d62bc4baSyz147064 (void) dlpi_open(statep->ls_link, &dh, 0); 46760ba2cbe9Sxc151355 4677d62bc4baSyz147064 buf = malloc((sizeof (char *) + DLADM_PROP_VAL_MAX) * 4678d62bc4baSyz147064 DLADM_MAX_PROP_VALCNT + MAX_PROP_LINE); 467933343a97Smeem if (buf == NULL) 468033343a97Smeem die("insufficient memory"); 468133343a97Smeem 4682f4b3ec61Sdh155122 statep->ls_propvals = (char **)(void *)buf; 4683d62bc4baSyz147064 for (i = 0; i < DLADM_MAX_PROP_VALCNT; i++) { 4684d62bc4baSyz147064 statep->ls_propvals[i] = buf + 4685d62bc4baSyz147064 sizeof (char *) * DLADM_MAX_PROP_VALCNT + 46860ba2cbe9Sxc151355 i * DLADM_PROP_VAL_MAX; 46870ba2cbe9Sxc151355 } 4688f4b3ec61Sdh155122 statep->ls_line = buf + 4689d62bc4baSyz147064 (sizeof (char *) + DLADM_PROP_VAL_MAX) * DLADM_MAX_PROP_VALCNT; 46900ba2cbe9Sxc151355 46910ba2cbe9Sxc151355 if (proplist != NULL) { 4692d62bc4baSyz147064 for (i = 0; i < proplist->pl_count; i++) { 4693d62bc4baSyz147064 (void) show_linkprop(linkid, 4694d62bc4baSyz147064 proplist->pl_info[i].pi_name, statep); 46950ba2cbe9Sxc151355 } 4696d62bc4baSyz147064 } else { 4697d62bc4baSyz147064 (void) dladm_walk_linkprop(linkid, statep, show_linkprop); 4698d62bc4baSyz147064 } 4699d62bc4baSyz147064 if (dh != NULL) 4700948f2876Sss150715 dlpi_close(dh); 47010ba2cbe9Sxc151355 free(buf); 4702d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 47030ba2cbe9Sxc151355 } 47040ba2cbe9Sxc151355 47050ba2cbe9Sxc151355 static dladm_status_t 4706d62bc4baSyz147064 set_linkprop_persist(datalink_id_t linkid, const char *prop_name, 4707d62bc4baSyz147064 char **prop_val, uint_t val_cnt, boolean_t reset) 47080ba2cbe9Sxc151355 { 47090ba2cbe9Sxc151355 dladm_status_t status; 47100ba2cbe9Sxc151355 4711d62bc4baSyz147064 status = dladm_set_linkprop(linkid, prop_name, prop_val, val_cnt, 4712d62bc4baSyz147064 DLADM_OPT_PERSIST); 47130ba2cbe9Sxc151355 47140ba2cbe9Sxc151355 if (status != DLADM_STATUS_OK) { 4715d62bc4baSyz147064 warn_dlerr(status, "cannot persistently %s link property", 4716d62bc4baSyz147064 reset ? "reset" : "set"); 47170ba2cbe9Sxc151355 } 47180ba2cbe9Sxc151355 return (status); 47190ba2cbe9Sxc151355 } 47200ba2cbe9Sxc151355 47210ba2cbe9Sxc151355 static void 47228d5c46e6Sam223141 set_linkprop(int argc, char **argv, boolean_t reset, const char *use) 47230ba2cbe9Sxc151355 { 47240ba2cbe9Sxc151355 int i, option; 47250ba2cbe9Sxc151355 char errmsg[DLADM_STRSIZE]; 4726d62bc4baSyz147064 char *altroot = NULL; 4727d62bc4baSyz147064 datalink_id_t linkid; 47280ba2cbe9Sxc151355 prop_list_t *proplist = NULL; 47290ba2cbe9Sxc151355 boolean_t temp = B_FALSE; 47300ba2cbe9Sxc151355 dladm_status_t status = DLADM_STATUS_OK; 47310ba2cbe9Sxc151355 47320ba2cbe9Sxc151355 opterr = 0; 47330ba2cbe9Sxc151355 while ((option = getopt_long(argc, argv, ":p:R:t", 47340ba2cbe9Sxc151355 prop_longopts, NULL)) != -1) { 47350ba2cbe9Sxc151355 switch (option) { 47360ba2cbe9Sxc151355 case 'p': 473733343a97Smeem if (parse_props(optarg, &proplist, reset) < 0) 473833343a97Smeem die("invalid link properties specified"); 47390ba2cbe9Sxc151355 break; 47400ba2cbe9Sxc151355 case 't': 47410ba2cbe9Sxc151355 temp = B_TRUE; 47420ba2cbe9Sxc151355 break; 47430ba2cbe9Sxc151355 case 'R': 4744d62bc4baSyz147064 altroot = optarg; 47450ba2cbe9Sxc151355 break; 47460ba2cbe9Sxc151355 default: 47478d5c46e6Sam223141 die_opterr(optopt, option, use); 47488d5c46e6Sam223141 47490ba2cbe9Sxc151355 } 47500ba2cbe9Sxc151355 } 47510ba2cbe9Sxc151355 4752d62bc4baSyz147064 /* get link name (required last argument) */ 4753d62bc4baSyz147064 if (optind != (argc - 1)) 47540ba2cbe9Sxc151355 usage(); 47550ba2cbe9Sxc151355 4756d62bc4baSyz147064 if (proplist == NULL && !reset) 475733343a97Smeem die("link property must be specified"); 475833343a97Smeem 4759d62bc4baSyz147064 if (altroot != NULL) { 4760d62bc4baSyz147064 free_props(proplist); 4761d62bc4baSyz147064 altroot_cmd(altroot, argc, argv); 4762d62bc4baSyz147064 } 4763d62bc4baSyz147064 4764d62bc4baSyz147064 status = dladm_name2info(argv[optind], &linkid, NULL, NULL, NULL); 4765d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 4766d62bc4baSyz147064 die_dlerr(status, "link %s is not valid", argv[optind]); 4767d62bc4baSyz147064 4768d62bc4baSyz147064 if (proplist == NULL) { 4769e7801d59Ssowmini status = dladm_set_linkprop(linkid, NULL, NULL, 0, 4770e7801d59Ssowmini DLADM_OPT_ACTIVE); 4771e7801d59Ssowmini if (status != DLADM_STATUS_OK) { 4772d62bc4baSyz147064 warn_dlerr(status, "cannot reset link property " 4773d62bc4baSyz147064 "on '%s'", argv[optind]); 47740ba2cbe9Sxc151355 } 47750ba2cbe9Sxc151355 if (!temp) { 477613994ee8Sxz162242 dladm_status_t s; 477713994ee8Sxz162242 4778d62bc4baSyz147064 s = set_linkprop_persist(linkid, NULL, NULL, 0, reset); 477913994ee8Sxz162242 if (s != DLADM_STATUS_OK) 478013994ee8Sxz162242 status = s; 47810ba2cbe9Sxc151355 } 47820ba2cbe9Sxc151355 goto done; 47830ba2cbe9Sxc151355 } 47840ba2cbe9Sxc151355 47850ba2cbe9Sxc151355 for (i = 0; i < proplist->pl_count; i++) { 47860ba2cbe9Sxc151355 prop_info_t *pip = &proplist->pl_info[i]; 47870ba2cbe9Sxc151355 char **val; 47880ba2cbe9Sxc151355 uint_t count; 47890ba2cbe9Sxc151355 dladm_status_t s; 47900ba2cbe9Sxc151355 47910ba2cbe9Sxc151355 if (reset) { 47920ba2cbe9Sxc151355 val = NULL; 47930ba2cbe9Sxc151355 count = 0; 47940ba2cbe9Sxc151355 } else { 47950ba2cbe9Sxc151355 val = pip->pi_val; 47960ba2cbe9Sxc151355 count = pip->pi_count; 47970ba2cbe9Sxc151355 if (count == 0) { 479833343a97Smeem warn("no value specified for '%s'", 479933343a97Smeem pip->pi_name); 48000ba2cbe9Sxc151355 status = DLADM_STATUS_BADARG; 48010ba2cbe9Sxc151355 continue; 48020ba2cbe9Sxc151355 } 48030ba2cbe9Sxc151355 } 4804d62bc4baSyz147064 s = dladm_set_linkprop(linkid, pip->pi_name, val, count, 4805d62bc4baSyz147064 DLADM_OPT_ACTIVE); 48060ba2cbe9Sxc151355 if (s == DLADM_STATUS_OK) { 48070ba2cbe9Sxc151355 if (!temp) { 4808d62bc4baSyz147064 s = set_linkprop_persist(linkid, 48090ba2cbe9Sxc151355 pip->pi_name, val, count, reset); 48100ba2cbe9Sxc151355 if (s != DLADM_STATUS_OK) 48110ba2cbe9Sxc151355 status = s; 48120ba2cbe9Sxc151355 } 48130ba2cbe9Sxc151355 continue; 48140ba2cbe9Sxc151355 } 48150ba2cbe9Sxc151355 status = s; 48160ba2cbe9Sxc151355 switch (s) { 48170ba2cbe9Sxc151355 case DLADM_STATUS_NOTFOUND: 481833343a97Smeem warn("invalid link property '%s'", pip->pi_name); 48190ba2cbe9Sxc151355 break; 48200ba2cbe9Sxc151355 case DLADM_STATUS_BADVAL: { 48210ba2cbe9Sxc151355 int j; 48220ba2cbe9Sxc151355 char *ptr, *lim; 48230ba2cbe9Sxc151355 char **propvals = NULL; 4824d62bc4baSyz147064 uint_t valcnt = DLADM_MAX_PROP_VALCNT; 48250ba2cbe9Sxc151355 48260ba2cbe9Sxc151355 ptr = malloc((sizeof (char *) + 4827d62bc4baSyz147064 DLADM_PROP_VAL_MAX) * DLADM_MAX_PROP_VALCNT + 48280ba2cbe9Sxc151355 MAX_PROP_LINE); 48290ba2cbe9Sxc151355 48300ba2cbe9Sxc151355 propvals = (char **)(void *)ptr; 483133343a97Smeem if (propvals == NULL) 483233343a97Smeem die("insufficient memory"); 483333343a97Smeem 4834d62bc4baSyz147064 for (j = 0; j < DLADM_MAX_PROP_VALCNT; j++) { 48350ba2cbe9Sxc151355 propvals[j] = ptr + sizeof (char *) * 4836d62bc4baSyz147064 DLADM_MAX_PROP_VALCNT + 48370ba2cbe9Sxc151355 j * DLADM_PROP_VAL_MAX; 48380ba2cbe9Sxc151355 } 4839d62bc4baSyz147064 s = dladm_get_linkprop(linkid, 4840d62bc4baSyz147064 DLADM_PROP_VAL_MODIFIABLE, pip->pi_name, propvals, 4841d62bc4baSyz147064 &valcnt); 4842d62bc4baSyz147064 4843d62bc4baSyz147064 if (s != DLADM_STATUS_OK) { 4844d62bc4baSyz147064 warn_dlerr(status, "cannot set link property " 4845d62bc4baSyz147064 "'%s' on '%s'", pip->pi_name, argv[optind]); 4846d62bc4baSyz147064 free(propvals); 4847d62bc4baSyz147064 break; 4848d62bc4baSyz147064 } 48490ba2cbe9Sxc151355 48500ba2cbe9Sxc151355 ptr = errmsg; 48510ba2cbe9Sxc151355 lim = ptr + DLADM_STRSIZE; 48520ba2cbe9Sxc151355 *ptr = '\0'; 4853d62bc4baSyz147064 for (j = 0; j < valcnt; j++) { 48540ba2cbe9Sxc151355 ptr += snprintf(ptr, lim - ptr, "%s,", 48550ba2cbe9Sxc151355 propvals[j]); 48560ba2cbe9Sxc151355 if (ptr >= lim) 48570ba2cbe9Sxc151355 break; 48580ba2cbe9Sxc151355 } 4859f4b3ec61Sdh155122 if (ptr > errmsg) { 48600ba2cbe9Sxc151355 *(ptr - 1) = '\0'; 486133343a97Smeem warn("link property '%s' must be one of: %s", 486233343a97Smeem pip->pi_name, errmsg); 4863f4b3ec61Sdh155122 } else 4864f4b3ec61Sdh155122 warn("invalid link property '%s'", *val); 48650ba2cbe9Sxc151355 free(propvals); 48660ba2cbe9Sxc151355 break; 48670ba2cbe9Sxc151355 } 48680ba2cbe9Sxc151355 default: 48690ba2cbe9Sxc151355 if (reset) { 487033343a97Smeem warn_dlerr(status, "cannot reset link property " 4871d62bc4baSyz147064 "'%s' on '%s'", pip->pi_name, argv[optind]); 48720ba2cbe9Sxc151355 } else { 487333343a97Smeem warn_dlerr(status, "cannot set link property " 4874d62bc4baSyz147064 "'%s' on '%s'", pip->pi_name, argv[optind]); 48750ba2cbe9Sxc151355 } 48760ba2cbe9Sxc151355 break; 48770ba2cbe9Sxc151355 } 48780ba2cbe9Sxc151355 } 48790ba2cbe9Sxc151355 done: 48800ba2cbe9Sxc151355 free_props(proplist); 48810ba2cbe9Sxc151355 if (status != DLADM_STATUS_OK) 48820ba2cbe9Sxc151355 exit(1); 48830ba2cbe9Sxc151355 } 48840ba2cbe9Sxc151355 48850ba2cbe9Sxc151355 static void 48868d5c46e6Sam223141 do_set_linkprop(int argc, char **argv, const char *use) 48870ba2cbe9Sxc151355 { 48888d5c46e6Sam223141 set_linkprop(argc, argv, B_FALSE, use); 48890ba2cbe9Sxc151355 } 48900ba2cbe9Sxc151355 48910ba2cbe9Sxc151355 static void 48928d5c46e6Sam223141 do_reset_linkprop(int argc, char **argv, const char *use) 48930ba2cbe9Sxc151355 { 48948d5c46e6Sam223141 set_linkprop(argc, argv, B_TRUE, use); 48950ba2cbe9Sxc151355 } 48960ba2cbe9Sxc151355 48970ba2cbe9Sxc151355 static int 48980ba2cbe9Sxc151355 convert_secobj(char *buf, uint_t len, uint8_t *obj_val, uint_t *obj_lenp, 48990ba2cbe9Sxc151355 dladm_secobj_class_t class) 49000ba2cbe9Sxc151355 { 49010ba2cbe9Sxc151355 int error = 0; 49020ba2cbe9Sxc151355 4903a399b765Szf162725 if (class == DLADM_SECOBJ_CLASS_WPA) { 4904a399b765Szf162725 if (len < 8 || len > 63) 4905a399b765Szf162725 return (EINVAL); 4906a399b765Szf162725 (void) memcpy(obj_val, buf, len); 4907a399b765Szf162725 *obj_lenp = len; 4908a399b765Szf162725 return (error); 4909a399b765Szf162725 } 49100ba2cbe9Sxc151355 4911a399b765Szf162725 if (class == DLADM_SECOBJ_CLASS_WEP) { 49120ba2cbe9Sxc151355 switch (len) { 49130ba2cbe9Sxc151355 case 5: /* ASCII key sizes */ 49140ba2cbe9Sxc151355 case 13: 49150ba2cbe9Sxc151355 (void) memcpy(obj_val, buf, len); 49160ba2cbe9Sxc151355 *obj_lenp = len; 49170ba2cbe9Sxc151355 break; 49180ba2cbe9Sxc151355 case 10: /* Hex key sizes, not preceded by 0x */ 49190ba2cbe9Sxc151355 case 26: 49200ba2cbe9Sxc151355 error = hexascii_to_octet(buf, len, obj_val, obj_lenp); 49210ba2cbe9Sxc151355 break; 49220ba2cbe9Sxc151355 case 12: /* Hex key sizes, preceded by 0x */ 49230ba2cbe9Sxc151355 case 28: 49240ba2cbe9Sxc151355 if (strncmp(buf, "0x", 2) != 0) 49250ba2cbe9Sxc151355 return (EINVAL); 4926a399b765Szf162725 error = hexascii_to_octet(buf + 2, len - 2, 4927a399b765Szf162725 obj_val, obj_lenp); 49280ba2cbe9Sxc151355 break; 49290ba2cbe9Sxc151355 default: 49300ba2cbe9Sxc151355 return (EINVAL); 49310ba2cbe9Sxc151355 } 49320ba2cbe9Sxc151355 return (error); 49330ba2cbe9Sxc151355 } 49340ba2cbe9Sxc151355 4935a399b765Szf162725 return (ENOENT); 4936a399b765Szf162725 } 4937a399b765Szf162725 49380ba2cbe9Sxc151355 /* ARGSUSED */ 49390ba2cbe9Sxc151355 static void 49400ba2cbe9Sxc151355 defersig(int sig) 49410ba2cbe9Sxc151355 { 49420ba2cbe9Sxc151355 signalled = sig; 49430ba2cbe9Sxc151355 } 49440ba2cbe9Sxc151355 49450ba2cbe9Sxc151355 static int 49460ba2cbe9Sxc151355 get_secobj_from_tty(uint_t try, const char *objname, char *buf) 49470ba2cbe9Sxc151355 { 49480ba2cbe9Sxc151355 uint_t len = 0; 49490ba2cbe9Sxc151355 int c; 49500ba2cbe9Sxc151355 struct termios stored, current; 49510ba2cbe9Sxc151355 void (*sigfunc)(int); 49520ba2cbe9Sxc151355 49530ba2cbe9Sxc151355 /* 49540ba2cbe9Sxc151355 * Turn off echo -- but before we do so, defer SIGINT handling 49550ba2cbe9Sxc151355 * so that a ^C doesn't leave the terminal corrupted. 49560ba2cbe9Sxc151355 */ 49570ba2cbe9Sxc151355 sigfunc = signal(SIGINT, defersig); 49580ba2cbe9Sxc151355 (void) fflush(stdin); 49590ba2cbe9Sxc151355 (void) tcgetattr(0, &stored); 49600ba2cbe9Sxc151355 current = stored; 49610ba2cbe9Sxc151355 current.c_lflag &= ~(ICANON|ECHO); 49620ba2cbe9Sxc151355 current.c_cc[VTIME] = 0; 49630ba2cbe9Sxc151355 current.c_cc[VMIN] = 1; 49640ba2cbe9Sxc151355 (void) tcsetattr(0, TCSANOW, ¤t); 49650ba2cbe9Sxc151355 again: 49660ba2cbe9Sxc151355 if (try == 1) 49670ba2cbe9Sxc151355 (void) printf(gettext("provide value for '%s': "), objname); 49680ba2cbe9Sxc151355 else 49690ba2cbe9Sxc151355 (void) printf(gettext("confirm value for '%s': "), objname); 49700ba2cbe9Sxc151355 49710ba2cbe9Sxc151355 (void) fflush(stdout); 49720ba2cbe9Sxc151355 while (signalled == 0) { 49730ba2cbe9Sxc151355 c = getchar(); 49740ba2cbe9Sxc151355 if (c == '\n' || c == '\r') { 49750ba2cbe9Sxc151355 if (len != 0) 49760ba2cbe9Sxc151355 break; 49770ba2cbe9Sxc151355 (void) putchar('\n'); 49780ba2cbe9Sxc151355 goto again; 49790ba2cbe9Sxc151355 } 49800ba2cbe9Sxc151355 49810ba2cbe9Sxc151355 buf[len++] = c; 49820ba2cbe9Sxc151355 if (len >= DLADM_SECOBJ_VAL_MAX - 1) 49830ba2cbe9Sxc151355 break; 49840ba2cbe9Sxc151355 (void) putchar('*'); 49850ba2cbe9Sxc151355 } 49860ba2cbe9Sxc151355 49870ba2cbe9Sxc151355 (void) putchar('\n'); 49880ba2cbe9Sxc151355 (void) fflush(stdin); 49890ba2cbe9Sxc151355 49900ba2cbe9Sxc151355 /* 49910ba2cbe9Sxc151355 * Restore terminal setting and handle deferred signals. 49920ba2cbe9Sxc151355 */ 49930ba2cbe9Sxc151355 (void) tcsetattr(0, TCSANOW, &stored); 49940ba2cbe9Sxc151355 49950ba2cbe9Sxc151355 (void) signal(SIGINT, sigfunc); 49960ba2cbe9Sxc151355 if (signalled != 0) 49970ba2cbe9Sxc151355 (void) kill(getpid(), signalled); 49980ba2cbe9Sxc151355 49990ba2cbe9Sxc151355 return (len); 50000ba2cbe9Sxc151355 } 50010ba2cbe9Sxc151355 50020ba2cbe9Sxc151355 static int 50030ba2cbe9Sxc151355 get_secobj_val(char *obj_name, uint8_t *obj_val, uint_t *obj_lenp, 50040ba2cbe9Sxc151355 dladm_secobj_class_t class, FILE *filep) 50050ba2cbe9Sxc151355 { 50060ba2cbe9Sxc151355 int rval; 50070ba2cbe9Sxc151355 uint_t len, len2; 50080ba2cbe9Sxc151355 char buf[DLADM_SECOBJ_VAL_MAX], buf2[DLADM_SECOBJ_VAL_MAX]; 50090ba2cbe9Sxc151355 50100ba2cbe9Sxc151355 if (filep == NULL) { 50110ba2cbe9Sxc151355 len = get_secobj_from_tty(1, obj_name, buf); 50120ba2cbe9Sxc151355 rval = convert_secobj(buf, len, obj_val, obj_lenp, class); 50130ba2cbe9Sxc151355 if (rval == 0) { 50140ba2cbe9Sxc151355 len2 = get_secobj_from_tty(2, obj_name, buf2); 50150ba2cbe9Sxc151355 if (len != len2 || memcmp(buf, buf2, len) != 0) 50160ba2cbe9Sxc151355 rval = ENOTSUP; 50170ba2cbe9Sxc151355 } 50180ba2cbe9Sxc151355 return (rval); 50190ba2cbe9Sxc151355 } else { 50200ba2cbe9Sxc151355 for (;;) { 50210ba2cbe9Sxc151355 if (fgets(buf, sizeof (buf), filep) == NULL) 50220ba2cbe9Sxc151355 break; 50230ba2cbe9Sxc151355 if (isspace(buf[0])) 50240ba2cbe9Sxc151355 continue; 50250ba2cbe9Sxc151355 50260ba2cbe9Sxc151355 len = strlen(buf); 50270ba2cbe9Sxc151355 if (buf[len - 1] == '\n') { 50280ba2cbe9Sxc151355 buf[len - 1] = '\0'; 50290ba2cbe9Sxc151355 len--; 50300ba2cbe9Sxc151355 } 50310ba2cbe9Sxc151355 break; 50320ba2cbe9Sxc151355 } 50330ba2cbe9Sxc151355 (void) fclose(filep); 50340ba2cbe9Sxc151355 } 50350ba2cbe9Sxc151355 return (convert_secobj(buf, len, obj_val, obj_lenp, class)); 50360ba2cbe9Sxc151355 } 50370ba2cbe9Sxc151355 50380ba2cbe9Sxc151355 static boolean_t 50390ba2cbe9Sxc151355 check_auth(const char *auth) 50400ba2cbe9Sxc151355 { 50410ba2cbe9Sxc151355 struct passwd *pw; 50420ba2cbe9Sxc151355 50430ba2cbe9Sxc151355 if ((pw = getpwuid(getuid())) == NULL) 50440ba2cbe9Sxc151355 return (B_FALSE); 50450ba2cbe9Sxc151355 50460ba2cbe9Sxc151355 return (chkauthattr(auth, pw->pw_name) != 0); 50470ba2cbe9Sxc151355 } 50480ba2cbe9Sxc151355 50490ba2cbe9Sxc151355 static void 50500ba2cbe9Sxc151355 audit_secobj(char *auth, char *class, char *obj, 50510ba2cbe9Sxc151355 boolean_t success, boolean_t create) 50520ba2cbe9Sxc151355 { 50530ba2cbe9Sxc151355 adt_session_data_t *ah; 50540ba2cbe9Sxc151355 adt_event_data_t *event; 50550ba2cbe9Sxc151355 au_event_t flag; 50560ba2cbe9Sxc151355 char *errstr; 50570ba2cbe9Sxc151355 50580ba2cbe9Sxc151355 if (create) { 50590ba2cbe9Sxc151355 flag = ADT_dladm_create_secobj; 50600ba2cbe9Sxc151355 errstr = "ADT_dladm_create_secobj"; 50610ba2cbe9Sxc151355 } else { 50620ba2cbe9Sxc151355 flag = ADT_dladm_delete_secobj; 50630ba2cbe9Sxc151355 errstr = "ADT_dladm_delete_secobj"; 50640ba2cbe9Sxc151355 } 50650ba2cbe9Sxc151355 506633343a97Smeem if (adt_start_session(&ah, NULL, ADT_USE_PROC_DATA) != 0) 506733343a97Smeem die("adt_start_session: %s", strerror(errno)); 50680ba2cbe9Sxc151355 506933343a97Smeem if ((event = adt_alloc_event(ah, flag)) == NULL) 507033343a97Smeem die("adt_alloc_event (%s): %s", errstr, strerror(errno)); 50710ba2cbe9Sxc151355 50720ba2cbe9Sxc151355 /* fill in audit info */ 50730ba2cbe9Sxc151355 if (create) { 50740ba2cbe9Sxc151355 event->adt_dladm_create_secobj.auth_used = auth; 50750ba2cbe9Sxc151355 event->adt_dladm_create_secobj.obj_class = class; 50760ba2cbe9Sxc151355 event->adt_dladm_create_secobj.obj_name = obj; 50770ba2cbe9Sxc151355 } else { 50780ba2cbe9Sxc151355 event->adt_dladm_delete_secobj.auth_used = auth; 50790ba2cbe9Sxc151355 event->adt_dladm_delete_secobj.obj_class = class; 50800ba2cbe9Sxc151355 event->adt_dladm_delete_secobj.obj_name = obj; 50810ba2cbe9Sxc151355 } 50820ba2cbe9Sxc151355 50830ba2cbe9Sxc151355 if (success) { 50840ba2cbe9Sxc151355 if (adt_put_event(event, ADT_SUCCESS, ADT_SUCCESS) != 0) { 508533343a97Smeem die("adt_put_event (%s, success): %s", errstr, 508633343a97Smeem strerror(errno)); 50870ba2cbe9Sxc151355 } 50880ba2cbe9Sxc151355 } else { 50890ba2cbe9Sxc151355 if (adt_put_event(event, ADT_FAILURE, 50900ba2cbe9Sxc151355 ADT_FAIL_VALUE_AUTH) != 0) { 509133343a97Smeem die("adt_put_event: (%s, failure): %s", errstr, 509233343a97Smeem strerror(errno)); 50930ba2cbe9Sxc151355 } 50940ba2cbe9Sxc151355 } 50950ba2cbe9Sxc151355 50960ba2cbe9Sxc151355 adt_free_event(event); 50970ba2cbe9Sxc151355 (void) adt_end_session(ah); 50980ba2cbe9Sxc151355 } 50990ba2cbe9Sxc151355 51000ba2cbe9Sxc151355 #define MAX_SECOBJS 32 51010ba2cbe9Sxc151355 #define MAX_SECOBJ_NAMELEN 32 51020ba2cbe9Sxc151355 static void 51038d5c46e6Sam223141 do_create_secobj(int argc, char **argv, const char *use) 51040ba2cbe9Sxc151355 { 51050ba2cbe9Sxc151355 int option, rval; 51060ba2cbe9Sxc151355 FILE *filep = NULL; 51070ba2cbe9Sxc151355 char *obj_name = NULL; 51080ba2cbe9Sxc151355 char *class_name = NULL; 51090ba2cbe9Sxc151355 uint8_t obj_val[DLADM_SECOBJ_VAL_MAX]; 51100ba2cbe9Sxc151355 uint_t obj_len; 51110ba2cbe9Sxc151355 boolean_t success, temp = B_FALSE; 51120ba2cbe9Sxc151355 dladm_status_t status; 51130ba2cbe9Sxc151355 dladm_secobj_class_t class = -1; 51140ba2cbe9Sxc151355 uid_t euid; 51150ba2cbe9Sxc151355 51160ba2cbe9Sxc151355 opterr = 0; 51170ba2cbe9Sxc151355 (void) memset(obj_val, 0, DLADM_SECOBJ_VAL_MAX); 51180ba2cbe9Sxc151355 while ((option = getopt_long(argc, argv, ":f:c:R:t", 51190ba2cbe9Sxc151355 wifi_longopts, NULL)) != -1) { 51200ba2cbe9Sxc151355 switch (option) { 51210ba2cbe9Sxc151355 case 'f': 51220ba2cbe9Sxc151355 euid = geteuid(); 51230ba2cbe9Sxc151355 (void) seteuid(getuid()); 51240ba2cbe9Sxc151355 filep = fopen(optarg, "r"); 51250ba2cbe9Sxc151355 if (filep == NULL) { 512633343a97Smeem die("cannot open %s: %s", optarg, 512733343a97Smeem strerror(errno)); 51280ba2cbe9Sxc151355 } 51290ba2cbe9Sxc151355 (void) seteuid(euid); 51300ba2cbe9Sxc151355 break; 51310ba2cbe9Sxc151355 case 'c': 51320ba2cbe9Sxc151355 class_name = optarg; 51330ba2cbe9Sxc151355 status = dladm_str2secobjclass(optarg, &class); 51340ba2cbe9Sxc151355 if (status != DLADM_STATUS_OK) { 513533343a97Smeem die("invalid secure object class '%s', " 5136a399b765Szf162725 "valid values are: wep, wpa", optarg); 51370ba2cbe9Sxc151355 } 51380ba2cbe9Sxc151355 break; 51390ba2cbe9Sxc151355 case 't': 51400ba2cbe9Sxc151355 temp = B_TRUE; 51410ba2cbe9Sxc151355 break; 51420ba2cbe9Sxc151355 case 'R': 51430ba2cbe9Sxc151355 status = dladm_set_rootdir(optarg); 51440ba2cbe9Sxc151355 if (status != DLADM_STATUS_OK) { 514533343a97Smeem die_dlerr(status, "invalid directory " 514633343a97Smeem "specified"); 51470ba2cbe9Sxc151355 } 51480ba2cbe9Sxc151355 break; 51490ba2cbe9Sxc151355 default: 51508d5c46e6Sam223141 die_opterr(optopt, option, use); 51510ba2cbe9Sxc151355 break; 51520ba2cbe9Sxc151355 } 51530ba2cbe9Sxc151355 } 51540ba2cbe9Sxc151355 51550ba2cbe9Sxc151355 if (optind == (argc - 1)) 51560ba2cbe9Sxc151355 obj_name = argv[optind]; 51570ba2cbe9Sxc151355 else if (optind != argc) 51580ba2cbe9Sxc151355 usage(); 51590ba2cbe9Sxc151355 516033343a97Smeem if (class == -1) 516133343a97Smeem die("secure object class required"); 51620ba2cbe9Sxc151355 516333343a97Smeem if (obj_name == NULL) 516433343a97Smeem die("secure object name required"); 51650ba2cbe9Sxc151355 51660ba2cbe9Sxc151355 success = check_auth(LINK_SEC_AUTH); 51670ba2cbe9Sxc151355 audit_secobj(LINK_SEC_AUTH, class_name, obj_name, success, B_TRUE); 516833343a97Smeem if (!success) 516933343a97Smeem die("authorization '%s' is required", LINK_SEC_AUTH); 51700ba2cbe9Sxc151355 517133343a97Smeem rval = get_secobj_val(obj_name, obj_val, &obj_len, class, filep); 517233343a97Smeem if (rval != 0) { 51730ba2cbe9Sxc151355 switch (rval) { 51740ba2cbe9Sxc151355 case ENOENT: 517533343a97Smeem die("invalid secure object class"); 51760ba2cbe9Sxc151355 break; 51770ba2cbe9Sxc151355 case EINVAL: 517833343a97Smeem die("invalid secure object value"); 51790ba2cbe9Sxc151355 break; 51800ba2cbe9Sxc151355 case ENOTSUP: 518133343a97Smeem die("verification failed"); 51820ba2cbe9Sxc151355 break; 51830ba2cbe9Sxc151355 default: 518433343a97Smeem die("invalid secure object: %s", strerror(rval)); 51850ba2cbe9Sxc151355 break; 51860ba2cbe9Sxc151355 } 51870ba2cbe9Sxc151355 } 51880ba2cbe9Sxc151355 51890ba2cbe9Sxc151355 status = dladm_set_secobj(obj_name, class, obj_val, obj_len, 5190d62bc4baSyz147064 DLADM_OPT_CREATE | DLADM_OPT_ACTIVE); 51910ba2cbe9Sxc151355 if (status != DLADM_STATUS_OK) { 519233343a97Smeem die_dlerr(status, "could not create secure object '%s'", 519333343a97Smeem obj_name); 51940ba2cbe9Sxc151355 } 51950ba2cbe9Sxc151355 if (temp) 51960ba2cbe9Sxc151355 return; 51970ba2cbe9Sxc151355 51980ba2cbe9Sxc151355 status = dladm_set_secobj(obj_name, class, obj_val, obj_len, 51990ba2cbe9Sxc151355 DLADM_OPT_PERSIST); 52000ba2cbe9Sxc151355 if (status != DLADM_STATUS_OK) { 520133343a97Smeem warn_dlerr(status, "could not persistently create secure " 520233343a97Smeem "object '%s'", obj_name); 52030ba2cbe9Sxc151355 } 52040ba2cbe9Sxc151355 } 52050ba2cbe9Sxc151355 52060ba2cbe9Sxc151355 static void 52078d5c46e6Sam223141 do_delete_secobj(int argc, char **argv, const char *use) 52080ba2cbe9Sxc151355 { 52090ba2cbe9Sxc151355 int i, option; 52100ba2cbe9Sxc151355 boolean_t temp = B_FALSE; 52110ba2cbe9Sxc151355 split_t *sp = NULL; 52120ba2cbe9Sxc151355 boolean_t success; 52130ba2cbe9Sxc151355 dladm_status_t status, pstatus; 52140ba2cbe9Sxc151355 52150ba2cbe9Sxc151355 opterr = 0; 52160ba2cbe9Sxc151355 status = pstatus = DLADM_STATUS_OK; 521733343a97Smeem while ((option = getopt_long(argc, argv, ":R:t", 52180ba2cbe9Sxc151355 wifi_longopts, NULL)) != -1) { 52190ba2cbe9Sxc151355 switch (option) { 52200ba2cbe9Sxc151355 case 't': 52210ba2cbe9Sxc151355 temp = B_TRUE; 52220ba2cbe9Sxc151355 break; 52230ba2cbe9Sxc151355 case 'R': 52240ba2cbe9Sxc151355 status = dladm_set_rootdir(optarg); 52250ba2cbe9Sxc151355 if (status != DLADM_STATUS_OK) { 522633343a97Smeem die_dlerr(status, "invalid directory " 522733343a97Smeem "specified"); 52280ba2cbe9Sxc151355 } 52290ba2cbe9Sxc151355 break; 52300ba2cbe9Sxc151355 default: 52318d5c46e6Sam223141 die_opterr(optopt, option, use); 52320ba2cbe9Sxc151355 break; 52330ba2cbe9Sxc151355 } 52340ba2cbe9Sxc151355 } 52350ba2cbe9Sxc151355 52360ba2cbe9Sxc151355 if (optind == (argc - 1)) { 52370ba2cbe9Sxc151355 sp = split(argv[optind], MAX_SECOBJS, MAX_SECOBJ_NAMELEN); 52380ba2cbe9Sxc151355 if (sp == NULL) { 523933343a97Smeem die("invalid secure object name(s): '%s'", 524033343a97Smeem argv[optind]); 52410ba2cbe9Sxc151355 } 52420ba2cbe9Sxc151355 } else if (optind != argc) 52430ba2cbe9Sxc151355 usage(); 52440ba2cbe9Sxc151355 524533343a97Smeem if (sp == NULL || sp->s_nfields < 1) 524633343a97Smeem die("secure object name required"); 52470ba2cbe9Sxc151355 52480ba2cbe9Sxc151355 success = check_auth(LINK_SEC_AUTH); 5249a399b765Szf162725 audit_secobj(LINK_SEC_AUTH, "unknown", argv[optind], success, B_FALSE); 525033343a97Smeem if (!success) 525133343a97Smeem die("authorization '%s' is required", LINK_SEC_AUTH); 52520ba2cbe9Sxc151355 52530ba2cbe9Sxc151355 for (i = 0; i < sp->s_nfields; i++) { 5254d62bc4baSyz147064 status = dladm_unset_secobj(sp->s_fields[i], DLADM_OPT_ACTIVE); 52550ba2cbe9Sxc151355 if (!temp) { 52560ba2cbe9Sxc151355 pstatus = dladm_unset_secobj(sp->s_fields[i], 52570ba2cbe9Sxc151355 DLADM_OPT_PERSIST); 52580ba2cbe9Sxc151355 } else { 52590ba2cbe9Sxc151355 pstatus = DLADM_STATUS_OK; 52600ba2cbe9Sxc151355 } 52610ba2cbe9Sxc151355 52620ba2cbe9Sxc151355 if (status != DLADM_STATUS_OK) { 526333343a97Smeem warn_dlerr(status, "could not delete secure object " 526433343a97Smeem "'%s'", sp->s_fields[i]); 52650ba2cbe9Sxc151355 } 52660ba2cbe9Sxc151355 if (pstatus != DLADM_STATUS_OK) { 526733343a97Smeem warn_dlerr(pstatus, "could not persistently delete " 526833343a97Smeem "secure object '%s'", sp->s_fields[i]); 52690ba2cbe9Sxc151355 } 52700ba2cbe9Sxc151355 } 52710ba2cbe9Sxc151355 if (status != DLADM_STATUS_OK || pstatus != DLADM_STATUS_OK) 52720ba2cbe9Sxc151355 exit(1); 52730ba2cbe9Sxc151355 } 52740ba2cbe9Sxc151355 52750ba2cbe9Sxc151355 typedef struct show_secobj_state { 52760ba2cbe9Sxc151355 boolean_t ss_persist; 52770ba2cbe9Sxc151355 boolean_t ss_parseable; 52780ba2cbe9Sxc151355 boolean_t ss_header; 5279e7801d59Ssowmini print_state_t ss_print; 52800ba2cbe9Sxc151355 } show_secobj_state_t; 52810ba2cbe9Sxc151355 52820ba2cbe9Sxc151355 52830ba2cbe9Sxc151355 static boolean_t 52840ba2cbe9Sxc151355 show_secobj(void *arg, const char *obj_name) 52850ba2cbe9Sxc151355 { 52860ba2cbe9Sxc151355 uint_t obj_len = DLADM_SECOBJ_VAL_MAX; 52870ba2cbe9Sxc151355 uint8_t obj_val[DLADM_SECOBJ_VAL_MAX]; 52880ba2cbe9Sxc151355 char buf[DLADM_STRSIZE]; 52890ba2cbe9Sxc151355 uint_t flags = 0; 52900ba2cbe9Sxc151355 dladm_secobj_class_t class; 52910ba2cbe9Sxc151355 show_secobj_state_t *statep = arg; 52920ba2cbe9Sxc151355 dladm_status_t status; 5293e7801d59Ssowmini secobj_fields_buf_t sbuf; 52940ba2cbe9Sxc151355 52955f5c9f54SAnurag S. Maskey bzero(&sbuf, sizeof (secobj_fields_buf_t)); 52960ba2cbe9Sxc151355 if (statep->ss_persist) 52970ba2cbe9Sxc151355 flags |= DLADM_OPT_PERSIST; 52980ba2cbe9Sxc151355 52990ba2cbe9Sxc151355 status = dladm_get_secobj(obj_name, &class, obj_val, &obj_len, flags); 530033343a97Smeem if (status != DLADM_STATUS_OK) 530133343a97Smeem die_dlerr(status, "cannot get secure object '%s'", obj_name); 53020ba2cbe9Sxc151355 53030ba2cbe9Sxc151355 if (statep->ss_header) { 53040ba2cbe9Sxc151355 statep->ss_header = B_FALSE; 53050ba2cbe9Sxc151355 if (!statep->ss_parseable) 5306e7801d59Ssowmini print_header(&statep->ss_print); 53070ba2cbe9Sxc151355 } 53080ba2cbe9Sxc151355 5309e7801d59Ssowmini (void) snprintf(sbuf.ss_obj_name, sizeof (sbuf.ss_obj_name), 5310e7801d59Ssowmini obj_name); 5311e7801d59Ssowmini (void) dladm_secobjclass2str(class, buf); 5312e7801d59Ssowmini (void) snprintf(sbuf.ss_class, sizeof (sbuf.ss_class), "%s", buf); 5313e7801d59Ssowmini if (getuid() == 0) { 53140ba2cbe9Sxc151355 char val[DLADM_SECOBJ_VAL_MAX * 2]; 53150ba2cbe9Sxc151355 uint_t len = sizeof (val); 53160ba2cbe9Sxc151355 5317e7801d59Ssowmini if (octet_to_hexascii(obj_val, obj_len, val, &len) == 0) 5318e7801d59Ssowmini (void) snprintf(sbuf.ss_val, 5319e7801d59Ssowmini sizeof (sbuf.ss_val), "%s", val); 53200ba2cbe9Sxc151355 } 5321e7801d59Ssowmini dladm_print_output(&statep->ss_print, statep->ss_parseable, 5322e7801d59Ssowmini dladm_print_field, (void *)&sbuf); 53230ba2cbe9Sxc151355 return (B_TRUE); 53240ba2cbe9Sxc151355 } 53250ba2cbe9Sxc151355 53260ba2cbe9Sxc151355 static void 53278d5c46e6Sam223141 do_show_secobj(int argc, char **argv, const char *use) 53280ba2cbe9Sxc151355 { 53290ba2cbe9Sxc151355 int option; 53300ba2cbe9Sxc151355 show_secobj_state_t state; 53310ba2cbe9Sxc151355 dladm_status_t status; 53320d365605Sschuster boolean_t o_arg = B_FALSE; 53330ba2cbe9Sxc151355 uint_t i; 53340ba2cbe9Sxc151355 split_t *sp; 53350ba2cbe9Sxc151355 uint_t flags; 5336e7801d59Ssowmini char *fields_str = NULL; 5337e7801d59Ssowmini print_field_t **fields; 5338e7801d59Ssowmini uint_t nfields; 5339e7801d59Ssowmini char *def_fields = "object,class"; 5340e7801d59Ssowmini char *all_fields = "object,class,value"; 53410ba2cbe9Sxc151355 53420ba2cbe9Sxc151355 opterr = 0; 5343e7801d59Ssowmini bzero(&state, sizeof (state)); 5344e7801d59Ssowmini state.ss_parseable = B_FALSE; 5345e7801d59Ssowmini fields_str = def_fields; 53460ba2cbe9Sxc151355 state.ss_persist = B_FALSE; 53470ba2cbe9Sxc151355 state.ss_parseable = B_FALSE; 53480ba2cbe9Sxc151355 state.ss_header = B_TRUE; 5349e7801d59Ssowmini while ((option = getopt_long(argc, argv, ":pPo:", 53500ba2cbe9Sxc151355 wifi_longopts, NULL)) != -1) { 53510ba2cbe9Sxc151355 switch (option) { 53520ba2cbe9Sxc151355 case 'p': 53530ba2cbe9Sxc151355 state.ss_parseable = B_TRUE; 53540ba2cbe9Sxc151355 break; 53550ba2cbe9Sxc151355 case 'P': 53560ba2cbe9Sxc151355 state.ss_persist = B_TRUE; 53570ba2cbe9Sxc151355 break; 5358e7801d59Ssowmini case 'o': 53590d365605Sschuster o_arg = B_TRUE; 5360e7801d59Ssowmini if (strcasecmp(optarg, "all") == 0) 5361e7801d59Ssowmini fields_str = all_fields; 5362e7801d59Ssowmini else 5363e7801d59Ssowmini fields_str = optarg; 53640ba2cbe9Sxc151355 break; 53650ba2cbe9Sxc151355 default: 53668d5c46e6Sam223141 die_opterr(optopt, option, use); 53670ba2cbe9Sxc151355 break; 53680ba2cbe9Sxc151355 } 53690ba2cbe9Sxc151355 } 53700ba2cbe9Sxc151355 53710d365605Sschuster if (state.ss_parseable && !o_arg) 53720d365605Sschuster die("option -c requires -o"); 53730d365605Sschuster 53740d365605Sschuster if (state.ss_parseable && fields_str == all_fields) 53750d365605Sschuster die("\"-o all\" is invalid with -p"); 53760d365605Sschuster 5377e7801d59Ssowmini fields = parse_output_fields(fields_str, secobj_fields, 5378e7801d59Ssowmini DEV_SOBJ_FIELDS, CMD_TYPE_ANY, &nfields); 5379e7801d59Ssowmini 5380e7801d59Ssowmini if (fields == NULL) { 5381e7801d59Ssowmini die("invalid field(s) specified"); 5382e7801d59Ssowmini return; 5383e7801d59Ssowmini } 5384e7801d59Ssowmini state.ss_print.ps_fields = fields; 5385e7801d59Ssowmini state.ss_print.ps_nfields = nfields; 5386e7801d59Ssowmini 5387e7801d59Ssowmini flags = state.ss_persist ? DLADM_OPT_PERSIST : 0; 53880ba2cbe9Sxc151355 if (optind == (argc - 1)) { 53890ba2cbe9Sxc151355 sp = split(argv[optind], MAX_SECOBJS, MAX_SECOBJ_NAMELEN); 53900ba2cbe9Sxc151355 if (sp == NULL) { 539133343a97Smeem die("invalid secure object name(s): '%s'", 539233343a97Smeem argv[optind]); 53930ba2cbe9Sxc151355 } 53940ba2cbe9Sxc151355 for (i = 0; i < sp->s_nfields; i++) { 53950ba2cbe9Sxc151355 if (!show_secobj(&state, sp->s_fields[i])) 53960ba2cbe9Sxc151355 break; 53970ba2cbe9Sxc151355 } 53980ba2cbe9Sxc151355 splitfree(sp); 53990ba2cbe9Sxc151355 return; 54000ba2cbe9Sxc151355 } else if (optind != argc) 54010ba2cbe9Sxc151355 usage(); 54020ba2cbe9Sxc151355 54030ba2cbe9Sxc151355 status = dladm_walk_secobj(&state, show_secobj, flags); 540433343a97Smeem if (status != DLADM_STATUS_OK) 540533343a97Smeem die_dlerr(status, "show-secobj"); 54060ba2cbe9Sxc151355 } 54070ba2cbe9Sxc151355 54080ba2cbe9Sxc151355 /*ARGSUSED*/ 5409d62bc4baSyz147064 static int 5410d62bc4baSyz147064 i_dladm_init_linkprop(datalink_id_t linkid, void *arg) 5411d62bc4baSyz147064 { 541230890389Sartem (void) dladm_init_linkprop(linkid, B_TRUE); 5413d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 5414d62bc4baSyz147064 } 5415d62bc4baSyz147064 54168d5c46e6Sam223141 /*ARGSUSED*/ 54170ba2cbe9Sxc151355 static void 54188d5c46e6Sam223141 do_init_linkprop(int argc, char **argv, const char *use) 54190ba2cbe9Sxc151355 { 542030890389Sartem int option; 542130890389Sartem dladm_status_t status; 542230890389Sartem datalink_id_t linkid = DATALINK_ALL_LINKID; 542330890389Sartem datalink_media_t media = DATALINK_ANY_MEDIATYPE; 542430890389Sartem uint_t any_media = B_TRUE; 542530890389Sartem 542630890389Sartem opterr = 0; 542730890389Sartem while ((option = getopt(argc, argv, ":w")) != -1) { 542830890389Sartem switch (option) { 542930890389Sartem case 'w': 543030890389Sartem media = DL_WIFI; 543130890389Sartem any_media = B_FALSE; 543230890389Sartem break; 543330890389Sartem default: 54348d5c46e6Sam223141 /* 54358d5c46e6Sam223141 * Because init-linkprop is not a public command, 54368d5c46e6Sam223141 * print the usage instead. 54378d5c46e6Sam223141 */ 54388d5c46e6Sam223141 usage(); 543930890389Sartem break; 544030890389Sartem } 544130890389Sartem } 544230890389Sartem 544330890389Sartem if (optind == (argc - 1)) { 544430890389Sartem if ((status = dladm_name2info(argv[optind], &linkid, NULL, NULL, 544530890389Sartem NULL)) != DLADM_STATUS_OK) 544630890389Sartem die_dlerr(status, "link %s is not valid", argv[optind]); 544730890389Sartem } else if (optind != argc) { 544830890389Sartem usage(); 544930890389Sartem } 545030890389Sartem 545130890389Sartem if (linkid == DATALINK_ALL_LINKID) { 5452d62bc4baSyz147064 /* 545330890389Sartem * linkprops of links of other classes have been initialized as 5454d62bc4baSyz147064 * part of the dladm up-xxx operation. 5455d62bc4baSyz147064 */ 5456d62bc4baSyz147064 (void) dladm_walk_datalink_id(i_dladm_init_linkprop, NULL, 545730890389Sartem DATALINK_CLASS_PHYS, media, DLADM_OPT_PERSIST); 545830890389Sartem } else { 545930890389Sartem (void) dladm_init_linkprop(linkid, any_media); 546030890389Sartem } 54610ba2cbe9Sxc151355 } 54620ba2cbe9Sxc151355 54630ba2cbe9Sxc151355 /* ARGSUSED */ 54640ba2cbe9Sxc151355 static void 54658d5c46e6Sam223141 do_show_ether(int argc, char **argv, const char *use) 5466e7801d59Ssowmini { 5467e7801d59Ssowmini int option; 5468e7801d59Ssowmini datalink_id_t linkid; 5469e7801d59Ssowmini print_ether_state_t state; 5470e7801d59Ssowmini print_field_t **fields; 54710d365605Sschuster boolean_t o_arg = B_FALSE; 5472e7801d59Ssowmini char *fields_str; 5473e7801d59Ssowmini uint_t nfields; 5474e7801d59Ssowmini char *all_fields = 5475e7801d59Ssowmini "link,ptype,state,auto,speed-duplex,pause,rem_fault"; 5476e7801d59Ssowmini char *default_fields = 5477e7801d59Ssowmini "link,ptype,state,auto,speed-duplex,pause"; 5478e7801d59Ssowmini 5479e7801d59Ssowmini fields_str = default_fields; 5480e7801d59Ssowmini bzero(&state, sizeof (state)); 5481e7801d59Ssowmini state.es_link = NULL; 5482e7801d59Ssowmini state.es_parseable = B_FALSE; 5483e7801d59Ssowmini 5484e7801d59Ssowmini while ((option = getopt_long(argc, argv, "o:px", 5485e7801d59Ssowmini showeth_lopts, NULL)) != -1) { 5486e7801d59Ssowmini switch (option) { 5487e7801d59Ssowmini case 'x': 5488e7801d59Ssowmini state.es_extended = B_TRUE; 5489e7801d59Ssowmini break; 5490e7801d59Ssowmini case 'p': 5491e7801d59Ssowmini state.es_parseable = B_TRUE; 5492e7801d59Ssowmini break; 5493e7801d59Ssowmini case 'o': 54940d365605Sschuster o_arg = B_TRUE; 5495e7801d59Ssowmini if (strcasecmp(optarg, "all") == 0) 5496e7801d59Ssowmini fields_str = all_fields; 5497e7801d59Ssowmini else 5498e7801d59Ssowmini fields_str = optarg; 5499e7801d59Ssowmini break; 5500e7801d59Ssowmini default: 55018d5c46e6Sam223141 die_opterr(optopt, option, use); 5502e7801d59Ssowmini break; 5503e7801d59Ssowmini } 5504e7801d59Ssowmini } 5505e7801d59Ssowmini 55060d365605Sschuster if (state.es_parseable && !o_arg) 55070d365605Sschuster die("-p requires -o"); 55080d365605Sschuster 55090d365605Sschuster if (state.es_parseable && fields_str == all_fields) 55100d365605Sschuster die("\"-o all\" is invalid with -p"); 55110d365605Sschuster 5512e7801d59Ssowmini if (optind == (argc - 1)) 5513e7801d59Ssowmini state.es_link = argv[optind]; 5514e7801d59Ssowmini 5515e7801d59Ssowmini fields = parse_output_fields(fields_str, ether_fields, 5516e7801d59Ssowmini ETHER_MAX_FIELDS, CMD_TYPE_ANY, &nfields); 5517e7801d59Ssowmini 5518e7801d59Ssowmini if (fields == NULL) { 5519e7801d59Ssowmini die("invalid field(s) specified"); 5520e7801d59Ssowmini exit(EXIT_FAILURE); 5521e7801d59Ssowmini } 5522e7801d59Ssowmini state.es_print.ps_fields = fields; 5523e7801d59Ssowmini state.es_print.ps_nfields = nfields; 5524e7801d59Ssowmini 5525e7801d59Ssowmini if (state.es_link == NULL) { 5526e7801d59Ssowmini (void) dladm_walk_datalink_id(show_etherprop, &state, 5527e7801d59Ssowmini DATALINK_CLASS_PHYS, DL_ETHER, 5528e7801d59Ssowmini DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST); 5529e7801d59Ssowmini } else { 5530e7801d59Ssowmini if (!link_is_ether(state.es_link, &linkid)) { 5531e7801d59Ssowmini die("invalid link specified"); 5532e7801d59Ssowmini } 5533e7801d59Ssowmini (void) show_etherprop(linkid, &state); 5534e7801d59Ssowmini } 5535e7801d59Ssowmini 5536e7801d59Ssowmini exit(DLADM_STATUS_OK); 5537e7801d59Ssowmini 5538e7801d59Ssowmini } 5539e7801d59Ssowmini 5540e7801d59Ssowmini static char * 5541e7801d59Ssowmini dladm_print_field(print_field_t *pf, void *arg) 5542e7801d59Ssowmini { 5543e7801d59Ssowmini char *value; 5544e7801d59Ssowmini 5545e7801d59Ssowmini value = (char *)arg + pf->pf_offset; 5546e7801d59Ssowmini return (value); 5547e7801d59Ssowmini } 5548e7801d59Ssowmini 5549e7801d59Ssowmini static int 5550e7801d59Ssowmini show_etherprop(datalink_id_t linkid, void *arg) 5551e7801d59Ssowmini { 5552e7801d59Ssowmini print_ether_state_t *statep = arg; 5553e7801d59Ssowmini char buf[DLADM_STRSIZE]; 5554e7801d59Ssowmini int speed; 5555e7801d59Ssowmini uint64_t s; 5556e7801d59Ssowmini uint32_t autoneg, pause, asmpause, adv_rf, cap_rf, lp_rf; 5557e7801d59Ssowmini ether_fields_buf_t ebuf; 5558e7801d59Ssowmini char speed_unit = 'M'; 5559e7801d59Ssowmini 55605f5c9f54SAnurag S. Maskey bzero(&ebuf, sizeof (ether_fields_buf_t)); 5561e7801d59Ssowmini if (dladm_datalink_id2info(linkid, NULL, NULL, NULL, 5562e7801d59Ssowmini ebuf.eth_link, sizeof (ebuf.eth_link)) != DLADM_STATUS_OK) { 5563e7801d59Ssowmini return (DLADM_WALK_CONTINUE); 5564e7801d59Ssowmini } 5565e7801d59Ssowmini 5566e7801d59Ssowmini if (!statep->es_header && !statep->es_parseable) { 5567e7801d59Ssowmini print_header(&statep->es_print); 5568e7801d59Ssowmini statep->es_header = B_TRUE; 5569e7801d59Ssowmini } 5570e7801d59Ssowmini (void) snprintf(ebuf.eth_ptype, sizeof (ebuf.eth_ptype), 5571e7801d59Ssowmini "%s", "current"); 5572e7801d59Ssowmini 5573e7801d59Ssowmini (void) dladm_get_single_mac_stat(linkid, "link_autoneg", 5574e7801d59Ssowmini KSTAT_DATA_UINT32, &autoneg); 5575e7801d59Ssowmini (void) snprintf(ebuf.eth_autoneg, sizeof (ebuf.eth_autoneg), 5576e7801d59Ssowmini "%s", (autoneg ? "yes" : "no")); 5577e7801d59Ssowmini 5578e7801d59Ssowmini (void) dladm_get_single_mac_stat(linkid, "link_pause", 5579e7801d59Ssowmini KSTAT_DATA_UINT32, &pause); 5580e7801d59Ssowmini (void) dladm_get_single_mac_stat(linkid, "link_asmpause", 5581e7801d59Ssowmini KSTAT_DATA_UINT32, &asmpause); 5582e7801d59Ssowmini (void) snprintf(ebuf.eth_pause, sizeof (ebuf.eth_pause), 5583e7801d59Ssowmini "%s", pause_str(pause, asmpause)); 5584e7801d59Ssowmini 5585e7801d59Ssowmini (void) dladm_get_single_mac_stat(linkid, "ifspeed", 5586e7801d59Ssowmini KSTAT_DATA_UINT64, &s); 5587e7801d59Ssowmini speed = (int)(s/1000000ull); 5588e7801d59Ssowmini 5589e7801d59Ssowmini if (speed >= 1000) { 5590e7801d59Ssowmini speed = speed/1000; 5591e7801d59Ssowmini speed_unit = 'G'; 5592e7801d59Ssowmini } 55934045d941Ssowmini (void) get_linkduplex(ebuf.eth_link, B_TRUE, buf); 5594e7801d59Ssowmini (void) snprintf(ebuf.eth_spdx, sizeof (ebuf.eth_spdx), "%d%c-%c", 5595e7801d59Ssowmini speed, speed_unit, buf[0]); 5596e7801d59Ssowmini 55974045d941Ssowmini (void) get_linkstate(ebuf.eth_link, B_TRUE, buf); 5598e7801d59Ssowmini (void) snprintf(ebuf.eth_state, sizeof (ebuf.eth_state), 5599e7801d59Ssowmini "%s", buf); 5600e7801d59Ssowmini 5601e7801d59Ssowmini (void) dladm_get_single_mac_stat(linkid, "adv_rem_fault", 5602e7801d59Ssowmini KSTAT_DATA_UINT32, &adv_rf); 5603e7801d59Ssowmini (void) dladm_get_single_mac_stat(linkid, "cap_rem_fault", 5604e7801d59Ssowmini KSTAT_DATA_UINT32, &cap_rf); 5605e7801d59Ssowmini (void) dladm_get_single_mac_stat(linkid, "lp_rem_fault", 5606e7801d59Ssowmini KSTAT_DATA_UINT32, &lp_rf); 5607e7801d59Ssowmini (void) snprintf(ebuf.eth_rem_fault, sizeof (ebuf.eth_rem_fault), 5608e7801d59Ssowmini "%s", (adv_rf == 0 && lp_rf == 0 ? "none" : "fault")); 5609e7801d59Ssowmini 5610e7801d59Ssowmini dladm_print_output(&statep->es_print, statep->es_parseable, 5611e7801d59Ssowmini dladm_print_field, &ebuf); 5612e7801d59Ssowmini 5613e7801d59Ssowmini if (statep->es_extended) 5614e7801d59Ssowmini show_ether_xprop(linkid, arg); 5615e7801d59Ssowmini 5616e7801d59Ssowmini return (DLADM_WALK_CONTINUE); 5617e7801d59Ssowmini } 5618e7801d59Ssowmini 5619e7801d59Ssowmini /* ARGSUSED */ 5620e7801d59Ssowmini static void 56218d5c46e6Sam223141 do_init_secobj(int argc, char **argv, const char *use) 56220ba2cbe9Sxc151355 { 56230ba2cbe9Sxc151355 dladm_status_t status; 56240ba2cbe9Sxc151355 56250ba2cbe9Sxc151355 status = dladm_init_secobj(); 562633343a97Smeem if (status != DLADM_STATUS_OK) 562733343a97Smeem die_dlerr(status, "secure object initialization failed"); 562833343a97Smeem } 562933343a97Smeem 5630d62bc4baSyz147064 /* 5631d62bc4baSyz147064 * "-R" option support. It is used for live upgrading. Append dladm commands 5632d62bc4baSyz147064 * to a upgrade script which will be run when the alternative root boots up: 5633d62bc4baSyz147064 * 5634b9e076dcSyz147064 * - If the /etc/dladm/datalink.conf file exists on the alternative root, 5635b9e076dcSyz147064 * append dladm commands to the <altroot>/var/svc/profile/upgrade_datalink 5636b9e076dcSyz147064 * script. This script will be run as part of the network/physical service. 5637b9e076dcSyz147064 * We cannot defer this to /var/svc/profile/upgrade because then the 5638b9e076dcSyz147064 * configuration will not be able to take effect before network/physical 5639b9e076dcSyz147064 * plumbs various interfaces. 5640d62bc4baSyz147064 * 5641b9e076dcSyz147064 * - If the /etc/dladm/datalink.conf file does not exist on the alternative 5642b9e076dcSyz147064 * root, append dladm commands to the <altroot>/var/svc/profile/upgrade script, 5643b9e076dcSyz147064 * which will be run in the manifest-import service. 5644d62bc4baSyz147064 * 5645d62bc4baSyz147064 * Note that the SMF team is considering to move the manifest-import service 5646d62bc4baSyz147064 * to be run at the very begining of boot. Once that is done, the need for 5647d62bc4baSyz147064 * the /var/svc/profile/upgrade_datalink script will not exist any more. 5648d62bc4baSyz147064 */ 5649d62bc4baSyz147064 static void 5650d62bc4baSyz147064 altroot_cmd(char *altroot, int argc, char *argv[]) 5651d62bc4baSyz147064 { 5652d62bc4baSyz147064 char path[MAXPATHLEN]; 5653d62bc4baSyz147064 struct stat stbuf; 5654d62bc4baSyz147064 FILE *fp; 5655d62bc4baSyz147064 int i; 5656d62bc4baSyz147064 5657d62bc4baSyz147064 /* 5658b9e076dcSyz147064 * Check for the existence of the /etc/dladm/datalink.conf 5659b9e076dcSyz147064 * configuration file, and determine the name of script file. 5660d62bc4baSyz147064 */ 5661b9e076dcSyz147064 (void) snprintf(path, MAXPATHLEN, "/%s/etc/dladm/datalink.conf", 5662b9e076dcSyz147064 altroot); 5663d62bc4baSyz147064 if (stat(path, &stbuf) < 0) { 5664d62bc4baSyz147064 (void) snprintf(path, MAXPATHLEN, "/%s/%s", altroot, 5665d62bc4baSyz147064 SMF_UPGRADE_FILE); 5666d62bc4baSyz147064 } else { 5667d62bc4baSyz147064 (void) snprintf(path, MAXPATHLEN, "/%s/%s", altroot, 5668d62bc4baSyz147064 SMF_UPGRADEDATALINK_FILE); 5669d62bc4baSyz147064 } 5670d62bc4baSyz147064 5671d62bc4baSyz147064 if ((fp = fopen(path, "a+")) == NULL) 5672d62bc4baSyz147064 die("operation not supported on %s", altroot); 5673d62bc4baSyz147064 5674d62bc4baSyz147064 (void) fprintf(fp, "/sbin/dladm "); 5675d62bc4baSyz147064 for (i = 0; i < argc; i++) { 5676d62bc4baSyz147064 /* 5677d62bc4baSyz147064 * Directly write to the file if it is not the "-R <altroot>" 5678d62bc4baSyz147064 * option. In which case, skip it. 5679d62bc4baSyz147064 */ 5680d62bc4baSyz147064 if (strcmp(argv[i], "-R") != 0) 5681d62bc4baSyz147064 (void) fprintf(fp, "%s ", argv[i]); 5682d62bc4baSyz147064 else 5683d62bc4baSyz147064 i ++; 5684d62bc4baSyz147064 } 5685d62bc4baSyz147064 (void) fprintf(fp, "%s\n", SMF_DLADM_UPGRADE_MSG); 5686d62bc4baSyz147064 (void) fclose(fp); 5687d62bc4baSyz147064 exit(0); 5688d62bc4baSyz147064 } 5689d62bc4baSyz147064 5690d62bc4baSyz147064 /* 5691d62bc4baSyz147064 * Convert the string to an integer. Note that the string must not have any 5692d62bc4baSyz147064 * trailing non-integer characters. 5693d62bc4baSyz147064 */ 569433343a97Smeem static boolean_t 569533343a97Smeem str2int(const char *str, int *valp) 569633343a97Smeem { 569733343a97Smeem int val; 569833343a97Smeem char *endp = NULL; 569933343a97Smeem 570033343a97Smeem errno = 0; 570133343a97Smeem val = strtol(str, &endp, 10); 570233343a97Smeem if (errno != 0 || *endp != '\0') 570333343a97Smeem return (B_FALSE); 570433343a97Smeem 570533343a97Smeem *valp = val; 570633343a97Smeem return (B_TRUE); 570733343a97Smeem } 570833343a97Smeem 570933343a97Smeem /* PRINTFLIKE1 */ 571033343a97Smeem static void 571133343a97Smeem warn(const char *format, ...) 571233343a97Smeem { 571333343a97Smeem va_list alist; 571433343a97Smeem 571533343a97Smeem format = gettext(format); 571633343a97Smeem (void) fprintf(stderr, "%s: warning: ", progname); 571733343a97Smeem 571833343a97Smeem va_start(alist, format); 571933343a97Smeem (void) vfprintf(stderr, format, alist); 572033343a97Smeem va_end(alist); 572133343a97Smeem 572233343a97Smeem (void) putchar('\n'); 572333343a97Smeem } 572433343a97Smeem 572533343a97Smeem /* PRINTFLIKE2 */ 572633343a97Smeem static void 572733343a97Smeem warn_dlerr(dladm_status_t err, const char *format, ...) 572833343a97Smeem { 572933343a97Smeem va_list alist; 573033343a97Smeem char errmsg[DLADM_STRSIZE]; 573133343a97Smeem 573233343a97Smeem format = gettext(format); 573333343a97Smeem (void) fprintf(stderr, gettext("%s: warning: "), progname); 573433343a97Smeem 573533343a97Smeem va_start(alist, format); 573633343a97Smeem (void) vfprintf(stderr, format, alist); 573733343a97Smeem va_end(alist); 573833343a97Smeem (void) fprintf(stderr, ": %s\n", dladm_status2str(err, errmsg)); 573933343a97Smeem } 574033343a97Smeem 574133343a97Smeem /* PRINTFLIKE2 */ 574233343a97Smeem static void 574333343a97Smeem die_dlerr(dladm_status_t err, const char *format, ...) 574433343a97Smeem { 574533343a97Smeem va_list alist; 574633343a97Smeem char errmsg[DLADM_STRSIZE]; 574733343a97Smeem 574833343a97Smeem format = gettext(format); 574933343a97Smeem (void) fprintf(stderr, "%s: ", progname); 575033343a97Smeem 575133343a97Smeem va_start(alist, format); 575233343a97Smeem (void) vfprintf(stderr, format, alist); 575333343a97Smeem va_end(alist); 575433343a97Smeem (void) fprintf(stderr, ": %s\n", dladm_status2str(err, errmsg)); 575533343a97Smeem 575633343a97Smeem exit(EXIT_FAILURE); 575733343a97Smeem } 575833343a97Smeem 575933343a97Smeem /* PRINTFLIKE1 */ 576033343a97Smeem static void 576133343a97Smeem die(const char *format, ...) 576233343a97Smeem { 576333343a97Smeem va_list alist; 576433343a97Smeem 576533343a97Smeem format = gettext(format); 576633343a97Smeem (void) fprintf(stderr, "%s: ", progname); 576733343a97Smeem 576833343a97Smeem va_start(alist, format); 576933343a97Smeem (void) vfprintf(stderr, format, alist); 577033343a97Smeem va_end(alist); 577133343a97Smeem 577233343a97Smeem (void) putchar('\n'); 577333343a97Smeem exit(EXIT_FAILURE); 577433343a97Smeem } 577533343a97Smeem 577633343a97Smeem static void 577733343a97Smeem die_optdup(int opt) 577833343a97Smeem { 577933343a97Smeem die("the option -%c cannot be specified more than once", opt); 578033343a97Smeem } 578133343a97Smeem 578233343a97Smeem static void 57838d5c46e6Sam223141 die_opterr(int opt, int opterr, const char *usage) 578433343a97Smeem { 578533343a97Smeem switch (opterr) { 578633343a97Smeem case ':': 57878d5c46e6Sam223141 die("option '-%c' requires a value\nusage: %s", opt, 57888d5c46e6Sam223141 gettext(usage)); 578933343a97Smeem break; 579033343a97Smeem case '?': 579133343a97Smeem default: 57928d5c46e6Sam223141 die("unrecognized option '-%c'\nusage: %s", opt, 57938d5c46e6Sam223141 gettext(usage)); 579433343a97Smeem break; 57950ba2cbe9Sxc151355 } 57960ba2cbe9Sxc151355 } 5797e7801d59Ssowmini 5798e7801d59Ssowmini static void 5799e7801d59Ssowmini show_ether_xprop(datalink_id_t linkid, void *arg) 5800e7801d59Ssowmini { 5801e7801d59Ssowmini print_ether_state_t *statep = arg; 5802e7801d59Ssowmini char buf[DLADM_STRSIZE]; 5803e7801d59Ssowmini uint32_t autoneg, pause, asmpause, adv_rf, cap_rf, lp_rf; 5804e7801d59Ssowmini boolean_t add_comma, r1; 5805e7801d59Ssowmini ether_fields_buf_t ebuf; 5806e7801d59Ssowmini 5807e7801d59Ssowmini /* capable */ 5808e7801d59Ssowmini bzero(&ebuf, sizeof (ebuf)); 5809e7801d59Ssowmini (void) snprintf(ebuf.eth_link, sizeof (ebuf.eth_link), ""); 5810e7801d59Ssowmini 5811e7801d59Ssowmini (void) snprintf(ebuf.eth_ptype, sizeof (ebuf.eth_ptype), 5812e7801d59Ssowmini "%s", "capable"); 58130d365605Sschuster (void) snprintf(ebuf.eth_state, sizeof (ebuf.eth_state), ""); 5814e7801d59Ssowmini 5815e7801d59Ssowmini (void) dladm_get_single_mac_stat(linkid, "cap_autoneg", 5816e7801d59Ssowmini KSTAT_DATA_UINT32, &autoneg); 5817e7801d59Ssowmini (void) snprintf(ebuf.eth_autoneg, sizeof (ebuf.eth_autoneg), 5818e7801d59Ssowmini "%s", (autoneg ? "yes" : "no")); 5819e7801d59Ssowmini 5820e7801d59Ssowmini add_comma = B_FALSE; 5821e7801d59Ssowmini bzero(buf, sizeof (buf)); 5822e7801d59Ssowmini r1 = get_speed_duplex(linkid, "cap_1000", buf, "1G", B_FALSE); 5823e7801d59Ssowmini if (r1) 5824e7801d59Ssowmini add_comma = B_TRUE; 5825e7801d59Ssowmini r1 = get_speed_duplex(linkid, "cap_100", buf, "100M", add_comma); 5826e7801d59Ssowmini if (r1) 5827e7801d59Ssowmini add_comma = B_TRUE; 5828e7801d59Ssowmini r1 = get_speed_duplex(linkid, "cap_10", buf, "10M", add_comma); 5829e7801d59Ssowmini add_comma = B_FALSE; 5830e7801d59Ssowmini (void) snprintf(ebuf.eth_spdx, sizeof (ebuf.eth_spdx), "%s", buf); 5831e7801d59Ssowmini 5832e7801d59Ssowmini (void) dladm_get_single_mac_stat(linkid, "cap_pause", 5833e7801d59Ssowmini KSTAT_DATA_UINT32, &pause); 5834e7801d59Ssowmini (void) dladm_get_single_mac_stat(linkid, "cap_asmpause", 5835e7801d59Ssowmini KSTAT_DATA_UINT32, &asmpause); 5836e7801d59Ssowmini (void) snprintf(ebuf.eth_pause, sizeof (ebuf.eth_pause), 5837e7801d59Ssowmini "%s", pause_str(pause, asmpause)); 5838e7801d59Ssowmini 5839e7801d59Ssowmini (void) dladm_get_single_mac_stat(linkid, "adv_rem_fault", 5840e7801d59Ssowmini KSTAT_DATA_UINT32, &adv_rf); 5841e7801d59Ssowmini (void) dladm_get_single_mac_stat(linkid, "cap_rem_fault", 5842e7801d59Ssowmini KSTAT_DATA_UINT32, &cap_rf); 5843e7801d59Ssowmini (void) dladm_get_single_mac_stat(linkid, "lp_rem_fault", 5844e7801d59Ssowmini KSTAT_DATA_UINT32, &lp_rf); 5845e7801d59Ssowmini 5846e7801d59Ssowmini (void) snprintf(ebuf.eth_rem_fault, sizeof (ebuf.eth_rem_fault), 5847e7801d59Ssowmini "%s", (cap_rf ? "yes" : "no")); 5848e7801d59Ssowmini 5849e7801d59Ssowmini dladm_print_output(&statep->es_print, statep->es_parseable, 5850e7801d59Ssowmini dladm_print_field, &ebuf); 5851e7801d59Ssowmini 5852e7801d59Ssowmini /* advertised */ 5853e7801d59Ssowmini bzero(&ebuf, sizeof (ebuf)); 5854e7801d59Ssowmini (void) snprintf(ebuf.eth_ptype, sizeof (ebuf.eth_ptype), 5855e7801d59Ssowmini "%s", "adv"); 58560d365605Sschuster (void) snprintf(ebuf.eth_state, sizeof (ebuf.eth_state), ""); 5857e7801d59Ssowmini 5858e7801d59Ssowmini (void) dladm_get_single_mac_stat(linkid, "adv_cap_autoneg", 5859e7801d59Ssowmini KSTAT_DATA_UINT32, &autoneg); 5860e7801d59Ssowmini (void) snprintf(ebuf.eth_autoneg, sizeof (ebuf.eth_autoneg), 5861e7801d59Ssowmini "%s", (autoneg ? "yes" : "no")); 5862e7801d59Ssowmini 5863e7801d59Ssowmini add_comma = B_FALSE; 5864e7801d59Ssowmini bzero(buf, sizeof (buf)); 5865e7801d59Ssowmini r1 = get_speed_duplex(linkid, "adv_cap_1000", buf, "1G", add_comma); 5866e7801d59Ssowmini if (r1) 5867e7801d59Ssowmini add_comma = B_TRUE; 5868e7801d59Ssowmini r1 = get_speed_duplex(linkid, "adv_cap_100", buf, "100M", add_comma); 5869e7801d59Ssowmini if (r1) 5870e7801d59Ssowmini add_comma = B_TRUE; 5871e7801d59Ssowmini r1 = get_speed_duplex(linkid, "adv_cap_10", buf, "10M", add_comma); 5872e7801d59Ssowmini add_comma = B_FALSE; 5873e7801d59Ssowmini (void) snprintf(ebuf.eth_spdx, sizeof (ebuf.eth_spdx), "%s", buf); 5874e7801d59Ssowmini 5875e7801d59Ssowmini (void) dladm_get_single_mac_stat(linkid, "adv_cap_pause", 5876e7801d59Ssowmini KSTAT_DATA_UINT32, &pause); 5877e7801d59Ssowmini (void) dladm_get_single_mac_stat(linkid, "adv_cap_asmpause", 5878e7801d59Ssowmini KSTAT_DATA_UINT32, &asmpause); 5879e7801d59Ssowmini (void) snprintf(ebuf.eth_pause, sizeof (ebuf.eth_pause), 5880e7801d59Ssowmini "%s", pause_str(pause, asmpause)); 5881e7801d59Ssowmini 5882e7801d59Ssowmini (void) snprintf(ebuf.eth_rem_fault, sizeof (ebuf.eth_rem_fault), 5883e7801d59Ssowmini "%s", (adv_rf ? "fault" : "none")); 5884e7801d59Ssowmini 5885e7801d59Ssowmini dladm_print_output(&statep->es_print, statep->es_parseable, 5886e7801d59Ssowmini dladm_print_field, &ebuf); 5887e7801d59Ssowmini 5888e7801d59Ssowmini /* peeradv */ 5889e7801d59Ssowmini bzero(&ebuf, sizeof (ebuf)); 5890e7801d59Ssowmini (void) snprintf(ebuf.eth_ptype, sizeof (ebuf.eth_ptype), 5891e7801d59Ssowmini "%s", "peeradv"); 58920d365605Sschuster (void) snprintf(ebuf.eth_state, sizeof (ebuf.eth_state), ""); 5893e7801d59Ssowmini (void) dladm_get_single_mac_stat(linkid, "lp_cap_autoneg", 5894e7801d59Ssowmini KSTAT_DATA_UINT32, &autoneg); 5895e7801d59Ssowmini (void) snprintf(ebuf.eth_autoneg, sizeof (ebuf.eth_autoneg), 5896e7801d59Ssowmini "%s", (autoneg ? "yes" : "no")); 5897e7801d59Ssowmini 5898e7801d59Ssowmini add_comma = B_FALSE; 5899e7801d59Ssowmini bzero(buf, sizeof (buf)); 5900e7801d59Ssowmini r1 = get_speed_duplex(linkid, "lp_cap_1000", buf, "1G", add_comma); 5901e7801d59Ssowmini if (r1) 5902e7801d59Ssowmini add_comma = B_TRUE; 5903e7801d59Ssowmini r1 = get_speed_duplex(linkid, "lp_cap_100", buf, "100M", add_comma); 5904e7801d59Ssowmini if (r1) 5905e7801d59Ssowmini add_comma = B_TRUE; 5906e7801d59Ssowmini r1 = get_speed_duplex(linkid, "lp_cap_10", buf, "10M", add_comma); 5907e7801d59Ssowmini (void) snprintf(ebuf.eth_spdx, sizeof (ebuf.eth_spdx), "%s", buf); 5908e7801d59Ssowmini 5909e7801d59Ssowmini (void) dladm_get_single_mac_stat(linkid, "lp_cap_pause", 5910e7801d59Ssowmini KSTAT_DATA_UINT32, &pause); 5911e7801d59Ssowmini (void) dladm_get_single_mac_stat(linkid, "lp_cap_asmpause", 5912e7801d59Ssowmini KSTAT_DATA_UINT32, &asmpause); 5913e7801d59Ssowmini (void) snprintf(ebuf.eth_pause, sizeof (ebuf.eth_pause), 5914e7801d59Ssowmini "%s", pause_str(pause, asmpause)); 5915e7801d59Ssowmini 5916e7801d59Ssowmini (void) snprintf(ebuf.eth_rem_fault, sizeof (ebuf.eth_rem_fault), 5917e7801d59Ssowmini "%s", (lp_rf ? "fault" : "none")); 5918e7801d59Ssowmini 5919e7801d59Ssowmini dladm_print_output(&statep->es_print, statep->es_parseable, 5920e7801d59Ssowmini dladm_print_field, &ebuf); 5921e7801d59Ssowmini } 5922e7801d59Ssowmini 5923e7801d59Ssowmini static boolean_t 5924e7801d59Ssowmini get_speed_duplex(datalink_id_t linkid, const char *mii_prop_prefix, 5925e7801d59Ssowmini char *spbuf, char *sp, boolean_t add_comma) 5926e7801d59Ssowmini { 5927e7801d59Ssowmini int speed, duplex = 0; 5928e7801d59Ssowmini boolean_t ret = B_FALSE; 5929e7801d59Ssowmini char mii_prop[DLADM_STRSIZE]; 5930e7801d59Ssowmini 5931e7801d59Ssowmini (void) snprintf(mii_prop, DLADM_STRSIZE, "%sfdx", mii_prop_prefix); 5932e7801d59Ssowmini (void) dladm_get_single_mac_stat(linkid, mii_prop, KSTAT_DATA_UINT32, 5933e7801d59Ssowmini &speed); 5934e7801d59Ssowmini if (speed) { 5935e7801d59Ssowmini ret = B_TRUE; 5936e7801d59Ssowmini duplex |= IS_FDX; 5937e7801d59Ssowmini } 5938e7801d59Ssowmini (void) snprintf(mii_prop, DLADM_STRSIZE, "%shdx", mii_prop_prefix); 5939e7801d59Ssowmini (void) dladm_get_single_mac_stat(linkid, mii_prop, 5940e7801d59Ssowmini KSTAT_DATA_UINT32, &speed); 5941e7801d59Ssowmini if (speed) { 5942e7801d59Ssowmini ret = B_TRUE; 5943e7801d59Ssowmini duplex |= IS_HDX; 5944e7801d59Ssowmini } 5945e7801d59Ssowmini if (ret) { 5946e7801d59Ssowmini if (add_comma) 5947e7801d59Ssowmini (void) strncat(spbuf, ",", DLADM_STRSIZE); 5948e7801d59Ssowmini (void) strncat(spbuf, sp, DLADM_STRSIZE); 5949e7801d59Ssowmini if ((duplex & (IS_FDX|IS_HDX)) == (IS_FDX|IS_HDX)) 5950e7801d59Ssowmini (void) strncat(spbuf, "-fh", DLADM_STRSIZE); 5951e7801d59Ssowmini else if (duplex & IS_FDX) 5952e7801d59Ssowmini (void) strncat(spbuf, "-f", DLADM_STRSIZE); 5953e7801d59Ssowmini else if (duplex & IS_HDX) 5954e7801d59Ssowmini (void) strncat(spbuf, "-h", DLADM_STRSIZE); 5955e7801d59Ssowmini } 5956e7801d59Ssowmini return (ret); 5957e7801d59Ssowmini } 5958e7801d59Ssowmini 5959e7801d59Ssowmini static void 5960e7801d59Ssowmini dladm_print_output(print_state_t *statep, boolean_t parseable, 5961e7801d59Ssowmini print_callback_t fn, void *arg) 5962e7801d59Ssowmini { 5963e7801d59Ssowmini int i; 5964e7801d59Ssowmini char *value; 5965e7801d59Ssowmini print_field_t **pf; 5966e7801d59Ssowmini 5967e7801d59Ssowmini pf = statep->ps_fields; 5968e7801d59Ssowmini for (i = 0; i < statep->ps_nfields; i++) { 5969e7801d59Ssowmini statep->ps_lastfield = (i + 1 == statep->ps_nfields); 5970e7801d59Ssowmini value = (*fn)(pf[i], arg); 5971e7801d59Ssowmini if (value != NULL) 5972e7801d59Ssowmini print_field(statep, pf[i], value, parseable); 5973e7801d59Ssowmini } 5974e7801d59Ssowmini (void) putchar('\n'); 5975e7801d59Ssowmini } 5976e7801d59Ssowmini 5977e7801d59Ssowmini static void 5978e7801d59Ssowmini print_header(print_state_t *ps) 5979e7801d59Ssowmini { 5980e7801d59Ssowmini int i; 5981e7801d59Ssowmini print_field_t **pf; 5982e7801d59Ssowmini 5983e7801d59Ssowmini pf = ps->ps_fields; 5984e7801d59Ssowmini for (i = 0; i < ps->ps_nfields; i++) { 5985e7801d59Ssowmini ps->ps_lastfield = (i + 1 == ps->ps_nfields); 5986e7801d59Ssowmini print_field(ps, pf[i], pf[i]->pf_header, B_FALSE); 5987e7801d59Ssowmini } 5988e7801d59Ssowmini (void) putchar('\n'); 5989e7801d59Ssowmini } 5990e7801d59Ssowmini 5991e7801d59Ssowmini static char * 5992e7801d59Ssowmini pause_str(int pause, int asmpause) 5993e7801d59Ssowmini { 5994e7801d59Ssowmini if (pause == 1) 5995e7801d59Ssowmini return ("bi"); 5996e7801d59Ssowmini if (asmpause == 1) 5997e7801d59Ssowmini return ("tx"); 5998e7801d59Ssowmini return ("none"); 5999e7801d59Ssowmini } 6000e7801d59Ssowmini 6001e7801d59Ssowmini static boolean_t 6002e7801d59Ssowmini link_is_ether(const char *link, datalink_id_t *linkid) 6003e7801d59Ssowmini { 6004e7801d59Ssowmini uint32_t media; 6005e7801d59Ssowmini datalink_class_t class; 6006e7801d59Ssowmini 6007e7801d59Ssowmini if (dladm_name2info(link, linkid, NULL, &class, &media) == 6008e7801d59Ssowmini DLADM_STATUS_OK) { 6009e7801d59Ssowmini if (class == DATALINK_CLASS_PHYS && media == DL_ETHER) 6010e7801d59Ssowmini return (B_TRUE); 6011e7801d59Ssowmini } 6012e7801d59Ssowmini return (B_FALSE); 6013e7801d59Ssowmini } 6014