17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5219a2a31Shl157128 * Common Development and Distribution License (the "License"). 6219a2a31Shl157128 * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 22ad091ee1SMichael Lim * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate #include <stdio.h> 270ba2cbe9Sxc151355 #include <ctype.h> 287c478bd9Sstevel@tonic-gate #include <locale.h> 290ba2cbe9Sxc151355 #include <signal.h> 307c478bd9Sstevel@tonic-gate #include <stdarg.h> 317c478bd9Sstevel@tonic-gate #include <stdlib.h> 327c478bd9Sstevel@tonic-gate #include <fcntl.h> 337c478bd9Sstevel@tonic-gate #include <string.h> 347c478bd9Sstevel@tonic-gate #include <stropts.h> 35d62bc4baSyz147064 #include <sys/stat.h> 367c478bd9Sstevel@tonic-gate #include <errno.h> 377c478bd9Sstevel@tonic-gate #include <kstat.h> 387c478bd9Sstevel@tonic-gate #include <strings.h> 397c478bd9Sstevel@tonic-gate #include <getopt.h> 407c478bd9Sstevel@tonic-gate #include <unistd.h> 41cd93090eSericheng #include <priv.h> 420ba2cbe9Sxc151355 #include <termios.h> 430ba2cbe9Sxc151355 #include <pwd.h> 440ba2cbe9Sxc151355 #include <auth_attr.h> 450ba2cbe9Sxc151355 #include <auth_list.h> 467c478bd9Sstevel@tonic-gate #include <libintl.h> 47d62bc4baSyz147064 #include <libdevinfo.h> 487c478bd9Sstevel@tonic-gate #include <libdlpi.h> 49da14cebeSEric Cheng #include <libdladm.h> 50f595a68aSyz147064 #include <libdllink.h> 51da14cebeSEric Cheng #include <libdlstat.h> 52f595a68aSyz147064 #include <libdlaggr.h> 53f595a68aSyz147064 #include <libdlwlan.h> 54d62bc4baSyz147064 #include <libdlvlan.h> 55d62bc4baSyz147064 #include <libdlvnic.h> 564784fcbdSSowmini Varadhan #include <libdlether.h> 570ba2cbe9Sxc151355 #include <libinetutil.h> 580ba2cbe9Sxc151355 #include <bsm/adt.h> 590ba2cbe9Sxc151355 #include <bsm/adt_event.h> 60da14cebeSEric Cheng #include <libdlvnic.h> 61da14cebeSEric Cheng #include <sys/types.h> 62da14cebeSEric Cheng #include <sys/socket.h> 63da14cebeSEric Cheng #include <sys/processor.h> 64da14cebeSEric Cheng #include <netinet/in.h> 65da14cebeSEric Cheng #include <arpa/inet.h> 66da14cebeSEric Cheng #include <net/if_types.h> 67e7801d59Ssowmini #include <stddef.h> 687c478bd9Sstevel@tonic-gate 69e7801d59Ssowmini #define STR_UNDEF_VAL "--" 707c478bd9Sstevel@tonic-gate #define MAXPORT 256 71da14cebeSEric Cheng #define MAXVNIC 256 72d62bc4baSyz147064 #define BUFLEN(lim, ptr) (((lim) > (ptr)) ? ((lim) - (ptr)) : 0) 73d62bc4baSyz147064 #define MAXLINELEN 1024 74d62bc4baSyz147064 #define SMF_UPGRADE_FILE "/var/svc/profile/upgrade" 75d62bc4baSyz147064 #define SMF_UPGRADEDATALINK_FILE "/var/svc/profile/upgrade_datalink" 76d62bc4baSyz147064 #define SMF_DLADM_UPGRADE_MSG " # added by dladm(1M)" 777c478bd9Sstevel@tonic-gate 78e7801d59Ssowmini #define CMD_TYPE_ANY 0xffffffff 79e7801d59Ssowmini #define WIFI_CMD_SCAN 0x00000001 80e7801d59Ssowmini #define WIFI_CMD_SHOW 0x00000002 81e7801d59Ssowmini #define WIFI_CMD_ALL (WIFI_CMD_SCAN | WIFI_CMD_SHOW) 82e7801d59Ssowmini 83e7801d59Ssowmini /* 840d365605Sschuster * Data structures and routines for printing output. 85e7801d59Ssowmini * All non-parseable output is assumed to be in a columnar format. 860d365605Sschuster * Multiple fields in parsable output are separated by ':'; single 870d365605Sschuster * field output is printed as-is. 88e7801d59Ssowmini * 89e7801d59Ssowmini * Each sub-command is associated with a global array of pointers, 90e7801d59Ssowmini * print_field_t *fields[], where the print_field_t contains information 91e7801d59Ssowmini * about the format in which the output is to be printed. 92e7801d59Ssowmini * 93e7801d59Ssowmini * Sub-commands may be implemented in one of two ways: 94e7801d59Ssowmini * (i) the implementation could get all field values into a character 95e7801d59Ssowmini * buffer, with pf_offset containing the offset (for pf_name) within 96e7801d59Ssowmini * the buffer. The sub-command would make the needed system calls 97e7801d59Ssowmini * to obtain all possible column values and then invoke the 98e7801d59Ssowmini * dladm_print_field() function to print the specific fields 99e7801d59Ssowmini * requested in the command line. See the comments for dladm_print_field 100e7801d59Ssowmini * for further details. 101e7801d59Ssowmini * (ii) Alternatively, each fields[i] entry could store a pf_index value 102e7801d59Ssowmini * that uniquely identifies the column to be printed. The implementation 103e7801d59Ssowmini * of the sub-command would then invoke dladm_print_output() with a 104e7801d59Ssowmini * callback function whose semantics are described below (see comments 105e7801d59Ssowmini * for dladm_print_output()) 106e7801d59Ssowmini * 107e7801d59Ssowmini * Thus, an implementation of a sub-command must provide the following: 108e7801d59Ssowmini * 109e7801d59Ssowmini * static print_field_t sub_command_fields[] = { 110e7801d59Ssowmini * {<name>, <header>,<field width>, <offset_or_index>, cmdtype}, 111e7801d59Ssowmini * : 112e7801d59Ssowmini * {<name>, <header>,<field width>, <offset_or_index>, cmdtype} 113e7801d59Ssowmini * }; 114e7801d59Ssowmini * 115e7801d59Ssowmini * #define SUB_COMMAND_MAX_FIELDS sizeof \ 116e7801d59Ssowmini * (sub_comand_fields) / sizeof (print_field_t)) 117e7801d59Ssowmini * 118e7801d59Ssowmini * print_state_t sub_command_print_state; 119e7801d59Ssowmini * 120e7801d59Ssowmini * The function that parses command line arguments (typically 121e7801d59Ssowmini * do_sub_command()) should then contain an invocation like: 122e7801d59Ssowmini * 123e7801d59Ssowmini * fields = parse_output_fields(fields_str, sub_command_fields, 124e7801d59Ssowmini * SUB_COMMAND_MAX_FIELDS, CMD_TYPE_ANY, &nfields); 125e7801d59Ssowmini * 126e7801d59Ssowmini * and store the resulting fields and nfields value in a print_state_t 127e7801d59Ssowmini * structure tracked for the command. 128e7801d59Ssowmini * 129e7801d59Ssowmini * sub_command_print_state.ps_fields = fields; 130e7801d59Ssowmini * sub_command_print_state.ps_nfields = nfields; 131e7801d59Ssowmini * 132e7801d59Ssowmini * To print the column header for the output, the print_header() 133e7801d59Ssowmini * function must then be invoked by do_sub_command(). 134e7801d59Ssowmini * 135e7801d59Ssowmini * Then if method (i) is used for the sub_command, the do_sub_command() 136e7801d59Ssowmini * function should make the necessary system calls to fill up the buffer 137e7801d59Ssowmini * and then invoke dladm_print_field(). An example of this method is 138e7801d59Ssowmini * the implementation of do_show_link() and show_link(); 139e7801d59Ssowmini * 140e7801d59Ssowmini * If method (ii) is used, do_sub_command should invoke dladm_print_output() 141e7801d59Ssowmini * with a callback function that will be called for each field to be printed. 142e7801d59Ssowmini * The callback function will be passed a pointer to the print_field_t 143e7801d59Ssowmini * for the field, and the pf_index may then be used to identify the 144da14cebeSEric Cheng * system call required to find the value to be printed. 145e7801d59Ssowmini */ 146e7801d59Ssowmini 147e7801d59Ssowmini typedef struct print_field_s { 148e7801d59Ssowmini const char *pf_name; /* name of column to be printed */ 149e7801d59Ssowmini const char *pf_header; /* header for this column */ 150e7801d59Ssowmini uint_t pf_width; 151e7801d59Ssowmini union { 152e7801d59Ssowmini uint_t _pf_index; /* private index for sub-command */ 153e7801d59Ssowmini size_t _pf_offset; 154e7801d59Ssowmini }_pf_un; 155e7801d59Ssowmini #define pf_index _pf_un._pf_index 156e7801d59Ssowmini #define pf_offset _pf_un._pf_offset; 157e7801d59Ssowmini uint_t pf_cmdtype; 158e7801d59Ssowmini } print_field_t; 159e7801d59Ssowmini 160e7801d59Ssowmini /* 161e7801d59Ssowmini * The state of the output is tracked in a print_state_t structure. 162e7801d59Ssowmini * Each ps_fields[i] entry points at the global print_field_t array for 163e7801d59Ssowmini * the sub-command, where ps_nfields is the number of requested fields. 164e7801d59Ssowmini */ 165e7801d59Ssowmini typedef struct print_state_s { 166e7801d59Ssowmini print_field_t **ps_fields; 167e7801d59Ssowmini uint_t ps_nfields; 168e7801d59Ssowmini boolean_t ps_lastfield; 169e7801d59Ssowmini uint_t ps_overflow; 170e7801d59Ssowmini } print_state_t; 171e7801d59Ssowmini 172e7801d59Ssowmini typedef char *(*print_callback_t)(print_field_t *, void *); 173e7801d59Ssowmini static print_field_t **parse_output_fields(char *, print_field_t *, int, 174e7801d59Ssowmini uint_t, uint_t *); 175e7801d59Ssowmini /* 176e7801d59Ssowmini * print the header for the output 177e7801d59Ssowmini */ 178e7801d59Ssowmini static void print_header(print_state_t *); 179e7801d59Ssowmini static void print_field(print_state_t *, print_field_t *, const char *, 180e7801d59Ssowmini boolean_t); 181e7801d59Ssowmini 182e7801d59Ssowmini /* 183e7801d59Ssowmini * to print output values, call dladm_print_output with a callback 184e7801d59Ssowmini * function (*func)() that should parse the args and return an 185e7801d59Ssowmini * unformatted character buffer with the value to be printed. 186e7801d59Ssowmini * 187e7801d59Ssowmini * dladm_print_output() prints the character buffer using the formatting 188e7801d59Ssowmini * information provided in the print_field_t for that column. 189e7801d59Ssowmini */ 190e7801d59Ssowmini static void dladm_print_output(print_state_t *, boolean_t, 191e7801d59Ssowmini print_callback_t, void *); 192e7801d59Ssowmini 193e7801d59Ssowmini /* 194e7801d59Ssowmini * helper function that, when invoked as dladm_print_field(pf, buf) 1954ac67f02SAnurag S. Maskey * prints string which is offset by pf->pf_offset within buf. 196e7801d59Ssowmini */ 197e7801d59Ssowmini static char *dladm_print_field(print_field_t *, void *); 198e7801d59Ssowmini 199e7801d59Ssowmini 200e7801d59Ssowmini #define MAX_FIELD_LEN 32 201e7801d59Ssowmini 202e7801d59Ssowmini 203d62bc4baSyz147064 typedef struct show_state { 2047c478bd9Sstevel@tonic-gate boolean_t ls_firstonly; 2057c478bd9Sstevel@tonic-gate boolean_t ls_donefirst; 2067c478bd9Sstevel@tonic-gate pktsum_t ls_prevstats; 207d62bc4baSyz147064 uint32_t ls_flags; 208d62bc4baSyz147064 dladm_status_t ls_status; 209e7801d59Ssowmini print_state_t ls_print; 210e7801d59Ssowmini boolean_t ls_parseable; 211e7801d59Ssowmini boolean_t ls_printheader; 212da14cebeSEric Cheng boolean_t ls_mac; 213da14cebeSEric Cheng boolean_t ls_hwgrp; 214d62bc4baSyz147064 } show_state_t; 2157c478bd9Sstevel@tonic-gate 2167c478bd9Sstevel@tonic-gate typedef struct show_grp_state { 217e7801d59Ssowmini pktsum_t gs_prevstats[MAXPORT]; 218e7801d59Ssowmini uint32_t gs_flags; 219e7801d59Ssowmini dladm_status_t gs_status; 220e7801d59Ssowmini boolean_t gs_parseable; 2217c478bd9Sstevel@tonic-gate boolean_t gs_lacp; 222d62bc4baSyz147064 boolean_t gs_extended; 2237c478bd9Sstevel@tonic-gate boolean_t gs_stats; 2247c478bd9Sstevel@tonic-gate boolean_t gs_firstonly; 225d62bc4baSyz147064 boolean_t gs_donefirst; 226e7801d59Ssowmini boolean_t gs_printheader; 227e7801d59Ssowmini print_state_t gs_print; 2287c478bd9Sstevel@tonic-gate } show_grp_state_t; 2297c478bd9Sstevel@tonic-gate 230da14cebeSEric Cheng typedef struct show_vnic_state { 231da14cebeSEric Cheng datalink_id_t vs_vnic_id; 232da14cebeSEric Cheng datalink_id_t vs_link_id; 233da14cebeSEric Cheng char vs_vnic[MAXLINKNAMELEN]; 234da14cebeSEric Cheng char vs_link[MAXLINKNAMELEN]; 235da14cebeSEric Cheng boolean_t vs_parseable; 236da14cebeSEric Cheng boolean_t vs_printheader; 237da14cebeSEric Cheng boolean_t vs_found; 238da14cebeSEric Cheng boolean_t vs_firstonly; 239da14cebeSEric Cheng boolean_t vs_donefirst; 240da14cebeSEric Cheng boolean_t vs_stats; 241da14cebeSEric Cheng boolean_t vs_printstats; 242da14cebeSEric Cheng pktsum_t vs_totalstats; 243da14cebeSEric Cheng pktsum_t vs_prevstats[MAXVNIC]; 244da14cebeSEric Cheng boolean_t vs_etherstub; 245da14cebeSEric Cheng dladm_status_t vs_status; 246da14cebeSEric Cheng uint32_t vs_flags; 247da14cebeSEric Cheng print_state_t vs_print; 248da14cebeSEric Cheng } show_vnic_state_t; 249da14cebeSEric Cheng 250da14cebeSEric Cheng typedef struct show_usage_state_s { 251da14cebeSEric Cheng boolean_t us_plot; 252da14cebeSEric Cheng boolean_t us_parseable; 253da14cebeSEric Cheng boolean_t us_printheader; 254da14cebeSEric Cheng boolean_t us_first; 255ae6aa22aSVenugopal Iyer boolean_t us_showall; 256da14cebeSEric Cheng print_state_t us_print; 257da14cebeSEric Cheng } show_usage_state_t; 258da14cebeSEric Cheng 2598d5c46e6Sam223141 typedef void cmdfunc_t(int, char **, const char *); 2600ba2cbe9Sxc151355 261da14cebeSEric Cheng static cmdfunc_t do_show_link, do_show_wifi, do_show_phys; 2620ba2cbe9Sxc151355 static cmdfunc_t do_create_aggr, do_delete_aggr, do_add_aggr, do_remove_aggr; 263d62bc4baSyz147064 static cmdfunc_t do_modify_aggr, do_show_aggr, do_up_aggr; 2640ba2cbe9Sxc151355 static cmdfunc_t do_scan_wifi, do_connect_wifi, do_disconnect_wifi; 2650ba2cbe9Sxc151355 static cmdfunc_t do_show_linkprop, do_set_linkprop, do_reset_linkprop; 2660ba2cbe9Sxc151355 static cmdfunc_t do_create_secobj, do_delete_secobj, do_show_secobj; 2670ba2cbe9Sxc151355 static cmdfunc_t do_init_linkprop, do_init_secobj; 268d62bc4baSyz147064 static cmdfunc_t do_create_vlan, do_delete_vlan, do_up_vlan, do_show_vlan; 269d62bc4baSyz147064 static cmdfunc_t do_rename_link, do_delete_phys, do_init_phys; 270d62bc4baSyz147064 static cmdfunc_t do_show_linkmap; 271e7801d59Ssowmini static cmdfunc_t do_show_ether; 272da14cebeSEric Cheng static cmdfunc_t do_create_vnic, do_delete_vnic, do_show_vnic; 273da14cebeSEric Cheng static cmdfunc_t do_up_vnic; 274da14cebeSEric Cheng static cmdfunc_t do_create_etherstub, do_delete_etherstub, do_show_etherstub; 275da14cebeSEric Cheng static cmdfunc_t do_show_usage; 276da14cebeSEric Cheng 277da14cebeSEric Cheng static void do_up_vnic_common(int, char **, const char *, boolean_t); 2787c478bd9Sstevel@tonic-gate 279d62bc4baSyz147064 static void altroot_cmd(char *, int, char **); 2804ac67f02SAnurag S. Maskey static int show_linkprop_onelink(dladm_handle_t, datalink_id_t, void *); 281f4b3ec61Sdh155122 2826be03d0bSVasumathi Sundaram - Sun Microsystems static void link_stats(datalink_id_t, uint_t, char *, show_state_t *); 283d62bc4baSyz147064 static void aggr_stats(datalink_id_t, show_grp_state_t *, uint_t); 284da14cebeSEric Cheng static void vnic_stats(show_vnic_state_t *, uint32_t); 2857c478bd9Sstevel@tonic-gate 286d62bc4baSyz147064 static int get_one_kstat(const char *, const char *, uint8_t, 287d62bc4baSyz147064 void *, boolean_t); 288ba2e4443Sseb static void get_mac_stats(const char *, pktsum_t *); 2897c478bd9Sstevel@tonic-gate static void get_link_stats(const char *, pktsum_t *); 290d62bc4baSyz147064 static uint64_t get_ifspeed(const char *, boolean_t); 291d62bc4baSyz147064 static const char *get_linkstate(const char *, boolean_t, char *); 292d62bc4baSyz147064 static const char *get_linkduplex(const char *, boolean_t, char *); 2937c478bd9Sstevel@tonic-gate 2944ac67f02SAnurag S. Maskey static int show_etherprop(dladm_handle_t, datalink_id_t, void *); 2954784fcbdSSowmini Varadhan static void show_ether_xprop(void *, dladm_ether_info_t *); 296e7801d59Ssowmini static boolean_t link_is_ether(const char *, datalink_id_t *); 297e7801d59Ssowmini 29833343a97Smeem static boolean_t str2int(const char *, int *); 29933343a97Smeem static void die(const char *, ...); 30033343a97Smeem static void die_optdup(int); 3018d5c46e6Sam223141 static void die_opterr(int, int, const char *); 30233343a97Smeem static void die_dlerr(dladm_status_t, const char *, ...); 30333343a97Smeem static void warn(const char *, ...); 30433343a97Smeem static void warn_dlerr(dladm_status_t, const char *, ...); 30533343a97Smeem 3067c478bd9Sstevel@tonic-gate typedef struct cmd { 3077c478bd9Sstevel@tonic-gate char *c_name; 3080ba2cbe9Sxc151355 cmdfunc_t *c_fn; 3098d5c46e6Sam223141 const char *c_usage; 3107c478bd9Sstevel@tonic-gate } cmd_t; 3117c478bd9Sstevel@tonic-gate 3127c478bd9Sstevel@tonic-gate static cmd_t cmds[] = { 3138d5c46e6Sam223141 { "rename-link", do_rename_link, 3140790b6dcSAnurag S. Maskey " rename-link <oldlink> <newlink>" }, 3150790b6dcSAnurag S. Maskey { "show-link", do_show_link, 3160790b6dcSAnurag S. Maskey " show-link [-pP] [-o <field>,..] [-s [-i <interval>]] " 3170790b6dcSAnurag S. Maskey "[<link>]\n" }, 3188d5c46e6Sam223141 { "create-aggr", do_create_aggr, 3190790b6dcSAnurag S. Maskey " create-aggr [-t] [-P <policy>] [-L <mode>] [-T <time>] " 3200790b6dcSAnurag S. Maskey "[-u <address>]\n" 3210790b6dcSAnurag S. Maskey "\t\t -l <link> [-l <link>...] <link>" }, 3228d5c46e6Sam223141 { "delete-aggr", do_delete_aggr, 3230790b6dcSAnurag S. Maskey " delete-aggr [-t] <link>" }, 3248d5c46e6Sam223141 { "add-aggr", do_add_aggr, 3250790b6dcSAnurag S. Maskey " add-aggr [-t] -l <link> [-l <link>...] <link>" }, 3268d5c46e6Sam223141 { "remove-aggr", do_remove_aggr, 3270790b6dcSAnurag S. Maskey " remove-aggr [-t] -l <link> [-l <link>...] <link>" }, 3288d5c46e6Sam223141 { "modify-aggr", do_modify_aggr, 3290790b6dcSAnurag S. Maskey " modify-aggr [-t] [-P <policy>] [-L <mode>] [-T <time>] " 3300790b6dcSAnurag S. Maskey "[-u <address>]\n" 3310790b6dcSAnurag S. Maskey "\t\t <link>" }, 3328d5c46e6Sam223141 { "show-aggr", do_show_aggr, 3330790b6dcSAnurag S. Maskey " show-aggr [-pPLx] [-o <field>,..] [-s [-i <interval>]] " 3348d5c46e6Sam223141 "[<link>]\n" }, 3358d5c46e6Sam223141 { "up-aggr", do_up_aggr, NULL }, 3368d5c46e6Sam223141 { "scan-wifi", do_scan_wifi, 3370790b6dcSAnurag S. Maskey " scan-wifi [-p] [-o <field>,...] [<link>]" }, 3388d5c46e6Sam223141 { "connect-wifi", do_connect_wifi, 3390790b6dcSAnurag S. Maskey " connect-wifi [-e <essid>] [-i <bssid>] [-k <key>,...] " 3408d5c46e6Sam223141 "[-s wep|wpa]\n" 3410790b6dcSAnurag S. Maskey "\t\t [-a open|shared] [-b bss|ibss] [-c] [-m a|b|g] " 3420790b6dcSAnurag S. Maskey "[-T <time>]\n" 3430790b6dcSAnurag S. Maskey "\t\t [<link>]" }, 3448d5c46e6Sam223141 { "disconnect-wifi", do_disconnect_wifi, 3450790b6dcSAnurag S. Maskey " disconnect-wifi [-a] [<link>]" }, 3468d5c46e6Sam223141 { "show-wifi", do_show_wifi, 3470790b6dcSAnurag S. Maskey " show-wifi [-p] [-o <field>,...] [<link>]\n" }, 3488d5c46e6Sam223141 { "set-linkprop", do_set_linkprop, 3490790b6dcSAnurag S. Maskey " set-linkprop [-t] -p <prop>=<value>[,...] <name>" }, 3508d5c46e6Sam223141 { "reset-linkprop", do_reset_linkprop, 3510790b6dcSAnurag S. Maskey " reset-linkprop [-t] [-p <prop>,...] <name>" }, 3520790b6dcSAnurag S. Maskey { "show-linkprop", do_show_linkprop, 3530790b6dcSAnurag S. Maskey " show-linkprop [-cP] [-o <field>,...] [-p <prop>,...] " 3540790b6dcSAnurag S. Maskey "<name>\n" }, 3558d5c46e6Sam223141 { "show-ether", do_show_ether, 3560790b6dcSAnurag S. Maskey " show-ether [-px][-o <field>,...] <link>\n" }, 3578d5c46e6Sam223141 { "create-secobj", do_create_secobj, 3580790b6dcSAnurag S. Maskey " create-secobj [-t] [-f <file>] -c <class> <secobj>" }, 3598d5c46e6Sam223141 { "delete-secobj", do_delete_secobj, 3600790b6dcSAnurag S. Maskey " delete-secobj [-t] <secobj>[,...]" }, 3618d5c46e6Sam223141 { "show-secobj", do_show_secobj, 3620790b6dcSAnurag S. Maskey " show-secobj [-pP] [-o <field>,...] [<secobj>,...]\n" }, 3638d5c46e6Sam223141 { "init-linkprop", do_init_linkprop, NULL }, 3648d5c46e6Sam223141 { "init-secobj", do_init_secobj, NULL }, 3658d5c46e6Sam223141 { "create-vlan", do_create_vlan, 3660790b6dcSAnurag S. Maskey " create-vlan [-ft] -l <link> -v <vid> [link]" }, 3678d5c46e6Sam223141 { "delete-vlan", do_delete_vlan, 3680790b6dcSAnurag S. Maskey " delete-vlan [-t] <link>" }, 3698d5c46e6Sam223141 { "show-vlan", do_show_vlan, 3700790b6dcSAnurag S. Maskey " show-vlan [-pP] [-o <field>,..] [<link>]\n" }, 3718d5c46e6Sam223141 { "up-vlan", do_up_vlan, NULL }, 3728d5c46e6Sam223141 { "delete-phys", do_delete_phys, 3730790b6dcSAnurag S. Maskey " delete-phys <link>" }, 3748d5c46e6Sam223141 { "show-phys", do_show_phys, 3750790b6dcSAnurag S. Maskey " show-phys [-pP] [-o <field>,..] [-H] [<link>]\n"}, 3768d5c46e6Sam223141 { "init-phys", do_init_phys, NULL }, 377da14cebeSEric Cheng { "show-linkmap", do_show_linkmap, NULL }, 378da14cebeSEric Cheng { "create-vnic", do_create_vnic, 3790790b6dcSAnurag S. Maskey " create-vnic [-t] -l <link> [-m <value> | auto |\n" 3800790b6dcSAnurag S. Maskey "\t\t {factory [-n <slot-id>]} | {random [-r <prefix>]}]\n" 3810790b6dcSAnurag S. Maskey "\t\t [-v <vid> [-f]] [-p <prop>=<value>[,...]] [-H] " 3820790b6dcSAnurag S. Maskey "<vnic-link>" }, 383da14cebeSEric Cheng { "delete-vnic", do_delete_vnic, 3840790b6dcSAnurag S. Maskey " delete-vnic [-t] <vnic-link>" }, 385da14cebeSEric Cheng { "show-vnic", do_show_vnic, 3860790b6dcSAnurag S. Maskey " show-vnic [-pP] [-l <link>] [-s [-i <interval>]] " 3870790b6dcSAnurag S. Maskey "[<link>]\n" }, 388da14cebeSEric Cheng { "up-vnic", do_up_vnic, NULL }, 389da14cebeSEric Cheng { "create-etherstub", do_create_etherstub, 3900790b6dcSAnurag S. Maskey " create-etherstub [-t] <link>" }, 391da14cebeSEric Cheng { "delete-etherstub", do_delete_etherstub, 3920790b6dcSAnurag S. Maskey " delete-etherstub [-t] <link>" }, 393da14cebeSEric Cheng { "show-etherstub", do_show_etherstub, 3940790b6dcSAnurag S. Maskey " show-etherstub [-t] [<link>]\n" }, 395da14cebeSEric Cheng { "show-usage", do_show_usage, 396ae6aa22aSVenugopal Iyer " show-usage [-a] [-d | -F <format>] " 3970790b6dcSAnurag S. Maskey "[-s <DD/MM/YYYY,HH:MM:SS>]\n" 3980790b6dcSAnurag S. Maskey "\t\t [-e <DD/MM/YYYY,HH:MM:SS>] -f <logfile> [<link>]" } 3997c478bd9Sstevel@tonic-gate }; 4007c478bd9Sstevel@tonic-gate 401d62bc4baSyz147064 static const struct option lopts[] = { 4027c478bd9Sstevel@tonic-gate {"vlan-id", required_argument, 0, 'v'}, 403e7801d59Ssowmini {"output", required_argument, 0, 'o'}, 4047c478bd9Sstevel@tonic-gate {"dev", required_argument, 0, 'd'}, 4057c478bd9Sstevel@tonic-gate {"policy", required_argument, 0, 'P'}, 406d62bc4baSyz147064 {"lacp-mode", required_argument, 0, 'L'}, 4077c478bd9Sstevel@tonic-gate {"lacp-timer", required_argument, 0, 'T'}, 4087c478bd9Sstevel@tonic-gate {"unicast", required_argument, 0, 'u'}, 409d62bc4baSyz147064 {"temporary", no_argument, 0, 't'}, 410d62bc4baSyz147064 {"root-dir", required_argument, 0, 'R'}, 411d62bc4baSyz147064 {"link", required_argument, 0, 'l'}, 412d62bc4baSyz147064 {"forcible", no_argument, 0, 'f'}, 413da14cebeSEric Cheng {"bw-limit", required_argument, 0, 'b'}, 414da14cebeSEric Cheng {"mac-address", required_argument, 0, 'm'}, 415da14cebeSEric Cheng {"slot", required_argument, 0, 'n'}, 416d62bc4baSyz147064 { 0, 0, 0, 0 } 417d62bc4baSyz147064 }; 418d62bc4baSyz147064 419d62bc4baSyz147064 static const struct option show_lopts[] = { 4207c478bd9Sstevel@tonic-gate {"statistics", no_argument, 0, 's'}, 421da14cebeSEric Cheng {"continuous", no_argument, 0, 'S'}, 4227c478bd9Sstevel@tonic-gate {"interval", required_argument, 0, 'i'}, 4237c478bd9Sstevel@tonic-gate {"parseable", no_argument, 0, 'p'}, 424d62bc4baSyz147064 {"extended", no_argument, 0, 'x'}, 425e7801d59Ssowmini {"output", required_argument, 0, 'o'}, 426d62bc4baSyz147064 {"persistent", no_argument, 0, 'P'}, 427d62bc4baSyz147064 {"lacp", no_argument, 0, 'L'}, 4287c478bd9Sstevel@tonic-gate { 0, 0, 0, 0 } 4297c478bd9Sstevel@tonic-gate }; 4307c478bd9Sstevel@tonic-gate 4310ba2cbe9Sxc151355 static const struct option prop_longopts[] = { 4320ba2cbe9Sxc151355 {"temporary", no_argument, 0, 't' }, 433e7801d59Ssowmini {"output", required_argument, 0, 'o' }, 4340ba2cbe9Sxc151355 {"root-dir", required_argument, 0, 'R' }, 4350ba2cbe9Sxc151355 {"prop", required_argument, 0, 'p' }, 4360ba2cbe9Sxc151355 {"parseable", no_argument, 0, 'c' }, 4370ba2cbe9Sxc151355 {"persistent", no_argument, 0, 'P' }, 4380ba2cbe9Sxc151355 { 0, 0, 0, 0 } 4390ba2cbe9Sxc151355 }; 4400ba2cbe9Sxc151355 4410ba2cbe9Sxc151355 static const struct option wifi_longopts[] = { 4420ba2cbe9Sxc151355 {"parseable", no_argument, 0, 'p' }, 4430ba2cbe9Sxc151355 {"output", required_argument, 0, 'o' }, 4440ba2cbe9Sxc151355 {"essid", required_argument, 0, 'e' }, 4450ba2cbe9Sxc151355 {"bsstype", required_argument, 0, 'b' }, 4460ba2cbe9Sxc151355 {"mode", required_argument, 0, 'm' }, 4470ba2cbe9Sxc151355 {"key", required_argument, 0, 'k' }, 4480ba2cbe9Sxc151355 {"sec", required_argument, 0, 's' }, 4490ba2cbe9Sxc151355 {"auth", required_argument, 0, 'a' }, 4500ba2cbe9Sxc151355 {"create-ibss", required_argument, 0, 'c' }, 4510ba2cbe9Sxc151355 {"timeout", required_argument, 0, 'T' }, 4520ba2cbe9Sxc151355 {"all-links", no_argument, 0, 'a' }, 4530ba2cbe9Sxc151355 {"temporary", no_argument, 0, 't' }, 4540ba2cbe9Sxc151355 {"root-dir", required_argument, 0, 'R' }, 4550ba2cbe9Sxc151355 {"persistent", no_argument, 0, 'P' }, 4560ba2cbe9Sxc151355 {"file", required_argument, 0, 'f' }, 4570ba2cbe9Sxc151355 { 0, 0, 0, 0 } 4580ba2cbe9Sxc151355 }; 459e7801d59Ssowmini static const struct option showeth_lopts[] = { 460e7801d59Ssowmini {"parseable", no_argument, 0, 'p' }, 461e7801d59Ssowmini {"extended", no_argument, 0, 'x' }, 462e7801d59Ssowmini {"output", required_argument, 0, 'o' }, 463e7801d59Ssowmini { 0, 0, 0, 0 } 464e7801d59Ssowmini }; 465e7801d59Ssowmini 466da14cebeSEric Cheng static const struct option vnic_lopts[] = { 467da14cebeSEric Cheng {"temporary", no_argument, 0, 't' }, 468da14cebeSEric Cheng {"root-dir", required_argument, 0, 'R' }, 469da14cebeSEric Cheng {"dev", required_argument, 0, 'd' }, 470da14cebeSEric Cheng {"mac-address", required_argument, 0, 'm' }, 471da14cebeSEric Cheng {"cpus", required_argument, 0, 'c' }, 472da14cebeSEric Cheng {"bw-limit", required_argument, 0, 'b' }, 473da14cebeSEric Cheng {"slot", required_argument, 0, 'n' }, 474da14cebeSEric Cheng {"mac-prefix", required_argument, 0, 'r' }, 475da14cebeSEric Cheng { 0, 0, 0, 0 } 476da14cebeSEric Cheng }; 477da14cebeSEric Cheng 478da14cebeSEric Cheng static const struct option etherstub_lopts[] = { 479da14cebeSEric Cheng {"temporary", no_argument, 0, 't' }, 480da14cebeSEric Cheng {"root-dir", required_argument, 0, 'R' }, 481da14cebeSEric Cheng { 0, 0, 0, 0 } 482da14cebeSEric Cheng }; 483da14cebeSEric Cheng 484ae6aa22aSVenugopal Iyer static const struct option usage_opts[] = { 485ae6aa22aSVenugopal Iyer {"file", required_argument, 0, 'f' }, 486ae6aa22aSVenugopal Iyer {"format", required_argument, 0, 'F' }, 487ae6aa22aSVenugopal Iyer {"start", required_argument, 0, 's' }, 488ae6aa22aSVenugopal Iyer {"stop", required_argument, 0, 'e' }, 489ae6aa22aSVenugopal Iyer { 0, 0, 0, 0 } 490ae6aa22aSVenugopal Iyer }; 491ae6aa22aSVenugopal Iyer 492e7801d59Ssowmini /* 493e7801d59Ssowmini * structures for 'dladm show-ether' 494e7801d59Ssowmini */ 4954784fcbdSSowmini Varadhan static const char *ptype[] = {LEI_ATTR_NAMES}; 4964784fcbdSSowmini Varadhan 497e7801d59Ssowmini typedef struct ether_fields_buf_s 498e7801d59Ssowmini { 499e7801d59Ssowmini char eth_link[15]; 500e7801d59Ssowmini char eth_ptype[8]; 501e7801d59Ssowmini char eth_state[8]; 502e7801d59Ssowmini char eth_autoneg[5]; 503e7801d59Ssowmini char eth_spdx[31]; 504e7801d59Ssowmini char eth_pause[6]; 505e7801d59Ssowmini char eth_rem_fault[16]; 506e7801d59Ssowmini } ether_fields_buf_t; 507e7801d59Ssowmini 508e7801d59Ssowmini static print_field_t ether_fields[] = { 509e7801d59Ssowmini /* name, header, field width, offset, cmdtype */ 510e7801d59Ssowmini { "link", "LINK", 15, 511e7801d59Ssowmini offsetof(ether_fields_buf_t, eth_link), CMD_TYPE_ANY}, 512e7801d59Ssowmini { "ptype", "PTYPE", 8, 513e7801d59Ssowmini offsetof(ether_fields_buf_t, eth_ptype), CMD_TYPE_ANY}, 514e7801d59Ssowmini { "state", "STATE", 8, 515e7801d59Ssowmini offsetof(ether_fields_buf_t, eth_state), CMD_TYPE_ANY}, 516e7801d59Ssowmini { "auto", "AUTO", 5, 517e7801d59Ssowmini offsetof(ether_fields_buf_t, eth_autoneg), CMD_TYPE_ANY}, 518e7801d59Ssowmini { "speed-duplex", "SPEED-DUPLEX", 31, 519e7801d59Ssowmini offsetof(ether_fields_buf_t, eth_spdx), CMD_TYPE_ANY}, 520e7801d59Ssowmini { "pause", "PAUSE", 6, 521e7801d59Ssowmini offsetof(ether_fields_buf_t, eth_pause), CMD_TYPE_ANY}, 522e7801d59Ssowmini { "rem_fault", "REM_FAULT", 16, 523e7801d59Ssowmini offsetof(ether_fields_buf_t, eth_rem_fault), CMD_TYPE_ANY}} 524e7801d59Ssowmini ; 525e7801d59Ssowmini #define ETHER_MAX_FIELDS (sizeof (ether_fields) / sizeof (print_field_t)) 526e7801d59Ssowmini 527e7801d59Ssowmini typedef struct print_ether_state { 528e7801d59Ssowmini const char *es_link; 529e7801d59Ssowmini boolean_t es_parseable; 530e7801d59Ssowmini boolean_t es_header; 531e7801d59Ssowmini boolean_t es_extended; 532e7801d59Ssowmini print_state_t es_print; 533e7801d59Ssowmini } print_ether_state_t; 534e7801d59Ssowmini 535e7801d59Ssowmini /* 536da14cebeSEric Cheng * structures for 'dladm show-link -s' (print statistics) 537e7801d59Ssowmini */ 538e7801d59Ssowmini typedef enum { 539ae6aa22aSVenugopal Iyer LINK_S_LINK, 540ae6aa22aSVenugopal Iyer LINK_S_IPKTS, 541ae6aa22aSVenugopal Iyer LINK_S_RBYTES, 542ae6aa22aSVenugopal Iyer LINK_S_IERRORS, 543ae6aa22aSVenugopal Iyer LINK_S_OPKTS, 544ae6aa22aSVenugopal Iyer LINK_S_OBYTES, 545ae6aa22aSVenugopal Iyer LINK_S_OERRORS 546ae6aa22aSVenugopal Iyer } link_s_field_index_t; 547e7801d59Ssowmini 548ae6aa22aSVenugopal Iyer static print_field_t link_s_fields[] = { 549e7801d59Ssowmini /* name, header, field width, index, cmdtype */ 550ae6aa22aSVenugopal Iyer { "link", "LINK", 15, LINK_S_LINK, CMD_TYPE_ANY}, 551ae6aa22aSVenugopal Iyer { "ipackets", "IPACKETS", 10, LINK_S_IPKTS, CMD_TYPE_ANY}, 552ae6aa22aSVenugopal Iyer { "rbytes", "RBYTES", 8, LINK_S_RBYTES, CMD_TYPE_ANY}, 553ae6aa22aSVenugopal Iyer { "ierrors", "IERRORS", 10, LINK_S_IERRORS, CMD_TYPE_ANY}, 554ae6aa22aSVenugopal Iyer { "opackets", "OPACKETS", 12, LINK_S_OPKTS, CMD_TYPE_ANY}, 555ae6aa22aSVenugopal Iyer { "obytes", "OBYTES", 12, LINK_S_OBYTES, CMD_TYPE_ANY}, 556ae6aa22aSVenugopal Iyer { "oerrors", "OERRORS", 8, LINK_S_OERRORS, CMD_TYPE_ANY}} 557e7801d59Ssowmini ; 558ae6aa22aSVenugopal Iyer #define LINK_S_MAX_FIELDS \ 559ae6aa22aSVenugopal Iyer (sizeof (link_s_fields) / sizeof (print_field_t)) 560ae6aa22aSVenugopal Iyer 561ae6aa22aSVenugopal Iyer typedef struct link_args_s { 562ae6aa22aSVenugopal Iyer char *link_s_link; 563ae6aa22aSVenugopal Iyer pktsum_t *link_s_psum; 564ae6aa22aSVenugopal Iyer } link_args_t; 565ae6aa22aSVenugopal Iyer static char *print_link_stats(print_field_t *, void *); 566e7801d59Ssowmini 567e7801d59Ssowmini /* 568e7801d59Ssowmini * buffer used by print functions for show-{link,phys,vlan} commands. 569e7801d59Ssowmini */ 570e7801d59Ssowmini typedef struct link_fields_buf_s { 571e7801d59Ssowmini char link_name[MAXLINKNAMELEN]; 572e7801d59Ssowmini char link_class[DLADM_STRSIZE]; 573c08e5e1aSdr146992 char link_mtu[11]; 574e7801d59Ssowmini char link_state[DLADM_STRSIZE]; 575e7801d59Ssowmini char link_over[MAXLINKNAMELEN]; 5764045d941Ssowmini char link_phys_state[DLADM_STRSIZE]; 577e7801d59Ssowmini char link_phys_media[DLADM_STRSIZE]; 578e7801d59Ssowmini char link_phys_speed[DLADM_STRSIZE]; 579e7801d59Ssowmini char link_phys_duplex[DLPI_LINKNAME_MAX]; 580e7801d59Ssowmini char link_phys_device[DLPI_LINKNAME_MAX]; 581e7801d59Ssowmini char link_flags[6]; 582e7801d59Ssowmini char link_vlan_vid[6]; 583e7801d59Ssowmini } link_fields_buf_t; 584e7801d59Ssowmini 585e7801d59Ssowmini /* 586e7801d59Ssowmini * structures for 'dladm show-link' 587e7801d59Ssowmini */ 588e7801d59Ssowmini static print_field_t link_fields[] = { 589e7801d59Ssowmini /* name, header, field width, offset, cmdtype */ 590e7801d59Ssowmini { "link", "LINK", 11, 591e7801d59Ssowmini offsetof(link_fields_buf_t, link_name), CMD_TYPE_ANY}, 592e7801d59Ssowmini { "class", "CLASS", 8, 593e7801d59Ssowmini offsetof(link_fields_buf_t, link_class), CMD_TYPE_ANY}, 594e7801d59Ssowmini { "mtu", "MTU", 6, 595e7801d59Ssowmini offsetof(link_fields_buf_t, link_mtu), CMD_TYPE_ANY}, 596e7801d59Ssowmini { "state", "STATE", 8, 597e7801d59Ssowmini offsetof(link_fields_buf_t, link_state), CMD_TYPE_ANY}, 598e7801d59Ssowmini { "over", "OVER", DLPI_LINKNAME_MAX, 599e7801d59Ssowmini offsetof(link_fields_buf_t, link_over), CMD_TYPE_ANY}} 600e7801d59Ssowmini ; 601e7801d59Ssowmini #define DEV_LINK_FIELDS (sizeof (link_fields) / sizeof (print_field_t)) 602e7801d59Ssowmini 603e7801d59Ssowmini /* 604e7801d59Ssowmini * structures for 'dladm show-aggr' 605e7801d59Ssowmini */ 606e7801d59Ssowmini typedef struct laggr_fields_buf_s { 607e7801d59Ssowmini char laggr_name[DLPI_LINKNAME_MAX]; 608e7801d59Ssowmini char laggr_policy[9]; 609e7801d59Ssowmini char laggr_addrpolicy[ETHERADDRL * 3 + 3]; 610e7801d59Ssowmini char laggr_lacpactivity[14]; 611e7801d59Ssowmini char laggr_lacptimer[DLADM_STRSIZE]; 612e7801d59Ssowmini char laggr_flags[7]; 613e7801d59Ssowmini } laggr_fields_buf_t; 614e7801d59Ssowmini 615e7801d59Ssowmini typedef struct laggr_args_s { 616e7801d59Ssowmini int laggr_lport; /* -1 indicates the aggr itself */ 617e7801d59Ssowmini const char *laggr_link; 618e7801d59Ssowmini dladm_aggr_grp_attr_t *laggr_ginfop; 619e7801d59Ssowmini dladm_status_t *laggr_status; 620e7801d59Ssowmini pktsum_t *laggr_pktsumtot; /* -s only */ 621e7801d59Ssowmini pktsum_t *laggr_prevstats; /* -s only */ 622e7801d59Ssowmini boolean_t laggr_parseable; 623e7801d59Ssowmini } laggr_args_t; 624e7801d59Ssowmini 625e7801d59Ssowmini static print_field_t laggr_fields[] = { 626e7801d59Ssowmini /* name, header, field width, offset, cmdtype */ 627e7801d59Ssowmini { "link", "LINK", 15, 628e7801d59Ssowmini offsetof(laggr_fields_buf_t, laggr_name), CMD_TYPE_ANY}, 629e7801d59Ssowmini { "policy", "POLICY", 8, 630e7801d59Ssowmini offsetof(laggr_fields_buf_t, laggr_policy), CMD_TYPE_ANY}, 631e7801d59Ssowmini { "addrpolicy", "ADDRPOLICY", ETHERADDRL * 3 + 2, 632e7801d59Ssowmini offsetof(laggr_fields_buf_t, laggr_addrpolicy), CMD_TYPE_ANY}, 633e7801d59Ssowmini { "lacpactivity", "LACPACTIVITY", 13, 634e7801d59Ssowmini offsetof(laggr_fields_buf_t, laggr_lacpactivity), CMD_TYPE_ANY}, 635e7801d59Ssowmini { "lacptimer", "LACPTIMER", 11, 636e7801d59Ssowmini offsetof(laggr_fields_buf_t, laggr_lacptimer), CMD_TYPE_ANY}, 637e7801d59Ssowmini { "flags", "FLAGS", 7, 638e7801d59Ssowmini offsetof(laggr_fields_buf_t, laggr_flags), CMD_TYPE_ANY}} 639e7801d59Ssowmini ; 640e7801d59Ssowmini #define LAGGR_MAX_FIELDS (sizeof (laggr_fields) / sizeof (print_field_t)) 641e7801d59Ssowmini 642e7801d59Ssowmini /* 643e7801d59Ssowmini * structures for 'dladm show-aggr -x'. 644e7801d59Ssowmini */ 645e7801d59Ssowmini typedef enum { 646e7801d59Ssowmini AGGR_X_LINK, 647e7801d59Ssowmini AGGR_X_PORT, 648e7801d59Ssowmini AGGR_X_SPEED, 649e7801d59Ssowmini AGGR_X_DUPLEX, 650e7801d59Ssowmini AGGR_X_STATE, 651e7801d59Ssowmini AGGR_X_ADDRESS, 652e7801d59Ssowmini AGGR_X_PORTSTATE 653e7801d59Ssowmini } aggr_x_field_index_t; 654e7801d59Ssowmini 655e7801d59Ssowmini static print_field_t aggr_x_fields[] = { 656e7801d59Ssowmini /* name, header, field width, index, cmdtype */ 657e7801d59Ssowmini { "link", "LINK", 11, AGGR_X_LINK, CMD_TYPE_ANY}, 658e7801d59Ssowmini { "port", "PORT", 14, AGGR_X_PORT, CMD_TYPE_ANY}, 659e7801d59Ssowmini { "speed", "SPEED", 4, AGGR_X_SPEED, CMD_TYPE_ANY}, 660e7801d59Ssowmini { "duplex", "DUPLEX", 9, AGGR_X_DUPLEX, CMD_TYPE_ANY}, 661e7801d59Ssowmini { "state", "STATE", 9, AGGR_X_STATE, CMD_TYPE_ANY}, 662e7801d59Ssowmini { "address", "ADDRESS", 18, AGGR_X_ADDRESS, CMD_TYPE_ANY}, 663e7801d59Ssowmini { "portstate", "PORTSTATE", 15, AGGR_X_PORTSTATE, CMD_TYPE_ANY}} 664e7801d59Ssowmini ; 665e7801d59Ssowmini #define AGGR_X_MAX_FIELDS \ 666e7801d59Ssowmini (sizeof (aggr_x_fields) / sizeof (print_field_t)) 667e7801d59Ssowmini 668e7801d59Ssowmini /* 669e7801d59Ssowmini * structures for 'dladm show-aggr -s'. 670e7801d59Ssowmini */ 671e7801d59Ssowmini typedef enum { 672e7801d59Ssowmini AGGR_S_LINK, 673e7801d59Ssowmini AGGR_S_PORT, 674e7801d59Ssowmini AGGR_S_IPKTS, 675e7801d59Ssowmini AGGR_S_RBYTES, 676e7801d59Ssowmini AGGR_S_OPKTS, 677e7801d59Ssowmini AGGR_S_OBYTES, 678e7801d59Ssowmini AGGR_S_IPKTDIST, 679e7801d59Ssowmini AGGR_S_OPKTDIST 680e7801d59Ssowmini } aggr_s_field_index_t; 681e7801d59Ssowmini 682e7801d59Ssowmini static print_field_t aggr_s_fields[] = { 683e7801d59Ssowmini /* name, header, field width, index, cmdtype */ 684e7801d59Ssowmini { "link", "LINK", 11, AGGR_S_LINK, 685e7801d59Ssowmini CMD_TYPE_ANY}, 686e7801d59Ssowmini { "port", "PORT", 9, AGGR_S_PORT, 687e7801d59Ssowmini CMD_TYPE_ANY}, 688e7801d59Ssowmini { "ipackets", "IPACKETS", 7, AGGR_S_IPKTS, 689e7801d59Ssowmini CMD_TYPE_ANY}, 690e7801d59Ssowmini { "rbytes", "RBYTES", 7, AGGR_S_RBYTES, 691e7801d59Ssowmini CMD_TYPE_ANY}, 692e7801d59Ssowmini { "opackets", "OPACKETS", 7, AGGR_S_OPKTS, 693e7801d59Ssowmini CMD_TYPE_ANY}, 694e7801d59Ssowmini { "obytes", "OBYTES", 7, AGGR_S_OBYTES, 695e7801d59Ssowmini CMD_TYPE_ANY}, 696e7801d59Ssowmini { "ipktdist", "IPKTDIST", 8, AGGR_S_IPKTDIST, 697e7801d59Ssowmini CMD_TYPE_ANY}, 698e7801d59Ssowmini { "opktdist", "OPKTDIST", 14, AGGR_S_OPKTDIST, 699e7801d59Ssowmini CMD_TYPE_ANY}} 700e7801d59Ssowmini ; 701e7801d59Ssowmini #define AGGR_S_MAX_FIELDS \ 702da14cebeSEric Cheng (sizeof (aggr_s_fields) / sizeof (print_field_t)) 703e7801d59Ssowmini 704e7801d59Ssowmini /* 705da14cebeSEric Cheng * structures for 'dladm show-aggr -L'. 706e7801d59Ssowmini */ 707e7801d59Ssowmini typedef enum { 708e7801d59Ssowmini AGGR_L_LINK, 709e7801d59Ssowmini AGGR_L_PORT, 710e7801d59Ssowmini AGGR_L_AGGREGATABLE, 711e7801d59Ssowmini AGGR_L_SYNC, 712e7801d59Ssowmini AGGR_L_COLL, 713e7801d59Ssowmini AGGR_L_DIST, 714e7801d59Ssowmini AGGR_L_DEFAULTED, 715e7801d59Ssowmini AGGR_L_EXPIRED 716e7801d59Ssowmini } aggr_l_field_index_t; 717e7801d59Ssowmini 718e7801d59Ssowmini static print_field_t aggr_l_fields[] = { 719e7801d59Ssowmini /* name, header, field width, index, cmdtype */ 720e7801d59Ssowmini { "link", "LINK", 11, AGGR_L_LINK, 721e7801d59Ssowmini CMD_TYPE_ANY}, 722e7801d59Ssowmini { "port", "PORT", 12, AGGR_L_PORT, 723e7801d59Ssowmini CMD_TYPE_ANY}, 724e7801d59Ssowmini { "aggregatable", "AGGREGATABLE", 12, AGGR_L_AGGREGATABLE, 725e7801d59Ssowmini CMD_TYPE_ANY}, 726e7801d59Ssowmini { "sync", "SYNC", 4, AGGR_L_SYNC, 727e7801d59Ssowmini CMD_TYPE_ANY}, 728e7801d59Ssowmini { "coll", "COLL", 4, AGGR_L_COLL, 729e7801d59Ssowmini CMD_TYPE_ANY}, 730e7801d59Ssowmini { "dist", "DIST", 4, AGGR_L_DIST, 731e7801d59Ssowmini CMD_TYPE_ANY}, 732e7801d59Ssowmini { "defaulted", "DEFAULTED", 9, AGGR_L_DEFAULTED, 733e7801d59Ssowmini CMD_TYPE_ANY}, 734e7801d59Ssowmini { "expired", "EXPIRED", 14, AGGR_L_EXPIRED, 735e7801d59Ssowmini CMD_TYPE_ANY}} 736e7801d59Ssowmini ; 737e7801d59Ssowmini #define AGGR_L_MAX_FIELDS \ 738e7801d59Ssowmini (sizeof (aggr_l_fields) / sizeof (print_field_t)) 739e7801d59Ssowmini 740e7801d59Ssowmini /* 741e7801d59Ssowmini * structures for 'dladm show-phys' 742e7801d59Ssowmini */ 743e7801d59Ssowmini 744e7801d59Ssowmini static print_field_t phys_fields[] = { 745e7801d59Ssowmini /* name, header, field width, offset, cmdtype */ 746e7801d59Ssowmini { "link", "LINK", 12, 747e7801d59Ssowmini offsetof(link_fields_buf_t, link_name), CMD_TYPE_ANY}, 748e7801d59Ssowmini { "media", "MEDIA", 20, 749e7801d59Ssowmini offsetof(link_fields_buf_t, link_phys_media), CMD_TYPE_ANY}, 750e7801d59Ssowmini { "state", "STATE", 10, 751e7801d59Ssowmini offsetof(link_fields_buf_t, link_phys_state), CMD_TYPE_ANY}, 7526be03d0bSVasumathi Sundaram - Sun Microsystems { "speed", "SPEED", 6, 753e7801d59Ssowmini offsetof(link_fields_buf_t, link_phys_speed), CMD_TYPE_ANY}, 754e7801d59Ssowmini { "duplex", "DUPLEX", 9, 755e7801d59Ssowmini offsetof(link_fields_buf_t, link_phys_duplex), CMD_TYPE_ANY}, 756e7801d59Ssowmini { "device", "DEVICE", 12, 757e7801d59Ssowmini offsetof(link_fields_buf_t, link_phys_device), CMD_TYPE_ANY}, 758e7801d59Ssowmini { "flags", "FLAGS", 6, 759e7801d59Ssowmini offsetof(link_fields_buf_t, link_flags), CMD_TYPE_ANY}} 760e7801d59Ssowmini ; 761e7801d59Ssowmini #define PHYS_MAX_FIELDS (sizeof (phys_fields) / sizeof (print_field_t)) 762e7801d59Ssowmini 763e7801d59Ssowmini /* 764da14cebeSEric Cheng * structures for 'dladm show-phys -m' 765da14cebeSEric Cheng */ 766da14cebeSEric Cheng 767da14cebeSEric Cheng typedef enum { 768da14cebeSEric Cheng PHYS_M_LINK, 769da14cebeSEric Cheng PHYS_M_SLOT, 770da14cebeSEric Cheng PHYS_M_ADDRESS, 771da14cebeSEric Cheng PHYS_M_INUSE, 772da14cebeSEric Cheng PHYS_M_CLIENT 773da14cebeSEric Cheng } phys_m_field_index_t; 774da14cebeSEric Cheng 775da14cebeSEric Cheng static print_field_t phys_m_fields[] = { 776da14cebeSEric Cheng /* name, header, field width, offset, cmdtype */ 777da14cebeSEric Cheng { "link", "LINK", 12, PHYS_M_LINK, CMD_TYPE_ANY}, 778da14cebeSEric Cheng { "slot", "SLOT", 8, PHYS_M_SLOT, CMD_TYPE_ANY}, 779da14cebeSEric Cheng { "address", "ADDRESS", 18, PHYS_M_ADDRESS, CMD_TYPE_ANY}, 780da14cebeSEric Cheng { "inuse", "INUSE", 4, PHYS_M_INUSE, CMD_TYPE_ANY}, 781da14cebeSEric Cheng { "client", "CLIENT", 12, PHYS_M_CLIENT, CMD_TYPE_ANY}} 782da14cebeSEric Cheng ; 783da14cebeSEric Cheng #define PHYS_M_MAX_FIELDS (sizeof (phys_m_fields) / sizeof (print_field_t)) 784da14cebeSEric Cheng 785da14cebeSEric Cheng /* 786da14cebeSEric Cheng * structures for 'dladm show-phys -H' 787da14cebeSEric Cheng */ 788da14cebeSEric Cheng 789da14cebeSEric Cheng typedef enum { 790da14cebeSEric Cheng PHYS_H_LINK, 791da14cebeSEric Cheng PHYS_H_GROUP, 792da14cebeSEric Cheng PHYS_H_GRPTYPE, 793da14cebeSEric Cheng PHYS_H_RINGS, 794da14cebeSEric Cheng PHYS_H_CLIENTS 795da14cebeSEric Cheng } phys_h_field_index_t; 796da14cebeSEric Cheng 797da14cebeSEric Cheng static print_field_t phys_h_fields[] = { 798da14cebeSEric Cheng /* name, header, field width, offset, cmdtype */ 799da14cebeSEric Cheng { "link", "LINK", 12, PHYS_H_LINK, CMD_TYPE_ANY}, 800da14cebeSEric Cheng { "group", "GROUP", 8, PHYS_H_GROUP, CMD_TYPE_ANY}, 801da14cebeSEric Cheng { "grouptype", "TYPE", 6, PHYS_H_GRPTYPE, CMD_TYPE_ANY}, 802da14cebeSEric Cheng { "rings", "NUM-RINGS", 16, PHYS_H_RINGS, CMD_TYPE_ANY}, 803da14cebeSEric Cheng { "clients", "CLIENTS", 20, PHYS_H_CLIENTS, CMD_TYPE_ANY}} 804da14cebeSEric Cheng ; 805da14cebeSEric Cheng #define PHYS_H_MAX_FIELDS (sizeof (phys_h_fields) / sizeof (print_field_t)) 806da14cebeSEric Cheng 807da14cebeSEric Cheng /* 808e7801d59Ssowmini * structures for 'dladm show-vlan' 809e7801d59Ssowmini */ 810e7801d59Ssowmini static print_field_t vlan_fields[] = { 811e7801d59Ssowmini /* name, header, field width, offset, cmdtype */ 812e7801d59Ssowmini { "link", "LINK", 15, 813e7801d59Ssowmini offsetof(link_fields_buf_t, link_name), CMD_TYPE_ANY}, 814e7801d59Ssowmini { "vid", "VID", 8, 815e7801d59Ssowmini offsetof(link_fields_buf_t, link_vlan_vid), CMD_TYPE_ANY}, 816e7801d59Ssowmini { "over", "OVER", 12, 817e7801d59Ssowmini offsetof(link_fields_buf_t, link_over), CMD_TYPE_ANY}, 818e7801d59Ssowmini { "flags", "FLAGS", 6, 819e7801d59Ssowmini offsetof(link_fields_buf_t, link_flags), CMD_TYPE_ANY}} 820e7801d59Ssowmini ; 821e7801d59Ssowmini #define VLAN_MAX_FIELDS (sizeof (vlan_fields) / sizeof (print_field_t)) 822e7801d59Ssowmini 823da14cebeSEric Cheng 824e7801d59Ssowmini /* 825e7801d59Ssowmini * structures for 'dladm show-wifi' 826e7801d59Ssowmini */ 827e7801d59Ssowmini static print_field_t wifi_fields[] = { 828e7801d59Ssowmini { "link", "LINK", 10, 0, WIFI_CMD_ALL}, 829e7801d59Ssowmini { "essid", "ESSID", 19, DLADM_WLAN_ATTR_ESSID, WIFI_CMD_ALL}, 830e7801d59Ssowmini { "bssid", "BSSID/IBSSID", 17, DLADM_WLAN_ATTR_BSSID, WIFI_CMD_ALL}, 831e7801d59Ssowmini { "ibssid", "BSSID/IBSSID", 17, DLADM_WLAN_ATTR_BSSID, WIFI_CMD_ALL}, 832e7801d59Ssowmini { "mode", "MODE", 6, DLADM_WLAN_ATTR_MODE, WIFI_CMD_ALL}, 833e7801d59Ssowmini { "speed", "SPEED", 6, DLADM_WLAN_ATTR_SPEED, WIFI_CMD_ALL}, 834e7801d59Ssowmini { "auth", "AUTH", 8, DLADM_WLAN_ATTR_AUTH, WIFI_CMD_SHOW}, 835e7801d59Ssowmini { "bsstype", "BSSTYPE", 8, DLADM_WLAN_ATTR_BSSTYPE, WIFI_CMD_ALL}, 836e7801d59Ssowmini { "sec", "SEC", 6, DLADM_WLAN_ATTR_SECMODE, WIFI_CMD_ALL}, 837e7801d59Ssowmini { "status", "STATUS", 17, DLADM_WLAN_LINKATTR_STATUS, WIFI_CMD_SHOW}, 838e7801d59Ssowmini { "strength", "STRENGTH", 10, DLADM_WLAN_ATTR_STRENGTH, WIFI_CMD_ALL}} 839e7801d59Ssowmini ; 840e7801d59Ssowmini 841e7801d59Ssowmini static char *all_scan_wifi_fields = 842e7801d59Ssowmini "link,essid,bssid,sec,strength,mode,speed,bsstype"; 843e7801d59Ssowmini static char *all_show_wifi_fields = 844e7801d59Ssowmini "link,status,essid,sec,strength,mode,speed,auth,bssid,bsstype"; 845e7801d59Ssowmini static char *def_scan_wifi_fields = 846e7801d59Ssowmini "link,essid,bssid,sec,strength,mode,speed"; 847e7801d59Ssowmini static char *def_show_wifi_fields = 848e7801d59Ssowmini "link,status,essid,sec,strength,mode,speed"; 849e7801d59Ssowmini 850e7801d59Ssowmini #define WIFI_MAX_FIELDS (sizeof (wifi_fields) / sizeof (print_field_t)) 851e7801d59Ssowmini 852e7801d59Ssowmini /* 853e7801d59Ssowmini * structures for 'dladm show-linkprop' 854e7801d59Ssowmini */ 855e7801d59Ssowmini typedef enum { 856e7801d59Ssowmini LINKPROP_LINK, 857e7801d59Ssowmini LINKPROP_PROPERTY, 858afdda45fSVasumathi Sundaram - Sun Microsystems LINKPROP_PERM, 859e7801d59Ssowmini LINKPROP_VALUE, 860e7801d59Ssowmini LINKPROP_DEFAULT, 861e7801d59Ssowmini LINKPROP_POSSIBLE 862e7801d59Ssowmini } linkprop_field_index_t; 863e7801d59Ssowmini 864e7801d59Ssowmini static print_field_t linkprop_fields[] = { 865e7801d59Ssowmini /* name, header, field width, index, cmdtype */ 866e7801d59Ssowmini { "link", "LINK", 12, LINKPROP_LINK, CMD_TYPE_ANY}, 867e7801d59Ssowmini { "property", "PROPERTY", 15, LINKPROP_PROPERTY, CMD_TYPE_ANY}, 868afdda45fSVasumathi Sundaram - Sun Microsystems { "perm", "PERM", 4, LINKPROP_PERM, CMD_TYPE_ANY}, 869e7801d59Ssowmini { "value", "VALUE", 14, LINKPROP_VALUE, CMD_TYPE_ANY}, 870e7801d59Ssowmini { "default", "DEFAULT", 14, LINKPROP_DEFAULT, CMD_TYPE_ANY}, 871e7801d59Ssowmini { "possible", "POSSIBLE", 20, LINKPROP_POSSIBLE, CMD_TYPE_ANY}} 872e7801d59Ssowmini ; 873e7801d59Ssowmini #define LINKPROP_MAX_FIELDS \ 874e7801d59Ssowmini (sizeof (linkprop_fields) / sizeof (print_field_t)) 875e7801d59Ssowmini 876e7801d59Ssowmini #define MAX_PROP_LINE 512 877e7801d59Ssowmini 878e7801d59Ssowmini typedef struct show_linkprop_state { 879e7801d59Ssowmini char ls_link[MAXLINKNAMELEN]; 880e7801d59Ssowmini char *ls_line; 881e7801d59Ssowmini char **ls_propvals; 882da14cebeSEric Cheng dladm_arg_list_t *ls_proplist; 883e7801d59Ssowmini boolean_t ls_parseable; 884e7801d59Ssowmini boolean_t ls_persist; 885e7801d59Ssowmini boolean_t ls_header; 886e7801d59Ssowmini dladm_status_t ls_status; 887e7801d59Ssowmini dladm_status_t ls_retstatus; 888e7801d59Ssowmini print_state_t ls_print; 889e7801d59Ssowmini } show_linkprop_state_t; 890e7801d59Ssowmini 891da14cebeSEric Cheng typedef struct set_linkprop_state { 892da14cebeSEric Cheng const char *ls_name; 893da14cebeSEric Cheng boolean_t ls_reset; 894da14cebeSEric Cheng boolean_t ls_temp; 895da14cebeSEric Cheng dladm_status_t ls_status; 896da14cebeSEric Cheng } set_linkprop_state_t; 897da14cebeSEric Cheng 898e7801d59Ssowmini typedef struct linkprop_args_s { 899e7801d59Ssowmini show_linkprop_state_t *ls_state; 900e7801d59Ssowmini char *ls_propname; 901e7801d59Ssowmini datalink_id_t ls_linkid; 902e7801d59Ssowmini } linkprop_args_t; 903e7801d59Ssowmini 904e7801d59Ssowmini /* 905e7801d59Ssowmini * structures for 'dladm show-secobj' 906e7801d59Ssowmini */ 907e7801d59Ssowmini typedef struct secobj_fields_buf_s { 908e7801d59Ssowmini char ss_obj_name[DLADM_SECOBJ_VAL_MAX]; 909e7801d59Ssowmini char ss_class[20]; 910e7801d59Ssowmini char ss_val[30]; 911e7801d59Ssowmini } secobj_fields_buf_t; 912e7801d59Ssowmini static print_field_t secobj_fields[] = { 913e7801d59Ssowmini /* name, header, field width, offset, cmdtype */ 914e7801d59Ssowmini { "object", "OBJECT", 20, 915e7801d59Ssowmini offsetof(secobj_fields_buf_t, ss_obj_name), CMD_TYPE_ANY}, 916e7801d59Ssowmini { "class", "CLASS", 20, 917e7801d59Ssowmini offsetof(secobj_fields_buf_t, ss_class), CMD_TYPE_ANY}, 918e7801d59Ssowmini { "value", "VALUE", 30, 919e7801d59Ssowmini offsetof(secobj_fields_buf_t, ss_val), CMD_TYPE_ANY}} 920e7801d59Ssowmini ; 921e7801d59Ssowmini #define DEV_SOBJ_FIELDS (sizeof (secobj_fields) / sizeof (print_field_t)) 9220ba2cbe9Sxc151355 923da14cebeSEric Cheng /* 924da14cebeSEric Cheng * structures for 'dladm show-vnic' 925da14cebeSEric Cheng */ 926da14cebeSEric Cheng typedef struct vnic_fields_buf_s 927da14cebeSEric Cheng { 928da14cebeSEric Cheng char vnic_link[DLPI_LINKNAME_MAX]; 929da14cebeSEric Cheng char vnic_over[DLPI_LINKNAME_MAX]; 930da14cebeSEric Cheng char vnic_speed[6]; 931da14cebeSEric Cheng char vnic_macaddr[19]; 932da14cebeSEric Cheng char vnic_macaddrtype[19]; 933da14cebeSEric Cheng char vnic_vid[6]; 934da14cebeSEric Cheng } vnic_fields_buf_t; 935da14cebeSEric Cheng 936da14cebeSEric Cheng static print_field_t vnic_fields[] = { 937da14cebeSEric Cheng /* name, header, field width, offset, cmdtype */ 938da14cebeSEric Cheng { "link", "LINK", 12, 939da14cebeSEric Cheng offsetof(vnic_fields_buf_t, vnic_link), CMD_TYPE_ANY}, 940da14cebeSEric Cheng { "over", "OVER", 12, 941da14cebeSEric Cheng offsetof(vnic_fields_buf_t, vnic_over), CMD_TYPE_ANY}, 942da14cebeSEric Cheng { "speed", "SPEED", 6, 943da14cebeSEric Cheng offsetof(vnic_fields_buf_t, vnic_speed), CMD_TYPE_ANY}, 944ae6aa22aSVenugopal Iyer { "macaddress", "MACADDRESS", 20, 945da14cebeSEric Cheng offsetof(vnic_fields_buf_t, vnic_macaddr), CMD_TYPE_ANY}, 946da14cebeSEric Cheng { "macaddrtype", "MACADDRTYPE", 19, 947da14cebeSEric Cheng offsetof(vnic_fields_buf_t, vnic_macaddrtype), CMD_TYPE_ANY}, 948da14cebeSEric Cheng { "vid", "VID", 6, 949da14cebeSEric Cheng offsetof(vnic_fields_buf_t, vnic_vid), CMD_TYPE_ANY}} 950da14cebeSEric Cheng ; 951da14cebeSEric Cheng #define VNIC_MAX_FIELDS (sizeof (vnic_fields) / sizeof (print_field_t)) 952da14cebeSEric Cheng 953da14cebeSEric Cheng /* 954da14cebeSEric Cheng * structures for 'dladm show-usage' 955da14cebeSEric Cheng */ 956da14cebeSEric Cheng 957da14cebeSEric Cheng typedef struct usage_fields_buf_s { 958da14cebeSEric Cheng char usage_link[12]; 959da14cebeSEric Cheng char usage_duration[10]; 960da14cebeSEric Cheng char usage_ipackets[9]; 961da14cebeSEric Cheng char usage_rbytes[10]; 962da14cebeSEric Cheng char usage_opackets[9]; 963da14cebeSEric Cheng char usage_obytes[10]; 964da14cebeSEric Cheng char usage_bandwidth[14]; 965da14cebeSEric Cheng } usage_fields_buf_t; 966da14cebeSEric Cheng 967da14cebeSEric Cheng static print_field_t usage_fields[] = { 968da14cebeSEric Cheng /* name, header, field width, offset, cmdtype */ 969da14cebeSEric Cheng { "link", "LINK", 12, 970da14cebeSEric Cheng offsetof(usage_fields_buf_t, usage_link), CMD_TYPE_ANY}, 971da14cebeSEric Cheng { "duration", "DURATION", 10, 972da14cebeSEric Cheng offsetof(usage_fields_buf_t, usage_duration), CMD_TYPE_ANY}, 973da14cebeSEric Cheng { "ipackets", "IPACKETS", 9, 974da14cebeSEric Cheng offsetof(usage_fields_buf_t, usage_ipackets), CMD_TYPE_ANY}, 975da14cebeSEric Cheng { "rbytes", "RBYTES", 10, 976da14cebeSEric Cheng offsetof(usage_fields_buf_t, usage_rbytes), CMD_TYPE_ANY}, 977da14cebeSEric Cheng { "opackets", "OPACKETS", 9, 978da14cebeSEric Cheng offsetof(usage_fields_buf_t, usage_opackets), CMD_TYPE_ANY}, 979da14cebeSEric Cheng { "obytes", "OBYTES", 10, 980da14cebeSEric Cheng offsetof(usage_fields_buf_t, usage_obytes), CMD_TYPE_ANY}, 981da14cebeSEric Cheng { "bandwidth", "BANDWIDTH", 14, 982da14cebeSEric Cheng offsetof(usage_fields_buf_t, usage_bandwidth), CMD_TYPE_ANY}} 983da14cebeSEric Cheng ; 984da14cebeSEric Cheng 985da14cebeSEric Cheng #define USAGE_MAX_FIELDS (sizeof (usage_fields) / sizeof (print_field_t)) 986da14cebeSEric Cheng 987da14cebeSEric Cheng /* 988da14cebeSEric Cheng * structures for 'dladm show-usage link' 989da14cebeSEric Cheng */ 990da14cebeSEric Cheng 991da14cebeSEric Cheng typedef struct usage_l_fields_buf_s { 992da14cebeSEric Cheng char usage_l_link[12]; 993da14cebeSEric Cheng char usage_l_stime[13]; 994da14cebeSEric Cheng char usage_l_etime[13]; 995da14cebeSEric Cheng char usage_l_rbytes[8]; 996da14cebeSEric Cheng char usage_l_obytes[8]; 997da14cebeSEric Cheng char usage_l_bandwidth[14]; 998da14cebeSEric Cheng } usage_l_fields_buf_t; 999da14cebeSEric Cheng 1000da14cebeSEric Cheng static print_field_t usage_l_fields[] = { 1001da14cebeSEric Cheng /* name, header, field width, offset, cmdtype */ 1002da14cebeSEric Cheng { "link", "LINK", 12, 1003da14cebeSEric Cheng offsetof(usage_l_fields_buf_t, usage_l_link), CMD_TYPE_ANY}, 1004da14cebeSEric Cheng { "start", "START", 13, 1005da14cebeSEric Cheng offsetof(usage_l_fields_buf_t, usage_l_stime), CMD_TYPE_ANY}, 1006da14cebeSEric Cheng { "end", "END", 13, 1007da14cebeSEric Cheng offsetof(usage_l_fields_buf_t, usage_l_etime), CMD_TYPE_ANY}, 1008da14cebeSEric Cheng { "rbytes", "RBYTES", 8, 1009da14cebeSEric Cheng offsetof(usage_l_fields_buf_t, usage_l_rbytes), CMD_TYPE_ANY}, 1010da14cebeSEric Cheng { "obytes", "OBYTES", 8, 1011da14cebeSEric Cheng offsetof(usage_l_fields_buf_t, usage_l_obytes), CMD_TYPE_ANY}, 1012da14cebeSEric Cheng { "bandwidth", "BANDWIDTH", 14, 1013da14cebeSEric Cheng offsetof(usage_l_fields_buf_t, usage_l_bandwidth), CMD_TYPE_ANY}} 1014da14cebeSEric Cheng ; 1015da14cebeSEric Cheng 1016da14cebeSEric Cheng #define USAGE_L_MAX_FIELDS \ 1017da14cebeSEric Cheng (sizeof (usage_l_fields) /sizeof (print_field_t)) 1018da14cebeSEric Cheng 10197c478bd9Sstevel@tonic-gate static char *progname; 10200ba2cbe9Sxc151355 static sig_atomic_t signalled; 10217c478bd9Sstevel@tonic-gate 10224ac67f02SAnurag S. Maskey /* 10234ac67f02SAnurag S. Maskey * Handle to libdladm. Opened in main() before the sub-command 10244ac67f02SAnurag S. Maskey * specific function is called. 10254ac67f02SAnurag S. Maskey */ 10264ac67f02SAnurag S. Maskey static dladm_handle_t handle = NULL; 10274ac67f02SAnurag S. Maskey 1028da14cebeSEric Cheng #define DLADM_ETHERSTUB_NAME "etherstub" 1029da14cebeSEric Cheng #define DLADM_IS_ETHERSTUB(id) (id == DATALINK_INVALID_LINKID) 1030da14cebeSEric Cheng 10317c478bd9Sstevel@tonic-gate static void 10327c478bd9Sstevel@tonic-gate usage(void) 10337c478bd9Sstevel@tonic-gate { 10348d5c46e6Sam223141 int i; 10358d5c46e6Sam223141 cmd_t *cmdp; 10368d5c46e6Sam223141 (void) fprintf(stderr, gettext("usage: dladm <subcommand> <args> ..." 10378d5c46e6Sam223141 "\n")); 10388d5c46e6Sam223141 for (i = 0; i < sizeof (cmds) / sizeof (cmds[0]); i++) { 10398d5c46e6Sam223141 cmdp = &cmds[i]; 10408d5c46e6Sam223141 if (cmdp->c_usage != NULL) 10418d5c46e6Sam223141 (void) fprintf(stderr, "%s\n", gettext(cmdp->c_usage)); 10428d5c46e6Sam223141 } 10434ac67f02SAnurag S. Maskey 10444ac67f02SAnurag S. Maskey /* close dladm handle if it was opened */ 10454ac67f02SAnurag S. Maskey if (handle != NULL) 10464ac67f02SAnurag S. Maskey dladm_close(handle); 10474ac67f02SAnurag S. Maskey 10487c478bd9Sstevel@tonic-gate exit(1); 10497c478bd9Sstevel@tonic-gate } 10507c478bd9Sstevel@tonic-gate 10517c478bd9Sstevel@tonic-gate int 10527c478bd9Sstevel@tonic-gate main(int argc, char *argv[]) 10537c478bd9Sstevel@tonic-gate { 10547c478bd9Sstevel@tonic-gate int i; 10557c478bd9Sstevel@tonic-gate cmd_t *cmdp; 10564ac67f02SAnurag S. Maskey dladm_status_t status; 10577c478bd9Sstevel@tonic-gate 10587c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, ""); 10597c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN) 10607c478bd9Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST" 10617c478bd9Sstevel@tonic-gate #endif 10627c478bd9Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN); 10637c478bd9Sstevel@tonic-gate 10647c478bd9Sstevel@tonic-gate progname = argv[0]; 10657c478bd9Sstevel@tonic-gate 10667c478bd9Sstevel@tonic-gate if (argc < 2) 10677c478bd9Sstevel@tonic-gate usage(); 10687c478bd9Sstevel@tonic-gate 10697c478bd9Sstevel@tonic-gate for (i = 0; i < sizeof (cmds) / sizeof (cmds[0]); i++) { 10707c478bd9Sstevel@tonic-gate cmdp = &cmds[i]; 10717c478bd9Sstevel@tonic-gate if (strcmp(argv[1], cmdp->c_name) == 0) { 10724ac67f02SAnurag S. Maskey /* Open the libdladm handle */ 10734ac67f02SAnurag S. Maskey if ((status = dladm_open(&handle)) != DLADM_STATUS_OK) { 10744ac67f02SAnurag S. Maskey die_dlerr(status, 10754ac67f02SAnurag S. Maskey "could not open /dev/dld"); 10764ac67f02SAnurag S. Maskey } 10774ac67f02SAnurag S. Maskey 10788d5c46e6Sam223141 cmdp->c_fn(argc - 1, &argv[1], cmdp->c_usage); 10794ac67f02SAnurag S. Maskey 10804ac67f02SAnurag S. Maskey dladm_close(handle); 10817c478bd9Sstevel@tonic-gate exit(0); 10827c478bd9Sstevel@tonic-gate } 10837c478bd9Sstevel@tonic-gate } 10847c478bd9Sstevel@tonic-gate 10857c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("%s: unknown subcommand '%s'\n"), 10867c478bd9Sstevel@tonic-gate progname, argv[1]); 10877c478bd9Sstevel@tonic-gate usage(); 10887c478bd9Sstevel@tonic-gate 10897c478bd9Sstevel@tonic-gate return (0); 10907c478bd9Sstevel@tonic-gate } 10917c478bd9Sstevel@tonic-gate 1092da14cebeSEric Cheng /*ARGSUSED*/ 1093da14cebeSEric Cheng static int 1094da14cebeSEric Cheng show_usage_date(dladm_usage_t *usage, void *arg) 1095da14cebeSEric Cheng { 1096ae6aa22aSVenugopal Iyer show_usage_state_t *state = (show_usage_state_t *)arg; 1097da14cebeSEric Cheng time_t stime; 1098da14cebeSEric Cheng char timebuf[20]; 1099ae6aa22aSVenugopal Iyer dladm_status_t status; 1100ae6aa22aSVenugopal Iyer uint32_t flags; 1101ae6aa22aSVenugopal Iyer 1102ae6aa22aSVenugopal Iyer /* 1103ae6aa22aSVenugopal Iyer * Only show usage information for existing links unless '-a' 1104ae6aa22aSVenugopal Iyer * is specified. 1105ae6aa22aSVenugopal Iyer */ 1106ae6aa22aSVenugopal Iyer if (!state->us_showall) { 1107ae6aa22aSVenugopal Iyer if ((status = dladm_name2info(handle, usage->du_name, 1108ae6aa22aSVenugopal Iyer NULL, &flags, NULL, NULL)) != DLADM_STATUS_OK) { 1109ae6aa22aSVenugopal Iyer return (status); 1110ae6aa22aSVenugopal Iyer } 1111ae6aa22aSVenugopal Iyer if ((flags & DLADM_OPT_ACTIVE) == 0) 1112ae6aa22aSVenugopal Iyer return (DLADM_STATUS_LINKINVAL); 1113ae6aa22aSVenugopal Iyer } 1114da14cebeSEric Cheng 1115da14cebeSEric Cheng stime = usage->du_stime; 1116da14cebeSEric Cheng (void) strftime(timebuf, sizeof (timebuf), "%m/%d/%Y", 1117da14cebeSEric Cheng localtime(&stime)); 1118da14cebeSEric Cheng (void) printf("%s\n", timebuf); 1119da14cebeSEric Cheng 1120da14cebeSEric Cheng return (DLADM_STATUS_OK); 1121da14cebeSEric Cheng } 1122da14cebeSEric Cheng 1123da14cebeSEric Cheng static int 1124da14cebeSEric Cheng show_usage_time(dladm_usage_t *usage, void *arg) 1125da14cebeSEric Cheng { 1126da14cebeSEric Cheng show_usage_state_t *state = (show_usage_state_t *)arg; 1127da14cebeSEric Cheng char buf[DLADM_STRSIZE]; 1128da14cebeSEric Cheng usage_l_fields_buf_t ubuf; 1129da14cebeSEric Cheng time_t time; 1130da14cebeSEric Cheng double bw; 1131ae6aa22aSVenugopal Iyer dladm_status_t status; 1132ae6aa22aSVenugopal Iyer uint32_t flags; 1133ae6aa22aSVenugopal Iyer 1134ae6aa22aSVenugopal Iyer /* 1135ae6aa22aSVenugopal Iyer * Only show usage information for existing links unless '-a' 1136ae6aa22aSVenugopal Iyer * is specified. 1137ae6aa22aSVenugopal Iyer */ 1138ae6aa22aSVenugopal Iyer if (!state->us_showall) { 1139ae6aa22aSVenugopal Iyer if ((status = dladm_name2info(handle, usage->du_name, 1140ae6aa22aSVenugopal Iyer NULL, &flags, NULL, NULL)) != DLADM_STATUS_OK) { 1141ae6aa22aSVenugopal Iyer return (status); 1142ae6aa22aSVenugopal Iyer } 1143ae6aa22aSVenugopal Iyer if ((flags & DLADM_OPT_ACTIVE) == 0) 1144ae6aa22aSVenugopal Iyer return (DLADM_STATUS_LINKINVAL); 1145ae6aa22aSVenugopal Iyer } 1146da14cebeSEric Cheng 1147da14cebeSEric Cheng if (state->us_plot) { 1148da14cebeSEric Cheng if (!state->us_printheader) { 1149da14cebeSEric Cheng if (state->us_first) { 1150da14cebeSEric Cheng (void) printf("# Time"); 1151da14cebeSEric Cheng state->us_first = B_FALSE; 1152da14cebeSEric Cheng } 1153da14cebeSEric Cheng (void) printf(" %s", usage->du_name); 1154da14cebeSEric Cheng if (usage->du_last) { 1155da14cebeSEric Cheng (void) printf("\n"); 1156da14cebeSEric Cheng state->us_first = B_TRUE; 1157da14cebeSEric Cheng state->us_printheader = B_TRUE; 1158da14cebeSEric Cheng } 1159da14cebeSEric Cheng } else { 1160da14cebeSEric Cheng if (state->us_first) { 1161da14cebeSEric Cheng time = usage->du_etime; 1162da14cebeSEric Cheng (void) strftime(buf, sizeof (buf), "%T", 1163da14cebeSEric Cheng localtime(&time)); 1164da14cebeSEric Cheng state->us_first = B_FALSE; 1165da14cebeSEric Cheng (void) printf("%s", buf); 1166da14cebeSEric Cheng } 1167da14cebeSEric Cheng bw = (double)usage->du_bandwidth/1000; 1168da14cebeSEric Cheng (void) printf(" %.2f", bw); 1169da14cebeSEric Cheng if (usage->du_last) { 1170da14cebeSEric Cheng (void) printf("\n"); 1171da14cebeSEric Cheng state->us_first = B_TRUE; 1172da14cebeSEric Cheng } 1173da14cebeSEric Cheng } 1174da14cebeSEric Cheng return (DLADM_STATUS_OK); 1175da14cebeSEric Cheng } 1176da14cebeSEric Cheng 1177da14cebeSEric Cheng bzero(&ubuf, sizeof (ubuf)); 1178da14cebeSEric Cheng 1179da14cebeSEric Cheng (void) snprintf(ubuf.usage_l_link, sizeof (ubuf.usage_l_link), "%s", 1180da14cebeSEric Cheng usage->du_name); 1181da14cebeSEric Cheng time = usage->du_stime; 1182da14cebeSEric Cheng (void) strftime(buf, sizeof (buf), "%T", localtime(&time)); 1183da14cebeSEric Cheng (void) snprintf(ubuf.usage_l_stime, sizeof (ubuf.usage_l_stime), "%s", 1184da14cebeSEric Cheng buf); 1185da14cebeSEric Cheng time = usage->du_etime; 1186da14cebeSEric Cheng (void) strftime(buf, sizeof (buf), "%T", localtime(&time)); 1187da14cebeSEric Cheng (void) snprintf(ubuf.usage_l_etime, sizeof (ubuf.usage_l_etime), "%s", 1188da14cebeSEric Cheng buf); 1189da14cebeSEric Cheng (void) snprintf(ubuf.usage_l_rbytes, sizeof (ubuf.usage_l_rbytes), 1190da14cebeSEric Cheng "%llu", usage->du_rbytes); 1191da14cebeSEric Cheng (void) snprintf(ubuf.usage_l_obytes, sizeof (ubuf.usage_l_obytes), 1192da14cebeSEric Cheng "%llu", usage->du_obytes); 1193da14cebeSEric Cheng (void) snprintf(ubuf.usage_l_bandwidth, sizeof (ubuf.usage_l_bandwidth), 1194da14cebeSEric Cheng "%s Mbps", dladm_bw2str(usage->du_bandwidth, buf)); 1195da14cebeSEric Cheng 1196da14cebeSEric Cheng if (!state->us_parseable && !state->us_printheader) { 1197da14cebeSEric Cheng print_header(&state->us_print); 1198da14cebeSEric Cheng state->us_printheader = B_TRUE; 1199da14cebeSEric Cheng } 1200da14cebeSEric Cheng 1201da14cebeSEric Cheng dladm_print_output(&state->us_print, state->us_parseable, 1202da14cebeSEric Cheng dladm_print_field, (void *)&ubuf); 1203da14cebeSEric Cheng 1204da14cebeSEric Cheng return (DLADM_STATUS_OK); 1205da14cebeSEric Cheng } 1206da14cebeSEric Cheng 1207da14cebeSEric Cheng static int 1208da14cebeSEric Cheng show_usage_res(dladm_usage_t *usage, void *arg) 1209da14cebeSEric Cheng { 1210da14cebeSEric Cheng show_usage_state_t *state = (show_usage_state_t *)arg; 1211da14cebeSEric Cheng char buf[DLADM_STRSIZE]; 1212da14cebeSEric Cheng usage_fields_buf_t ubuf; 1213ae6aa22aSVenugopal Iyer dladm_status_t status; 1214ae6aa22aSVenugopal Iyer uint32_t flags; 1215ae6aa22aSVenugopal Iyer 1216ae6aa22aSVenugopal Iyer /* 1217ae6aa22aSVenugopal Iyer * Only show usage information for existing links unless '-a' 1218ae6aa22aSVenugopal Iyer * is specified. 1219ae6aa22aSVenugopal Iyer */ 1220ae6aa22aSVenugopal Iyer if (!state->us_showall) { 1221ae6aa22aSVenugopal Iyer if ((status = dladm_name2info(handle, usage->du_name, 1222ae6aa22aSVenugopal Iyer NULL, &flags, NULL, NULL)) != DLADM_STATUS_OK) { 1223ae6aa22aSVenugopal Iyer return (status); 1224ae6aa22aSVenugopal Iyer } 1225ae6aa22aSVenugopal Iyer if ((flags & DLADM_OPT_ACTIVE) == 0) 1226ae6aa22aSVenugopal Iyer return (DLADM_STATUS_LINKINVAL); 1227ae6aa22aSVenugopal Iyer } 1228da14cebeSEric Cheng 1229da14cebeSEric Cheng bzero(&ubuf, sizeof (ubuf)); 1230da14cebeSEric Cheng 1231da14cebeSEric Cheng (void) snprintf(ubuf.usage_link, sizeof (ubuf.usage_link), "%s", 1232da14cebeSEric Cheng usage->du_name); 1233da14cebeSEric Cheng (void) snprintf(ubuf.usage_duration, sizeof (ubuf.usage_duration), 1234da14cebeSEric Cheng "%llu", usage->du_duration); 1235da14cebeSEric Cheng (void) snprintf(ubuf.usage_ipackets, sizeof (ubuf.usage_ipackets), 1236da14cebeSEric Cheng "%llu", usage->du_ipackets); 1237da14cebeSEric Cheng (void) snprintf(ubuf.usage_rbytes, sizeof (ubuf.usage_rbytes), 1238da14cebeSEric Cheng "%llu", usage->du_rbytes); 1239da14cebeSEric Cheng (void) snprintf(ubuf.usage_opackets, sizeof (ubuf.usage_opackets), 1240da14cebeSEric Cheng "%llu", usage->du_opackets); 1241da14cebeSEric Cheng (void) snprintf(ubuf.usage_obytes, sizeof (ubuf.usage_obytes), 1242da14cebeSEric Cheng "%llu", usage->du_obytes); 1243da14cebeSEric Cheng (void) snprintf(ubuf.usage_bandwidth, sizeof (ubuf.usage_bandwidth), 1244da14cebeSEric Cheng "%s Mbps", dladm_bw2str(usage->du_bandwidth, buf)); 1245da14cebeSEric Cheng 1246da14cebeSEric Cheng if (!state->us_parseable && !state->us_printheader) { 1247da14cebeSEric Cheng print_header(&state->us_print); 1248da14cebeSEric Cheng state->us_printheader = B_TRUE; 1249da14cebeSEric Cheng } 1250da14cebeSEric Cheng 1251da14cebeSEric Cheng dladm_print_output(&state->us_print, state->us_parseable, 1252da14cebeSEric Cheng dladm_print_field, (void *)&ubuf); 1253da14cebeSEric Cheng 1254da14cebeSEric Cheng return (DLADM_STATUS_OK); 1255da14cebeSEric Cheng } 1256da14cebeSEric Cheng 1257da14cebeSEric Cheng static boolean_t 1258da14cebeSEric Cheng valid_formatspec(char *formatspec_str) 1259da14cebeSEric Cheng { 1260da14cebeSEric Cheng if (strcmp(formatspec_str, "gnuplot") == 0) 1261da14cebeSEric Cheng return (B_TRUE); 1262da14cebeSEric Cheng return (B_FALSE); 1263da14cebeSEric Cheng 1264da14cebeSEric Cheng } 1265da14cebeSEric Cheng 1266da14cebeSEric Cheng /*ARGSUSED*/ 1267da14cebeSEric Cheng static void 1268da14cebeSEric Cheng do_show_usage(int argc, char *argv[], const char *use) 1269da14cebeSEric Cheng { 1270da14cebeSEric Cheng char *file = NULL; 1271da14cebeSEric Cheng int opt; 1272da14cebeSEric Cheng dladm_status_t status; 1273da14cebeSEric Cheng boolean_t d_arg = B_FALSE; 1274da14cebeSEric Cheng char *stime = NULL; 1275da14cebeSEric Cheng char *etime = NULL; 1276da14cebeSEric Cheng char *resource = NULL; 1277da14cebeSEric Cheng show_usage_state_t state; 1278da14cebeSEric Cheng boolean_t o_arg = B_FALSE; 1279da14cebeSEric Cheng boolean_t F_arg = B_FALSE; 1280da14cebeSEric Cheng char *fields_str = NULL; 1281da14cebeSEric Cheng char *formatspec_str = NULL; 1282da14cebeSEric Cheng print_field_t **fields; 1283da14cebeSEric Cheng uint_t nfields; 1284da14cebeSEric Cheng char *all_fields = 1285da14cebeSEric Cheng "link,duration,ipackets,rbytes,opackets,obytes,bandwidth"; 1286da14cebeSEric Cheng char *all_l_fields = 1287da14cebeSEric Cheng "link,start,end,rbytes,obytes,bandwidth"; 1288da14cebeSEric Cheng 1289da14cebeSEric Cheng bzero(&state, sizeof (show_usage_state_t)); 1290da14cebeSEric Cheng state.us_parseable = B_FALSE; 1291da14cebeSEric Cheng state.us_printheader = B_FALSE; 1292da14cebeSEric Cheng state.us_plot = B_FALSE; 1293da14cebeSEric Cheng state.us_first = B_TRUE; 1294da14cebeSEric Cheng 1295ae6aa22aSVenugopal Iyer while ((opt = getopt_long(argc, argv, "das:e:o:f:F:", 1296ae6aa22aSVenugopal Iyer usage_opts, NULL)) != -1) { 1297da14cebeSEric Cheng switch (opt) { 1298da14cebeSEric Cheng case 'd': 1299da14cebeSEric Cheng d_arg = B_TRUE; 1300da14cebeSEric Cheng break; 1301ae6aa22aSVenugopal Iyer case 'a': 1302ae6aa22aSVenugopal Iyer state.us_showall = B_TRUE; 1303da14cebeSEric Cheng break; 1304da14cebeSEric Cheng case 'f': 1305da14cebeSEric Cheng file = optarg; 1306da14cebeSEric Cheng break; 1307da14cebeSEric Cheng case 's': 1308da14cebeSEric Cheng stime = optarg; 1309da14cebeSEric Cheng break; 1310da14cebeSEric Cheng case 'e': 1311da14cebeSEric Cheng etime = optarg; 1312da14cebeSEric Cheng break; 1313da14cebeSEric Cheng case 'o': 1314da14cebeSEric Cheng o_arg = B_TRUE; 1315da14cebeSEric Cheng fields_str = optarg; 1316da14cebeSEric Cheng break; 1317da14cebeSEric Cheng case 'F': 1318ae6aa22aSVenugopal Iyer state.us_plot = F_arg = B_TRUE; 1319da14cebeSEric Cheng formatspec_str = optarg; 1320da14cebeSEric Cheng break; 1321da14cebeSEric Cheng default: 1322da14cebeSEric Cheng die_opterr(optopt, opt, use); 1323da14cebeSEric Cheng break; 1324da14cebeSEric Cheng } 1325da14cebeSEric Cheng } 1326da14cebeSEric Cheng 1327da14cebeSEric Cheng if (file == NULL) 1328da14cebeSEric Cheng die("show-usage requires a file"); 1329da14cebeSEric Cheng 1330da14cebeSEric Cheng if (optind == (argc-1)) { 1331ae6aa22aSVenugopal Iyer uint32_t flags; 1332ae6aa22aSVenugopal Iyer 1333da14cebeSEric Cheng resource = argv[optind]; 1334ae6aa22aSVenugopal Iyer if (!state.us_showall && 1335ae6aa22aSVenugopal Iyer (((status = dladm_name2info(handle, resource, NULL, &flags, 1336ae6aa22aSVenugopal Iyer NULL, NULL)) != DLADM_STATUS_OK) || 1337ae6aa22aSVenugopal Iyer ((flags & DLADM_OPT_ACTIVE) == 0))) { 1338ae6aa22aSVenugopal Iyer die("invalid link: '%s'", resource); 1339ae6aa22aSVenugopal Iyer } 1340da14cebeSEric Cheng } 1341da14cebeSEric Cheng 1342da14cebeSEric Cheng if (resource == NULL && stime == NULL && etime == NULL) { 1343da14cebeSEric Cheng if (!o_arg || (o_arg && strcasecmp(fields_str, "all") == 0)) 1344da14cebeSEric Cheng fields_str = all_fields; 1345da14cebeSEric Cheng fields = parse_output_fields(fields_str, usage_fields, 1346da14cebeSEric Cheng USAGE_MAX_FIELDS, CMD_TYPE_ANY, &nfields); 1347da14cebeSEric Cheng } else { 1348da14cebeSEric Cheng if (!o_arg || (o_arg && strcasecmp(fields_str, "all") == 0)) 1349da14cebeSEric Cheng fields_str = all_l_fields; 1350da14cebeSEric Cheng fields = parse_output_fields(fields_str, usage_l_fields, 1351da14cebeSEric Cheng USAGE_L_MAX_FIELDS, CMD_TYPE_ANY, &nfields); 1352da14cebeSEric Cheng } 1353da14cebeSEric Cheng 1354da14cebeSEric Cheng if (fields == NULL) { 1355da14cebeSEric Cheng die("invalid fields(s) specified"); 1356da14cebeSEric Cheng return; 1357da14cebeSEric Cheng } 1358da14cebeSEric Cheng state.us_print.ps_fields = fields; 1359da14cebeSEric Cheng state.us_print.ps_nfields = nfields; 1360da14cebeSEric Cheng 1361ae6aa22aSVenugopal Iyer if (F_arg && d_arg) 1362ae6aa22aSVenugopal Iyer die("incompatible -d and -F options"); 1363da14cebeSEric Cheng 1364da14cebeSEric Cheng if (F_arg && valid_formatspec(formatspec_str) == B_FALSE) 1365da14cebeSEric Cheng die("Format specifier %s not supported", formatspec_str); 1366da14cebeSEric Cheng 1367da14cebeSEric Cheng if (d_arg) { 1368da14cebeSEric Cheng /* Print log dates */ 1369da14cebeSEric Cheng status = dladm_usage_dates(show_usage_date, 1370da14cebeSEric Cheng DLADM_LOGTYPE_LINK, file, resource, &state); 1371da14cebeSEric Cheng } else if (resource == NULL && stime == NULL && etime == NULL && 1372ae6aa22aSVenugopal Iyer !F_arg) { 1373da14cebeSEric Cheng /* Print summary */ 1374da14cebeSEric Cheng status = dladm_usage_summary(show_usage_res, 1375da14cebeSEric Cheng DLADM_LOGTYPE_LINK, file, &state); 1376da14cebeSEric Cheng } else if (resource != NULL) { 1377da14cebeSEric Cheng /* Print log entries for named resource */ 1378da14cebeSEric Cheng status = dladm_walk_usage_res(show_usage_time, 1379da14cebeSEric Cheng DLADM_LOGTYPE_LINK, file, resource, stime, etime, &state); 1380da14cebeSEric Cheng } else { 1381da14cebeSEric Cheng /* Print time and information for each link */ 1382da14cebeSEric Cheng status = dladm_walk_usage_time(show_usage_time, 1383da14cebeSEric Cheng DLADM_LOGTYPE_LINK, file, stime, etime, &state); 1384da14cebeSEric Cheng } 1385da14cebeSEric Cheng 1386da14cebeSEric Cheng if (status != DLADM_STATUS_OK) 1387da14cebeSEric Cheng die_dlerr(status, "show-usage"); 1388da14cebeSEric Cheng } 1389da14cebeSEric Cheng 13907c478bd9Sstevel@tonic-gate static void 13918d5c46e6Sam223141 do_create_aggr(int argc, char *argv[], const char *use) 13927c478bd9Sstevel@tonic-gate { 13937c478bd9Sstevel@tonic-gate char option; 1394d62bc4baSyz147064 int key = 0; 13957c478bd9Sstevel@tonic-gate uint32_t policy = AGGR_POLICY_L4; 13967c478bd9Sstevel@tonic-gate aggr_lacp_mode_t lacp_mode = AGGR_LACP_OFF; 13977c478bd9Sstevel@tonic-gate aggr_lacp_timer_t lacp_timer = AGGR_LACP_TIMER_SHORT; 1398f595a68aSyz147064 dladm_aggr_port_attr_db_t port[MAXPORT]; 1399d62bc4baSyz147064 uint_t n, ndev, nlink; 14007c478bd9Sstevel@tonic-gate uint8_t mac_addr[ETHERADDRL]; 14017c478bd9Sstevel@tonic-gate boolean_t mac_addr_fixed = B_FALSE; 14027c478bd9Sstevel@tonic-gate boolean_t P_arg = B_FALSE; 14037c478bd9Sstevel@tonic-gate boolean_t l_arg = B_FALSE; 14047c478bd9Sstevel@tonic-gate boolean_t u_arg = B_FALSE; 14057c478bd9Sstevel@tonic-gate boolean_t T_arg = B_FALSE; 1406d62bc4baSyz147064 uint32_t flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST; 14077c478bd9Sstevel@tonic-gate char *altroot = NULL; 1408d62bc4baSyz147064 char name[MAXLINKNAMELEN]; 1409d62bc4baSyz147064 char *devs[MAXPORT]; 1410d62bc4baSyz147064 char *links[MAXPORT]; 1411f595a68aSyz147064 dladm_status_t status; 1412da14cebeSEric Cheng dladm_status_t pstatus; 1413da14cebeSEric Cheng dladm_arg_list_t *proplist = NULL; 1414da14cebeSEric Cheng int i; 1415da14cebeSEric Cheng datalink_id_t linkid; 14167c478bd9Sstevel@tonic-gate 1417d62bc4baSyz147064 ndev = nlink = opterr = 0; 1418da14cebeSEric Cheng while ((option = getopt_long(argc, argv, ":d:l:L:P:R:tfu:T:p:", 1419d62bc4baSyz147064 lopts, NULL)) != -1) { 14207c478bd9Sstevel@tonic-gate switch (option) { 14217c478bd9Sstevel@tonic-gate case 'd': 1422d62bc4baSyz147064 if (ndev + nlink >= MAXPORT) 1423d62bc4baSyz147064 die("too many ports specified"); 14247c478bd9Sstevel@tonic-gate 1425d62bc4baSyz147064 devs[ndev++] = optarg; 14267c478bd9Sstevel@tonic-gate break; 14277c478bd9Sstevel@tonic-gate case 'P': 142833343a97Smeem if (P_arg) 142933343a97Smeem die_optdup(option); 14307c478bd9Sstevel@tonic-gate 14317c478bd9Sstevel@tonic-gate P_arg = B_TRUE; 1432f595a68aSyz147064 if (!dladm_aggr_str2policy(optarg, &policy)) 143333343a97Smeem die("invalid policy '%s'", optarg); 14347c478bd9Sstevel@tonic-gate break; 14357c478bd9Sstevel@tonic-gate case 'u': 143633343a97Smeem if (u_arg) 143733343a97Smeem die_optdup(option); 14387c478bd9Sstevel@tonic-gate 14397c478bd9Sstevel@tonic-gate u_arg = B_TRUE; 1440f595a68aSyz147064 if (!dladm_aggr_str2macaddr(optarg, &mac_addr_fixed, 144133343a97Smeem mac_addr)) 144233343a97Smeem die("invalid MAC address '%s'", optarg); 14437c478bd9Sstevel@tonic-gate break; 14447c478bd9Sstevel@tonic-gate case 'l': 1445d62bc4baSyz147064 if (isdigit(optarg[strlen(optarg) - 1])) { 1446d62bc4baSyz147064 1447d62bc4baSyz147064 /* 1448d62bc4baSyz147064 * Ended with digit, possibly a link name. 1449d62bc4baSyz147064 */ 1450d62bc4baSyz147064 if (ndev + nlink >= MAXPORT) 1451d62bc4baSyz147064 die("too many ports specified"); 1452d62bc4baSyz147064 1453d62bc4baSyz147064 links[nlink++] = optarg; 1454d62bc4baSyz147064 break; 1455d62bc4baSyz147064 } 1456d62bc4baSyz147064 /* FALLTHROUGH */ 1457d62bc4baSyz147064 case 'L': 145833343a97Smeem if (l_arg) 145933343a97Smeem die_optdup(option); 14607c478bd9Sstevel@tonic-gate 14617c478bd9Sstevel@tonic-gate l_arg = B_TRUE; 1462f595a68aSyz147064 if (!dladm_aggr_str2lacpmode(optarg, &lacp_mode)) 146333343a97Smeem die("invalid LACP mode '%s'", optarg); 14647c478bd9Sstevel@tonic-gate break; 14657c478bd9Sstevel@tonic-gate case 'T': 146633343a97Smeem if (T_arg) 146733343a97Smeem die_optdup(option); 14687c478bd9Sstevel@tonic-gate 14697c478bd9Sstevel@tonic-gate T_arg = B_TRUE; 1470f595a68aSyz147064 if (!dladm_aggr_str2lacptimer(optarg, &lacp_timer)) 147133343a97Smeem die("invalid LACP timer value '%s'", optarg); 14727c478bd9Sstevel@tonic-gate break; 14737c478bd9Sstevel@tonic-gate case 't': 1474d62bc4baSyz147064 flags &= ~DLADM_OPT_PERSIST; 1475d62bc4baSyz147064 break; 1476d62bc4baSyz147064 case 'f': 1477d62bc4baSyz147064 flags |= DLADM_OPT_FORCE; 14787c478bd9Sstevel@tonic-gate break; 14797c478bd9Sstevel@tonic-gate case 'R': 14807c478bd9Sstevel@tonic-gate altroot = optarg; 14817c478bd9Sstevel@tonic-gate break; 1482da14cebeSEric Cheng case 'p': 1483da14cebeSEric Cheng if (dladm_parse_link_props(optarg, &proplist, B_FALSE) 1484da14cebeSEric Cheng != DLADM_STATUS_OK) 1485da14cebeSEric Cheng die("invalid aggregation property"); 1486da14cebeSEric Cheng break; 14877c478bd9Sstevel@tonic-gate default: 14888d5c46e6Sam223141 die_opterr(optopt, option, use); 148933343a97Smeem break; 14907c478bd9Sstevel@tonic-gate } 14917c478bd9Sstevel@tonic-gate } 14927c478bd9Sstevel@tonic-gate 1493d62bc4baSyz147064 if (ndev + nlink == 0) 14947c478bd9Sstevel@tonic-gate usage(); 14957c478bd9Sstevel@tonic-gate 1496d62bc4baSyz147064 /* get key value or the aggregation name (required last argument) */ 14977c478bd9Sstevel@tonic-gate if (optind != (argc-1)) 14987c478bd9Sstevel@tonic-gate usage(); 14997c478bd9Sstevel@tonic-gate 1500d62bc4baSyz147064 if (!str2int(argv[optind], &key)) { 1501d62bc4baSyz147064 if (strlcpy(name, argv[optind], MAXLINKNAMELEN) >= 1502d62bc4baSyz147064 MAXLINKNAMELEN) { 1503d62bc4baSyz147064 die("link name too long '%s'", argv[optind]); 1504d62bc4baSyz147064 } 15057c478bd9Sstevel@tonic-gate 1506d62bc4baSyz147064 if (!dladm_valid_linkname(name)) 1507d62bc4baSyz147064 die("invalid link name '%s'", argv[optind]); 1508d62bc4baSyz147064 } else { 1509d62bc4baSyz147064 (void) snprintf(name, MAXLINKNAMELEN, "aggr%d", key); 1510d62bc4baSyz147064 } 1511d62bc4baSyz147064 1512d62bc4baSyz147064 if (altroot != NULL) 1513d62bc4baSyz147064 altroot_cmd(altroot, argc, argv); 1514d62bc4baSyz147064 1515d62bc4baSyz147064 for (n = 0; n < ndev; n++) { 15164ac67f02SAnurag S. Maskey if ((status = dladm_dev2linkid(handle, devs[n], 15174ac67f02SAnurag S. Maskey &port[n].lp_linkid)) != DLADM_STATUS_OK) { 15184ac67f02SAnurag S. Maskey die_dlerr(status, "invalid dev name '%s'", devs[n]); 1519d62bc4baSyz147064 } 1520d62bc4baSyz147064 } 1521d62bc4baSyz147064 1522d62bc4baSyz147064 for (n = 0; n < nlink; n++) { 15234ac67f02SAnurag S. Maskey if ((status = dladm_name2info(handle, links[n], 15244ac67f02SAnurag S. Maskey &port[ndev + n].lp_linkid, NULL, NULL, NULL)) != 15254ac67f02SAnurag S. Maskey DLADM_STATUS_OK) { 15264ac67f02SAnurag S. Maskey die_dlerr(status, "invalid link name '%s'", links[n]); 1527d62bc4baSyz147064 } 1528d62bc4baSyz147064 } 1529d62bc4baSyz147064 15304ac67f02SAnurag S. Maskey status = dladm_aggr_create(handle, name, key, ndev + nlink, port, 15314ac67f02SAnurag S. Maskey policy, mac_addr_fixed, (const uchar_t *)mac_addr, lacp_mode, 1532d62bc4baSyz147064 lacp_timer, flags); 1533da14cebeSEric Cheng if (status != DLADM_STATUS_OK) 1534da14cebeSEric Cheng goto done; 1535da14cebeSEric Cheng 1536da14cebeSEric Cheng if (proplist == NULL) 1537da14cebeSEric Cheng return; 1538da14cebeSEric Cheng 15394ac67f02SAnurag S. Maskey status = dladm_name2info(handle, name, &linkid, NULL, NULL, NULL); 1540da14cebeSEric Cheng if (status != DLADM_STATUS_OK) 1541da14cebeSEric Cheng goto done; 1542da14cebeSEric Cheng 1543da14cebeSEric Cheng for (i = 0; i < proplist->al_count; i++) { 1544da14cebeSEric Cheng dladm_arg_info_t *aip = &proplist->al_info[i]; 1545da14cebeSEric Cheng 15464ac67f02SAnurag S. Maskey pstatus = dladm_set_linkprop(handle, linkid, aip->ai_name, 1547da14cebeSEric Cheng aip->ai_val, aip->ai_count, flags); 1548da14cebeSEric Cheng 1549da14cebeSEric Cheng if (pstatus != DLADM_STATUS_OK) { 1550da14cebeSEric Cheng die_dlerr(pstatus, 1551da14cebeSEric Cheng "aggr creation succeeded but " 1552da14cebeSEric Cheng "could not set property '%s'", aip->ai_name); 1553da14cebeSEric Cheng } 1554da14cebeSEric Cheng } 1555d62bc4baSyz147064 done: 1556da14cebeSEric Cheng dladm_free_props(proplist); 1557d62bc4baSyz147064 if (status != DLADM_STATUS_OK) { 1558d62bc4baSyz147064 if (status == DLADM_STATUS_NONOTIF) { 1559d62bc4baSyz147064 die_dlerr(status, "not all links have link up/down " 1560d62bc4baSyz147064 "detection; must use -f (see dladm(1M))\n"); 1561d62bc4baSyz147064 } else { 1562f595a68aSyz147064 die_dlerr(status, "create operation failed"); 15637c478bd9Sstevel@tonic-gate } 1564d62bc4baSyz147064 } 1565d62bc4baSyz147064 } 1566d62bc4baSyz147064 1567d62bc4baSyz147064 /* 1568d62bc4baSyz147064 * arg is either the key or the aggr name. Validate it and convert it to 1569d62bc4baSyz147064 * the linkid if altroot is NULL. 1570d62bc4baSyz147064 */ 1571d62bc4baSyz147064 static dladm_status_t 1572d62bc4baSyz147064 i_dladm_aggr_get_linkid(const char *altroot, const char *arg, 1573d62bc4baSyz147064 datalink_id_t *linkidp, uint32_t flags) 1574d62bc4baSyz147064 { 1575d62bc4baSyz147064 int key = 0; 1576d62bc4baSyz147064 char *aggr = NULL; 1577d62bc4baSyz147064 dladm_status_t status; 1578d62bc4baSyz147064 1579d62bc4baSyz147064 if (!str2int(arg, &key)) 1580d62bc4baSyz147064 aggr = (char *)arg; 1581d62bc4baSyz147064 1582d62bc4baSyz147064 if (aggr == NULL && key == 0) 1583d62bc4baSyz147064 return (DLADM_STATUS_LINKINVAL); 1584d62bc4baSyz147064 1585d62bc4baSyz147064 if (altroot != NULL) 1586d62bc4baSyz147064 return (DLADM_STATUS_OK); 1587d62bc4baSyz147064 1588d62bc4baSyz147064 if (aggr != NULL) { 15894ac67f02SAnurag S. Maskey status = dladm_name2info(handle, aggr, linkidp, NULL, NULL, 15904ac67f02SAnurag S. Maskey NULL); 1591d62bc4baSyz147064 } else { 15924ac67f02SAnurag S. Maskey status = dladm_key2linkid(handle, key, linkidp, flags); 1593d62bc4baSyz147064 } 1594d62bc4baSyz147064 1595d62bc4baSyz147064 return (status); 1596d62bc4baSyz147064 } 15977c478bd9Sstevel@tonic-gate 15987c478bd9Sstevel@tonic-gate static void 15998d5c46e6Sam223141 do_delete_aggr(int argc, char *argv[], const char *use) 16007c478bd9Sstevel@tonic-gate { 16017c478bd9Sstevel@tonic-gate char option; 16027c478bd9Sstevel@tonic-gate char *altroot = NULL; 1603d62bc4baSyz147064 uint32_t flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST; 1604f595a68aSyz147064 dladm_status_t status; 1605d62bc4baSyz147064 datalink_id_t linkid; 16067c478bd9Sstevel@tonic-gate 16077c478bd9Sstevel@tonic-gate opterr = 0; 1608d62bc4baSyz147064 while ((option = getopt_long(argc, argv, ":R:t", lopts, NULL)) != -1) { 16097c478bd9Sstevel@tonic-gate switch (option) { 16107c478bd9Sstevel@tonic-gate case 't': 1611d62bc4baSyz147064 flags &= ~DLADM_OPT_PERSIST; 16127c478bd9Sstevel@tonic-gate break; 16137c478bd9Sstevel@tonic-gate case 'R': 16147c478bd9Sstevel@tonic-gate altroot = optarg; 16157c478bd9Sstevel@tonic-gate break; 16167c478bd9Sstevel@tonic-gate default: 16178d5c46e6Sam223141 die_opterr(optopt, option, use); 16187c478bd9Sstevel@tonic-gate break; 16197c478bd9Sstevel@tonic-gate } 16207c478bd9Sstevel@tonic-gate } 16217c478bd9Sstevel@tonic-gate 1622d62bc4baSyz147064 /* get key value or the aggregation name (required last argument) */ 16237c478bd9Sstevel@tonic-gate if (optind != (argc-1)) 16247c478bd9Sstevel@tonic-gate usage(); 16257c478bd9Sstevel@tonic-gate 1626d62bc4baSyz147064 status = i_dladm_aggr_get_linkid(altroot, argv[optind], &linkid, flags); 1627d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 1628d62bc4baSyz147064 goto done; 16297c478bd9Sstevel@tonic-gate 1630d62bc4baSyz147064 if (altroot != NULL) 1631d62bc4baSyz147064 altroot_cmd(altroot, argc, argv); 1632d62bc4baSyz147064 16334ac67f02SAnurag S. Maskey status = dladm_aggr_delete(handle, linkid, flags); 1634d62bc4baSyz147064 done: 1635f595a68aSyz147064 if (status != DLADM_STATUS_OK) 1636f595a68aSyz147064 die_dlerr(status, "delete operation failed"); 16377c478bd9Sstevel@tonic-gate } 16387c478bd9Sstevel@tonic-gate 16397c478bd9Sstevel@tonic-gate static void 16408d5c46e6Sam223141 do_add_aggr(int argc, char *argv[], const char *use) 16417c478bd9Sstevel@tonic-gate { 16427c478bd9Sstevel@tonic-gate char option; 1643d62bc4baSyz147064 uint_t n, ndev, nlink; 16447c478bd9Sstevel@tonic-gate char *altroot = NULL; 1645d62bc4baSyz147064 uint32_t flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST; 1646d62bc4baSyz147064 datalink_id_t linkid; 1647f595a68aSyz147064 dladm_status_t status; 1648d62bc4baSyz147064 dladm_aggr_port_attr_db_t port[MAXPORT]; 1649d62bc4baSyz147064 char *devs[MAXPORT]; 1650d62bc4baSyz147064 char *links[MAXPORT]; 16517c478bd9Sstevel@tonic-gate 1652d62bc4baSyz147064 ndev = nlink = opterr = 0; 1653d62bc4baSyz147064 while ((option = getopt_long(argc, argv, ":d:l:R:tf", lopts, 16547c478bd9Sstevel@tonic-gate NULL)) != -1) { 16557c478bd9Sstevel@tonic-gate switch (option) { 16567c478bd9Sstevel@tonic-gate case 'd': 1657d62bc4baSyz147064 if (ndev + nlink >= MAXPORT) 1658d62bc4baSyz147064 die("too many ports specified"); 16597c478bd9Sstevel@tonic-gate 1660d62bc4baSyz147064 devs[ndev++] = optarg; 1661d62bc4baSyz147064 break; 1662d62bc4baSyz147064 case 'l': 1663d62bc4baSyz147064 if (ndev + nlink >= MAXPORT) 1664d62bc4baSyz147064 die("too many ports specified"); 166533343a97Smeem 1666d62bc4baSyz147064 links[nlink++] = optarg; 16677c478bd9Sstevel@tonic-gate break; 16687c478bd9Sstevel@tonic-gate case 't': 1669d62bc4baSyz147064 flags &= ~DLADM_OPT_PERSIST; 1670d62bc4baSyz147064 break; 1671d62bc4baSyz147064 case 'f': 1672d62bc4baSyz147064 flags |= DLADM_OPT_FORCE; 16737c478bd9Sstevel@tonic-gate break; 16747c478bd9Sstevel@tonic-gate case 'R': 16757c478bd9Sstevel@tonic-gate altroot = optarg; 16767c478bd9Sstevel@tonic-gate break; 16777c478bd9Sstevel@tonic-gate default: 16788d5c46e6Sam223141 die_opterr(optopt, option, use); 167933343a97Smeem break; 16807c478bd9Sstevel@tonic-gate } 16817c478bd9Sstevel@tonic-gate } 16827c478bd9Sstevel@tonic-gate 1683d62bc4baSyz147064 if (ndev + nlink == 0) 16847c478bd9Sstevel@tonic-gate usage(); 16857c478bd9Sstevel@tonic-gate 1686d62bc4baSyz147064 /* get key value or the aggregation name (required last argument) */ 16877c478bd9Sstevel@tonic-gate if (optind != (argc-1)) 16887c478bd9Sstevel@tonic-gate usage(); 16897c478bd9Sstevel@tonic-gate 1690d62bc4baSyz147064 if ((status = i_dladm_aggr_get_linkid(altroot, argv[optind], &linkid, 1691d62bc4baSyz147064 flags & (DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST))) != 1692d62bc4baSyz147064 DLADM_STATUS_OK) { 1693d62bc4baSyz147064 goto done; 1694d62bc4baSyz147064 } 16957c478bd9Sstevel@tonic-gate 1696d62bc4baSyz147064 if (altroot != NULL) 1697d62bc4baSyz147064 altroot_cmd(altroot, argc, argv); 1698d62bc4baSyz147064 1699d62bc4baSyz147064 for (n = 0; n < ndev; n++) { 17004ac67f02SAnurag S. Maskey if ((status = dladm_dev2linkid(handle, devs[n], 17014ac67f02SAnurag S. Maskey &(port[n].lp_linkid))) != DLADM_STATUS_OK) { 17024ac67f02SAnurag S. Maskey die_dlerr(status, "invalid <dev> '%s'", devs[n]); 1703d62bc4baSyz147064 } 1704d62bc4baSyz147064 } 1705d62bc4baSyz147064 1706d62bc4baSyz147064 for (n = 0; n < nlink; n++) { 17074ac67f02SAnurag S. Maskey if ((status = dladm_name2info(handle, links[n], 17084ac67f02SAnurag S. Maskey &port[n + ndev].lp_linkid, NULL, NULL, NULL)) != 17094ac67f02SAnurag S. Maskey DLADM_STATUS_OK) { 17104ac67f02SAnurag S. Maskey die_dlerr(status, "invalid <link> '%s'", links[n]); 1711d62bc4baSyz147064 } 1712d62bc4baSyz147064 } 1713d62bc4baSyz147064 17144ac67f02SAnurag S. Maskey status = dladm_aggr_add(handle, linkid, ndev + nlink, port, flags); 1715d62bc4baSyz147064 done: 1716f595a68aSyz147064 if (status != DLADM_STATUS_OK) { 1717219a2a31Shl157128 /* 1718f595a68aSyz147064 * checking DLADM_STATUS_NOTSUP is a temporary workaround 1719219a2a31Shl157128 * and should be removed once 6399681 is fixed. 1720219a2a31Shl157128 */ 1721f595a68aSyz147064 if (status == DLADM_STATUS_NOTSUP) { 1722219a2a31Shl157128 (void) fprintf(stderr, 1723219a2a31Shl157128 gettext("%s: add operation failed: %s\n"), 1724219a2a31Shl157128 progname, 1725d62bc4baSyz147064 gettext("link capabilities don't match")); 17264ac67f02SAnurag S. Maskey dladm_close(handle); 1727219a2a31Shl157128 exit(ENOTSUP); 1728d62bc4baSyz147064 } else if (status == DLADM_STATUS_NONOTIF) { 1729d62bc4baSyz147064 die_dlerr(status, "not all links have link up/down " 1730d62bc4baSyz147064 "detection; must use -f (see dladm(1M))\n"); 1731d62bc4baSyz147064 } else { 1732f595a68aSyz147064 die_dlerr(status, "add operation failed"); 17337c478bd9Sstevel@tonic-gate } 17347c478bd9Sstevel@tonic-gate } 1735d62bc4baSyz147064 } 17367c478bd9Sstevel@tonic-gate 17377c478bd9Sstevel@tonic-gate static void 17388d5c46e6Sam223141 do_remove_aggr(int argc, char *argv[], const char *use) 17397c478bd9Sstevel@tonic-gate { 17407c478bd9Sstevel@tonic-gate char option; 1741f595a68aSyz147064 dladm_aggr_port_attr_db_t port[MAXPORT]; 1742d62bc4baSyz147064 uint_t n, ndev, nlink; 1743d62bc4baSyz147064 char *devs[MAXPORT]; 1744d62bc4baSyz147064 char *links[MAXPORT]; 17457c478bd9Sstevel@tonic-gate char *altroot = NULL; 1746d62bc4baSyz147064 uint32_t flags; 1747d62bc4baSyz147064 datalink_id_t linkid; 1748f595a68aSyz147064 dladm_status_t status; 17497c478bd9Sstevel@tonic-gate 1750d62bc4baSyz147064 flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST; 1751d62bc4baSyz147064 ndev = nlink = opterr = 0; 1752d62bc4baSyz147064 while ((option = getopt_long(argc, argv, ":d:l:R:t", 1753d62bc4baSyz147064 lopts, NULL)) != -1) { 17547c478bd9Sstevel@tonic-gate switch (option) { 17557c478bd9Sstevel@tonic-gate case 'd': 1756d62bc4baSyz147064 if (ndev + nlink >= MAXPORT) 1757d62bc4baSyz147064 die("too many ports specified"); 17587c478bd9Sstevel@tonic-gate 1759d62bc4baSyz147064 devs[ndev++] = optarg; 1760d62bc4baSyz147064 break; 1761d62bc4baSyz147064 case 'l': 1762d62bc4baSyz147064 if (ndev + nlink >= MAXPORT) 1763d62bc4baSyz147064 die("too many ports specified"); 176433343a97Smeem 1765d62bc4baSyz147064 links[nlink++] = optarg; 17667c478bd9Sstevel@tonic-gate break; 17677c478bd9Sstevel@tonic-gate case 't': 1768d62bc4baSyz147064 flags &= ~DLADM_OPT_PERSIST; 17697c478bd9Sstevel@tonic-gate break; 17707c478bd9Sstevel@tonic-gate case 'R': 17717c478bd9Sstevel@tonic-gate altroot = optarg; 17727c478bd9Sstevel@tonic-gate break; 17737c478bd9Sstevel@tonic-gate default: 17748d5c46e6Sam223141 die_opterr(optopt, option, use); 177533343a97Smeem break; 17767c478bd9Sstevel@tonic-gate } 17777c478bd9Sstevel@tonic-gate } 17787c478bd9Sstevel@tonic-gate 1779d62bc4baSyz147064 if (ndev + nlink == 0) 17807c478bd9Sstevel@tonic-gate usage(); 17817c478bd9Sstevel@tonic-gate 1782d62bc4baSyz147064 /* get key value or the aggregation name (required last argument) */ 17837c478bd9Sstevel@tonic-gate if (optind != (argc-1)) 17847c478bd9Sstevel@tonic-gate usage(); 17857c478bd9Sstevel@tonic-gate 1786d62bc4baSyz147064 status = i_dladm_aggr_get_linkid(altroot, argv[optind], &linkid, flags); 1787d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 1788d62bc4baSyz147064 goto done; 17897c478bd9Sstevel@tonic-gate 1790d62bc4baSyz147064 if (altroot != NULL) 1791d62bc4baSyz147064 altroot_cmd(altroot, argc, argv); 1792d62bc4baSyz147064 1793d62bc4baSyz147064 for (n = 0; n < ndev; n++) { 17944ac67f02SAnurag S. Maskey if ((status = dladm_dev2linkid(handle, devs[n], 17954ac67f02SAnurag S. Maskey &(port[n].lp_linkid))) != DLADM_STATUS_OK) { 17964ac67f02SAnurag S. Maskey die_dlerr(status, "invalid <dev> '%s'", devs[n]); 1797d62bc4baSyz147064 } 1798d62bc4baSyz147064 } 1799d62bc4baSyz147064 1800d62bc4baSyz147064 for (n = 0; n < nlink; n++) { 18014ac67f02SAnurag S. Maskey if ((status = dladm_name2info(handle, links[n], 18024ac67f02SAnurag S. Maskey &port[n + ndev].lp_linkid, NULL, NULL, NULL)) != 18034ac67f02SAnurag S. Maskey DLADM_STATUS_OK) { 18044ac67f02SAnurag S. Maskey die_dlerr(status, "invalid <link> '%s'", links[n]); 1805d62bc4baSyz147064 } 1806d62bc4baSyz147064 } 1807d62bc4baSyz147064 18084ac67f02SAnurag S. Maskey status = dladm_aggr_remove(handle, linkid, ndev + nlink, port, flags); 1809d62bc4baSyz147064 done: 1810f595a68aSyz147064 if (status != DLADM_STATUS_OK) 1811f595a68aSyz147064 die_dlerr(status, "remove operation failed"); 18127c478bd9Sstevel@tonic-gate } 18137c478bd9Sstevel@tonic-gate 18147c478bd9Sstevel@tonic-gate static void 18158d5c46e6Sam223141 do_modify_aggr(int argc, char *argv[], const char *use) 18167c478bd9Sstevel@tonic-gate { 18177c478bd9Sstevel@tonic-gate char option; 18187c478bd9Sstevel@tonic-gate uint32_t policy = AGGR_POLICY_L4; 18197c478bd9Sstevel@tonic-gate aggr_lacp_mode_t lacp_mode = AGGR_LACP_OFF; 18207c478bd9Sstevel@tonic-gate aggr_lacp_timer_t lacp_timer = AGGR_LACP_TIMER_SHORT; 18217c478bd9Sstevel@tonic-gate uint8_t mac_addr[ETHERADDRL]; 18227c478bd9Sstevel@tonic-gate boolean_t mac_addr_fixed = B_FALSE; 18237c478bd9Sstevel@tonic-gate uint8_t modify_mask = 0; 18247c478bd9Sstevel@tonic-gate char *altroot = NULL; 1825d62bc4baSyz147064 uint32_t flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST; 1826d62bc4baSyz147064 datalink_id_t linkid; 1827f595a68aSyz147064 dladm_status_t status; 18287c478bd9Sstevel@tonic-gate 18297c478bd9Sstevel@tonic-gate opterr = 0; 1830d62bc4baSyz147064 while ((option = getopt_long(argc, argv, ":L:l:P:R:tu:T:", lopts, 18317c478bd9Sstevel@tonic-gate NULL)) != -1) { 18327c478bd9Sstevel@tonic-gate switch (option) { 18337c478bd9Sstevel@tonic-gate case 'P': 1834f595a68aSyz147064 if (modify_mask & DLADM_AGGR_MODIFY_POLICY) 183533343a97Smeem die_optdup(option); 18367c478bd9Sstevel@tonic-gate 1837f595a68aSyz147064 modify_mask |= DLADM_AGGR_MODIFY_POLICY; 18387c478bd9Sstevel@tonic-gate 1839f595a68aSyz147064 if (!dladm_aggr_str2policy(optarg, &policy)) 184033343a97Smeem die("invalid policy '%s'", optarg); 18417c478bd9Sstevel@tonic-gate break; 18427c478bd9Sstevel@tonic-gate case 'u': 1843f595a68aSyz147064 if (modify_mask & DLADM_AGGR_MODIFY_MAC) 184433343a97Smeem die_optdup(option); 18457c478bd9Sstevel@tonic-gate 1846f595a68aSyz147064 modify_mask |= DLADM_AGGR_MODIFY_MAC; 18477c478bd9Sstevel@tonic-gate 1848f595a68aSyz147064 if (!dladm_aggr_str2macaddr(optarg, &mac_addr_fixed, 184933343a97Smeem mac_addr)) 185033343a97Smeem die("invalid MAC address '%s'", optarg); 18517c478bd9Sstevel@tonic-gate break; 18527c478bd9Sstevel@tonic-gate case 'l': 1853d62bc4baSyz147064 case 'L': 1854f595a68aSyz147064 if (modify_mask & DLADM_AGGR_MODIFY_LACP_MODE) 185533343a97Smeem die_optdup(option); 18567c478bd9Sstevel@tonic-gate 1857f595a68aSyz147064 modify_mask |= DLADM_AGGR_MODIFY_LACP_MODE; 18587c478bd9Sstevel@tonic-gate 1859f595a68aSyz147064 if (!dladm_aggr_str2lacpmode(optarg, &lacp_mode)) 186033343a97Smeem die("invalid LACP mode '%s'", optarg); 18617c478bd9Sstevel@tonic-gate break; 18627c478bd9Sstevel@tonic-gate case 'T': 1863f595a68aSyz147064 if (modify_mask & DLADM_AGGR_MODIFY_LACP_TIMER) 186433343a97Smeem die_optdup(option); 18657c478bd9Sstevel@tonic-gate 1866f595a68aSyz147064 modify_mask |= DLADM_AGGR_MODIFY_LACP_TIMER; 18677c478bd9Sstevel@tonic-gate 1868f595a68aSyz147064 if (!dladm_aggr_str2lacptimer(optarg, &lacp_timer)) 186933343a97Smeem die("invalid LACP timer value '%s'", optarg); 18707c478bd9Sstevel@tonic-gate break; 18717c478bd9Sstevel@tonic-gate case 't': 1872d62bc4baSyz147064 flags &= ~DLADM_OPT_PERSIST; 18737c478bd9Sstevel@tonic-gate break; 18747c478bd9Sstevel@tonic-gate case 'R': 18757c478bd9Sstevel@tonic-gate altroot = optarg; 18767c478bd9Sstevel@tonic-gate break; 18777c478bd9Sstevel@tonic-gate default: 18788d5c46e6Sam223141 die_opterr(optopt, option, use); 187933343a97Smeem break; 18807c478bd9Sstevel@tonic-gate } 18817c478bd9Sstevel@tonic-gate } 18827c478bd9Sstevel@tonic-gate 188333343a97Smeem if (modify_mask == 0) 188433343a97Smeem die("at least one of the -PulT options must be specified"); 18857c478bd9Sstevel@tonic-gate 1886d62bc4baSyz147064 /* get key value or the aggregation name (required last argument) */ 18877c478bd9Sstevel@tonic-gate if (optind != (argc-1)) 18887c478bd9Sstevel@tonic-gate usage(); 18897c478bd9Sstevel@tonic-gate 1890d62bc4baSyz147064 status = i_dladm_aggr_get_linkid(altroot, argv[optind], &linkid, flags); 1891d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 1892d62bc4baSyz147064 goto done; 18937c478bd9Sstevel@tonic-gate 1894d62bc4baSyz147064 if (altroot != NULL) 1895d62bc4baSyz147064 altroot_cmd(altroot, argc, argv); 1896d62bc4baSyz147064 18974ac67f02SAnurag S. Maskey status = dladm_aggr_modify(handle, linkid, modify_mask, policy, 18984ac67f02SAnurag S. Maskey mac_addr_fixed, (const uchar_t *)mac_addr, lacp_mode, lacp_timer, 18994ac67f02SAnurag S. Maskey flags); 1900d62bc4baSyz147064 1901d62bc4baSyz147064 done: 1902f595a68aSyz147064 if (status != DLADM_STATUS_OK) 1903f595a68aSyz147064 die_dlerr(status, "modify operation failed"); 19047c478bd9Sstevel@tonic-gate } 19057c478bd9Sstevel@tonic-gate 19068d5c46e6Sam223141 /*ARGSUSED*/ 19077c478bd9Sstevel@tonic-gate static void 19088d5c46e6Sam223141 do_up_aggr(int argc, char *argv[], const char *use) 19097c478bd9Sstevel@tonic-gate { 1910d62bc4baSyz147064 datalink_id_t linkid = DATALINK_ALL_LINKID; 1911f595a68aSyz147064 dladm_status_t status; 19127c478bd9Sstevel@tonic-gate 1913d62bc4baSyz147064 /* 1914d62bc4baSyz147064 * get the key or the name of the aggregation (optional last argument) 1915d62bc4baSyz147064 */ 19167c478bd9Sstevel@tonic-gate if (argc == 2) { 1917d62bc4baSyz147064 if ((status = i_dladm_aggr_get_linkid(NULL, argv[1], &linkid, 19184ac67f02SAnurag S. Maskey DLADM_OPT_PERSIST)) != DLADM_STATUS_OK) 1919d62bc4baSyz147064 goto done; 19207c478bd9Sstevel@tonic-gate } else if (argc > 2) { 19217c478bd9Sstevel@tonic-gate usage(); 19227c478bd9Sstevel@tonic-gate } 19237c478bd9Sstevel@tonic-gate 19244ac67f02SAnurag S. Maskey status = dladm_aggr_up(handle, linkid); 1925d62bc4baSyz147064 done: 1926d62bc4baSyz147064 if (status != DLADM_STATUS_OK) { 1927d62bc4baSyz147064 if (argc == 2) { 1928d62bc4baSyz147064 die_dlerr(status, 1929d62bc4baSyz147064 "could not bring up aggregation '%s'", argv[1]); 19307c478bd9Sstevel@tonic-gate } else { 1931f595a68aSyz147064 die_dlerr(status, "could not bring aggregations up"); 19327c478bd9Sstevel@tonic-gate } 19337c478bd9Sstevel@tonic-gate } 19347c478bd9Sstevel@tonic-gate } 19357c478bd9Sstevel@tonic-gate 19367c478bd9Sstevel@tonic-gate static void 19378d5c46e6Sam223141 do_create_vlan(int argc, char *argv[], const char *use) 19387c478bd9Sstevel@tonic-gate { 1939d62bc4baSyz147064 char *link = NULL; 1940d62bc4baSyz147064 char drv[DLPI_LINKNAME_MAX]; 1941d62bc4baSyz147064 uint_t ppa; 1942d62bc4baSyz147064 datalink_id_t linkid; 1943da14cebeSEric Cheng datalink_id_t dev_linkid; 1944d62bc4baSyz147064 int vid = 0; 1945d62bc4baSyz147064 char option; 1946d62bc4baSyz147064 uint32_t flags = (DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST); 1947d62bc4baSyz147064 char *altroot = NULL; 1948d62bc4baSyz147064 char vlan[MAXLINKNAMELEN]; 1949da14cebeSEric Cheng dladm_arg_list_t *proplist = NULL; 1950f595a68aSyz147064 dladm_status_t status; 19517c478bd9Sstevel@tonic-gate 1952d62bc4baSyz147064 opterr = 0; 1953da14cebeSEric Cheng while ((option = getopt_long(argc, argv, ":tfR:l:v:p:", 1954d62bc4baSyz147064 lopts, NULL)) != -1) { 1955d62bc4baSyz147064 switch (option) { 1956d62bc4baSyz147064 case 'v': 1957d62bc4baSyz147064 if (vid != 0) 1958d62bc4baSyz147064 die_optdup(option); 1959d62bc4baSyz147064 1960d62bc4baSyz147064 if (!str2int(optarg, &vid) || vid < 1 || vid > 4094) 1961d62bc4baSyz147064 die("invalid VLAN identifier '%s'", optarg); 1962d62bc4baSyz147064 1963d62bc4baSyz147064 break; 1964d62bc4baSyz147064 case 'l': 1965d62bc4baSyz147064 if (link != NULL) 1966d62bc4baSyz147064 die_optdup(option); 1967d62bc4baSyz147064 1968d62bc4baSyz147064 link = optarg; 1969d62bc4baSyz147064 break; 1970d62bc4baSyz147064 case 't': 1971d62bc4baSyz147064 flags &= ~DLADM_OPT_PERSIST; 1972d62bc4baSyz147064 break; 1973d62bc4baSyz147064 case 'R': 1974d62bc4baSyz147064 altroot = optarg; 1975d62bc4baSyz147064 break; 1976da14cebeSEric Cheng case 'p': 1977da14cebeSEric Cheng if (dladm_parse_link_props(optarg, &proplist, B_FALSE) 1978da14cebeSEric Cheng != DLADM_STATUS_OK) { 1979da14cebeSEric Cheng die("invalid vlan property"); 1980da14cebeSEric Cheng } 1981da14cebeSEric Cheng break; 1982da14cebeSEric Cheng case 'f': 1983da14cebeSEric Cheng flags |= DLADM_OPT_FORCE; 1984da14cebeSEric Cheng break; 1985d62bc4baSyz147064 default: 19868d5c46e6Sam223141 die_opterr(optopt, option, use); 1987d62bc4baSyz147064 break; 1988d62bc4baSyz147064 } 1989d62bc4baSyz147064 } 1990d62bc4baSyz147064 1991d62bc4baSyz147064 /* get vlan name if there is any */ 1992d62bc4baSyz147064 if ((vid == 0) || (link == NULL) || (argc - optind > 1)) 19937c478bd9Sstevel@tonic-gate usage(); 1994d62bc4baSyz147064 1995d62bc4baSyz147064 if (optind == (argc - 1)) { 1996d62bc4baSyz147064 if (strlcpy(vlan, argv[optind], MAXLINKNAMELEN) >= 1997d62bc4baSyz147064 MAXLINKNAMELEN) { 1998d62bc4baSyz147064 die("vlan name too long '%s'", argv[optind]); 1999d62bc4baSyz147064 } 2000d62bc4baSyz147064 } else { 2001d62bc4baSyz147064 if ((dlpi_parselink(link, drv, &ppa) != DLPI_SUCCESS) || 2002d62bc4baSyz147064 (ppa >= 1000) || 2003d62bc4baSyz147064 (dlpi_makelink(vlan, drv, vid * 1000 + ppa) != 2004d62bc4baSyz147064 DLPI_SUCCESS)) { 2005d62bc4baSyz147064 die("invalid link name '%s'", link); 2006d62bc4baSyz147064 } 20077c478bd9Sstevel@tonic-gate } 20087c478bd9Sstevel@tonic-gate 2009d62bc4baSyz147064 if (altroot != NULL) 2010d62bc4baSyz147064 altroot_cmd(altroot, argc, argv); 2011d62bc4baSyz147064 20124ac67f02SAnurag S. Maskey if (dladm_name2info(handle, link, &dev_linkid, NULL, NULL, NULL) != 2013d62bc4baSyz147064 DLADM_STATUS_OK) { 2014d62bc4baSyz147064 die("invalid link name '%s'", link); 2015d62bc4baSyz147064 } 2016d62bc4baSyz147064 20174ac67f02SAnurag S. Maskey if ((status = dladm_vlan_create(handle, vlan, dev_linkid, vid, proplist, 20184ac67f02SAnurag S. Maskey flags, &linkid)) != DLADM_STATUS_OK) { 2019da14cebeSEric Cheng die_dlerr(status, "create operation over %s failed", link); 2020d62bc4baSyz147064 } 2021d62bc4baSyz147064 } 2022d62bc4baSyz147064 2023d62bc4baSyz147064 static void 20248d5c46e6Sam223141 do_delete_vlan(int argc, char *argv[], const char *use) 2025d62bc4baSyz147064 { 2026d62bc4baSyz147064 char option; 2027d62bc4baSyz147064 uint32_t flags = (DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST); 2028d62bc4baSyz147064 char *altroot = NULL; 2029d62bc4baSyz147064 datalink_id_t linkid; 2030d62bc4baSyz147064 dladm_status_t status; 2031d62bc4baSyz147064 2032d62bc4baSyz147064 opterr = 0; 2033d62bc4baSyz147064 while ((option = getopt_long(argc, argv, ":R:t", lopts, NULL)) != -1) { 2034d62bc4baSyz147064 switch (option) { 2035d62bc4baSyz147064 case 't': 2036d62bc4baSyz147064 flags &= ~DLADM_OPT_PERSIST; 2037d62bc4baSyz147064 break; 2038d62bc4baSyz147064 case 'R': 2039d62bc4baSyz147064 altroot = optarg; 2040d62bc4baSyz147064 break; 2041d62bc4baSyz147064 default: 20428d5c46e6Sam223141 die_opterr(optopt, option, use); 2043d62bc4baSyz147064 break; 2044d62bc4baSyz147064 } 2045d62bc4baSyz147064 } 2046d62bc4baSyz147064 2047d62bc4baSyz147064 /* get VLAN link name (required last argument) */ 2048d62bc4baSyz147064 if (optind != (argc - 1)) 2049d62bc4baSyz147064 usage(); 2050d62bc4baSyz147064 2051d62bc4baSyz147064 if (altroot != NULL) 2052d62bc4baSyz147064 altroot_cmd(altroot, argc, argv); 2053d62bc4baSyz147064 20544ac67f02SAnurag S. Maskey status = dladm_name2info(handle, argv[optind], &linkid, NULL, NULL, 20554ac67f02SAnurag S. Maskey NULL); 2056d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 2057d62bc4baSyz147064 goto done; 2058d62bc4baSyz147064 20594ac67f02SAnurag S. Maskey status = dladm_vlan_delete(handle, linkid, flags); 2060d62bc4baSyz147064 done: 2061d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 2062d62bc4baSyz147064 die_dlerr(status, "delete operation failed"); 2063d62bc4baSyz147064 } 2064d62bc4baSyz147064 20658d5c46e6Sam223141 /*ARGSUSED*/ 2066d62bc4baSyz147064 static void 20678d5c46e6Sam223141 do_up_vlan(int argc, char *argv[], const char *use) 2068d62bc4baSyz147064 { 2069da14cebeSEric Cheng do_up_vnic_common(argc, argv, use, B_TRUE); 20707c478bd9Sstevel@tonic-gate } 20717c478bd9Sstevel@tonic-gate 2072210db224Sericheng static void 20738d5c46e6Sam223141 do_rename_link(int argc, char *argv[], const char *use) 2074210db224Sericheng { 2075d62bc4baSyz147064 char option; 2076d62bc4baSyz147064 char *link1, *link2; 2077d62bc4baSyz147064 char *altroot = NULL; 2078d62bc4baSyz147064 dladm_status_t status; 2079210db224Sericheng 2080d62bc4baSyz147064 opterr = 0; 2081d62bc4baSyz147064 while ((option = getopt_long(argc, argv, ":R:", lopts, NULL)) != -1) { 2082d62bc4baSyz147064 switch (option) { 2083d62bc4baSyz147064 case 'R': 2084d62bc4baSyz147064 altroot = optarg; 2085d62bc4baSyz147064 break; 2086d62bc4baSyz147064 default: 20878d5c46e6Sam223141 die_opterr(optopt, option, use); 2088d62bc4baSyz147064 break; 2089210db224Sericheng } 2090210db224Sericheng } 2091210db224Sericheng 2092d62bc4baSyz147064 /* get link1 and link2 name (required the last 2 arguments) */ 2093d62bc4baSyz147064 if (optind != (argc - 2)) 2094d62bc4baSyz147064 usage(); 2095d62bc4baSyz147064 2096d62bc4baSyz147064 if (altroot != NULL) 2097d62bc4baSyz147064 altroot_cmd(altroot, argc, argv); 2098d62bc4baSyz147064 2099d62bc4baSyz147064 link1 = argv[optind++]; 2100d62bc4baSyz147064 link2 = argv[optind]; 21014ac67f02SAnurag S. Maskey if ((status = dladm_rename_link(handle, link1, link2)) != 21024ac67f02SAnurag S. Maskey DLADM_STATUS_OK) 2103d62bc4baSyz147064 die_dlerr(status, "rename operation failed"); 2104d62bc4baSyz147064 } 2105d62bc4baSyz147064 21068d5c46e6Sam223141 /*ARGSUSED*/ 2107d62bc4baSyz147064 static void 21088d5c46e6Sam223141 do_delete_phys(int argc, char *argv[], const char *use) 2109d62bc4baSyz147064 { 2110d62bc4baSyz147064 datalink_id_t linkid = DATALINK_ALL_LINKID; 2111d62bc4baSyz147064 dladm_status_t status; 2112d62bc4baSyz147064 2113d62bc4baSyz147064 /* get link name (required the last argument) */ 2114d62bc4baSyz147064 if (argc > 2) 2115d62bc4baSyz147064 usage(); 2116d62bc4baSyz147064 2117d62bc4baSyz147064 if (argc == 2) { 21184ac67f02SAnurag S. Maskey if ((status = dladm_name2info(handle, argv[1], &linkid, NULL, 21194ac67f02SAnurag S. Maskey NULL, NULL)) != DLADM_STATUS_OK) 2120d62bc4baSyz147064 die_dlerr(status, "cannot delete '%s'", argv[1]); 2121d62bc4baSyz147064 } 2122d62bc4baSyz147064 21234ac67f02SAnurag S. Maskey if ((status = dladm_phys_delete(handle, linkid)) != DLADM_STATUS_OK) { 2124d62bc4baSyz147064 if (argc == 2) 2125d62bc4baSyz147064 die_dlerr(status, "cannot delete '%s'", argv[1]); 2126d62bc4baSyz147064 else 2127d62bc4baSyz147064 die_dlerr(status, "delete operation failed"); 2128d62bc4baSyz147064 } 2129d62bc4baSyz147064 } 2130d62bc4baSyz147064 2131d62bc4baSyz147064 /*ARGSUSED*/ 2132210db224Sericheng static int 21334ac67f02SAnurag S. Maskey i_dladm_walk_linkmap(dladm_handle_t dh, datalink_id_t linkid, void *arg) 2134210db224Sericheng { 2135d62bc4baSyz147064 char name[MAXLINKNAMELEN]; 2136d62bc4baSyz147064 char mediabuf[DLADM_STRSIZE]; 2137d62bc4baSyz147064 char classbuf[DLADM_STRSIZE]; 2138d62bc4baSyz147064 datalink_class_t class; 2139d62bc4baSyz147064 uint32_t media; 2140d62bc4baSyz147064 uint32_t flags; 2141210db224Sericheng 21424ac67f02SAnurag S. Maskey if (dladm_datalink_id2info(dh, linkid, &flags, &class, &media, name, 2143d62bc4baSyz147064 MAXLINKNAMELEN) == DLADM_STATUS_OK) { 2144d62bc4baSyz147064 (void) dladm_class2str(class, classbuf); 2145d62bc4baSyz147064 (void) dladm_media2str(media, mediabuf); 2146d62bc4baSyz147064 (void) printf("%-12s%8d %-12s%-20s %6d\n", name, 2147d62bc4baSyz147064 linkid, classbuf, mediabuf, flags); 2148210db224Sericheng } 2149d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 2150210db224Sericheng } 21517c478bd9Sstevel@tonic-gate 21527c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 21537c478bd9Sstevel@tonic-gate static void 21548d5c46e6Sam223141 do_show_linkmap(int argc, char *argv[], const char *use) 21557c478bd9Sstevel@tonic-gate { 2156d62bc4baSyz147064 if (argc != 1) 2157d62bc4baSyz147064 die("invalid arguments"); 21587c478bd9Sstevel@tonic-gate 2159d62bc4baSyz147064 (void) printf("%-12s%8s %-12s%-20s %6s\n", "NAME", "LINKID", 2160d62bc4baSyz147064 "CLASS", "MEDIA", "FLAGS"); 21614ac67f02SAnurag S. Maskey 21624ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(i_dladm_walk_linkmap, handle, NULL, 2163d62bc4baSyz147064 DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE, 2164d62bc4baSyz147064 DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST); 21657c478bd9Sstevel@tonic-gate } 2166d62bc4baSyz147064 2167d62bc4baSyz147064 /* 2168d62bc4baSyz147064 * Delete inactive physical links. 2169d62bc4baSyz147064 */ 2170d62bc4baSyz147064 /*ARGSUSED*/ 2171d62bc4baSyz147064 static int 21724ac67f02SAnurag S. Maskey purge_phys(dladm_handle_t dh, datalink_id_t linkid, void *arg) 2173d62bc4baSyz147064 { 2174d62bc4baSyz147064 datalink_class_t class; 2175d62bc4baSyz147064 uint32_t flags; 2176d62bc4baSyz147064 21774ac67f02SAnurag S. Maskey if (dladm_datalink_id2info(dh, linkid, &flags, &class, NULL, NULL, 0) 21784ac67f02SAnurag S. Maskey != DLADM_STATUS_OK) { 2179d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 2180d62bc4baSyz147064 } 2181d62bc4baSyz147064 2182d62bc4baSyz147064 if (class == DATALINK_CLASS_PHYS && !(flags & DLADM_OPT_ACTIVE)) 21834ac67f02SAnurag S. Maskey (void) dladm_phys_delete(dh, linkid); 2184d62bc4baSyz147064 2185d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 2186d62bc4baSyz147064 } 2187d62bc4baSyz147064 2188d62bc4baSyz147064 /*ARGSUSED*/ 2189d62bc4baSyz147064 static void 21908d5c46e6Sam223141 do_init_phys(int argc, char *argv[], const char *use) 2191d62bc4baSyz147064 { 2192d62bc4baSyz147064 di_node_t devtree; 2193d62bc4baSyz147064 2194d62bc4baSyz147064 if (argc > 1) 2195d62bc4baSyz147064 usage(); 2196d62bc4baSyz147064 2197d62bc4baSyz147064 /* 2198d62bc4baSyz147064 * Force all the devices to attach, therefore all the network physical 2199d62bc4baSyz147064 * devices can be known to the dlmgmtd daemon. 2200d62bc4baSyz147064 */ 2201d62bc4baSyz147064 if ((devtree = di_init("/", DINFOFORCE | DINFOSUBTREE)) != DI_NODE_NIL) 2202d62bc4baSyz147064 di_fini(devtree); 2203d62bc4baSyz147064 22044ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(purge_phys, handle, NULL, 2205d62bc4baSyz147064 DATALINK_CLASS_PHYS, DATALINK_ANY_MEDIATYPE, DLADM_OPT_PERSIST); 22067c478bd9Sstevel@tonic-gate } 22077c478bd9Sstevel@tonic-gate 2208d62bc4baSyz147064 2209d62bc4baSyz147064 /* 2210d62bc4baSyz147064 * Print the active topology information. 2211d62bc4baSyz147064 */ 2212d62bc4baSyz147064 static dladm_status_t 2213d62bc4baSyz147064 print_link_topology(show_state_t *state, datalink_id_t linkid, 2214e7801d59Ssowmini datalink_class_t class, link_fields_buf_t *lbuf) 2215d62bc4baSyz147064 { 2216d62bc4baSyz147064 uint32_t flags = state->ls_flags; 2217d62bc4baSyz147064 dladm_status_t status = DLADM_STATUS_OK; 22186b9e797cSsowmini char tmpbuf[MAXLINKNAMELEN]; 2219d62bc4baSyz147064 2220e7801d59Ssowmini if (!state->ls_parseable) 2221e7801d59Ssowmini (void) sprintf(lbuf->link_over, STR_UNDEF_VAL); 2222d62bc4baSyz147064 else 2223e7801d59Ssowmini (void) sprintf(lbuf->link_over, ""); 2224d62bc4baSyz147064 2225d62bc4baSyz147064 if (class == DATALINK_CLASS_VLAN) { 2226d62bc4baSyz147064 dladm_vlan_attr_t vinfo; 2227d62bc4baSyz147064 22284ac67f02SAnurag S. Maskey status = dladm_vlan_info(handle, linkid, &vinfo, flags); 2229d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 2230d62bc4baSyz147064 goto done; 22314ac67f02SAnurag S. Maskey status = dladm_datalink_id2info(handle, vinfo.dv_linkid, NULL, 22324ac67f02SAnurag S. Maskey NULL, NULL, lbuf->link_over, sizeof (lbuf->link_over)); 2233d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 2234d62bc4baSyz147064 goto done; 2235d62bc4baSyz147064 } else if (class == DATALINK_CLASS_AGGR) { 2236d62bc4baSyz147064 dladm_aggr_grp_attr_t ginfo; 2237d62bc4baSyz147064 int i; 2238d62bc4baSyz147064 22396b9e797cSsowmini (void) sprintf(lbuf->link_over, ""); 22406b9e797cSsowmini 22414ac67f02SAnurag S. Maskey status = dladm_aggr_info(handle, linkid, &ginfo, flags); 2242d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 2243d62bc4baSyz147064 goto done; 2244d62bc4baSyz147064 2245d62bc4baSyz147064 if (ginfo.lg_nports == 0) { 2246d62bc4baSyz147064 status = DLADM_STATUS_BADVAL; 2247d62bc4baSyz147064 goto done; 2248d62bc4baSyz147064 } 2249d62bc4baSyz147064 for (i = 0; i < ginfo.lg_nports; i++) { 22504ac67f02SAnurag S. Maskey status = dladm_datalink_id2info(handle, 2251e7801d59Ssowmini ginfo.lg_ports[i].lp_linkid, NULL, NULL, NULL, 22526b9e797cSsowmini tmpbuf, sizeof (tmpbuf)); 2253d62bc4baSyz147064 if (status != DLADM_STATUS_OK) { 2254d62bc4baSyz147064 free(ginfo.lg_ports); 2255d62bc4baSyz147064 goto done; 2256d62bc4baSyz147064 } 22576b9e797cSsowmini (void) strlcat(lbuf->link_over, tmpbuf, 22586b9e797cSsowmini sizeof (lbuf->link_over)); 22596b9e797cSsowmini if (i != (ginfo.lg_nports - 1)) { 22606b9e797cSsowmini (void) strlcat(lbuf->link_over, " ", 22616b9e797cSsowmini sizeof (lbuf->link_over)); 22626b9e797cSsowmini } 2263d62bc4baSyz147064 } 2264d62bc4baSyz147064 free(ginfo.lg_ports); 2265d62bc4baSyz147064 } else if (class == DATALINK_CLASS_VNIC) { 2266da14cebeSEric Cheng dladm_vnic_attr_t vinfo; 2267d62bc4baSyz147064 22684ac67f02SAnurag S. Maskey if ((status = dladm_vnic_info(handle, linkid, &vinfo, flags)) != 22694ac67f02SAnurag S. Maskey DLADM_STATUS_OK || 22704ac67f02SAnurag S. Maskey (status = dladm_datalink_id2info(handle, vinfo.va_link_id, 22714ac67f02SAnurag S. Maskey NULL, NULL, NULL, lbuf->link_over, 2272e7801d59Ssowmini sizeof (lbuf->link_over)) != DLADM_STATUS_OK)) { 2273d62bc4baSyz147064 goto done; 2274d62bc4baSyz147064 } 2275d62bc4baSyz147064 } 2276d62bc4baSyz147064 done: 2277d62bc4baSyz147064 return (status); 2278d62bc4baSyz147064 } 2279d62bc4baSyz147064 2280d62bc4baSyz147064 static dladm_status_t 2281e7801d59Ssowmini print_link(show_state_t *state, datalink_id_t linkid, link_fields_buf_t *lbuf) 2282d62bc4baSyz147064 { 2283d62bc4baSyz147064 char link[MAXLINKNAMELEN]; 2284d62bc4baSyz147064 datalink_class_t class; 2285d62bc4baSyz147064 uint_t mtu; 2286d62bc4baSyz147064 uint32_t flags; 2287d62bc4baSyz147064 dladm_status_t status; 2288d62bc4baSyz147064 22894ac67f02SAnurag S. Maskey if ((status = dladm_datalink_id2info(handle, linkid, &flags, &class, 22904ac67f02SAnurag S. Maskey NULL, link, sizeof (link))) != DLADM_STATUS_OK) { 2291d62bc4baSyz147064 goto done; 2292d62bc4baSyz147064 } 2293d62bc4baSyz147064 2294d62bc4baSyz147064 if (!(state->ls_flags & flags)) { 2295d62bc4baSyz147064 status = DLADM_STATUS_NOTFOUND; 2296d62bc4baSyz147064 goto done; 2297d62bc4baSyz147064 } 2298d62bc4baSyz147064 2299d62bc4baSyz147064 if (state->ls_flags == DLADM_OPT_ACTIVE) { 2300d62bc4baSyz147064 dladm_attr_t dlattr; 2301d62bc4baSyz147064 2302d62bc4baSyz147064 if (class == DATALINK_CLASS_PHYS) { 2303d62bc4baSyz147064 dladm_phys_attr_t dpa; 2304d62bc4baSyz147064 dlpi_handle_t dh; 2305d62bc4baSyz147064 dlpi_info_t dlinfo; 2306d62bc4baSyz147064 23074ac67f02SAnurag S. Maskey if ((status = dladm_phys_info(handle, linkid, &dpa, 2308d62bc4baSyz147064 DLADM_OPT_ACTIVE)) != DLADM_STATUS_OK) { 2309d62bc4baSyz147064 goto done; 2310d62bc4baSyz147064 } 2311d62bc4baSyz147064 2312d62bc4baSyz147064 if (!dpa.dp_novanity) 2313d62bc4baSyz147064 goto link_mtu; 2314d62bc4baSyz147064 2315d62bc4baSyz147064 /* 2316d62bc4baSyz147064 * This is a physical link that does not have 2317d62bc4baSyz147064 * vanity naming support. 2318d62bc4baSyz147064 */ 2319d62bc4baSyz147064 if (dlpi_open(dpa.dp_dev, &dh, DLPI_DEVONLY) != 2320d62bc4baSyz147064 DLPI_SUCCESS) { 2321d62bc4baSyz147064 status = DLADM_STATUS_NOTFOUND; 2322d62bc4baSyz147064 goto done; 2323d62bc4baSyz147064 } 2324d62bc4baSyz147064 2325d62bc4baSyz147064 if (dlpi_info(dh, &dlinfo, 0) != DLPI_SUCCESS) { 2326d62bc4baSyz147064 dlpi_close(dh); 2327d62bc4baSyz147064 status = DLADM_STATUS_BADARG; 2328d62bc4baSyz147064 goto done; 2329d62bc4baSyz147064 } 2330d62bc4baSyz147064 2331d62bc4baSyz147064 dlpi_close(dh); 2332d62bc4baSyz147064 mtu = dlinfo.di_max_sdu; 2333d62bc4baSyz147064 } else { 2334d62bc4baSyz147064 link_mtu: 23354ac67f02SAnurag S. Maskey status = dladm_info(handle, linkid, &dlattr); 2336d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 2337d62bc4baSyz147064 goto done; 2338d62bc4baSyz147064 mtu = dlattr.da_max_sdu; 2339d62bc4baSyz147064 } 2340d62bc4baSyz147064 } 2341d62bc4baSyz147064 2342e7801d59Ssowmini (void) snprintf(lbuf->link_name, sizeof (lbuf->link_name), 2343e7801d59Ssowmini "%s", link); 2344e7801d59Ssowmini (void) dladm_class2str(class, lbuf->link_class); 2345d62bc4baSyz147064 if (state->ls_flags == DLADM_OPT_ACTIVE) { 2346e7801d59Ssowmini (void) snprintf(lbuf->link_mtu, sizeof (lbuf->link_mtu), 2347c08e5e1aSdr146992 "%u", mtu); 2348e7801d59Ssowmini (void) get_linkstate(link, B_TRUE, lbuf->link_state); 2349d62bc4baSyz147064 } 2350d62bc4baSyz147064 2351e7801d59Ssowmini status = print_link_topology(state, linkid, class, lbuf); 2352d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 2353d62bc4baSyz147064 goto done; 2354d62bc4baSyz147064 2355d62bc4baSyz147064 done: 2356d62bc4baSyz147064 return (status); 2357d62bc4baSyz147064 } 2358d62bc4baSyz147064 23594ac67f02SAnurag S. Maskey /* ARGSUSED */ 2360d62bc4baSyz147064 static int 23614ac67f02SAnurag S. Maskey show_link(dladm_handle_t dh, datalink_id_t linkid, void *arg) 2362d62bc4baSyz147064 { 2363e7801d59Ssowmini show_state_t *state = (show_state_t *)arg; 2364d62bc4baSyz147064 dladm_status_t status; 2365e7801d59Ssowmini link_fields_buf_t lbuf; 2366d62bc4baSyz147064 2367e7801d59Ssowmini /* 2368e7801d59Ssowmini * first get all the link attributes into lbuf; 2369e7801d59Ssowmini */ 23705f5c9f54SAnurag S. Maskey bzero(&lbuf, sizeof (link_fields_buf_t)); 2371e7801d59Ssowmini status = print_link(state, linkid, &lbuf); 2372e7801d59Ssowmini 2373d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 2374d62bc4baSyz147064 goto done; 2375e7801d59Ssowmini 2376e7801d59Ssowmini if (!state->ls_parseable && !state->ls_printheader) { 2377e7801d59Ssowmini print_header(&state->ls_print); 2378e7801d59Ssowmini state->ls_printheader = B_TRUE; 2379e7801d59Ssowmini } 2380e7801d59Ssowmini 2381e7801d59Ssowmini dladm_print_output(&state->ls_print, state->ls_parseable, 2382e7801d59Ssowmini dladm_print_field, (void *)&lbuf); 2383d62bc4baSyz147064 2384d62bc4baSyz147064 done: 2385d62bc4baSyz147064 state->ls_status = status; 2386d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 2387d62bc4baSyz147064 } 2388d62bc4baSyz147064 2389ae6aa22aSVenugopal Iyer static char * 2390ae6aa22aSVenugopal Iyer print_link_stats(print_field_t *pf, void *arg) 2391ae6aa22aSVenugopal Iyer { 2392ae6aa22aSVenugopal Iyer link_args_t *largs = arg; 2393ae6aa22aSVenugopal Iyer pktsum_t *diff_stats = largs->link_s_psum; 2394ae6aa22aSVenugopal Iyer static char buf[DLADM_STRSIZE]; 2395ae6aa22aSVenugopal Iyer 2396ae6aa22aSVenugopal Iyer switch (pf->pf_index) { 2397ae6aa22aSVenugopal Iyer case LINK_S_LINK: 2398ae6aa22aSVenugopal Iyer (void) snprintf(buf, sizeof (buf), "%s", largs->link_s_link); 2399ae6aa22aSVenugopal Iyer break; 2400ae6aa22aSVenugopal Iyer case LINK_S_IPKTS: 2401ae6aa22aSVenugopal Iyer (void) snprintf(buf, sizeof (buf), "%llu", 2402ae6aa22aSVenugopal Iyer diff_stats->ipackets); 2403ae6aa22aSVenugopal Iyer break; 2404ae6aa22aSVenugopal Iyer case LINK_S_RBYTES: 2405ae6aa22aSVenugopal Iyer (void) snprintf(buf, sizeof (buf), "%llu", 2406ae6aa22aSVenugopal Iyer diff_stats->rbytes); 2407ae6aa22aSVenugopal Iyer break; 2408ae6aa22aSVenugopal Iyer case LINK_S_IERRORS: 2409ae6aa22aSVenugopal Iyer (void) snprintf(buf, sizeof (buf), "%u", 2410ae6aa22aSVenugopal Iyer diff_stats->ierrors); 2411ae6aa22aSVenugopal Iyer break; 2412ae6aa22aSVenugopal Iyer case LINK_S_OPKTS: 2413ae6aa22aSVenugopal Iyer (void) snprintf(buf, sizeof (buf), "%llu", 2414ae6aa22aSVenugopal Iyer diff_stats->opackets); 2415ae6aa22aSVenugopal Iyer break; 2416ae6aa22aSVenugopal Iyer case LINK_S_OBYTES: 2417ae6aa22aSVenugopal Iyer (void) snprintf(buf, sizeof (buf), "%llu", 2418ae6aa22aSVenugopal Iyer diff_stats->obytes); 2419ae6aa22aSVenugopal Iyer break; 2420ae6aa22aSVenugopal Iyer case LINK_S_OERRORS: 2421ae6aa22aSVenugopal Iyer (void) snprintf(buf, sizeof (buf), "%u", 2422ae6aa22aSVenugopal Iyer diff_stats->oerrors); 2423ae6aa22aSVenugopal Iyer break; 2424ae6aa22aSVenugopal Iyer default: 2425ae6aa22aSVenugopal Iyer die("invalid input"); 2426ae6aa22aSVenugopal Iyer break; 2427ae6aa22aSVenugopal Iyer } 2428ae6aa22aSVenugopal Iyer return (buf); 2429ae6aa22aSVenugopal Iyer } 2430ae6aa22aSVenugopal Iyer 2431d62bc4baSyz147064 static int 24324ac67f02SAnurag S. Maskey show_link_stats(dladm_handle_t dh, datalink_id_t linkid, void *arg) 2433d62bc4baSyz147064 { 2434e7801d59Ssowmini char link[DLPI_LINKNAME_MAX]; 2435d62bc4baSyz147064 datalink_class_t class; 2436e7801d59Ssowmini show_state_t *state = (show_state_t *)arg; 24377c478bd9Sstevel@tonic-gate pktsum_t stats, diff_stats; 2438d62bc4baSyz147064 dladm_phys_attr_t dpa; 2439ae6aa22aSVenugopal Iyer link_args_t largs; 24407c478bd9Sstevel@tonic-gate 24417c478bd9Sstevel@tonic-gate if (state->ls_firstonly) { 24427c478bd9Sstevel@tonic-gate if (state->ls_donefirst) 2443d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 24447c478bd9Sstevel@tonic-gate state->ls_donefirst = B_TRUE; 24457c478bd9Sstevel@tonic-gate } else { 24467c478bd9Sstevel@tonic-gate bzero(&state->ls_prevstats, sizeof (state->ls_prevstats)); 24477c478bd9Sstevel@tonic-gate } 24487c478bd9Sstevel@tonic-gate 24494ac67f02SAnurag S. Maskey if (dladm_datalink_id2info(dh, linkid, NULL, &class, NULL, link, 2450e7801d59Ssowmini DLPI_LINKNAME_MAX) != DLADM_STATUS_OK) { 2451d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 2452d62bc4baSyz147064 } 2453d62bc4baSyz147064 2454d62bc4baSyz147064 if (class == DATALINK_CLASS_PHYS) { 24554ac67f02SAnurag S. Maskey if (dladm_phys_info(dh, linkid, &dpa, DLADM_OPT_ACTIVE) != 2456d62bc4baSyz147064 DLADM_STATUS_OK) { 2457d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 2458d62bc4baSyz147064 } 2459d62bc4baSyz147064 if (dpa.dp_novanity) 2460d62bc4baSyz147064 get_mac_stats(dpa.dp_dev, &stats); 2461d62bc4baSyz147064 else 2462d62bc4baSyz147064 get_link_stats(link, &stats); 2463d62bc4baSyz147064 } else { 2464d62bc4baSyz147064 get_link_stats(link, &stats); 2465d62bc4baSyz147064 } 2466da14cebeSEric Cheng dladm_stats_diff(&diff_stats, &stats, &state->ls_prevstats); 24677c478bd9Sstevel@tonic-gate 2468ae6aa22aSVenugopal Iyer largs.link_s_link = link; 2469ae6aa22aSVenugopal Iyer largs.link_s_psum = &diff_stats; 2470ae6aa22aSVenugopal Iyer dladm_print_output(&state->ls_print, state->ls_parseable, 2471ae6aa22aSVenugopal Iyer print_link_stats, &largs); 24727c478bd9Sstevel@tonic-gate 24737c478bd9Sstevel@tonic-gate state->ls_prevstats = stats; 2474d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 24757c478bd9Sstevel@tonic-gate } 24767c478bd9Sstevel@tonic-gate 2477d62bc4baSyz147064 2478d62bc4baSyz147064 static dladm_status_t 2479d62bc4baSyz147064 print_aggr_info(show_grp_state_t *state, const char *link, 2480e7801d59Ssowmini dladm_aggr_grp_attr_t *ginfop) 2481d62bc4baSyz147064 { 2482d62bc4baSyz147064 char addr_str[ETHERADDRL * 3]; 2483e7801d59Ssowmini laggr_fields_buf_t lbuf; 2484d62bc4baSyz147064 2485e7801d59Ssowmini (void) snprintf(lbuf.laggr_name, sizeof (lbuf.laggr_name), 2486e7801d59Ssowmini "%s", link); 2487e7801d59Ssowmini 2488e7801d59Ssowmini (void) dladm_aggr_policy2str(ginfop->lg_policy, 2489e7801d59Ssowmini lbuf.laggr_policy); 2490d62bc4baSyz147064 2491d62bc4baSyz147064 if (ginfop->lg_mac_fixed) { 2492d62bc4baSyz147064 (void) dladm_aggr_macaddr2str(ginfop->lg_mac, addr_str); 2493e7801d59Ssowmini (void) snprintf(lbuf.laggr_addrpolicy, 2494e7801d59Ssowmini sizeof (lbuf.laggr_addrpolicy), "fixed (%s)", addr_str); 2495d62bc4baSyz147064 } else { 2496e7801d59Ssowmini (void) snprintf(lbuf.laggr_addrpolicy, 2497e7801d59Ssowmini sizeof (lbuf.laggr_addrpolicy), "auto"); 2498d62bc4baSyz147064 } 2499d62bc4baSyz147064 2500d62bc4baSyz147064 2501e7801d59Ssowmini (void) dladm_aggr_lacpmode2str(ginfop->lg_lacp_mode, 2502e7801d59Ssowmini lbuf.laggr_lacpactivity); 2503e7801d59Ssowmini (void) dladm_aggr_lacptimer2str(ginfop->lg_lacp_timer, 2504e7801d59Ssowmini lbuf.laggr_lacptimer); 2505e7801d59Ssowmini (void) snprintf(lbuf.laggr_flags, sizeof (lbuf.laggr_flags), "%c----", 2506d62bc4baSyz147064 ginfop->lg_force ? 'f' : '-'); 2507e7801d59Ssowmini 2508e7801d59Ssowmini if (!state->gs_parseable && !state->gs_printheader) { 2509e7801d59Ssowmini print_header(&state->gs_print); 2510e7801d59Ssowmini state->gs_printheader = B_TRUE; 2511d62bc4baSyz147064 } 2512d62bc4baSyz147064 2513e7801d59Ssowmini dladm_print_output(&state->gs_print, state->gs_parseable, 2514e7801d59Ssowmini dladm_print_field, (void *)&lbuf); 2515e7801d59Ssowmini 2516d62bc4baSyz147064 return (DLADM_STATUS_OK); 2517d62bc4baSyz147064 } 2518d62bc4baSyz147064 2519e7801d59Ssowmini static char * 2520e7801d59Ssowmini print_xaggr_callback(print_field_t *pf, void *arg) 2521d62bc4baSyz147064 { 2522e7801d59Ssowmini const laggr_args_t *l = arg; 2523e7801d59Ssowmini int portnum; 2524e7801d59Ssowmini static char buf[DLADM_STRSIZE]; 2525e7801d59Ssowmini boolean_t is_port = (l->laggr_lport >= 0); 2526e7801d59Ssowmini dladm_aggr_port_attr_t *portp; 2527d62bc4baSyz147064 dladm_phys_attr_t dpa; 2528e7801d59Ssowmini dladm_status_t *stat, status; 2529d62bc4baSyz147064 2530e7801d59Ssowmini stat = l->laggr_status; 2531e7801d59Ssowmini *stat = DLADM_STATUS_OK; 2532d62bc4baSyz147064 2533e7801d59Ssowmini if (is_port) { 2534e7801d59Ssowmini portnum = l->laggr_lport; 2535e7801d59Ssowmini portp = &(l->laggr_ginfop->lg_ports[portnum]); 25364ac67f02SAnurag S. Maskey if ((status = dladm_datalink_id2info(handle, 25374ac67f02SAnurag S. Maskey portp->lp_linkid, NULL, NULL, NULL, buf, sizeof (buf))) != 2538e7801d59Ssowmini DLADM_STATUS_OK) { 2539e7801d59Ssowmini goto err; 2540d62bc4baSyz147064 } 25414ac67f02SAnurag S. Maskey 25424ac67f02SAnurag S. Maskey if ((status = dladm_phys_info(handle, portp->lp_linkid, 25434ac67f02SAnurag S. Maskey &dpa, DLADM_OPT_ACTIVE)) != DLADM_STATUS_OK) { 2544e7801d59Ssowmini goto err; 2545e7801d59Ssowmini } 2546d62bc4baSyz147064 } 2547d62bc4baSyz147064 2548e7801d59Ssowmini switch (pf->pf_index) { 2549e7801d59Ssowmini case AGGR_X_LINK: 2550e7801d59Ssowmini (void) snprintf(buf, sizeof (buf), "%s", 2551e7801d59Ssowmini (is_port && !l->laggr_parseable ? " " : l->laggr_link)); 2552e7801d59Ssowmini break; 2553e7801d59Ssowmini case AGGR_X_PORT: 2554e7801d59Ssowmini if (is_port) 2555e7801d59Ssowmini break; 2556e7801d59Ssowmini return (""); 2557e7801d59Ssowmini break; 2558d62bc4baSyz147064 2559e7801d59Ssowmini case AGGR_X_SPEED: 2560e7801d59Ssowmini if (is_port) { 2561e7801d59Ssowmini (void) snprintf(buf, sizeof (buf), "%uMb", 2562e7801d59Ssowmini (uint_t)((get_ifspeed(dpa.dp_dev, 2563e7801d59Ssowmini B_FALSE)) / 1000000ull)); 2564e7801d59Ssowmini } else { 2565e7801d59Ssowmini (void) snprintf(buf, sizeof (buf), "%uMb", 2566e7801d59Ssowmini (uint_t)((get_ifspeed(l->laggr_link, 2567e7801d59Ssowmini B_TRUE)) / 1000000ull)); 2568e7801d59Ssowmini } 2569e7801d59Ssowmini break; 2570e7801d59Ssowmini 2571e7801d59Ssowmini case AGGR_X_DUPLEX: 2572e7801d59Ssowmini if (is_port) 2573e7801d59Ssowmini (void) get_linkduplex(dpa.dp_dev, B_FALSE, buf); 2574d62bc4baSyz147064 else 2575e7801d59Ssowmini (void) get_linkduplex(l->laggr_link, B_TRUE, buf); 2576e7801d59Ssowmini break; 2577d62bc4baSyz147064 2578e7801d59Ssowmini case AGGR_X_STATE: 25791a1811a0Svs226613 if (is_port) 25801a1811a0Svs226613 (void) get_linkstate(dpa.dp_dev, B_FALSE, buf); 25811a1811a0Svs226613 else 25821a1811a0Svs226613 (void) get_linkstate(l->laggr_link, B_TRUE, buf); 2583e7801d59Ssowmini break; 2584e7801d59Ssowmini case AGGR_X_ADDRESS: 2585e7801d59Ssowmini (void) dladm_aggr_macaddr2str( 2586e7801d59Ssowmini (is_port ? portp->lp_mac : l->laggr_ginfop->lg_mac), 2587e7801d59Ssowmini buf); 2588e7801d59Ssowmini break; 2589e7801d59Ssowmini case AGGR_X_PORTSTATE: 25900d365605Sschuster if (is_port) 25910d365605Sschuster (void) dladm_aggr_portstate2str( 25920d365605Sschuster portp->lp_state, buf); 25930d365605Sschuster else 25940d365605Sschuster return (""); 2595e7801d59Ssowmini break; 2596e7801d59Ssowmini } 2597e7801d59Ssowmini return (buf); 2598e7801d59Ssowmini 2599e7801d59Ssowmini err: 2600e7801d59Ssowmini *stat = status; 2601e7801d59Ssowmini buf[0] = '\0'; 2602e7801d59Ssowmini return (buf); 2603e7801d59Ssowmini } 2604e7801d59Ssowmini 2605e7801d59Ssowmini static dladm_status_t 2606e7801d59Ssowmini print_aggr_extended(show_grp_state_t *state, const char *link, 2607e7801d59Ssowmini dladm_aggr_grp_attr_t *ginfop) 2608e7801d59Ssowmini { 2609e7801d59Ssowmini int i; 2610e7801d59Ssowmini dladm_status_t status; 2611e7801d59Ssowmini laggr_args_t largs; 2612e7801d59Ssowmini 2613e7801d59Ssowmini if (!state->gs_parseable && !state->gs_printheader) { 2614e7801d59Ssowmini print_header(&state->gs_print); 2615e7801d59Ssowmini state->gs_printheader = B_TRUE; 2616e7801d59Ssowmini } 2617e7801d59Ssowmini 2618e7801d59Ssowmini largs.laggr_lport = -1; 2619e7801d59Ssowmini largs.laggr_link = link; 2620e7801d59Ssowmini largs.laggr_ginfop = ginfop; 2621e7801d59Ssowmini largs.laggr_status = &status; 2622e7801d59Ssowmini largs.laggr_parseable = state->gs_parseable; 2623e7801d59Ssowmini 2624e7801d59Ssowmini dladm_print_output(&state->gs_print, state->gs_parseable, 2625e7801d59Ssowmini print_xaggr_callback, &largs); 2626e7801d59Ssowmini 2627e7801d59Ssowmini if (status != DLADM_STATUS_OK) 2628e7801d59Ssowmini goto done; 2629e7801d59Ssowmini 2630e7801d59Ssowmini for (i = 0; i < ginfop->lg_nports; i++) { 2631e7801d59Ssowmini largs.laggr_lport = i; 2632e7801d59Ssowmini dladm_print_output(&state->gs_print, state->gs_parseable, 2633e7801d59Ssowmini print_xaggr_callback, &largs); 2634e7801d59Ssowmini if (status != DLADM_STATUS_OK) 2635e7801d59Ssowmini goto done; 2636d62bc4baSyz147064 } 2637d62bc4baSyz147064 2638d62bc4baSyz147064 status = DLADM_STATUS_OK; 2639d62bc4baSyz147064 done: 2640d62bc4baSyz147064 return (status); 2641d62bc4baSyz147064 } 2642d62bc4baSyz147064 2643e7801d59Ssowmini 2644e7801d59Ssowmini static char * 2645e7801d59Ssowmini print_lacp_callback(print_field_t *pf, void *arg) 2646e7801d59Ssowmini { 2647e7801d59Ssowmini const laggr_args_t *l = arg; 2648e7801d59Ssowmini int portnum; 2649e7801d59Ssowmini static char buf[DLADM_STRSIZE]; 2650e7801d59Ssowmini boolean_t is_port = (l->laggr_lport >= 0); 2651e7801d59Ssowmini dladm_aggr_port_attr_t *portp; 2652e7801d59Ssowmini dladm_status_t *stat, status; 2653e7801d59Ssowmini aggr_lacp_state_t *lstate; 2654e7801d59Ssowmini 2655e7801d59Ssowmini if (!is_port) { 2656e7801d59Ssowmini return (NULL); /* cannot happen! */ 2657e7801d59Ssowmini } 2658e7801d59Ssowmini 2659e7801d59Ssowmini stat = l->laggr_status; 2660e7801d59Ssowmini 2661e7801d59Ssowmini portnum = l->laggr_lport; 2662e7801d59Ssowmini portp = &(l->laggr_ginfop->lg_ports[portnum]); 26634ac67f02SAnurag S. Maskey 26644ac67f02SAnurag S. Maskey if ((status = dladm_datalink_id2info(handle, portp->lp_linkid, 2665e7801d59Ssowmini NULL, NULL, NULL, buf, sizeof (buf))) != DLADM_STATUS_OK) { 2666e7801d59Ssowmini goto err; 2667e7801d59Ssowmini } 2668e7801d59Ssowmini lstate = &(portp->lp_lacp_state); 2669e7801d59Ssowmini 2670e7801d59Ssowmini switch (pf->pf_index) { 2671e7801d59Ssowmini case AGGR_L_LINK: 2672e7801d59Ssowmini (void) snprintf(buf, sizeof (buf), "%s", 2673e7801d59Ssowmini (portnum > 0 ? "" : l->laggr_link)); 2674e7801d59Ssowmini break; 2675e7801d59Ssowmini 2676e7801d59Ssowmini case AGGR_L_PORT: 2677e7801d59Ssowmini break; 2678e7801d59Ssowmini 2679e7801d59Ssowmini case AGGR_L_AGGREGATABLE: 2680e7801d59Ssowmini (void) snprintf(buf, sizeof (buf), "%s", 2681e7801d59Ssowmini (lstate->bit.aggregation ? "yes" : "no")); 2682e7801d59Ssowmini break; 2683e7801d59Ssowmini 2684e7801d59Ssowmini case AGGR_L_SYNC: 2685e7801d59Ssowmini (void) snprintf(buf, sizeof (buf), "%s", 2686e7801d59Ssowmini (lstate->bit.sync ? "yes" : "no")); 2687e7801d59Ssowmini break; 2688e7801d59Ssowmini 2689e7801d59Ssowmini case AGGR_L_COLL: 2690e7801d59Ssowmini (void) snprintf(buf, sizeof (buf), "%s", 2691e7801d59Ssowmini (lstate->bit.collecting ? "yes" : "no")); 2692e7801d59Ssowmini break; 2693e7801d59Ssowmini 2694e7801d59Ssowmini case AGGR_L_DIST: 2695e7801d59Ssowmini (void) snprintf(buf, sizeof (buf), "%s", 2696e7801d59Ssowmini (lstate->bit.distributing ? "yes" : "no")); 2697e7801d59Ssowmini break; 2698e7801d59Ssowmini 2699e7801d59Ssowmini case AGGR_L_DEFAULTED: 2700e7801d59Ssowmini (void) snprintf(buf, sizeof (buf), "%s", 2701e7801d59Ssowmini (lstate->bit.defaulted ? "yes" : "no")); 2702e7801d59Ssowmini break; 2703e7801d59Ssowmini 2704e7801d59Ssowmini case AGGR_L_EXPIRED: 2705e7801d59Ssowmini (void) snprintf(buf, sizeof (buf), "%s", 2706e7801d59Ssowmini (lstate->bit.expired ? "yes" : "no")); 2707e7801d59Ssowmini break; 2708e7801d59Ssowmini } 2709e7801d59Ssowmini 2710e7801d59Ssowmini *stat = DLADM_STATUS_OK; 2711e7801d59Ssowmini return (buf); 2712e7801d59Ssowmini 2713e7801d59Ssowmini err: 2714e7801d59Ssowmini *stat = status; 2715e7801d59Ssowmini buf[0] = '\0'; 2716e7801d59Ssowmini return (buf); 2717e7801d59Ssowmini } 2718e7801d59Ssowmini 2719d62bc4baSyz147064 static dladm_status_t 2720d62bc4baSyz147064 print_aggr_lacp(show_grp_state_t *state, const char *link, 2721e7801d59Ssowmini dladm_aggr_grp_attr_t *ginfop) 2722d62bc4baSyz147064 { 2723d62bc4baSyz147064 int i; 2724d62bc4baSyz147064 dladm_status_t status; 2725e7801d59Ssowmini laggr_args_t largs; 2726d62bc4baSyz147064 2727e7801d59Ssowmini if (!state->gs_parseable && !state->gs_printheader) { 2728e7801d59Ssowmini print_header(&state->gs_print); 2729e7801d59Ssowmini state->gs_printheader = B_TRUE; 2730d62bc4baSyz147064 } 2731d62bc4baSyz147064 2732e7801d59Ssowmini largs.laggr_link = link; 2733e7801d59Ssowmini largs.laggr_ginfop = ginfop; 2734e7801d59Ssowmini largs.laggr_status = &status; 2735d62bc4baSyz147064 2736e7801d59Ssowmini for (i = 0; i < ginfop->lg_nports; i++) { 2737e7801d59Ssowmini largs.laggr_lport = i; 2738e7801d59Ssowmini dladm_print_output(&state->gs_print, state->gs_parseable, 2739e7801d59Ssowmini print_lacp_callback, &largs); 2740d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 2741d62bc4baSyz147064 goto done; 2742d62bc4baSyz147064 } 2743d62bc4baSyz147064 2744d62bc4baSyz147064 status = DLADM_STATUS_OK; 2745d62bc4baSyz147064 done: 2746d62bc4baSyz147064 return (status); 2747d62bc4baSyz147064 } 2748d62bc4baSyz147064 2749e7801d59Ssowmini static char * 2750e7801d59Ssowmini print_aggr_stats_callback(print_field_t *pf, void *arg) 2751e7801d59Ssowmini { 2752e7801d59Ssowmini const laggr_args_t *l = arg; 2753e7801d59Ssowmini int portnum; 2754e7801d59Ssowmini static char buf[DLADM_STRSIZE]; 2755e7801d59Ssowmini boolean_t is_port = (l->laggr_lport >= 0); 2756e7801d59Ssowmini dladm_aggr_port_attr_t *portp; 2757e7801d59Ssowmini dladm_phys_attr_t dpa; 2758e7801d59Ssowmini dladm_status_t *stat, status; 2759e7801d59Ssowmini pktsum_t port_stat, diff_stats; 2760e7801d59Ssowmini 2761e7801d59Ssowmini stat = l->laggr_status; 2762e7801d59Ssowmini *stat = DLADM_STATUS_OK; 2763e7801d59Ssowmini 2764e7801d59Ssowmini if (is_port) { 2765e7801d59Ssowmini portnum = l->laggr_lport; 2766e7801d59Ssowmini portp = &(l->laggr_ginfop->lg_ports[portnum]); 27674ac67f02SAnurag S. Maskey if ((status = dladm_phys_info(handle, portp->lp_linkid, 27684ac67f02SAnurag S. Maskey &dpa, DLADM_OPT_ACTIVE)) != DLADM_STATUS_OK) { 2769e7801d59Ssowmini goto err; 2770e7801d59Ssowmini } 2771e7801d59Ssowmini 2772e7801d59Ssowmini get_mac_stats(dpa.dp_dev, &port_stat); 2773e7801d59Ssowmini 27744ac67f02SAnurag S. Maskey if ((status = dladm_datalink_id2info(handle, 27754ac67f02SAnurag S. Maskey portp->lp_linkid, NULL, NULL, NULL, buf, sizeof (buf))) != 27764ac67f02SAnurag S. Maskey DLADM_STATUS_OK) { 2777e7801d59Ssowmini goto err; 2778e7801d59Ssowmini } 2779e7801d59Ssowmini 2780da14cebeSEric Cheng dladm_stats_diff(&diff_stats, &port_stat, l->laggr_prevstats); 2781e7801d59Ssowmini } 2782e7801d59Ssowmini 2783e7801d59Ssowmini switch (pf->pf_index) { 2784e7801d59Ssowmini case AGGR_S_LINK: 2785e7801d59Ssowmini (void) snprintf(buf, sizeof (buf), "%s", 2786e7801d59Ssowmini (is_port ? "" : l->laggr_link)); 2787e7801d59Ssowmini break; 2788e7801d59Ssowmini case AGGR_S_PORT: 2789e7801d59Ssowmini if (is_port) 2790e7801d59Ssowmini break; 27910d365605Sschuster return (""); 2792e7801d59Ssowmini break; 2793e7801d59Ssowmini 2794e7801d59Ssowmini case AGGR_S_IPKTS: 2795e7801d59Ssowmini if (is_port) { 2796e7801d59Ssowmini (void) snprintf(buf, sizeof (buf), "%llu", 2797e7801d59Ssowmini diff_stats.ipackets); 2798e7801d59Ssowmini } else { 2799e7801d59Ssowmini (void) snprintf(buf, sizeof (buf), "%llu", 2800e7801d59Ssowmini l->laggr_pktsumtot->ipackets); 2801e7801d59Ssowmini } 2802e7801d59Ssowmini break; 2803e7801d59Ssowmini 2804e7801d59Ssowmini case AGGR_S_RBYTES: 2805e7801d59Ssowmini if (is_port) { 2806e7801d59Ssowmini (void) snprintf(buf, sizeof (buf), "%llu", 2807e7801d59Ssowmini diff_stats.rbytes); 2808e7801d59Ssowmini } else { 2809e7801d59Ssowmini (void) snprintf(buf, sizeof (buf), "%llu", 2810e7801d59Ssowmini l->laggr_pktsumtot->rbytes); 2811e7801d59Ssowmini } 2812e7801d59Ssowmini break; 2813e7801d59Ssowmini 2814e7801d59Ssowmini case AGGR_S_OPKTS: 2815e7801d59Ssowmini if (is_port) { 2816e7801d59Ssowmini (void) snprintf(buf, sizeof (buf), "%llu", 2817e7801d59Ssowmini diff_stats.opackets); 2818e7801d59Ssowmini } else { 2819e7801d59Ssowmini (void) snprintf(buf, sizeof (buf), "%llu", 2820e7801d59Ssowmini l->laggr_pktsumtot->opackets); 2821e7801d59Ssowmini } 2822e7801d59Ssowmini break; 2823e7801d59Ssowmini case AGGR_S_OBYTES: 2824e7801d59Ssowmini if (is_port) { 2825e7801d59Ssowmini (void) snprintf(buf, sizeof (buf), "%llu", 2826e7801d59Ssowmini diff_stats.obytes); 2827e7801d59Ssowmini } else { 2828e7801d59Ssowmini (void) snprintf(buf, sizeof (buf), "%llu", 2829e7801d59Ssowmini l->laggr_pktsumtot->obytes); 2830e7801d59Ssowmini } 2831e7801d59Ssowmini break; 2832e7801d59Ssowmini 2833e7801d59Ssowmini case AGGR_S_IPKTDIST: 2834e7801d59Ssowmini if (is_port) { 2835e7801d59Ssowmini (void) snprintf(buf, sizeof (buf), "%-6.1f", 2836e7801d59Ssowmini (double)diff_stats.opackets/ 2837e7801d59Ssowmini (double)l->laggr_pktsumtot->ipackets * 100); 2838e7801d59Ssowmini } else { 28390d365605Sschuster return (""); 2840e7801d59Ssowmini } 2841e7801d59Ssowmini break; 2842e7801d59Ssowmini case AGGR_S_OPKTDIST: 2843e7801d59Ssowmini if (is_port) { 2844e7801d59Ssowmini (void) snprintf(buf, sizeof (buf), "%-6.1f", 2845e7801d59Ssowmini (double)diff_stats.opackets/ 2846e7801d59Ssowmini (double)l->laggr_pktsumtot->opackets * 100); 2847e7801d59Ssowmini } else { 28480d365605Sschuster return (""); 2849e7801d59Ssowmini } 2850e7801d59Ssowmini break; 2851e7801d59Ssowmini } 2852e7801d59Ssowmini return (buf); 2853e7801d59Ssowmini 2854e7801d59Ssowmini err: 2855e7801d59Ssowmini *stat = status; 2856e7801d59Ssowmini buf[0] = '\0'; 2857e7801d59Ssowmini return (buf); 2858e7801d59Ssowmini } 2859e7801d59Ssowmini 2860d62bc4baSyz147064 static dladm_status_t 2861d62bc4baSyz147064 print_aggr_stats(show_grp_state_t *state, const char *link, 2862e7801d59Ssowmini dladm_aggr_grp_attr_t *ginfop) 2863d62bc4baSyz147064 { 2864d62bc4baSyz147064 dladm_phys_attr_t dpa; 2865d62bc4baSyz147064 dladm_aggr_port_attr_t *portp; 2866d62bc4baSyz147064 pktsum_t pktsumtot, port_stat; 2867d62bc4baSyz147064 dladm_status_t status; 2868d62bc4baSyz147064 int i; 2869e7801d59Ssowmini laggr_args_t largs; 28707c478bd9Sstevel@tonic-gate 28717c478bd9Sstevel@tonic-gate /* sum the ports statistics */ 28727c478bd9Sstevel@tonic-gate bzero(&pktsumtot, sizeof (pktsumtot)); 2873d62bc4baSyz147064 2874d62bc4baSyz147064 for (i = 0; i < ginfop->lg_nports; i++) { 2875d62bc4baSyz147064 2876d62bc4baSyz147064 portp = &(ginfop->lg_ports[i]); 28774ac67f02SAnurag S. Maskey if ((status = dladm_phys_info(handle, portp->lp_linkid, &dpa, 2878d62bc4baSyz147064 DLADM_OPT_ACTIVE)) != DLADM_STATUS_OK) { 2879d62bc4baSyz147064 goto done; 28807c478bd9Sstevel@tonic-gate } 28817c478bd9Sstevel@tonic-gate 2882d62bc4baSyz147064 get_mac_stats(dpa.dp_dev, &port_stat); 2883da14cebeSEric Cheng dladm_stats_total(&pktsumtot, &port_stat, 2884da14cebeSEric Cheng &state->gs_prevstats[i]); 28857c478bd9Sstevel@tonic-gate } 28867c478bd9Sstevel@tonic-gate 2887e7801d59Ssowmini if (!state->gs_parseable && !state->gs_printheader) { 2888e7801d59Ssowmini print_header(&state->gs_print); 2889e7801d59Ssowmini state->gs_printheader = B_TRUE; 2890e7801d59Ssowmini } 2891e7801d59Ssowmini 2892e7801d59Ssowmini largs.laggr_lport = -1; 2893e7801d59Ssowmini largs.laggr_link = link; 2894e7801d59Ssowmini largs.laggr_ginfop = ginfop; 2895e7801d59Ssowmini largs.laggr_status = &status; 2896e7801d59Ssowmini largs.laggr_pktsumtot = &pktsumtot; 2897e7801d59Ssowmini 2898e7801d59Ssowmini dladm_print_output(&state->gs_print, state->gs_parseable, 2899e7801d59Ssowmini print_aggr_stats_callback, &largs); 2900e7801d59Ssowmini 2901e7801d59Ssowmini if (status != DLADM_STATUS_OK) 2902e7801d59Ssowmini goto done; 2903d62bc4baSyz147064 2904d62bc4baSyz147064 for (i = 0; i < ginfop->lg_nports; i++) { 2905e7801d59Ssowmini largs.laggr_lport = i; 2906e7801d59Ssowmini largs.laggr_prevstats = &state->gs_prevstats[i]; 2907e7801d59Ssowmini dladm_print_output(&state->gs_print, state->gs_parseable, 2908e7801d59Ssowmini print_aggr_stats_callback, &largs); 2909e7801d59Ssowmini if (status != DLADM_STATUS_OK) 2910d62bc4baSyz147064 goto done; 2911d62bc4baSyz147064 } 2912d62bc4baSyz147064 2913d62bc4baSyz147064 status = DLADM_STATUS_OK; 2914d62bc4baSyz147064 done: 2915d62bc4baSyz147064 return (status); 2916d62bc4baSyz147064 } 2917d62bc4baSyz147064 2918d62bc4baSyz147064 static dladm_status_t 2919e7801d59Ssowmini print_aggr(show_grp_state_t *state, datalink_id_t linkid) 2920d62bc4baSyz147064 { 2921d62bc4baSyz147064 char link[MAXLINKNAMELEN]; 2922d62bc4baSyz147064 dladm_aggr_grp_attr_t ginfo; 2923d62bc4baSyz147064 uint32_t flags; 2924d62bc4baSyz147064 dladm_status_t status; 2925d62bc4baSyz147064 29265f5c9f54SAnurag S. Maskey bzero(&ginfo, sizeof (dladm_aggr_grp_attr_t)); 29274ac67f02SAnurag S. Maskey if ((status = dladm_datalink_id2info(handle, linkid, &flags, NULL, 29284ac67f02SAnurag S. Maskey NULL, link, MAXLINKNAMELEN)) != DLADM_STATUS_OK) { 2929d62bc4baSyz147064 return (status); 2930d62bc4baSyz147064 } 2931d62bc4baSyz147064 2932d62bc4baSyz147064 if (!(state->gs_flags & flags)) 2933d62bc4baSyz147064 return (DLADM_STATUS_NOTFOUND); 2934d62bc4baSyz147064 29354ac67f02SAnurag S. Maskey status = dladm_aggr_info(handle, linkid, &ginfo, state->gs_flags); 2936d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 2937d62bc4baSyz147064 return (status); 2938d62bc4baSyz147064 2939d62bc4baSyz147064 if (state->gs_lacp) 2940e7801d59Ssowmini status = print_aggr_lacp(state, link, &ginfo); 2941d62bc4baSyz147064 else if (state->gs_extended) 2942e7801d59Ssowmini status = print_aggr_extended(state, link, &ginfo); 2943d62bc4baSyz147064 else if (state->gs_stats) 2944e7801d59Ssowmini status = print_aggr_stats(state, link, &ginfo); 29454ac67f02SAnurag S. Maskey else 2946e7801d59Ssowmini status = print_aggr_info(state, link, &ginfo); 2947d62bc4baSyz147064 2948d62bc4baSyz147064 done: 2949d62bc4baSyz147064 free(ginfo.lg_ports); 2950d62bc4baSyz147064 return (status); 2951d62bc4baSyz147064 } 2952d62bc4baSyz147064 29534ac67f02SAnurag S. Maskey /* ARGSUSED */ 2954d62bc4baSyz147064 static int 29554ac67f02SAnurag S. Maskey show_aggr(dladm_handle_t dh, datalink_id_t linkid, void *arg) 2956d62bc4baSyz147064 { 2957d62bc4baSyz147064 show_grp_state_t *state = arg; 2958d62bc4baSyz147064 dladm_status_t status; 2959d62bc4baSyz147064 29604ac67f02SAnurag S. Maskey if ((status = print_aggr(state, linkid)) != DLADM_STATUS_OK) 2961d62bc4baSyz147064 goto done; 2962d62bc4baSyz147064 2963d62bc4baSyz147064 done: 2964d62bc4baSyz147064 state->gs_status = status; 2965d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 29667c478bd9Sstevel@tonic-gate } 29677c478bd9Sstevel@tonic-gate 29687c478bd9Sstevel@tonic-gate static void 29698d5c46e6Sam223141 do_show_link(int argc, char *argv[], const char *use) 29707c478bd9Sstevel@tonic-gate { 29717c478bd9Sstevel@tonic-gate int option; 29727c478bd9Sstevel@tonic-gate boolean_t s_arg = B_FALSE; 2973da14cebeSEric Cheng boolean_t S_arg = B_FALSE; 29747c478bd9Sstevel@tonic-gate boolean_t i_arg = B_FALSE; 2975d62bc4baSyz147064 uint32_t flags = DLADM_OPT_ACTIVE; 2976d62bc4baSyz147064 boolean_t p_arg = B_FALSE; 2977d62bc4baSyz147064 datalink_id_t linkid = DATALINK_ALL_LINKID; 2978da14cebeSEric Cheng char linkname[MAXLINKNAMELEN]; 297933343a97Smeem int interval = 0; 2980d62bc4baSyz147064 show_state_t state; 2981d62bc4baSyz147064 dladm_status_t status; 2982e7801d59Ssowmini boolean_t o_arg = B_FALSE; 2983e7801d59Ssowmini char *fields_str = NULL; 2984e7801d59Ssowmini print_field_t **fields; 2985e7801d59Ssowmini uint_t nfields; 2986e7801d59Ssowmini char *all_active_fields = "link,class,mtu,state,over"; 2987e7801d59Ssowmini char *all_inactive_fields = "link,class,over"; 29886be03d0bSVasumathi Sundaram - Sun Microsystems char *allstat_fields = 29896be03d0bSVasumathi Sundaram - Sun Microsystems "link,ipackets,rbytes,ierrors,opackets,obytes,oerrors"; 2990e7801d59Ssowmini 2991e7801d59Ssowmini bzero(&state, sizeof (state)); 29927c478bd9Sstevel@tonic-gate 29937c478bd9Sstevel@tonic-gate opterr = 0; 2994da14cebeSEric Cheng while ((option = getopt_long(argc, argv, ":pPsSi:o:", 2995d62bc4baSyz147064 show_lopts, NULL)) != -1) { 29967c478bd9Sstevel@tonic-gate switch (option) { 29977c478bd9Sstevel@tonic-gate case 'p': 2998d62bc4baSyz147064 if (p_arg) 2999d62bc4baSyz147064 die_optdup(option); 3000d62bc4baSyz147064 3001d62bc4baSyz147064 p_arg = B_TRUE; 30027c478bd9Sstevel@tonic-gate break; 30037c478bd9Sstevel@tonic-gate case 's': 300433343a97Smeem if (s_arg) 300533343a97Smeem die_optdup(option); 30067c478bd9Sstevel@tonic-gate 30077c478bd9Sstevel@tonic-gate s_arg = B_TRUE; 30087c478bd9Sstevel@tonic-gate break; 3009d62bc4baSyz147064 case 'P': 3010d62bc4baSyz147064 if (flags != DLADM_OPT_ACTIVE) 3011d62bc4baSyz147064 die_optdup(option); 3012d62bc4baSyz147064 3013d62bc4baSyz147064 flags = DLADM_OPT_PERSIST; 3014d62bc4baSyz147064 break; 3015da14cebeSEric Cheng case 'S': 3016da14cebeSEric Cheng if (S_arg) 3017da14cebeSEric Cheng die_optdup(option); 3018da14cebeSEric Cheng 3019da14cebeSEric Cheng S_arg = B_TRUE; 3020da14cebeSEric Cheng break; 3021e7801d59Ssowmini case 'o': 3022e7801d59Ssowmini o_arg = B_TRUE; 3023e7801d59Ssowmini fields_str = optarg; 3024e7801d59Ssowmini break; 30257c478bd9Sstevel@tonic-gate case 'i': 302633343a97Smeem if (i_arg) 302733343a97Smeem die_optdup(option); 30287c478bd9Sstevel@tonic-gate 30297c478bd9Sstevel@tonic-gate i_arg = B_TRUE; 303033343a97Smeem if (!str2int(optarg, &interval) || interval == 0) 303133343a97Smeem die("invalid interval value '%s'", optarg); 30327c478bd9Sstevel@tonic-gate break; 30337c478bd9Sstevel@tonic-gate default: 30348d5c46e6Sam223141 die_opterr(optopt, option, use); 303533343a97Smeem break; 30367c478bd9Sstevel@tonic-gate } 30377c478bd9Sstevel@tonic-gate } 30387c478bd9Sstevel@tonic-gate 3039da14cebeSEric Cheng if (i_arg && !(s_arg || S_arg)) 3040da14cebeSEric Cheng die("the option -i can be used only with -s or -S"); 3041da14cebeSEric Cheng 3042da14cebeSEric Cheng if (s_arg && S_arg) 3043da14cebeSEric Cheng die("the -s option cannot be used with -S"); 30447c478bd9Sstevel@tonic-gate 30456be03d0bSVasumathi Sundaram - Sun Microsystems if (s_arg && flags != DLADM_OPT_ACTIVE) 30466be03d0bSVasumathi Sundaram - Sun Microsystems die("the option -P cannot be used with -s"); 3047d62bc4baSyz147064 3048da14cebeSEric Cheng if (S_arg && (p_arg || flags != DLADM_OPT_ACTIVE)) 3049da14cebeSEric Cheng die("the option -%c cannot be used with -S", p_arg ? 'p' : 'P'); 3050da14cebeSEric Cheng 30517c478bd9Sstevel@tonic-gate /* get link name (optional last argument) */ 3052d62bc4baSyz147064 if (optind == (argc-1)) { 3053d62bc4baSyz147064 uint32_t f; 3054d62bc4baSyz147064 3055da14cebeSEric Cheng if (strlcpy(linkname, argv[optind], MAXLINKNAMELEN) 3056da14cebeSEric Cheng >= MAXLINKNAMELEN) { 3057da14cebeSEric Cheng (void) fprintf(stderr, 3058da14cebeSEric Cheng gettext("%s: link name too long\n"), 3059da14cebeSEric Cheng progname); 30604ac67f02SAnurag S. Maskey dladm_close(handle); 3061da14cebeSEric Cheng exit(1); 3062da14cebeSEric Cheng } 30634ac67f02SAnurag S. Maskey if ((status = dladm_name2info(handle, linkname, &linkid, &f, 3064d62bc4baSyz147064 NULL, NULL)) != DLADM_STATUS_OK) { 3065da14cebeSEric Cheng die_dlerr(status, "link %s is not valid", linkname); 3066d62bc4baSyz147064 } 3067d62bc4baSyz147064 3068d62bc4baSyz147064 if (!(f & flags)) { 3069d62bc4baSyz147064 die_dlerr(DLADM_STATUS_BADARG, "link %s is %s", 3070d62bc4baSyz147064 argv[optind], flags == DLADM_OPT_PERSIST ? 3071d62bc4baSyz147064 "a temporary link" : "temporarily removed"); 3072d62bc4baSyz147064 } 3073d62bc4baSyz147064 } else if (optind != argc) { 30747c478bd9Sstevel@tonic-gate usage(); 3075d62bc4baSyz147064 } 30767c478bd9Sstevel@tonic-gate 30770d365605Sschuster if (p_arg && !o_arg) 30780d365605Sschuster die("-p requires -o"); 30790d365605Sschuster 3080da14cebeSEric Cheng if (S_arg) { 30814ac67f02SAnurag S. Maskey dladm_continuous(handle, linkid, NULL, interval, LINK_REPORT); 3082da14cebeSEric Cheng return; 3083da14cebeSEric Cheng } 3084da14cebeSEric Cheng 30850d365605Sschuster if (p_arg && strcasecmp(fields_str, "all") == 0) 30860d365605Sschuster die("\"-o all\" is invalid with -p"); 30870d365605Sschuster 3088e7801d59Ssowmini if (!o_arg || (o_arg && strcasecmp(fields_str, "all") == 0)) { 30896be03d0bSVasumathi Sundaram - Sun Microsystems if (s_arg) 30906be03d0bSVasumathi Sundaram - Sun Microsystems fields_str = allstat_fields; 30916be03d0bSVasumathi Sundaram - Sun Microsystems else if (flags & DLADM_OPT_ACTIVE) 3092e7801d59Ssowmini fields_str = all_active_fields; 3093e7801d59Ssowmini else 3094e7801d59Ssowmini fields_str = all_inactive_fields; 3095e7801d59Ssowmini } 3096e7801d59Ssowmini 30976be03d0bSVasumathi Sundaram - Sun Microsystems state.ls_parseable = p_arg; 30986be03d0bSVasumathi Sundaram - Sun Microsystems state.ls_flags = flags; 30996be03d0bSVasumathi Sundaram - Sun Microsystems state.ls_donefirst = B_FALSE; 31006be03d0bSVasumathi Sundaram - Sun Microsystems 31016be03d0bSVasumathi Sundaram - Sun Microsystems if (s_arg) { 31026be03d0bSVasumathi Sundaram - Sun Microsystems link_stats(linkid, interval, fields_str, &state); 31036be03d0bSVasumathi Sundaram - Sun Microsystems return; 31046be03d0bSVasumathi Sundaram - Sun Microsystems } 31056be03d0bSVasumathi Sundaram - Sun Microsystems 3106e7801d59Ssowmini fields = parse_output_fields(fields_str, link_fields, DEV_LINK_FIELDS, 3107e7801d59Ssowmini CMD_TYPE_ANY, &nfields); 3108e7801d59Ssowmini 31090d365605Sschuster if (fields == NULL) 3110e7801d59Ssowmini die("invalid field(s) specified"); 3111e7801d59Ssowmini 3112e7801d59Ssowmini state.ls_print.ps_fields = fields; 3113e7801d59Ssowmini state.ls_print.ps_nfields = nfields; 3114e7801d59Ssowmini 3115d62bc4baSyz147064 if (linkid == DATALINK_ALL_LINKID) { 31164ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(show_link, handle, &state, 3117d62bc4baSyz147064 DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE, flags); 3118210db224Sericheng } else { 31194ac67f02SAnurag S. Maskey (void) show_link(handle, linkid, &state); 3120d62bc4baSyz147064 if (state.ls_status != DLADM_STATUS_OK) { 3121d62bc4baSyz147064 die_dlerr(state.ls_status, "failed to show link %s", 3122d62bc4baSyz147064 argv[optind]); 3123d62bc4baSyz147064 } 31247c478bd9Sstevel@tonic-gate } 3125210db224Sericheng } 31267c478bd9Sstevel@tonic-gate 31277c478bd9Sstevel@tonic-gate static void 31288d5c46e6Sam223141 do_show_aggr(int argc, char *argv[], const char *use) 31297c478bd9Sstevel@tonic-gate { 31307c478bd9Sstevel@tonic-gate boolean_t L_arg = B_FALSE; 31317c478bd9Sstevel@tonic-gate boolean_t s_arg = B_FALSE; 31327c478bd9Sstevel@tonic-gate boolean_t i_arg = B_FALSE; 3133d62bc4baSyz147064 boolean_t p_arg = B_FALSE; 3134d62bc4baSyz147064 boolean_t x_arg = B_FALSE; 31357c478bd9Sstevel@tonic-gate show_grp_state_t state; 3136d62bc4baSyz147064 uint32_t flags = DLADM_OPT_ACTIVE; 3137d62bc4baSyz147064 datalink_id_t linkid = DATALINK_ALL_LINKID; 3138d62bc4baSyz147064 int option; 313933343a97Smeem int interval = 0; 3140d62bc4baSyz147064 int key; 3141d62bc4baSyz147064 dladm_status_t status; 3142e7801d59Ssowmini boolean_t o_arg = B_FALSE; 3143e7801d59Ssowmini char *fields_str = NULL; 3144e7801d59Ssowmini print_field_t **fields; 3145e7801d59Ssowmini uint_t nfields; 3146e7801d59Ssowmini char *all_fields = 3147e7801d59Ssowmini "link,policy,addrpolicy,lacpactivity,lacptimer,flags"; 3148e7801d59Ssowmini char *all_lacp_fields = 3149e7801d59Ssowmini "link,port,aggregatable,sync,coll,dist,defaulted,expired"; 3150e7801d59Ssowmini char *all_stats_fields = 3151e7801d59Ssowmini "link,port,ipackets,rbytes,opackets,obytes,ipktdist,opktdist"; 3152e7801d59Ssowmini char *all_extended_fields = 3153e7801d59Ssowmini "link,port,speed,duplex,state,address,portstate"; 3154e7801d59Ssowmini print_field_t *pf; 3155e7801d59Ssowmini int pfmax; 3156e7801d59Ssowmini 3157e7801d59Ssowmini bzero(&state, sizeof (state)); 31587c478bd9Sstevel@tonic-gate 31597c478bd9Sstevel@tonic-gate opterr = 0; 3160e7801d59Ssowmini while ((option = getopt_long(argc, argv, ":LpPxsi:o:", 3161d62bc4baSyz147064 show_lopts, NULL)) != -1) { 31627c478bd9Sstevel@tonic-gate switch (option) { 31637c478bd9Sstevel@tonic-gate case 'L': 316433343a97Smeem if (L_arg) 316533343a97Smeem die_optdup(option); 31667c478bd9Sstevel@tonic-gate 31677c478bd9Sstevel@tonic-gate L_arg = B_TRUE; 31687c478bd9Sstevel@tonic-gate break; 31697c478bd9Sstevel@tonic-gate case 'p': 3170d62bc4baSyz147064 if (p_arg) 3171d62bc4baSyz147064 die_optdup(option); 3172d62bc4baSyz147064 3173d62bc4baSyz147064 p_arg = B_TRUE; 3174d62bc4baSyz147064 break; 3175d62bc4baSyz147064 case 'x': 3176d62bc4baSyz147064 if (x_arg) 3177d62bc4baSyz147064 die_optdup(option); 3178d62bc4baSyz147064 3179d62bc4baSyz147064 x_arg = B_TRUE; 3180d62bc4baSyz147064 break; 3181d62bc4baSyz147064 case 'P': 3182d62bc4baSyz147064 if (flags != DLADM_OPT_ACTIVE) 3183d62bc4baSyz147064 die_optdup(option); 3184d62bc4baSyz147064 3185d62bc4baSyz147064 flags = DLADM_OPT_PERSIST; 31867c478bd9Sstevel@tonic-gate break; 31877c478bd9Sstevel@tonic-gate case 's': 318833343a97Smeem if (s_arg) 318933343a97Smeem die_optdup(option); 31907c478bd9Sstevel@tonic-gate 31917c478bd9Sstevel@tonic-gate s_arg = B_TRUE; 31927c478bd9Sstevel@tonic-gate break; 3193e7801d59Ssowmini case 'o': 3194e7801d59Ssowmini o_arg = B_TRUE; 3195e7801d59Ssowmini fields_str = optarg; 3196e7801d59Ssowmini break; 31977c478bd9Sstevel@tonic-gate case 'i': 319833343a97Smeem if (i_arg) 319933343a97Smeem die_optdup(option); 32007c478bd9Sstevel@tonic-gate 32017c478bd9Sstevel@tonic-gate i_arg = B_TRUE; 320233343a97Smeem if (!str2int(optarg, &interval) || interval == 0) 320333343a97Smeem die("invalid interval value '%s'", optarg); 32047c478bd9Sstevel@tonic-gate break; 32057c478bd9Sstevel@tonic-gate default: 32068d5c46e6Sam223141 die_opterr(optopt, option, use); 320733343a97Smeem break; 32087c478bd9Sstevel@tonic-gate } 32097c478bd9Sstevel@tonic-gate } 32107c478bd9Sstevel@tonic-gate 32110d365605Sschuster if (p_arg && !o_arg) 32120d365605Sschuster die("-p requires -o"); 32130d365605Sschuster 32140d365605Sschuster if (p_arg && strcasecmp(fields_str, "all") == 0) 32150d365605Sschuster die("\"-o all\" is invalid with -p"); 32160d365605Sschuster 321733343a97Smeem if (i_arg && !s_arg) 321833343a97Smeem die("the option -i can be used only with -s"); 32197c478bd9Sstevel@tonic-gate 3220d62bc4baSyz147064 if (s_arg && (L_arg || p_arg || x_arg || flags != DLADM_OPT_ACTIVE)) { 3221d62bc4baSyz147064 die("the option -%c cannot be used with -s", 3222d62bc4baSyz147064 L_arg ? 'L' : (p_arg ? 'p' : (x_arg ? 'x' : 'P'))); 3223d62bc4baSyz147064 } 3224d62bc4baSyz147064 3225d62bc4baSyz147064 if (L_arg && flags != DLADM_OPT_ACTIVE) 3226d62bc4baSyz147064 die("the option -P cannot be used with -L"); 3227d62bc4baSyz147064 3228d62bc4baSyz147064 if (x_arg && (L_arg || flags != DLADM_OPT_ACTIVE)) 3229d62bc4baSyz147064 die("the option -%c cannot be used with -x", L_arg ? 'L' : 'P'); 3230d62bc4baSyz147064 3231d62bc4baSyz147064 /* get aggregation key or aggrname (optional last argument) */ 32327c478bd9Sstevel@tonic-gate if (optind == (argc-1)) { 3233d62bc4baSyz147064 if (!str2int(argv[optind], &key)) { 32344ac67f02SAnurag S. Maskey status = dladm_name2info(handle, argv[optind], 32354ac67f02SAnurag S. Maskey &linkid, NULL, NULL, NULL); 3236d62bc4baSyz147064 } else { 32374ac67f02SAnurag S. Maskey status = dladm_key2linkid(handle, (uint16_t)key, 3238d62bc4baSyz147064 &linkid, DLADM_OPT_ACTIVE); 3239d62bc4baSyz147064 } 3240d62bc4baSyz147064 3241d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 3242d62bc4baSyz147064 die("non-existent aggregation '%s'", argv[optind]); 3243d62bc4baSyz147064 32447c478bd9Sstevel@tonic-gate } else if (optind != argc) { 32457c478bd9Sstevel@tonic-gate usage(); 32467c478bd9Sstevel@tonic-gate } 32477c478bd9Sstevel@tonic-gate 3248d62bc4baSyz147064 bzero(&state, sizeof (state)); 3249d62bc4baSyz147064 state.gs_lacp = L_arg; 3250d62bc4baSyz147064 state.gs_stats = s_arg; 3251d62bc4baSyz147064 state.gs_flags = flags; 3252d62bc4baSyz147064 state.gs_parseable = p_arg; 3253d62bc4baSyz147064 state.gs_extended = x_arg; 3254d62bc4baSyz147064 3255e7801d59Ssowmini if (!o_arg || (o_arg && strcasecmp(fields_str, "all") == 0)) { 3256e7801d59Ssowmini if (state.gs_lacp) 3257e7801d59Ssowmini fields_str = all_lacp_fields; 3258e7801d59Ssowmini else if (state.gs_stats) 3259e7801d59Ssowmini fields_str = all_stats_fields; 3260e7801d59Ssowmini else if (state.gs_extended) 3261e7801d59Ssowmini fields_str = all_extended_fields; 3262e7801d59Ssowmini else 3263e7801d59Ssowmini fields_str = all_fields; 3264e7801d59Ssowmini } 3265e7801d59Ssowmini 3266e7801d59Ssowmini if (state.gs_lacp) { 3267e7801d59Ssowmini pf = aggr_l_fields; 3268e7801d59Ssowmini pfmax = AGGR_L_MAX_FIELDS; 3269e7801d59Ssowmini } else if (state.gs_stats) { 3270e7801d59Ssowmini pf = aggr_s_fields; 3271e7801d59Ssowmini pfmax = AGGR_S_MAX_FIELDS; 3272e7801d59Ssowmini } else if (state.gs_extended) { 3273e7801d59Ssowmini pf = aggr_x_fields; 3274e7801d59Ssowmini pfmax = AGGR_X_MAX_FIELDS; 3275e7801d59Ssowmini } else { 3276e7801d59Ssowmini pf = laggr_fields; 3277e7801d59Ssowmini pfmax = LAGGR_MAX_FIELDS; 3278e7801d59Ssowmini } 3279e7801d59Ssowmini fields = parse_output_fields(fields_str, pf, pfmax, CMD_TYPE_ANY, 3280e7801d59Ssowmini &nfields); 3281e7801d59Ssowmini 3282e7801d59Ssowmini if (fields == NULL) { 3283e7801d59Ssowmini die("invalid field(s) specified"); 3284e7801d59Ssowmini return; 3285e7801d59Ssowmini } 3286e7801d59Ssowmini 3287e7801d59Ssowmini state.gs_print.ps_fields = fields; 3288e7801d59Ssowmini state.gs_print.ps_nfields = nfields; 3289e7801d59Ssowmini 32907c478bd9Sstevel@tonic-gate if (s_arg) { 3291d62bc4baSyz147064 aggr_stats(linkid, &state, interval); 32927c478bd9Sstevel@tonic-gate return; 32937c478bd9Sstevel@tonic-gate } 32947c478bd9Sstevel@tonic-gate 3295d62bc4baSyz147064 if (linkid == DATALINK_ALL_LINKID) { 32964ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(show_aggr, handle, &state, 3297d62bc4baSyz147064 DATALINK_CLASS_AGGR, DATALINK_ANY_MEDIATYPE, flags); 3298d62bc4baSyz147064 } else { 32994ac67f02SAnurag S. Maskey (void) show_aggr(handle, linkid, &state); 3300d62bc4baSyz147064 if (state.gs_status != DLADM_STATUS_OK) { 3301d62bc4baSyz147064 die_dlerr(state.gs_status, "failed to show aggr %s", 3302d62bc4baSyz147064 argv[optind]); 3303d62bc4baSyz147064 } 3304d62bc4baSyz147064 } 33057c478bd9Sstevel@tonic-gate } 33067c478bd9Sstevel@tonic-gate 3307da14cebeSEric Cheng static dladm_status_t 3308da14cebeSEric Cheng print_phys_default(show_state_t *state, datalink_id_t linkid, 3309da14cebeSEric Cheng const char *link, uint32_t flags, uint32_t media) 33107c478bd9Sstevel@tonic-gate { 3311da14cebeSEric Cheng dladm_phys_attr_t dpa; 3312da14cebeSEric Cheng dladm_status_t status; 3313da14cebeSEric Cheng link_fields_buf_t pattr; 3314e7801d59Ssowmini 33154ac67f02SAnurag S. Maskey status = dladm_phys_info(handle, linkid, &dpa, state->ls_flags); 3316da14cebeSEric Cheng if (status != DLADM_STATUS_OK) 3317da14cebeSEric Cheng goto done; 33187c478bd9Sstevel@tonic-gate 3319da14cebeSEric Cheng (void) snprintf(pattr.link_phys_device, 3320da14cebeSEric Cheng sizeof (pattr.link_phys_device), "%s", dpa.dp_dev); 3321da14cebeSEric Cheng (void) dladm_media2str(media, pattr.link_phys_media); 3322da14cebeSEric Cheng if (state->ls_flags == DLADM_OPT_ACTIVE) { 3323da14cebeSEric Cheng boolean_t islink; 3324d62bc4baSyz147064 3325da14cebeSEric Cheng if (!dpa.dp_novanity) { 3326da14cebeSEric Cheng (void) strlcpy(pattr.link_name, link, 3327da14cebeSEric Cheng sizeof (pattr.link_name)); 3328da14cebeSEric Cheng islink = B_TRUE; 3329d62bc4baSyz147064 } else { 3330da14cebeSEric Cheng /* 3331da14cebeSEric Cheng * This is a physical link that does not have 3332da14cebeSEric Cheng * vanity naming support. 3333da14cebeSEric Cheng */ 3334da14cebeSEric Cheng (void) strlcpy(pattr.link_name, dpa.dp_dev, 3335da14cebeSEric Cheng sizeof (pattr.link_name)); 3336da14cebeSEric Cheng islink = B_FALSE; 33377c478bd9Sstevel@tonic-gate } 33387c478bd9Sstevel@tonic-gate 3339da14cebeSEric Cheng (void) get_linkstate(pattr.link_name, islink, 3340da14cebeSEric Cheng pattr.link_phys_state); 3341da14cebeSEric Cheng (void) snprintf(pattr.link_phys_speed, 3342da14cebeSEric Cheng sizeof (pattr.link_phys_speed), "%u", 3343da14cebeSEric Cheng (uint_t)((get_ifspeed(pattr.link_name, 3344da14cebeSEric Cheng islink)) / 1000000ull)); 3345da14cebeSEric Cheng (void) get_linkduplex(pattr.link_name, islink, 3346da14cebeSEric Cheng pattr.link_phys_duplex); 3347da14cebeSEric Cheng } else { 3348da14cebeSEric Cheng (void) snprintf(pattr.link_name, sizeof (pattr.link_name), 3349da14cebeSEric Cheng "%s", link); 3350da14cebeSEric Cheng (void) snprintf(pattr.link_flags, sizeof (pattr.link_flags), 3351da14cebeSEric Cheng "%c----", flags & DLADM_OPT_ACTIVE ? '-' : 'r'); 3352da14cebeSEric Cheng } 3353da14cebeSEric Cheng 3354da14cebeSEric Cheng if (!state->ls_parseable && !state->ls_printheader) { 3355da14cebeSEric Cheng print_header(&state->ls_print); 3356da14cebeSEric Cheng state->ls_printheader = B_TRUE; 3357da14cebeSEric Cheng } 3358da14cebeSEric Cheng 3359da14cebeSEric Cheng dladm_print_output(&state->ls_print, state->ls_parseable, 3360da14cebeSEric Cheng dladm_print_field, (void *)&pattr); 3361da14cebeSEric Cheng 3362da14cebeSEric Cheng done: 3363da14cebeSEric Cheng return (status); 3364da14cebeSEric Cheng } 3365da14cebeSEric Cheng 3366da14cebeSEric Cheng typedef struct { 3367da14cebeSEric Cheng show_state_t *ms_state; 3368da14cebeSEric Cheng char *ms_link; 3369da14cebeSEric Cheng dladm_macaddr_attr_t *ms_mac_attr; 3370da14cebeSEric Cheng } print_phys_mac_state_t; 3371da14cebeSEric Cheng 3372da14cebeSEric Cheng /* callback of dladm_print_output() */ 3373da14cebeSEric Cheng static char * 3374da14cebeSEric Cheng print_phys_one_mac_callback(print_field_t *pf, void *arg) 3375da14cebeSEric Cheng { 3376da14cebeSEric Cheng print_phys_mac_state_t *mac_state = arg; 3377da14cebeSEric Cheng dladm_macaddr_attr_t *attr = mac_state->ms_mac_attr; 3378da14cebeSEric Cheng static char buf[DLADM_STRSIZE]; 3379da14cebeSEric Cheng boolean_t is_primary = (attr->ma_slot == 0); 3380da14cebeSEric Cheng boolean_t is_parseable = mac_state->ms_state->ls_parseable; 3381da14cebeSEric Cheng 3382da14cebeSEric Cheng switch (pf->pf_index) { 3383da14cebeSEric Cheng case PHYS_M_LINK: 3384da14cebeSEric Cheng (void) snprintf(buf, sizeof (buf), "%s", 3385da14cebeSEric Cheng (is_primary || is_parseable) ? mac_state->ms_link : " "); 3386da14cebeSEric Cheng break; 3387da14cebeSEric Cheng case PHYS_M_SLOT: 3388da14cebeSEric Cheng if (is_primary) 3389da14cebeSEric Cheng (void) snprintf(buf, sizeof (buf), gettext("primary")); 3390da14cebeSEric Cheng else 3391da14cebeSEric Cheng (void) snprintf(buf, sizeof (buf), "%d", attr->ma_slot); 3392da14cebeSEric Cheng break; 3393da14cebeSEric Cheng case PHYS_M_ADDRESS: 3394da14cebeSEric Cheng (void) dladm_aggr_macaddr2str(attr->ma_addr, buf); 3395da14cebeSEric Cheng break; 3396da14cebeSEric Cheng case PHYS_M_INUSE: 3397da14cebeSEric Cheng (void) snprintf(buf, sizeof (buf), "%s", 3398da14cebeSEric Cheng attr->ma_flags & DLADM_MACADDR_USED ? gettext("yes") : 3399da14cebeSEric Cheng gettext("no")); 3400da14cebeSEric Cheng break; 3401da14cebeSEric Cheng case PHYS_M_CLIENT: 3402da14cebeSEric Cheng /* 3403da14cebeSEric Cheng * CR 6678526: resolve link id to actual link name if 3404da14cebeSEric Cheng * it is valid. 3405da14cebeSEric Cheng */ 3406da14cebeSEric Cheng (void) snprintf(buf, sizeof (buf), "%s", attr->ma_client_name); 3407da14cebeSEric Cheng break; 3408da14cebeSEric Cheng } 3409da14cebeSEric Cheng 3410da14cebeSEric Cheng return (buf); 3411da14cebeSEric Cheng } 3412da14cebeSEric Cheng 3413da14cebeSEric Cheng typedef struct { 3414da14cebeSEric Cheng show_state_t *hs_state; 3415da14cebeSEric Cheng char *hs_link; 3416da14cebeSEric Cheng dladm_hwgrp_attr_t *hs_grp_attr; 3417da14cebeSEric Cheng } print_phys_hwgrp_state_t; 3418da14cebeSEric Cheng 3419da14cebeSEric Cheng static char * 3420da14cebeSEric Cheng print_phys_one_hwgrp_callback(print_field_t *pf, void *arg) 3421da14cebeSEric Cheng { 3422da14cebeSEric Cheng print_phys_hwgrp_state_t *hg_state = arg; 3423da14cebeSEric Cheng dladm_hwgrp_attr_t *attr = hg_state->hs_grp_attr; 3424da14cebeSEric Cheng static char buf[DLADM_STRSIZE]; 3425da14cebeSEric Cheng 3426da14cebeSEric Cheng switch (pf->pf_index) { 3427da14cebeSEric Cheng case PHYS_H_LINK: 3428da14cebeSEric Cheng (void) snprintf(buf, sizeof (buf), "%s", attr->hg_link_name); 3429da14cebeSEric Cheng break; 3430da14cebeSEric Cheng case PHYS_H_GROUP: 3431da14cebeSEric Cheng (void) snprintf(buf, sizeof (buf), "%d", attr->hg_grp_num); 3432da14cebeSEric Cheng break; 3433da14cebeSEric Cheng case PHYS_H_GRPTYPE: 3434da14cebeSEric Cheng (void) snprintf(buf, sizeof (buf), "%s", 3435da14cebeSEric Cheng attr->hg_grp_type == DLADM_HWGRP_TYPE_RX ? "RX" : "TX"); 3436da14cebeSEric Cheng break; 3437da14cebeSEric Cheng case PHYS_H_RINGS: 3438da14cebeSEric Cheng (void) snprintf(buf, sizeof (buf), "%d", attr->hg_n_rings); 3439da14cebeSEric Cheng break; 3440da14cebeSEric Cheng case PHYS_H_CLIENTS: 3441da14cebeSEric Cheng if (attr->hg_client_names[0] == '\0') { 3442da14cebeSEric Cheng (void) snprintf(buf, sizeof (buf), "--"); 3443da14cebeSEric Cheng } else { 3444da14cebeSEric Cheng (void) snprintf(buf, sizeof (buf), "%s ", 3445da14cebeSEric Cheng attr->hg_client_names); 3446da14cebeSEric Cheng } 3447da14cebeSEric Cheng break; 3448da14cebeSEric Cheng } 3449da14cebeSEric Cheng 3450da14cebeSEric Cheng return (buf); 3451da14cebeSEric Cheng } 3452da14cebeSEric Cheng 3453da14cebeSEric Cheng /* callback of dladm_walk_macaddr, invoked for each MAC address slot */ 3454da14cebeSEric Cheng static boolean_t 3455da14cebeSEric Cheng print_phys_mac_callback(void *arg, dladm_macaddr_attr_t *attr) 3456da14cebeSEric Cheng { 3457da14cebeSEric Cheng print_phys_mac_state_t *mac_state = arg; 3458da14cebeSEric Cheng show_state_t *state = mac_state->ms_state; 3459da14cebeSEric Cheng 3460da14cebeSEric Cheng if (!state->ls_parseable && !state->ls_printheader) { 3461da14cebeSEric Cheng print_header(&state->ls_print); 3462da14cebeSEric Cheng state->ls_printheader = B_TRUE; 3463da14cebeSEric Cheng } 3464da14cebeSEric Cheng 3465da14cebeSEric Cheng mac_state->ms_mac_attr = attr; 3466da14cebeSEric Cheng dladm_print_output(&state->ls_print, state->ls_parseable, 3467da14cebeSEric Cheng print_phys_one_mac_callback, mac_state); 3468da14cebeSEric Cheng 3469da14cebeSEric Cheng return (B_TRUE); 3470da14cebeSEric Cheng } 3471da14cebeSEric Cheng 3472da14cebeSEric Cheng /* invoked by show-phys -m for each physical data-link */ 3473da14cebeSEric Cheng static dladm_status_t 3474da14cebeSEric Cheng print_phys_mac(show_state_t *state, datalink_id_t linkid, char *link) 3475da14cebeSEric Cheng { 3476da14cebeSEric Cheng print_phys_mac_state_t mac_state; 3477da14cebeSEric Cheng 3478da14cebeSEric Cheng mac_state.ms_state = state; 3479da14cebeSEric Cheng mac_state.ms_link = link; 3480da14cebeSEric Cheng 34814ac67f02SAnurag S. Maskey return (dladm_walk_macaddr(handle, linkid, &mac_state, 3482da14cebeSEric Cheng print_phys_mac_callback)); 3483da14cebeSEric Cheng } 3484da14cebeSEric Cheng 3485da14cebeSEric Cheng /* callback of dladm_walk_hwgrp, invoked for each MAC hwgrp */ 3486da14cebeSEric Cheng static boolean_t 3487da14cebeSEric Cheng print_phys_hwgrp_callback(void *arg, dladm_hwgrp_attr_t *attr) 3488da14cebeSEric Cheng { 3489da14cebeSEric Cheng print_phys_hwgrp_state_t *hwgrp_state = arg; 3490da14cebeSEric Cheng show_state_t *state = hwgrp_state->hs_state; 3491da14cebeSEric Cheng 3492da14cebeSEric Cheng if (!state->ls_parseable && !state->ls_printheader) { 3493da14cebeSEric Cheng print_header(&state->ls_print); 3494da14cebeSEric Cheng state->ls_printheader = B_TRUE; 3495da14cebeSEric Cheng } 3496da14cebeSEric Cheng hwgrp_state->hs_grp_attr = attr; 3497da14cebeSEric Cheng dladm_print_output(&state->ls_print, state->ls_parseable, 3498da14cebeSEric Cheng print_phys_one_hwgrp_callback, hwgrp_state); 3499da14cebeSEric Cheng 3500da14cebeSEric Cheng return (B_TRUE); 3501da14cebeSEric Cheng } 3502da14cebeSEric Cheng 3503da14cebeSEric Cheng /* invoked by show-phys -H for each physical data-link */ 3504da14cebeSEric Cheng static dladm_status_t 3505da14cebeSEric Cheng print_phys_hwgrp(show_state_t *state, datalink_id_t linkid, char *link) 3506da14cebeSEric Cheng { 3507da14cebeSEric Cheng print_phys_hwgrp_state_t hwgrp_state; 3508da14cebeSEric Cheng 3509da14cebeSEric Cheng hwgrp_state.hs_state = state; 3510da14cebeSEric Cheng hwgrp_state.hs_link = link; 35114ac67f02SAnurag S. Maskey return (dladm_walk_hwgrp(handle, linkid, &hwgrp_state, 3512da14cebeSEric Cheng print_phys_hwgrp_callback)); 3513da14cebeSEric Cheng } 3514d62bc4baSyz147064 3515d62bc4baSyz147064 static dladm_status_t 3516da14cebeSEric Cheng print_phys(show_state_t *state, datalink_id_t linkid) 3517d62bc4baSyz147064 { 3518d62bc4baSyz147064 char link[MAXLINKNAMELEN]; 3519d62bc4baSyz147064 uint32_t flags; 3520da14cebeSEric Cheng dladm_status_t status; 3521d62bc4baSyz147064 datalink_class_t class; 3522d62bc4baSyz147064 uint32_t media; 3523d62bc4baSyz147064 35244ac67f02SAnurag S. Maskey if ((status = dladm_datalink_id2info(handle, linkid, &flags, &class, 35254ac67f02SAnurag S. Maskey &media, link, MAXLINKNAMELEN)) != DLADM_STATUS_OK) { 3526d62bc4baSyz147064 goto done; 3527d62bc4baSyz147064 } 3528d62bc4baSyz147064 3529d62bc4baSyz147064 if (class != DATALINK_CLASS_PHYS) { 3530d62bc4baSyz147064 status = DLADM_STATUS_BADARG; 3531d62bc4baSyz147064 goto done; 3532d62bc4baSyz147064 } 3533d62bc4baSyz147064 3534d62bc4baSyz147064 if (!(state->ls_flags & flags)) { 3535d62bc4baSyz147064 status = DLADM_STATUS_NOTFOUND; 3536d62bc4baSyz147064 goto done; 3537d62bc4baSyz147064 } 3538d62bc4baSyz147064 3539da14cebeSEric Cheng if (state->ls_mac) 3540da14cebeSEric Cheng status = print_phys_mac(state, linkid, link); 3541da14cebeSEric Cheng else if (state->ls_hwgrp) 3542da14cebeSEric Cheng status = print_phys_hwgrp(state, linkid, link); 3543da14cebeSEric Cheng else 3544da14cebeSEric Cheng status = print_phys_default(state, linkid, link, flags, media); 3545d62bc4baSyz147064 3546d62bc4baSyz147064 done: 3547d62bc4baSyz147064 return (status); 3548d62bc4baSyz147064 } 3549d62bc4baSyz147064 35504ac67f02SAnurag S. Maskey /* ARGSUSED */ 3551d62bc4baSyz147064 static int 35524ac67f02SAnurag S. Maskey show_phys(dladm_handle_t dh, datalink_id_t linkid, void *arg) 3553d62bc4baSyz147064 { 3554d62bc4baSyz147064 show_state_t *state = arg; 3555d62bc4baSyz147064 3556da14cebeSEric Cheng state->ls_status = print_phys(state, linkid); 3557d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 3558d62bc4baSyz147064 } 3559d62bc4baSyz147064 3560d62bc4baSyz147064 /* 3561d62bc4baSyz147064 * Print the active topology information. 3562d62bc4baSyz147064 */ 3563d62bc4baSyz147064 static dladm_status_t 3564e7801d59Ssowmini print_vlan(show_state_t *state, datalink_id_t linkid, link_fields_buf_t *l) 3565d62bc4baSyz147064 { 3566d62bc4baSyz147064 dladm_vlan_attr_t vinfo; 3567d62bc4baSyz147064 uint32_t flags; 3568d62bc4baSyz147064 dladm_status_t status; 3569d62bc4baSyz147064 35704ac67f02SAnurag S. Maskey if ((status = dladm_datalink_id2info(handle, linkid, &flags, NULL, NULL, 3571e7801d59Ssowmini l->link_name, sizeof (l->link_name))) != DLADM_STATUS_OK) { 3572d62bc4baSyz147064 goto done; 3573d62bc4baSyz147064 } 3574d62bc4baSyz147064 3575d62bc4baSyz147064 if (!(state->ls_flags & flags)) { 3576d62bc4baSyz147064 status = DLADM_STATUS_NOTFOUND; 3577d62bc4baSyz147064 goto done; 3578d62bc4baSyz147064 } 3579d62bc4baSyz147064 35804ac67f02SAnurag S. Maskey if ((status = dladm_vlan_info(handle, linkid, &vinfo, 35814ac67f02SAnurag S. Maskey state->ls_flags)) != DLADM_STATUS_OK || 35824ac67f02SAnurag S. Maskey (status = dladm_datalink_id2info(handle, vinfo.dv_linkid, NULL, 35834ac67f02SAnurag S. Maskey NULL, NULL, l->link_over, sizeof (l->link_over))) != 35844ac67f02SAnurag S. Maskey DLADM_STATUS_OK) { 3585d62bc4baSyz147064 goto done; 3586d62bc4baSyz147064 } 3587d62bc4baSyz147064 3588e7801d59Ssowmini (void) snprintf(l->link_vlan_vid, sizeof (l->link_vlan_vid), "%d", 3589e7801d59Ssowmini vinfo.dv_vid); 3590da14cebeSEric Cheng (void) snprintf(l->link_flags, sizeof (l->link_flags), "%c----", 3591da14cebeSEric Cheng vinfo.dv_force ? 'f' : '-'); 3592d62bc4baSyz147064 3593d62bc4baSyz147064 done: 3594d62bc4baSyz147064 return (status); 3595d62bc4baSyz147064 } 3596d62bc4baSyz147064 35974ac67f02SAnurag S. Maskey /* ARGSUSED */ 3598d62bc4baSyz147064 static int 35994ac67f02SAnurag S. Maskey show_vlan(dladm_handle_t dh, datalink_id_t linkid, void *arg) 3600d62bc4baSyz147064 { 3601d62bc4baSyz147064 show_state_t *state = arg; 3602d62bc4baSyz147064 dladm_status_t status; 3603e7801d59Ssowmini link_fields_buf_t lbuf; 3604d62bc4baSyz147064 36055f5c9f54SAnurag S. Maskey bzero(&lbuf, sizeof (link_fields_buf_t)); 3606e7801d59Ssowmini status = print_vlan(state, linkid, &lbuf); 3607d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 3608d62bc4baSyz147064 goto done; 3609e7801d59Ssowmini 3610e7801d59Ssowmini if (!state->ls_parseable && !state->ls_printheader) { 3611e7801d59Ssowmini print_header(&state->ls_print); 3612e7801d59Ssowmini state->ls_printheader = B_TRUE; 3613e7801d59Ssowmini } 3614e7801d59Ssowmini 3615e7801d59Ssowmini dladm_print_output(&state->ls_print, state->ls_parseable, 3616e7801d59Ssowmini dladm_print_field, (void *)&lbuf); 3617d62bc4baSyz147064 3618d62bc4baSyz147064 done: 3619d62bc4baSyz147064 state->ls_status = status; 3620d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 3621d62bc4baSyz147064 } 3622d62bc4baSyz147064 3623d62bc4baSyz147064 static void 36248d5c46e6Sam223141 do_show_phys(int argc, char *argv[], const char *use) 3625d62bc4baSyz147064 { 3626d62bc4baSyz147064 int option; 3627d62bc4baSyz147064 uint32_t flags = DLADM_OPT_ACTIVE; 3628d62bc4baSyz147064 boolean_t p_arg = B_FALSE; 3629e7801d59Ssowmini boolean_t o_arg = B_FALSE; 3630da14cebeSEric Cheng boolean_t m_arg = B_FALSE; 3631da14cebeSEric Cheng boolean_t H_arg = B_FALSE; 3632d62bc4baSyz147064 datalink_id_t linkid = DATALINK_ALL_LINKID; 3633d62bc4baSyz147064 show_state_t state; 3634d62bc4baSyz147064 dladm_status_t status; 3635e7801d59Ssowmini char *fields_str = NULL; 3636e7801d59Ssowmini print_field_t **fields; 3637e7801d59Ssowmini uint_t nfields; 3638e7801d59Ssowmini char *all_active_fields = 3639e7801d59Ssowmini "link,media,state,speed,duplex,device"; 36405f5c9f54SAnurag S. Maskey char *all_inactive_fields = "link,device,media,flags"; 3641da14cebeSEric Cheng char *all_mac_fields = "link,slot,address,inuse,client"; 3642da14cebeSEric Cheng char *all_hwgrp_fields = 3643da14cebeSEric Cheng "link,group,grouptype,rings,clients"; 3644da14cebeSEric Cheng print_field_t *pf; 3645da14cebeSEric Cheng int pfmax; 3646d62bc4baSyz147064 3647e7801d59Ssowmini bzero(&state, sizeof (state)); 3648d62bc4baSyz147064 opterr = 0; 3649da14cebeSEric Cheng while ((option = getopt_long(argc, argv, ":pPo:mH", 3650d62bc4baSyz147064 show_lopts, NULL)) != -1) { 3651d62bc4baSyz147064 switch (option) { 3652d62bc4baSyz147064 case 'p': 3653d62bc4baSyz147064 if (p_arg) 3654d62bc4baSyz147064 die_optdup(option); 3655d62bc4baSyz147064 3656d62bc4baSyz147064 p_arg = B_TRUE; 3657d62bc4baSyz147064 break; 3658d62bc4baSyz147064 case 'P': 3659d62bc4baSyz147064 if (flags != DLADM_OPT_ACTIVE) 3660d62bc4baSyz147064 die_optdup(option); 3661d62bc4baSyz147064 3662d62bc4baSyz147064 flags = DLADM_OPT_PERSIST; 3663d62bc4baSyz147064 break; 3664e7801d59Ssowmini case 'o': 3665e7801d59Ssowmini o_arg = B_TRUE; 3666e7801d59Ssowmini fields_str = optarg; 3667e7801d59Ssowmini break; 3668da14cebeSEric Cheng case 'm': 3669da14cebeSEric Cheng m_arg = B_TRUE; 3670da14cebeSEric Cheng break; 3671da14cebeSEric Cheng case 'H': 3672da14cebeSEric Cheng H_arg = B_TRUE; 3673da14cebeSEric Cheng break; 3674d62bc4baSyz147064 default: 36758d5c46e6Sam223141 die_opterr(optopt, option, use); 3676d62bc4baSyz147064 break; 3677d62bc4baSyz147064 } 3678d62bc4baSyz147064 } 3679d62bc4baSyz147064 36800d365605Sschuster if (p_arg && !o_arg) 36810d365605Sschuster die("-p requires -o"); 36820d365605Sschuster 3683da14cebeSEric Cheng if (m_arg && H_arg) 3684da14cebeSEric Cheng die("-m cannot combine with -H"); 3685da14cebeSEric Cheng 36860d365605Sschuster if (p_arg && strcasecmp(fields_str, "all") == 0) 36870d365605Sschuster die("\"-o all\" is invalid with -p"); 36880d365605Sschuster 3689d62bc4baSyz147064 /* get link name (optional last argument) */ 3690d62bc4baSyz147064 if (optind == (argc-1)) { 36914ac67f02SAnurag S. Maskey if ((status = dladm_name2info(handle, argv[optind], &linkid, 36924ac67f02SAnurag S. Maskey NULL, NULL, NULL)) != DLADM_STATUS_OK) { 3693d62bc4baSyz147064 die_dlerr(status, "link %s is not valid", argv[optind]); 3694d62bc4baSyz147064 } 3695d62bc4baSyz147064 } else if (optind != argc) { 3696d62bc4baSyz147064 usage(); 3697d62bc4baSyz147064 } 3698d62bc4baSyz147064 3699d62bc4baSyz147064 state.ls_parseable = p_arg; 3700d62bc4baSyz147064 state.ls_flags = flags; 3701d62bc4baSyz147064 state.ls_donefirst = B_FALSE; 3702da14cebeSEric Cheng state.ls_mac = m_arg; 3703da14cebeSEric Cheng state.ls_hwgrp = H_arg; 3704d62bc4baSyz147064 3705da14cebeSEric Cheng if (m_arg && !(flags & DLADM_OPT_ACTIVE)) { 3706da14cebeSEric Cheng /* 3707da14cebeSEric Cheng * We can only display the factory MAC addresses of 3708da14cebeSEric Cheng * active data-links. 3709da14cebeSEric Cheng */ 3710da14cebeSEric Cheng die("-m not compatible with -P"); 3711e7801d59Ssowmini } 3712e7801d59Ssowmini 3713da14cebeSEric Cheng if (!o_arg || (o_arg && strcasecmp(fields_str, "all") == 0)) { 3714da14cebeSEric Cheng if (state.ls_mac) 3715da14cebeSEric Cheng fields_str = all_mac_fields; 3716da14cebeSEric Cheng else if (state.ls_hwgrp) 3717da14cebeSEric Cheng fields_str = all_hwgrp_fields; 3718da14cebeSEric Cheng else if (state.ls_flags & DLADM_OPT_ACTIVE) { 3719da14cebeSEric Cheng fields_str = all_active_fields; 3720da14cebeSEric Cheng } else { 3721da14cebeSEric Cheng fields_str = all_inactive_fields; 3722da14cebeSEric Cheng } 3723da14cebeSEric Cheng } 3724da14cebeSEric Cheng 3725da14cebeSEric Cheng if (state.ls_mac) { 3726da14cebeSEric Cheng pf = phys_m_fields; 3727da14cebeSEric Cheng pfmax = PHYS_M_MAX_FIELDS; 3728da14cebeSEric Cheng } else if (state.ls_hwgrp) { 3729da14cebeSEric Cheng pf = phys_h_fields; 3730da14cebeSEric Cheng pfmax = PHYS_H_MAX_FIELDS; 3731da14cebeSEric Cheng } else { 3732da14cebeSEric Cheng pf = phys_fields; 3733da14cebeSEric Cheng pfmax = PHYS_MAX_FIELDS; 3734da14cebeSEric Cheng } 3735da14cebeSEric Cheng 3736da14cebeSEric Cheng fields = parse_output_fields(fields_str, pf, 3737da14cebeSEric Cheng pfmax, CMD_TYPE_ANY, &nfields); 3738e7801d59Ssowmini 3739e7801d59Ssowmini if (fields == NULL) { 3740e7801d59Ssowmini die("invalid field(s) specified"); 3741e7801d59Ssowmini return; 3742e7801d59Ssowmini } 3743e7801d59Ssowmini 3744e7801d59Ssowmini state.ls_print.ps_fields = fields; 3745e7801d59Ssowmini state.ls_print.ps_nfields = nfields; 3746e7801d59Ssowmini 3747d62bc4baSyz147064 if (linkid == DATALINK_ALL_LINKID) { 37484ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(show_phys, handle, &state, 3749d62bc4baSyz147064 DATALINK_CLASS_PHYS, DATALINK_ANY_MEDIATYPE, flags); 3750d62bc4baSyz147064 } else { 37514ac67f02SAnurag S. Maskey (void) show_phys(handle, linkid, &state); 3752d62bc4baSyz147064 if (state.ls_status != DLADM_STATUS_OK) { 3753d62bc4baSyz147064 die_dlerr(state.ls_status, 3754d62bc4baSyz147064 "failed to show physical link %s", argv[optind]); 3755d62bc4baSyz147064 } 3756d62bc4baSyz147064 } 3757d62bc4baSyz147064 } 3758d62bc4baSyz147064 3759d62bc4baSyz147064 static void 37608d5c46e6Sam223141 do_show_vlan(int argc, char *argv[], const char *use) 3761d62bc4baSyz147064 { 3762d62bc4baSyz147064 int option; 3763d62bc4baSyz147064 uint32_t flags = DLADM_OPT_ACTIVE; 3764d62bc4baSyz147064 boolean_t p_arg = B_FALSE; 3765d62bc4baSyz147064 datalink_id_t linkid = DATALINK_ALL_LINKID; 3766d62bc4baSyz147064 show_state_t state; 3767d62bc4baSyz147064 dladm_status_t status; 3768e7801d59Ssowmini boolean_t o_arg = B_FALSE; 3769e7801d59Ssowmini char *fields_str = NULL; 3770e7801d59Ssowmini print_field_t **fields; 3771e7801d59Ssowmini uint_t nfields; 3772e7801d59Ssowmini char *all_fields = "link,vid,over,flags"; 3773e7801d59Ssowmini 3774e7801d59Ssowmini bzero(&state, sizeof (state)); 3775d62bc4baSyz147064 3776d62bc4baSyz147064 opterr = 0; 3777e7801d59Ssowmini while ((option = getopt_long(argc, argv, ":pPo:", 3778d62bc4baSyz147064 show_lopts, NULL)) != -1) { 3779d62bc4baSyz147064 switch (option) { 3780d62bc4baSyz147064 case 'p': 3781d62bc4baSyz147064 if (p_arg) 3782d62bc4baSyz147064 die_optdup(option); 3783d62bc4baSyz147064 3784d62bc4baSyz147064 p_arg = B_TRUE; 3785d62bc4baSyz147064 break; 3786d62bc4baSyz147064 case 'P': 3787d62bc4baSyz147064 if (flags != DLADM_OPT_ACTIVE) 3788d62bc4baSyz147064 die_optdup(option); 3789d62bc4baSyz147064 3790d62bc4baSyz147064 flags = DLADM_OPT_PERSIST; 3791d62bc4baSyz147064 break; 3792e7801d59Ssowmini case 'o': 3793e7801d59Ssowmini o_arg = B_TRUE; 3794e7801d59Ssowmini fields_str = optarg; 3795e7801d59Ssowmini break; 3796d62bc4baSyz147064 default: 37978d5c46e6Sam223141 die_opterr(optopt, option, use); 3798d62bc4baSyz147064 break; 3799d62bc4baSyz147064 } 3800d62bc4baSyz147064 } 3801d62bc4baSyz147064 38020d365605Sschuster if (p_arg && !o_arg) 38030d365605Sschuster die("-p requires -o"); 38040d365605Sschuster 38050d365605Sschuster if (p_arg && strcasecmp(fields_str, "all") == 0) 38060d365605Sschuster die("\"-o all\" is invalid with -p"); 38070d365605Sschuster 3808d62bc4baSyz147064 /* get link name (optional last argument) */ 3809d62bc4baSyz147064 if (optind == (argc-1)) { 38104ac67f02SAnurag S. Maskey if ((status = dladm_name2info(handle, argv[optind], &linkid, 38114ac67f02SAnurag S. Maskey NULL, NULL, NULL)) != DLADM_STATUS_OK) { 3812d62bc4baSyz147064 die_dlerr(status, "link %s is not valid", argv[optind]); 3813d62bc4baSyz147064 } 3814d62bc4baSyz147064 } else if (optind != argc) { 3815d62bc4baSyz147064 usage(); 3816d62bc4baSyz147064 } 3817d62bc4baSyz147064 3818d62bc4baSyz147064 state.ls_parseable = p_arg; 3819d62bc4baSyz147064 state.ls_flags = flags; 3820d62bc4baSyz147064 state.ls_donefirst = B_FALSE; 3821d62bc4baSyz147064 3822e7801d59Ssowmini if (!o_arg || (o_arg && strcasecmp(fields_str, "all") == 0)) 3823e7801d59Ssowmini fields_str = all_fields; 3824e7801d59Ssowmini 3825e7801d59Ssowmini fields = parse_output_fields(fields_str, vlan_fields, VLAN_MAX_FIELDS, 3826e7801d59Ssowmini CMD_TYPE_ANY, &nfields); 3827e7801d59Ssowmini 3828e7801d59Ssowmini if (fields == NULL) { 3829e7801d59Ssowmini die("invalid field(s) specified"); 3830e7801d59Ssowmini return; 3831e7801d59Ssowmini } 3832e7801d59Ssowmini state.ls_print.ps_fields = fields; 3833e7801d59Ssowmini state.ls_print.ps_nfields = nfields; 3834e7801d59Ssowmini 3835d62bc4baSyz147064 if (linkid == DATALINK_ALL_LINKID) { 38364ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(show_vlan, handle, &state, 3837d62bc4baSyz147064 DATALINK_CLASS_VLAN, DATALINK_ANY_MEDIATYPE, flags); 3838d62bc4baSyz147064 } else { 38394ac67f02SAnurag S. Maskey (void) show_vlan(handle, linkid, &state); 3840d62bc4baSyz147064 if (state.ls_status != DLADM_STATUS_OK) { 3841d62bc4baSyz147064 die_dlerr(state.ls_status, "failed to show vlan %s", 3842d62bc4baSyz147064 argv[optind]); 3843d62bc4baSyz147064 } 3844d62bc4baSyz147064 } 3845d62bc4baSyz147064 } 3846d62bc4baSyz147064 3847d62bc4baSyz147064 static void 3848da14cebeSEric Cheng do_create_vnic(int argc, char *argv[], const char *use) 3849da14cebeSEric Cheng { 3850da14cebeSEric Cheng datalink_id_t linkid, dev_linkid; 3851da14cebeSEric Cheng char devname[MAXLINKNAMELEN]; 3852da14cebeSEric Cheng char name[MAXLINKNAMELEN]; 3853da14cebeSEric Cheng boolean_t l_arg = B_FALSE; 3854da14cebeSEric Cheng uint32_t flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST; 3855da14cebeSEric Cheng char *altroot = NULL; 3856da14cebeSEric Cheng char option; 3857da14cebeSEric Cheng char *endp = NULL; 3858da14cebeSEric Cheng dladm_status_t status; 3859da14cebeSEric Cheng vnic_mac_addr_type_t mac_addr_type = VNIC_MAC_ADDR_TYPE_AUTO; 3860da14cebeSEric Cheng uchar_t *mac_addr; 3861da14cebeSEric Cheng int mac_slot = -1, maclen = 0, mac_prefix_len = 0; 3862da14cebeSEric Cheng dladm_arg_list_t *proplist = NULL; 3863*285e94f9SMichael Lim int vid = 0; 3864da14cebeSEric Cheng 3865da14cebeSEric Cheng opterr = 0; 3866da14cebeSEric Cheng while ((option = getopt_long(argc, argv, ":tfR:l:m:n:p:r:v:H", 3867da14cebeSEric Cheng vnic_lopts, NULL)) != -1) { 3868da14cebeSEric Cheng switch (option) { 3869da14cebeSEric Cheng case 't': 3870da14cebeSEric Cheng flags &= ~DLADM_OPT_PERSIST; 3871da14cebeSEric Cheng break; 3872da14cebeSEric Cheng case 'R': 3873da14cebeSEric Cheng altroot = optarg; 3874da14cebeSEric Cheng break; 3875da14cebeSEric Cheng case 'l': 3876da14cebeSEric Cheng if (strlcpy(devname, optarg, MAXLINKNAMELEN) >= 3877da14cebeSEric Cheng MAXLINKNAMELEN) 3878da14cebeSEric Cheng die("link name too long"); 3879da14cebeSEric Cheng l_arg = B_TRUE; 3880da14cebeSEric Cheng break; 3881da14cebeSEric Cheng case 'm': 3882da14cebeSEric Cheng if (strcmp(optarg, "fixed") == 0) { 3883da14cebeSEric Cheng /* 3884da14cebeSEric Cheng * A fixed MAC address must be specified 3885da14cebeSEric Cheng * by its value, not by the keyword 'fixed'. 3886da14cebeSEric Cheng */ 3887da14cebeSEric Cheng die("'fixed' is not a valid MAC address"); 3888da14cebeSEric Cheng } 3889da14cebeSEric Cheng if (dladm_vnic_str2macaddrtype(optarg, 3890da14cebeSEric Cheng &mac_addr_type) != DLADM_STATUS_OK) { 3891da14cebeSEric Cheng mac_addr_type = VNIC_MAC_ADDR_TYPE_FIXED; 3892da14cebeSEric Cheng /* MAC address specified by value */ 3893da14cebeSEric Cheng mac_addr = _link_aton(optarg, &maclen); 3894da14cebeSEric Cheng if (mac_addr == NULL) { 3895da14cebeSEric Cheng if (maclen == -1) 3896da14cebeSEric Cheng die("invalid MAC address"); 3897da14cebeSEric Cheng else 3898da14cebeSEric Cheng die("out of memory"); 3899da14cebeSEric Cheng } 3900da14cebeSEric Cheng } 3901da14cebeSEric Cheng break; 3902da14cebeSEric Cheng case 'n': 3903da14cebeSEric Cheng errno = 0; 3904da14cebeSEric Cheng mac_slot = (int)strtol(optarg, &endp, 10); 3905da14cebeSEric Cheng if (errno != 0 || *endp != '\0') 3906da14cebeSEric Cheng die("invalid slot number"); 3907da14cebeSEric Cheng break; 3908da14cebeSEric Cheng case 'p': 3909da14cebeSEric Cheng if (dladm_parse_link_props(optarg, &proplist, B_FALSE) 3910da14cebeSEric Cheng != DLADM_STATUS_OK) 3911da14cebeSEric Cheng die("invalid vnic property"); 3912da14cebeSEric Cheng break; 3913da14cebeSEric Cheng case 'r': 3914da14cebeSEric Cheng mac_addr = _link_aton(optarg, &mac_prefix_len); 3915da14cebeSEric Cheng if (mac_addr == NULL) { 3916da14cebeSEric Cheng if (mac_prefix_len == -1) 3917da14cebeSEric Cheng die("invalid MAC address"); 3918da14cebeSEric Cheng else 3919da14cebeSEric Cheng die("out of memory"); 3920da14cebeSEric Cheng } 3921da14cebeSEric Cheng break; 3922da14cebeSEric Cheng case 'v': 3923*285e94f9SMichael Lim if (vid != 0) 3924*285e94f9SMichael Lim die_optdup(option); 3925*285e94f9SMichael Lim 3926*285e94f9SMichael Lim if (!str2int(optarg, &vid) || vid < 1 || vid > 4094) 3927*285e94f9SMichael Lim die("invalid VLAN identifier '%s'", optarg); 3928*285e94f9SMichael Lim 3929da14cebeSEric Cheng break; 3930da14cebeSEric Cheng case 'f': 3931da14cebeSEric Cheng flags |= DLADM_OPT_FORCE; 3932da14cebeSEric Cheng break; 3933da14cebeSEric Cheng case 'H': 3934da14cebeSEric Cheng flags |= DLADM_OPT_HWRINGS; 3935da14cebeSEric Cheng break; 3936da14cebeSEric Cheng default: 3937da14cebeSEric Cheng die_opterr(optopt, option, use); 3938da14cebeSEric Cheng } 3939da14cebeSEric Cheng } 3940da14cebeSEric Cheng 3941da14cebeSEric Cheng /* 3942da14cebeSEric Cheng * 'f' - force, flag can be specified only with 'v' - vlan. 3943da14cebeSEric Cheng */ 3944da14cebeSEric Cheng if ((flags & DLADM_OPT_FORCE) != 0 && vid == 0) 3945da14cebeSEric Cheng die("-f option can only be used with -v"); 3946da14cebeSEric Cheng 3947da14cebeSEric Cheng if (mac_prefix_len != 0 && mac_addr_type != VNIC_MAC_ADDR_TYPE_RANDOM && 3948da14cebeSEric Cheng mac_addr_type != VNIC_MAC_ADDR_TYPE_FIXED) 3949da14cebeSEric Cheng usage(); 3950da14cebeSEric Cheng 3951da14cebeSEric Cheng /* check required options */ 3952da14cebeSEric Cheng if (!l_arg) 3953da14cebeSEric Cheng usage(); 3954da14cebeSEric Cheng 3955da14cebeSEric Cheng if (mac_slot != -1 && mac_addr_type != VNIC_MAC_ADDR_TYPE_FACTORY) 3956da14cebeSEric Cheng usage(); 3957da14cebeSEric Cheng 3958da14cebeSEric Cheng /* the VNIC id is the required operand */ 3959da14cebeSEric Cheng if (optind != (argc - 1)) 3960da14cebeSEric Cheng usage(); 3961da14cebeSEric Cheng 3962da14cebeSEric Cheng if (strlcpy(name, argv[optind], MAXLINKNAMELEN) >= MAXLINKNAMELEN) 3963da14cebeSEric Cheng die("link name too long '%s'", argv[optind]); 3964da14cebeSEric Cheng 3965da14cebeSEric Cheng if (!dladm_valid_linkname(name)) 3966da14cebeSEric Cheng die("invalid link name '%s'", argv[optind]); 3967da14cebeSEric Cheng 3968da14cebeSEric Cheng if (altroot != NULL) 3969da14cebeSEric Cheng altroot_cmd(altroot, argc, argv); 3970da14cebeSEric Cheng 39714ac67f02SAnurag S. Maskey if (dladm_name2info(handle, devname, &dev_linkid, NULL, NULL, NULL) != 3972da14cebeSEric Cheng DLADM_STATUS_OK) 3973da14cebeSEric Cheng die("invalid link name '%s'", devname); 3974da14cebeSEric Cheng 39754ac67f02SAnurag S. Maskey status = dladm_vnic_create(handle, name, dev_linkid, mac_addr_type, 39764ac67f02SAnurag S. Maskey mac_addr, maclen, &mac_slot, mac_prefix_len, vid, &linkid, proplist, 39774ac67f02SAnurag S. Maskey flags); 3978da14cebeSEric Cheng if (status != DLADM_STATUS_OK) 3979da14cebeSEric Cheng die_dlerr(status, "vnic creation over %s failed", devname); 3980da14cebeSEric Cheng 3981da14cebeSEric Cheng dladm_free_props(proplist); 3982da14cebeSEric Cheng } 3983da14cebeSEric Cheng 3984da14cebeSEric Cheng static void 3985da14cebeSEric Cheng do_etherstub_check(const char *name, datalink_id_t linkid, boolean_t etherstub, 3986da14cebeSEric Cheng uint32_t flags) 3987da14cebeSEric Cheng { 3988da14cebeSEric Cheng boolean_t is_etherstub; 3989da14cebeSEric Cheng dladm_vnic_attr_t attr; 3990da14cebeSEric Cheng 39914ac67f02SAnurag S. Maskey if (dladm_vnic_info(handle, linkid, &attr, flags) != DLADM_STATUS_OK) { 3992da14cebeSEric Cheng /* 3993da14cebeSEric Cheng * Let the delete continue anyway. 3994da14cebeSEric Cheng */ 3995da14cebeSEric Cheng return; 3996da14cebeSEric Cheng } 3997da14cebeSEric Cheng is_etherstub = (attr.va_link_id == DATALINK_INVALID_LINKID); 3998da14cebeSEric Cheng if (is_etherstub != etherstub) { 3999da14cebeSEric Cheng die("'%s' is not %s", name, 4000da14cebeSEric Cheng (is_etherstub ? "a vnic" : "an etherstub")); 4001da14cebeSEric Cheng } 4002da14cebeSEric Cheng } 4003da14cebeSEric Cheng 4004da14cebeSEric Cheng static void 4005da14cebeSEric Cheng do_delete_vnic_common(int argc, char *argv[], const char *use, 4006da14cebeSEric Cheng boolean_t etherstub) 4007da14cebeSEric Cheng { 4008da14cebeSEric Cheng char option; 4009da14cebeSEric Cheng uint32_t flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST; 4010da14cebeSEric Cheng datalink_id_t linkid; 4011da14cebeSEric Cheng char *altroot = NULL; 4012da14cebeSEric Cheng dladm_status_t status; 4013da14cebeSEric Cheng 4014da14cebeSEric Cheng opterr = 0; 4015da14cebeSEric Cheng while ((option = getopt_long(argc, argv, ":R:t", lopts, 4016da14cebeSEric Cheng NULL)) != -1) { 4017da14cebeSEric Cheng switch (option) { 4018da14cebeSEric Cheng case 't': 4019da14cebeSEric Cheng flags &= ~DLADM_OPT_PERSIST; 4020da14cebeSEric Cheng break; 4021da14cebeSEric Cheng case 'R': 4022da14cebeSEric Cheng altroot = optarg; 4023da14cebeSEric Cheng break; 4024da14cebeSEric Cheng default: 4025da14cebeSEric Cheng die_opterr(optopt, option, use); 4026da14cebeSEric Cheng } 4027da14cebeSEric Cheng } 4028da14cebeSEric Cheng 4029da14cebeSEric Cheng /* get vnic name (required last argument) */ 4030da14cebeSEric Cheng if (optind != (argc - 1)) 4031da14cebeSEric Cheng usage(); 4032da14cebeSEric Cheng 4033da14cebeSEric Cheng if (altroot != NULL) 4034da14cebeSEric Cheng altroot_cmd(altroot, argc, argv); 4035da14cebeSEric Cheng 40364ac67f02SAnurag S. Maskey status = dladm_name2info(handle, argv[optind], &linkid, NULL, NULL, 40374ac67f02SAnurag S. Maskey NULL); 4038da14cebeSEric Cheng if (status != DLADM_STATUS_OK) 4039da14cebeSEric Cheng die("invalid link name '%s'", argv[optind]); 4040da14cebeSEric Cheng 4041da14cebeSEric Cheng if ((flags & DLADM_OPT_ACTIVE) != 0) { 4042da14cebeSEric Cheng do_etherstub_check(argv[optind], linkid, etherstub, 4043da14cebeSEric Cheng DLADM_OPT_ACTIVE); 4044da14cebeSEric Cheng } 4045da14cebeSEric Cheng if ((flags & DLADM_OPT_PERSIST) != 0) { 4046da14cebeSEric Cheng do_etherstub_check(argv[optind], linkid, etherstub, 4047da14cebeSEric Cheng DLADM_OPT_PERSIST); 4048da14cebeSEric Cheng } 4049da14cebeSEric Cheng 40504ac67f02SAnurag S. Maskey status = dladm_vnic_delete(handle, linkid, flags); 4051da14cebeSEric Cheng if (status != DLADM_STATUS_OK) 4052da14cebeSEric Cheng die_dlerr(status, "vnic deletion failed"); 4053da14cebeSEric Cheng } 4054da14cebeSEric Cheng 4055da14cebeSEric Cheng static void 4056da14cebeSEric Cheng do_delete_vnic(int argc, char *argv[], const char *use) 4057da14cebeSEric Cheng { 4058da14cebeSEric Cheng do_delete_vnic_common(argc, argv, use, B_FALSE); 4059da14cebeSEric Cheng } 4060da14cebeSEric Cheng 4061da14cebeSEric Cheng /* ARGSUSED */ 4062da14cebeSEric Cheng static void 4063da14cebeSEric Cheng do_up_vnic_common(int argc, char *argv[], const char *use, boolean_t vlan) 4064da14cebeSEric Cheng { 4065da14cebeSEric Cheng datalink_id_t linkid = DATALINK_ALL_LINKID; 4066da14cebeSEric Cheng dladm_status_t status; 4067da14cebeSEric Cheng char *type; 4068da14cebeSEric Cheng 4069da14cebeSEric Cheng type = vlan ? "vlan" : "vnic"; 4070da14cebeSEric Cheng 4071da14cebeSEric Cheng /* 4072da14cebeSEric Cheng * get the id or the name of the vnic/vlan (optional last argument) 4073da14cebeSEric Cheng */ 4074da14cebeSEric Cheng if (argc == 2) { 40754ac67f02SAnurag S. Maskey status = dladm_name2info(handle, argv[1], &linkid, NULL, NULL, 40764ac67f02SAnurag S. Maskey NULL); 4077da14cebeSEric Cheng if (status != DLADM_STATUS_OK) 4078da14cebeSEric Cheng goto done; 4079da14cebeSEric Cheng 4080da14cebeSEric Cheng } else if (argc > 2) { 4081da14cebeSEric Cheng usage(); 4082da14cebeSEric Cheng } 4083da14cebeSEric Cheng 4084da14cebeSEric Cheng if (vlan) 40854ac67f02SAnurag S. Maskey status = dladm_vlan_up(handle, linkid); 4086da14cebeSEric Cheng else 40874ac67f02SAnurag S. Maskey status = dladm_vnic_up(handle, linkid, 0); 4088da14cebeSEric Cheng 4089da14cebeSEric Cheng done: 4090da14cebeSEric Cheng if (status != DLADM_STATUS_OK) { 4091da14cebeSEric Cheng if (argc == 2) { 4092da14cebeSEric Cheng die_dlerr(status, 4093da14cebeSEric Cheng "could not bring up %s '%s'", type, argv[1]); 4094da14cebeSEric Cheng } else { 4095da14cebeSEric Cheng die_dlerr(status, "could not bring %ss up", type); 4096da14cebeSEric Cheng } 4097da14cebeSEric Cheng } 4098da14cebeSEric Cheng } 4099da14cebeSEric Cheng 4100da14cebeSEric Cheng static void 4101da14cebeSEric Cheng do_up_vnic(int argc, char *argv[], const char *use) 4102da14cebeSEric Cheng { 4103da14cebeSEric Cheng do_up_vnic_common(argc, argv, use, B_FALSE); 4104da14cebeSEric Cheng } 4105da14cebeSEric Cheng 4106da14cebeSEric Cheng static void 4107da14cebeSEric Cheng dump_vnics_head(const char *dev) 4108da14cebeSEric Cheng { 4109da14cebeSEric Cheng if (strlen(dev)) 4110da14cebeSEric Cheng (void) printf("%s", dev); 4111da14cebeSEric Cheng 4112da14cebeSEric Cheng (void) printf("\tipackets rbytes opackets obytes "); 4113da14cebeSEric Cheng 4114da14cebeSEric Cheng if (strlen(dev)) 4115da14cebeSEric Cheng (void) printf("%%ipkts %%opkts\n"); 4116da14cebeSEric Cheng else 4117da14cebeSEric Cheng (void) printf("\n"); 4118da14cebeSEric Cheng } 4119da14cebeSEric Cheng 4120da14cebeSEric Cheng static void 4121da14cebeSEric Cheng dump_vnic_stat(const char *name, datalink_id_t vnic_id, 4122da14cebeSEric Cheng show_vnic_state_t *state, pktsum_t *vnic_stats, pktsum_t *tot_stats) 4123da14cebeSEric Cheng { 4124da14cebeSEric Cheng pktsum_t diff_stats; 4125da14cebeSEric Cheng pktsum_t *old_stats = &state->vs_prevstats[vnic_id]; 4126da14cebeSEric Cheng 4127da14cebeSEric Cheng dladm_stats_diff(&diff_stats, vnic_stats, old_stats); 4128da14cebeSEric Cheng 4129da14cebeSEric Cheng (void) printf("%s", name); 4130da14cebeSEric Cheng 4131da14cebeSEric Cheng (void) printf("\t%-10llu", diff_stats.ipackets); 4132da14cebeSEric Cheng (void) printf("%-12llu", diff_stats.rbytes); 4133da14cebeSEric Cheng (void) printf("%-10llu", diff_stats.opackets); 4134da14cebeSEric Cheng (void) printf("%-12llu", diff_stats.obytes); 4135da14cebeSEric Cheng 4136da14cebeSEric Cheng if (tot_stats) { 4137da14cebeSEric Cheng if (tot_stats->ipackets == 0) { 4138da14cebeSEric Cheng (void) printf("\t-"); 4139da14cebeSEric Cheng } else { 4140da14cebeSEric Cheng (void) printf("\t%-6.1f", (double)diff_stats.ipackets/ 4141da14cebeSEric Cheng (double)tot_stats->ipackets * 100); 4142da14cebeSEric Cheng } 4143da14cebeSEric Cheng if (tot_stats->opackets == 0) { 4144da14cebeSEric Cheng (void) printf("\t-"); 4145da14cebeSEric Cheng } else { 4146da14cebeSEric Cheng (void) printf("\t%-6.1f", (double)diff_stats.opackets/ 4147da14cebeSEric Cheng (double)tot_stats->opackets * 100); 4148da14cebeSEric Cheng } 4149da14cebeSEric Cheng } 4150da14cebeSEric Cheng (void) printf("\n"); 4151da14cebeSEric Cheng 4152da14cebeSEric Cheng *old_stats = *vnic_stats; 4153da14cebeSEric Cheng } 4154da14cebeSEric Cheng 4155da14cebeSEric Cheng /* 4156da14cebeSEric Cheng * Called from the walker dladm_vnic_walk_sys() for each vnic to display 4157da14cebeSEric Cheng * vnic information or statistics. 4158da14cebeSEric Cheng */ 4159da14cebeSEric Cheng static dladm_status_t 4160da14cebeSEric Cheng print_vnic(show_vnic_state_t *state, datalink_id_t linkid) 4161da14cebeSEric Cheng { 4162da14cebeSEric Cheng dladm_vnic_attr_t attr, *vnic = &attr; 4163da14cebeSEric Cheng dladm_status_t status; 4164da14cebeSEric Cheng boolean_t is_etherstub; 4165da14cebeSEric Cheng char devname[MAXLINKNAMELEN]; 4166da14cebeSEric Cheng char vnic_name[MAXLINKNAMELEN]; 4167da14cebeSEric Cheng char mstr[MAXMACADDRLEN * 3]; 4168da14cebeSEric Cheng vnic_fields_buf_t vbuf; 4169da14cebeSEric Cheng 41704ac67f02SAnurag S. Maskey if ((status = dladm_vnic_info(handle, linkid, vnic, state->vs_flags)) != 4171da14cebeSEric Cheng DLADM_STATUS_OK) 4172da14cebeSEric Cheng return (status); 4173da14cebeSEric Cheng 4174da14cebeSEric Cheng is_etherstub = (vnic->va_link_id == DATALINK_INVALID_LINKID); 4175da14cebeSEric Cheng if (state->vs_etherstub != is_etherstub) { 4176da14cebeSEric Cheng /* 4177da14cebeSEric Cheng * Want all etherstub but it's not one, or want 4178da14cebeSEric Cheng * non-etherstub and it's one. 4179da14cebeSEric Cheng */ 4180da14cebeSEric Cheng return (DLADM_STATUS_OK); 4181da14cebeSEric Cheng } 4182da14cebeSEric Cheng 4183da14cebeSEric Cheng if (state->vs_link_id != DATALINK_ALL_LINKID) { 4184da14cebeSEric Cheng if (state->vs_link_id != vnic->va_link_id) 4185da14cebeSEric Cheng return (DLADM_STATUS_OK); 4186da14cebeSEric Cheng } 4187da14cebeSEric Cheng 41884ac67f02SAnurag S. Maskey if (dladm_datalink_id2info(handle, linkid, NULL, NULL, 4189da14cebeSEric Cheng NULL, vnic_name, sizeof (vnic_name)) != DLADM_STATUS_OK) 4190da14cebeSEric Cheng return (DLADM_STATUS_BADARG); 4191da14cebeSEric Cheng 4192da14cebeSEric Cheng bzero(devname, sizeof (devname)); 4193da14cebeSEric Cheng if (!is_etherstub && 41944ac67f02SAnurag S. Maskey dladm_datalink_id2info(handle, vnic->va_link_id, NULL, NULL, 4195da14cebeSEric Cheng NULL, devname, sizeof (devname)) != DLADM_STATUS_OK) 4196da14cebeSEric Cheng return (DLADM_STATUS_BADARG); 4197da14cebeSEric Cheng 4198da14cebeSEric Cheng state->vs_found = B_TRUE; 4199da14cebeSEric Cheng if (state->vs_stats) { 4200da14cebeSEric Cheng /* print vnic statistics */ 4201da14cebeSEric Cheng pktsum_t vnic_stats; 4202da14cebeSEric Cheng 4203da14cebeSEric Cheng if (state->vs_firstonly) { 4204da14cebeSEric Cheng if (state->vs_donefirst) 4205da14cebeSEric Cheng return (0); 4206da14cebeSEric Cheng state->vs_donefirst = B_TRUE; 4207da14cebeSEric Cheng } 4208da14cebeSEric Cheng 4209da14cebeSEric Cheng if (!state->vs_printstats) { 4210da14cebeSEric Cheng /* 4211da14cebeSEric Cheng * get vnic statistics and add to the sum for the 4212da14cebeSEric Cheng * named device. 4213da14cebeSEric Cheng */ 4214da14cebeSEric Cheng get_link_stats(vnic_name, &vnic_stats); 4215da14cebeSEric Cheng dladm_stats_total(&state->vs_totalstats, &vnic_stats, 4216da14cebeSEric Cheng &state->vs_prevstats[vnic->va_vnic_id]); 4217da14cebeSEric Cheng } else { 4218da14cebeSEric Cheng /* get and print vnic statistics */ 4219da14cebeSEric Cheng get_link_stats(vnic_name, &vnic_stats); 4220da14cebeSEric Cheng dump_vnic_stat(vnic_name, linkid, state, &vnic_stats, 4221da14cebeSEric Cheng &state->vs_totalstats); 4222da14cebeSEric Cheng } 4223da14cebeSEric Cheng return (DLADM_STATUS_OK); 4224da14cebeSEric Cheng } else { 4225da14cebeSEric Cheng (void) snprintf(vbuf.vnic_link, sizeof (vbuf.vnic_link), 4226da14cebeSEric Cheng "%s", vnic_name); 4227da14cebeSEric Cheng 4228da14cebeSEric Cheng if (!is_etherstub) { 4229da14cebeSEric Cheng 4230da14cebeSEric Cheng (void) snprintf(vbuf.vnic_over, sizeof (vbuf.vnic_over), 4231da14cebeSEric Cheng "%s", devname); 4232da14cebeSEric Cheng (void) snprintf(vbuf.vnic_speed, 4233da14cebeSEric Cheng sizeof (vbuf.vnic_speed), "%u", 4234da14cebeSEric Cheng (uint_t)((get_ifspeed(vnic_name, B_TRUE)) 4235da14cebeSEric Cheng / 1000000ull)); 4236da14cebeSEric Cheng 4237da14cebeSEric Cheng switch (vnic->va_mac_addr_type) { 4238da14cebeSEric Cheng case VNIC_MAC_ADDR_TYPE_FIXED: 4239da14cebeSEric Cheng case VNIC_MAC_ADDR_TYPE_PRIMARY: 4240da14cebeSEric Cheng (void) snprintf(vbuf.vnic_macaddrtype, 4241da14cebeSEric Cheng sizeof (vbuf.vnic_macaddrtype), 4242da14cebeSEric Cheng gettext("fixed")); 4243da14cebeSEric Cheng break; 4244da14cebeSEric Cheng case VNIC_MAC_ADDR_TYPE_RANDOM: 4245da14cebeSEric Cheng (void) snprintf(vbuf.vnic_macaddrtype, 4246da14cebeSEric Cheng sizeof (vbuf.vnic_macaddrtype), 4247da14cebeSEric Cheng gettext("random")); 4248da14cebeSEric Cheng break; 4249da14cebeSEric Cheng case VNIC_MAC_ADDR_TYPE_FACTORY: 4250da14cebeSEric Cheng (void) snprintf(vbuf.vnic_macaddrtype, 4251da14cebeSEric Cheng sizeof (vbuf.vnic_macaddrtype), 4252da14cebeSEric Cheng gettext("factory, slot %d"), 4253da14cebeSEric Cheng vnic->va_mac_slot); 4254da14cebeSEric Cheng break; 4255da14cebeSEric Cheng } 4256da14cebeSEric Cheng 4257da14cebeSEric Cheng if (strlen(vbuf.vnic_macaddrtype) > 0) { 4258da14cebeSEric Cheng (void) snprintf(vbuf.vnic_macaddr, 4259da14cebeSEric Cheng sizeof (vbuf.vnic_macaddr), "%s", 4260da14cebeSEric Cheng dladm_aggr_macaddr2str(vnic->va_mac_addr, 4261da14cebeSEric Cheng mstr)); 4262da14cebeSEric Cheng } 4263da14cebeSEric Cheng 4264da14cebeSEric Cheng (void) snprintf(vbuf.vnic_vid, sizeof (vbuf.vnic_vid), 4265da14cebeSEric Cheng "%d", vnic->va_vid); 4266da14cebeSEric Cheng } 4267da14cebeSEric Cheng 4268da14cebeSEric Cheng if (!state->vs_parseable && !state->vs_printheader) { 4269da14cebeSEric Cheng print_header(&state->vs_print); 4270da14cebeSEric Cheng state->vs_printheader = B_TRUE; 4271da14cebeSEric Cheng } 4272da14cebeSEric Cheng 4273da14cebeSEric Cheng dladm_print_output(&state->vs_print, state->vs_parseable, 4274da14cebeSEric Cheng dladm_print_field, (void *)&vbuf); 4275da14cebeSEric Cheng 4276da14cebeSEric Cheng return (DLADM_STATUS_OK); 4277da14cebeSEric Cheng } 4278da14cebeSEric Cheng } 4279da14cebeSEric Cheng 42804ac67f02SAnurag S. Maskey /* ARGSUSED */ 4281da14cebeSEric Cheng static int 42824ac67f02SAnurag S. Maskey show_vnic(dladm_handle_t dh, datalink_id_t linkid, void *arg) 4283da14cebeSEric Cheng { 4284da14cebeSEric Cheng show_vnic_state_t *state = arg; 4285da14cebeSEric Cheng 4286da14cebeSEric Cheng state->vs_status = print_vnic(state, linkid); 4287da14cebeSEric Cheng return (DLADM_WALK_CONTINUE); 4288da14cebeSEric Cheng } 4289da14cebeSEric Cheng 4290da14cebeSEric Cheng static void 4291da14cebeSEric Cheng do_show_vnic_common(int argc, char *argv[], const char *use, 4292da14cebeSEric Cheng boolean_t etherstub) 4293da14cebeSEric Cheng { 4294da14cebeSEric Cheng int option; 4295da14cebeSEric Cheng boolean_t s_arg = B_FALSE; 4296da14cebeSEric Cheng boolean_t i_arg = B_FALSE; 4297da14cebeSEric Cheng boolean_t l_arg = B_FALSE; 4298da14cebeSEric Cheng char *endp = NULL; 4299da14cebeSEric Cheng uint32_t interval = 0, flags = DLADM_OPT_ACTIVE; 4300da14cebeSEric Cheng datalink_id_t linkid = DATALINK_ALL_LINKID; 4301da14cebeSEric Cheng datalink_id_t dev_linkid = DATALINK_ALL_LINKID; 4302da14cebeSEric Cheng show_vnic_state_t state; 4303da14cebeSEric Cheng dladm_status_t status; 4304da14cebeSEric Cheng boolean_t o_arg = B_FALSE; 4305da14cebeSEric Cheng char *fields_str = NULL; 4306da14cebeSEric Cheng print_field_t **fields; 4307da14cebeSEric Cheng print_field_t *pf; 4308da14cebeSEric Cheng int pfmax; 4309da14cebeSEric Cheng uint_t nfields; 4310da14cebeSEric Cheng char *all_fields = 4311ae6aa22aSVenugopal Iyer "link,over,speed,macaddress,macaddrtype,vid"; 4312da14cebeSEric Cheng char *all_e_fields = 4313da14cebeSEric Cheng "link"; 4314da14cebeSEric Cheng 4315da14cebeSEric Cheng bzero(&state, sizeof (state)); 4316da14cebeSEric Cheng opterr = 0; 4317da14cebeSEric Cheng while ((option = getopt_long(argc, argv, ":pPl:si:o:", lopts, 4318da14cebeSEric Cheng NULL)) != -1) { 4319da14cebeSEric Cheng switch (option) { 4320da14cebeSEric Cheng case 'p': 4321da14cebeSEric Cheng state.vs_parseable = B_TRUE; 4322da14cebeSEric Cheng break; 4323da14cebeSEric Cheng case 'P': 4324da14cebeSEric Cheng flags = DLADM_OPT_PERSIST; 4325da14cebeSEric Cheng break; 4326da14cebeSEric Cheng case 'l': 4327da14cebeSEric Cheng if (etherstub) 4328da14cebeSEric Cheng die("option not supported for this command"); 4329da14cebeSEric Cheng 4330da14cebeSEric Cheng if (strlcpy(state.vs_link, optarg, MAXLINKNAMELEN) >= 4331da14cebeSEric Cheng MAXLINKNAMELEN) 4332da14cebeSEric Cheng die("link name too long"); 4333da14cebeSEric Cheng 4334da14cebeSEric Cheng l_arg = B_TRUE; 4335da14cebeSEric Cheng break; 4336da14cebeSEric Cheng case 's': 4337da14cebeSEric Cheng if (s_arg) { 4338da14cebeSEric Cheng die("the option -s cannot be specified " 4339da14cebeSEric Cheng "more than once"); 4340da14cebeSEric Cheng } 4341da14cebeSEric Cheng s_arg = B_TRUE; 4342da14cebeSEric Cheng break; 4343da14cebeSEric Cheng case 'i': 4344da14cebeSEric Cheng if (i_arg) { 4345da14cebeSEric Cheng die("the option -i cannot be specified " 4346da14cebeSEric Cheng "more than once"); 4347da14cebeSEric Cheng } 4348da14cebeSEric Cheng i_arg = B_TRUE; 4349da14cebeSEric Cheng interval = (int)strtol(optarg, &endp, 10); 4350da14cebeSEric Cheng if (errno != 0 || interval == 0 || *endp != '\0') 4351da14cebeSEric Cheng die("invalid interval value '%s'", optarg); 4352da14cebeSEric Cheng break; 4353da14cebeSEric Cheng case 'o': 4354da14cebeSEric Cheng o_arg = B_TRUE; 4355da14cebeSEric Cheng fields_str = optarg; 4356da14cebeSEric Cheng break; 4357da14cebeSEric Cheng default: 4358da14cebeSEric Cheng die_opterr(optopt, option, use); 4359da14cebeSEric Cheng } 4360da14cebeSEric Cheng } 4361da14cebeSEric Cheng 4362ad091ee1SMichael Lim if (state.vs_parseable && !o_arg) 4363ad091ee1SMichael Lim die("-p requires -o"); 4364ad091ee1SMichael Lim 4365ad091ee1SMichael Lim if (state.vs_parseable && strcasecmp(fields_str, "all") == 0) 4366ad091ee1SMichael Lim die("\"-o all\" is invalid with -p"); 4367ad091ee1SMichael Lim 4368da14cebeSEric Cheng if (i_arg && !s_arg) 4369da14cebeSEric Cheng die("the option -i can be used only with -s"); 4370da14cebeSEric Cheng 4371da14cebeSEric Cheng /* get vnic ID (optional last argument) */ 4372da14cebeSEric Cheng if (optind == (argc - 1)) { 43734ac67f02SAnurag S. Maskey status = dladm_name2info(handle, argv[optind], &linkid, NULL, 4374da14cebeSEric Cheng NULL, NULL); 4375da14cebeSEric Cheng if (status != DLADM_STATUS_OK) { 4376da14cebeSEric Cheng die_dlerr(status, "invalid vnic name '%s'", 4377da14cebeSEric Cheng argv[optind]); 4378da14cebeSEric Cheng } 4379da14cebeSEric Cheng (void) strlcpy(state.vs_vnic, argv[optind], MAXLINKNAMELEN); 4380da14cebeSEric Cheng } else if (optind != argc) { 4381da14cebeSEric Cheng usage(); 4382da14cebeSEric Cheng } 4383da14cebeSEric Cheng 4384da14cebeSEric Cheng if (l_arg) { 43854ac67f02SAnurag S. Maskey status = dladm_name2info(handle, state.vs_link, &dev_linkid, 43864ac67f02SAnurag S. Maskey NULL, NULL, NULL); 4387da14cebeSEric Cheng if (status != DLADM_STATUS_OK) { 4388da14cebeSEric Cheng die_dlerr(status, "invalid link name '%s'", 4389da14cebeSEric Cheng state.vs_link); 4390da14cebeSEric Cheng } 4391da14cebeSEric Cheng } 4392da14cebeSEric Cheng 4393da14cebeSEric Cheng state.vs_vnic_id = linkid; 4394da14cebeSEric Cheng state.vs_link_id = dev_linkid; 4395da14cebeSEric Cheng state.vs_etherstub = etherstub; 4396da14cebeSEric Cheng state.vs_found = B_FALSE; 4397da14cebeSEric Cheng state.vs_flags = flags; 4398da14cebeSEric Cheng 4399da14cebeSEric Cheng if (!o_arg || (o_arg && strcasecmp(fields_str, "all") == 0)) { 4400da14cebeSEric Cheng if (etherstub) 4401da14cebeSEric Cheng fields_str = all_e_fields; 4402da14cebeSEric Cheng else 4403da14cebeSEric Cheng fields_str = all_fields; 4404da14cebeSEric Cheng } 4405da14cebeSEric Cheng 4406da14cebeSEric Cheng pf = vnic_fields; 4407da14cebeSEric Cheng pfmax = VNIC_MAX_FIELDS; 4408da14cebeSEric Cheng 4409da14cebeSEric Cheng fields = parse_output_fields(fields_str, pf, pfmax, CMD_TYPE_ANY, 4410da14cebeSEric Cheng &nfields); 4411da14cebeSEric Cheng 4412da14cebeSEric Cheng if (fields == NULL) { 4413da14cebeSEric Cheng die("invalid field(s) specified"); 4414da14cebeSEric Cheng return; 4415da14cebeSEric Cheng } 4416da14cebeSEric Cheng 4417da14cebeSEric Cheng state.vs_print.ps_fields = fields; 4418da14cebeSEric Cheng state.vs_print.ps_nfields = nfields; 4419da14cebeSEric Cheng 4420da14cebeSEric Cheng if (s_arg) { 4421da14cebeSEric Cheng /* Display vnic statistics */ 4422da14cebeSEric Cheng vnic_stats(&state, interval); 4423da14cebeSEric Cheng return; 4424da14cebeSEric Cheng } 4425da14cebeSEric Cheng 4426da14cebeSEric Cheng /* Display vnic information */ 4427da14cebeSEric Cheng state.vs_donefirst = B_FALSE; 4428da14cebeSEric Cheng 4429da14cebeSEric Cheng if (linkid == DATALINK_ALL_LINKID) { 44304ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(show_vnic, handle, &state, 4431da14cebeSEric Cheng DATALINK_CLASS_VNIC | DATALINK_CLASS_ETHERSTUB, 4432da14cebeSEric Cheng DATALINK_ANY_MEDIATYPE, DLADM_OPT_ACTIVE); 4433da14cebeSEric Cheng } else { 44344ac67f02SAnurag S. Maskey (void) show_vnic(handle, linkid, &state); 4435da14cebeSEric Cheng if (state.vs_status != DLADM_STATUS_OK) { 4436da14cebeSEric Cheng die_dlerr(state.vs_status, "failed to show vnic '%s'", 4437da14cebeSEric Cheng state.vs_vnic); 4438da14cebeSEric Cheng } 4439da14cebeSEric Cheng } 4440da14cebeSEric Cheng } 4441da14cebeSEric Cheng 4442da14cebeSEric Cheng static void 4443da14cebeSEric Cheng do_show_vnic(int argc, char *argv[], const char *use) 4444da14cebeSEric Cheng { 4445da14cebeSEric Cheng do_show_vnic_common(argc, argv, use, B_FALSE); 4446da14cebeSEric Cheng } 4447da14cebeSEric Cheng 4448da14cebeSEric Cheng static void 4449da14cebeSEric Cheng do_create_etherstub(int argc, char *argv[], const char *use) 4450da14cebeSEric Cheng { 4451da14cebeSEric Cheng uint32_t flags; 4452da14cebeSEric Cheng char *altroot = NULL; 4453da14cebeSEric Cheng char option; 4454da14cebeSEric Cheng dladm_status_t status; 4455da14cebeSEric Cheng char name[MAXLINKNAMELEN]; 4456da14cebeSEric Cheng uchar_t mac_addr[ETHERADDRL]; 4457da14cebeSEric Cheng 4458da14cebeSEric Cheng name[0] = '\0'; 4459da14cebeSEric Cheng bzero(mac_addr, sizeof (mac_addr)); 4460da14cebeSEric Cheng flags = DLADM_OPT_ANCHOR | DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST; 4461da14cebeSEric Cheng 4462da14cebeSEric Cheng opterr = 0; 4463da14cebeSEric Cheng while ((option = getopt_long(argc, argv, "tR:", 4464da14cebeSEric Cheng etherstub_lopts, NULL)) != -1) { 4465da14cebeSEric Cheng switch (option) { 4466da14cebeSEric Cheng case 't': 4467da14cebeSEric Cheng flags &= ~DLADM_OPT_PERSIST; 4468da14cebeSEric Cheng break; 4469da14cebeSEric Cheng case 'R': 4470da14cebeSEric Cheng altroot = optarg; 4471da14cebeSEric Cheng break; 4472da14cebeSEric Cheng default: 4473da14cebeSEric Cheng die_opterr(optopt, option, use); 4474da14cebeSEric Cheng } 4475da14cebeSEric Cheng } 4476da14cebeSEric Cheng 4477da14cebeSEric Cheng /* the etherstub id is the required operand */ 4478da14cebeSEric Cheng if (optind != (argc - 1)) 4479da14cebeSEric Cheng usage(); 4480da14cebeSEric Cheng 4481da14cebeSEric Cheng if (strlcpy(name, argv[optind], MAXLINKNAMELEN) >= MAXLINKNAMELEN) 4482da14cebeSEric Cheng die("link name too long '%s'", argv[optind]); 4483da14cebeSEric Cheng 4484da14cebeSEric Cheng if (!dladm_valid_linkname(name)) 4485da14cebeSEric Cheng die("invalid link name '%s'", argv[optind]); 4486da14cebeSEric Cheng 4487da14cebeSEric Cheng if (altroot != NULL) 4488da14cebeSEric Cheng altroot_cmd(altroot, argc, argv); 4489da14cebeSEric Cheng 44904ac67f02SAnurag S. Maskey status = dladm_vnic_create(handle, name, DATALINK_INVALID_LINKID, 4491da14cebeSEric Cheng VNIC_MAC_ADDR_TYPE_AUTO, mac_addr, ETHERADDRL, NULL, 0, 0, NULL, 4492da14cebeSEric Cheng NULL, flags); 4493da14cebeSEric Cheng if (status != DLADM_STATUS_OK) 4494da14cebeSEric Cheng die_dlerr(status, "etherstub creation failed"); 4495da14cebeSEric Cheng 4496da14cebeSEric Cheng 4497da14cebeSEric Cheng } 4498da14cebeSEric Cheng 4499da14cebeSEric Cheng static void 4500da14cebeSEric Cheng do_delete_etherstub(int argc, char *argv[], const char *use) 4501da14cebeSEric Cheng { 4502da14cebeSEric Cheng do_delete_vnic_common(argc, argv, use, B_TRUE); 4503da14cebeSEric Cheng } 4504da14cebeSEric Cheng 4505da14cebeSEric Cheng /* ARGSUSED */ 4506da14cebeSEric Cheng static void 4507da14cebeSEric Cheng do_show_etherstub(int argc, char *argv[], const char *use) 4508da14cebeSEric Cheng { 4509da14cebeSEric Cheng do_show_vnic_common(argc, argv, use, B_TRUE); 4510da14cebeSEric Cheng } 4511da14cebeSEric Cheng 4512da14cebeSEric Cheng static void 45136be03d0bSVasumathi Sundaram - Sun Microsystems link_stats(datalink_id_t linkid, uint_t interval, char *fields_str, 45146be03d0bSVasumathi Sundaram - Sun Microsystems show_state_t *state) 4515d62bc4baSyz147064 { 45166be03d0bSVasumathi Sundaram - Sun Microsystems print_field_t **fields; 45176be03d0bSVasumathi Sundaram - Sun Microsystems uint_t nfields; 451833343a97Smeem 4519ae6aa22aSVenugopal Iyer fields = parse_output_fields(fields_str, link_s_fields, 4520ae6aa22aSVenugopal Iyer LINK_S_MAX_FIELDS, CMD_TYPE_ANY, &nfields); 45216be03d0bSVasumathi Sundaram - Sun Microsystems if (fields == NULL) { 45226be03d0bSVasumathi Sundaram - Sun Microsystems die("invalid field(s) specified"); 45236be03d0bSVasumathi Sundaram - Sun Microsystems return; 45246be03d0bSVasumathi Sundaram - Sun Microsystems } 45256be03d0bSVasumathi Sundaram - Sun Microsystems 45266be03d0bSVasumathi Sundaram - Sun Microsystems state->ls_print.ps_fields = fields; 45276be03d0bSVasumathi Sundaram - Sun Microsystems state->ls_print.ps_nfields = nfields; 45287c478bd9Sstevel@tonic-gate 45297c478bd9Sstevel@tonic-gate /* 45307c478bd9Sstevel@tonic-gate * If an interval is specified, continuously show the stats 45317c478bd9Sstevel@tonic-gate * only for the first MAC port. 45327c478bd9Sstevel@tonic-gate */ 45336be03d0bSVasumathi Sundaram - Sun Microsystems state->ls_firstonly = (interval != 0); 45347c478bd9Sstevel@tonic-gate 45356be03d0bSVasumathi Sundaram - Sun Microsystems if (!state->ls_parseable) 45366be03d0bSVasumathi Sundaram - Sun Microsystems print_header(&state->ls_print); 45377c478bd9Sstevel@tonic-gate for (;;) { 45386be03d0bSVasumathi Sundaram - Sun Microsystems state->ls_donefirst = B_FALSE; 4539d62bc4baSyz147064 if (linkid == DATALINK_ALL_LINKID) { 45404ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(show_link_stats, handle, 45414ac67f02SAnurag S. Maskey state, DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE, 4542d62bc4baSyz147064 DLADM_OPT_ACTIVE); 4543d62bc4baSyz147064 } else { 45444ac67f02SAnurag S. Maskey (void) show_link_stats(handle, linkid, state); 4545d62bc4baSyz147064 } 45467c478bd9Sstevel@tonic-gate 45477c478bd9Sstevel@tonic-gate if (interval == 0) 45487c478bd9Sstevel@tonic-gate break; 45497c478bd9Sstevel@tonic-gate 45507c478bd9Sstevel@tonic-gate (void) sleep(interval); 45517c478bd9Sstevel@tonic-gate } 45527c478bd9Sstevel@tonic-gate } 45537c478bd9Sstevel@tonic-gate 45547c478bd9Sstevel@tonic-gate static void 4555d62bc4baSyz147064 aggr_stats(datalink_id_t linkid, show_grp_state_t *state, uint_t interval) 45567c478bd9Sstevel@tonic-gate { 45577c478bd9Sstevel@tonic-gate /* 45587c478bd9Sstevel@tonic-gate * If an interval is specified, continuously show the stats 45597c478bd9Sstevel@tonic-gate * only for the first group. 45607c478bd9Sstevel@tonic-gate */ 4561d62bc4baSyz147064 state->gs_firstonly = (interval != 0); 45627c478bd9Sstevel@tonic-gate 45637c478bd9Sstevel@tonic-gate for (;;) { 4564d62bc4baSyz147064 state->gs_donefirst = B_FALSE; 4565d62bc4baSyz147064 if (linkid == DATALINK_ALL_LINKID) 45664ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(show_aggr, handle, state, 4567d62bc4baSyz147064 DATALINK_CLASS_AGGR, DATALINK_ANY_MEDIATYPE, 4568d62bc4baSyz147064 DLADM_OPT_ACTIVE); 4569d62bc4baSyz147064 else 45704ac67f02SAnurag S. Maskey (void) show_aggr(handle, linkid, state); 45717c478bd9Sstevel@tonic-gate 45727c478bd9Sstevel@tonic-gate if (interval == 0) 45737c478bd9Sstevel@tonic-gate break; 45747c478bd9Sstevel@tonic-gate 45757c478bd9Sstevel@tonic-gate (void) sleep(interval); 45767c478bd9Sstevel@tonic-gate } 45777c478bd9Sstevel@tonic-gate } 45787c478bd9Sstevel@tonic-gate 4579da14cebeSEric Cheng /* ARGSUSED */ 45807c478bd9Sstevel@tonic-gate static void 4581da14cebeSEric Cheng vnic_stats(show_vnic_state_t *sp, uint32_t interval) 45827c478bd9Sstevel@tonic-gate { 4583da14cebeSEric Cheng show_vnic_state_t state; 4584da14cebeSEric Cheng boolean_t specific_link, specific_dev; 45857c478bd9Sstevel@tonic-gate 4586da14cebeSEric Cheng /* Display vnic statistics */ 4587da14cebeSEric Cheng dump_vnics_head(sp->vs_link); 4588e7801d59Ssowmini 4589da14cebeSEric Cheng bzero(&state, sizeof (state)); 4590da14cebeSEric Cheng state.vs_stats = B_TRUE; 4591da14cebeSEric Cheng state.vs_vnic_id = sp->vs_vnic_id; 4592da14cebeSEric Cheng state.vs_link_id = sp->vs_link_id; 45937c478bd9Sstevel@tonic-gate 45947c478bd9Sstevel@tonic-gate /* 4595da14cebeSEric Cheng * If an interval is specified, and a vnic ID is not specified, 4596da14cebeSEric Cheng * continuously show the stats only for the first vnic. 45977c478bd9Sstevel@tonic-gate */ 4598da14cebeSEric Cheng specific_link = (sp->vs_vnic_id != DATALINK_ALL_LINKID); 4599da14cebeSEric Cheng specific_dev = (sp->vs_link_id != DATALINK_ALL_LINKID); 46007c478bd9Sstevel@tonic-gate 46017c478bd9Sstevel@tonic-gate for (;;) { 4602da14cebeSEric Cheng /* Get stats for each vnic */ 4603da14cebeSEric Cheng state.vs_found = B_FALSE; 4604da14cebeSEric Cheng state.vs_donefirst = B_FALSE; 4605da14cebeSEric Cheng state.vs_printstats = B_FALSE; 4606da14cebeSEric Cheng state.vs_flags = DLADM_OPT_ACTIVE; 46077c478bd9Sstevel@tonic-gate 4608da14cebeSEric Cheng if (!specific_link) { 46094ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(show_vnic, handle, &state, 4610da14cebeSEric Cheng DATALINK_CLASS_VNIC, DATALINK_ANY_MEDIATYPE, 4611da14cebeSEric Cheng DLADM_OPT_ACTIVE); 4612da14cebeSEric Cheng } else { 46134ac67f02SAnurag S. Maskey (void) show_vnic(handle, sp->vs_vnic_id, &state); 4614da14cebeSEric Cheng if (state.vs_status != DLADM_STATUS_OK) { 4615da14cebeSEric Cheng die_dlerr(state.vs_status, 4616da14cebeSEric Cheng "failed to show vnic '%s'", sp->vs_vnic); 4617da14cebeSEric Cheng } 4618da14cebeSEric Cheng } 46197c478bd9Sstevel@tonic-gate 4620da14cebeSEric Cheng if (specific_link && !state.vs_found) 4621da14cebeSEric Cheng die("non-existent vnic '%s'", sp->vs_vnic); 4622da14cebeSEric Cheng if (specific_dev && !state.vs_found) 4623da14cebeSEric Cheng die("device %s has no vnics", sp->vs_link); 4624da14cebeSEric Cheng 4625da14cebeSEric Cheng /* Show totals */ 4626da14cebeSEric Cheng if ((specific_link | specific_dev) && !interval) { 4627da14cebeSEric Cheng (void) printf("Total"); 4628da14cebeSEric Cheng (void) printf("\t%-10llu", 4629da14cebeSEric Cheng state.vs_totalstats.ipackets); 4630da14cebeSEric Cheng (void) printf("%-12llu", 4631da14cebeSEric Cheng state.vs_totalstats.rbytes); 4632da14cebeSEric Cheng (void) printf("%-10llu", 4633da14cebeSEric Cheng state.vs_totalstats.opackets); 4634da14cebeSEric Cheng (void) printf("%-12llu\n", 4635da14cebeSEric Cheng state.vs_totalstats.obytes); 4636da14cebeSEric Cheng } 4637da14cebeSEric Cheng 4638da14cebeSEric Cheng /* Show stats for each vnic */ 4639da14cebeSEric Cheng state.vs_donefirst = B_FALSE; 4640da14cebeSEric Cheng state.vs_printstats = B_TRUE; 4641da14cebeSEric Cheng 4642da14cebeSEric Cheng if (!specific_link) { 46434ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(show_vnic, handle, &state, 4644da14cebeSEric Cheng DATALINK_CLASS_VNIC, DATALINK_ANY_MEDIATYPE, 4645da14cebeSEric Cheng DLADM_OPT_ACTIVE); 4646da14cebeSEric Cheng } else { 46474ac67f02SAnurag S. Maskey (void) show_vnic(handle, sp->vs_vnic_id, &state); 4648da14cebeSEric Cheng if (state.vs_status != DLADM_STATUS_OK) { 4649da14cebeSEric Cheng die_dlerr(state.vs_status, 4650da14cebeSEric Cheng "failed to show vnic '%s'", sp->vs_vnic); 4651da14cebeSEric Cheng } 4652da14cebeSEric Cheng } 46537c478bd9Sstevel@tonic-gate 46547c478bd9Sstevel@tonic-gate if (interval == 0) 46557c478bd9Sstevel@tonic-gate break; 46567c478bd9Sstevel@tonic-gate 46577c478bd9Sstevel@tonic-gate (void) sleep(interval); 46587c478bd9Sstevel@tonic-gate } 46597c478bd9Sstevel@tonic-gate } 46607c478bd9Sstevel@tonic-gate 46617c478bd9Sstevel@tonic-gate static void 4662da14cebeSEric Cheng get_mac_stats(const char *dev, pktsum_t *stats) 46637c478bd9Sstevel@tonic-gate { 46647c478bd9Sstevel@tonic-gate kstat_ctl_t *kcp; 46657c478bd9Sstevel@tonic-gate kstat_t *ksp; 4666da14cebeSEric Cheng char module[DLPI_LINKNAME_MAX]; 4667da14cebeSEric Cheng uint_t instance; 4668da14cebeSEric Cheng 4669da14cebeSEric Cheng 4670da14cebeSEric Cheng bzero(stats, sizeof (*stats)); 4671da14cebeSEric Cheng 4672da14cebeSEric Cheng if (dlpi_parselink(dev, module, &instance) != DLPI_SUCCESS) 4673da14cebeSEric Cheng return; 46747c478bd9Sstevel@tonic-gate 46757c478bd9Sstevel@tonic-gate if ((kcp = kstat_open()) == NULL) { 467633343a97Smeem warn("kstat open operation failed"); 46777c478bd9Sstevel@tonic-gate return; 46787c478bd9Sstevel@tonic-gate } 46797c478bd9Sstevel@tonic-gate 4680da14cebeSEric Cheng ksp = dladm_kstat_lookup(kcp, module, instance, "mac", NULL); 4681da14cebeSEric Cheng if (ksp != NULL) 4682da14cebeSEric Cheng dladm_get_stats(kcp, ksp, stats); 4683da14cebeSEric Cheng 46847c478bd9Sstevel@tonic-gate (void) kstat_close(kcp); 46857c478bd9Sstevel@tonic-gate 46867c478bd9Sstevel@tonic-gate } 46877c478bd9Sstevel@tonic-gate 46887c478bd9Sstevel@tonic-gate static void 46897c478bd9Sstevel@tonic-gate get_link_stats(const char *link, pktsum_t *stats) 46907c478bd9Sstevel@tonic-gate { 4691da14cebeSEric Cheng kstat_ctl_t *kcp; 4692da14cebeSEric Cheng kstat_t *ksp; 4693da14cebeSEric Cheng 46947c478bd9Sstevel@tonic-gate bzero(stats, sizeof (*stats)); 4695da14cebeSEric Cheng 4696da14cebeSEric Cheng if ((kcp = kstat_open()) == NULL) { 4697da14cebeSEric Cheng warn("kstat_open operation failed"); 4698da14cebeSEric Cheng return; 4699da14cebeSEric Cheng } 4700da14cebeSEric Cheng 4701da14cebeSEric Cheng ksp = dladm_kstat_lookup(kcp, "link", 0, link, NULL); 4702da14cebeSEric Cheng 4703da14cebeSEric Cheng if (ksp != NULL) 4704da14cebeSEric Cheng dladm_get_stats(kcp, ksp, stats); 4705da14cebeSEric Cheng 4706da14cebeSEric Cheng (void) kstat_close(kcp); 47077c478bd9Sstevel@tonic-gate } 47087c478bd9Sstevel@tonic-gate 4709ba2e4443Sseb static int 4710d62bc4baSyz147064 query_kstat(char *module, int instance, const char *name, const char *stat, 4711d62bc4baSyz147064 uint8_t type, void *val) 47127c478bd9Sstevel@tonic-gate { 47137c478bd9Sstevel@tonic-gate kstat_ctl_t *kcp; 47147c478bd9Sstevel@tonic-gate kstat_t *ksp; 47157c478bd9Sstevel@tonic-gate 47167c478bd9Sstevel@tonic-gate if ((kcp = kstat_open()) == NULL) { 471733343a97Smeem warn("kstat open operation failed"); 4718ba2e4443Sseb return (-1); 47197c478bd9Sstevel@tonic-gate } 47207c478bd9Sstevel@tonic-gate 4721d62bc4baSyz147064 if ((ksp = kstat_lookup(kcp, module, instance, (char *)name)) == NULL) { 47227c478bd9Sstevel@tonic-gate /* 47237c478bd9Sstevel@tonic-gate * The kstat query could fail if the underlying MAC 47247c478bd9Sstevel@tonic-gate * driver was already detached. 47257c478bd9Sstevel@tonic-gate */ 47267c478bd9Sstevel@tonic-gate goto bail; 47277c478bd9Sstevel@tonic-gate } 47287c478bd9Sstevel@tonic-gate 47297c478bd9Sstevel@tonic-gate if (kstat_read(kcp, ksp, NULL) == -1) { 473033343a97Smeem warn("kstat read failed"); 47317c478bd9Sstevel@tonic-gate goto bail; 47327c478bd9Sstevel@tonic-gate } 47337c478bd9Sstevel@tonic-gate 4734e7801d59Ssowmini if (dladm_kstat_value(ksp, stat, type, val) < 0) 47357c478bd9Sstevel@tonic-gate goto bail; 4736ba2e4443Sseb 4737ba2e4443Sseb (void) kstat_close(kcp); 4738ba2e4443Sseb return (0); 47397c478bd9Sstevel@tonic-gate 47407c478bd9Sstevel@tonic-gate bail: 47417c478bd9Sstevel@tonic-gate (void) kstat_close(kcp); 4742ba2e4443Sseb return (-1); 4743ba2e4443Sseb } 4744ba2e4443Sseb 4745d62bc4baSyz147064 static int 4746d62bc4baSyz147064 get_one_kstat(const char *name, const char *stat, uint8_t type, 4747d62bc4baSyz147064 void *val, boolean_t islink) 4748d62bc4baSyz147064 { 4749d62bc4baSyz147064 char module[DLPI_LINKNAME_MAX]; 4750d62bc4baSyz147064 uint_t instance; 4751d62bc4baSyz147064 4752d62bc4baSyz147064 if (islink) { 4753d62bc4baSyz147064 return (query_kstat("link", 0, name, stat, type, val)); 4754d62bc4baSyz147064 } else { 4755d62bc4baSyz147064 if (dlpi_parselink(name, module, &instance) != DLPI_SUCCESS) 4756d62bc4baSyz147064 return (-1); 4757d62bc4baSyz147064 4758d62bc4baSyz147064 return (query_kstat(module, instance, "mac", stat, type, val)); 4759d62bc4baSyz147064 } 4760d62bc4baSyz147064 } 4761d62bc4baSyz147064 4762ba2e4443Sseb static uint64_t 4763d62bc4baSyz147064 get_ifspeed(const char *name, boolean_t islink) 4764ba2e4443Sseb { 4765ba2e4443Sseb uint64_t ifspeed = 0; 4766ba2e4443Sseb 4767d62bc4baSyz147064 (void) get_one_kstat(name, "ifspeed", KSTAT_DATA_UINT64, 4768d62bc4baSyz147064 &ifspeed, islink); 4769d62bc4baSyz147064 47707c478bd9Sstevel@tonic-gate return (ifspeed); 47717c478bd9Sstevel@tonic-gate } 47727c478bd9Sstevel@tonic-gate 4773f595a68aSyz147064 static const char * 4774d62bc4baSyz147064 get_linkstate(const char *name, boolean_t islink, char *buf) 47757c478bd9Sstevel@tonic-gate { 4776d62bc4baSyz147064 link_state_t linkstate; 47777c478bd9Sstevel@tonic-gate 4778d62bc4baSyz147064 if (get_one_kstat(name, "link_state", KSTAT_DATA_UINT32, 4779d62bc4baSyz147064 &linkstate, islink) != 0) { 4780da14cebeSEric Cheng (void) strlcpy(buf, "?", DLADM_STRSIZE); 47813a62633bSyz147064 return (buf); 47827c478bd9Sstevel@tonic-gate } 4783d62bc4baSyz147064 return (dladm_linkstate2str(linkstate, buf)); 47847c478bd9Sstevel@tonic-gate } 47857c478bd9Sstevel@tonic-gate 4786f595a68aSyz147064 static const char * 4787d62bc4baSyz147064 get_linkduplex(const char *name, boolean_t islink, char *buf) 47887c478bd9Sstevel@tonic-gate { 4789d62bc4baSyz147064 link_duplex_t linkduplex; 47907c478bd9Sstevel@tonic-gate 4791d62bc4baSyz147064 if (get_one_kstat(name, "link_duplex", KSTAT_DATA_UINT32, 4792d62bc4baSyz147064 &linkduplex, islink) != 0) { 47933a62633bSyz147064 (void) strlcpy(buf, "unknown", DLADM_STRSIZE); 47943a62633bSyz147064 return (buf); 47957c478bd9Sstevel@tonic-gate } 47967c478bd9Sstevel@tonic-gate 4797d62bc4baSyz147064 return (dladm_linkduplex2str(linkduplex, buf)); 47987c478bd9Sstevel@tonic-gate } 47990ba2cbe9Sxc151355 48000ba2cbe9Sxc151355 typedef struct { 48010ba2cbe9Sxc151355 char *s_buf; 48020ba2cbe9Sxc151355 char **s_fields; /* array of pointer to the fields in s_buf */ 48030ba2cbe9Sxc151355 uint_t s_nfields; /* the number of fields in s_buf */ 48040ba2cbe9Sxc151355 } split_t; 48050ba2cbe9Sxc151355 48060ba2cbe9Sxc151355 /* 48070ba2cbe9Sxc151355 * Free the split_t structure pointed to by `sp'. 48080ba2cbe9Sxc151355 */ 48090ba2cbe9Sxc151355 static void 48100ba2cbe9Sxc151355 splitfree(split_t *sp) 48110ba2cbe9Sxc151355 { 48120ba2cbe9Sxc151355 free(sp->s_buf); 48130ba2cbe9Sxc151355 free(sp->s_fields); 48140ba2cbe9Sxc151355 free(sp); 48150ba2cbe9Sxc151355 } 48160ba2cbe9Sxc151355 48170ba2cbe9Sxc151355 /* 48180ba2cbe9Sxc151355 * Split `str' into at most `maxfields' fields, each field at most `maxlen' in 48190ba2cbe9Sxc151355 * length. Return a pointer to a split_t containing the split fields, or NULL 48200ba2cbe9Sxc151355 * on failure. 48210ba2cbe9Sxc151355 */ 48220ba2cbe9Sxc151355 static split_t * 48230ba2cbe9Sxc151355 split(const char *str, uint_t maxfields, uint_t maxlen) 48240ba2cbe9Sxc151355 { 48250ba2cbe9Sxc151355 char *field, *token, *lasts = NULL; 48260ba2cbe9Sxc151355 split_t *sp; 48270ba2cbe9Sxc151355 48280ba2cbe9Sxc151355 if (*str == '\0' || maxfields == 0 || maxlen == 0) 48290ba2cbe9Sxc151355 return (NULL); 48300ba2cbe9Sxc151355 48310ba2cbe9Sxc151355 sp = calloc(sizeof (split_t), 1); 48320ba2cbe9Sxc151355 if (sp == NULL) 48330ba2cbe9Sxc151355 return (NULL); 48340ba2cbe9Sxc151355 48350ba2cbe9Sxc151355 sp->s_buf = strdup(str); 48360ba2cbe9Sxc151355 sp->s_fields = malloc(sizeof (char *) * maxfields); 48370ba2cbe9Sxc151355 if (sp->s_buf == NULL || sp->s_fields == NULL) 48380ba2cbe9Sxc151355 goto fail; 48390ba2cbe9Sxc151355 48400ba2cbe9Sxc151355 token = sp->s_buf; 48410ba2cbe9Sxc151355 while ((field = strtok_r(token, ",", &lasts)) != NULL) { 48420ba2cbe9Sxc151355 if (sp->s_nfields == maxfields || strlen(field) > maxlen) 48430ba2cbe9Sxc151355 goto fail; 48440ba2cbe9Sxc151355 token = NULL; 48450ba2cbe9Sxc151355 sp->s_fields[sp->s_nfields++] = field; 48460ba2cbe9Sxc151355 } 48470ba2cbe9Sxc151355 return (sp); 48480ba2cbe9Sxc151355 fail: 48490ba2cbe9Sxc151355 splitfree(sp); 48500ba2cbe9Sxc151355 return (NULL); 48510ba2cbe9Sxc151355 } 48520ba2cbe9Sxc151355 48530ba2cbe9Sxc151355 static int 4854e7801d59Ssowmini parse_wifi_fields(char *str, print_field_t ***fields, uint_t *countp, 48550ba2cbe9Sxc151355 uint_t cmdtype) 48560ba2cbe9Sxc151355 { 48570ba2cbe9Sxc151355 48580ba2cbe9Sxc151355 if (cmdtype == WIFI_CMD_SCAN) { 48590ba2cbe9Sxc151355 if (str == NULL) 48600ba2cbe9Sxc151355 str = def_scan_wifi_fields; 48610ba2cbe9Sxc151355 if (strcasecmp(str, "all") == 0) 48620ba2cbe9Sxc151355 str = all_scan_wifi_fields; 48630ba2cbe9Sxc151355 } else if (cmdtype == WIFI_CMD_SHOW) { 48640ba2cbe9Sxc151355 if (str == NULL) 48650ba2cbe9Sxc151355 str = def_show_wifi_fields; 48660ba2cbe9Sxc151355 if (strcasecmp(str, "all") == 0) 48670ba2cbe9Sxc151355 str = all_show_wifi_fields; 48680ba2cbe9Sxc151355 } else { 48690ba2cbe9Sxc151355 return (-1); 48700ba2cbe9Sxc151355 } 4871e7801d59Ssowmini *fields = parse_output_fields(str, wifi_fields, WIFI_MAX_FIELDS, 4872e7801d59Ssowmini cmdtype, countp); 4873e7801d59Ssowmini if (*fields != NULL) 4874e7801d59Ssowmini return (0); 48750ba2cbe9Sxc151355 return (-1); 4876e7801d59Ssowmini } 4877e7801d59Ssowmini static print_field_t ** 4878e7801d59Ssowmini parse_output_fields(char *str, print_field_t *template, int max_fields, 4879e7801d59Ssowmini uint_t cmdtype, uint_t *countp) 4880e7801d59Ssowmini { 4881e7801d59Ssowmini split_t *sp; 4882e7801d59Ssowmini boolean_t good_match = B_FALSE; 4883e7801d59Ssowmini uint_t i, j; 4884e7801d59Ssowmini print_field_t **pf = NULL; 48850ba2cbe9Sxc151355 4886e7801d59Ssowmini sp = split(str, max_fields, MAX_FIELD_LEN); 4887e7801d59Ssowmini 4888e7801d59Ssowmini if (sp == NULL) 4889e7801d59Ssowmini return (NULL); 4890e7801d59Ssowmini 4891e7801d59Ssowmini pf = malloc(sp->s_nfields * sizeof (print_field_t *)); 4892e7801d59Ssowmini if (pf == NULL) 48930ba2cbe9Sxc151355 goto fail; 48940ba2cbe9Sxc151355 48950ba2cbe9Sxc151355 for (i = 0; i < sp->s_nfields; i++) { 4896e7801d59Ssowmini for (j = 0; j < max_fields; j++) { 48970ba2cbe9Sxc151355 if (strcasecmp(sp->s_fields[i], 4898e7801d59Ssowmini template[j].pf_name) == 0) { 4899e7801d59Ssowmini good_match = template[j]. pf_cmdtype & cmdtype; 49000ba2cbe9Sxc151355 break; 49010ba2cbe9Sxc151355 } 49020ba2cbe9Sxc151355 } 49030ba2cbe9Sxc151355 if (!good_match) 49040ba2cbe9Sxc151355 goto fail; 49050ba2cbe9Sxc151355 49060ba2cbe9Sxc151355 good_match = B_FALSE; 4907e7801d59Ssowmini pf[i] = &template[j]; 49080ba2cbe9Sxc151355 } 49090ba2cbe9Sxc151355 *countp = i; 49100ba2cbe9Sxc151355 splitfree(sp); 4911e7801d59Ssowmini return (pf); 49120ba2cbe9Sxc151355 fail: 4913e7801d59Ssowmini free(pf); 49140ba2cbe9Sxc151355 splitfree(sp); 4915e7801d59Ssowmini return (NULL); 49160ba2cbe9Sxc151355 } 49170ba2cbe9Sxc151355 49180ba2cbe9Sxc151355 typedef struct print_wifi_state { 4919d62bc4baSyz147064 char *ws_link; 49200ba2cbe9Sxc151355 boolean_t ws_parseable; 49210ba2cbe9Sxc151355 boolean_t ws_header; 4922e7801d59Ssowmini print_state_t ws_print_state; 49230ba2cbe9Sxc151355 } print_wifi_state_t; 49240ba2cbe9Sxc151355 4925e7801d59Ssowmini typedef struct wlan_scan_args_s { 4926e7801d59Ssowmini print_wifi_state_t *ws_state; 4927e7801d59Ssowmini void *ws_attr; 4928e7801d59Ssowmini } wlan_scan_args_t; 49290ba2cbe9Sxc151355 49300ba2cbe9Sxc151355 static void 4931e7801d59Ssowmini print_field(print_state_t *statep, print_field_t *pfp, const char *value, 4932e7801d59Ssowmini boolean_t parseable) 49330ba2cbe9Sxc151355 { 4934e7801d59Ssowmini uint_t width = pfp->pf_width; 49356be03d0bSVasumathi Sundaram - Sun Microsystems uint_t valwidth; 49360ba2cbe9Sxc151355 uint_t compress; 49370ba2cbe9Sxc151355 49380d365605Sschuster /* 49390d365605Sschuster * Parsable fields are separated by ':'. If such a field contains 49400d365605Sschuster * a ':' or '\', this character is prefixed by a '\'. 49410d365605Sschuster */ 4942e7801d59Ssowmini if (parseable) { 49430d365605Sschuster char c; 49440d365605Sschuster 49450d365605Sschuster if (statep->ps_nfields == 1) { 49460d365605Sschuster (void) printf("%s", value); 49470d365605Sschuster return; 49480d365605Sschuster } 49490d365605Sschuster while ((c = *value++) != '\0') { 49500d365605Sschuster if (c == ':' || c == '\\') 49510d365605Sschuster (void) putchar('\\'); 49520d365605Sschuster (void) putchar(c); 49530d365605Sschuster } 49540d365605Sschuster if (!statep->ps_lastfield) 49550d365605Sschuster (void) putchar(':'); 49560d365605Sschuster return; 49570ba2cbe9Sxc151355 } else { 49580ba2cbe9Sxc151355 if (value[0] == '\0') 4959e7801d59Ssowmini value = STR_UNDEF_VAL; 4960e7801d59Ssowmini if (statep->ps_lastfield) { 49610ba2cbe9Sxc151355 (void) printf("%s", value); 49626be03d0bSVasumathi Sundaram - Sun Microsystems statep->ps_overflow = 0; 49630ba2cbe9Sxc151355 return; 49640ba2cbe9Sxc151355 } 49650ba2cbe9Sxc151355 49666be03d0bSVasumathi Sundaram - Sun Microsystems valwidth = strlen(value); 49670ba2cbe9Sxc151355 if (valwidth > width) { 4968e7801d59Ssowmini statep->ps_overflow += valwidth - width; 4969e7801d59Ssowmini } else if (valwidth < width && statep->ps_overflow > 0) { 4970e7801d59Ssowmini compress = min(statep->ps_overflow, width - valwidth); 4971e7801d59Ssowmini statep->ps_overflow -= compress; 49720ba2cbe9Sxc151355 width -= compress; 49730ba2cbe9Sxc151355 } 49740ba2cbe9Sxc151355 (void) printf("%-*s", width, value); 49750ba2cbe9Sxc151355 } 49760ba2cbe9Sxc151355 4977e7801d59Ssowmini if (!statep->ps_lastfield) 49780ba2cbe9Sxc151355 (void) putchar(' '); 49790ba2cbe9Sxc151355 } 49800ba2cbe9Sxc151355 4981e7801d59Ssowmini static char * 4982e7801d59Ssowmini print_wlan_attr(print_field_t *wfp, void *warg) 49830ba2cbe9Sxc151355 { 4984e7801d59Ssowmini static char buf[DLADM_STRSIZE]; 4985e7801d59Ssowmini wlan_scan_args_t *w = warg; 4986e7801d59Ssowmini print_wifi_state_t *statep = w->ws_state; 4987e7801d59Ssowmini dladm_wlan_attr_t *attrp = w->ws_attr; 49880ba2cbe9Sxc151355 4989e7801d59Ssowmini if (wfp->pf_index == 0) { 4990e7801d59Ssowmini return ((char *)statep->ws_link); 49910ba2cbe9Sxc151355 } 49920ba2cbe9Sxc151355 4993e7801d59Ssowmini if ((wfp->pf_index & attrp->wa_valid) == 0) { 4994e7801d59Ssowmini return (""); 49950ba2cbe9Sxc151355 } 49960ba2cbe9Sxc151355 4997e7801d59Ssowmini switch (wfp->pf_index) { 4998f595a68aSyz147064 case DLADM_WLAN_ATTR_ESSID: 4999e7801d59Ssowmini (void) dladm_wlan_essid2str(&attrp->wa_essid, buf); 50000ba2cbe9Sxc151355 break; 5001f595a68aSyz147064 case DLADM_WLAN_ATTR_BSSID: 5002e7801d59Ssowmini (void) dladm_wlan_bssid2str(&attrp->wa_bssid, buf); 50030ba2cbe9Sxc151355 break; 5004f595a68aSyz147064 case DLADM_WLAN_ATTR_SECMODE: 5005e7801d59Ssowmini (void) dladm_wlan_secmode2str(&attrp->wa_secmode, buf); 50060ba2cbe9Sxc151355 break; 5007f595a68aSyz147064 case DLADM_WLAN_ATTR_STRENGTH: 5008e7801d59Ssowmini (void) dladm_wlan_strength2str(&attrp->wa_strength, buf); 50090ba2cbe9Sxc151355 break; 5010f595a68aSyz147064 case DLADM_WLAN_ATTR_MODE: 5011e7801d59Ssowmini (void) dladm_wlan_mode2str(&attrp->wa_mode, buf); 50120ba2cbe9Sxc151355 break; 5013f595a68aSyz147064 case DLADM_WLAN_ATTR_SPEED: 5014e7801d59Ssowmini (void) dladm_wlan_speed2str(&attrp->wa_speed, buf); 50150ba2cbe9Sxc151355 (void) strlcat(buf, "Mb", sizeof (buf)); 50160ba2cbe9Sxc151355 break; 5017f595a68aSyz147064 case DLADM_WLAN_ATTR_AUTH: 5018e7801d59Ssowmini (void) dladm_wlan_auth2str(&attrp->wa_auth, buf); 50190ba2cbe9Sxc151355 break; 5020f595a68aSyz147064 case DLADM_WLAN_ATTR_BSSTYPE: 5021e7801d59Ssowmini (void) dladm_wlan_bsstype2str(&attrp->wa_bsstype, buf); 50220ba2cbe9Sxc151355 break; 50230ba2cbe9Sxc151355 } 50240ba2cbe9Sxc151355 5025e7801d59Ssowmini return (buf); 50260ba2cbe9Sxc151355 } 50270ba2cbe9Sxc151355 50280ba2cbe9Sxc151355 static boolean_t 5029f595a68aSyz147064 print_scan_results(void *arg, dladm_wlan_attr_t *attrp) 50300ba2cbe9Sxc151355 { 50310ba2cbe9Sxc151355 print_wifi_state_t *statep = arg; 5032e7801d59Ssowmini wlan_scan_args_t warg; 50330ba2cbe9Sxc151355 50340ba2cbe9Sxc151355 if (statep->ws_header) { 50350ba2cbe9Sxc151355 statep->ws_header = B_FALSE; 50360ba2cbe9Sxc151355 if (!statep->ws_parseable) 5037e7801d59Ssowmini print_header(&statep->ws_print_state); 50380ba2cbe9Sxc151355 } 50390ba2cbe9Sxc151355 5040e7801d59Ssowmini statep->ws_print_state.ps_overflow = 0; 5041e7801d59Ssowmini bzero(&warg, sizeof (warg)); 5042e7801d59Ssowmini warg.ws_state = statep; 5043e7801d59Ssowmini warg.ws_attr = attrp; 5044e7801d59Ssowmini dladm_print_output(&statep->ws_print_state, statep->ws_parseable, 5045e7801d59Ssowmini print_wlan_attr, &warg); 50460ba2cbe9Sxc151355 return (B_TRUE); 50470ba2cbe9Sxc151355 } 50480ba2cbe9Sxc151355 5049d62bc4baSyz147064 static int 50504ac67f02SAnurag S. Maskey scan_wifi(dladm_handle_t dh, datalink_id_t linkid, void *arg) 50510ba2cbe9Sxc151355 { 50520ba2cbe9Sxc151355 print_wifi_state_t *statep = arg; 5053f595a68aSyz147064 dladm_status_t status; 5054d62bc4baSyz147064 char link[MAXLINKNAMELEN]; 5055d62bc4baSyz147064 50564ac67f02SAnurag S. Maskey if ((status = dladm_datalink_id2info(dh, linkid, NULL, NULL, NULL, link, 5057e7801d59Ssowmini sizeof (link))) != DLADM_STATUS_OK) { 5058d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 5059d62bc4baSyz147064 } 50600ba2cbe9Sxc151355 50610ba2cbe9Sxc151355 statep->ws_link = link; 50624ac67f02SAnurag S. Maskey status = dladm_wlan_scan(dh, linkid, statep, print_scan_results); 5063f595a68aSyz147064 if (status != DLADM_STATUS_OK) 5064d62bc4baSyz147064 die_dlerr(status, "cannot scan link '%s'", statep->ws_link); 506533343a97Smeem 5066d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 50670ba2cbe9Sxc151355 } 50680ba2cbe9Sxc151355 5069e7801d59Ssowmini static char * 5070e7801d59Ssowmini print_link_attr(print_field_t *wfp, void *warg) 50710ba2cbe9Sxc151355 { 5072e7801d59Ssowmini static char buf[DLADM_STRSIZE]; 5073e7801d59Ssowmini char *ptr; 5074e7801d59Ssowmini wlan_scan_args_t *w = warg, w1; 5075e7801d59Ssowmini print_wifi_state_t *statep = w->ws_state; 5076e7801d59Ssowmini dladm_wlan_linkattr_t *attrp = w->ws_attr; 50770ba2cbe9Sxc151355 5078e7801d59Ssowmini if (strcmp(wfp->pf_name, "status") == 0) { 5079e7801d59Ssowmini if ((wfp->pf_index & attrp->la_valid) != 0) 5080e7801d59Ssowmini (void) dladm_wlan_linkstatus2str( 5081e7801d59Ssowmini &attrp->la_status, buf); 5082e7801d59Ssowmini return (buf); 50830ba2cbe9Sxc151355 } 5084e7801d59Ssowmini statep->ws_print_state.ps_overflow = 0; 5085e7801d59Ssowmini bzero(&w1, sizeof (w1)); 5086e7801d59Ssowmini w1.ws_state = statep; 5087e7801d59Ssowmini w1.ws_attr = &attrp->la_wlan_attr; 5088e7801d59Ssowmini ptr = print_wlan_attr(wfp, &w1); 5089e7801d59Ssowmini return (ptr); 50900ba2cbe9Sxc151355 } 50910ba2cbe9Sxc151355 5092d62bc4baSyz147064 static int 50934ac67f02SAnurag S. Maskey show_wifi(dladm_handle_t dh, datalink_id_t linkid, void *arg) 50940ba2cbe9Sxc151355 { 50950ba2cbe9Sxc151355 print_wifi_state_t *statep = arg; 5096f595a68aSyz147064 dladm_wlan_linkattr_t attr; 5097f595a68aSyz147064 dladm_status_t status; 5098d62bc4baSyz147064 char link[MAXLINKNAMELEN]; 5099e7801d59Ssowmini wlan_scan_args_t warg; 51000ba2cbe9Sxc151355 51014ac67f02SAnurag S. Maskey if ((status = dladm_datalink_id2info(dh, linkid, NULL, NULL, NULL, link, 5102e7801d59Ssowmini sizeof (link))) != DLADM_STATUS_OK) { 5103d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 5104d62bc4baSyz147064 } 5105d62bc4baSyz147064 51065f5c9f54SAnurag S. Maskey /* dladm_wlan_get_linkattr() memsets attr with 0 */ 51074ac67f02SAnurag S. Maskey status = dladm_wlan_get_linkattr(dh, linkid, &attr); 5108f595a68aSyz147064 if (status != DLADM_STATUS_OK) 5109d62bc4baSyz147064 die_dlerr(status, "cannot get link attributes for %s", link); 5110d62bc4baSyz147064 5111d62bc4baSyz147064 statep->ws_link = link; 51120ba2cbe9Sxc151355 51130ba2cbe9Sxc151355 if (statep->ws_header) { 51140ba2cbe9Sxc151355 statep->ws_header = B_FALSE; 51150ba2cbe9Sxc151355 if (!statep->ws_parseable) 5116e7801d59Ssowmini print_header(&statep->ws_print_state); 51170ba2cbe9Sxc151355 } 51180ba2cbe9Sxc151355 5119e7801d59Ssowmini statep->ws_print_state.ps_overflow = 0; 5120e7801d59Ssowmini bzero(&warg, sizeof (warg)); 5121e7801d59Ssowmini warg.ws_state = statep; 5122e7801d59Ssowmini warg.ws_attr = &attr; 5123e7801d59Ssowmini dladm_print_output(&statep->ws_print_state, statep->ws_parseable, 5124e7801d59Ssowmini print_link_attr, &warg); 5125d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 51260ba2cbe9Sxc151355 } 51270ba2cbe9Sxc151355 51280ba2cbe9Sxc151355 static void 51298d5c46e6Sam223141 do_display_wifi(int argc, char **argv, int cmd, const char *use) 51300ba2cbe9Sxc151355 { 51310ba2cbe9Sxc151355 int option; 51320ba2cbe9Sxc151355 char *fields_str = NULL; 5133e7801d59Ssowmini print_field_t **fields; 51344ac67f02SAnurag S. Maskey int (*callback)(dladm_handle_t, datalink_id_t, void *); 51350ba2cbe9Sxc151355 uint_t nfields; 51360ba2cbe9Sxc151355 print_wifi_state_t state; 5137d62bc4baSyz147064 datalink_id_t linkid = DATALINK_ALL_LINKID; 5138f595a68aSyz147064 dladm_status_t status; 51390ba2cbe9Sxc151355 51400ba2cbe9Sxc151355 if (cmd == WIFI_CMD_SCAN) 51410ba2cbe9Sxc151355 callback = scan_wifi; 51420ba2cbe9Sxc151355 else if (cmd == WIFI_CMD_SHOW) 51430ba2cbe9Sxc151355 callback = show_wifi; 51440ba2cbe9Sxc151355 else 51450ba2cbe9Sxc151355 return; 51460ba2cbe9Sxc151355 51470ba2cbe9Sxc151355 state.ws_parseable = B_FALSE; 51480ba2cbe9Sxc151355 state.ws_header = B_TRUE; 51490ba2cbe9Sxc151355 opterr = 0; 51500ba2cbe9Sxc151355 while ((option = getopt_long(argc, argv, ":o:p", 51510ba2cbe9Sxc151355 wifi_longopts, NULL)) != -1) { 51520ba2cbe9Sxc151355 switch (option) { 51530ba2cbe9Sxc151355 case 'o': 51540ba2cbe9Sxc151355 fields_str = optarg; 51550ba2cbe9Sxc151355 break; 51560ba2cbe9Sxc151355 case 'p': 51570ba2cbe9Sxc151355 state.ws_parseable = B_TRUE; 51580ba2cbe9Sxc151355 break; 51590ba2cbe9Sxc151355 default: 51608d5c46e6Sam223141 die_opterr(optopt, option, use); 51610ba2cbe9Sxc151355 } 51620ba2cbe9Sxc151355 } 51630ba2cbe9Sxc151355 51640d365605Sschuster if (state.ws_parseable && fields_str == NULL) 51650d365605Sschuster die("-p requires -o"); 51660d365605Sschuster 51670d365605Sschuster if (state.ws_parseable && strcasecmp(fields_str, "all") == 0) 51680d365605Sschuster die("\"-o all\" is invalid with -p"); 51690d365605Sschuster 5170d62bc4baSyz147064 if (optind == (argc - 1)) { 51714ac67f02SAnurag S. Maskey if ((status = dladm_name2info(handle, argv[optind], &linkid, 51724ac67f02SAnurag S. Maskey NULL, NULL, NULL)) != DLADM_STATUS_OK) { 5173d62bc4baSyz147064 die_dlerr(status, "link %s is not valid", argv[optind]); 5174d62bc4baSyz147064 } 5175d62bc4baSyz147064 } else if (optind != argc) { 51760ba2cbe9Sxc151355 usage(); 5177d62bc4baSyz147064 } 51780ba2cbe9Sxc151355 517933343a97Smeem if (parse_wifi_fields(fields_str, &fields, &nfields, cmd) < 0) 518033343a97Smeem die("invalid field(s) specified"); 518133343a97Smeem 5182e7801d59Ssowmini bzero(&state.ws_print_state, sizeof (state.ws_print_state)); 5183e7801d59Ssowmini state.ws_print_state.ps_fields = fields; 5184e7801d59Ssowmini state.ws_print_state.ps_nfields = nfields; 51850ba2cbe9Sxc151355 5186d62bc4baSyz147064 if (linkid == DATALINK_ALL_LINKID) { 51874ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(callback, handle, &state, 5188d62bc4baSyz147064 DATALINK_CLASS_PHYS, DL_WIFI, DLADM_OPT_ACTIVE); 51890ba2cbe9Sxc151355 } else { 51904ac67f02SAnurag S. Maskey (void) (*callback)(handle, linkid, &state); 51910ba2cbe9Sxc151355 } 51920ba2cbe9Sxc151355 free(fields); 51930ba2cbe9Sxc151355 } 51940ba2cbe9Sxc151355 51950ba2cbe9Sxc151355 static void 51968d5c46e6Sam223141 do_scan_wifi(int argc, char **argv, const char *use) 51970ba2cbe9Sxc151355 { 51988d5c46e6Sam223141 do_display_wifi(argc, argv, WIFI_CMD_SCAN, use); 51990ba2cbe9Sxc151355 } 52000ba2cbe9Sxc151355 52010ba2cbe9Sxc151355 static void 52028d5c46e6Sam223141 do_show_wifi(int argc, char **argv, const char *use) 52030ba2cbe9Sxc151355 { 52048d5c46e6Sam223141 do_display_wifi(argc, argv, WIFI_CMD_SHOW, use); 52050ba2cbe9Sxc151355 } 52060ba2cbe9Sxc151355 52070ba2cbe9Sxc151355 typedef struct wlan_count_attr { 52080ba2cbe9Sxc151355 uint_t wc_count; 5209d62bc4baSyz147064 datalink_id_t wc_linkid; 52100ba2cbe9Sxc151355 } wlan_count_attr_t; 52110ba2cbe9Sxc151355 52124ac67f02SAnurag S. Maskey /* ARGSUSED */ 5213d62bc4baSyz147064 static int 52144ac67f02SAnurag S. Maskey do_count_wlan(dladm_handle_t dh, datalink_id_t linkid, void *arg) 52150ba2cbe9Sxc151355 { 521633343a97Smeem wlan_count_attr_t *cp = arg; 52170ba2cbe9Sxc151355 52180ba2cbe9Sxc151355 if (cp->wc_count == 0) 5219d62bc4baSyz147064 cp->wc_linkid = linkid; 52200ba2cbe9Sxc151355 cp->wc_count++; 5221d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 52220ba2cbe9Sxc151355 } 52230ba2cbe9Sxc151355 52240ba2cbe9Sxc151355 static int 5225a399b765Szf162725 parse_wlan_keys(char *str, dladm_wlan_key_t **keys, uint_t *key_countp) 52260ba2cbe9Sxc151355 { 52270ba2cbe9Sxc151355 uint_t i; 52280ba2cbe9Sxc151355 split_t *sp; 5229a399b765Szf162725 dladm_wlan_key_t *wk; 52300ba2cbe9Sxc151355 5231a399b765Szf162725 sp = split(str, DLADM_WLAN_MAX_WEPKEYS, DLADM_WLAN_MAX_KEYNAME_LEN); 52320ba2cbe9Sxc151355 if (sp == NULL) 52330ba2cbe9Sxc151355 return (-1); 52340ba2cbe9Sxc151355 5235a399b765Szf162725 wk = malloc(sp->s_nfields * sizeof (dladm_wlan_key_t)); 52360ba2cbe9Sxc151355 if (wk == NULL) 52370ba2cbe9Sxc151355 goto fail; 52380ba2cbe9Sxc151355 52390ba2cbe9Sxc151355 for (i = 0; i < sp->s_nfields; i++) { 52400ba2cbe9Sxc151355 char *s; 52410ba2cbe9Sxc151355 dladm_secobj_class_t class; 52420ba2cbe9Sxc151355 dladm_status_t status; 52430ba2cbe9Sxc151355 52440ba2cbe9Sxc151355 (void) strlcpy(wk[i].wk_name, sp->s_fields[i], 5245a399b765Szf162725 DLADM_WLAN_MAX_KEYNAME_LEN); 52460ba2cbe9Sxc151355 52470ba2cbe9Sxc151355 wk[i].wk_idx = 1; 52480ba2cbe9Sxc151355 if ((s = strrchr(wk[i].wk_name, ':')) != NULL) { 52490ba2cbe9Sxc151355 if (s[1] == '\0' || s[2] != '\0' || !isdigit(s[1])) 52500ba2cbe9Sxc151355 goto fail; 52510ba2cbe9Sxc151355 52520ba2cbe9Sxc151355 wk[i].wk_idx = (uint_t)(s[1] - '0'); 52530ba2cbe9Sxc151355 *s = '\0'; 52540ba2cbe9Sxc151355 } 5255a399b765Szf162725 wk[i].wk_len = DLADM_WLAN_MAX_KEY_LEN; 52560ba2cbe9Sxc151355 52574ac67f02SAnurag S. Maskey status = dladm_get_secobj(handle, wk[i].wk_name, &class, 52580ba2cbe9Sxc151355 wk[i].wk_val, &wk[i].wk_len, 0); 52590ba2cbe9Sxc151355 if (status != DLADM_STATUS_OK) { 52600ba2cbe9Sxc151355 if (status == DLADM_STATUS_NOTFOUND) { 52614ac67f02SAnurag S. Maskey status = dladm_get_secobj(handle, wk[i].wk_name, 52620ba2cbe9Sxc151355 &class, wk[i].wk_val, &wk[i].wk_len, 52630ba2cbe9Sxc151355 DLADM_OPT_PERSIST); 52640ba2cbe9Sxc151355 } 52650ba2cbe9Sxc151355 if (status != DLADM_STATUS_OK) 52660ba2cbe9Sxc151355 goto fail; 52670ba2cbe9Sxc151355 } 5268a399b765Szf162725 wk[i].wk_class = class; 52690ba2cbe9Sxc151355 } 52700ba2cbe9Sxc151355 *keys = wk; 52710ba2cbe9Sxc151355 *key_countp = i; 52720ba2cbe9Sxc151355 splitfree(sp); 52730ba2cbe9Sxc151355 return (0); 52740ba2cbe9Sxc151355 fail: 52750ba2cbe9Sxc151355 free(wk); 52760ba2cbe9Sxc151355 splitfree(sp); 52770ba2cbe9Sxc151355 return (-1); 52780ba2cbe9Sxc151355 } 52790ba2cbe9Sxc151355 52800ba2cbe9Sxc151355 static void 52818d5c46e6Sam223141 do_connect_wifi(int argc, char **argv, const char *use) 52820ba2cbe9Sxc151355 { 52830ba2cbe9Sxc151355 int option; 5284f595a68aSyz147064 dladm_wlan_attr_t attr, *attrp; 5285f595a68aSyz147064 dladm_status_t status = DLADM_STATUS_OK; 5286f595a68aSyz147064 int timeout = DLADM_WLAN_CONNECT_TIMEOUT_DEFAULT; 5287d62bc4baSyz147064 datalink_id_t linkid = DATALINK_ALL_LINKID; 5288a399b765Szf162725 dladm_wlan_key_t *keys = NULL; 52890ba2cbe9Sxc151355 uint_t key_count = 0; 52900ba2cbe9Sxc151355 uint_t flags = 0; 5291f595a68aSyz147064 dladm_wlan_secmode_t keysecmode = DLADM_WLAN_SECMODE_NONE; 5292a399b765Szf162725 char buf[DLADM_STRSIZE]; 52930ba2cbe9Sxc151355 52940ba2cbe9Sxc151355 opterr = 0; 52950ba2cbe9Sxc151355 (void) memset(&attr, 0, sizeof (attr)); 52960ba2cbe9Sxc151355 while ((option = getopt_long(argc, argv, ":e:i:a:m:b:s:k:T:c", 52970ba2cbe9Sxc151355 wifi_longopts, NULL)) != -1) { 52980ba2cbe9Sxc151355 switch (option) { 52990ba2cbe9Sxc151355 case 'e': 5300f595a68aSyz147064 status = dladm_wlan_str2essid(optarg, &attr.wa_essid); 5301f595a68aSyz147064 if (status != DLADM_STATUS_OK) 530233343a97Smeem die("invalid ESSID '%s'", optarg); 530333343a97Smeem 5304f595a68aSyz147064 attr.wa_valid |= DLADM_WLAN_ATTR_ESSID; 53050ba2cbe9Sxc151355 /* 53060ba2cbe9Sxc151355 * Try to connect without doing a scan. 53070ba2cbe9Sxc151355 */ 5308f595a68aSyz147064 flags |= DLADM_WLAN_CONNECT_NOSCAN; 53090ba2cbe9Sxc151355 break; 53100ba2cbe9Sxc151355 case 'i': 5311f595a68aSyz147064 status = dladm_wlan_str2bssid(optarg, &attr.wa_bssid); 5312f595a68aSyz147064 if (status != DLADM_STATUS_OK) 531333343a97Smeem die("invalid BSSID %s", optarg); 531433343a97Smeem 5315f595a68aSyz147064 attr.wa_valid |= DLADM_WLAN_ATTR_BSSID; 53160ba2cbe9Sxc151355 break; 53170ba2cbe9Sxc151355 case 'a': 5318f595a68aSyz147064 status = dladm_wlan_str2auth(optarg, &attr.wa_auth); 5319f595a68aSyz147064 if (status != DLADM_STATUS_OK) 532033343a97Smeem die("invalid authentication mode '%s'", optarg); 532133343a97Smeem 5322f595a68aSyz147064 attr.wa_valid |= DLADM_WLAN_ATTR_AUTH; 53230ba2cbe9Sxc151355 break; 53240ba2cbe9Sxc151355 case 'm': 5325f595a68aSyz147064 status = dladm_wlan_str2mode(optarg, &attr.wa_mode); 5326f595a68aSyz147064 if (status != DLADM_STATUS_OK) 532733343a97Smeem die("invalid mode '%s'", optarg); 532833343a97Smeem 5329f595a68aSyz147064 attr.wa_valid |= DLADM_WLAN_ATTR_MODE; 53300ba2cbe9Sxc151355 break; 53310ba2cbe9Sxc151355 case 'b': 5332f595a68aSyz147064 if ((status = dladm_wlan_str2bsstype(optarg, 5333f595a68aSyz147064 &attr.wa_bsstype)) != DLADM_STATUS_OK) { 533433343a97Smeem die("invalid bsstype '%s'", optarg); 5335f595a68aSyz147064 } 533633343a97Smeem 5337f595a68aSyz147064 attr.wa_valid |= DLADM_WLAN_ATTR_BSSTYPE; 53380ba2cbe9Sxc151355 break; 53390ba2cbe9Sxc151355 case 's': 5340f595a68aSyz147064 if ((status = dladm_wlan_str2secmode(optarg, 5341f595a68aSyz147064 &attr.wa_secmode)) != DLADM_STATUS_OK) { 534233343a97Smeem die("invalid security mode '%s'", optarg); 5343f595a68aSyz147064 } 534433343a97Smeem 5345f595a68aSyz147064 attr.wa_valid |= DLADM_WLAN_ATTR_SECMODE; 53460ba2cbe9Sxc151355 break; 53470ba2cbe9Sxc151355 case 'k': 5348a399b765Szf162725 if (parse_wlan_keys(optarg, &keys, &key_count) < 0) 534933343a97Smeem die("invalid key(s) '%s'", optarg); 535033343a97Smeem 5351a399b765Szf162725 if (keys[0].wk_class == DLADM_SECOBJ_CLASS_WEP) 5352f595a68aSyz147064 keysecmode = DLADM_WLAN_SECMODE_WEP; 5353a399b765Szf162725 else 5354a399b765Szf162725 keysecmode = DLADM_WLAN_SECMODE_WPA; 53550ba2cbe9Sxc151355 break; 53560ba2cbe9Sxc151355 case 'T': 53570ba2cbe9Sxc151355 if (strcasecmp(optarg, "forever") == 0) { 53580ba2cbe9Sxc151355 timeout = -1; 53590ba2cbe9Sxc151355 break; 53600ba2cbe9Sxc151355 } 536133343a97Smeem if (!str2int(optarg, &timeout) || timeout < 0) 536233343a97Smeem die("invalid timeout value '%s'", optarg); 53630ba2cbe9Sxc151355 break; 53640ba2cbe9Sxc151355 case 'c': 5365f595a68aSyz147064 flags |= DLADM_WLAN_CONNECT_CREATEIBSS; 5366a399b765Szf162725 flags |= DLADM_WLAN_CONNECT_CREATEIBSS; 53670ba2cbe9Sxc151355 break; 53680ba2cbe9Sxc151355 default: 53698d5c46e6Sam223141 die_opterr(optopt, option, use); 53700ba2cbe9Sxc151355 break; 53710ba2cbe9Sxc151355 } 53720ba2cbe9Sxc151355 } 53730ba2cbe9Sxc151355 5374f595a68aSyz147064 if (keysecmode == DLADM_WLAN_SECMODE_NONE) { 5375a399b765Szf162725 if ((attr.wa_valid & DLADM_WLAN_ATTR_SECMODE) != 0) { 5376a399b765Szf162725 die("key required for security mode '%s'", 5377a399b765Szf162725 dladm_wlan_secmode2str(&attr.wa_secmode, buf)); 5378a399b765Szf162725 } 53790ba2cbe9Sxc151355 } else { 5380f595a68aSyz147064 if ((attr.wa_valid & DLADM_WLAN_ATTR_SECMODE) != 0 && 538133343a97Smeem attr.wa_secmode != keysecmode) 538233343a97Smeem die("incompatible -s and -k options"); 5383f595a68aSyz147064 attr.wa_valid |= DLADM_WLAN_ATTR_SECMODE; 5384a399b765Szf162725 attr.wa_secmode = keysecmode; 5385a399b765Szf162725 } 53860ba2cbe9Sxc151355 5387d62bc4baSyz147064 if (optind == (argc - 1)) { 53884ac67f02SAnurag S. Maskey if ((status = dladm_name2info(handle, argv[optind], &linkid, 53894ac67f02SAnurag S. Maskey NULL, NULL, NULL)) != DLADM_STATUS_OK) { 5390d62bc4baSyz147064 die_dlerr(status, "link %s is not valid", argv[optind]); 5391d62bc4baSyz147064 } 5392d62bc4baSyz147064 } else if (optind != argc) { 53930ba2cbe9Sxc151355 usage(); 5394d62bc4baSyz147064 } 53950ba2cbe9Sxc151355 5396d62bc4baSyz147064 if (linkid == DATALINK_ALL_LINKID) { 53970ba2cbe9Sxc151355 wlan_count_attr_t wcattr; 53980ba2cbe9Sxc151355 5399d62bc4baSyz147064 wcattr.wc_linkid = DATALINK_INVALID_LINKID; 54000ba2cbe9Sxc151355 wcattr.wc_count = 0; 54014ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(do_count_wlan, handle, &wcattr, 5402d62bc4baSyz147064 DATALINK_CLASS_PHYS, DL_WIFI, DLADM_OPT_ACTIVE); 54030ba2cbe9Sxc151355 if (wcattr.wc_count == 0) { 540433343a97Smeem die("no wifi links are available"); 54050ba2cbe9Sxc151355 } else if (wcattr.wc_count > 1) { 540633343a97Smeem die("link name is required when more than one wifi " 540733343a97Smeem "link is available"); 54080ba2cbe9Sxc151355 } 5409d62bc4baSyz147064 linkid = wcattr.wc_linkid; 54100ba2cbe9Sxc151355 } 54110ba2cbe9Sxc151355 attrp = (attr.wa_valid == 0) ? NULL : &attr; 541233343a97Smeem again: 54134ac67f02SAnurag S. Maskey if ((status = dladm_wlan_connect(handle, linkid, attrp, timeout, keys, 5414f595a68aSyz147064 key_count, flags)) != DLADM_STATUS_OK) { 5415f595a68aSyz147064 if ((flags & DLADM_WLAN_CONNECT_NOSCAN) != 0) { 54160ba2cbe9Sxc151355 /* 541733343a97Smeem * Try again with scanning and filtering. 54180ba2cbe9Sxc151355 */ 5419f595a68aSyz147064 flags &= ~DLADM_WLAN_CONNECT_NOSCAN; 542033343a97Smeem goto again; 54210ba2cbe9Sxc151355 } 542233343a97Smeem 5423f595a68aSyz147064 if (status == DLADM_STATUS_NOTFOUND) { 54240ba2cbe9Sxc151355 if (attr.wa_valid == 0) { 542533343a97Smeem die("no wifi networks are available"); 54260ba2cbe9Sxc151355 } else { 542733343a97Smeem die("no wifi networks with the specified " 542833343a97Smeem "criteria are available"); 54290ba2cbe9Sxc151355 } 54300ba2cbe9Sxc151355 } 5431d62bc4baSyz147064 die_dlerr(status, "cannot connect"); 54320ba2cbe9Sxc151355 } 54330ba2cbe9Sxc151355 free(keys); 54340ba2cbe9Sxc151355 } 54350ba2cbe9Sxc151355 54360ba2cbe9Sxc151355 /* ARGSUSED */ 5437d62bc4baSyz147064 static int 54384ac67f02SAnurag S. Maskey do_all_disconnect_wifi(dladm_handle_t dh, datalink_id_t linkid, void *arg) 54390ba2cbe9Sxc151355 { 5440f595a68aSyz147064 dladm_status_t status; 54410ba2cbe9Sxc151355 54424ac67f02SAnurag S. Maskey status = dladm_wlan_disconnect(dh, linkid); 5443f595a68aSyz147064 if (status != DLADM_STATUS_OK) 5444d62bc4baSyz147064 warn_dlerr(status, "cannot disconnect link"); 544533343a97Smeem 5446d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 54470ba2cbe9Sxc151355 } 54480ba2cbe9Sxc151355 54490ba2cbe9Sxc151355 static void 54508d5c46e6Sam223141 do_disconnect_wifi(int argc, char **argv, const char *use) 54510ba2cbe9Sxc151355 { 54520ba2cbe9Sxc151355 int option; 5453d62bc4baSyz147064 datalink_id_t linkid = DATALINK_ALL_LINKID; 54540ba2cbe9Sxc151355 boolean_t all_links = B_FALSE; 5455f595a68aSyz147064 dladm_status_t status; 54560ba2cbe9Sxc151355 wlan_count_attr_t wcattr; 54570ba2cbe9Sxc151355 54580ba2cbe9Sxc151355 opterr = 0; 54590ba2cbe9Sxc151355 while ((option = getopt_long(argc, argv, ":a", 54600ba2cbe9Sxc151355 wifi_longopts, NULL)) != -1) { 54610ba2cbe9Sxc151355 switch (option) { 54620ba2cbe9Sxc151355 case 'a': 54630ba2cbe9Sxc151355 all_links = B_TRUE; 54640ba2cbe9Sxc151355 break; 54650ba2cbe9Sxc151355 default: 54668d5c46e6Sam223141 die_opterr(optopt, option, use); 54670ba2cbe9Sxc151355 break; 54680ba2cbe9Sxc151355 } 54690ba2cbe9Sxc151355 } 54700ba2cbe9Sxc151355 5471d62bc4baSyz147064 if (optind == (argc - 1)) { 54724ac67f02SAnurag S. Maskey if ((status = dladm_name2info(handle, argv[optind], &linkid, 54734ac67f02SAnurag S. Maskey NULL, NULL, NULL)) != DLADM_STATUS_OK) { 5474d62bc4baSyz147064 die_dlerr(status, "link %s is not valid", argv[optind]); 5475d62bc4baSyz147064 } 5476d62bc4baSyz147064 } else if (optind != argc) { 54770ba2cbe9Sxc151355 usage(); 5478d62bc4baSyz147064 } 54790ba2cbe9Sxc151355 5480d62bc4baSyz147064 if (linkid == DATALINK_ALL_LINKID) { 54810ba2cbe9Sxc151355 if (!all_links) { 5482d62bc4baSyz147064 wcattr.wc_linkid = linkid; 54830ba2cbe9Sxc151355 wcattr.wc_count = 0; 54844ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(do_count_wlan, handle, 54854ac67f02SAnurag S. Maskey &wcattr, DATALINK_CLASS_PHYS, DL_WIFI, 54864ac67f02SAnurag S. Maskey DLADM_OPT_ACTIVE); 54870ba2cbe9Sxc151355 if (wcattr.wc_count == 0) { 548833343a97Smeem die("no wifi links are available"); 54890ba2cbe9Sxc151355 } else if (wcattr.wc_count > 1) { 549033343a97Smeem die("link name is required when more than " 549133343a97Smeem "one wifi link is available"); 54920ba2cbe9Sxc151355 } 5493d62bc4baSyz147064 linkid = wcattr.wc_linkid; 54940ba2cbe9Sxc151355 } else { 5495d62bc4baSyz147064 (void) dladm_walk_datalink_id(do_all_disconnect_wifi, 54964ac67f02SAnurag S. Maskey handle, NULL, DATALINK_CLASS_PHYS, DL_WIFI, 5497d62bc4baSyz147064 DLADM_OPT_ACTIVE); 54980ba2cbe9Sxc151355 return; 54990ba2cbe9Sxc151355 } 55000ba2cbe9Sxc151355 } 55014ac67f02SAnurag S. Maskey status = dladm_wlan_disconnect(handle, linkid); 5502f595a68aSyz147064 if (status != DLADM_STATUS_OK) 5503d62bc4baSyz147064 die_dlerr(status, "cannot disconnect"); 55040ba2cbe9Sxc151355 } 55050ba2cbe9Sxc151355 55060ba2cbe9Sxc151355 static void 5507d62bc4baSyz147064 print_linkprop(datalink_id_t linkid, show_linkprop_state_t *statep, 55084ac67f02SAnurag S. Maskey const char *propname, dladm_prop_type_t type, const char *format, 55094ac67f02SAnurag S. Maskey char **pptr) 55100ba2cbe9Sxc151355 { 55110ba2cbe9Sxc151355 int i; 55120ba2cbe9Sxc151355 char *ptr, *lim; 55130ba2cbe9Sxc151355 char buf[DLADM_STRSIZE]; 5514da14cebeSEric Cheng char *unknown = "--", *notsup = ""; 55150ba2cbe9Sxc151355 char **propvals = statep->ls_propvals; 5516d62bc4baSyz147064 uint_t valcnt = DLADM_MAX_PROP_VALCNT; 55170ba2cbe9Sxc151355 dladm_status_t status; 55180ba2cbe9Sxc151355 55194ac67f02SAnurag S. Maskey status = dladm_get_linkprop(handle, linkid, type, propname, propvals, 55204ac67f02SAnurag S. Maskey &valcnt); 55210ba2cbe9Sxc151355 if (status != DLADM_STATUS_OK) { 5522f595a68aSyz147064 if (status == DLADM_STATUS_TEMPONLY) { 5523d62bc4baSyz147064 if (type == DLADM_PROP_VAL_MODIFIABLE && 5524d62bc4baSyz147064 statep->ls_persist) { 5525d62bc4baSyz147064 valcnt = 1; 5526d62bc4baSyz147064 propvals = &unknown; 5527d62bc4baSyz147064 } else { 5528f595a68aSyz147064 statep->ls_status = status; 5529e7801d59Ssowmini statep->ls_retstatus = status; 5530f595a68aSyz147064 return; 5531d62bc4baSyz147064 } 5532f595a68aSyz147064 } else if (status == DLADM_STATUS_NOTSUP || 5533f595a68aSyz147064 statep->ls_persist) { 55340ba2cbe9Sxc151355 valcnt = 1; 5535afdda45fSVasumathi Sundaram - Sun Microsystems if (type == DLADM_PROP_VAL_CURRENT || 5536afdda45fSVasumathi Sundaram - Sun Microsystems type == DLADM_PROP_VAL_PERM) 55370ba2cbe9Sxc151355 propvals = &unknown; 55380ba2cbe9Sxc151355 else 55390ba2cbe9Sxc151355 propvals = ¬sup; 5540149b7eb2SSowmini Varadhan } else if (status == DLADM_STATUS_NOTDEFINED) { 5541149b7eb2SSowmini Varadhan propvals = ¬sup; /* STR_UNDEF_VAL */ 55420ba2cbe9Sxc151355 } else { 5543e7801d59Ssowmini if (statep->ls_proplist && 5544e7801d59Ssowmini statep->ls_status == DLADM_STATUS_OK) { 5545f595a68aSyz147064 warn_dlerr(status, 5546f595a68aSyz147064 "cannot get link property '%s' for %s", 5547f595a68aSyz147064 propname, statep->ls_link); 5548d62bc4baSyz147064 } 5549e7801d59Ssowmini statep->ls_status = status; 5550e7801d59Ssowmini statep->ls_retstatus = status; 5551f595a68aSyz147064 return; 55520ba2cbe9Sxc151355 } 55530ba2cbe9Sxc151355 } 55540ba2cbe9Sxc151355 5555e7801d59Ssowmini statep->ls_status = DLADM_STATUS_OK; 5556e7801d59Ssowmini 55570ba2cbe9Sxc151355 ptr = buf; 55580ba2cbe9Sxc151355 lim = buf + DLADM_STRSIZE; 55590ba2cbe9Sxc151355 for (i = 0; i < valcnt; i++) { 55600ba2cbe9Sxc151355 if (propvals[i][0] == '\0' && !statep->ls_parseable) 5561e7801d59Ssowmini ptr += snprintf(ptr, lim - ptr, STR_UNDEF_VAL","); 55620ba2cbe9Sxc151355 else 55630ba2cbe9Sxc151355 ptr += snprintf(ptr, lim - ptr, "%s,", propvals[i]); 55640ba2cbe9Sxc151355 if (ptr >= lim) 55650ba2cbe9Sxc151355 break; 55660ba2cbe9Sxc151355 } 55670ba2cbe9Sxc151355 if (valcnt > 0) 55680ba2cbe9Sxc151355 buf[strlen(buf) - 1] = '\0'; 55690ba2cbe9Sxc151355 55700ba2cbe9Sxc151355 lim = statep->ls_line + MAX_PROP_LINE; 55710ba2cbe9Sxc151355 if (statep->ls_parseable) { 55720ba2cbe9Sxc151355 *pptr += snprintf(*pptr, lim - *pptr, 5573e7801d59Ssowmini "%s", buf); 55740ba2cbe9Sxc151355 } else { 55750ba2cbe9Sxc151355 *pptr += snprintf(*pptr, lim - *pptr, format, buf); 55760ba2cbe9Sxc151355 } 55770ba2cbe9Sxc151355 } 55780ba2cbe9Sxc151355 5579e7801d59Ssowmini static char * 5580e7801d59Ssowmini linkprop_callback(print_field_t *pf, void *ls_arg) 5581e7801d59Ssowmini { 5582e7801d59Ssowmini linkprop_args_t *arg = ls_arg; 5583e7801d59Ssowmini char *propname = arg->ls_propname; 5584e7801d59Ssowmini show_linkprop_state_t *statep = arg->ls_state; 5585e7801d59Ssowmini char *ptr = statep->ls_line; 5586e7801d59Ssowmini char *lim = ptr + MAX_PROP_LINE; 5587e7801d59Ssowmini datalink_id_t linkid = arg->ls_linkid; 5588e7801d59Ssowmini 5589e7801d59Ssowmini switch (pf->pf_index) { 5590e7801d59Ssowmini case LINKPROP_LINK: 5591e7801d59Ssowmini (void) snprintf(ptr, lim - ptr, "%s", statep->ls_link); 5592e7801d59Ssowmini break; 5593e7801d59Ssowmini case LINKPROP_PROPERTY: 5594e7801d59Ssowmini (void) snprintf(ptr, lim - ptr, "%s", propname); 5595e7801d59Ssowmini break; 5596e7801d59Ssowmini case LINKPROP_VALUE: 5597e7801d59Ssowmini print_linkprop(linkid, statep, propname, 5598e7801d59Ssowmini statep->ls_persist ? DLADM_PROP_VAL_PERSISTENT : 5599e7801d59Ssowmini DLADM_PROP_VAL_CURRENT, "%s", &ptr); 5600e7801d59Ssowmini /* 5601e7801d59Ssowmini * If we failed to query the link property, for example, query 5602e7801d59Ssowmini * the persistent value of a non-persistable link property, 5603e7801d59Ssowmini * simply skip the output. 5604e7801d59Ssowmini */ 5605e7801d59Ssowmini if (statep->ls_status != DLADM_STATUS_OK) 5606e7801d59Ssowmini goto skip; 5607e7801d59Ssowmini ptr = statep->ls_line; 5608e7801d59Ssowmini break; 5609afdda45fSVasumathi Sundaram - Sun Microsystems case LINKPROP_PERM: 5610afdda45fSVasumathi Sundaram - Sun Microsystems print_linkprop(linkid, statep, propname, 5611afdda45fSVasumathi Sundaram - Sun Microsystems DLADM_PROP_VAL_PERM, "%s", &ptr); 5612afdda45fSVasumathi Sundaram - Sun Microsystems if (statep->ls_status != DLADM_STATUS_OK) 5613afdda45fSVasumathi Sundaram - Sun Microsystems goto skip; 5614afdda45fSVasumathi Sundaram - Sun Microsystems ptr = statep->ls_line; 5615afdda45fSVasumathi Sundaram - Sun Microsystems break; 5616e7801d59Ssowmini case LINKPROP_DEFAULT: 5617e7801d59Ssowmini print_linkprop(linkid, statep, propname, 5618e7801d59Ssowmini DLADM_PROP_VAL_DEFAULT, "%s", &ptr); 5619e7801d59Ssowmini if (statep->ls_status != DLADM_STATUS_OK) 5620e7801d59Ssowmini goto skip; 5621e7801d59Ssowmini ptr = statep->ls_line; 5622e7801d59Ssowmini break; 5623e7801d59Ssowmini case LINKPROP_POSSIBLE: 5624e7801d59Ssowmini print_linkprop(linkid, statep, propname, 5625e7801d59Ssowmini DLADM_PROP_VAL_MODIFIABLE, "%s ", &ptr); 5626e7801d59Ssowmini if (statep->ls_status != DLADM_STATUS_OK) 5627e7801d59Ssowmini goto skip; 5628e7801d59Ssowmini ptr = statep->ls_line; 5629e7801d59Ssowmini break; 5630e7801d59Ssowmini default: 5631e7801d59Ssowmini die("invalid input"); 5632e7801d59Ssowmini break; 5633e7801d59Ssowmini } 5634e7801d59Ssowmini return (ptr); 5635e7801d59Ssowmini skip: 5636e7801d59Ssowmini if (statep->ls_status != DLADM_STATUS_OK) 5637e7801d59Ssowmini return (NULL); 5638e7801d59Ssowmini else 5639e7801d59Ssowmini return (""); 5640e7801d59Ssowmini } 5641e7801d59Ssowmini 5642bcb5c89dSSowmini Varadhan static boolean_t 5643bcb5c89dSSowmini Varadhan linkprop_is_supported(datalink_id_t linkid, const char *propname, 5644bcb5c89dSSowmini Varadhan show_linkprop_state_t *statep) 5645bcb5c89dSSowmini Varadhan { 5646bcb5c89dSSowmini Varadhan dladm_status_t status; 5647bcb5c89dSSowmini Varadhan uint_t valcnt = DLADM_MAX_PROP_VALCNT; 5648bcb5c89dSSowmini Varadhan 56494784fcbdSSowmini Varadhan /* if used with -p flag, always print output */ 56504784fcbdSSowmini Varadhan if (statep->ls_proplist != NULL) 56514784fcbdSSowmini Varadhan return (B_TRUE); 56524784fcbdSSowmini Varadhan 56534ac67f02SAnurag S. Maskey status = dladm_get_linkprop(handle, linkid, DLADM_PROP_VAL_DEFAULT, 5654bcb5c89dSSowmini Varadhan propname, statep->ls_propvals, &valcnt); 5655bcb5c89dSSowmini Varadhan 5656149b7eb2SSowmini Varadhan if (status == DLADM_STATUS_OK) 5657149b7eb2SSowmini Varadhan return (B_TRUE); 5658149b7eb2SSowmini Varadhan 5659149b7eb2SSowmini Varadhan /* 5660149b7eb2SSowmini Varadhan * A system wide default value is not available for the 5661149b7eb2SSowmini Varadhan * property. Check if current value can be retrieved. 5662149b7eb2SSowmini Varadhan */ 56634ac67f02SAnurag S. Maskey status = dladm_get_linkprop(handle, linkid, DLADM_PROP_VAL_CURRENT, 5664149b7eb2SSowmini Varadhan propname, statep->ls_propvals, &valcnt); 5665149b7eb2SSowmini Varadhan 5666149b7eb2SSowmini Varadhan return (status == DLADM_STATUS_OK); 5667bcb5c89dSSowmini Varadhan } 5668bcb5c89dSSowmini Varadhan 56694ac67f02SAnurag S. Maskey /* ARGSUSED */ 5670d62bc4baSyz147064 static int 56714ac67f02SAnurag S. Maskey show_linkprop(dladm_handle_t dh, datalink_id_t linkid, const char *propname, 56724ac67f02SAnurag S. Maskey void *arg) 56730ba2cbe9Sxc151355 { 56740ba2cbe9Sxc151355 show_linkprop_state_t *statep = arg; 5675e7801d59Ssowmini linkprop_args_t ls_arg; 56760ba2cbe9Sxc151355 5677e7801d59Ssowmini bzero(&ls_arg, sizeof (ls_arg)); 5678e7801d59Ssowmini ls_arg.ls_state = statep; 5679e7801d59Ssowmini ls_arg.ls_propname = (char *)propname; 5680e7801d59Ssowmini ls_arg.ls_linkid = linkid; 56810ba2cbe9Sxc151355 56820ba2cbe9Sxc151355 if (statep->ls_header) { 56830ba2cbe9Sxc151355 statep->ls_header = B_FALSE; 56840ba2cbe9Sxc151355 if (!statep->ls_parseable) 5685e7801d59Ssowmini print_header(&statep->ls_print); 56860ba2cbe9Sxc151355 } 568762ee1d25SArtem Kachitchkine /* 568862ee1d25SArtem Kachitchkine * This will need to be fixed when kernel interfaces are added 568962ee1d25SArtem Kachitchkine * to enable walking of all known private properties. For now, 569062ee1d25SArtem Kachitchkine * we are limited to walking persistent private properties only. 569162ee1d25SArtem Kachitchkine */ 569262ee1d25SArtem Kachitchkine if ((propname[0] == '_') && !statep->ls_persist && 569362ee1d25SArtem Kachitchkine (statep->ls_proplist == NULL)) 569462ee1d25SArtem Kachitchkine return (DLADM_WALK_CONTINUE); 5695149b7eb2SSowmini Varadhan if (!statep->ls_parseable && 5696149b7eb2SSowmini Varadhan !linkprop_is_supported(linkid, propname, statep)) 5697bcb5c89dSSowmini Varadhan return (DLADM_WALK_CONTINUE); 5698bcb5c89dSSowmini Varadhan 5699e7801d59Ssowmini dladm_print_output(&statep->ls_print, statep->ls_parseable, 5700e7801d59Ssowmini linkprop_callback, (void *)&ls_arg); 5701e7801d59Ssowmini 5702d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 57030ba2cbe9Sxc151355 } 57040ba2cbe9Sxc151355 57050ba2cbe9Sxc151355 static void 57068d5c46e6Sam223141 do_show_linkprop(int argc, char **argv, const char *use) 57070ba2cbe9Sxc151355 { 5708f4b3ec61Sdh155122 int option; 5709da14cebeSEric Cheng dladm_arg_list_t *proplist = NULL; 5710d62bc4baSyz147064 datalink_id_t linkid = DATALINK_ALL_LINKID; 57110ba2cbe9Sxc151355 show_linkprop_state_t state; 5712d62bc4baSyz147064 uint32_t flags = DLADM_OPT_ACTIVE; 5713d62bc4baSyz147064 dladm_status_t status; 5714e7801d59Ssowmini char *fields_str = NULL; 5715e7801d59Ssowmini print_field_t **fields; 5716e7801d59Ssowmini uint_t nfields; 57170d365605Sschuster boolean_t o_arg = B_FALSE; 5718e7801d59Ssowmini char *all_fields = 5719afdda45fSVasumathi Sundaram - Sun Microsystems "link,property,perm,value,default,possible"; 5720e7801d59Ssowmini 5721e7801d59Ssowmini fields_str = all_fields; 57220ba2cbe9Sxc151355 57230ba2cbe9Sxc151355 opterr = 0; 57240ba2cbe9Sxc151355 state.ls_propvals = NULL; 57250ba2cbe9Sxc151355 state.ls_line = NULL; 57260ba2cbe9Sxc151355 state.ls_parseable = B_FALSE; 57270ba2cbe9Sxc151355 state.ls_persist = B_FALSE; 57280ba2cbe9Sxc151355 state.ls_header = B_TRUE; 5729e7801d59Ssowmini state.ls_retstatus = DLADM_STATUS_OK; 5730e7801d59Ssowmini while ((option = getopt_long(argc, argv, ":p:cPo:", 57310ba2cbe9Sxc151355 prop_longopts, NULL)) != -1) { 57320ba2cbe9Sxc151355 switch (option) { 57330ba2cbe9Sxc151355 case 'p': 5734da14cebeSEric Cheng if (dladm_parse_link_props(optarg, &proplist, B_TRUE) 5735da14cebeSEric Cheng != DLADM_STATUS_OK) 573613994ee8Sxz162242 die("invalid link properties specified"); 57370ba2cbe9Sxc151355 break; 57380ba2cbe9Sxc151355 case 'c': 57390ba2cbe9Sxc151355 state.ls_parseable = B_TRUE; 57400ba2cbe9Sxc151355 break; 57410ba2cbe9Sxc151355 case 'P': 57420ba2cbe9Sxc151355 state.ls_persist = B_TRUE; 5743d62bc4baSyz147064 flags = DLADM_OPT_PERSIST; 57440ba2cbe9Sxc151355 break; 5745e7801d59Ssowmini case 'o': 57460d365605Sschuster o_arg = B_TRUE; 5747e7801d59Ssowmini if (strcasecmp(optarg, "all") == 0) 5748e7801d59Ssowmini fields_str = all_fields; 5749e7801d59Ssowmini else 5750e7801d59Ssowmini fields_str = optarg; 5751e7801d59Ssowmini break; 57520ba2cbe9Sxc151355 default: 57538d5c46e6Sam223141 die_opterr(optopt, option, use); 57540ba2cbe9Sxc151355 break; 57550ba2cbe9Sxc151355 } 57560ba2cbe9Sxc151355 } 57570ba2cbe9Sxc151355 57580d365605Sschuster if (state.ls_parseable && !o_arg) 57590d365605Sschuster die("-c requires -o"); 57600d365605Sschuster 57610d365605Sschuster if (state.ls_parseable && fields_str == all_fields) 57620d365605Sschuster die("\"-o all\" is invalid with -c"); 57630d365605Sschuster 5764d62bc4baSyz147064 if (optind == (argc - 1)) { 57654ac67f02SAnurag S. Maskey if ((status = dladm_name2info(handle, argv[optind], &linkid, 57664ac67f02SAnurag S. Maskey NULL, NULL, NULL)) != DLADM_STATUS_OK) { 5767d62bc4baSyz147064 die_dlerr(status, "link %s is not valid", argv[optind]); 5768d62bc4baSyz147064 } 5769d62bc4baSyz147064 } else if (optind != argc) { 57700ba2cbe9Sxc151355 usage(); 5771d62bc4baSyz147064 } 57720ba2cbe9Sxc151355 5773e7801d59Ssowmini bzero(&state.ls_print, sizeof (print_state_t)); 5774f4b3ec61Sdh155122 state.ls_proplist = proplist; 5775f595a68aSyz147064 state.ls_status = DLADM_STATUS_OK; 5776f4b3ec61Sdh155122 5777e7801d59Ssowmini fields = parse_output_fields(fields_str, linkprop_fields, 5778e7801d59Ssowmini LINKPROP_MAX_FIELDS, CMD_TYPE_ANY, &nfields); 5779e7801d59Ssowmini 5780e7801d59Ssowmini if (fields == NULL) { 5781e7801d59Ssowmini die("invalid field(s) specified"); 5782e7801d59Ssowmini return; 5783e7801d59Ssowmini } 5784e7801d59Ssowmini 5785e7801d59Ssowmini state.ls_print.ps_fields = fields; 5786e7801d59Ssowmini state.ls_print.ps_nfields = nfields; 5787d62bc4baSyz147064 if (linkid == DATALINK_ALL_LINKID) { 57884ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(show_linkprop_onelink, handle, 57894ac67f02SAnurag S. Maskey &state, DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE, flags); 5790f4b3ec61Sdh155122 } else { 57914ac67f02SAnurag S. Maskey (void) show_linkprop_onelink(handle, linkid, &state); 5792f4b3ec61Sdh155122 } 5793da14cebeSEric Cheng dladm_free_props(proplist); 5794f595a68aSyz147064 57954ac67f02SAnurag S. Maskey if (state.ls_retstatus != DLADM_STATUS_OK) { 57964ac67f02SAnurag S. Maskey dladm_close(handle); 5797f595a68aSyz147064 exit(EXIT_FAILURE); 5798f4b3ec61Sdh155122 } 57994ac67f02SAnurag S. Maskey } 5800f4b3ec61Sdh155122 5801d62bc4baSyz147064 static int 58024ac67f02SAnurag S. Maskey show_linkprop_onelink(dladm_handle_t hdl, datalink_id_t linkid, void *arg) 5803f4b3ec61Sdh155122 { 5804948f2876Sss150715 int i; 5805f4b3ec61Sdh155122 char *buf; 5806d62bc4baSyz147064 uint32_t flags; 5807da14cebeSEric Cheng dladm_arg_list_t *proplist = NULL; 5808d62bc4baSyz147064 show_linkprop_state_t *statep = arg; 5809d62bc4baSyz147064 dlpi_handle_t dh = NULL; 5810f4b3ec61Sdh155122 5811d62bc4baSyz147064 statep->ls_status = DLADM_STATUS_OK; 5812d62bc4baSyz147064 58134ac67f02SAnurag S. Maskey if (dladm_datalink_id2info(hdl, linkid, &flags, NULL, NULL, 58144ac67f02SAnurag S. Maskey statep->ls_link, MAXLINKNAMELEN) != DLADM_STATUS_OK) { 5815d62bc4baSyz147064 statep->ls_status = DLADM_STATUS_NOTFOUND; 5816d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 5817d62bc4baSyz147064 } 5818d62bc4baSyz147064 5819d62bc4baSyz147064 if ((statep->ls_persist && !(flags & DLADM_OPT_PERSIST)) || 5820d62bc4baSyz147064 (!statep->ls_persist && !(flags & DLADM_OPT_ACTIVE))) { 5821d62bc4baSyz147064 statep->ls_status = DLADM_STATUS_BADARG; 5822d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 5823d62bc4baSyz147064 } 5824d62bc4baSyz147064 5825f4b3ec61Sdh155122 proplist = statep->ls_proplist; 58260ba2cbe9Sxc151355 58270ba2cbe9Sxc151355 /* 58280ba2cbe9Sxc151355 * When some WiFi links are opened for the first time, their hardware 58290ba2cbe9Sxc151355 * automatically scans for APs and does other slow operations. Thus, 58300ba2cbe9Sxc151355 * if there are no open links, the retrieval of link properties 58310ba2cbe9Sxc151355 * (below) will proceed slowly unless we hold the link open. 5832d62bc4baSyz147064 * 5833d62bc4baSyz147064 * Note that failure of dlpi_open() does not necessarily mean invalid 5834d62bc4baSyz147064 * link properties, because dlpi_open() may fail because of incorrect 5835d62bc4baSyz147064 * autopush configuration. Therefore, we ingore the return value of 5836d62bc4baSyz147064 * dlpi_open(). 58370ba2cbe9Sxc151355 */ 5838d62bc4baSyz147064 if (!statep->ls_persist) 5839d62bc4baSyz147064 (void) dlpi_open(statep->ls_link, &dh, 0); 58400ba2cbe9Sxc151355 5841d62bc4baSyz147064 buf = malloc((sizeof (char *) + DLADM_PROP_VAL_MAX) * 5842d62bc4baSyz147064 DLADM_MAX_PROP_VALCNT + MAX_PROP_LINE); 584333343a97Smeem if (buf == NULL) 584433343a97Smeem die("insufficient memory"); 584533343a97Smeem 5846f4b3ec61Sdh155122 statep->ls_propvals = (char **)(void *)buf; 5847d62bc4baSyz147064 for (i = 0; i < DLADM_MAX_PROP_VALCNT; i++) { 5848d62bc4baSyz147064 statep->ls_propvals[i] = buf + 5849d62bc4baSyz147064 sizeof (char *) * DLADM_MAX_PROP_VALCNT + 58500ba2cbe9Sxc151355 i * DLADM_PROP_VAL_MAX; 58510ba2cbe9Sxc151355 } 5852f4b3ec61Sdh155122 statep->ls_line = buf + 5853d62bc4baSyz147064 (sizeof (char *) + DLADM_PROP_VAL_MAX) * DLADM_MAX_PROP_VALCNT; 58540ba2cbe9Sxc151355 58550ba2cbe9Sxc151355 if (proplist != NULL) { 5856da14cebeSEric Cheng for (i = 0; i < proplist->al_count; i++) { 58574ac67f02SAnurag S. Maskey (void) show_linkprop(hdl, linkid, 5858da14cebeSEric Cheng proplist->al_info[i].ai_name, statep); 58590ba2cbe9Sxc151355 } 5860d62bc4baSyz147064 } else { 58614ac67f02SAnurag S. Maskey (void) dladm_walk_linkprop(hdl, linkid, statep, 58624ac67f02SAnurag S. Maskey show_linkprop); 5863d62bc4baSyz147064 } 5864d62bc4baSyz147064 if (dh != NULL) 5865948f2876Sss150715 dlpi_close(dh); 58660ba2cbe9Sxc151355 free(buf); 5867d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 58680ba2cbe9Sxc151355 } 58690ba2cbe9Sxc151355 58700ba2cbe9Sxc151355 static dladm_status_t 5871d62bc4baSyz147064 set_linkprop_persist(datalink_id_t linkid, const char *prop_name, 5872d62bc4baSyz147064 char **prop_val, uint_t val_cnt, boolean_t reset) 58730ba2cbe9Sxc151355 { 58740ba2cbe9Sxc151355 dladm_status_t status; 58750ba2cbe9Sxc151355 58764ac67f02SAnurag S. Maskey status = dladm_set_linkprop(handle, linkid, prop_name, prop_val, 58774ac67f02SAnurag S. Maskey val_cnt, DLADM_OPT_PERSIST); 58780ba2cbe9Sxc151355 58790ba2cbe9Sxc151355 if (status != DLADM_STATUS_OK) { 5880da14cebeSEric Cheng warn_dlerr(status, "cannot persistently %s link property '%s'", 5881da14cebeSEric Cheng reset ? "reset" : "set", prop_name); 58820ba2cbe9Sxc151355 } 58830ba2cbe9Sxc151355 return (status); 58840ba2cbe9Sxc151355 } 58850ba2cbe9Sxc151355 5886da14cebeSEric Cheng static int 58874ac67f02SAnurag S. Maskey reset_one_linkprop(dladm_handle_t dh, datalink_id_t linkid, 58884ac67f02SAnurag S. Maskey const char *propname, void *arg) 5889da14cebeSEric Cheng { 5890da14cebeSEric Cheng set_linkprop_state_t *statep = arg; 5891da14cebeSEric Cheng dladm_status_t status; 5892da14cebeSEric Cheng 58934ac67f02SAnurag S. Maskey status = dladm_set_linkprop(dh, linkid, propname, NULL, 0, 5894da14cebeSEric Cheng DLADM_OPT_ACTIVE); 5895da14cebeSEric Cheng if (status != DLADM_STATUS_OK) { 5896da14cebeSEric Cheng warn_dlerr(status, "cannot reset link property '%s' on '%s'", 5897da14cebeSEric Cheng propname, statep->ls_name); 5898da14cebeSEric Cheng } 5899da14cebeSEric Cheng if (!statep->ls_temp) { 5900da14cebeSEric Cheng dladm_status_t s; 5901da14cebeSEric Cheng 5902da14cebeSEric Cheng s = set_linkprop_persist(linkid, propname, NULL, 0, 5903da14cebeSEric Cheng statep->ls_reset); 5904da14cebeSEric Cheng if (s != DLADM_STATUS_OK) 5905da14cebeSEric Cheng status = s; 5906da14cebeSEric Cheng } 5907da14cebeSEric Cheng if (status != DLADM_STATUS_OK) 5908da14cebeSEric Cheng statep->ls_status = status; 5909da14cebeSEric Cheng 5910da14cebeSEric Cheng return (DLADM_WALK_CONTINUE); 5911da14cebeSEric Cheng } 5912da14cebeSEric Cheng 59130ba2cbe9Sxc151355 static void 59148d5c46e6Sam223141 set_linkprop(int argc, char **argv, boolean_t reset, const char *use) 59150ba2cbe9Sxc151355 { 59160ba2cbe9Sxc151355 int i, option; 59170ba2cbe9Sxc151355 char errmsg[DLADM_STRSIZE]; 5918d62bc4baSyz147064 char *altroot = NULL; 5919d62bc4baSyz147064 datalink_id_t linkid; 59200ba2cbe9Sxc151355 boolean_t temp = B_FALSE; 59210ba2cbe9Sxc151355 dladm_status_t status = DLADM_STATUS_OK; 5922da14cebeSEric Cheng dladm_arg_list_t *proplist = NULL; 59230ba2cbe9Sxc151355 59240ba2cbe9Sxc151355 opterr = 0; 59250ba2cbe9Sxc151355 while ((option = getopt_long(argc, argv, ":p:R:t", 59260ba2cbe9Sxc151355 prop_longopts, NULL)) != -1) { 59270ba2cbe9Sxc151355 switch (option) { 59280ba2cbe9Sxc151355 case 'p': 5929da14cebeSEric Cheng if (dladm_parse_link_props(optarg, &proplist, reset) != 5930da14cebeSEric Cheng DLADM_STATUS_OK) { 593133343a97Smeem die("invalid link properties specified"); 5932da14cebeSEric Cheng } 59330ba2cbe9Sxc151355 break; 59340ba2cbe9Sxc151355 case 't': 59350ba2cbe9Sxc151355 temp = B_TRUE; 59360ba2cbe9Sxc151355 break; 59370ba2cbe9Sxc151355 case 'R': 5938d62bc4baSyz147064 altroot = optarg; 59390ba2cbe9Sxc151355 break; 59400ba2cbe9Sxc151355 default: 59418d5c46e6Sam223141 die_opterr(optopt, option, use); 59428d5c46e6Sam223141 59430ba2cbe9Sxc151355 } 59440ba2cbe9Sxc151355 } 59450ba2cbe9Sxc151355 5946d62bc4baSyz147064 /* get link name (required last argument) */ 5947d62bc4baSyz147064 if (optind != (argc - 1)) 59480ba2cbe9Sxc151355 usage(); 59490ba2cbe9Sxc151355 5950d62bc4baSyz147064 if (proplist == NULL && !reset) 595133343a97Smeem die("link property must be specified"); 595233343a97Smeem 5953d62bc4baSyz147064 if (altroot != NULL) { 5954da14cebeSEric Cheng dladm_free_props(proplist); 5955d62bc4baSyz147064 altroot_cmd(altroot, argc, argv); 5956d62bc4baSyz147064 } 5957d62bc4baSyz147064 59584ac67f02SAnurag S. Maskey status = dladm_name2info(handle, argv[optind], &linkid, NULL, NULL, 59594ac67f02SAnurag S. Maskey NULL); 5960d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 5961d62bc4baSyz147064 die_dlerr(status, "link %s is not valid", argv[optind]); 5962d62bc4baSyz147064 5963d62bc4baSyz147064 if (proplist == NULL) { 5964da14cebeSEric Cheng set_linkprop_state_t state; 596513994ee8Sxz162242 5966da14cebeSEric Cheng state.ls_name = argv[optind]; 5967da14cebeSEric Cheng state.ls_reset = reset; 5968da14cebeSEric Cheng state.ls_temp = temp; 5969da14cebeSEric Cheng state.ls_status = DLADM_STATUS_OK; 5970da14cebeSEric Cheng 59714ac67f02SAnurag S. Maskey (void) dladm_walk_linkprop(handle, linkid, &state, 59724ac67f02SAnurag S. Maskey reset_one_linkprop); 5973da14cebeSEric Cheng 5974da14cebeSEric Cheng status = state.ls_status; 59750ba2cbe9Sxc151355 goto done; 59760ba2cbe9Sxc151355 } 59770ba2cbe9Sxc151355 5978da14cebeSEric Cheng for (i = 0; i < proplist->al_count; i++) { 5979da14cebeSEric Cheng dladm_arg_info_t *aip = &proplist->al_info[i]; 59800ba2cbe9Sxc151355 char **val; 59810ba2cbe9Sxc151355 uint_t count; 59820ba2cbe9Sxc151355 dladm_status_t s; 59830ba2cbe9Sxc151355 59840ba2cbe9Sxc151355 if (reset) { 59850ba2cbe9Sxc151355 val = NULL; 59860ba2cbe9Sxc151355 count = 0; 59870ba2cbe9Sxc151355 } else { 5988da14cebeSEric Cheng val = aip->ai_val; 5989da14cebeSEric Cheng count = aip->ai_count; 59900ba2cbe9Sxc151355 if (count == 0) { 599133343a97Smeem warn("no value specified for '%s'", 5992da14cebeSEric Cheng aip->ai_name); 59930ba2cbe9Sxc151355 status = DLADM_STATUS_BADARG; 59940ba2cbe9Sxc151355 continue; 59950ba2cbe9Sxc151355 } 59960ba2cbe9Sxc151355 } 59974ac67f02SAnurag S. Maskey s = dladm_set_linkprop(handle, linkid, aip->ai_name, val, count, 5998d62bc4baSyz147064 DLADM_OPT_ACTIVE); 59990ba2cbe9Sxc151355 if (s == DLADM_STATUS_OK) { 60000ba2cbe9Sxc151355 if (!temp) { 6001d62bc4baSyz147064 s = set_linkprop_persist(linkid, 6002da14cebeSEric Cheng aip->ai_name, val, count, reset); 60030ba2cbe9Sxc151355 if (s != DLADM_STATUS_OK) 60040ba2cbe9Sxc151355 status = s; 60050ba2cbe9Sxc151355 } 60060ba2cbe9Sxc151355 continue; 60070ba2cbe9Sxc151355 } 60080ba2cbe9Sxc151355 status = s; 60090ba2cbe9Sxc151355 switch (s) { 60100ba2cbe9Sxc151355 case DLADM_STATUS_NOTFOUND: 6011da14cebeSEric Cheng warn("invalid link property '%s'", aip->ai_name); 60120ba2cbe9Sxc151355 break; 60130ba2cbe9Sxc151355 case DLADM_STATUS_BADVAL: { 60140ba2cbe9Sxc151355 int j; 60150ba2cbe9Sxc151355 char *ptr, *lim; 60160ba2cbe9Sxc151355 char **propvals = NULL; 6017d62bc4baSyz147064 uint_t valcnt = DLADM_MAX_PROP_VALCNT; 60180ba2cbe9Sxc151355 60190ba2cbe9Sxc151355 ptr = malloc((sizeof (char *) + 6020d62bc4baSyz147064 DLADM_PROP_VAL_MAX) * DLADM_MAX_PROP_VALCNT + 60210ba2cbe9Sxc151355 MAX_PROP_LINE); 60220ba2cbe9Sxc151355 60230ba2cbe9Sxc151355 propvals = (char **)(void *)ptr; 602433343a97Smeem if (propvals == NULL) 602533343a97Smeem die("insufficient memory"); 602633343a97Smeem 6027d62bc4baSyz147064 for (j = 0; j < DLADM_MAX_PROP_VALCNT; j++) { 60280ba2cbe9Sxc151355 propvals[j] = ptr + sizeof (char *) * 6029d62bc4baSyz147064 DLADM_MAX_PROP_VALCNT + 60300ba2cbe9Sxc151355 j * DLADM_PROP_VAL_MAX; 60310ba2cbe9Sxc151355 } 60324ac67f02SAnurag S. Maskey s = dladm_get_linkprop(handle, linkid, 6033da14cebeSEric Cheng DLADM_PROP_VAL_MODIFIABLE, aip->ai_name, propvals, 6034d62bc4baSyz147064 &valcnt); 6035d62bc4baSyz147064 6036d62bc4baSyz147064 if (s != DLADM_STATUS_OK) { 6037d62bc4baSyz147064 warn_dlerr(status, "cannot set link property " 6038da14cebeSEric Cheng "'%s' on '%s'", aip->ai_name, argv[optind]); 6039d62bc4baSyz147064 free(propvals); 6040d62bc4baSyz147064 break; 6041d62bc4baSyz147064 } 60420ba2cbe9Sxc151355 60430ba2cbe9Sxc151355 ptr = errmsg; 60440ba2cbe9Sxc151355 lim = ptr + DLADM_STRSIZE; 60450ba2cbe9Sxc151355 *ptr = '\0'; 6046d62bc4baSyz147064 for (j = 0; j < valcnt; j++) { 60470ba2cbe9Sxc151355 ptr += snprintf(ptr, lim - ptr, "%s,", 60480ba2cbe9Sxc151355 propvals[j]); 60490ba2cbe9Sxc151355 if (ptr >= lim) 60500ba2cbe9Sxc151355 break; 60510ba2cbe9Sxc151355 } 6052f4b3ec61Sdh155122 if (ptr > errmsg) { 60530ba2cbe9Sxc151355 *(ptr - 1) = '\0'; 605433343a97Smeem warn("link property '%s' must be one of: %s", 6055da14cebeSEric Cheng aip->ai_name, errmsg); 6056f4b3ec61Sdh155122 } else 6057f4b3ec61Sdh155122 warn("invalid link property '%s'", *val); 60580ba2cbe9Sxc151355 free(propvals); 60590ba2cbe9Sxc151355 break; 60600ba2cbe9Sxc151355 } 60610ba2cbe9Sxc151355 default: 60620ba2cbe9Sxc151355 if (reset) { 606333343a97Smeem warn_dlerr(status, "cannot reset link property " 6064da14cebeSEric Cheng "'%s' on '%s'", aip->ai_name, argv[optind]); 60650ba2cbe9Sxc151355 } else { 606633343a97Smeem warn_dlerr(status, "cannot set link property " 6067da14cebeSEric Cheng "'%s' on '%s'", aip->ai_name, argv[optind]); 60680ba2cbe9Sxc151355 } 60690ba2cbe9Sxc151355 break; 60700ba2cbe9Sxc151355 } 60710ba2cbe9Sxc151355 } 60720ba2cbe9Sxc151355 done: 6073da14cebeSEric Cheng dladm_free_props(proplist); 60744ac67f02SAnurag S. Maskey if (status != DLADM_STATUS_OK) { 60754ac67f02SAnurag S. Maskey dladm_close(handle); 60760ba2cbe9Sxc151355 exit(1); 60770ba2cbe9Sxc151355 } 60784ac67f02SAnurag S. Maskey } 60790ba2cbe9Sxc151355 60800ba2cbe9Sxc151355 static void 60818d5c46e6Sam223141 do_set_linkprop(int argc, char **argv, const char *use) 60820ba2cbe9Sxc151355 { 60838d5c46e6Sam223141 set_linkprop(argc, argv, B_FALSE, use); 60840ba2cbe9Sxc151355 } 60850ba2cbe9Sxc151355 60860ba2cbe9Sxc151355 static void 60878d5c46e6Sam223141 do_reset_linkprop(int argc, char **argv, const char *use) 60880ba2cbe9Sxc151355 { 60898d5c46e6Sam223141 set_linkprop(argc, argv, B_TRUE, use); 60900ba2cbe9Sxc151355 } 60910ba2cbe9Sxc151355 60920ba2cbe9Sxc151355 static int 60930ba2cbe9Sxc151355 convert_secobj(char *buf, uint_t len, uint8_t *obj_val, uint_t *obj_lenp, 60940ba2cbe9Sxc151355 dladm_secobj_class_t class) 60950ba2cbe9Sxc151355 { 60960ba2cbe9Sxc151355 int error = 0; 60970ba2cbe9Sxc151355 6098a399b765Szf162725 if (class == DLADM_SECOBJ_CLASS_WPA) { 6099a399b765Szf162725 if (len < 8 || len > 63) 6100a399b765Szf162725 return (EINVAL); 6101a399b765Szf162725 (void) memcpy(obj_val, buf, len); 6102a399b765Szf162725 *obj_lenp = len; 6103a399b765Szf162725 return (error); 6104a399b765Szf162725 } 61050ba2cbe9Sxc151355 6106a399b765Szf162725 if (class == DLADM_SECOBJ_CLASS_WEP) { 61070ba2cbe9Sxc151355 switch (len) { 61080ba2cbe9Sxc151355 case 5: /* ASCII key sizes */ 61090ba2cbe9Sxc151355 case 13: 61100ba2cbe9Sxc151355 (void) memcpy(obj_val, buf, len); 61110ba2cbe9Sxc151355 *obj_lenp = len; 61120ba2cbe9Sxc151355 break; 61130ba2cbe9Sxc151355 case 10: /* Hex key sizes, not preceded by 0x */ 61140ba2cbe9Sxc151355 case 26: 61150ba2cbe9Sxc151355 error = hexascii_to_octet(buf, len, obj_val, obj_lenp); 61160ba2cbe9Sxc151355 break; 61170ba2cbe9Sxc151355 case 12: /* Hex key sizes, preceded by 0x */ 61180ba2cbe9Sxc151355 case 28: 61190ba2cbe9Sxc151355 if (strncmp(buf, "0x", 2) != 0) 61200ba2cbe9Sxc151355 return (EINVAL); 6121a399b765Szf162725 error = hexascii_to_octet(buf + 2, len - 2, 6122a399b765Szf162725 obj_val, obj_lenp); 61230ba2cbe9Sxc151355 break; 61240ba2cbe9Sxc151355 default: 61250ba2cbe9Sxc151355 return (EINVAL); 61260ba2cbe9Sxc151355 } 61270ba2cbe9Sxc151355 return (error); 61280ba2cbe9Sxc151355 } 61290ba2cbe9Sxc151355 6130a399b765Szf162725 return (ENOENT); 6131a399b765Szf162725 } 6132a399b765Szf162725 61330ba2cbe9Sxc151355 static void 61340ba2cbe9Sxc151355 defersig(int sig) 61350ba2cbe9Sxc151355 { 61360ba2cbe9Sxc151355 signalled = sig; 61370ba2cbe9Sxc151355 } 61380ba2cbe9Sxc151355 61390ba2cbe9Sxc151355 static int 61400ba2cbe9Sxc151355 get_secobj_from_tty(uint_t try, const char *objname, char *buf) 61410ba2cbe9Sxc151355 { 61420ba2cbe9Sxc151355 uint_t len = 0; 61430ba2cbe9Sxc151355 int c; 61440ba2cbe9Sxc151355 struct termios stored, current; 61450ba2cbe9Sxc151355 void (*sigfunc)(int); 61460ba2cbe9Sxc151355 61470ba2cbe9Sxc151355 /* 61480ba2cbe9Sxc151355 * Turn off echo -- but before we do so, defer SIGINT handling 61490ba2cbe9Sxc151355 * so that a ^C doesn't leave the terminal corrupted. 61500ba2cbe9Sxc151355 */ 61510ba2cbe9Sxc151355 sigfunc = signal(SIGINT, defersig); 61520ba2cbe9Sxc151355 (void) fflush(stdin); 61530ba2cbe9Sxc151355 (void) tcgetattr(0, &stored); 61540ba2cbe9Sxc151355 current = stored; 61550ba2cbe9Sxc151355 current.c_lflag &= ~(ICANON|ECHO); 61560ba2cbe9Sxc151355 current.c_cc[VTIME] = 0; 61570ba2cbe9Sxc151355 current.c_cc[VMIN] = 1; 61580ba2cbe9Sxc151355 (void) tcsetattr(0, TCSANOW, ¤t); 61590ba2cbe9Sxc151355 again: 61600ba2cbe9Sxc151355 if (try == 1) 61610ba2cbe9Sxc151355 (void) printf(gettext("provide value for '%s': "), objname); 61620ba2cbe9Sxc151355 else 61630ba2cbe9Sxc151355 (void) printf(gettext("confirm value for '%s': "), objname); 61640ba2cbe9Sxc151355 61650ba2cbe9Sxc151355 (void) fflush(stdout); 61660ba2cbe9Sxc151355 while (signalled == 0) { 61670ba2cbe9Sxc151355 c = getchar(); 61680ba2cbe9Sxc151355 if (c == '\n' || c == '\r') { 61690ba2cbe9Sxc151355 if (len != 0) 61700ba2cbe9Sxc151355 break; 61710ba2cbe9Sxc151355 (void) putchar('\n'); 61720ba2cbe9Sxc151355 goto again; 61730ba2cbe9Sxc151355 } 61740ba2cbe9Sxc151355 61750ba2cbe9Sxc151355 buf[len++] = c; 61760ba2cbe9Sxc151355 if (len >= DLADM_SECOBJ_VAL_MAX - 1) 61770ba2cbe9Sxc151355 break; 61780ba2cbe9Sxc151355 (void) putchar('*'); 61790ba2cbe9Sxc151355 } 61800ba2cbe9Sxc151355 61810ba2cbe9Sxc151355 (void) putchar('\n'); 61820ba2cbe9Sxc151355 (void) fflush(stdin); 61830ba2cbe9Sxc151355 61840ba2cbe9Sxc151355 /* 61850ba2cbe9Sxc151355 * Restore terminal setting and handle deferred signals. 61860ba2cbe9Sxc151355 */ 61870ba2cbe9Sxc151355 (void) tcsetattr(0, TCSANOW, &stored); 61880ba2cbe9Sxc151355 61890ba2cbe9Sxc151355 (void) signal(SIGINT, sigfunc); 61900ba2cbe9Sxc151355 if (signalled != 0) 61910ba2cbe9Sxc151355 (void) kill(getpid(), signalled); 61920ba2cbe9Sxc151355 61930ba2cbe9Sxc151355 return (len); 61940ba2cbe9Sxc151355 } 61950ba2cbe9Sxc151355 61960ba2cbe9Sxc151355 static int 61970ba2cbe9Sxc151355 get_secobj_val(char *obj_name, uint8_t *obj_val, uint_t *obj_lenp, 61980ba2cbe9Sxc151355 dladm_secobj_class_t class, FILE *filep) 61990ba2cbe9Sxc151355 { 62000ba2cbe9Sxc151355 int rval; 62010ba2cbe9Sxc151355 uint_t len, len2; 62020ba2cbe9Sxc151355 char buf[DLADM_SECOBJ_VAL_MAX], buf2[DLADM_SECOBJ_VAL_MAX]; 62030ba2cbe9Sxc151355 62040ba2cbe9Sxc151355 if (filep == NULL) { 62050ba2cbe9Sxc151355 len = get_secobj_from_tty(1, obj_name, buf); 62060ba2cbe9Sxc151355 rval = convert_secobj(buf, len, obj_val, obj_lenp, class); 62070ba2cbe9Sxc151355 if (rval == 0) { 62080ba2cbe9Sxc151355 len2 = get_secobj_from_tty(2, obj_name, buf2); 62090ba2cbe9Sxc151355 if (len != len2 || memcmp(buf, buf2, len) != 0) 62100ba2cbe9Sxc151355 rval = ENOTSUP; 62110ba2cbe9Sxc151355 } 62120ba2cbe9Sxc151355 return (rval); 62130ba2cbe9Sxc151355 } else { 62140ba2cbe9Sxc151355 for (;;) { 62150ba2cbe9Sxc151355 if (fgets(buf, sizeof (buf), filep) == NULL) 62160ba2cbe9Sxc151355 break; 62170ba2cbe9Sxc151355 if (isspace(buf[0])) 62180ba2cbe9Sxc151355 continue; 62190ba2cbe9Sxc151355 62200ba2cbe9Sxc151355 len = strlen(buf); 62210ba2cbe9Sxc151355 if (buf[len - 1] == '\n') { 62220ba2cbe9Sxc151355 buf[len - 1] = '\0'; 62230ba2cbe9Sxc151355 len--; 62240ba2cbe9Sxc151355 } 62250ba2cbe9Sxc151355 break; 62260ba2cbe9Sxc151355 } 62270ba2cbe9Sxc151355 (void) fclose(filep); 62280ba2cbe9Sxc151355 } 62290ba2cbe9Sxc151355 return (convert_secobj(buf, len, obj_val, obj_lenp, class)); 62300ba2cbe9Sxc151355 } 62310ba2cbe9Sxc151355 62320ba2cbe9Sxc151355 static boolean_t 62330ba2cbe9Sxc151355 check_auth(const char *auth) 62340ba2cbe9Sxc151355 { 62350ba2cbe9Sxc151355 struct passwd *pw; 62360ba2cbe9Sxc151355 62370ba2cbe9Sxc151355 if ((pw = getpwuid(getuid())) == NULL) 62380ba2cbe9Sxc151355 return (B_FALSE); 62390ba2cbe9Sxc151355 62400ba2cbe9Sxc151355 return (chkauthattr(auth, pw->pw_name) != 0); 62410ba2cbe9Sxc151355 } 62420ba2cbe9Sxc151355 62430ba2cbe9Sxc151355 static void 62440ba2cbe9Sxc151355 audit_secobj(char *auth, char *class, char *obj, 62450ba2cbe9Sxc151355 boolean_t success, boolean_t create) 62460ba2cbe9Sxc151355 { 62470ba2cbe9Sxc151355 adt_session_data_t *ah; 62480ba2cbe9Sxc151355 adt_event_data_t *event; 62490ba2cbe9Sxc151355 au_event_t flag; 62500ba2cbe9Sxc151355 char *errstr; 62510ba2cbe9Sxc151355 62520ba2cbe9Sxc151355 if (create) { 62530ba2cbe9Sxc151355 flag = ADT_dladm_create_secobj; 62540ba2cbe9Sxc151355 errstr = "ADT_dladm_create_secobj"; 62550ba2cbe9Sxc151355 } else { 62560ba2cbe9Sxc151355 flag = ADT_dladm_delete_secobj; 62570ba2cbe9Sxc151355 errstr = "ADT_dladm_delete_secobj"; 62580ba2cbe9Sxc151355 } 62590ba2cbe9Sxc151355 626033343a97Smeem if (adt_start_session(&ah, NULL, ADT_USE_PROC_DATA) != 0) 626133343a97Smeem die("adt_start_session: %s", strerror(errno)); 62620ba2cbe9Sxc151355 626333343a97Smeem if ((event = adt_alloc_event(ah, flag)) == NULL) 626433343a97Smeem die("adt_alloc_event (%s): %s", errstr, strerror(errno)); 62650ba2cbe9Sxc151355 62660ba2cbe9Sxc151355 /* fill in audit info */ 62670ba2cbe9Sxc151355 if (create) { 62680ba2cbe9Sxc151355 event->adt_dladm_create_secobj.auth_used = auth; 62690ba2cbe9Sxc151355 event->adt_dladm_create_secobj.obj_class = class; 62700ba2cbe9Sxc151355 event->adt_dladm_create_secobj.obj_name = obj; 62710ba2cbe9Sxc151355 } else { 62720ba2cbe9Sxc151355 event->adt_dladm_delete_secobj.auth_used = auth; 62730ba2cbe9Sxc151355 event->adt_dladm_delete_secobj.obj_class = class; 62740ba2cbe9Sxc151355 event->adt_dladm_delete_secobj.obj_name = obj; 62750ba2cbe9Sxc151355 } 62760ba2cbe9Sxc151355 62770ba2cbe9Sxc151355 if (success) { 62780ba2cbe9Sxc151355 if (adt_put_event(event, ADT_SUCCESS, ADT_SUCCESS) != 0) { 627933343a97Smeem die("adt_put_event (%s, success): %s", errstr, 628033343a97Smeem strerror(errno)); 62810ba2cbe9Sxc151355 } 62820ba2cbe9Sxc151355 } else { 62830ba2cbe9Sxc151355 if (adt_put_event(event, ADT_FAILURE, 62840ba2cbe9Sxc151355 ADT_FAIL_VALUE_AUTH) != 0) { 628533343a97Smeem die("adt_put_event: (%s, failure): %s", errstr, 628633343a97Smeem strerror(errno)); 62870ba2cbe9Sxc151355 } 62880ba2cbe9Sxc151355 } 62890ba2cbe9Sxc151355 62900ba2cbe9Sxc151355 adt_free_event(event); 62910ba2cbe9Sxc151355 (void) adt_end_session(ah); 62920ba2cbe9Sxc151355 } 62930ba2cbe9Sxc151355 62940ba2cbe9Sxc151355 #define MAX_SECOBJS 32 62950ba2cbe9Sxc151355 #define MAX_SECOBJ_NAMELEN 32 62960ba2cbe9Sxc151355 static void 62978d5c46e6Sam223141 do_create_secobj(int argc, char **argv, const char *use) 62980ba2cbe9Sxc151355 { 62990ba2cbe9Sxc151355 int option, rval; 63000ba2cbe9Sxc151355 FILE *filep = NULL; 63010ba2cbe9Sxc151355 char *obj_name = NULL; 63020ba2cbe9Sxc151355 char *class_name = NULL; 63030ba2cbe9Sxc151355 uint8_t obj_val[DLADM_SECOBJ_VAL_MAX]; 63040ba2cbe9Sxc151355 uint_t obj_len; 63050ba2cbe9Sxc151355 boolean_t success, temp = B_FALSE; 63060ba2cbe9Sxc151355 dladm_status_t status; 63070ba2cbe9Sxc151355 dladm_secobj_class_t class = -1; 63080ba2cbe9Sxc151355 uid_t euid; 63090ba2cbe9Sxc151355 63100ba2cbe9Sxc151355 opterr = 0; 63110ba2cbe9Sxc151355 (void) memset(obj_val, 0, DLADM_SECOBJ_VAL_MAX); 63120ba2cbe9Sxc151355 while ((option = getopt_long(argc, argv, ":f:c:R:t", 63130ba2cbe9Sxc151355 wifi_longopts, NULL)) != -1) { 63140ba2cbe9Sxc151355 switch (option) { 63150ba2cbe9Sxc151355 case 'f': 63160ba2cbe9Sxc151355 euid = geteuid(); 63170ba2cbe9Sxc151355 (void) seteuid(getuid()); 63180ba2cbe9Sxc151355 filep = fopen(optarg, "r"); 63190ba2cbe9Sxc151355 if (filep == NULL) { 632033343a97Smeem die("cannot open %s: %s", optarg, 632133343a97Smeem strerror(errno)); 63220ba2cbe9Sxc151355 } 63230ba2cbe9Sxc151355 (void) seteuid(euid); 63240ba2cbe9Sxc151355 break; 63250ba2cbe9Sxc151355 case 'c': 63260ba2cbe9Sxc151355 class_name = optarg; 63270ba2cbe9Sxc151355 status = dladm_str2secobjclass(optarg, &class); 63280ba2cbe9Sxc151355 if (status != DLADM_STATUS_OK) { 632933343a97Smeem die("invalid secure object class '%s', " 6330a399b765Szf162725 "valid values are: wep, wpa", optarg); 63310ba2cbe9Sxc151355 } 63320ba2cbe9Sxc151355 break; 63330ba2cbe9Sxc151355 case 't': 63340ba2cbe9Sxc151355 temp = B_TRUE; 63350ba2cbe9Sxc151355 break; 63360ba2cbe9Sxc151355 case 'R': 63370ba2cbe9Sxc151355 status = dladm_set_rootdir(optarg); 63380ba2cbe9Sxc151355 if (status != DLADM_STATUS_OK) { 633933343a97Smeem die_dlerr(status, "invalid directory " 634033343a97Smeem "specified"); 63410ba2cbe9Sxc151355 } 63420ba2cbe9Sxc151355 break; 63430ba2cbe9Sxc151355 default: 63448d5c46e6Sam223141 die_opterr(optopt, option, use); 63450ba2cbe9Sxc151355 break; 63460ba2cbe9Sxc151355 } 63470ba2cbe9Sxc151355 } 63480ba2cbe9Sxc151355 63490ba2cbe9Sxc151355 if (optind == (argc - 1)) 63500ba2cbe9Sxc151355 obj_name = argv[optind]; 63510ba2cbe9Sxc151355 else if (optind != argc) 63520ba2cbe9Sxc151355 usage(); 63530ba2cbe9Sxc151355 635433343a97Smeem if (class == -1) 635533343a97Smeem die("secure object class required"); 63560ba2cbe9Sxc151355 635733343a97Smeem if (obj_name == NULL) 635833343a97Smeem die("secure object name required"); 63590ba2cbe9Sxc151355 6360a9489f61SAnurag S. Maskey if (!dladm_valid_secobj_name(obj_name)) 6361a9489f61SAnurag S. Maskey die("invalid secure object name '%s'", obj_name); 6362a9489f61SAnurag S. Maskey 63630ba2cbe9Sxc151355 success = check_auth(LINK_SEC_AUTH); 63640ba2cbe9Sxc151355 audit_secobj(LINK_SEC_AUTH, class_name, obj_name, success, B_TRUE); 636533343a97Smeem if (!success) 636633343a97Smeem die("authorization '%s' is required", LINK_SEC_AUTH); 63670ba2cbe9Sxc151355 636833343a97Smeem rval = get_secobj_val(obj_name, obj_val, &obj_len, class, filep); 636933343a97Smeem if (rval != 0) { 63700ba2cbe9Sxc151355 switch (rval) { 63710ba2cbe9Sxc151355 case ENOENT: 637233343a97Smeem die("invalid secure object class"); 63730ba2cbe9Sxc151355 break; 63740ba2cbe9Sxc151355 case EINVAL: 637533343a97Smeem die("invalid secure object value"); 63760ba2cbe9Sxc151355 break; 63770ba2cbe9Sxc151355 case ENOTSUP: 637833343a97Smeem die("verification failed"); 63790ba2cbe9Sxc151355 break; 63800ba2cbe9Sxc151355 default: 638133343a97Smeem die("invalid secure object: %s", strerror(rval)); 63820ba2cbe9Sxc151355 break; 63830ba2cbe9Sxc151355 } 63840ba2cbe9Sxc151355 } 63850ba2cbe9Sxc151355 63864ac67f02SAnurag S. Maskey status = dladm_set_secobj(handle, obj_name, class, obj_val, obj_len, 6387d62bc4baSyz147064 DLADM_OPT_CREATE | DLADM_OPT_ACTIVE); 63880ba2cbe9Sxc151355 if (status != DLADM_STATUS_OK) { 638933343a97Smeem die_dlerr(status, "could not create secure object '%s'", 639033343a97Smeem obj_name); 63910ba2cbe9Sxc151355 } 63920ba2cbe9Sxc151355 if (temp) 63930ba2cbe9Sxc151355 return; 63940ba2cbe9Sxc151355 63954ac67f02SAnurag S. Maskey status = dladm_set_secobj(handle, obj_name, class, obj_val, obj_len, 63960ba2cbe9Sxc151355 DLADM_OPT_PERSIST); 63970ba2cbe9Sxc151355 if (status != DLADM_STATUS_OK) { 639833343a97Smeem warn_dlerr(status, "could not persistently create secure " 639933343a97Smeem "object '%s'", obj_name); 64000ba2cbe9Sxc151355 } 64010ba2cbe9Sxc151355 } 64020ba2cbe9Sxc151355 64030ba2cbe9Sxc151355 static void 64048d5c46e6Sam223141 do_delete_secobj(int argc, char **argv, const char *use) 64050ba2cbe9Sxc151355 { 64060ba2cbe9Sxc151355 int i, option; 64070ba2cbe9Sxc151355 boolean_t temp = B_FALSE; 64080ba2cbe9Sxc151355 split_t *sp = NULL; 64090ba2cbe9Sxc151355 boolean_t success; 64100ba2cbe9Sxc151355 dladm_status_t status, pstatus; 64110ba2cbe9Sxc151355 64120ba2cbe9Sxc151355 opterr = 0; 64130ba2cbe9Sxc151355 status = pstatus = DLADM_STATUS_OK; 641433343a97Smeem while ((option = getopt_long(argc, argv, ":R:t", 64150ba2cbe9Sxc151355 wifi_longopts, NULL)) != -1) { 64160ba2cbe9Sxc151355 switch (option) { 64170ba2cbe9Sxc151355 case 't': 64180ba2cbe9Sxc151355 temp = B_TRUE; 64190ba2cbe9Sxc151355 break; 64200ba2cbe9Sxc151355 case 'R': 64210ba2cbe9Sxc151355 status = dladm_set_rootdir(optarg); 64220ba2cbe9Sxc151355 if (status != DLADM_STATUS_OK) { 642333343a97Smeem die_dlerr(status, "invalid directory " 642433343a97Smeem "specified"); 64250ba2cbe9Sxc151355 } 64260ba2cbe9Sxc151355 break; 64270ba2cbe9Sxc151355 default: 64288d5c46e6Sam223141 die_opterr(optopt, option, use); 64290ba2cbe9Sxc151355 break; 64300ba2cbe9Sxc151355 } 64310ba2cbe9Sxc151355 } 64320ba2cbe9Sxc151355 64330ba2cbe9Sxc151355 if (optind == (argc - 1)) { 64340ba2cbe9Sxc151355 sp = split(argv[optind], MAX_SECOBJS, MAX_SECOBJ_NAMELEN); 64350ba2cbe9Sxc151355 if (sp == NULL) { 643633343a97Smeem die("invalid secure object name(s): '%s'", 643733343a97Smeem argv[optind]); 64380ba2cbe9Sxc151355 } 64390ba2cbe9Sxc151355 } else if (optind != argc) 64400ba2cbe9Sxc151355 usage(); 64410ba2cbe9Sxc151355 644233343a97Smeem if (sp == NULL || sp->s_nfields < 1) 644333343a97Smeem die("secure object name required"); 64440ba2cbe9Sxc151355 64450ba2cbe9Sxc151355 success = check_auth(LINK_SEC_AUTH); 6446a399b765Szf162725 audit_secobj(LINK_SEC_AUTH, "unknown", argv[optind], success, B_FALSE); 644733343a97Smeem if (!success) 644833343a97Smeem die("authorization '%s' is required", LINK_SEC_AUTH); 64490ba2cbe9Sxc151355 64500ba2cbe9Sxc151355 for (i = 0; i < sp->s_nfields; i++) { 64514ac67f02SAnurag S. Maskey status = dladm_unset_secobj(handle, sp->s_fields[i], 64524ac67f02SAnurag S. Maskey DLADM_OPT_ACTIVE); 64530ba2cbe9Sxc151355 if (!temp) { 64544ac67f02SAnurag S. Maskey pstatus = dladm_unset_secobj(handle, sp->s_fields[i], 64550ba2cbe9Sxc151355 DLADM_OPT_PERSIST); 64560ba2cbe9Sxc151355 } else { 64570ba2cbe9Sxc151355 pstatus = DLADM_STATUS_OK; 64580ba2cbe9Sxc151355 } 64590ba2cbe9Sxc151355 64600ba2cbe9Sxc151355 if (status != DLADM_STATUS_OK) { 646133343a97Smeem warn_dlerr(status, "could not delete secure object " 646233343a97Smeem "'%s'", sp->s_fields[i]); 64630ba2cbe9Sxc151355 } 64640ba2cbe9Sxc151355 if (pstatus != DLADM_STATUS_OK) { 646533343a97Smeem warn_dlerr(pstatus, "could not persistently delete " 646633343a97Smeem "secure object '%s'", sp->s_fields[i]); 64670ba2cbe9Sxc151355 } 64680ba2cbe9Sxc151355 } 64694ac67f02SAnurag S. Maskey 64704ac67f02SAnurag S. Maskey if (status != DLADM_STATUS_OK || pstatus != DLADM_STATUS_OK) { 64714ac67f02SAnurag S. Maskey dladm_close(handle); 64720ba2cbe9Sxc151355 exit(1); 64730ba2cbe9Sxc151355 } 64744ac67f02SAnurag S. Maskey } 64750ba2cbe9Sxc151355 64760ba2cbe9Sxc151355 typedef struct show_secobj_state { 64770ba2cbe9Sxc151355 boolean_t ss_persist; 64780ba2cbe9Sxc151355 boolean_t ss_parseable; 64790ba2cbe9Sxc151355 boolean_t ss_header; 6480e7801d59Ssowmini print_state_t ss_print; 64810ba2cbe9Sxc151355 } show_secobj_state_t; 64820ba2cbe9Sxc151355 64830ba2cbe9Sxc151355 64840ba2cbe9Sxc151355 static boolean_t 64854ac67f02SAnurag S. Maskey show_secobj(dladm_handle_t dh, void *arg, const char *obj_name) 64860ba2cbe9Sxc151355 { 64870ba2cbe9Sxc151355 uint_t obj_len = DLADM_SECOBJ_VAL_MAX; 64880ba2cbe9Sxc151355 uint8_t obj_val[DLADM_SECOBJ_VAL_MAX]; 64890ba2cbe9Sxc151355 char buf[DLADM_STRSIZE]; 64900ba2cbe9Sxc151355 uint_t flags = 0; 64910ba2cbe9Sxc151355 dladm_secobj_class_t class; 64920ba2cbe9Sxc151355 show_secobj_state_t *statep = arg; 64930ba2cbe9Sxc151355 dladm_status_t status; 6494e7801d59Ssowmini secobj_fields_buf_t sbuf; 64950ba2cbe9Sxc151355 64965f5c9f54SAnurag S. Maskey bzero(&sbuf, sizeof (secobj_fields_buf_t)); 64970ba2cbe9Sxc151355 if (statep->ss_persist) 64980ba2cbe9Sxc151355 flags |= DLADM_OPT_PERSIST; 64990ba2cbe9Sxc151355 65004ac67f02SAnurag S. Maskey status = dladm_get_secobj(dh, obj_name, &class, obj_val, &obj_len, 65014ac67f02SAnurag S. Maskey flags); 650233343a97Smeem if (status != DLADM_STATUS_OK) 650333343a97Smeem die_dlerr(status, "cannot get secure object '%s'", obj_name); 65040ba2cbe9Sxc151355 65050ba2cbe9Sxc151355 if (statep->ss_header) { 65060ba2cbe9Sxc151355 statep->ss_header = B_FALSE; 65070ba2cbe9Sxc151355 if (!statep->ss_parseable) 6508e7801d59Ssowmini print_header(&statep->ss_print); 65090ba2cbe9Sxc151355 } 65100ba2cbe9Sxc151355 6511e7801d59Ssowmini (void) snprintf(sbuf.ss_obj_name, sizeof (sbuf.ss_obj_name), 6512e7801d59Ssowmini obj_name); 6513e7801d59Ssowmini (void) dladm_secobjclass2str(class, buf); 6514e7801d59Ssowmini (void) snprintf(sbuf.ss_class, sizeof (sbuf.ss_class), "%s", buf); 6515e7801d59Ssowmini if (getuid() == 0) { 65160ba2cbe9Sxc151355 char val[DLADM_SECOBJ_VAL_MAX * 2]; 65170ba2cbe9Sxc151355 uint_t len = sizeof (val); 65180ba2cbe9Sxc151355 6519e7801d59Ssowmini if (octet_to_hexascii(obj_val, obj_len, val, &len) == 0) 6520e7801d59Ssowmini (void) snprintf(sbuf.ss_val, 6521e7801d59Ssowmini sizeof (sbuf.ss_val), "%s", val); 65220ba2cbe9Sxc151355 } 6523e7801d59Ssowmini dladm_print_output(&statep->ss_print, statep->ss_parseable, 6524e7801d59Ssowmini dladm_print_field, (void *)&sbuf); 65250ba2cbe9Sxc151355 return (B_TRUE); 65260ba2cbe9Sxc151355 } 65270ba2cbe9Sxc151355 65280ba2cbe9Sxc151355 static void 65298d5c46e6Sam223141 do_show_secobj(int argc, char **argv, const char *use) 65300ba2cbe9Sxc151355 { 65310ba2cbe9Sxc151355 int option; 65320ba2cbe9Sxc151355 show_secobj_state_t state; 65330ba2cbe9Sxc151355 dladm_status_t status; 65340d365605Sschuster boolean_t o_arg = B_FALSE; 65350ba2cbe9Sxc151355 uint_t i; 65360ba2cbe9Sxc151355 split_t *sp; 65370ba2cbe9Sxc151355 uint_t flags; 6538e7801d59Ssowmini char *fields_str = NULL; 6539e7801d59Ssowmini print_field_t **fields; 6540e7801d59Ssowmini uint_t nfields; 6541e7801d59Ssowmini char *def_fields = "object,class"; 6542e7801d59Ssowmini char *all_fields = "object,class,value"; 65430ba2cbe9Sxc151355 65440ba2cbe9Sxc151355 opterr = 0; 6545e7801d59Ssowmini bzero(&state, sizeof (state)); 6546e7801d59Ssowmini state.ss_parseable = B_FALSE; 6547e7801d59Ssowmini fields_str = def_fields; 65480ba2cbe9Sxc151355 state.ss_persist = B_FALSE; 65490ba2cbe9Sxc151355 state.ss_parseable = B_FALSE; 65500ba2cbe9Sxc151355 state.ss_header = B_TRUE; 6551e7801d59Ssowmini while ((option = getopt_long(argc, argv, ":pPo:", 65520ba2cbe9Sxc151355 wifi_longopts, NULL)) != -1) { 65530ba2cbe9Sxc151355 switch (option) { 65540ba2cbe9Sxc151355 case 'p': 65550ba2cbe9Sxc151355 state.ss_parseable = B_TRUE; 65560ba2cbe9Sxc151355 break; 65570ba2cbe9Sxc151355 case 'P': 65580ba2cbe9Sxc151355 state.ss_persist = B_TRUE; 65590ba2cbe9Sxc151355 break; 6560e7801d59Ssowmini case 'o': 65610d365605Sschuster o_arg = B_TRUE; 6562e7801d59Ssowmini if (strcasecmp(optarg, "all") == 0) 6563e7801d59Ssowmini fields_str = all_fields; 6564e7801d59Ssowmini else 6565e7801d59Ssowmini fields_str = optarg; 65660ba2cbe9Sxc151355 break; 65670ba2cbe9Sxc151355 default: 65688d5c46e6Sam223141 die_opterr(optopt, option, use); 65690ba2cbe9Sxc151355 break; 65700ba2cbe9Sxc151355 } 65710ba2cbe9Sxc151355 } 65720ba2cbe9Sxc151355 65730d365605Sschuster if (state.ss_parseable && !o_arg) 65740d365605Sschuster die("option -c requires -o"); 65750d365605Sschuster 65760d365605Sschuster if (state.ss_parseable && fields_str == all_fields) 65770d365605Sschuster die("\"-o all\" is invalid with -p"); 65780d365605Sschuster 6579e7801d59Ssowmini fields = parse_output_fields(fields_str, secobj_fields, 6580e7801d59Ssowmini DEV_SOBJ_FIELDS, CMD_TYPE_ANY, &nfields); 6581e7801d59Ssowmini 6582e7801d59Ssowmini if (fields == NULL) { 6583e7801d59Ssowmini die("invalid field(s) specified"); 6584e7801d59Ssowmini return; 6585e7801d59Ssowmini } 6586e7801d59Ssowmini state.ss_print.ps_fields = fields; 6587e7801d59Ssowmini state.ss_print.ps_nfields = nfields; 6588e7801d59Ssowmini 6589e7801d59Ssowmini flags = state.ss_persist ? DLADM_OPT_PERSIST : 0; 65904ac67f02SAnurag S. Maskey 65910ba2cbe9Sxc151355 if (optind == (argc - 1)) { 65920ba2cbe9Sxc151355 sp = split(argv[optind], MAX_SECOBJS, MAX_SECOBJ_NAMELEN); 65930ba2cbe9Sxc151355 if (sp == NULL) { 659433343a97Smeem die("invalid secure object name(s): '%s'", 659533343a97Smeem argv[optind]); 65960ba2cbe9Sxc151355 } 65970ba2cbe9Sxc151355 for (i = 0; i < sp->s_nfields; i++) { 65984ac67f02SAnurag S. Maskey if (!show_secobj(handle, &state, sp->s_fields[i])) 65990ba2cbe9Sxc151355 break; 66000ba2cbe9Sxc151355 } 66010ba2cbe9Sxc151355 splitfree(sp); 66020ba2cbe9Sxc151355 return; 66030ba2cbe9Sxc151355 } else if (optind != argc) 66040ba2cbe9Sxc151355 usage(); 66050ba2cbe9Sxc151355 66064ac67f02SAnurag S. Maskey status = dladm_walk_secobj(handle, &state, show_secobj, flags); 66074ac67f02SAnurag S. Maskey 660833343a97Smeem if (status != DLADM_STATUS_OK) 660933343a97Smeem die_dlerr(status, "show-secobj"); 66100ba2cbe9Sxc151355 } 66110ba2cbe9Sxc151355 66120ba2cbe9Sxc151355 /*ARGSUSED*/ 6613d62bc4baSyz147064 static int 66144ac67f02SAnurag S. Maskey i_dladm_init_linkprop(dladm_handle_t dh, datalink_id_t linkid, void *arg) 6615d62bc4baSyz147064 { 66164ac67f02SAnurag S. Maskey (void) dladm_init_linkprop(dh, linkid, B_TRUE); 6617d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 6618d62bc4baSyz147064 } 6619d62bc4baSyz147064 66208d5c46e6Sam223141 /*ARGSUSED*/ 6621da14cebeSEric Cheng void 66228d5c46e6Sam223141 do_init_linkprop(int argc, char **argv, const char *use) 66230ba2cbe9Sxc151355 { 662430890389Sartem int option; 662530890389Sartem dladm_status_t status; 662630890389Sartem datalink_id_t linkid = DATALINK_ALL_LINKID; 662730890389Sartem datalink_media_t media = DATALINK_ANY_MEDIATYPE; 662830890389Sartem uint_t any_media = B_TRUE; 662930890389Sartem 663030890389Sartem opterr = 0; 663130890389Sartem while ((option = getopt(argc, argv, ":w")) != -1) { 663230890389Sartem switch (option) { 663330890389Sartem case 'w': 663430890389Sartem media = DL_WIFI; 663530890389Sartem any_media = B_FALSE; 663630890389Sartem break; 663730890389Sartem default: 66388d5c46e6Sam223141 /* 66398d5c46e6Sam223141 * Because init-linkprop is not a public command, 66408d5c46e6Sam223141 * print the usage instead. 66418d5c46e6Sam223141 */ 66428d5c46e6Sam223141 usage(); 664330890389Sartem break; 664430890389Sartem } 664530890389Sartem } 664630890389Sartem 664730890389Sartem if (optind == (argc - 1)) { 66484ac67f02SAnurag S. Maskey if ((status = dladm_name2info(handle, argv[optind], &linkid, 66494ac67f02SAnurag S. Maskey NULL, NULL, NULL)) != DLADM_STATUS_OK) 665030890389Sartem die_dlerr(status, "link %s is not valid", argv[optind]); 665130890389Sartem } else if (optind != argc) { 665230890389Sartem usage(); 665330890389Sartem } 665430890389Sartem 665530890389Sartem if (linkid == DATALINK_ALL_LINKID) { 6656d62bc4baSyz147064 /* 665730890389Sartem * linkprops of links of other classes have been initialized as 6658d62bc4baSyz147064 * part of the dladm up-xxx operation. 6659d62bc4baSyz147064 */ 66604ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(i_dladm_init_linkprop, handle, 66614ac67f02SAnurag S. Maskey NULL, DATALINK_CLASS_PHYS, media, DLADM_OPT_PERSIST); 666230890389Sartem } else { 66634ac67f02SAnurag S. Maskey (void) dladm_init_linkprop(handle, linkid, any_media); 666430890389Sartem } 66650ba2cbe9Sxc151355 } 66660ba2cbe9Sxc151355 66670ba2cbe9Sxc151355 static void 66688d5c46e6Sam223141 do_show_ether(int argc, char **argv, const char *use) 6669e7801d59Ssowmini { 6670e7801d59Ssowmini int option; 6671e7801d59Ssowmini datalink_id_t linkid; 6672e7801d59Ssowmini print_ether_state_t state; 6673e7801d59Ssowmini print_field_t **fields; 66740d365605Sschuster boolean_t o_arg = B_FALSE; 6675e7801d59Ssowmini char *fields_str; 6676e7801d59Ssowmini uint_t nfields; 6677e7801d59Ssowmini char *all_fields = 6678e7801d59Ssowmini "link,ptype,state,auto,speed-duplex,pause,rem_fault"; 6679e7801d59Ssowmini char *default_fields = 6680e7801d59Ssowmini "link,ptype,state,auto,speed-duplex,pause"; 6681e7801d59Ssowmini 6682e7801d59Ssowmini fields_str = default_fields; 6683e7801d59Ssowmini bzero(&state, sizeof (state)); 6684e7801d59Ssowmini state.es_link = NULL; 6685e7801d59Ssowmini state.es_parseable = B_FALSE; 6686e7801d59Ssowmini 6687e7801d59Ssowmini while ((option = getopt_long(argc, argv, "o:px", 6688e7801d59Ssowmini showeth_lopts, NULL)) != -1) { 6689e7801d59Ssowmini switch (option) { 6690e7801d59Ssowmini case 'x': 6691e7801d59Ssowmini state.es_extended = B_TRUE; 6692e7801d59Ssowmini break; 6693e7801d59Ssowmini case 'p': 6694e7801d59Ssowmini state.es_parseable = B_TRUE; 6695e7801d59Ssowmini break; 6696e7801d59Ssowmini case 'o': 66970d365605Sschuster o_arg = B_TRUE; 6698e7801d59Ssowmini if (strcasecmp(optarg, "all") == 0) 6699e7801d59Ssowmini fields_str = all_fields; 6700e7801d59Ssowmini else 6701e7801d59Ssowmini fields_str = optarg; 6702e7801d59Ssowmini break; 6703e7801d59Ssowmini default: 67048d5c46e6Sam223141 die_opterr(optopt, option, use); 6705e7801d59Ssowmini break; 6706e7801d59Ssowmini } 6707e7801d59Ssowmini } 6708e7801d59Ssowmini 67090d365605Sschuster if (state.es_parseable && !o_arg) 67100d365605Sschuster die("-p requires -o"); 67110d365605Sschuster 67120d365605Sschuster if (state.es_parseable && fields_str == all_fields) 67130d365605Sschuster die("\"-o all\" is invalid with -p"); 67140d365605Sschuster 6715e7801d59Ssowmini if (optind == (argc - 1)) 6716e7801d59Ssowmini state.es_link = argv[optind]; 6717e7801d59Ssowmini 6718e7801d59Ssowmini fields = parse_output_fields(fields_str, ether_fields, 6719e7801d59Ssowmini ETHER_MAX_FIELDS, CMD_TYPE_ANY, &nfields); 6720e7801d59Ssowmini 67214ac67f02SAnurag S. Maskey if (fields == NULL) 6722e7801d59Ssowmini die("invalid field(s) specified"); 67234ac67f02SAnurag S. Maskey 6724e7801d59Ssowmini state.es_print.ps_fields = fields; 6725e7801d59Ssowmini state.es_print.ps_nfields = nfields; 6726e7801d59Ssowmini 67274ac67f02SAnurag S. Maskey 6728e7801d59Ssowmini if (state.es_link == NULL) { 67294ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(show_etherprop, handle, &state, 6730e7801d59Ssowmini DATALINK_CLASS_PHYS, DL_ETHER, 6731e7801d59Ssowmini DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST); 6732e7801d59Ssowmini } else { 67334ac67f02SAnurag S. Maskey if (!link_is_ether(state.es_link, &linkid)) 6734e7801d59Ssowmini die("invalid link specified"); 67354ac67f02SAnurag S. Maskey (void) show_etherprop(handle, linkid, &state); 6736e7801d59Ssowmini } 6737e7801d59Ssowmini } 6738e7801d59Ssowmini 6739e7801d59Ssowmini static char * 6740e7801d59Ssowmini dladm_print_field(print_field_t *pf, void *arg) 6741e7801d59Ssowmini { 6742e7801d59Ssowmini char *value; 6743e7801d59Ssowmini 6744e7801d59Ssowmini value = (char *)arg + pf->pf_offset; 6745e7801d59Ssowmini return (value); 6746e7801d59Ssowmini } 6747e7801d59Ssowmini 6748e7801d59Ssowmini static int 67494ac67f02SAnurag S. Maskey show_etherprop(dladm_handle_t dh, datalink_id_t linkid, void *arg) 6750e7801d59Ssowmini { 6751e7801d59Ssowmini print_ether_state_t *statep = arg; 6752e7801d59Ssowmini ether_fields_buf_t ebuf; 67534784fcbdSSowmini Varadhan dladm_ether_info_t eattr; 67544784fcbdSSowmini Varadhan dladm_status_t status; 6755e7801d59Ssowmini 67565f5c9f54SAnurag S. Maskey bzero(&ebuf, sizeof (ether_fields_buf_t)); 67574ac67f02SAnurag S. Maskey if (dladm_datalink_id2info(dh, linkid, NULL, NULL, NULL, 6758e7801d59Ssowmini ebuf.eth_link, sizeof (ebuf.eth_link)) != DLADM_STATUS_OK) { 6759e7801d59Ssowmini return (DLADM_WALK_CONTINUE); 6760e7801d59Ssowmini } 6761e7801d59Ssowmini 6762e7801d59Ssowmini if (!statep->es_header && !statep->es_parseable) { 6763e7801d59Ssowmini print_header(&statep->es_print); 6764e7801d59Ssowmini statep->es_header = B_TRUE; 6765e7801d59Ssowmini } 6766e7801d59Ssowmini 67674ac67f02SAnurag S. Maskey status = dladm_ether_info(dh, linkid, &eattr); 67684784fcbdSSowmini Varadhan if (status != DLADM_STATUS_OK) 67694784fcbdSSowmini Varadhan goto cleanup; 6770e7801d59Ssowmini 67714784fcbdSSowmini Varadhan (void) strlcpy(ebuf.eth_ptype, "current", sizeof (ebuf.eth_ptype)); 6772e7801d59Ssowmini 67734784fcbdSSowmini Varadhan (void) dladm_ether_autoneg2str(ebuf.eth_autoneg, 67744784fcbdSSowmini Varadhan sizeof (ebuf.eth_autoneg), &eattr, CURRENT); 67754784fcbdSSowmini Varadhan (void) dladm_ether_pause2str(ebuf.eth_pause, 67764784fcbdSSowmini Varadhan sizeof (ebuf.eth_pause), &eattr, CURRENT); 67774784fcbdSSowmini Varadhan (void) dladm_ether_spdx2str(ebuf.eth_spdx, 67784784fcbdSSowmini Varadhan sizeof (ebuf.eth_spdx), &eattr, CURRENT); 67794784fcbdSSowmini Varadhan (void) strlcpy(ebuf.eth_state, 67804784fcbdSSowmini Varadhan dladm_linkstate2str(eattr.lei_state, ebuf.eth_state), 67814784fcbdSSowmini Varadhan sizeof (ebuf.eth_state)); 67824784fcbdSSowmini Varadhan (void) strlcpy(ebuf.eth_rem_fault, 67834784fcbdSSowmini Varadhan (eattr.lei_attr[CURRENT].le_fault ? "fault" : "none"), 67844784fcbdSSowmini Varadhan sizeof (ebuf.eth_rem_fault)); 6785e7801d59Ssowmini 6786e7801d59Ssowmini dladm_print_output(&statep->es_print, statep->es_parseable, 6787e7801d59Ssowmini dladm_print_field, &ebuf); 6788e7801d59Ssowmini 6789e7801d59Ssowmini if (statep->es_extended) 67904784fcbdSSowmini Varadhan show_ether_xprop(arg, &eattr); 6791e7801d59Ssowmini 67924784fcbdSSowmini Varadhan cleanup: 67934784fcbdSSowmini Varadhan dladm_ether_info_done(&eattr); 6794e7801d59Ssowmini return (DLADM_WALK_CONTINUE); 6795e7801d59Ssowmini } 6796e7801d59Ssowmini 6797e7801d59Ssowmini /* ARGSUSED */ 6798e7801d59Ssowmini static void 67998d5c46e6Sam223141 do_init_secobj(int argc, char **argv, const char *use) 68000ba2cbe9Sxc151355 { 68010ba2cbe9Sxc151355 dladm_status_t status; 68020ba2cbe9Sxc151355 68034ac67f02SAnurag S. Maskey status = dladm_init_secobj(handle); 680433343a97Smeem if (status != DLADM_STATUS_OK) 680533343a97Smeem die_dlerr(status, "secure object initialization failed"); 680633343a97Smeem } 680733343a97Smeem 6808d62bc4baSyz147064 /* 6809d62bc4baSyz147064 * "-R" option support. It is used for live upgrading. Append dladm commands 6810d62bc4baSyz147064 * to a upgrade script which will be run when the alternative root boots up: 6811d62bc4baSyz147064 * 6812b9e076dcSyz147064 * - If the /etc/dladm/datalink.conf file exists on the alternative root, 6813b9e076dcSyz147064 * append dladm commands to the <altroot>/var/svc/profile/upgrade_datalink 6814b9e076dcSyz147064 * script. This script will be run as part of the network/physical service. 6815b9e076dcSyz147064 * We cannot defer this to /var/svc/profile/upgrade because then the 6816b9e076dcSyz147064 * configuration will not be able to take effect before network/physical 6817b9e076dcSyz147064 * plumbs various interfaces. 6818d62bc4baSyz147064 * 6819b9e076dcSyz147064 * - If the /etc/dladm/datalink.conf file does not exist on the alternative 6820b9e076dcSyz147064 * root, append dladm commands to the <altroot>/var/svc/profile/upgrade script, 6821b9e076dcSyz147064 * which will be run in the manifest-import service. 6822d62bc4baSyz147064 * 6823d62bc4baSyz147064 * Note that the SMF team is considering to move the manifest-import service 6824d62bc4baSyz147064 * to be run at the very begining of boot. Once that is done, the need for 6825d62bc4baSyz147064 * the /var/svc/profile/upgrade_datalink script will not exist any more. 6826d62bc4baSyz147064 */ 6827d62bc4baSyz147064 static void 6828d62bc4baSyz147064 altroot_cmd(char *altroot, int argc, char *argv[]) 6829d62bc4baSyz147064 { 6830d62bc4baSyz147064 char path[MAXPATHLEN]; 6831d62bc4baSyz147064 struct stat stbuf; 6832d62bc4baSyz147064 FILE *fp; 6833d62bc4baSyz147064 int i; 6834d62bc4baSyz147064 6835d62bc4baSyz147064 /* 6836b9e076dcSyz147064 * Check for the existence of the /etc/dladm/datalink.conf 6837b9e076dcSyz147064 * configuration file, and determine the name of script file. 6838d62bc4baSyz147064 */ 6839b9e076dcSyz147064 (void) snprintf(path, MAXPATHLEN, "/%s/etc/dladm/datalink.conf", 6840b9e076dcSyz147064 altroot); 6841d62bc4baSyz147064 if (stat(path, &stbuf) < 0) { 6842d62bc4baSyz147064 (void) snprintf(path, MAXPATHLEN, "/%s/%s", altroot, 6843d62bc4baSyz147064 SMF_UPGRADE_FILE); 6844d62bc4baSyz147064 } else { 6845d62bc4baSyz147064 (void) snprintf(path, MAXPATHLEN, "/%s/%s", altroot, 6846d62bc4baSyz147064 SMF_UPGRADEDATALINK_FILE); 6847d62bc4baSyz147064 } 6848d62bc4baSyz147064 6849d62bc4baSyz147064 if ((fp = fopen(path, "a+")) == NULL) 6850d62bc4baSyz147064 die("operation not supported on %s", altroot); 6851d62bc4baSyz147064 6852d62bc4baSyz147064 (void) fprintf(fp, "/sbin/dladm "); 6853d62bc4baSyz147064 for (i = 0; i < argc; i++) { 6854d62bc4baSyz147064 /* 6855d62bc4baSyz147064 * Directly write to the file if it is not the "-R <altroot>" 6856d62bc4baSyz147064 * option. In which case, skip it. 6857d62bc4baSyz147064 */ 6858d62bc4baSyz147064 if (strcmp(argv[i], "-R") != 0) 6859d62bc4baSyz147064 (void) fprintf(fp, "%s ", argv[i]); 6860d62bc4baSyz147064 else 6861d62bc4baSyz147064 i ++; 6862d62bc4baSyz147064 } 6863d62bc4baSyz147064 (void) fprintf(fp, "%s\n", SMF_DLADM_UPGRADE_MSG); 6864d62bc4baSyz147064 (void) fclose(fp); 68654ac67f02SAnurag S. Maskey dladm_close(handle); 6866d62bc4baSyz147064 exit(0); 6867d62bc4baSyz147064 } 6868d62bc4baSyz147064 6869d62bc4baSyz147064 /* 6870d62bc4baSyz147064 * Convert the string to an integer. Note that the string must not have any 6871d62bc4baSyz147064 * trailing non-integer characters. 6872d62bc4baSyz147064 */ 687333343a97Smeem static boolean_t 687433343a97Smeem str2int(const char *str, int *valp) 687533343a97Smeem { 687633343a97Smeem int val; 687733343a97Smeem char *endp = NULL; 687833343a97Smeem 687933343a97Smeem errno = 0; 688033343a97Smeem val = strtol(str, &endp, 10); 688133343a97Smeem if (errno != 0 || *endp != '\0') 688233343a97Smeem return (B_FALSE); 688333343a97Smeem 688433343a97Smeem *valp = val; 688533343a97Smeem return (B_TRUE); 688633343a97Smeem } 688733343a97Smeem 688833343a97Smeem /* PRINTFLIKE1 */ 688933343a97Smeem static void 689033343a97Smeem warn(const char *format, ...) 689133343a97Smeem { 689233343a97Smeem va_list alist; 689333343a97Smeem 689433343a97Smeem format = gettext(format); 689533343a97Smeem (void) fprintf(stderr, "%s: warning: ", progname); 689633343a97Smeem 689733343a97Smeem va_start(alist, format); 689833343a97Smeem (void) vfprintf(stderr, format, alist); 689933343a97Smeem va_end(alist); 690033343a97Smeem 690133343a97Smeem (void) putchar('\n'); 690233343a97Smeem } 690333343a97Smeem 690433343a97Smeem /* PRINTFLIKE2 */ 690533343a97Smeem static void 690633343a97Smeem warn_dlerr(dladm_status_t err, const char *format, ...) 690733343a97Smeem { 690833343a97Smeem va_list alist; 690933343a97Smeem char errmsg[DLADM_STRSIZE]; 691033343a97Smeem 691133343a97Smeem format = gettext(format); 691233343a97Smeem (void) fprintf(stderr, gettext("%s: warning: "), progname); 691333343a97Smeem 691433343a97Smeem va_start(alist, format); 691533343a97Smeem (void) vfprintf(stderr, format, alist); 691633343a97Smeem va_end(alist); 691733343a97Smeem (void) fprintf(stderr, ": %s\n", dladm_status2str(err, errmsg)); 691833343a97Smeem } 691933343a97Smeem 69204ac67f02SAnurag S. Maskey /* 69214ac67f02SAnurag S. Maskey * Also closes the dladm handle if it is not NULL. 69224ac67f02SAnurag S. Maskey */ 692333343a97Smeem /* PRINTFLIKE2 */ 692433343a97Smeem static void 692533343a97Smeem die_dlerr(dladm_status_t err, const char *format, ...) 692633343a97Smeem { 692733343a97Smeem va_list alist; 692833343a97Smeem char errmsg[DLADM_STRSIZE]; 692933343a97Smeem 693033343a97Smeem format = gettext(format); 693133343a97Smeem (void) fprintf(stderr, "%s: ", progname); 693233343a97Smeem 693333343a97Smeem va_start(alist, format); 693433343a97Smeem (void) vfprintf(stderr, format, alist); 693533343a97Smeem va_end(alist); 693633343a97Smeem (void) fprintf(stderr, ": %s\n", dladm_status2str(err, errmsg)); 693733343a97Smeem 69384ac67f02SAnurag S. Maskey /* close dladm handle if it was opened */ 69394ac67f02SAnurag S. Maskey if (handle != NULL) 69404ac67f02SAnurag S. Maskey dladm_close(handle); 69414ac67f02SAnurag S. Maskey 694233343a97Smeem exit(EXIT_FAILURE); 694333343a97Smeem } 694433343a97Smeem 694533343a97Smeem /* PRINTFLIKE1 */ 694633343a97Smeem static void 694733343a97Smeem die(const char *format, ...) 694833343a97Smeem { 694933343a97Smeem va_list alist; 695033343a97Smeem 695133343a97Smeem format = gettext(format); 695233343a97Smeem (void) fprintf(stderr, "%s: ", progname); 695333343a97Smeem 695433343a97Smeem va_start(alist, format); 695533343a97Smeem (void) vfprintf(stderr, format, alist); 695633343a97Smeem va_end(alist); 695733343a97Smeem 695833343a97Smeem (void) putchar('\n'); 69594ac67f02SAnurag S. Maskey 69604ac67f02SAnurag S. Maskey /* close dladm handle if it was opened */ 69614ac67f02SAnurag S. Maskey if (handle != NULL) 69624ac67f02SAnurag S. Maskey dladm_close(handle); 69634ac67f02SAnurag S. Maskey 696433343a97Smeem exit(EXIT_FAILURE); 696533343a97Smeem } 696633343a97Smeem 696733343a97Smeem static void 696833343a97Smeem die_optdup(int opt) 696933343a97Smeem { 697033343a97Smeem die("the option -%c cannot be specified more than once", opt); 697133343a97Smeem } 697233343a97Smeem 697333343a97Smeem static void 69748d5c46e6Sam223141 die_opterr(int opt, int opterr, const char *usage) 697533343a97Smeem { 697633343a97Smeem switch (opterr) { 697733343a97Smeem case ':': 69788d5c46e6Sam223141 die("option '-%c' requires a value\nusage: %s", opt, 69798d5c46e6Sam223141 gettext(usage)); 698033343a97Smeem break; 698133343a97Smeem case '?': 698233343a97Smeem default: 69838d5c46e6Sam223141 die("unrecognized option '-%c'\nusage: %s", opt, 69848d5c46e6Sam223141 gettext(usage)); 698533343a97Smeem break; 69860ba2cbe9Sxc151355 } 69870ba2cbe9Sxc151355 } 6988e7801d59Ssowmini 6989e7801d59Ssowmini static void 69904784fcbdSSowmini Varadhan show_ether_xprop(void *arg, dladm_ether_info_t *eattr) 6991e7801d59Ssowmini { 6992e7801d59Ssowmini print_ether_state_t *statep = arg; 6993e7801d59Ssowmini ether_fields_buf_t ebuf; 69944784fcbdSSowmini Varadhan int i; 6995e7801d59Ssowmini 69964784fcbdSSowmini Varadhan for (i = CAPABLE; i <= PEERADV; i++) { 6997e7801d59Ssowmini bzero(&ebuf, sizeof (ebuf)); 69984784fcbdSSowmini Varadhan (void) strlcpy(ebuf.eth_ptype, ptype[i], 69994784fcbdSSowmini Varadhan sizeof (ebuf.eth_ptype)); 70004784fcbdSSowmini Varadhan (void) dladm_ether_autoneg2str(ebuf.eth_autoneg, 70014784fcbdSSowmini Varadhan sizeof (ebuf.eth_autoneg), eattr, i); 70024784fcbdSSowmini Varadhan (void) dladm_ether_spdx2str(ebuf.eth_spdx, 70034784fcbdSSowmini Varadhan sizeof (ebuf.eth_spdx), eattr, i); 70044784fcbdSSowmini Varadhan (void) dladm_ether_pause2str(ebuf.eth_pause, 70054784fcbdSSowmini Varadhan sizeof (ebuf.eth_pause), eattr, i); 70064784fcbdSSowmini Varadhan (void) strlcpy(ebuf.eth_rem_fault, 70074784fcbdSSowmini Varadhan (eattr->lei_attr[i].le_fault ? "fault" : "none"), 70084784fcbdSSowmini Varadhan sizeof (ebuf.eth_rem_fault)); 7009e7801d59Ssowmini dladm_print_output(&statep->es_print, statep->es_parseable, 7010e7801d59Ssowmini dladm_print_field, &ebuf); 7011e7801d59Ssowmini } 7012e7801d59Ssowmini 7013e7801d59Ssowmini } 7014e7801d59Ssowmini 7015e7801d59Ssowmini static void 7016e7801d59Ssowmini dladm_print_output(print_state_t *statep, boolean_t parseable, 7017e7801d59Ssowmini print_callback_t fn, void *arg) 7018e7801d59Ssowmini { 7019e7801d59Ssowmini int i; 7020e7801d59Ssowmini char *value; 7021e7801d59Ssowmini print_field_t **pf; 7022e7801d59Ssowmini 7023e7801d59Ssowmini pf = statep->ps_fields; 7024e7801d59Ssowmini for (i = 0; i < statep->ps_nfields; i++) { 7025e7801d59Ssowmini statep->ps_lastfield = (i + 1 == statep->ps_nfields); 7026e7801d59Ssowmini value = (*fn)(pf[i], arg); 7027e7801d59Ssowmini if (value != NULL) 7028e7801d59Ssowmini print_field(statep, pf[i], value, parseable); 7029e7801d59Ssowmini } 7030e7801d59Ssowmini (void) putchar('\n'); 7031e7801d59Ssowmini } 7032e7801d59Ssowmini 7033e7801d59Ssowmini static void 7034e7801d59Ssowmini print_header(print_state_t *ps) 7035e7801d59Ssowmini { 7036e7801d59Ssowmini int i; 7037e7801d59Ssowmini print_field_t **pf; 7038e7801d59Ssowmini 7039e7801d59Ssowmini pf = ps->ps_fields; 7040e7801d59Ssowmini for (i = 0; i < ps->ps_nfields; i++) { 7041e7801d59Ssowmini ps->ps_lastfield = (i + 1 == ps->ps_nfields); 7042e7801d59Ssowmini print_field(ps, pf[i], pf[i]->pf_header, B_FALSE); 7043e7801d59Ssowmini } 7044e7801d59Ssowmini (void) putchar('\n'); 7045e7801d59Ssowmini } 7046e7801d59Ssowmini 7047e7801d59Ssowmini static boolean_t 7048e7801d59Ssowmini link_is_ether(const char *link, datalink_id_t *linkid) 7049e7801d59Ssowmini { 7050e7801d59Ssowmini uint32_t media; 7051e7801d59Ssowmini datalink_class_t class; 7052e7801d59Ssowmini 70534ac67f02SAnurag S. Maskey if (dladm_name2info(handle, link, linkid, NULL, &class, &media) == 7054e7801d59Ssowmini DLADM_STATUS_OK) { 7055e7801d59Ssowmini if (class == DATALINK_CLASS_PHYS && media == DL_ETHER) 7056e7801d59Ssowmini return (B_TRUE); 7057e7801d59Ssowmini } 7058e7801d59Ssowmini return (B_FALSE); 7059e7801d59Ssowmini } 7060