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; 1413*63a6526dSMichael Lim char propstr[DLADM_STRSIZE]; 1414da14cebeSEric Cheng dladm_arg_list_t *proplist = NULL; 1415da14cebeSEric Cheng int i; 1416da14cebeSEric Cheng datalink_id_t linkid; 14177c478bd9Sstevel@tonic-gate 1418d62bc4baSyz147064 ndev = nlink = opterr = 0; 1419*63a6526dSMichael Lim bzero(propstr, DLADM_STRSIZE); 1420*63a6526dSMichael Lim 1421da14cebeSEric Cheng while ((option = getopt_long(argc, argv, ":d:l:L:P:R:tfu:T:p:", 1422d62bc4baSyz147064 lopts, NULL)) != -1) { 14237c478bd9Sstevel@tonic-gate switch (option) { 14247c478bd9Sstevel@tonic-gate case 'd': 1425d62bc4baSyz147064 if (ndev + nlink >= MAXPORT) 1426d62bc4baSyz147064 die("too many ports specified"); 14277c478bd9Sstevel@tonic-gate 1428d62bc4baSyz147064 devs[ndev++] = optarg; 14297c478bd9Sstevel@tonic-gate break; 14307c478bd9Sstevel@tonic-gate case 'P': 143133343a97Smeem if (P_arg) 143233343a97Smeem die_optdup(option); 14337c478bd9Sstevel@tonic-gate 14347c478bd9Sstevel@tonic-gate P_arg = B_TRUE; 1435f595a68aSyz147064 if (!dladm_aggr_str2policy(optarg, &policy)) 143633343a97Smeem die("invalid policy '%s'", optarg); 14377c478bd9Sstevel@tonic-gate break; 14387c478bd9Sstevel@tonic-gate case 'u': 143933343a97Smeem if (u_arg) 144033343a97Smeem die_optdup(option); 14417c478bd9Sstevel@tonic-gate 14427c478bd9Sstevel@tonic-gate u_arg = B_TRUE; 1443f595a68aSyz147064 if (!dladm_aggr_str2macaddr(optarg, &mac_addr_fixed, 144433343a97Smeem mac_addr)) 144533343a97Smeem die("invalid MAC address '%s'", optarg); 14467c478bd9Sstevel@tonic-gate break; 14477c478bd9Sstevel@tonic-gate case 'l': 1448d62bc4baSyz147064 if (isdigit(optarg[strlen(optarg) - 1])) { 1449d62bc4baSyz147064 1450d62bc4baSyz147064 /* 1451d62bc4baSyz147064 * Ended with digit, possibly a link name. 1452d62bc4baSyz147064 */ 1453d62bc4baSyz147064 if (ndev + nlink >= MAXPORT) 1454d62bc4baSyz147064 die("too many ports specified"); 1455d62bc4baSyz147064 1456d62bc4baSyz147064 links[nlink++] = optarg; 1457d62bc4baSyz147064 break; 1458d62bc4baSyz147064 } 1459d62bc4baSyz147064 /* FALLTHROUGH */ 1460d62bc4baSyz147064 case 'L': 146133343a97Smeem if (l_arg) 146233343a97Smeem die_optdup(option); 14637c478bd9Sstevel@tonic-gate 14647c478bd9Sstevel@tonic-gate l_arg = B_TRUE; 1465f595a68aSyz147064 if (!dladm_aggr_str2lacpmode(optarg, &lacp_mode)) 146633343a97Smeem die("invalid LACP mode '%s'", optarg); 14677c478bd9Sstevel@tonic-gate break; 14687c478bd9Sstevel@tonic-gate case 'T': 146933343a97Smeem if (T_arg) 147033343a97Smeem die_optdup(option); 14717c478bd9Sstevel@tonic-gate 14727c478bd9Sstevel@tonic-gate T_arg = B_TRUE; 1473f595a68aSyz147064 if (!dladm_aggr_str2lacptimer(optarg, &lacp_timer)) 147433343a97Smeem die("invalid LACP timer value '%s'", optarg); 14757c478bd9Sstevel@tonic-gate break; 14767c478bd9Sstevel@tonic-gate case 't': 1477d62bc4baSyz147064 flags &= ~DLADM_OPT_PERSIST; 1478d62bc4baSyz147064 break; 1479d62bc4baSyz147064 case 'f': 1480d62bc4baSyz147064 flags |= DLADM_OPT_FORCE; 14817c478bd9Sstevel@tonic-gate break; 14827c478bd9Sstevel@tonic-gate case 'R': 14837c478bd9Sstevel@tonic-gate altroot = optarg; 14847c478bd9Sstevel@tonic-gate break; 1485da14cebeSEric Cheng case 'p': 1486*63a6526dSMichael Lim (void) strlcat(propstr, optarg, DLADM_STRSIZE); 1487*63a6526dSMichael Lim if (strlcat(propstr, ",", DLADM_STRSIZE) >= 1488*63a6526dSMichael Lim DLADM_STRSIZE) 1489*63a6526dSMichael Lim die("property list too long '%s'", propstr); 1490da14cebeSEric Cheng break; 1491*63a6526dSMichael Lim 14927c478bd9Sstevel@tonic-gate default: 14938d5c46e6Sam223141 die_opterr(optopt, option, use); 149433343a97Smeem break; 14957c478bd9Sstevel@tonic-gate } 14967c478bd9Sstevel@tonic-gate } 14977c478bd9Sstevel@tonic-gate 1498d62bc4baSyz147064 if (ndev + nlink == 0) 14997c478bd9Sstevel@tonic-gate usage(); 15007c478bd9Sstevel@tonic-gate 1501d62bc4baSyz147064 /* get key value or the aggregation name (required last argument) */ 15027c478bd9Sstevel@tonic-gate if (optind != (argc-1)) 15037c478bd9Sstevel@tonic-gate usage(); 15047c478bd9Sstevel@tonic-gate 1505d62bc4baSyz147064 if (!str2int(argv[optind], &key)) { 1506d62bc4baSyz147064 if (strlcpy(name, argv[optind], MAXLINKNAMELEN) >= 1507d62bc4baSyz147064 MAXLINKNAMELEN) { 1508d62bc4baSyz147064 die("link name too long '%s'", argv[optind]); 1509d62bc4baSyz147064 } 15107c478bd9Sstevel@tonic-gate 1511d62bc4baSyz147064 if (!dladm_valid_linkname(name)) 1512d62bc4baSyz147064 die("invalid link name '%s'", argv[optind]); 1513d62bc4baSyz147064 } else { 1514d62bc4baSyz147064 (void) snprintf(name, MAXLINKNAMELEN, "aggr%d", key); 1515d62bc4baSyz147064 } 1516d62bc4baSyz147064 1517d62bc4baSyz147064 if (altroot != NULL) 1518d62bc4baSyz147064 altroot_cmd(altroot, argc, argv); 1519d62bc4baSyz147064 1520d62bc4baSyz147064 for (n = 0; n < ndev; n++) { 15214ac67f02SAnurag S. Maskey if ((status = dladm_dev2linkid(handle, devs[n], 15224ac67f02SAnurag S. Maskey &port[n].lp_linkid)) != DLADM_STATUS_OK) { 15234ac67f02SAnurag S. Maskey die_dlerr(status, "invalid dev name '%s'", devs[n]); 1524d62bc4baSyz147064 } 1525d62bc4baSyz147064 } 1526d62bc4baSyz147064 1527d62bc4baSyz147064 for (n = 0; n < nlink; n++) { 15284ac67f02SAnurag S. Maskey if ((status = dladm_name2info(handle, links[n], 15294ac67f02SAnurag S. Maskey &port[ndev + n].lp_linkid, NULL, NULL, NULL)) != 15304ac67f02SAnurag S. Maskey DLADM_STATUS_OK) { 15314ac67f02SAnurag S. Maskey die_dlerr(status, "invalid link name '%s'", links[n]); 1532d62bc4baSyz147064 } 1533d62bc4baSyz147064 } 1534d62bc4baSyz147064 15354ac67f02SAnurag S. Maskey status = dladm_aggr_create(handle, name, key, ndev + nlink, port, 15364ac67f02SAnurag S. Maskey policy, mac_addr_fixed, (const uchar_t *)mac_addr, lacp_mode, 1537d62bc4baSyz147064 lacp_timer, flags); 1538da14cebeSEric Cheng if (status != DLADM_STATUS_OK) 1539da14cebeSEric Cheng goto done; 1540da14cebeSEric Cheng 1541*63a6526dSMichael Lim if (dladm_parse_link_props(propstr, &proplist, B_FALSE) 1542*63a6526dSMichael Lim != DLADM_STATUS_OK) 1543*63a6526dSMichael Lim die("invalid aggregation property"); 1544*63a6526dSMichael Lim 1545da14cebeSEric Cheng if (proplist == NULL) 1546da14cebeSEric Cheng return; 1547da14cebeSEric Cheng 15484ac67f02SAnurag S. Maskey status = dladm_name2info(handle, name, &linkid, NULL, NULL, NULL); 1549da14cebeSEric Cheng if (status != DLADM_STATUS_OK) 1550da14cebeSEric Cheng goto done; 1551da14cebeSEric Cheng 1552da14cebeSEric Cheng for (i = 0; i < proplist->al_count; i++) { 1553da14cebeSEric Cheng dladm_arg_info_t *aip = &proplist->al_info[i]; 1554da14cebeSEric Cheng 15554ac67f02SAnurag S. Maskey pstatus = dladm_set_linkprop(handle, linkid, aip->ai_name, 1556da14cebeSEric Cheng aip->ai_val, aip->ai_count, flags); 1557da14cebeSEric Cheng 1558da14cebeSEric Cheng if (pstatus != DLADM_STATUS_OK) { 1559da14cebeSEric Cheng die_dlerr(pstatus, 1560da14cebeSEric Cheng "aggr creation succeeded but " 1561da14cebeSEric Cheng "could not set property '%s'", aip->ai_name); 1562da14cebeSEric Cheng } 1563da14cebeSEric Cheng } 1564d62bc4baSyz147064 done: 1565da14cebeSEric Cheng dladm_free_props(proplist); 1566d62bc4baSyz147064 if (status != DLADM_STATUS_OK) { 1567d62bc4baSyz147064 if (status == DLADM_STATUS_NONOTIF) { 1568d62bc4baSyz147064 die_dlerr(status, "not all links have link up/down " 1569d62bc4baSyz147064 "detection; must use -f (see dladm(1M))\n"); 1570d62bc4baSyz147064 } else { 1571f595a68aSyz147064 die_dlerr(status, "create operation failed"); 15727c478bd9Sstevel@tonic-gate } 1573d62bc4baSyz147064 } 1574d62bc4baSyz147064 } 1575d62bc4baSyz147064 1576d62bc4baSyz147064 /* 1577d62bc4baSyz147064 * arg is either the key or the aggr name. Validate it and convert it to 1578d62bc4baSyz147064 * the linkid if altroot is NULL. 1579d62bc4baSyz147064 */ 1580d62bc4baSyz147064 static dladm_status_t 1581d62bc4baSyz147064 i_dladm_aggr_get_linkid(const char *altroot, const char *arg, 1582d62bc4baSyz147064 datalink_id_t *linkidp, uint32_t flags) 1583d62bc4baSyz147064 { 1584d62bc4baSyz147064 int key = 0; 1585d62bc4baSyz147064 char *aggr = NULL; 1586d62bc4baSyz147064 dladm_status_t status; 1587d62bc4baSyz147064 1588d62bc4baSyz147064 if (!str2int(arg, &key)) 1589d62bc4baSyz147064 aggr = (char *)arg; 1590d62bc4baSyz147064 1591d62bc4baSyz147064 if (aggr == NULL && key == 0) 1592d62bc4baSyz147064 return (DLADM_STATUS_LINKINVAL); 1593d62bc4baSyz147064 1594d62bc4baSyz147064 if (altroot != NULL) 1595d62bc4baSyz147064 return (DLADM_STATUS_OK); 1596d62bc4baSyz147064 1597d62bc4baSyz147064 if (aggr != NULL) { 15984ac67f02SAnurag S. Maskey status = dladm_name2info(handle, aggr, linkidp, NULL, NULL, 15994ac67f02SAnurag S. Maskey NULL); 1600d62bc4baSyz147064 } else { 16014ac67f02SAnurag S. Maskey status = dladm_key2linkid(handle, key, linkidp, flags); 1602d62bc4baSyz147064 } 1603d62bc4baSyz147064 1604d62bc4baSyz147064 return (status); 1605d62bc4baSyz147064 } 16067c478bd9Sstevel@tonic-gate 16077c478bd9Sstevel@tonic-gate static void 16088d5c46e6Sam223141 do_delete_aggr(int argc, char *argv[], const char *use) 16097c478bd9Sstevel@tonic-gate { 16107c478bd9Sstevel@tonic-gate char option; 16117c478bd9Sstevel@tonic-gate char *altroot = NULL; 1612d62bc4baSyz147064 uint32_t flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST; 1613f595a68aSyz147064 dladm_status_t status; 1614d62bc4baSyz147064 datalink_id_t linkid; 16157c478bd9Sstevel@tonic-gate 16167c478bd9Sstevel@tonic-gate opterr = 0; 1617d62bc4baSyz147064 while ((option = getopt_long(argc, argv, ":R:t", lopts, NULL)) != -1) { 16187c478bd9Sstevel@tonic-gate switch (option) { 16197c478bd9Sstevel@tonic-gate case 't': 1620d62bc4baSyz147064 flags &= ~DLADM_OPT_PERSIST; 16217c478bd9Sstevel@tonic-gate break; 16227c478bd9Sstevel@tonic-gate case 'R': 16237c478bd9Sstevel@tonic-gate altroot = optarg; 16247c478bd9Sstevel@tonic-gate break; 16257c478bd9Sstevel@tonic-gate default: 16268d5c46e6Sam223141 die_opterr(optopt, option, use); 16277c478bd9Sstevel@tonic-gate break; 16287c478bd9Sstevel@tonic-gate } 16297c478bd9Sstevel@tonic-gate } 16307c478bd9Sstevel@tonic-gate 1631d62bc4baSyz147064 /* get key value or the aggregation name (required last argument) */ 16327c478bd9Sstevel@tonic-gate if (optind != (argc-1)) 16337c478bd9Sstevel@tonic-gate usage(); 16347c478bd9Sstevel@tonic-gate 1635d62bc4baSyz147064 status = i_dladm_aggr_get_linkid(altroot, argv[optind], &linkid, flags); 1636d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 1637d62bc4baSyz147064 goto done; 16387c478bd9Sstevel@tonic-gate 1639d62bc4baSyz147064 if (altroot != NULL) 1640d62bc4baSyz147064 altroot_cmd(altroot, argc, argv); 1641d62bc4baSyz147064 16424ac67f02SAnurag S. Maskey status = dladm_aggr_delete(handle, linkid, flags); 1643d62bc4baSyz147064 done: 1644f595a68aSyz147064 if (status != DLADM_STATUS_OK) 1645f595a68aSyz147064 die_dlerr(status, "delete operation failed"); 16467c478bd9Sstevel@tonic-gate } 16477c478bd9Sstevel@tonic-gate 16487c478bd9Sstevel@tonic-gate static void 16498d5c46e6Sam223141 do_add_aggr(int argc, char *argv[], const char *use) 16507c478bd9Sstevel@tonic-gate { 16517c478bd9Sstevel@tonic-gate char option; 1652d62bc4baSyz147064 uint_t n, ndev, nlink; 16537c478bd9Sstevel@tonic-gate char *altroot = NULL; 1654d62bc4baSyz147064 uint32_t flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST; 1655d62bc4baSyz147064 datalink_id_t linkid; 1656f595a68aSyz147064 dladm_status_t status; 1657d62bc4baSyz147064 dladm_aggr_port_attr_db_t port[MAXPORT]; 1658d62bc4baSyz147064 char *devs[MAXPORT]; 1659d62bc4baSyz147064 char *links[MAXPORT]; 16607c478bd9Sstevel@tonic-gate 1661d62bc4baSyz147064 ndev = nlink = opterr = 0; 1662d62bc4baSyz147064 while ((option = getopt_long(argc, argv, ":d:l:R:tf", lopts, 16637c478bd9Sstevel@tonic-gate NULL)) != -1) { 16647c478bd9Sstevel@tonic-gate switch (option) { 16657c478bd9Sstevel@tonic-gate case 'd': 1666d62bc4baSyz147064 if (ndev + nlink >= MAXPORT) 1667d62bc4baSyz147064 die("too many ports specified"); 16687c478bd9Sstevel@tonic-gate 1669d62bc4baSyz147064 devs[ndev++] = optarg; 1670d62bc4baSyz147064 break; 1671d62bc4baSyz147064 case 'l': 1672d62bc4baSyz147064 if (ndev + nlink >= MAXPORT) 1673d62bc4baSyz147064 die("too many ports specified"); 167433343a97Smeem 1675d62bc4baSyz147064 links[nlink++] = optarg; 16767c478bd9Sstevel@tonic-gate break; 16777c478bd9Sstevel@tonic-gate case 't': 1678d62bc4baSyz147064 flags &= ~DLADM_OPT_PERSIST; 1679d62bc4baSyz147064 break; 1680d62bc4baSyz147064 case 'f': 1681d62bc4baSyz147064 flags |= DLADM_OPT_FORCE; 16827c478bd9Sstevel@tonic-gate break; 16837c478bd9Sstevel@tonic-gate case 'R': 16847c478bd9Sstevel@tonic-gate altroot = optarg; 16857c478bd9Sstevel@tonic-gate break; 16867c478bd9Sstevel@tonic-gate default: 16878d5c46e6Sam223141 die_opterr(optopt, option, use); 168833343a97Smeem break; 16897c478bd9Sstevel@tonic-gate } 16907c478bd9Sstevel@tonic-gate } 16917c478bd9Sstevel@tonic-gate 1692d62bc4baSyz147064 if (ndev + nlink == 0) 16937c478bd9Sstevel@tonic-gate usage(); 16947c478bd9Sstevel@tonic-gate 1695d62bc4baSyz147064 /* get key value or the aggregation name (required last argument) */ 16967c478bd9Sstevel@tonic-gate if (optind != (argc-1)) 16977c478bd9Sstevel@tonic-gate usage(); 16987c478bd9Sstevel@tonic-gate 1699d62bc4baSyz147064 if ((status = i_dladm_aggr_get_linkid(altroot, argv[optind], &linkid, 1700d62bc4baSyz147064 flags & (DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST))) != 1701d62bc4baSyz147064 DLADM_STATUS_OK) { 1702d62bc4baSyz147064 goto done; 1703d62bc4baSyz147064 } 17047c478bd9Sstevel@tonic-gate 1705d62bc4baSyz147064 if (altroot != NULL) 1706d62bc4baSyz147064 altroot_cmd(altroot, argc, argv); 1707d62bc4baSyz147064 1708d62bc4baSyz147064 for (n = 0; n < ndev; n++) { 17094ac67f02SAnurag S. Maskey if ((status = dladm_dev2linkid(handle, devs[n], 17104ac67f02SAnurag S. Maskey &(port[n].lp_linkid))) != DLADM_STATUS_OK) { 17114ac67f02SAnurag S. Maskey die_dlerr(status, "invalid <dev> '%s'", devs[n]); 1712d62bc4baSyz147064 } 1713d62bc4baSyz147064 } 1714d62bc4baSyz147064 1715d62bc4baSyz147064 for (n = 0; n < nlink; n++) { 17164ac67f02SAnurag S. Maskey if ((status = dladm_name2info(handle, links[n], 17174ac67f02SAnurag S. Maskey &port[n + ndev].lp_linkid, NULL, NULL, NULL)) != 17184ac67f02SAnurag S. Maskey DLADM_STATUS_OK) { 17194ac67f02SAnurag S. Maskey die_dlerr(status, "invalid <link> '%s'", links[n]); 1720d62bc4baSyz147064 } 1721d62bc4baSyz147064 } 1722d62bc4baSyz147064 17234ac67f02SAnurag S. Maskey status = dladm_aggr_add(handle, linkid, ndev + nlink, port, flags); 1724d62bc4baSyz147064 done: 1725f595a68aSyz147064 if (status != DLADM_STATUS_OK) { 1726219a2a31Shl157128 /* 1727f595a68aSyz147064 * checking DLADM_STATUS_NOTSUP is a temporary workaround 1728219a2a31Shl157128 * and should be removed once 6399681 is fixed. 1729219a2a31Shl157128 */ 1730f595a68aSyz147064 if (status == DLADM_STATUS_NOTSUP) { 1731219a2a31Shl157128 (void) fprintf(stderr, 1732219a2a31Shl157128 gettext("%s: add operation failed: %s\n"), 1733219a2a31Shl157128 progname, 1734d62bc4baSyz147064 gettext("link capabilities don't match")); 17354ac67f02SAnurag S. Maskey dladm_close(handle); 1736219a2a31Shl157128 exit(ENOTSUP); 1737d62bc4baSyz147064 } else if (status == DLADM_STATUS_NONOTIF) { 1738d62bc4baSyz147064 die_dlerr(status, "not all links have link up/down " 1739d62bc4baSyz147064 "detection; must use -f (see dladm(1M))\n"); 1740d62bc4baSyz147064 } else { 1741f595a68aSyz147064 die_dlerr(status, "add operation failed"); 17427c478bd9Sstevel@tonic-gate } 17437c478bd9Sstevel@tonic-gate } 1744d62bc4baSyz147064 } 17457c478bd9Sstevel@tonic-gate 17467c478bd9Sstevel@tonic-gate static void 17478d5c46e6Sam223141 do_remove_aggr(int argc, char *argv[], const char *use) 17487c478bd9Sstevel@tonic-gate { 17497c478bd9Sstevel@tonic-gate char option; 1750f595a68aSyz147064 dladm_aggr_port_attr_db_t port[MAXPORT]; 1751d62bc4baSyz147064 uint_t n, ndev, nlink; 1752d62bc4baSyz147064 char *devs[MAXPORT]; 1753d62bc4baSyz147064 char *links[MAXPORT]; 17547c478bd9Sstevel@tonic-gate char *altroot = NULL; 1755d62bc4baSyz147064 uint32_t flags; 1756d62bc4baSyz147064 datalink_id_t linkid; 1757f595a68aSyz147064 dladm_status_t status; 17587c478bd9Sstevel@tonic-gate 1759d62bc4baSyz147064 flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST; 1760d62bc4baSyz147064 ndev = nlink = opterr = 0; 1761d62bc4baSyz147064 while ((option = getopt_long(argc, argv, ":d:l:R:t", 1762d62bc4baSyz147064 lopts, NULL)) != -1) { 17637c478bd9Sstevel@tonic-gate switch (option) { 17647c478bd9Sstevel@tonic-gate case 'd': 1765d62bc4baSyz147064 if (ndev + nlink >= MAXPORT) 1766d62bc4baSyz147064 die("too many ports specified"); 17677c478bd9Sstevel@tonic-gate 1768d62bc4baSyz147064 devs[ndev++] = optarg; 1769d62bc4baSyz147064 break; 1770d62bc4baSyz147064 case 'l': 1771d62bc4baSyz147064 if (ndev + nlink >= MAXPORT) 1772d62bc4baSyz147064 die("too many ports specified"); 177333343a97Smeem 1774d62bc4baSyz147064 links[nlink++] = optarg; 17757c478bd9Sstevel@tonic-gate break; 17767c478bd9Sstevel@tonic-gate case 't': 1777d62bc4baSyz147064 flags &= ~DLADM_OPT_PERSIST; 17787c478bd9Sstevel@tonic-gate break; 17797c478bd9Sstevel@tonic-gate case 'R': 17807c478bd9Sstevel@tonic-gate altroot = optarg; 17817c478bd9Sstevel@tonic-gate break; 17827c478bd9Sstevel@tonic-gate default: 17838d5c46e6Sam223141 die_opterr(optopt, option, use); 178433343a97Smeem break; 17857c478bd9Sstevel@tonic-gate } 17867c478bd9Sstevel@tonic-gate } 17877c478bd9Sstevel@tonic-gate 1788d62bc4baSyz147064 if (ndev + nlink == 0) 17897c478bd9Sstevel@tonic-gate usage(); 17907c478bd9Sstevel@tonic-gate 1791d62bc4baSyz147064 /* get key value or the aggregation name (required last argument) */ 17927c478bd9Sstevel@tonic-gate if (optind != (argc-1)) 17937c478bd9Sstevel@tonic-gate usage(); 17947c478bd9Sstevel@tonic-gate 1795d62bc4baSyz147064 status = i_dladm_aggr_get_linkid(altroot, argv[optind], &linkid, flags); 1796d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 1797d62bc4baSyz147064 goto done; 17987c478bd9Sstevel@tonic-gate 1799d62bc4baSyz147064 if (altroot != NULL) 1800d62bc4baSyz147064 altroot_cmd(altroot, argc, argv); 1801d62bc4baSyz147064 1802d62bc4baSyz147064 for (n = 0; n < ndev; n++) { 18034ac67f02SAnurag S. Maskey if ((status = dladm_dev2linkid(handle, devs[n], 18044ac67f02SAnurag S. Maskey &(port[n].lp_linkid))) != DLADM_STATUS_OK) { 18054ac67f02SAnurag S. Maskey die_dlerr(status, "invalid <dev> '%s'", devs[n]); 1806d62bc4baSyz147064 } 1807d62bc4baSyz147064 } 1808d62bc4baSyz147064 1809d62bc4baSyz147064 for (n = 0; n < nlink; n++) { 18104ac67f02SAnurag S. Maskey if ((status = dladm_name2info(handle, links[n], 18114ac67f02SAnurag S. Maskey &port[n + ndev].lp_linkid, NULL, NULL, NULL)) != 18124ac67f02SAnurag S. Maskey DLADM_STATUS_OK) { 18134ac67f02SAnurag S. Maskey die_dlerr(status, "invalid <link> '%s'", links[n]); 1814d62bc4baSyz147064 } 1815d62bc4baSyz147064 } 1816d62bc4baSyz147064 18174ac67f02SAnurag S. Maskey status = dladm_aggr_remove(handle, linkid, ndev + nlink, port, flags); 1818d62bc4baSyz147064 done: 1819f595a68aSyz147064 if (status != DLADM_STATUS_OK) 1820f595a68aSyz147064 die_dlerr(status, "remove operation failed"); 18217c478bd9Sstevel@tonic-gate } 18227c478bd9Sstevel@tonic-gate 18237c478bd9Sstevel@tonic-gate static void 18248d5c46e6Sam223141 do_modify_aggr(int argc, char *argv[], const char *use) 18257c478bd9Sstevel@tonic-gate { 18267c478bd9Sstevel@tonic-gate char option; 18277c478bd9Sstevel@tonic-gate uint32_t policy = AGGR_POLICY_L4; 18287c478bd9Sstevel@tonic-gate aggr_lacp_mode_t lacp_mode = AGGR_LACP_OFF; 18297c478bd9Sstevel@tonic-gate aggr_lacp_timer_t lacp_timer = AGGR_LACP_TIMER_SHORT; 18307c478bd9Sstevel@tonic-gate uint8_t mac_addr[ETHERADDRL]; 18317c478bd9Sstevel@tonic-gate boolean_t mac_addr_fixed = B_FALSE; 18327c478bd9Sstevel@tonic-gate uint8_t modify_mask = 0; 18337c478bd9Sstevel@tonic-gate char *altroot = NULL; 1834d62bc4baSyz147064 uint32_t flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST; 1835d62bc4baSyz147064 datalink_id_t linkid; 1836f595a68aSyz147064 dladm_status_t status; 18377c478bd9Sstevel@tonic-gate 18387c478bd9Sstevel@tonic-gate opterr = 0; 1839d62bc4baSyz147064 while ((option = getopt_long(argc, argv, ":L:l:P:R:tu:T:", lopts, 18407c478bd9Sstevel@tonic-gate NULL)) != -1) { 18417c478bd9Sstevel@tonic-gate switch (option) { 18427c478bd9Sstevel@tonic-gate case 'P': 1843f595a68aSyz147064 if (modify_mask & DLADM_AGGR_MODIFY_POLICY) 184433343a97Smeem die_optdup(option); 18457c478bd9Sstevel@tonic-gate 1846f595a68aSyz147064 modify_mask |= DLADM_AGGR_MODIFY_POLICY; 18477c478bd9Sstevel@tonic-gate 1848f595a68aSyz147064 if (!dladm_aggr_str2policy(optarg, &policy)) 184933343a97Smeem die("invalid policy '%s'", optarg); 18507c478bd9Sstevel@tonic-gate break; 18517c478bd9Sstevel@tonic-gate case 'u': 1852f595a68aSyz147064 if (modify_mask & DLADM_AGGR_MODIFY_MAC) 185333343a97Smeem die_optdup(option); 18547c478bd9Sstevel@tonic-gate 1855f595a68aSyz147064 modify_mask |= DLADM_AGGR_MODIFY_MAC; 18567c478bd9Sstevel@tonic-gate 1857f595a68aSyz147064 if (!dladm_aggr_str2macaddr(optarg, &mac_addr_fixed, 185833343a97Smeem mac_addr)) 185933343a97Smeem die("invalid MAC address '%s'", optarg); 18607c478bd9Sstevel@tonic-gate break; 18617c478bd9Sstevel@tonic-gate case 'l': 1862d62bc4baSyz147064 case 'L': 1863f595a68aSyz147064 if (modify_mask & DLADM_AGGR_MODIFY_LACP_MODE) 186433343a97Smeem die_optdup(option); 18657c478bd9Sstevel@tonic-gate 1866f595a68aSyz147064 modify_mask |= DLADM_AGGR_MODIFY_LACP_MODE; 18677c478bd9Sstevel@tonic-gate 1868f595a68aSyz147064 if (!dladm_aggr_str2lacpmode(optarg, &lacp_mode)) 186933343a97Smeem die("invalid LACP mode '%s'", optarg); 18707c478bd9Sstevel@tonic-gate break; 18717c478bd9Sstevel@tonic-gate case 'T': 1872f595a68aSyz147064 if (modify_mask & DLADM_AGGR_MODIFY_LACP_TIMER) 187333343a97Smeem die_optdup(option); 18747c478bd9Sstevel@tonic-gate 1875f595a68aSyz147064 modify_mask |= DLADM_AGGR_MODIFY_LACP_TIMER; 18767c478bd9Sstevel@tonic-gate 1877f595a68aSyz147064 if (!dladm_aggr_str2lacptimer(optarg, &lacp_timer)) 187833343a97Smeem die("invalid LACP timer value '%s'", optarg); 18797c478bd9Sstevel@tonic-gate break; 18807c478bd9Sstevel@tonic-gate case 't': 1881d62bc4baSyz147064 flags &= ~DLADM_OPT_PERSIST; 18827c478bd9Sstevel@tonic-gate break; 18837c478bd9Sstevel@tonic-gate case 'R': 18847c478bd9Sstevel@tonic-gate altroot = optarg; 18857c478bd9Sstevel@tonic-gate break; 18867c478bd9Sstevel@tonic-gate default: 18878d5c46e6Sam223141 die_opterr(optopt, option, use); 188833343a97Smeem break; 18897c478bd9Sstevel@tonic-gate } 18907c478bd9Sstevel@tonic-gate } 18917c478bd9Sstevel@tonic-gate 189233343a97Smeem if (modify_mask == 0) 189333343a97Smeem die("at least one of the -PulT options must be specified"); 18947c478bd9Sstevel@tonic-gate 1895d62bc4baSyz147064 /* get key value or the aggregation name (required last argument) */ 18967c478bd9Sstevel@tonic-gate if (optind != (argc-1)) 18977c478bd9Sstevel@tonic-gate usage(); 18987c478bd9Sstevel@tonic-gate 1899d62bc4baSyz147064 status = i_dladm_aggr_get_linkid(altroot, argv[optind], &linkid, flags); 1900d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 1901d62bc4baSyz147064 goto done; 19027c478bd9Sstevel@tonic-gate 1903d62bc4baSyz147064 if (altroot != NULL) 1904d62bc4baSyz147064 altroot_cmd(altroot, argc, argv); 1905d62bc4baSyz147064 19064ac67f02SAnurag S. Maskey status = dladm_aggr_modify(handle, linkid, modify_mask, policy, 19074ac67f02SAnurag S. Maskey mac_addr_fixed, (const uchar_t *)mac_addr, lacp_mode, lacp_timer, 19084ac67f02SAnurag S. Maskey flags); 1909d62bc4baSyz147064 1910d62bc4baSyz147064 done: 1911f595a68aSyz147064 if (status != DLADM_STATUS_OK) 1912f595a68aSyz147064 die_dlerr(status, "modify operation failed"); 19137c478bd9Sstevel@tonic-gate } 19147c478bd9Sstevel@tonic-gate 19158d5c46e6Sam223141 /*ARGSUSED*/ 19167c478bd9Sstevel@tonic-gate static void 19178d5c46e6Sam223141 do_up_aggr(int argc, char *argv[], const char *use) 19187c478bd9Sstevel@tonic-gate { 1919d62bc4baSyz147064 datalink_id_t linkid = DATALINK_ALL_LINKID; 1920f595a68aSyz147064 dladm_status_t status; 19217c478bd9Sstevel@tonic-gate 1922d62bc4baSyz147064 /* 1923d62bc4baSyz147064 * get the key or the name of the aggregation (optional last argument) 1924d62bc4baSyz147064 */ 19257c478bd9Sstevel@tonic-gate if (argc == 2) { 1926d62bc4baSyz147064 if ((status = i_dladm_aggr_get_linkid(NULL, argv[1], &linkid, 19274ac67f02SAnurag S. Maskey DLADM_OPT_PERSIST)) != DLADM_STATUS_OK) 1928d62bc4baSyz147064 goto done; 19297c478bd9Sstevel@tonic-gate } else if (argc > 2) { 19307c478bd9Sstevel@tonic-gate usage(); 19317c478bd9Sstevel@tonic-gate } 19327c478bd9Sstevel@tonic-gate 19334ac67f02SAnurag S. Maskey status = dladm_aggr_up(handle, linkid); 1934d62bc4baSyz147064 done: 1935d62bc4baSyz147064 if (status != DLADM_STATUS_OK) { 1936d62bc4baSyz147064 if (argc == 2) { 1937d62bc4baSyz147064 die_dlerr(status, 1938d62bc4baSyz147064 "could not bring up aggregation '%s'", argv[1]); 19397c478bd9Sstevel@tonic-gate } else { 1940f595a68aSyz147064 die_dlerr(status, "could not bring aggregations up"); 19417c478bd9Sstevel@tonic-gate } 19427c478bd9Sstevel@tonic-gate } 19437c478bd9Sstevel@tonic-gate } 19447c478bd9Sstevel@tonic-gate 19457c478bd9Sstevel@tonic-gate static void 19468d5c46e6Sam223141 do_create_vlan(int argc, char *argv[], const char *use) 19477c478bd9Sstevel@tonic-gate { 1948d62bc4baSyz147064 char *link = NULL; 1949d62bc4baSyz147064 char drv[DLPI_LINKNAME_MAX]; 1950d62bc4baSyz147064 uint_t ppa; 1951d62bc4baSyz147064 datalink_id_t linkid; 1952da14cebeSEric Cheng datalink_id_t dev_linkid; 1953d62bc4baSyz147064 int vid = 0; 1954d62bc4baSyz147064 char option; 1955d62bc4baSyz147064 uint32_t flags = (DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST); 1956d62bc4baSyz147064 char *altroot = NULL; 1957d62bc4baSyz147064 char vlan[MAXLINKNAMELEN]; 1958*63a6526dSMichael Lim char propstr[DLADM_STRSIZE]; 1959da14cebeSEric Cheng dladm_arg_list_t *proplist = NULL; 1960f595a68aSyz147064 dladm_status_t status; 19617c478bd9Sstevel@tonic-gate 1962d62bc4baSyz147064 opterr = 0; 1963*63a6526dSMichael Lim bzero(propstr, DLADM_STRSIZE); 1964*63a6526dSMichael Lim 1965da14cebeSEric Cheng while ((option = getopt_long(argc, argv, ":tfR:l:v:p:", 1966d62bc4baSyz147064 lopts, NULL)) != -1) { 1967d62bc4baSyz147064 switch (option) { 1968d62bc4baSyz147064 case 'v': 1969d62bc4baSyz147064 if (vid != 0) 1970d62bc4baSyz147064 die_optdup(option); 1971d62bc4baSyz147064 1972d62bc4baSyz147064 if (!str2int(optarg, &vid) || vid < 1 || vid > 4094) 1973d62bc4baSyz147064 die("invalid VLAN identifier '%s'", optarg); 1974d62bc4baSyz147064 1975d62bc4baSyz147064 break; 1976d62bc4baSyz147064 case 'l': 1977d62bc4baSyz147064 if (link != NULL) 1978d62bc4baSyz147064 die_optdup(option); 1979d62bc4baSyz147064 1980d62bc4baSyz147064 link = optarg; 1981d62bc4baSyz147064 break; 1982d62bc4baSyz147064 case 't': 1983d62bc4baSyz147064 flags &= ~DLADM_OPT_PERSIST; 1984d62bc4baSyz147064 break; 1985d62bc4baSyz147064 case 'R': 1986d62bc4baSyz147064 altroot = optarg; 1987d62bc4baSyz147064 break; 1988da14cebeSEric Cheng case 'p': 1989*63a6526dSMichael Lim (void) strlcat(propstr, optarg, DLADM_STRSIZE); 1990*63a6526dSMichael Lim if (strlcat(propstr, ",", DLADM_STRSIZE) >= 1991*63a6526dSMichael Lim DLADM_STRSIZE) 1992*63a6526dSMichael Lim die("property list too long '%s'", propstr); 1993da14cebeSEric Cheng break; 1994da14cebeSEric Cheng case 'f': 1995da14cebeSEric Cheng flags |= DLADM_OPT_FORCE; 1996da14cebeSEric Cheng break; 1997d62bc4baSyz147064 default: 19988d5c46e6Sam223141 die_opterr(optopt, option, use); 1999d62bc4baSyz147064 break; 2000d62bc4baSyz147064 } 2001d62bc4baSyz147064 } 2002d62bc4baSyz147064 2003d62bc4baSyz147064 /* get vlan name if there is any */ 2004d62bc4baSyz147064 if ((vid == 0) || (link == NULL) || (argc - optind > 1)) 20057c478bd9Sstevel@tonic-gate usage(); 2006d62bc4baSyz147064 2007d62bc4baSyz147064 if (optind == (argc - 1)) { 2008d62bc4baSyz147064 if (strlcpy(vlan, argv[optind], MAXLINKNAMELEN) >= 2009d62bc4baSyz147064 MAXLINKNAMELEN) { 2010d62bc4baSyz147064 die("vlan name too long '%s'", argv[optind]); 2011d62bc4baSyz147064 } 2012d62bc4baSyz147064 } else { 2013d62bc4baSyz147064 if ((dlpi_parselink(link, drv, &ppa) != DLPI_SUCCESS) || 2014d62bc4baSyz147064 (ppa >= 1000) || 2015d62bc4baSyz147064 (dlpi_makelink(vlan, drv, vid * 1000 + ppa) != 2016d62bc4baSyz147064 DLPI_SUCCESS)) { 2017d62bc4baSyz147064 die("invalid link name '%s'", link); 2018d62bc4baSyz147064 } 20197c478bd9Sstevel@tonic-gate } 20207c478bd9Sstevel@tonic-gate 2021d62bc4baSyz147064 if (altroot != NULL) 2022d62bc4baSyz147064 altroot_cmd(altroot, argc, argv); 2023d62bc4baSyz147064 20244ac67f02SAnurag S. Maskey if (dladm_name2info(handle, link, &dev_linkid, NULL, NULL, NULL) != 2025d62bc4baSyz147064 DLADM_STATUS_OK) { 2026d62bc4baSyz147064 die("invalid link name '%s'", link); 2027d62bc4baSyz147064 } 2028d62bc4baSyz147064 2029*63a6526dSMichael Lim if (dladm_parse_link_props(propstr, &proplist, B_FALSE) 2030*63a6526dSMichael Lim != DLADM_STATUS_OK) 2031*63a6526dSMichael Lim die("invalid vlan property"); 2032*63a6526dSMichael Lim 20334ac67f02SAnurag S. Maskey if ((status = dladm_vlan_create(handle, vlan, dev_linkid, vid, proplist, 20344ac67f02SAnurag S. Maskey flags, &linkid)) != DLADM_STATUS_OK) { 2035da14cebeSEric Cheng die_dlerr(status, "create operation over %s failed", link); 2036d62bc4baSyz147064 } 2037d62bc4baSyz147064 } 2038d62bc4baSyz147064 2039d62bc4baSyz147064 static void 20408d5c46e6Sam223141 do_delete_vlan(int argc, char *argv[], const char *use) 2041d62bc4baSyz147064 { 2042d62bc4baSyz147064 char option; 2043d62bc4baSyz147064 uint32_t flags = (DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST); 2044d62bc4baSyz147064 char *altroot = NULL; 2045d62bc4baSyz147064 datalink_id_t linkid; 2046d62bc4baSyz147064 dladm_status_t status; 2047d62bc4baSyz147064 2048d62bc4baSyz147064 opterr = 0; 2049d62bc4baSyz147064 while ((option = getopt_long(argc, argv, ":R:t", lopts, NULL)) != -1) { 2050d62bc4baSyz147064 switch (option) { 2051d62bc4baSyz147064 case 't': 2052d62bc4baSyz147064 flags &= ~DLADM_OPT_PERSIST; 2053d62bc4baSyz147064 break; 2054d62bc4baSyz147064 case 'R': 2055d62bc4baSyz147064 altroot = optarg; 2056d62bc4baSyz147064 break; 2057d62bc4baSyz147064 default: 20588d5c46e6Sam223141 die_opterr(optopt, option, use); 2059d62bc4baSyz147064 break; 2060d62bc4baSyz147064 } 2061d62bc4baSyz147064 } 2062d62bc4baSyz147064 2063d62bc4baSyz147064 /* get VLAN link name (required last argument) */ 2064d62bc4baSyz147064 if (optind != (argc - 1)) 2065d62bc4baSyz147064 usage(); 2066d62bc4baSyz147064 2067d62bc4baSyz147064 if (altroot != NULL) 2068d62bc4baSyz147064 altroot_cmd(altroot, argc, argv); 2069d62bc4baSyz147064 20704ac67f02SAnurag S. Maskey status = dladm_name2info(handle, argv[optind], &linkid, NULL, NULL, 20714ac67f02SAnurag S. Maskey NULL); 2072d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 2073d62bc4baSyz147064 goto done; 2074d62bc4baSyz147064 20754ac67f02SAnurag S. Maskey status = dladm_vlan_delete(handle, linkid, flags); 2076d62bc4baSyz147064 done: 2077d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 2078d62bc4baSyz147064 die_dlerr(status, "delete operation failed"); 2079d62bc4baSyz147064 } 2080d62bc4baSyz147064 20818d5c46e6Sam223141 /*ARGSUSED*/ 2082d62bc4baSyz147064 static void 20838d5c46e6Sam223141 do_up_vlan(int argc, char *argv[], const char *use) 2084d62bc4baSyz147064 { 2085da14cebeSEric Cheng do_up_vnic_common(argc, argv, use, B_TRUE); 20867c478bd9Sstevel@tonic-gate } 20877c478bd9Sstevel@tonic-gate 2088210db224Sericheng static void 20898d5c46e6Sam223141 do_rename_link(int argc, char *argv[], const char *use) 2090210db224Sericheng { 2091d62bc4baSyz147064 char option; 2092d62bc4baSyz147064 char *link1, *link2; 2093d62bc4baSyz147064 char *altroot = NULL; 2094d62bc4baSyz147064 dladm_status_t status; 2095210db224Sericheng 2096d62bc4baSyz147064 opterr = 0; 2097d62bc4baSyz147064 while ((option = getopt_long(argc, argv, ":R:", lopts, NULL)) != -1) { 2098d62bc4baSyz147064 switch (option) { 2099d62bc4baSyz147064 case 'R': 2100d62bc4baSyz147064 altroot = optarg; 2101d62bc4baSyz147064 break; 2102d62bc4baSyz147064 default: 21038d5c46e6Sam223141 die_opterr(optopt, option, use); 2104d62bc4baSyz147064 break; 2105210db224Sericheng } 2106210db224Sericheng } 2107210db224Sericheng 2108d62bc4baSyz147064 /* get link1 and link2 name (required the last 2 arguments) */ 2109d62bc4baSyz147064 if (optind != (argc - 2)) 2110d62bc4baSyz147064 usage(); 2111d62bc4baSyz147064 2112d62bc4baSyz147064 if (altroot != NULL) 2113d62bc4baSyz147064 altroot_cmd(altroot, argc, argv); 2114d62bc4baSyz147064 2115d62bc4baSyz147064 link1 = argv[optind++]; 2116d62bc4baSyz147064 link2 = argv[optind]; 21174ac67f02SAnurag S. Maskey if ((status = dladm_rename_link(handle, link1, link2)) != 21184ac67f02SAnurag S. Maskey DLADM_STATUS_OK) 2119d62bc4baSyz147064 die_dlerr(status, "rename operation failed"); 2120d62bc4baSyz147064 } 2121d62bc4baSyz147064 21228d5c46e6Sam223141 /*ARGSUSED*/ 2123d62bc4baSyz147064 static void 21248d5c46e6Sam223141 do_delete_phys(int argc, char *argv[], const char *use) 2125d62bc4baSyz147064 { 2126d62bc4baSyz147064 datalink_id_t linkid = DATALINK_ALL_LINKID; 2127d62bc4baSyz147064 dladm_status_t status; 2128d62bc4baSyz147064 2129d62bc4baSyz147064 /* get link name (required the last argument) */ 2130d62bc4baSyz147064 if (argc > 2) 2131d62bc4baSyz147064 usage(); 2132d62bc4baSyz147064 2133d62bc4baSyz147064 if (argc == 2) { 21344ac67f02SAnurag S. Maskey if ((status = dladm_name2info(handle, argv[1], &linkid, NULL, 21354ac67f02SAnurag S. Maskey NULL, NULL)) != DLADM_STATUS_OK) 2136d62bc4baSyz147064 die_dlerr(status, "cannot delete '%s'", argv[1]); 2137d62bc4baSyz147064 } 2138d62bc4baSyz147064 21394ac67f02SAnurag S. Maskey if ((status = dladm_phys_delete(handle, linkid)) != DLADM_STATUS_OK) { 2140d62bc4baSyz147064 if (argc == 2) 2141d62bc4baSyz147064 die_dlerr(status, "cannot delete '%s'", argv[1]); 2142d62bc4baSyz147064 else 2143d62bc4baSyz147064 die_dlerr(status, "delete operation failed"); 2144d62bc4baSyz147064 } 2145d62bc4baSyz147064 } 2146d62bc4baSyz147064 2147d62bc4baSyz147064 /*ARGSUSED*/ 2148210db224Sericheng static int 21494ac67f02SAnurag S. Maskey i_dladm_walk_linkmap(dladm_handle_t dh, datalink_id_t linkid, void *arg) 2150210db224Sericheng { 2151d62bc4baSyz147064 char name[MAXLINKNAMELEN]; 2152d62bc4baSyz147064 char mediabuf[DLADM_STRSIZE]; 2153d62bc4baSyz147064 char classbuf[DLADM_STRSIZE]; 2154d62bc4baSyz147064 datalink_class_t class; 2155d62bc4baSyz147064 uint32_t media; 2156d62bc4baSyz147064 uint32_t flags; 2157210db224Sericheng 21584ac67f02SAnurag S. Maskey if (dladm_datalink_id2info(dh, linkid, &flags, &class, &media, name, 2159d62bc4baSyz147064 MAXLINKNAMELEN) == DLADM_STATUS_OK) { 2160d62bc4baSyz147064 (void) dladm_class2str(class, classbuf); 2161d62bc4baSyz147064 (void) dladm_media2str(media, mediabuf); 2162d62bc4baSyz147064 (void) printf("%-12s%8d %-12s%-20s %6d\n", name, 2163d62bc4baSyz147064 linkid, classbuf, mediabuf, flags); 2164210db224Sericheng } 2165d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 2166210db224Sericheng } 21677c478bd9Sstevel@tonic-gate 21687c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 21697c478bd9Sstevel@tonic-gate static void 21708d5c46e6Sam223141 do_show_linkmap(int argc, char *argv[], const char *use) 21717c478bd9Sstevel@tonic-gate { 2172d62bc4baSyz147064 if (argc != 1) 2173d62bc4baSyz147064 die("invalid arguments"); 21747c478bd9Sstevel@tonic-gate 2175d62bc4baSyz147064 (void) printf("%-12s%8s %-12s%-20s %6s\n", "NAME", "LINKID", 2176d62bc4baSyz147064 "CLASS", "MEDIA", "FLAGS"); 21774ac67f02SAnurag S. Maskey 21784ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(i_dladm_walk_linkmap, handle, NULL, 2179d62bc4baSyz147064 DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE, 2180d62bc4baSyz147064 DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST); 21817c478bd9Sstevel@tonic-gate } 2182d62bc4baSyz147064 2183d62bc4baSyz147064 /* 2184d62bc4baSyz147064 * Delete inactive physical links. 2185d62bc4baSyz147064 */ 2186d62bc4baSyz147064 /*ARGSUSED*/ 2187d62bc4baSyz147064 static int 21884ac67f02SAnurag S. Maskey purge_phys(dladm_handle_t dh, datalink_id_t linkid, void *arg) 2189d62bc4baSyz147064 { 2190d62bc4baSyz147064 datalink_class_t class; 2191d62bc4baSyz147064 uint32_t flags; 2192d62bc4baSyz147064 21934ac67f02SAnurag S. Maskey if (dladm_datalink_id2info(dh, linkid, &flags, &class, NULL, NULL, 0) 21944ac67f02SAnurag S. Maskey != DLADM_STATUS_OK) { 2195d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 2196d62bc4baSyz147064 } 2197d62bc4baSyz147064 2198d62bc4baSyz147064 if (class == DATALINK_CLASS_PHYS && !(flags & DLADM_OPT_ACTIVE)) 21994ac67f02SAnurag S. Maskey (void) dladm_phys_delete(dh, linkid); 2200d62bc4baSyz147064 2201d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 2202d62bc4baSyz147064 } 2203d62bc4baSyz147064 2204d62bc4baSyz147064 /*ARGSUSED*/ 2205d62bc4baSyz147064 static void 22068d5c46e6Sam223141 do_init_phys(int argc, char *argv[], const char *use) 2207d62bc4baSyz147064 { 2208d62bc4baSyz147064 di_node_t devtree; 2209d62bc4baSyz147064 2210d62bc4baSyz147064 if (argc > 1) 2211d62bc4baSyz147064 usage(); 2212d62bc4baSyz147064 2213d62bc4baSyz147064 /* 2214d62bc4baSyz147064 * Force all the devices to attach, therefore all the network physical 2215d62bc4baSyz147064 * devices can be known to the dlmgmtd daemon. 2216d62bc4baSyz147064 */ 2217d62bc4baSyz147064 if ((devtree = di_init("/", DINFOFORCE | DINFOSUBTREE)) != DI_NODE_NIL) 2218d62bc4baSyz147064 di_fini(devtree); 2219d62bc4baSyz147064 22204ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(purge_phys, handle, NULL, 2221d62bc4baSyz147064 DATALINK_CLASS_PHYS, DATALINK_ANY_MEDIATYPE, DLADM_OPT_PERSIST); 22227c478bd9Sstevel@tonic-gate } 22237c478bd9Sstevel@tonic-gate 2224d62bc4baSyz147064 2225d62bc4baSyz147064 /* 2226d62bc4baSyz147064 * Print the active topology information. 2227d62bc4baSyz147064 */ 2228d62bc4baSyz147064 static dladm_status_t 2229d62bc4baSyz147064 print_link_topology(show_state_t *state, datalink_id_t linkid, 2230e7801d59Ssowmini datalink_class_t class, link_fields_buf_t *lbuf) 2231d62bc4baSyz147064 { 2232d62bc4baSyz147064 uint32_t flags = state->ls_flags; 2233d62bc4baSyz147064 dladm_status_t status = DLADM_STATUS_OK; 22346b9e797cSsowmini char tmpbuf[MAXLINKNAMELEN]; 2235d62bc4baSyz147064 2236e7801d59Ssowmini if (!state->ls_parseable) 2237e7801d59Ssowmini (void) sprintf(lbuf->link_over, STR_UNDEF_VAL); 2238d62bc4baSyz147064 else 2239e7801d59Ssowmini (void) sprintf(lbuf->link_over, ""); 2240d62bc4baSyz147064 2241d62bc4baSyz147064 if (class == DATALINK_CLASS_VLAN) { 2242d62bc4baSyz147064 dladm_vlan_attr_t vinfo; 2243d62bc4baSyz147064 22444ac67f02SAnurag S. Maskey status = dladm_vlan_info(handle, linkid, &vinfo, flags); 2245d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 2246d62bc4baSyz147064 goto done; 22474ac67f02SAnurag S. Maskey status = dladm_datalink_id2info(handle, vinfo.dv_linkid, NULL, 22484ac67f02SAnurag S. Maskey NULL, NULL, lbuf->link_over, sizeof (lbuf->link_over)); 2249d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 2250d62bc4baSyz147064 goto done; 2251d62bc4baSyz147064 } else if (class == DATALINK_CLASS_AGGR) { 2252d62bc4baSyz147064 dladm_aggr_grp_attr_t ginfo; 2253d62bc4baSyz147064 int i; 2254d62bc4baSyz147064 22556b9e797cSsowmini (void) sprintf(lbuf->link_over, ""); 22566b9e797cSsowmini 22574ac67f02SAnurag S. Maskey status = dladm_aggr_info(handle, linkid, &ginfo, flags); 2258d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 2259d62bc4baSyz147064 goto done; 2260d62bc4baSyz147064 2261d62bc4baSyz147064 if (ginfo.lg_nports == 0) { 2262d62bc4baSyz147064 status = DLADM_STATUS_BADVAL; 2263d62bc4baSyz147064 goto done; 2264d62bc4baSyz147064 } 2265d62bc4baSyz147064 for (i = 0; i < ginfo.lg_nports; i++) { 22664ac67f02SAnurag S. Maskey status = dladm_datalink_id2info(handle, 2267e7801d59Ssowmini ginfo.lg_ports[i].lp_linkid, NULL, NULL, NULL, 22686b9e797cSsowmini tmpbuf, sizeof (tmpbuf)); 2269d62bc4baSyz147064 if (status != DLADM_STATUS_OK) { 2270d62bc4baSyz147064 free(ginfo.lg_ports); 2271d62bc4baSyz147064 goto done; 2272d62bc4baSyz147064 } 22736b9e797cSsowmini (void) strlcat(lbuf->link_over, tmpbuf, 22746b9e797cSsowmini sizeof (lbuf->link_over)); 22756b9e797cSsowmini if (i != (ginfo.lg_nports - 1)) { 22766b9e797cSsowmini (void) strlcat(lbuf->link_over, " ", 22776b9e797cSsowmini sizeof (lbuf->link_over)); 22786b9e797cSsowmini } 2279d62bc4baSyz147064 } 2280d62bc4baSyz147064 free(ginfo.lg_ports); 2281d62bc4baSyz147064 } else if (class == DATALINK_CLASS_VNIC) { 2282da14cebeSEric Cheng dladm_vnic_attr_t vinfo; 2283d62bc4baSyz147064 22844ac67f02SAnurag S. Maskey if ((status = dladm_vnic_info(handle, linkid, &vinfo, flags)) != 22854ac67f02SAnurag S. Maskey DLADM_STATUS_OK || 22864ac67f02SAnurag S. Maskey (status = dladm_datalink_id2info(handle, vinfo.va_link_id, 22874ac67f02SAnurag S. Maskey NULL, NULL, NULL, lbuf->link_over, 2288e7801d59Ssowmini sizeof (lbuf->link_over)) != DLADM_STATUS_OK)) { 2289d62bc4baSyz147064 goto done; 2290d62bc4baSyz147064 } 2291d62bc4baSyz147064 } 2292d62bc4baSyz147064 done: 2293d62bc4baSyz147064 return (status); 2294d62bc4baSyz147064 } 2295d62bc4baSyz147064 2296d62bc4baSyz147064 static dladm_status_t 2297e7801d59Ssowmini print_link(show_state_t *state, datalink_id_t linkid, link_fields_buf_t *lbuf) 2298d62bc4baSyz147064 { 2299d62bc4baSyz147064 char link[MAXLINKNAMELEN]; 2300d62bc4baSyz147064 datalink_class_t class; 2301d62bc4baSyz147064 uint_t mtu; 2302d62bc4baSyz147064 uint32_t flags; 2303d62bc4baSyz147064 dladm_status_t status; 2304d62bc4baSyz147064 23054ac67f02SAnurag S. Maskey if ((status = dladm_datalink_id2info(handle, linkid, &flags, &class, 23064ac67f02SAnurag S. Maskey NULL, link, sizeof (link))) != DLADM_STATUS_OK) { 2307d62bc4baSyz147064 goto done; 2308d62bc4baSyz147064 } 2309d62bc4baSyz147064 2310d62bc4baSyz147064 if (!(state->ls_flags & flags)) { 2311d62bc4baSyz147064 status = DLADM_STATUS_NOTFOUND; 2312d62bc4baSyz147064 goto done; 2313d62bc4baSyz147064 } 2314d62bc4baSyz147064 2315d62bc4baSyz147064 if (state->ls_flags == DLADM_OPT_ACTIVE) { 2316d62bc4baSyz147064 dladm_attr_t dlattr; 2317d62bc4baSyz147064 2318d62bc4baSyz147064 if (class == DATALINK_CLASS_PHYS) { 2319d62bc4baSyz147064 dladm_phys_attr_t dpa; 2320d62bc4baSyz147064 dlpi_handle_t dh; 2321d62bc4baSyz147064 dlpi_info_t dlinfo; 2322d62bc4baSyz147064 23234ac67f02SAnurag S. Maskey if ((status = dladm_phys_info(handle, linkid, &dpa, 2324d62bc4baSyz147064 DLADM_OPT_ACTIVE)) != DLADM_STATUS_OK) { 2325d62bc4baSyz147064 goto done; 2326d62bc4baSyz147064 } 2327d62bc4baSyz147064 2328d62bc4baSyz147064 if (!dpa.dp_novanity) 2329d62bc4baSyz147064 goto link_mtu; 2330d62bc4baSyz147064 2331d62bc4baSyz147064 /* 2332d62bc4baSyz147064 * This is a physical link that does not have 2333d62bc4baSyz147064 * vanity naming support. 2334d62bc4baSyz147064 */ 2335d62bc4baSyz147064 if (dlpi_open(dpa.dp_dev, &dh, DLPI_DEVONLY) != 2336d62bc4baSyz147064 DLPI_SUCCESS) { 2337d62bc4baSyz147064 status = DLADM_STATUS_NOTFOUND; 2338d62bc4baSyz147064 goto done; 2339d62bc4baSyz147064 } 2340d62bc4baSyz147064 2341d62bc4baSyz147064 if (dlpi_info(dh, &dlinfo, 0) != DLPI_SUCCESS) { 2342d62bc4baSyz147064 dlpi_close(dh); 2343d62bc4baSyz147064 status = DLADM_STATUS_BADARG; 2344d62bc4baSyz147064 goto done; 2345d62bc4baSyz147064 } 2346d62bc4baSyz147064 2347d62bc4baSyz147064 dlpi_close(dh); 2348d62bc4baSyz147064 mtu = dlinfo.di_max_sdu; 2349d62bc4baSyz147064 } else { 2350d62bc4baSyz147064 link_mtu: 23514ac67f02SAnurag S. Maskey status = dladm_info(handle, linkid, &dlattr); 2352d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 2353d62bc4baSyz147064 goto done; 2354d62bc4baSyz147064 mtu = dlattr.da_max_sdu; 2355d62bc4baSyz147064 } 2356d62bc4baSyz147064 } 2357d62bc4baSyz147064 2358e7801d59Ssowmini (void) snprintf(lbuf->link_name, sizeof (lbuf->link_name), 2359e7801d59Ssowmini "%s", link); 2360e7801d59Ssowmini (void) dladm_class2str(class, lbuf->link_class); 2361d62bc4baSyz147064 if (state->ls_flags == DLADM_OPT_ACTIVE) { 2362e7801d59Ssowmini (void) snprintf(lbuf->link_mtu, sizeof (lbuf->link_mtu), 2363c08e5e1aSdr146992 "%u", mtu); 2364e7801d59Ssowmini (void) get_linkstate(link, B_TRUE, lbuf->link_state); 2365d62bc4baSyz147064 } 2366d62bc4baSyz147064 2367e7801d59Ssowmini status = print_link_topology(state, linkid, class, lbuf); 2368d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 2369d62bc4baSyz147064 goto done; 2370d62bc4baSyz147064 2371d62bc4baSyz147064 done: 2372d62bc4baSyz147064 return (status); 2373d62bc4baSyz147064 } 2374d62bc4baSyz147064 23754ac67f02SAnurag S. Maskey /* ARGSUSED */ 2376d62bc4baSyz147064 static int 23774ac67f02SAnurag S. Maskey show_link(dladm_handle_t dh, datalink_id_t linkid, void *arg) 2378d62bc4baSyz147064 { 2379e7801d59Ssowmini show_state_t *state = (show_state_t *)arg; 2380d62bc4baSyz147064 dladm_status_t status; 2381e7801d59Ssowmini link_fields_buf_t lbuf; 2382d62bc4baSyz147064 2383e7801d59Ssowmini /* 2384e7801d59Ssowmini * first get all the link attributes into lbuf; 2385e7801d59Ssowmini */ 23865f5c9f54SAnurag S. Maskey bzero(&lbuf, sizeof (link_fields_buf_t)); 2387e7801d59Ssowmini status = print_link(state, linkid, &lbuf); 2388e7801d59Ssowmini 2389d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 2390d62bc4baSyz147064 goto done; 2391e7801d59Ssowmini 2392e7801d59Ssowmini if (!state->ls_parseable && !state->ls_printheader) { 2393e7801d59Ssowmini print_header(&state->ls_print); 2394e7801d59Ssowmini state->ls_printheader = B_TRUE; 2395e7801d59Ssowmini } 2396e7801d59Ssowmini 2397e7801d59Ssowmini dladm_print_output(&state->ls_print, state->ls_parseable, 2398e7801d59Ssowmini dladm_print_field, (void *)&lbuf); 2399d62bc4baSyz147064 2400d62bc4baSyz147064 done: 2401d62bc4baSyz147064 state->ls_status = status; 2402d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 2403d62bc4baSyz147064 } 2404d62bc4baSyz147064 2405ae6aa22aSVenugopal Iyer static char * 2406ae6aa22aSVenugopal Iyer print_link_stats(print_field_t *pf, void *arg) 2407ae6aa22aSVenugopal Iyer { 2408ae6aa22aSVenugopal Iyer link_args_t *largs = arg; 2409ae6aa22aSVenugopal Iyer pktsum_t *diff_stats = largs->link_s_psum; 2410ae6aa22aSVenugopal Iyer static char buf[DLADM_STRSIZE]; 2411ae6aa22aSVenugopal Iyer 2412ae6aa22aSVenugopal Iyer switch (pf->pf_index) { 2413ae6aa22aSVenugopal Iyer case LINK_S_LINK: 2414ae6aa22aSVenugopal Iyer (void) snprintf(buf, sizeof (buf), "%s", largs->link_s_link); 2415ae6aa22aSVenugopal Iyer break; 2416ae6aa22aSVenugopal Iyer case LINK_S_IPKTS: 2417ae6aa22aSVenugopal Iyer (void) snprintf(buf, sizeof (buf), "%llu", 2418ae6aa22aSVenugopal Iyer diff_stats->ipackets); 2419ae6aa22aSVenugopal Iyer break; 2420ae6aa22aSVenugopal Iyer case LINK_S_RBYTES: 2421ae6aa22aSVenugopal Iyer (void) snprintf(buf, sizeof (buf), "%llu", 2422ae6aa22aSVenugopal Iyer diff_stats->rbytes); 2423ae6aa22aSVenugopal Iyer break; 2424ae6aa22aSVenugopal Iyer case LINK_S_IERRORS: 2425ae6aa22aSVenugopal Iyer (void) snprintf(buf, sizeof (buf), "%u", 2426ae6aa22aSVenugopal Iyer diff_stats->ierrors); 2427ae6aa22aSVenugopal Iyer break; 2428ae6aa22aSVenugopal Iyer case LINK_S_OPKTS: 2429ae6aa22aSVenugopal Iyer (void) snprintf(buf, sizeof (buf), "%llu", 2430ae6aa22aSVenugopal Iyer diff_stats->opackets); 2431ae6aa22aSVenugopal Iyer break; 2432ae6aa22aSVenugopal Iyer case LINK_S_OBYTES: 2433ae6aa22aSVenugopal Iyer (void) snprintf(buf, sizeof (buf), "%llu", 2434ae6aa22aSVenugopal Iyer diff_stats->obytes); 2435ae6aa22aSVenugopal Iyer break; 2436ae6aa22aSVenugopal Iyer case LINK_S_OERRORS: 2437ae6aa22aSVenugopal Iyer (void) snprintf(buf, sizeof (buf), "%u", 2438ae6aa22aSVenugopal Iyer diff_stats->oerrors); 2439ae6aa22aSVenugopal Iyer break; 2440ae6aa22aSVenugopal Iyer default: 2441ae6aa22aSVenugopal Iyer die("invalid input"); 2442ae6aa22aSVenugopal Iyer break; 2443ae6aa22aSVenugopal Iyer } 2444ae6aa22aSVenugopal Iyer return (buf); 2445ae6aa22aSVenugopal Iyer } 2446ae6aa22aSVenugopal Iyer 2447d62bc4baSyz147064 static int 24484ac67f02SAnurag S. Maskey show_link_stats(dladm_handle_t dh, datalink_id_t linkid, void *arg) 2449d62bc4baSyz147064 { 2450e7801d59Ssowmini char link[DLPI_LINKNAME_MAX]; 2451d62bc4baSyz147064 datalink_class_t class; 2452e7801d59Ssowmini show_state_t *state = (show_state_t *)arg; 24537c478bd9Sstevel@tonic-gate pktsum_t stats, diff_stats; 2454d62bc4baSyz147064 dladm_phys_attr_t dpa; 2455ae6aa22aSVenugopal Iyer link_args_t largs; 24567c478bd9Sstevel@tonic-gate 24577c478bd9Sstevel@tonic-gate if (state->ls_firstonly) { 24587c478bd9Sstevel@tonic-gate if (state->ls_donefirst) 2459d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 24607c478bd9Sstevel@tonic-gate state->ls_donefirst = B_TRUE; 24617c478bd9Sstevel@tonic-gate } else { 24627c478bd9Sstevel@tonic-gate bzero(&state->ls_prevstats, sizeof (state->ls_prevstats)); 24637c478bd9Sstevel@tonic-gate } 24647c478bd9Sstevel@tonic-gate 24654ac67f02SAnurag S. Maskey if (dladm_datalink_id2info(dh, linkid, NULL, &class, NULL, link, 2466e7801d59Ssowmini DLPI_LINKNAME_MAX) != DLADM_STATUS_OK) { 2467d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 2468d62bc4baSyz147064 } 2469d62bc4baSyz147064 2470d62bc4baSyz147064 if (class == DATALINK_CLASS_PHYS) { 24714ac67f02SAnurag S. Maskey if (dladm_phys_info(dh, linkid, &dpa, DLADM_OPT_ACTIVE) != 2472d62bc4baSyz147064 DLADM_STATUS_OK) { 2473d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 2474d62bc4baSyz147064 } 2475d62bc4baSyz147064 if (dpa.dp_novanity) 2476d62bc4baSyz147064 get_mac_stats(dpa.dp_dev, &stats); 2477d62bc4baSyz147064 else 2478d62bc4baSyz147064 get_link_stats(link, &stats); 2479d62bc4baSyz147064 } else { 2480d62bc4baSyz147064 get_link_stats(link, &stats); 2481d62bc4baSyz147064 } 2482da14cebeSEric Cheng dladm_stats_diff(&diff_stats, &stats, &state->ls_prevstats); 24837c478bd9Sstevel@tonic-gate 2484ae6aa22aSVenugopal Iyer largs.link_s_link = link; 2485ae6aa22aSVenugopal Iyer largs.link_s_psum = &diff_stats; 2486ae6aa22aSVenugopal Iyer dladm_print_output(&state->ls_print, state->ls_parseable, 2487ae6aa22aSVenugopal Iyer print_link_stats, &largs); 24887c478bd9Sstevel@tonic-gate 24897c478bd9Sstevel@tonic-gate state->ls_prevstats = stats; 2490d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 24917c478bd9Sstevel@tonic-gate } 24927c478bd9Sstevel@tonic-gate 2493d62bc4baSyz147064 2494d62bc4baSyz147064 static dladm_status_t 2495d62bc4baSyz147064 print_aggr_info(show_grp_state_t *state, const char *link, 2496e7801d59Ssowmini dladm_aggr_grp_attr_t *ginfop) 2497d62bc4baSyz147064 { 2498d62bc4baSyz147064 char addr_str[ETHERADDRL * 3]; 2499e7801d59Ssowmini laggr_fields_buf_t lbuf; 2500d62bc4baSyz147064 2501e7801d59Ssowmini (void) snprintf(lbuf.laggr_name, sizeof (lbuf.laggr_name), 2502e7801d59Ssowmini "%s", link); 2503e7801d59Ssowmini 2504e7801d59Ssowmini (void) dladm_aggr_policy2str(ginfop->lg_policy, 2505e7801d59Ssowmini lbuf.laggr_policy); 2506d62bc4baSyz147064 2507d62bc4baSyz147064 if (ginfop->lg_mac_fixed) { 2508d62bc4baSyz147064 (void) dladm_aggr_macaddr2str(ginfop->lg_mac, addr_str); 2509e7801d59Ssowmini (void) snprintf(lbuf.laggr_addrpolicy, 2510e7801d59Ssowmini sizeof (lbuf.laggr_addrpolicy), "fixed (%s)", addr_str); 2511d62bc4baSyz147064 } else { 2512e7801d59Ssowmini (void) snprintf(lbuf.laggr_addrpolicy, 2513e7801d59Ssowmini sizeof (lbuf.laggr_addrpolicy), "auto"); 2514d62bc4baSyz147064 } 2515d62bc4baSyz147064 2516d62bc4baSyz147064 2517e7801d59Ssowmini (void) dladm_aggr_lacpmode2str(ginfop->lg_lacp_mode, 2518e7801d59Ssowmini lbuf.laggr_lacpactivity); 2519e7801d59Ssowmini (void) dladm_aggr_lacptimer2str(ginfop->lg_lacp_timer, 2520e7801d59Ssowmini lbuf.laggr_lacptimer); 2521e7801d59Ssowmini (void) snprintf(lbuf.laggr_flags, sizeof (lbuf.laggr_flags), "%c----", 2522d62bc4baSyz147064 ginfop->lg_force ? 'f' : '-'); 2523e7801d59Ssowmini 2524e7801d59Ssowmini if (!state->gs_parseable && !state->gs_printheader) { 2525e7801d59Ssowmini print_header(&state->gs_print); 2526e7801d59Ssowmini state->gs_printheader = B_TRUE; 2527d62bc4baSyz147064 } 2528d62bc4baSyz147064 2529e7801d59Ssowmini dladm_print_output(&state->gs_print, state->gs_parseable, 2530e7801d59Ssowmini dladm_print_field, (void *)&lbuf); 2531e7801d59Ssowmini 2532d62bc4baSyz147064 return (DLADM_STATUS_OK); 2533d62bc4baSyz147064 } 2534d62bc4baSyz147064 2535e7801d59Ssowmini static char * 2536e7801d59Ssowmini print_xaggr_callback(print_field_t *pf, void *arg) 2537d62bc4baSyz147064 { 2538e7801d59Ssowmini const laggr_args_t *l = arg; 2539e7801d59Ssowmini int portnum; 2540e7801d59Ssowmini static char buf[DLADM_STRSIZE]; 2541e7801d59Ssowmini boolean_t is_port = (l->laggr_lport >= 0); 2542e7801d59Ssowmini dladm_aggr_port_attr_t *portp; 2543d62bc4baSyz147064 dladm_phys_attr_t dpa; 2544e7801d59Ssowmini dladm_status_t *stat, status; 2545d62bc4baSyz147064 2546e7801d59Ssowmini stat = l->laggr_status; 2547e7801d59Ssowmini *stat = DLADM_STATUS_OK; 2548d62bc4baSyz147064 2549e7801d59Ssowmini if (is_port) { 2550e7801d59Ssowmini portnum = l->laggr_lport; 2551e7801d59Ssowmini portp = &(l->laggr_ginfop->lg_ports[portnum]); 25524ac67f02SAnurag S. Maskey if ((status = dladm_datalink_id2info(handle, 25534ac67f02SAnurag S. Maskey portp->lp_linkid, NULL, NULL, NULL, buf, sizeof (buf))) != 2554e7801d59Ssowmini DLADM_STATUS_OK) { 2555e7801d59Ssowmini goto err; 2556d62bc4baSyz147064 } 25574ac67f02SAnurag S. Maskey 25584ac67f02SAnurag S. Maskey if ((status = dladm_phys_info(handle, portp->lp_linkid, 25594ac67f02SAnurag S. Maskey &dpa, DLADM_OPT_ACTIVE)) != DLADM_STATUS_OK) { 2560e7801d59Ssowmini goto err; 2561e7801d59Ssowmini } 2562d62bc4baSyz147064 } 2563d62bc4baSyz147064 2564e7801d59Ssowmini switch (pf->pf_index) { 2565e7801d59Ssowmini case AGGR_X_LINK: 2566e7801d59Ssowmini (void) snprintf(buf, sizeof (buf), "%s", 2567e7801d59Ssowmini (is_port && !l->laggr_parseable ? " " : l->laggr_link)); 2568e7801d59Ssowmini break; 2569e7801d59Ssowmini case AGGR_X_PORT: 2570e7801d59Ssowmini if (is_port) 2571e7801d59Ssowmini break; 2572e7801d59Ssowmini return (""); 2573e7801d59Ssowmini break; 2574d62bc4baSyz147064 2575e7801d59Ssowmini case AGGR_X_SPEED: 2576e7801d59Ssowmini if (is_port) { 2577e7801d59Ssowmini (void) snprintf(buf, sizeof (buf), "%uMb", 2578e7801d59Ssowmini (uint_t)((get_ifspeed(dpa.dp_dev, 2579e7801d59Ssowmini B_FALSE)) / 1000000ull)); 2580e7801d59Ssowmini } else { 2581e7801d59Ssowmini (void) snprintf(buf, sizeof (buf), "%uMb", 2582e7801d59Ssowmini (uint_t)((get_ifspeed(l->laggr_link, 2583e7801d59Ssowmini B_TRUE)) / 1000000ull)); 2584e7801d59Ssowmini } 2585e7801d59Ssowmini break; 2586e7801d59Ssowmini 2587e7801d59Ssowmini case AGGR_X_DUPLEX: 2588e7801d59Ssowmini if (is_port) 2589e7801d59Ssowmini (void) get_linkduplex(dpa.dp_dev, B_FALSE, buf); 2590d62bc4baSyz147064 else 2591e7801d59Ssowmini (void) get_linkduplex(l->laggr_link, B_TRUE, buf); 2592e7801d59Ssowmini break; 2593d62bc4baSyz147064 2594e7801d59Ssowmini case AGGR_X_STATE: 25951a1811a0Svs226613 if (is_port) 25961a1811a0Svs226613 (void) get_linkstate(dpa.dp_dev, B_FALSE, buf); 25971a1811a0Svs226613 else 25981a1811a0Svs226613 (void) get_linkstate(l->laggr_link, B_TRUE, buf); 2599e7801d59Ssowmini break; 2600e7801d59Ssowmini case AGGR_X_ADDRESS: 2601e7801d59Ssowmini (void) dladm_aggr_macaddr2str( 2602e7801d59Ssowmini (is_port ? portp->lp_mac : l->laggr_ginfop->lg_mac), 2603e7801d59Ssowmini buf); 2604e7801d59Ssowmini break; 2605e7801d59Ssowmini case AGGR_X_PORTSTATE: 26060d365605Sschuster if (is_port) 26070d365605Sschuster (void) dladm_aggr_portstate2str( 26080d365605Sschuster portp->lp_state, buf); 26090d365605Sschuster else 26100d365605Sschuster return (""); 2611e7801d59Ssowmini break; 2612e7801d59Ssowmini } 2613e7801d59Ssowmini return (buf); 2614e7801d59Ssowmini 2615e7801d59Ssowmini err: 2616e7801d59Ssowmini *stat = status; 2617e7801d59Ssowmini buf[0] = '\0'; 2618e7801d59Ssowmini return (buf); 2619e7801d59Ssowmini } 2620e7801d59Ssowmini 2621e7801d59Ssowmini static dladm_status_t 2622e7801d59Ssowmini print_aggr_extended(show_grp_state_t *state, const char *link, 2623e7801d59Ssowmini dladm_aggr_grp_attr_t *ginfop) 2624e7801d59Ssowmini { 2625e7801d59Ssowmini int i; 2626e7801d59Ssowmini dladm_status_t status; 2627e7801d59Ssowmini laggr_args_t largs; 2628e7801d59Ssowmini 2629e7801d59Ssowmini if (!state->gs_parseable && !state->gs_printheader) { 2630e7801d59Ssowmini print_header(&state->gs_print); 2631e7801d59Ssowmini state->gs_printheader = B_TRUE; 2632e7801d59Ssowmini } 2633e7801d59Ssowmini 2634e7801d59Ssowmini largs.laggr_lport = -1; 2635e7801d59Ssowmini largs.laggr_link = link; 2636e7801d59Ssowmini largs.laggr_ginfop = ginfop; 2637e7801d59Ssowmini largs.laggr_status = &status; 2638e7801d59Ssowmini largs.laggr_parseable = state->gs_parseable; 2639e7801d59Ssowmini 2640e7801d59Ssowmini dladm_print_output(&state->gs_print, state->gs_parseable, 2641e7801d59Ssowmini print_xaggr_callback, &largs); 2642e7801d59Ssowmini 2643e7801d59Ssowmini if (status != DLADM_STATUS_OK) 2644e7801d59Ssowmini goto done; 2645e7801d59Ssowmini 2646e7801d59Ssowmini for (i = 0; i < ginfop->lg_nports; i++) { 2647e7801d59Ssowmini largs.laggr_lport = i; 2648e7801d59Ssowmini dladm_print_output(&state->gs_print, state->gs_parseable, 2649e7801d59Ssowmini print_xaggr_callback, &largs); 2650e7801d59Ssowmini if (status != DLADM_STATUS_OK) 2651e7801d59Ssowmini goto done; 2652d62bc4baSyz147064 } 2653d62bc4baSyz147064 2654d62bc4baSyz147064 status = DLADM_STATUS_OK; 2655d62bc4baSyz147064 done: 2656d62bc4baSyz147064 return (status); 2657d62bc4baSyz147064 } 2658d62bc4baSyz147064 2659e7801d59Ssowmini 2660e7801d59Ssowmini static char * 2661e7801d59Ssowmini print_lacp_callback(print_field_t *pf, void *arg) 2662e7801d59Ssowmini { 2663e7801d59Ssowmini const laggr_args_t *l = arg; 2664e7801d59Ssowmini int portnum; 2665e7801d59Ssowmini static char buf[DLADM_STRSIZE]; 2666e7801d59Ssowmini boolean_t is_port = (l->laggr_lport >= 0); 2667e7801d59Ssowmini dladm_aggr_port_attr_t *portp; 2668e7801d59Ssowmini dladm_status_t *stat, status; 2669e7801d59Ssowmini aggr_lacp_state_t *lstate; 2670e7801d59Ssowmini 2671e7801d59Ssowmini if (!is_port) { 2672e7801d59Ssowmini return (NULL); /* cannot happen! */ 2673e7801d59Ssowmini } 2674e7801d59Ssowmini 2675e7801d59Ssowmini stat = l->laggr_status; 2676e7801d59Ssowmini 2677e7801d59Ssowmini portnum = l->laggr_lport; 2678e7801d59Ssowmini portp = &(l->laggr_ginfop->lg_ports[portnum]); 26794ac67f02SAnurag S. Maskey 26804ac67f02SAnurag S. Maskey if ((status = dladm_datalink_id2info(handle, portp->lp_linkid, 2681e7801d59Ssowmini NULL, NULL, NULL, buf, sizeof (buf))) != DLADM_STATUS_OK) { 2682e7801d59Ssowmini goto err; 2683e7801d59Ssowmini } 2684e7801d59Ssowmini lstate = &(portp->lp_lacp_state); 2685e7801d59Ssowmini 2686e7801d59Ssowmini switch (pf->pf_index) { 2687e7801d59Ssowmini case AGGR_L_LINK: 2688e7801d59Ssowmini (void) snprintf(buf, sizeof (buf), "%s", 2689e7801d59Ssowmini (portnum > 0 ? "" : l->laggr_link)); 2690e7801d59Ssowmini break; 2691e7801d59Ssowmini 2692e7801d59Ssowmini case AGGR_L_PORT: 2693e7801d59Ssowmini break; 2694e7801d59Ssowmini 2695e7801d59Ssowmini case AGGR_L_AGGREGATABLE: 2696e7801d59Ssowmini (void) snprintf(buf, sizeof (buf), "%s", 2697e7801d59Ssowmini (lstate->bit.aggregation ? "yes" : "no")); 2698e7801d59Ssowmini break; 2699e7801d59Ssowmini 2700e7801d59Ssowmini case AGGR_L_SYNC: 2701e7801d59Ssowmini (void) snprintf(buf, sizeof (buf), "%s", 2702e7801d59Ssowmini (lstate->bit.sync ? "yes" : "no")); 2703e7801d59Ssowmini break; 2704e7801d59Ssowmini 2705e7801d59Ssowmini case AGGR_L_COLL: 2706e7801d59Ssowmini (void) snprintf(buf, sizeof (buf), "%s", 2707e7801d59Ssowmini (lstate->bit.collecting ? "yes" : "no")); 2708e7801d59Ssowmini break; 2709e7801d59Ssowmini 2710e7801d59Ssowmini case AGGR_L_DIST: 2711e7801d59Ssowmini (void) snprintf(buf, sizeof (buf), "%s", 2712e7801d59Ssowmini (lstate->bit.distributing ? "yes" : "no")); 2713e7801d59Ssowmini break; 2714e7801d59Ssowmini 2715e7801d59Ssowmini case AGGR_L_DEFAULTED: 2716e7801d59Ssowmini (void) snprintf(buf, sizeof (buf), "%s", 2717e7801d59Ssowmini (lstate->bit.defaulted ? "yes" : "no")); 2718e7801d59Ssowmini break; 2719e7801d59Ssowmini 2720e7801d59Ssowmini case AGGR_L_EXPIRED: 2721e7801d59Ssowmini (void) snprintf(buf, sizeof (buf), "%s", 2722e7801d59Ssowmini (lstate->bit.expired ? "yes" : "no")); 2723e7801d59Ssowmini break; 2724e7801d59Ssowmini } 2725e7801d59Ssowmini 2726e7801d59Ssowmini *stat = DLADM_STATUS_OK; 2727e7801d59Ssowmini return (buf); 2728e7801d59Ssowmini 2729e7801d59Ssowmini err: 2730e7801d59Ssowmini *stat = status; 2731e7801d59Ssowmini buf[0] = '\0'; 2732e7801d59Ssowmini return (buf); 2733e7801d59Ssowmini } 2734e7801d59Ssowmini 2735d62bc4baSyz147064 static dladm_status_t 2736d62bc4baSyz147064 print_aggr_lacp(show_grp_state_t *state, const char *link, 2737e7801d59Ssowmini dladm_aggr_grp_attr_t *ginfop) 2738d62bc4baSyz147064 { 2739d62bc4baSyz147064 int i; 2740d62bc4baSyz147064 dladm_status_t status; 2741e7801d59Ssowmini laggr_args_t largs; 2742d62bc4baSyz147064 2743e7801d59Ssowmini if (!state->gs_parseable && !state->gs_printheader) { 2744e7801d59Ssowmini print_header(&state->gs_print); 2745e7801d59Ssowmini state->gs_printheader = B_TRUE; 2746d62bc4baSyz147064 } 2747d62bc4baSyz147064 2748e7801d59Ssowmini largs.laggr_link = link; 2749e7801d59Ssowmini largs.laggr_ginfop = ginfop; 2750e7801d59Ssowmini largs.laggr_status = &status; 2751d62bc4baSyz147064 2752e7801d59Ssowmini for (i = 0; i < ginfop->lg_nports; i++) { 2753e7801d59Ssowmini largs.laggr_lport = i; 2754e7801d59Ssowmini dladm_print_output(&state->gs_print, state->gs_parseable, 2755e7801d59Ssowmini print_lacp_callback, &largs); 2756d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 2757d62bc4baSyz147064 goto done; 2758d62bc4baSyz147064 } 2759d62bc4baSyz147064 2760d62bc4baSyz147064 status = DLADM_STATUS_OK; 2761d62bc4baSyz147064 done: 2762d62bc4baSyz147064 return (status); 2763d62bc4baSyz147064 } 2764d62bc4baSyz147064 2765e7801d59Ssowmini static char * 2766e7801d59Ssowmini print_aggr_stats_callback(print_field_t *pf, void *arg) 2767e7801d59Ssowmini { 2768e7801d59Ssowmini const laggr_args_t *l = arg; 2769e7801d59Ssowmini int portnum; 2770e7801d59Ssowmini static char buf[DLADM_STRSIZE]; 2771e7801d59Ssowmini boolean_t is_port = (l->laggr_lport >= 0); 2772e7801d59Ssowmini dladm_aggr_port_attr_t *portp; 2773e7801d59Ssowmini dladm_phys_attr_t dpa; 2774e7801d59Ssowmini dladm_status_t *stat, status; 2775e7801d59Ssowmini pktsum_t port_stat, diff_stats; 2776e7801d59Ssowmini 2777e7801d59Ssowmini stat = l->laggr_status; 2778e7801d59Ssowmini *stat = DLADM_STATUS_OK; 2779e7801d59Ssowmini 2780e7801d59Ssowmini if (is_port) { 2781e7801d59Ssowmini portnum = l->laggr_lport; 2782e7801d59Ssowmini portp = &(l->laggr_ginfop->lg_ports[portnum]); 27834ac67f02SAnurag S. Maskey if ((status = dladm_phys_info(handle, portp->lp_linkid, 27844ac67f02SAnurag S. Maskey &dpa, DLADM_OPT_ACTIVE)) != DLADM_STATUS_OK) { 2785e7801d59Ssowmini goto err; 2786e7801d59Ssowmini } 2787e7801d59Ssowmini 2788e7801d59Ssowmini get_mac_stats(dpa.dp_dev, &port_stat); 2789e7801d59Ssowmini 27904ac67f02SAnurag S. Maskey if ((status = dladm_datalink_id2info(handle, 27914ac67f02SAnurag S. Maskey portp->lp_linkid, NULL, NULL, NULL, buf, sizeof (buf))) != 27924ac67f02SAnurag S. Maskey DLADM_STATUS_OK) { 2793e7801d59Ssowmini goto err; 2794e7801d59Ssowmini } 2795e7801d59Ssowmini 2796da14cebeSEric Cheng dladm_stats_diff(&diff_stats, &port_stat, l->laggr_prevstats); 2797e7801d59Ssowmini } 2798e7801d59Ssowmini 2799e7801d59Ssowmini switch (pf->pf_index) { 2800e7801d59Ssowmini case AGGR_S_LINK: 2801e7801d59Ssowmini (void) snprintf(buf, sizeof (buf), "%s", 2802e7801d59Ssowmini (is_port ? "" : l->laggr_link)); 2803e7801d59Ssowmini break; 2804e7801d59Ssowmini case AGGR_S_PORT: 2805e7801d59Ssowmini if (is_port) 2806e7801d59Ssowmini break; 28070d365605Sschuster return (""); 2808e7801d59Ssowmini break; 2809e7801d59Ssowmini 2810e7801d59Ssowmini case AGGR_S_IPKTS: 2811e7801d59Ssowmini if (is_port) { 2812e7801d59Ssowmini (void) snprintf(buf, sizeof (buf), "%llu", 2813e7801d59Ssowmini diff_stats.ipackets); 2814e7801d59Ssowmini } else { 2815e7801d59Ssowmini (void) snprintf(buf, sizeof (buf), "%llu", 2816e7801d59Ssowmini l->laggr_pktsumtot->ipackets); 2817e7801d59Ssowmini } 2818e7801d59Ssowmini break; 2819e7801d59Ssowmini 2820e7801d59Ssowmini case AGGR_S_RBYTES: 2821e7801d59Ssowmini if (is_port) { 2822e7801d59Ssowmini (void) snprintf(buf, sizeof (buf), "%llu", 2823e7801d59Ssowmini diff_stats.rbytes); 2824e7801d59Ssowmini } else { 2825e7801d59Ssowmini (void) snprintf(buf, sizeof (buf), "%llu", 2826e7801d59Ssowmini l->laggr_pktsumtot->rbytes); 2827e7801d59Ssowmini } 2828e7801d59Ssowmini break; 2829e7801d59Ssowmini 2830e7801d59Ssowmini case AGGR_S_OPKTS: 2831e7801d59Ssowmini if (is_port) { 2832e7801d59Ssowmini (void) snprintf(buf, sizeof (buf), "%llu", 2833e7801d59Ssowmini diff_stats.opackets); 2834e7801d59Ssowmini } else { 2835e7801d59Ssowmini (void) snprintf(buf, sizeof (buf), "%llu", 2836e7801d59Ssowmini l->laggr_pktsumtot->opackets); 2837e7801d59Ssowmini } 2838e7801d59Ssowmini break; 2839e7801d59Ssowmini case AGGR_S_OBYTES: 2840e7801d59Ssowmini if (is_port) { 2841e7801d59Ssowmini (void) snprintf(buf, sizeof (buf), "%llu", 2842e7801d59Ssowmini diff_stats.obytes); 2843e7801d59Ssowmini } else { 2844e7801d59Ssowmini (void) snprintf(buf, sizeof (buf), "%llu", 2845e7801d59Ssowmini l->laggr_pktsumtot->obytes); 2846e7801d59Ssowmini } 2847e7801d59Ssowmini break; 2848e7801d59Ssowmini 2849e7801d59Ssowmini case AGGR_S_IPKTDIST: 2850e7801d59Ssowmini if (is_port) { 2851e7801d59Ssowmini (void) snprintf(buf, sizeof (buf), "%-6.1f", 2852e7801d59Ssowmini (double)diff_stats.opackets/ 2853e7801d59Ssowmini (double)l->laggr_pktsumtot->ipackets * 100); 2854e7801d59Ssowmini } else { 28550d365605Sschuster return (""); 2856e7801d59Ssowmini } 2857e7801d59Ssowmini break; 2858e7801d59Ssowmini case AGGR_S_OPKTDIST: 2859e7801d59Ssowmini if (is_port) { 2860e7801d59Ssowmini (void) snprintf(buf, sizeof (buf), "%-6.1f", 2861e7801d59Ssowmini (double)diff_stats.opackets/ 2862e7801d59Ssowmini (double)l->laggr_pktsumtot->opackets * 100); 2863e7801d59Ssowmini } else { 28640d365605Sschuster return (""); 2865e7801d59Ssowmini } 2866e7801d59Ssowmini break; 2867e7801d59Ssowmini } 2868e7801d59Ssowmini return (buf); 2869e7801d59Ssowmini 2870e7801d59Ssowmini err: 2871e7801d59Ssowmini *stat = status; 2872e7801d59Ssowmini buf[0] = '\0'; 2873e7801d59Ssowmini return (buf); 2874e7801d59Ssowmini } 2875e7801d59Ssowmini 2876d62bc4baSyz147064 static dladm_status_t 2877d62bc4baSyz147064 print_aggr_stats(show_grp_state_t *state, const char *link, 2878e7801d59Ssowmini dladm_aggr_grp_attr_t *ginfop) 2879d62bc4baSyz147064 { 2880d62bc4baSyz147064 dladm_phys_attr_t dpa; 2881d62bc4baSyz147064 dladm_aggr_port_attr_t *portp; 2882d62bc4baSyz147064 pktsum_t pktsumtot, port_stat; 2883d62bc4baSyz147064 dladm_status_t status; 2884d62bc4baSyz147064 int i; 2885e7801d59Ssowmini laggr_args_t largs; 28867c478bd9Sstevel@tonic-gate 28877c478bd9Sstevel@tonic-gate /* sum the ports statistics */ 28887c478bd9Sstevel@tonic-gate bzero(&pktsumtot, sizeof (pktsumtot)); 2889d62bc4baSyz147064 2890d62bc4baSyz147064 for (i = 0; i < ginfop->lg_nports; i++) { 2891d62bc4baSyz147064 2892d62bc4baSyz147064 portp = &(ginfop->lg_ports[i]); 28934ac67f02SAnurag S. Maskey if ((status = dladm_phys_info(handle, portp->lp_linkid, &dpa, 2894d62bc4baSyz147064 DLADM_OPT_ACTIVE)) != DLADM_STATUS_OK) { 2895d62bc4baSyz147064 goto done; 28967c478bd9Sstevel@tonic-gate } 28977c478bd9Sstevel@tonic-gate 2898d62bc4baSyz147064 get_mac_stats(dpa.dp_dev, &port_stat); 2899da14cebeSEric Cheng dladm_stats_total(&pktsumtot, &port_stat, 2900da14cebeSEric Cheng &state->gs_prevstats[i]); 29017c478bd9Sstevel@tonic-gate } 29027c478bd9Sstevel@tonic-gate 2903e7801d59Ssowmini if (!state->gs_parseable && !state->gs_printheader) { 2904e7801d59Ssowmini print_header(&state->gs_print); 2905e7801d59Ssowmini state->gs_printheader = B_TRUE; 2906e7801d59Ssowmini } 2907e7801d59Ssowmini 2908e7801d59Ssowmini largs.laggr_lport = -1; 2909e7801d59Ssowmini largs.laggr_link = link; 2910e7801d59Ssowmini largs.laggr_ginfop = ginfop; 2911e7801d59Ssowmini largs.laggr_status = &status; 2912e7801d59Ssowmini largs.laggr_pktsumtot = &pktsumtot; 2913e7801d59Ssowmini 2914e7801d59Ssowmini dladm_print_output(&state->gs_print, state->gs_parseable, 2915e7801d59Ssowmini print_aggr_stats_callback, &largs); 2916e7801d59Ssowmini 2917e7801d59Ssowmini if (status != DLADM_STATUS_OK) 2918e7801d59Ssowmini goto done; 2919d62bc4baSyz147064 2920d62bc4baSyz147064 for (i = 0; i < ginfop->lg_nports; i++) { 2921e7801d59Ssowmini largs.laggr_lport = i; 2922e7801d59Ssowmini largs.laggr_prevstats = &state->gs_prevstats[i]; 2923e7801d59Ssowmini dladm_print_output(&state->gs_print, state->gs_parseable, 2924e7801d59Ssowmini print_aggr_stats_callback, &largs); 2925e7801d59Ssowmini if (status != DLADM_STATUS_OK) 2926d62bc4baSyz147064 goto done; 2927d62bc4baSyz147064 } 2928d62bc4baSyz147064 2929d62bc4baSyz147064 status = DLADM_STATUS_OK; 2930d62bc4baSyz147064 done: 2931d62bc4baSyz147064 return (status); 2932d62bc4baSyz147064 } 2933d62bc4baSyz147064 2934d62bc4baSyz147064 static dladm_status_t 2935e7801d59Ssowmini print_aggr(show_grp_state_t *state, datalink_id_t linkid) 2936d62bc4baSyz147064 { 2937d62bc4baSyz147064 char link[MAXLINKNAMELEN]; 2938d62bc4baSyz147064 dladm_aggr_grp_attr_t ginfo; 2939d62bc4baSyz147064 uint32_t flags; 2940d62bc4baSyz147064 dladm_status_t status; 2941d62bc4baSyz147064 29425f5c9f54SAnurag S. Maskey bzero(&ginfo, sizeof (dladm_aggr_grp_attr_t)); 29434ac67f02SAnurag S. Maskey if ((status = dladm_datalink_id2info(handle, linkid, &flags, NULL, 29444ac67f02SAnurag S. Maskey NULL, link, MAXLINKNAMELEN)) != DLADM_STATUS_OK) { 2945d62bc4baSyz147064 return (status); 2946d62bc4baSyz147064 } 2947d62bc4baSyz147064 2948d62bc4baSyz147064 if (!(state->gs_flags & flags)) 2949d62bc4baSyz147064 return (DLADM_STATUS_NOTFOUND); 2950d62bc4baSyz147064 29514ac67f02SAnurag S. Maskey status = dladm_aggr_info(handle, linkid, &ginfo, state->gs_flags); 2952d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 2953d62bc4baSyz147064 return (status); 2954d62bc4baSyz147064 2955d62bc4baSyz147064 if (state->gs_lacp) 2956e7801d59Ssowmini status = print_aggr_lacp(state, link, &ginfo); 2957d62bc4baSyz147064 else if (state->gs_extended) 2958e7801d59Ssowmini status = print_aggr_extended(state, link, &ginfo); 2959d62bc4baSyz147064 else if (state->gs_stats) 2960e7801d59Ssowmini status = print_aggr_stats(state, link, &ginfo); 29614ac67f02SAnurag S. Maskey else 2962e7801d59Ssowmini status = print_aggr_info(state, link, &ginfo); 2963d62bc4baSyz147064 2964d62bc4baSyz147064 done: 2965d62bc4baSyz147064 free(ginfo.lg_ports); 2966d62bc4baSyz147064 return (status); 2967d62bc4baSyz147064 } 2968d62bc4baSyz147064 29694ac67f02SAnurag S. Maskey /* ARGSUSED */ 2970d62bc4baSyz147064 static int 29714ac67f02SAnurag S. Maskey show_aggr(dladm_handle_t dh, datalink_id_t linkid, void *arg) 2972d62bc4baSyz147064 { 2973d62bc4baSyz147064 show_grp_state_t *state = arg; 2974d62bc4baSyz147064 dladm_status_t status; 2975d62bc4baSyz147064 29764ac67f02SAnurag S. Maskey if ((status = print_aggr(state, linkid)) != DLADM_STATUS_OK) 2977d62bc4baSyz147064 goto done; 2978d62bc4baSyz147064 2979d62bc4baSyz147064 done: 2980d62bc4baSyz147064 state->gs_status = status; 2981d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 29827c478bd9Sstevel@tonic-gate } 29837c478bd9Sstevel@tonic-gate 29847c478bd9Sstevel@tonic-gate static void 29858d5c46e6Sam223141 do_show_link(int argc, char *argv[], const char *use) 29867c478bd9Sstevel@tonic-gate { 29877c478bd9Sstevel@tonic-gate int option; 29887c478bd9Sstevel@tonic-gate boolean_t s_arg = B_FALSE; 2989da14cebeSEric Cheng boolean_t S_arg = B_FALSE; 29907c478bd9Sstevel@tonic-gate boolean_t i_arg = B_FALSE; 2991d62bc4baSyz147064 uint32_t flags = DLADM_OPT_ACTIVE; 2992d62bc4baSyz147064 boolean_t p_arg = B_FALSE; 2993d62bc4baSyz147064 datalink_id_t linkid = DATALINK_ALL_LINKID; 2994da14cebeSEric Cheng char linkname[MAXLINKNAMELEN]; 2995*63a6526dSMichael Lim uint32_t interval = 0; 2996d62bc4baSyz147064 show_state_t state; 2997d62bc4baSyz147064 dladm_status_t status; 2998e7801d59Ssowmini boolean_t o_arg = B_FALSE; 2999e7801d59Ssowmini char *fields_str = NULL; 3000e7801d59Ssowmini print_field_t **fields; 3001e7801d59Ssowmini uint_t nfields; 3002e7801d59Ssowmini char *all_active_fields = "link,class,mtu,state,over"; 3003e7801d59Ssowmini char *all_inactive_fields = "link,class,over"; 30046be03d0bSVasumathi Sundaram - Sun Microsystems char *allstat_fields = 30056be03d0bSVasumathi Sundaram - Sun Microsystems "link,ipackets,rbytes,ierrors,opackets,obytes,oerrors"; 3006e7801d59Ssowmini 3007e7801d59Ssowmini bzero(&state, sizeof (state)); 30087c478bd9Sstevel@tonic-gate 30097c478bd9Sstevel@tonic-gate opterr = 0; 3010da14cebeSEric Cheng while ((option = getopt_long(argc, argv, ":pPsSi:o:", 3011d62bc4baSyz147064 show_lopts, NULL)) != -1) { 30127c478bd9Sstevel@tonic-gate switch (option) { 30137c478bd9Sstevel@tonic-gate case 'p': 3014d62bc4baSyz147064 if (p_arg) 3015d62bc4baSyz147064 die_optdup(option); 3016d62bc4baSyz147064 3017d62bc4baSyz147064 p_arg = B_TRUE; 30187c478bd9Sstevel@tonic-gate break; 30197c478bd9Sstevel@tonic-gate case 's': 302033343a97Smeem if (s_arg) 302133343a97Smeem die_optdup(option); 30227c478bd9Sstevel@tonic-gate 30237c478bd9Sstevel@tonic-gate s_arg = B_TRUE; 30247c478bd9Sstevel@tonic-gate break; 3025d62bc4baSyz147064 case 'P': 3026d62bc4baSyz147064 if (flags != DLADM_OPT_ACTIVE) 3027d62bc4baSyz147064 die_optdup(option); 3028d62bc4baSyz147064 3029d62bc4baSyz147064 flags = DLADM_OPT_PERSIST; 3030d62bc4baSyz147064 break; 3031da14cebeSEric Cheng case 'S': 3032da14cebeSEric Cheng if (S_arg) 3033da14cebeSEric Cheng die_optdup(option); 3034da14cebeSEric Cheng 3035da14cebeSEric Cheng S_arg = B_TRUE; 3036da14cebeSEric Cheng break; 3037e7801d59Ssowmini case 'o': 3038e7801d59Ssowmini o_arg = B_TRUE; 3039e7801d59Ssowmini fields_str = optarg; 3040e7801d59Ssowmini break; 30417c478bd9Sstevel@tonic-gate case 'i': 304233343a97Smeem if (i_arg) 304333343a97Smeem die_optdup(option); 30447c478bd9Sstevel@tonic-gate 30457c478bd9Sstevel@tonic-gate i_arg = B_TRUE; 3046*63a6526dSMichael Lim if (!dladm_str2interval(optarg, &interval)) 304733343a97Smeem die("invalid interval value '%s'", optarg); 30487c478bd9Sstevel@tonic-gate break; 30497c478bd9Sstevel@tonic-gate default: 30508d5c46e6Sam223141 die_opterr(optopt, option, use); 305133343a97Smeem break; 30527c478bd9Sstevel@tonic-gate } 30537c478bd9Sstevel@tonic-gate } 30547c478bd9Sstevel@tonic-gate 3055da14cebeSEric Cheng if (i_arg && !(s_arg || S_arg)) 3056da14cebeSEric Cheng die("the option -i can be used only with -s or -S"); 3057da14cebeSEric Cheng 3058da14cebeSEric Cheng if (s_arg && S_arg) 3059da14cebeSEric Cheng die("the -s option cannot be used with -S"); 30607c478bd9Sstevel@tonic-gate 30616be03d0bSVasumathi Sundaram - Sun Microsystems if (s_arg && flags != DLADM_OPT_ACTIVE) 30626be03d0bSVasumathi Sundaram - Sun Microsystems die("the option -P cannot be used with -s"); 3063d62bc4baSyz147064 3064da14cebeSEric Cheng if (S_arg && (p_arg || flags != DLADM_OPT_ACTIVE)) 3065da14cebeSEric Cheng die("the option -%c cannot be used with -S", p_arg ? 'p' : 'P'); 3066da14cebeSEric Cheng 30677c478bd9Sstevel@tonic-gate /* get link name (optional last argument) */ 3068d62bc4baSyz147064 if (optind == (argc-1)) { 3069d62bc4baSyz147064 uint32_t f; 3070d62bc4baSyz147064 3071da14cebeSEric Cheng if (strlcpy(linkname, argv[optind], MAXLINKNAMELEN) 3072da14cebeSEric Cheng >= MAXLINKNAMELEN) { 3073da14cebeSEric Cheng (void) fprintf(stderr, 3074da14cebeSEric Cheng gettext("%s: link name too long\n"), 3075da14cebeSEric Cheng progname); 30764ac67f02SAnurag S. Maskey dladm_close(handle); 3077da14cebeSEric Cheng exit(1); 3078da14cebeSEric Cheng } 30794ac67f02SAnurag S. Maskey if ((status = dladm_name2info(handle, linkname, &linkid, &f, 3080d62bc4baSyz147064 NULL, NULL)) != DLADM_STATUS_OK) { 3081da14cebeSEric Cheng die_dlerr(status, "link %s is not valid", linkname); 3082d62bc4baSyz147064 } 3083d62bc4baSyz147064 3084d62bc4baSyz147064 if (!(f & flags)) { 3085d62bc4baSyz147064 die_dlerr(DLADM_STATUS_BADARG, "link %s is %s", 3086d62bc4baSyz147064 argv[optind], flags == DLADM_OPT_PERSIST ? 3087d62bc4baSyz147064 "a temporary link" : "temporarily removed"); 3088d62bc4baSyz147064 } 3089d62bc4baSyz147064 } else if (optind != argc) { 30907c478bd9Sstevel@tonic-gate usage(); 3091d62bc4baSyz147064 } 30927c478bd9Sstevel@tonic-gate 30930d365605Sschuster if (p_arg && !o_arg) 30940d365605Sschuster die("-p requires -o"); 30950d365605Sschuster 3096da14cebeSEric Cheng if (S_arg) { 30974ac67f02SAnurag S. Maskey dladm_continuous(handle, linkid, NULL, interval, LINK_REPORT); 3098da14cebeSEric Cheng return; 3099da14cebeSEric Cheng } 3100da14cebeSEric Cheng 31010d365605Sschuster if (p_arg && strcasecmp(fields_str, "all") == 0) 31020d365605Sschuster die("\"-o all\" is invalid with -p"); 31030d365605Sschuster 3104e7801d59Ssowmini if (!o_arg || (o_arg && strcasecmp(fields_str, "all") == 0)) { 31056be03d0bSVasumathi Sundaram - Sun Microsystems if (s_arg) 31066be03d0bSVasumathi Sundaram - Sun Microsystems fields_str = allstat_fields; 31076be03d0bSVasumathi Sundaram - Sun Microsystems else if (flags & DLADM_OPT_ACTIVE) 3108e7801d59Ssowmini fields_str = all_active_fields; 3109e7801d59Ssowmini else 3110e7801d59Ssowmini fields_str = all_inactive_fields; 3111e7801d59Ssowmini } 3112e7801d59Ssowmini 31136be03d0bSVasumathi Sundaram - Sun Microsystems state.ls_parseable = p_arg; 31146be03d0bSVasumathi Sundaram - Sun Microsystems state.ls_flags = flags; 31156be03d0bSVasumathi Sundaram - Sun Microsystems state.ls_donefirst = B_FALSE; 31166be03d0bSVasumathi Sundaram - Sun Microsystems 31176be03d0bSVasumathi Sundaram - Sun Microsystems if (s_arg) { 31186be03d0bSVasumathi Sundaram - Sun Microsystems link_stats(linkid, interval, fields_str, &state); 31196be03d0bSVasumathi Sundaram - Sun Microsystems return; 31206be03d0bSVasumathi Sundaram - Sun Microsystems } 31216be03d0bSVasumathi Sundaram - Sun Microsystems 3122e7801d59Ssowmini fields = parse_output_fields(fields_str, link_fields, DEV_LINK_FIELDS, 3123e7801d59Ssowmini CMD_TYPE_ANY, &nfields); 3124e7801d59Ssowmini 31250d365605Sschuster if (fields == NULL) 3126e7801d59Ssowmini die("invalid field(s) specified"); 3127e7801d59Ssowmini 3128e7801d59Ssowmini state.ls_print.ps_fields = fields; 3129e7801d59Ssowmini state.ls_print.ps_nfields = nfields; 3130e7801d59Ssowmini 3131d62bc4baSyz147064 if (linkid == DATALINK_ALL_LINKID) { 31324ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(show_link, handle, &state, 3133d62bc4baSyz147064 DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE, flags); 3134210db224Sericheng } else { 31354ac67f02SAnurag S. Maskey (void) show_link(handle, linkid, &state); 3136d62bc4baSyz147064 if (state.ls_status != DLADM_STATUS_OK) { 3137d62bc4baSyz147064 die_dlerr(state.ls_status, "failed to show link %s", 3138d62bc4baSyz147064 argv[optind]); 3139d62bc4baSyz147064 } 31407c478bd9Sstevel@tonic-gate } 3141210db224Sericheng } 31427c478bd9Sstevel@tonic-gate 31437c478bd9Sstevel@tonic-gate static void 31448d5c46e6Sam223141 do_show_aggr(int argc, char *argv[], const char *use) 31457c478bd9Sstevel@tonic-gate { 31467c478bd9Sstevel@tonic-gate boolean_t L_arg = B_FALSE; 31477c478bd9Sstevel@tonic-gate boolean_t s_arg = B_FALSE; 31487c478bd9Sstevel@tonic-gate boolean_t i_arg = B_FALSE; 3149d62bc4baSyz147064 boolean_t p_arg = B_FALSE; 3150d62bc4baSyz147064 boolean_t x_arg = B_FALSE; 31517c478bd9Sstevel@tonic-gate show_grp_state_t state; 3152d62bc4baSyz147064 uint32_t flags = DLADM_OPT_ACTIVE; 3153d62bc4baSyz147064 datalink_id_t linkid = DATALINK_ALL_LINKID; 3154d62bc4baSyz147064 int option; 3155*63a6526dSMichael Lim uint32_t interval = 0; 3156d62bc4baSyz147064 int key; 3157d62bc4baSyz147064 dladm_status_t status; 3158e7801d59Ssowmini boolean_t o_arg = B_FALSE; 3159e7801d59Ssowmini char *fields_str = NULL; 3160e7801d59Ssowmini print_field_t **fields; 3161e7801d59Ssowmini uint_t nfields; 3162e7801d59Ssowmini char *all_fields = 3163e7801d59Ssowmini "link,policy,addrpolicy,lacpactivity,lacptimer,flags"; 3164e7801d59Ssowmini char *all_lacp_fields = 3165e7801d59Ssowmini "link,port,aggregatable,sync,coll,dist,defaulted,expired"; 3166e7801d59Ssowmini char *all_stats_fields = 3167e7801d59Ssowmini "link,port,ipackets,rbytes,opackets,obytes,ipktdist,opktdist"; 3168e7801d59Ssowmini char *all_extended_fields = 3169e7801d59Ssowmini "link,port,speed,duplex,state,address,portstate"; 3170e7801d59Ssowmini print_field_t *pf; 3171e7801d59Ssowmini int pfmax; 3172e7801d59Ssowmini 3173e7801d59Ssowmini bzero(&state, sizeof (state)); 31747c478bd9Sstevel@tonic-gate 31757c478bd9Sstevel@tonic-gate opterr = 0; 3176e7801d59Ssowmini while ((option = getopt_long(argc, argv, ":LpPxsi:o:", 3177d62bc4baSyz147064 show_lopts, NULL)) != -1) { 31787c478bd9Sstevel@tonic-gate switch (option) { 31797c478bd9Sstevel@tonic-gate case 'L': 318033343a97Smeem if (L_arg) 318133343a97Smeem die_optdup(option); 31827c478bd9Sstevel@tonic-gate 31837c478bd9Sstevel@tonic-gate L_arg = B_TRUE; 31847c478bd9Sstevel@tonic-gate break; 31857c478bd9Sstevel@tonic-gate case 'p': 3186d62bc4baSyz147064 if (p_arg) 3187d62bc4baSyz147064 die_optdup(option); 3188d62bc4baSyz147064 3189d62bc4baSyz147064 p_arg = B_TRUE; 3190d62bc4baSyz147064 break; 3191d62bc4baSyz147064 case 'x': 3192d62bc4baSyz147064 if (x_arg) 3193d62bc4baSyz147064 die_optdup(option); 3194d62bc4baSyz147064 3195d62bc4baSyz147064 x_arg = B_TRUE; 3196d62bc4baSyz147064 break; 3197d62bc4baSyz147064 case 'P': 3198d62bc4baSyz147064 if (flags != DLADM_OPT_ACTIVE) 3199d62bc4baSyz147064 die_optdup(option); 3200d62bc4baSyz147064 3201d62bc4baSyz147064 flags = DLADM_OPT_PERSIST; 32027c478bd9Sstevel@tonic-gate break; 32037c478bd9Sstevel@tonic-gate case 's': 320433343a97Smeem if (s_arg) 320533343a97Smeem die_optdup(option); 32067c478bd9Sstevel@tonic-gate 32077c478bd9Sstevel@tonic-gate s_arg = B_TRUE; 32087c478bd9Sstevel@tonic-gate break; 3209e7801d59Ssowmini case 'o': 3210e7801d59Ssowmini o_arg = B_TRUE; 3211e7801d59Ssowmini fields_str = optarg; 3212e7801d59Ssowmini break; 32137c478bd9Sstevel@tonic-gate case 'i': 321433343a97Smeem if (i_arg) 321533343a97Smeem die_optdup(option); 32167c478bd9Sstevel@tonic-gate 32177c478bd9Sstevel@tonic-gate i_arg = B_TRUE; 3218*63a6526dSMichael Lim if (!dladm_str2interval(optarg, &interval)) 321933343a97Smeem die("invalid interval value '%s'", optarg); 32207c478bd9Sstevel@tonic-gate break; 32217c478bd9Sstevel@tonic-gate default: 32228d5c46e6Sam223141 die_opterr(optopt, option, use); 322333343a97Smeem break; 32247c478bd9Sstevel@tonic-gate } 32257c478bd9Sstevel@tonic-gate } 32267c478bd9Sstevel@tonic-gate 32270d365605Sschuster if (p_arg && !o_arg) 32280d365605Sschuster die("-p requires -o"); 32290d365605Sschuster 32300d365605Sschuster if (p_arg && strcasecmp(fields_str, "all") == 0) 32310d365605Sschuster die("\"-o all\" is invalid with -p"); 32320d365605Sschuster 323333343a97Smeem if (i_arg && !s_arg) 323433343a97Smeem die("the option -i can be used only with -s"); 32357c478bd9Sstevel@tonic-gate 3236d62bc4baSyz147064 if (s_arg && (L_arg || p_arg || x_arg || flags != DLADM_OPT_ACTIVE)) { 3237d62bc4baSyz147064 die("the option -%c cannot be used with -s", 3238d62bc4baSyz147064 L_arg ? 'L' : (p_arg ? 'p' : (x_arg ? 'x' : 'P'))); 3239d62bc4baSyz147064 } 3240d62bc4baSyz147064 3241d62bc4baSyz147064 if (L_arg && flags != DLADM_OPT_ACTIVE) 3242d62bc4baSyz147064 die("the option -P cannot be used with -L"); 3243d62bc4baSyz147064 3244d62bc4baSyz147064 if (x_arg && (L_arg || flags != DLADM_OPT_ACTIVE)) 3245d62bc4baSyz147064 die("the option -%c cannot be used with -x", L_arg ? 'L' : 'P'); 3246d62bc4baSyz147064 3247d62bc4baSyz147064 /* get aggregation key or aggrname (optional last argument) */ 32487c478bd9Sstevel@tonic-gate if (optind == (argc-1)) { 3249d62bc4baSyz147064 if (!str2int(argv[optind], &key)) { 32504ac67f02SAnurag S. Maskey status = dladm_name2info(handle, argv[optind], 32514ac67f02SAnurag S. Maskey &linkid, NULL, NULL, NULL); 3252d62bc4baSyz147064 } else { 32534ac67f02SAnurag S. Maskey status = dladm_key2linkid(handle, (uint16_t)key, 3254d62bc4baSyz147064 &linkid, DLADM_OPT_ACTIVE); 3255d62bc4baSyz147064 } 3256d62bc4baSyz147064 3257d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 3258d62bc4baSyz147064 die("non-existent aggregation '%s'", argv[optind]); 3259d62bc4baSyz147064 32607c478bd9Sstevel@tonic-gate } else if (optind != argc) { 32617c478bd9Sstevel@tonic-gate usage(); 32627c478bd9Sstevel@tonic-gate } 32637c478bd9Sstevel@tonic-gate 3264d62bc4baSyz147064 bzero(&state, sizeof (state)); 3265d62bc4baSyz147064 state.gs_lacp = L_arg; 3266d62bc4baSyz147064 state.gs_stats = s_arg; 3267d62bc4baSyz147064 state.gs_flags = flags; 3268d62bc4baSyz147064 state.gs_parseable = p_arg; 3269d62bc4baSyz147064 state.gs_extended = x_arg; 3270d62bc4baSyz147064 3271e7801d59Ssowmini if (!o_arg || (o_arg && strcasecmp(fields_str, "all") == 0)) { 3272e7801d59Ssowmini if (state.gs_lacp) 3273e7801d59Ssowmini fields_str = all_lacp_fields; 3274e7801d59Ssowmini else if (state.gs_stats) 3275e7801d59Ssowmini fields_str = all_stats_fields; 3276e7801d59Ssowmini else if (state.gs_extended) 3277e7801d59Ssowmini fields_str = all_extended_fields; 3278e7801d59Ssowmini else 3279e7801d59Ssowmini fields_str = all_fields; 3280e7801d59Ssowmini } 3281e7801d59Ssowmini 3282e7801d59Ssowmini if (state.gs_lacp) { 3283e7801d59Ssowmini pf = aggr_l_fields; 3284e7801d59Ssowmini pfmax = AGGR_L_MAX_FIELDS; 3285e7801d59Ssowmini } else if (state.gs_stats) { 3286e7801d59Ssowmini pf = aggr_s_fields; 3287e7801d59Ssowmini pfmax = AGGR_S_MAX_FIELDS; 3288e7801d59Ssowmini } else if (state.gs_extended) { 3289e7801d59Ssowmini pf = aggr_x_fields; 3290e7801d59Ssowmini pfmax = AGGR_X_MAX_FIELDS; 3291e7801d59Ssowmini } else { 3292e7801d59Ssowmini pf = laggr_fields; 3293e7801d59Ssowmini pfmax = LAGGR_MAX_FIELDS; 3294e7801d59Ssowmini } 3295e7801d59Ssowmini fields = parse_output_fields(fields_str, pf, pfmax, CMD_TYPE_ANY, 3296e7801d59Ssowmini &nfields); 3297e7801d59Ssowmini 3298e7801d59Ssowmini if (fields == NULL) { 3299e7801d59Ssowmini die("invalid field(s) specified"); 3300e7801d59Ssowmini return; 3301e7801d59Ssowmini } 3302e7801d59Ssowmini 3303e7801d59Ssowmini state.gs_print.ps_fields = fields; 3304e7801d59Ssowmini state.gs_print.ps_nfields = nfields; 3305e7801d59Ssowmini 33067c478bd9Sstevel@tonic-gate if (s_arg) { 3307d62bc4baSyz147064 aggr_stats(linkid, &state, interval); 33087c478bd9Sstevel@tonic-gate return; 33097c478bd9Sstevel@tonic-gate } 33107c478bd9Sstevel@tonic-gate 3311d62bc4baSyz147064 if (linkid == DATALINK_ALL_LINKID) { 33124ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(show_aggr, handle, &state, 3313d62bc4baSyz147064 DATALINK_CLASS_AGGR, DATALINK_ANY_MEDIATYPE, flags); 3314d62bc4baSyz147064 } else { 33154ac67f02SAnurag S. Maskey (void) show_aggr(handle, linkid, &state); 3316d62bc4baSyz147064 if (state.gs_status != DLADM_STATUS_OK) { 3317d62bc4baSyz147064 die_dlerr(state.gs_status, "failed to show aggr %s", 3318d62bc4baSyz147064 argv[optind]); 3319d62bc4baSyz147064 } 3320d62bc4baSyz147064 } 33217c478bd9Sstevel@tonic-gate } 33227c478bd9Sstevel@tonic-gate 3323da14cebeSEric Cheng static dladm_status_t 3324da14cebeSEric Cheng print_phys_default(show_state_t *state, datalink_id_t linkid, 3325da14cebeSEric Cheng const char *link, uint32_t flags, uint32_t media) 33267c478bd9Sstevel@tonic-gate { 3327da14cebeSEric Cheng dladm_phys_attr_t dpa; 3328da14cebeSEric Cheng dladm_status_t status; 3329da14cebeSEric Cheng link_fields_buf_t pattr; 3330e7801d59Ssowmini 33314ac67f02SAnurag S. Maskey status = dladm_phys_info(handle, linkid, &dpa, state->ls_flags); 3332da14cebeSEric Cheng if (status != DLADM_STATUS_OK) 3333da14cebeSEric Cheng goto done; 33347c478bd9Sstevel@tonic-gate 3335da14cebeSEric Cheng (void) snprintf(pattr.link_phys_device, 3336da14cebeSEric Cheng sizeof (pattr.link_phys_device), "%s", dpa.dp_dev); 3337da14cebeSEric Cheng (void) dladm_media2str(media, pattr.link_phys_media); 3338da14cebeSEric Cheng if (state->ls_flags == DLADM_OPT_ACTIVE) { 3339da14cebeSEric Cheng boolean_t islink; 3340d62bc4baSyz147064 3341da14cebeSEric Cheng if (!dpa.dp_novanity) { 3342da14cebeSEric Cheng (void) strlcpy(pattr.link_name, link, 3343da14cebeSEric Cheng sizeof (pattr.link_name)); 3344da14cebeSEric Cheng islink = B_TRUE; 3345d62bc4baSyz147064 } else { 3346da14cebeSEric Cheng /* 3347da14cebeSEric Cheng * This is a physical link that does not have 3348da14cebeSEric Cheng * vanity naming support. 3349da14cebeSEric Cheng */ 3350da14cebeSEric Cheng (void) strlcpy(pattr.link_name, dpa.dp_dev, 3351da14cebeSEric Cheng sizeof (pattr.link_name)); 3352da14cebeSEric Cheng islink = B_FALSE; 33537c478bd9Sstevel@tonic-gate } 33547c478bd9Sstevel@tonic-gate 3355da14cebeSEric Cheng (void) get_linkstate(pattr.link_name, islink, 3356da14cebeSEric Cheng pattr.link_phys_state); 3357da14cebeSEric Cheng (void) snprintf(pattr.link_phys_speed, 3358da14cebeSEric Cheng sizeof (pattr.link_phys_speed), "%u", 3359da14cebeSEric Cheng (uint_t)((get_ifspeed(pattr.link_name, 3360da14cebeSEric Cheng islink)) / 1000000ull)); 3361da14cebeSEric Cheng (void) get_linkduplex(pattr.link_name, islink, 3362da14cebeSEric Cheng pattr.link_phys_duplex); 3363da14cebeSEric Cheng } else { 3364da14cebeSEric Cheng (void) snprintf(pattr.link_name, sizeof (pattr.link_name), 3365da14cebeSEric Cheng "%s", link); 3366da14cebeSEric Cheng (void) snprintf(pattr.link_flags, sizeof (pattr.link_flags), 3367da14cebeSEric Cheng "%c----", flags & DLADM_OPT_ACTIVE ? '-' : 'r'); 3368da14cebeSEric Cheng } 3369da14cebeSEric Cheng 3370da14cebeSEric Cheng if (!state->ls_parseable && !state->ls_printheader) { 3371da14cebeSEric Cheng print_header(&state->ls_print); 3372da14cebeSEric Cheng state->ls_printheader = B_TRUE; 3373da14cebeSEric Cheng } 3374da14cebeSEric Cheng 3375da14cebeSEric Cheng dladm_print_output(&state->ls_print, state->ls_parseable, 3376da14cebeSEric Cheng dladm_print_field, (void *)&pattr); 3377da14cebeSEric Cheng 3378da14cebeSEric Cheng done: 3379da14cebeSEric Cheng return (status); 3380da14cebeSEric Cheng } 3381da14cebeSEric Cheng 3382da14cebeSEric Cheng typedef struct { 3383da14cebeSEric Cheng show_state_t *ms_state; 3384da14cebeSEric Cheng char *ms_link; 3385da14cebeSEric Cheng dladm_macaddr_attr_t *ms_mac_attr; 3386da14cebeSEric Cheng } print_phys_mac_state_t; 3387da14cebeSEric Cheng 3388da14cebeSEric Cheng /* callback of dladm_print_output() */ 3389da14cebeSEric Cheng static char * 3390da14cebeSEric Cheng print_phys_one_mac_callback(print_field_t *pf, void *arg) 3391da14cebeSEric Cheng { 3392da14cebeSEric Cheng print_phys_mac_state_t *mac_state = arg; 3393da14cebeSEric Cheng dladm_macaddr_attr_t *attr = mac_state->ms_mac_attr; 3394da14cebeSEric Cheng static char buf[DLADM_STRSIZE]; 3395da14cebeSEric Cheng boolean_t is_primary = (attr->ma_slot == 0); 3396da14cebeSEric Cheng boolean_t is_parseable = mac_state->ms_state->ls_parseable; 3397da14cebeSEric Cheng 3398da14cebeSEric Cheng switch (pf->pf_index) { 3399da14cebeSEric Cheng case PHYS_M_LINK: 3400da14cebeSEric Cheng (void) snprintf(buf, sizeof (buf), "%s", 3401da14cebeSEric Cheng (is_primary || is_parseable) ? mac_state->ms_link : " "); 3402da14cebeSEric Cheng break; 3403da14cebeSEric Cheng case PHYS_M_SLOT: 3404da14cebeSEric Cheng if (is_primary) 3405da14cebeSEric Cheng (void) snprintf(buf, sizeof (buf), gettext("primary")); 3406da14cebeSEric Cheng else 3407da14cebeSEric Cheng (void) snprintf(buf, sizeof (buf), "%d", attr->ma_slot); 3408da14cebeSEric Cheng break; 3409da14cebeSEric Cheng case PHYS_M_ADDRESS: 3410da14cebeSEric Cheng (void) dladm_aggr_macaddr2str(attr->ma_addr, buf); 3411da14cebeSEric Cheng break; 3412da14cebeSEric Cheng case PHYS_M_INUSE: 3413da14cebeSEric Cheng (void) snprintf(buf, sizeof (buf), "%s", 3414da14cebeSEric Cheng attr->ma_flags & DLADM_MACADDR_USED ? gettext("yes") : 3415da14cebeSEric Cheng gettext("no")); 3416da14cebeSEric Cheng break; 3417da14cebeSEric Cheng case PHYS_M_CLIENT: 3418da14cebeSEric Cheng /* 3419da14cebeSEric Cheng * CR 6678526: resolve link id to actual link name if 3420da14cebeSEric Cheng * it is valid. 3421da14cebeSEric Cheng */ 3422da14cebeSEric Cheng (void) snprintf(buf, sizeof (buf), "%s", attr->ma_client_name); 3423da14cebeSEric Cheng break; 3424da14cebeSEric Cheng } 3425da14cebeSEric Cheng 3426da14cebeSEric Cheng return (buf); 3427da14cebeSEric Cheng } 3428da14cebeSEric Cheng 3429da14cebeSEric Cheng typedef struct { 3430da14cebeSEric Cheng show_state_t *hs_state; 3431da14cebeSEric Cheng char *hs_link; 3432da14cebeSEric Cheng dladm_hwgrp_attr_t *hs_grp_attr; 3433da14cebeSEric Cheng } print_phys_hwgrp_state_t; 3434da14cebeSEric Cheng 3435da14cebeSEric Cheng static char * 3436da14cebeSEric Cheng print_phys_one_hwgrp_callback(print_field_t *pf, void *arg) 3437da14cebeSEric Cheng { 3438da14cebeSEric Cheng print_phys_hwgrp_state_t *hg_state = arg; 3439da14cebeSEric Cheng dladm_hwgrp_attr_t *attr = hg_state->hs_grp_attr; 3440da14cebeSEric Cheng static char buf[DLADM_STRSIZE]; 3441da14cebeSEric Cheng 3442da14cebeSEric Cheng switch (pf->pf_index) { 3443da14cebeSEric Cheng case PHYS_H_LINK: 3444da14cebeSEric Cheng (void) snprintf(buf, sizeof (buf), "%s", attr->hg_link_name); 3445da14cebeSEric Cheng break; 3446da14cebeSEric Cheng case PHYS_H_GROUP: 3447da14cebeSEric Cheng (void) snprintf(buf, sizeof (buf), "%d", attr->hg_grp_num); 3448da14cebeSEric Cheng break; 3449da14cebeSEric Cheng case PHYS_H_GRPTYPE: 3450da14cebeSEric Cheng (void) snprintf(buf, sizeof (buf), "%s", 3451da14cebeSEric Cheng attr->hg_grp_type == DLADM_HWGRP_TYPE_RX ? "RX" : "TX"); 3452da14cebeSEric Cheng break; 3453da14cebeSEric Cheng case PHYS_H_RINGS: 3454da14cebeSEric Cheng (void) snprintf(buf, sizeof (buf), "%d", attr->hg_n_rings); 3455da14cebeSEric Cheng break; 3456da14cebeSEric Cheng case PHYS_H_CLIENTS: 3457da14cebeSEric Cheng if (attr->hg_client_names[0] == '\0') { 3458da14cebeSEric Cheng (void) snprintf(buf, sizeof (buf), "--"); 3459da14cebeSEric Cheng } else { 3460da14cebeSEric Cheng (void) snprintf(buf, sizeof (buf), "%s ", 3461da14cebeSEric Cheng attr->hg_client_names); 3462da14cebeSEric Cheng } 3463da14cebeSEric Cheng break; 3464da14cebeSEric Cheng } 3465da14cebeSEric Cheng 3466da14cebeSEric Cheng return (buf); 3467da14cebeSEric Cheng } 3468da14cebeSEric Cheng 3469da14cebeSEric Cheng /* callback of dladm_walk_macaddr, invoked for each MAC address slot */ 3470da14cebeSEric Cheng static boolean_t 3471da14cebeSEric Cheng print_phys_mac_callback(void *arg, dladm_macaddr_attr_t *attr) 3472da14cebeSEric Cheng { 3473da14cebeSEric Cheng print_phys_mac_state_t *mac_state = arg; 3474da14cebeSEric Cheng show_state_t *state = mac_state->ms_state; 3475da14cebeSEric Cheng 3476da14cebeSEric Cheng if (!state->ls_parseable && !state->ls_printheader) { 3477da14cebeSEric Cheng print_header(&state->ls_print); 3478da14cebeSEric Cheng state->ls_printheader = B_TRUE; 3479da14cebeSEric Cheng } 3480da14cebeSEric Cheng 3481da14cebeSEric Cheng mac_state->ms_mac_attr = attr; 3482da14cebeSEric Cheng dladm_print_output(&state->ls_print, state->ls_parseable, 3483da14cebeSEric Cheng print_phys_one_mac_callback, mac_state); 3484da14cebeSEric Cheng 3485da14cebeSEric Cheng return (B_TRUE); 3486da14cebeSEric Cheng } 3487da14cebeSEric Cheng 3488da14cebeSEric Cheng /* invoked by show-phys -m for each physical data-link */ 3489da14cebeSEric Cheng static dladm_status_t 3490da14cebeSEric Cheng print_phys_mac(show_state_t *state, datalink_id_t linkid, char *link) 3491da14cebeSEric Cheng { 3492da14cebeSEric Cheng print_phys_mac_state_t mac_state; 3493da14cebeSEric Cheng 3494da14cebeSEric Cheng mac_state.ms_state = state; 3495da14cebeSEric Cheng mac_state.ms_link = link; 3496da14cebeSEric Cheng 34974ac67f02SAnurag S. Maskey return (dladm_walk_macaddr(handle, linkid, &mac_state, 3498da14cebeSEric Cheng print_phys_mac_callback)); 3499da14cebeSEric Cheng } 3500da14cebeSEric Cheng 3501da14cebeSEric Cheng /* callback of dladm_walk_hwgrp, invoked for each MAC hwgrp */ 3502da14cebeSEric Cheng static boolean_t 3503da14cebeSEric Cheng print_phys_hwgrp_callback(void *arg, dladm_hwgrp_attr_t *attr) 3504da14cebeSEric Cheng { 3505da14cebeSEric Cheng print_phys_hwgrp_state_t *hwgrp_state = arg; 3506da14cebeSEric Cheng show_state_t *state = hwgrp_state->hs_state; 3507da14cebeSEric Cheng 3508da14cebeSEric Cheng if (!state->ls_parseable && !state->ls_printheader) { 3509da14cebeSEric Cheng print_header(&state->ls_print); 3510da14cebeSEric Cheng state->ls_printheader = B_TRUE; 3511da14cebeSEric Cheng } 3512da14cebeSEric Cheng hwgrp_state->hs_grp_attr = attr; 3513da14cebeSEric Cheng dladm_print_output(&state->ls_print, state->ls_parseable, 3514da14cebeSEric Cheng print_phys_one_hwgrp_callback, hwgrp_state); 3515da14cebeSEric Cheng 3516da14cebeSEric Cheng return (B_TRUE); 3517da14cebeSEric Cheng } 3518da14cebeSEric Cheng 3519da14cebeSEric Cheng /* invoked by show-phys -H for each physical data-link */ 3520da14cebeSEric Cheng static dladm_status_t 3521da14cebeSEric Cheng print_phys_hwgrp(show_state_t *state, datalink_id_t linkid, char *link) 3522da14cebeSEric Cheng { 3523da14cebeSEric Cheng print_phys_hwgrp_state_t hwgrp_state; 3524da14cebeSEric Cheng 3525da14cebeSEric Cheng hwgrp_state.hs_state = state; 3526da14cebeSEric Cheng hwgrp_state.hs_link = link; 35274ac67f02SAnurag S. Maskey return (dladm_walk_hwgrp(handle, linkid, &hwgrp_state, 3528da14cebeSEric Cheng print_phys_hwgrp_callback)); 3529da14cebeSEric Cheng } 3530d62bc4baSyz147064 3531d62bc4baSyz147064 static dladm_status_t 3532da14cebeSEric Cheng print_phys(show_state_t *state, datalink_id_t linkid) 3533d62bc4baSyz147064 { 3534d62bc4baSyz147064 char link[MAXLINKNAMELEN]; 3535d62bc4baSyz147064 uint32_t flags; 3536da14cebeSEric Cheng dladm_status_t status; 3537d62bc4baSyz147064 datalink_class_t class; 3538d62bc4baSyz147064 uint32_t media; 3539d62bc4baSyz147064 35404ac67f02SAnurag S. Maskey if ((status = dladm_datalink_id2info(handle, linkid, &flags, &class, 35414ac67f02SAnurag S. Maskey &media, link, MAXLINKNAMELEN)) != DLADM_STATUS_OK) { 3542d62bc4baSyz147064 goto done; 3543d62bc4baSyz147064 } 3544d62bc4baSyz147064 3545d62bc4baSyz147064 if (class != DATALINK_CLASS_PHYS) { 3546d62bc4baSyz147064 status = DLADM_STATUS_BADARG; 3547d62bc4baSyz147064 goto done; 3548d62bc4baSyz147064 } 3549d62bc4baSyz147064 3550d62bc4baSyz147064 if (!(state->ls_flags & flags)) { 3551d62bc4baSyz147064 status = DLADM_STATUS_NOTFOUND; 3552d62bc4baSyz147064 goto done; 3553d62bc4baSyz147064 } 3554d62bc4baSyz147064 3555da14cebeSEric Cheng if (state->ls_mac) 3556da14cebeSEric Cheng status = print_phys_mac(state, linkid, link); 3557da14cebeSEric Cheng else if (state->ls_hwgrp) 3558da14cebeSEric Cheng status = print_phys_hwgrp(state, linkid, link); 3559da14cebeSEric Cheng else 3560da14cebeSEric Cheng status = print_phys_default(state, linkid, link, flags, media); 3561d62bc4baSyz147064 3562d62bc4baSyz147064 done: 3563d62bc4baSyz147064 return (status); 3564d62bc4baSyz147064 } 3565d62bc4baSyz147064 35664ac67f02SAnurag S. Maskey /* ARGSUSED */ 3567d62bc4baSyz147064 static int 35684ac67f02SAnurag S. Maskey show_phys(dladm_handle_t dh, datalink_id_t linkid, void *arg) 3569d62bc4baSyz147064 { 3570d62bc4baSyz147064 show_state_t *state = arg; 3571d62bc4baSyz147064 3572da14cebeSEric Cheng state->ls_status = print_phys(state, linkid); 3573d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 3574d62bc4baSyz147064 } 3575d62bc4baSyz147064 3576d62bc4baSyz147064 /* 3577d62bc4baSyz147064 * Print the active topology information. 3578d62bc4baSyz147064 */ 3579d62bc4baSyz147064 static dladm_status_t 3580e7801d59Ssowmini print_vlan(show_state_t *state, datalink_id_t linkid, link_fields_buf_t *l) 3581d62bc4baSyz147064 { 3582d62bc4baSyz147064 dladm_vlan_attr_t vinfo; 3583d62bc4baSyz147064 uint32_t flags; 3584d62bc4baSyz147064 dladm_status_t status; 3585d62bc4baSyz147064 35864ac67f02SAnurag S. Maskey if ((status = dladm_datalink_id2info(handle, linkid, &flags, NULL, NULL, 3587e7801d59Ssowmini l->link_name, sizeof (l->link_name))) != DLADM_STATUS_OK) { 3588d62bc4baSyz147064 goto done; 3589d62bc4baSyz147064 } 3590d62bc4baSyz147064 3591d62bc4baSyz147064 if (!(state->ls_flags & flags)) { 3592d62bc4baSyz147064 status = DLADM_STATUS_NOTFOUND; 3593d62bc4baSyz147064 goto done; 3594d62bc4baSyz147064 } 3595d62bc4baSyz147064 35964ac67f02SAnurag S. Maskey if ((status = dladm_vlan_info(handle, linkid, &vinfo, 35974ac67f02SAnurag S. Maskey state->ls_flags)) != DLADM_STATUS_OK || 35984ac67f02SAnurag S. Maskey (status = dladm_datalink_id2info(handle, vinfo.dv_linkid, NULL, 35994ac67f02SAnurag S. Maskey NULL, NULL, l->link_over, sizeof (l->link_over))) != 36004ac67f02SAnurag S. Maskey DLADM_STATUS_OK) { 3601d62bc4baSyz147064 goto done; 3602d62bc4baSyz147064 } 3603d62bc4baSyz147064 3604e7801d59Ssowmini (void) snprintf(l->link_vlan_vid, sizeof (l->link_vlan_vid), "%d", 3605e7801d59Ssowmini vinfo.dv_vid); 3606da14cebeSEric Cheng (void) snprintf(l->link_flags, sizeof (l->link_flags), "%c----", 3607da14cebeSEric Cheng vinfo.dv_force ? 'f' : '-'); 3608d62bc4baSyz147064 3609d62bc4baSyz147064 done: 3610d62bc4baSyz147064 return (status); 3611d62bc4baSyz147064 } 3612d62bc4baSyz147064 36134ac67f02SAnurag S. Maskey /* ARGSUSED */ 3614d62bc4baSyz147064 static int 36154ac67f02SAnurag S. Maskey show_vlan(dladm_handle_t dh, datalink_id_t linkid, void *arg) 3616d62bc4baSyz147064 { 3617d62bc4baSyz147064 show_state_t *state = arg; 3618d62bc4baSyz147064 dladm_status_t status; 3619e7801d59Ssowmini link_fields_buf_t lbuf; 3620d62bc4baSyz147064 36215f5c9f54SAnurag S. Maskey bzero(&lbuf, sizeof (link_fields_buf_t)); 3622e7801d59Ssowmini status = print_vlan(state, linkid, &lbuf); 3623d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 3624d62bc4baSyz147064 goto done; 3625e7801d59Ssowmini 3626e7801d59Ssowmini if (!state->ls_parseable && !state->ls_printheader) { 3627e7801d59Ssowmini print_header(&state->ls_print); 3628e7801d59Ssowmini state->ls_printheader = B_TRUE; 3629e7801d59Ssowmini } 3630e7801d59Ssowmini 3631e7801d59Ssowmini dladm_print_output(&state->ls_print, state->ls_parseable, 3632e7801d59Ssowmini dladm_print_field, (void *)&lbuf); 3633d62bc4baSyz147064 3634d62bc4baSyz147064 done: 3635d62bc4baSyz147064 state->ls_status = status; 3636d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 3637d62bc4baSyz147064 } 3638d62bc4baSyz147064 3639d62bc4baSyz147064 static void 36408d5c46e6Sam223141 do_show_phys(int argc, char *argv[], const char *use) 3641d62bc4baSyz147064 { 3642d62bc4baSyz147064 int option; 3643d62bc4baSyz147064 uint32_t flags = DLADM_OPT_ACTIVE; 3644d62bc4baSyz147064 boolean_t p_arg = B_FALSE; 3645e7801d59Ssowmini boolean_t o_arg = B_FALSE; 3646da14cebeSEric Cheng boolean_t m_arg = B_FALSE; 3647da14cebeSEric Cheng boolean_t H_arg = B_FALSE; 3648d62bc4baSyz147064 datalink_id_t linkid = DATALINK_ALL_LINKID; 3649d62bc4baSyz147064 show_state_t state; 3650d62bc4baSyz147064 dladm_status_t status; 3651e7801d59Ssowmini char *fields_str = NULL; 3652e7801d59Ssowmini print_field_t **fields; 3653e7801d59Ssowmini uint_t nfields; 3654e7801d59Ssowmini char *all_active_fields = 3655e7801d59Ssowmini "link,media,state,speed,duplex,device"; 36565f5c9f54SAnurag S. Maskey char *all_inactive_fields = "link,device,media,flags"; 3657da14cebeSEric Cheng char *all_mac_fields = "link,slot,address,inuse,client"; 3658da14cebeSEric Cheng char *all_hwgrp_fields = 3659da14cebeSEric Cheng "link,group,grouptype,rings,clients"; 3660da14cebeSEric Cheng print_field_t *pf; 3661da14cebeSEric Cheng int pfmax; 3662d62bc4baSyz147064 3663e7801d59Ssowmini bzero(&state, sizeof (state)); 3664d62bc4baSyz147064 opterr = 0; 3665da14cebeSEric Cheng while ((option = getopt_long(argc, argv, ":pPo:mH", 3666d62bc4baSyz147064 show_lopts, NULL)) != -1) { 3667d62bc4baSyz147064 switch (option) { 3668d62bc4baSyz147064 case 'p': 3669d62bc4baSyz147064 if (p_arg) 3670d62bc4baSyz147064 die_optdup(option); 3671d62bc4baSyz147064 3672d62bc4baSyz147064 p_arg = B_TRUE; 3673d62bc4baSyz147064 break; 3674d62bc4baSyz147064 case 'P': 3675d62bc4baSyz147064 if (flags != DLADM_OPT_ACTIVE) 3676d62bc4baSyz147064 die_optdup(option); 3677d62bc4baSyz147064 3678d62bc4baSyz147064 flags = DLADM_OPT_PERSIST; 3679d62bc4baSyz147064 break; 3680e7801d59Ssowmini case 'o': 3681e7801d59Ssowmini o_arg = B_TRUE; 3682e7801d59Ssowmini fields_str = optarg; 3683e7801d59Ssowmini break; 3684da14cebeSEric Cheng case 'm': 3685da14cebeSEric Cheng m_arg = B_TRUE; 3686da14cebeSEric Cheng break; 3687da14cebeSEric Cheng case 'H': 3688da14cebeSEric Cheng H_arg = B_TRUE; 3689da14cebeSEric Cheng break; 3690d62bc4baSyz147064 default: 36918d5c46e6Sam223141 die_opterr(optopt, option, use); 3692d62bc4baSyz147064 break; 3693d62bc4baSyz147064 } 3694d62bc4baSyz147064 } 3695d62bc4baSyz147064 36960d365605Sschuster if (p_arg && !o_arg) 36970d365605Sschuster die("-p requires -o"); 36980d365605Sschuster 3699da14cebeSEric Cheng if (m_arg && H_arg) 3700da14cebeSEric Cheng die("-m cannot combine with -H"); 3701da14cebeSEric Cheng 37020d365605Sschuster if (p_arg && strcasecmp(fields_str, "all") == 0) 37030d365605Sschuster die("\"-o all\" is invalid with -p"); 37040d365605Sschuster 3705d62bc4baSyz147064 /* get link name (optional last argument) */ 3706d62bc4baSyz147064 if (optind == (argc-1)) { 37074ac67f02SAnurag S. Maskey if ((status = dladm_name2info(handle, argv[optind], &linkid, 37084ac67f02SAnurag S. Maskey NULL, NULL, NULL)) != DLADM_STATUS_OK) { 3709d62bc4baSyz147064 die_dlerr(status, "link %s is not valid", argv[optind]); 3710d62bc4baSyz147064 } 3711d62bc4baSyz147064 } else if (optind != argc) { 3712d62bc4baSyz147064 usage(); 3713d62bc4baSyz147064 } 3714d62bc4baSyz147064 3715d62bc4baSyz147064 state.ls_parseable = p_arg; 3716d62bc4baSyz147064 state.ls_flags = flags; 3717d62bc4baSyz147064 state.ls_donefirst = B_FALSE; 3718da14cebeSEric Cheng state.ls_mac = m_arg; 3719da14cebeSEric Cheng state.ls_hwgrp = H_arg; 3720d62bc4baSyz147064 3721da14cebeSEric Cheng if (m_arg && !(flags & DLADM_OPT_ACTIVE)) { 3722da14cebeSEric Cheng /* 3723da14cebeSEric Cheng * We can only display the factory MAC addresses of 3724da14cebeSEric Cheng * active data-links. 3725da14cebeSEric Cheng */ 3726da14cebeSEric Cheng die("-m not compatible with -P"); 3727e7801d59Ssowmini } 3728e7801d59Ssowmini 3729da14cebeSEric Cheng if (!o_arg || (o_arg && strcasecmp(fields_str, "all") == 0)) { 3730da14cebeSEric Cheng if (state.ls_mac) 3731da14cebeSEric Cheng fields_str = all_mac_fields; 3732da14cebeSEric Cheng else if (state.ls_hwgrp) 3733da14cebeSEric Cheng fields_str = all_hwgrp_fields; 3734da14cebeSEric Cheng else if (state.ls_flags & DLADM_OPT_ACTIVE) { 3735da14cebeSEric Cheng fields_str = all_active_fields; 3736da14cebeSEric Cheng } else { 3737da14cebeSEric Cheng fields_str = all_inactive_fields; 3738da14cebeSEric Cheng } 3739da14cebeSEric Cheng } 3740da14cebeSEric Cheng 3741da14cebeSEric Cheng if (state.ls_mac) { 3742da14cebeSEric Cheng pf = phys_m_fields; 3743da14cebeSEric Cheng pfmax = PHYS_M_MAX_FIELDS; 3744da14cebeSEric Cheng } else if (state.ls_hwgrp) { 3745da14cebeSEric Cheng pf = phys_h_fields; 3746da14cebeSEric Cheng pfmax = PHYS_H_MAX_FIELDS; 3747da14cebeSEric Cheng } else { 3748da14cebeSEric Cheng pf = phys_fields; 3749da14cebeSEric Cheng pfmax = PHYS_MAX_FIELDS; 3750da14cebeSEric Cheng } 3751da14cebeSEric Cheng 3752da14cebeSEric Cheng fields = parse_output_fields(fields_str, pf, 3753da14cebeSEric Cheng pfmax, CMD_TYPE_ANY, &nfields); 3754e7801d59Ssowmini 3755e7801d59Ssowmini if (fields == NULL) { 3756e7801d59Ssowmini die("invalid field(s) specified"); 3757e7801d59Ssowmini return; 3758e7801d59Ssowmini } 3759e7801d59Ssowmini 3760e7801d59Ssowmini state.ls_print.ps_fields = fields; 3761e7801d59Ssowmini state.ls_print.ps_nfields = nfields; 3762e7801d59Ssowmini 3763d62bc4baSyz147064 if (linkid == DATALINK_ALL_LINKID) { 37644ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(show_phys, handle, &state, 3765d62bc4baSyz147064 DATALINK_CLASS_PHYS, DATALINK_ANY_MEDIATYPE, flags); 3766d62bc4baSyz147064 } else { 37674ac67f02SAnurag S. Maskey (void) show_phys(handle, linkid, &state); 3768d62bc4baSyz147064 if (state.ls_status != DLADM_STATUS_OK) { 3769d62bc4baSyz147064 die_dlerr(state.ls_status, 3770d62bc4baSyz147064 "failed to show physical link %s", argv[optind]); 3771d62bc4baSyz147064 } 3772d62bc4baSyz147064 } 3773d62bc4baSyz147064 } 3774d62bc4baSyz147064 3775d62bc4baSyz147064 static void 37768d5c46e6Sam223141 do_show_vlan(int argc, char *argv[], const char *use) 3777d62bc4baSyz147064 { 3778d62bc4baSyz147064 int option; 3779d62bc4baSyz147064 uint32_t flags = DLADM_OPT_ACTIVE; 3780d62bc4baSyz147064 boolean_t p_arg = B_FALSE; 3781d62bc4baSyz147064 datalink_id_t linkid = DATALINK_ALL_LINKID; 3782d62bc4baSyz147064 show_state_t state; 3783d62bc4baSyz147064 dladm_status_t status; 3784e7801d59Ssowmini boolean_t o_arg = B_FALSE; 3785e7801d59Ssowmini char *fields_str = NULL; 3786e7801d59Ssowmini print_field_t **fields; 3787e7801d59Ssowmini uint_t nfields; 3788e7801d59Ssowmini char *all_fields = "link,vid,over,flags"; 3789e7801d59Ssowmini 3790e7801d59Ssowmini bzero(&state, sizeof (state)); 3791d62bc4baSyz147064 3792d62bc4baSyz147064 opterr = 0; 3793e7801d59Ssowmini while ((option = getopt_long(argc, argv, ":pPo:", 3794d62bc4baSyz147064 show_lopts, NULL)) != -1) { 3795d62bc4baSyz147064 switch (option) { 3796d62bc4baSyz147064 case 'p': 3797d62bc4baSyz147064 if (p_arg) 3798d62bc4baSyz147064 die_optdup(option); 3799d62bc4baSyz147064 3800d62bc4baSyz147064 p_arg = B_TRUE; 3801d62bc4baSyz147064 break; 3802d62bc4baSyz147064 case 'P': 3803d62bc4baSyz147064 if (flags != DLADM_OPT_ACTIVE) 3804d62bc4baSyz147064 die_optdup(option); 3805d62bc4baSyz147064 3806d62bc4baSyz147064 flags = DLADM_OPT_PERSIST; 3807d62bc4baSyz147064 break; 3808e7801d59Ssowmini case 'o': 3809e7801d59Ssowmini o_arg = B_TRUE; 3810e7801d59Ssowmini fields_str = optarg; 3811e7801d59Ssowmini break; 3812d62bc4baSyz147064 default: 38138d5c46e6Sam223141 die_opterr(optopt, option, use); 3814d62bc4baSyz147064 break; 3815d62bc4baSyz147064 } 3816d62bc4baSyz147064 } 3817d62bc4baSyz147064 38180d365605Sschuster if (p_arg && !o_arg) 38190d365605Sschuster die("-p requires -o"); 38200d365605Sschuster 38210d365605Sschuster if (p_arg && strcasecmp(fields_str, "all") == 0) 38220d365605Sschuster die("\"-o all\" is invalid with -p"); 38230d365605Sschuster 3824d62bc4baSyz147064 /* get link name (optional last argument) */ 3825d62bc4baSyz147064 if (optind == (argc-1)) { 38264ac67f02SAnurag S. Maskey if ((status = dladm_name2info(handle, argv[optind], &linkid, 38274ac67f02SAnurag S. Maskey NULL, NULL, NULL)) != DLADM_STATUS_OK) { 3828d62bc4baSyz147064 die_dlerr(status, "link %s is not valid", argv[optind]); 3829d62bc4baSyz147064 } 3830d62bc4baSyz147064 } else if (optind != argc) { 3831d62bc4baSyz147064 usage(); 3832d62bc4baSyz147064 } 3833d62bc4baSyz147064 3834d62bc4baSyz147064 state.ls_parseable = p_arg; 3835d62bc4baSyz147064 state.ls_flags = flags; 3836d62bc4baSyz147064 state.ls_donefirst = B_FALSE; 3837d62bc4baSyz147064 3838e7801d59Ssowmini if (!o_arg || (o_arg && strcasecmp(fields_str, "all") == 0)) 3839e7801d59Ssowmini fields_str = all_fields; 3840e7801d59Ssowmini 3841e7801d59Ssowmini fields = parse_output_fields(fields_str, vlan_fields, VLAN_MAX_FIELDS, 3842e7801d59Ssowmini CMD_TYPE_ANY, &nfields); 3843e7801d59Ssowmini 3844e7801d59Ssowmini if (fields == NULL) { 3845e7801d59Ssowmini die("invalid field(s) specified"); 3846e7801d59Ssowmini return; 3847e7801d59Ssowmini } 3848e7801d59Ssowmini state.ls_print.ps_fields = fields; 3849e7801d59Ssowmini state.ls_print.ps_nfields = nfields; 3850e7801d59Ssowmini 3851d62bc4baSyz147064 if (linkid == DATALINK_ALL_LINKID) { 38524ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(show_vlan, handle, &state, 3853d62bc4baSyz147064 DATALINK_CLASS_VLAN, DATALINK_ANY_MEDIATYPE, flags); 3854d62bc4baSyz147064 } else { 38554ac67f02SAnurag S. Maskey (void) show_vlan(handle, linkid, &state); 3856d62bc4baSyz147064 if (state.ls_status != DLADM_STATUS_OK) { 3857d62bc4baSyz147064 die_dlerr(state.ls_status, "failed to show vlan %s", 3858d62bc4baSyz147064 argv[optind]); 3859d62bc4baSyz147064 } 3860d62bc4baSyz147064 } 3861d62bc4baSyz147064 } 3862d62bc4baSyz147064 3863d62bc4baSyz147064 static void 3864da14cebeSEric Cheng do_create_vnic(int argc, char *argv[], const char *use) 3865da14cebeSEric Cheng { 3866da14cebeSEric Cheng datalink_id_t linkid, dev_linkid; 3867da14cebeSEric Cheng char devname[MAXLINKNAMELEN]; 3868da14cebeSEric Cheng char name[MAXLINKNAMELEN]; 3869da14cebeSEric Cheng boolean_t l_arg = B_FALSE; 3870da14cebeSEric Cheng uint32_t flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST; 3871da14cebeSEric Cheng char *altroot = NULL; 3872da14cebeSEric Cheng char option; 3873da14cebeSEric Cheng char *endp = NULL; 3874da14cebeSEric Cheng dladm_status_t status; 3875da14cebeSEric Cheng vnic_mac_addr_type_t mac_addr_type = VNIC_MAC_ADDR_TYPE_AUTO; 3876da14cebeSEric Cheng uchar_t *mac_addr; 3877da14cebeSEric Cheng int mac_slot = -1, maclen = 0, mac_prefix_len = 0; 3878*63a6526dSMichael Lim char propstr[DLADM_STRSIZE]; 3879da14cebeSEric Cheng dladm_arg_list_t *proplist = NULL; 3880285e94f9SMichael Lim int vid = 0; 3881da14cebeSEric Cheng 3882da14cebeSEric Cheng opterr = 0; 3883*63a6526dSMichael Lim bzero(propstr, DLADM_STRSIZE); 3884*63a6526dSMichael Lim 3885da14cebeSEric Cheng while ((option = getopt_long(argc, argv, ":tfR:l:m:n:p:r:v:H", 3886da14cebeSEric Cheng vnic_lopts, NULL)) != -1) { 3887da14cebeSEric Cheng switch (option) { 3888da14cebeSEric Cheng case 't': 3889da14cebeSEric Cheng flags &= ~DLADM_OPT_PERSIST; 3890da14cebeSEric Cheng break; 3891da14cebeSEric Cheng case 'R': 3892da14cebeSEric Cheng altroot = optarg; 3893da14cebeSEric Cheng break; 3894da14cebeSEric Cheng case 'l': 3895da14cebeSEric Cheng if (strlcpy(devname, optarg, MAXLINKNAMELEN) >= 3896da14cebeSEric Cheng MAXLINKNAMELEN) 3897da14cebeSEric Cheng die("link name too long"); 3898da14cebeSEric Cheng l_arg = B_TRUE; 3899da14cebeSEric Cheng break; 3900da14cebeSEric Cheng case 'm': 3901da14cebeSEric Cheng if (strcmp(optarg, "fixed") == 0) { 3902da14cebeSEric Cheng /* 3903da14cebeSEric Cheng * A fixed MAC address must be specified 3904da14cebeSEric Cheng * by its value, not by the keyword 'fixed'. 3905da14cebeSEric Cheng */ 3906da14cebeSEric Cheng die("'fixed' is not a valid MAC address"); 3907da14cebeSEric Cheng } 3908da14cebeSEric Cheng if (dladm_vnic_str2macaddrtype(optarg, 3909da14cebeSEric Cheng &mac_addr_type) != DLADM_STATUS_OK) { 3910da14cebeSEric Cheng mac_addr_type = VNIC_MAC_ADDR_TYPE_FIXED; 3911da14cebeSEric Cheng /* MAC address specified by value */ 3912da14cebeSEric Cheng mac_addr = _link_aton(optarg, &maclen); 3913da14cebeSEric Cheng if (mac_addr == NULL) { 3914da14cebeSEric Cheng if (maclen == -1) 3915da14cebeSEric Cheng die("invalid MAC address"); 3916da14cebeSEric Cheng else 3917da14cebeSEric Cheng die("out of memory"); 3918da14cebeSEric Cheng } 3919da14cebeSEric Cheng } 3920da14cebeSEric Cheng break; 3921da14cebeSEric Cheng case 'n': 3922da14cebeSEric Cheng errno = 0; 3923da14cebeSEric Cheng mac_slot = (int)strtol(optarg, &endp, 10); 3924da14cebeSEric Cheng if (errno != 0 || *endp != '\0') 3925da14cebeSEric Cheng die("invalid slot number"); 3926da14cebeSEric Cheng break; 3927da14cebeSEric Cheng case 'p': 3928*63a6526dSMichael Lim (void) strlcat(propstr, optarg, DLADM_STRSIZE); 3929*63a6526dSMichael Lim if (strlcat(propstr, ",", DLADM_STRSIZE) >= 3930*63a6526dSMichael Lim DLADM_STRSIZE) 3931*63a6526dSMichael Lim die("property list too long '%s'", propstr); 3932da14cebeSEric Cheng break; 3933da14cebeSEric Cheng case 'r': 3934da14cebeSEric Cheng mac_addr = _link_aton(optarg, &mac_prefix_len); 3935da14cebeSEric Cheng if (mac_addr == NULL) { 3936da14cebeSEric Cheng if (mac_prefix_len == -1) 3937da14cebeSEric Cheng die("invalid MAC address"); 3938da14cebeSEric Cheng else 3939da14cebeSEric Cheng die("out of memory"); 3940da14cebeSEric Cheng } 3941da14cebeSEric Cheng break; 3942da14cebeSEric Cheng case 'v': 3943285e94f9SMichael Lim if (vid != 0) 3944285e94f9SMichael Lim die_optdup(option); 3945285e94f9SMichael Lim 3946285e94f9SMichael Lim if (!str2int(optarg, &vid) || vid < 1 || vid > 4094) 3947285e94f9SMichael Lim die("invalid VLAN identifier '%s'", optarg); 3948285e94f9SMichael Lim 3949da14cebeSEric Cheng break; 3950da14cebeSEric Cheng case 'f': 3951da14cebeSEric Cheng flags |= DLADM_OPT_FORCE; 3952da14cebeSEric Cheng break; 3953da14cebeSEric Cheng case 'H': 3954da14cebeSEric Cheng flags |= DLADM_OPT_HWRINGS; 3955da14cebeSEric Cheng break; 3956da14cebeSEric Cheng default: 3957da14cebeSEric Cheng die_opterr(optopt, option, use); 3958da14cebeSEric Cheng } 3959da14cebeSEric Cheng } 3960da14cebeSEric Cheng 3961da14cebeSEric Cheng /* 3962da14cebeSEric Cheng * 'f' - force, flag can be specified only with 'v' - vlan. 3963da14cebeSEric Cheng */ 3964da14cebeSEric Cheng if ((flags & DLADM_OPT_FORCE) != 0 && vid == 0) 3965da14cebeSEric Cheng die("-f option can only be used with -v"); 3966da14cebeSEric Cheng 3967da14cebeSEric Cheng if (mac_prefix_len != 0 && mac_addr_type != VNIC_MAC_ADDR_TYPE_RANDOM && 3968da14cebeSEric Cheng mac_addr_type != VNIC_MAC_ADDR_TYPE_FIXED) 3969da14cebeSEric Cheng usage(); 3970da14cebeSEric Cheng 3971da14cebeSEric Cheng /* check required options */ 3972da14cebeSEric Cheng if (!l_arg) 3973da14cebeSEric Cheng usage(); 3974da14cebeSEric Cheng 3975da14cebeSEric Cheng if (mac_slot != -1 && mac_addr_type != VNIC_MAC_ADDR_TYPE_FACTORY) 3976da14cebeSEric Cheng usage(); 3977da14cebeSEric Cheng 3978da14cebeSEric Cheng /* the VNIC id is the required operand */ 3979da14cebeSEric Cheng if (optind != (argc - 1)) 3980da14cebeSEric Cheng usage(); 3981da14cebeSEric Cheng 3982da14cebeSEric Cheng if (strlcpy(name, argv[optind], MAXLINKNAMELEN) >= MAXLINKNAMELEN) 3983da14cebeSEric Cheng die("link name too long '%s'", argv[optind]); 3984da14cebeSEric Cheng 3985da14cebeSEric Cheng if (!dladm_valid_linkname(name)) 3986da14cebeSEric Cheng die("invalid link name '%s'", argv[optind]); 3987da14cebeSEric Cheng 3988da14cebeSEric Cheng if (altroot != NULL) 3989da14cebeSEric Cheng altroot_cmd(altroot, argc, argv); 3990da14cebeSEric Cheng 39914ac67f02SAnurag S. Maskey if (dladm_name2info(handle, devname, &dev_linkid, NULL, NULL, NULL) != 3992da14cebeSEric Cheng DLADM_STATUS_OK) 3993da14cebeSEric Cheng die("invalid link name '%s'", devname); 3994da14cebeSEric Cheng 3995*63a6526dSMichael Lim if (dladm_parse_link_props(propstr, &proplist, B_FALSE) 3996*63a6526dSMichael Lim != DLADM_STATUS_OK) 3997*63a6526dSMichael Lim die("invalid vnic property"); 3998*63a6526dSMichael Lim 39994ac67f02SAnurag S. Maskey status = dladm_vnic_create(handle, name, dev_linkid, mac_addr_type, 40004ac67f02SAnurag S. Maskey mac_addr, maclen, &mac_slot, mac_prefix_len, vid, &linkid, proplist, 40014ac67f02SAnurag S. Maskey flags); 4002da14cebeSEric Cheng if (status != DLADM_STATUS_OK) 4003da14cebeSEric Cheng die_dlerr(status, "vnic creation over %s failed", devname); 4004da14cebeSEric Cheng 4005da14cebeSEric Cheng dladm_free_props(proplist); 4006da14cebeSEric Cheng } 4007da14cebeSEric Cheng 4008da14cebeSEric Cheng static void 4009da14cebeSEric Cheng do_etherstub_check(const char *name, datalink_id_t linkid, boolean_t etherstub, 4010da14cebeSEric Cheng uint32_t flags) 4011da14cebeSEric Cheng { 4012da14cebeSEric Cheng boolean_t is_etherstub; 4013da14cebeSEric Cheng dladm_vnic_attr_t attr; 4014da14cebeSEric Cheng 40154ac67f02SAnurag S. Maskey if (dladm_vnic_info(handle, linkid, &attr, flags) != DLADM_STATUS_OK) { 4016da14cebeSEric Cheng /* 4017da14cebeSEric Cheng * Let the delete continue anyway. 4018da14cebeSEric Cheng */ 4019da14cebeSEric Cheng return; 4020da14cebeSEric Cheng } 4021da14cebeSEric Cheng is_etherstub = (attr.va_link_id == DATALINK_INVALID_LINKID); 4022da14cebeSEric Cheng if (is_etherstub != etherstub) { 4023da14cebeSEric Cheng die("'%s' is not %s", name, 4024da14cebeSEric Cheng (is_etherstub ? "a vnic" : "an etherstub")); 4025da14cebeSEric Cheng } 4026da14cebeSEric Cheng } 4027da14cebeSEric Cheng 4028da14cebeSEric Cheng static void 4029da14cebeSEric Cheng do_delete_vnic_common(int argc, char *argv[], const char *use, 4030da14cebeSEric Cheng boolean_t etherstub) 4031da14cebeSEric Cheng { 4032da14cebeSEric Cheng char option; 4033da14cebeSEric Cheng uint32_t flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST; 4034da14cebeSEric Cheng datalink_id_t linkid; 4035da14cebeSEric Cheng char *altroot = NULL; 4036da14cebeSEric Cheng dladm_status_t status; 4037da14cebeSEric Cheng 4038da14cebeSEric Cheng opterr = 0; 4039da14cebeSEric Cheng while ((option = getopt_long(argc, argv, ":R:t", lopts, 4040da14cebeSEric Cheng NULL)) != -1) { 4041da14cebeSEric Cheng switch (option) { 4042da14cebeSEric Cheng case 't': 4043da14cebeSEric Cheng flags &= ~DLADM_OPT_PERSIST; 4044da14cebeSEric Cheng break; 4045da14cebeSEric Cheng case 'R': 4046da14cebeSEric Cheng altroot = optarg; 4047da14cebeSEric Cheng break; 4048da14cebeSEric Cheng default: 4049da14cebeSEric Cheng die_opterr(optopt, option, use); 4050da14cebeSEric Cheng } 4051da14cebeSEric Cheng } 4052da14cebeSEric Cheng 4053da14cebeSEric Cheng /* get vnic name (required last argument) */ 4054da14cebeSEric Cheng if (optind != (argc - 1)) 4055da14cebeSEric Cheng usage(); 4056da14cebeSEric Cheng 4057da14cebeSEric Cheng if (altroot != NULL) 4058da14cebeSEric Cheng altroot_cmd(altroot, argc, argv); 4059da14cebeSEric Cheng 40604ac67f02SAnurag S. Maskey status = dladm_name2info(handle, argv[optind], &linkid, NULL, NULL, 40614ac67f02SAnurag S. Maskey NULL); 4062da14cebeSEric Cheng if (status != DLADM_STATUS_OK) 4063da14cebeSEric Cheng die("invalid link name '%s'", argv[optind]); 4064da14cebeSEric Cheng 4065da14cebeSEric Cheng if ((flags & DLADM_OPT_ACTIVE) != 0) { 4066da14cebeSEric Cheng do_etherstub_check(argv[optind], linkid, etherstub, 4067da14cebeSEric Cheng DLADM_OPT_ACTIVE); 4068da14cebeSEric Cheng } 4069da14cebeSEric Cheng if ((flags & DLADM_OPT_PERSIST) != 0) { 4070da14cebeSEric Cheng do_etherstub_check(argv[optind], linkid, etherstub, 4071da14cebeSEric Cheng DLADM_OPT_PERSIST); 4072da14cebeSEric Cheng } 4073da14cebeSEric Cheng 40744ac67f02SAnurag S. Maskey status = dladm_vnic_delete(handle, linkid, flags); 4075da14cebeSEric Cheng if (status != DLADM_STATUS_OK) 4076da14cebeSEric Cheng die_dlerr(status, "vnic deletion failed"); 4077da14cebeSEric Cheng } 4078da14cebeSEric Cheng 4079da14cebeSEric Cheng static void 4080da14cebeSEric Cheng do_delete_vnic(int argc, char *argv[], const char *use) 4081da14cebeSEric Cheng { 4082da14cebeSEric Cheng do_delete_vnic_common(argc, argv, use, B_FALSE); 4083da14cebeSEric Cheng } 4084da14cebeSEric Cheng 4085da14cebeSEric Cheng /* ARGSUSED */ 4086da14cebeSEric Cheng static void 4087da14cebeSEric Cheng do_up_vnic_common(int argc, char *argv[], const char *use, boolean_t vlan) 4088da14cebeSEric Cheng { 4089da14cebeSEric Cheng datalink_id_t linkid = DATALINK_ALL_LINKID; 4090da14cebeSEric Cheng dladm_status_t status; 4091da14cebeSEric Cheng char *type; 4092da14cebeSEric Cheng 4093da14cebeSEric Cheng type = vlan ? "vlan" : "vnic"; 4094da14cebeSEric Cheng 4095da14cebeSEric Cheng /* 4096da14cebeSEric Cheng * get the id or the name of the vnic/vlan (optional last argument) 4097da14cebeSEric Cheng */ 4098da14cebeSEric Cheng if (argc == 2) { 40994ac67f02SAnurag S. Maskey status = dladm_name2info(handle, argv[1], &linkid, NULL, NULL, 41004ac67f02SAnurag S. Maskey NULL); 4101da14cebeSEric Cheng if (status != DLADM_STATUS_OK) 4102da14cebeSEric Cheng goto done; 4103da14cebeSEric Cheng 4104da14cebeSEric Cheng } else if (argc > 2) { 4105da14cebeSEric Cheng usage(); 4106da14cebeSEric Cheng } 4107da14cebeSEric Cheng 4108da14cebeSEric Cheng if (vlan) 41094ac67f02SAnurag S. Maskey status = dladm_vlan_up(handle, linkid); 4110da14cebeSEric Cheng else 41114ac67f02SAnurag S. Maskey status = dladm_vnic_up(handle, linkid, 0); 4112da14cebeSEric Cheng 4113da14cebeSEric Cheng done: 4114da14cebeSEric Cheng if (status != DLADM_STATUS_OK) { 4115da14cebeSEric Cheng if (argc == 2) { 4116da14cebeSEric Cheng die_dlerr(status, 4117da14cebeSEric Cheng "could not bring up %s '%s'", type, argv[1]); 4118da14cebeSEric Cheng } else { 4119da14cebeSEric Cheng die_dlerr(status, "could not bring %ss up", type); 4120da14cebeSEric Cheng } 4121da14cebeSEric Cheng } 4122da14cebeSEric Cheng } 4123da14cebeSEric Cheng 4124da14cebeSEric Cheng static void 4125da14cebeSEric Cheng do_up_vnic(int argc, char *argv[], const char *use) 4126da14cebeSEric Cheng { 4127da14cebeSEric Cheng do_up_vnic_common(argc, argv, use, B_FALSE); 4128da14cebeSEric Cheng } 4129da14cebeSEric Cheng 4130da14cebeSEric Cheng static void 4131da14cebeSEric Cheng dump_vnics_head(const char *dev) 4132da14cebeSEric Cheng { 4133da14cebeSEric Cheng if (strlen(dev)) 4134da14cebeSEric Cheng (void) printf("%s", dev); 4135da14cebeSEric Cheng 4136da14cebeSEric Cheng (void) printf("\tipackets rbytes opackets obytes "); 4137da14cebeSEric Cheng 4138da14cebeSEric Cheng if (strlen(dev)) 4139da14cebeSEric Cheng (void) printf("%%ipkts %%opkts\n"); 4140da14cebeSEric Cheng else 4141da14cebeSEric Cheng (void) printf("\n"); 4142da14cebeSEric Cheng } 4143da14cebeSEric Cheng 4144da14cebeSEric Cheng static void 4145da14cebeSEric Cheng dump_vnic_stat(const char *name, datalink_id_t vnic_id, 4146da14cebeSEric Cheng show_vnic_state_t *state, pktsum_t *vnic_stats, pktsum_t *tot_stats) 4147da14cebeSEric Cheng { 4148da14cebeSEric Cheng pktsum_t diff_stats; 4149da14cebeSEric Cheng pktsum_t *old_stats = &state->vs_prevstats[vnic_id]; 4150da14cebeSEric Cheng 4151da14cebeSEric Cheng dladm_stats_diff(&diff_stats, vnic_stats, old_stats); 4152da14cebeSEric Cheng 4153da14cebeSEric Cheng (void) printf("%s", name); 4154da14cebeSEric Cheng 4155da14cebeSEric Cheng (void) printf("\t%-10llu", diff_stats.ipackets); 4156da14cebeSEric Cheng (void) printf("%-12llu", diff_stats.rbytes); 4157da14cebeSEric Cheng (void) printf("%-10llu", diff_stats.opackets); 4158da14cebeSEric Cheng (void) printf("%-12llu", diff_stats.obytes); 4159da14cebeSEric Cheng 4160da14cebeSEric Cheng if (tot_stats) { 4161da14cebeSEric Cheng if (tot_stats->ipackets == 0) { 4162da14cebeSEric Cheng (void) printf("\t-"); 4163da14cebeSEric Cheng } else { 4164da14cebeSEric Cheng (void) printf("\t%-6.1f", (double)diff_stats.ipackets/ 4165da14cebeSEric Cheng (double)tot_stats->ipackets * 100); 4166da14cebeSEric Cheng } 4167da14cebeSEric Cheng if (tot_stats->opackets == 0) { 4168da14cebeSEric Cheng (void) printf("\t-"); 4169da14cebeSEric Cheng } else { 4170da14cebeSEric Cheng (void) printf("\t%-6.1f", (double)diff_stats.opackets/ 4171da14cebeSEric Cheng (double)tot_stats->opackets * 100); 4172da14cebeSEric Cheng } 4173da14cebeSEric Cheng } 4174da14cebeSEric Cheng (void) printf("\n"); 4175da14cebeSEric Cheng 4176da14cebeSEric Cheng *old_stats = *vnic_stats; 4177da14cebeSEric Cheng } 4178da14cebeSEric Cheng 4179da14cebeSEric Cheng /* 4180da14cebeSEric Cheng * Called from the walker dladm_vnic_walk_sys() for each vnic to display 4181da14cebeSEric Cheng * vnic information or statistics. 4182da14cebeSEric Cheng */ 4183da14cebeSEric Cheng static dladm_status_t 4184da14cebeSEric Cheng print_vnic(show_vnic_state_t *state, datalink_id_t linkid) 4185da14cebeSEric Cheng { 4186da14cebeSEric Cheng dladm_vnic_attr_t attr, *vnic = &attr; 4187da14cebeSEric Cheng dladm_status_t status; 4188da14cebeSEric Cheng boolean_t is_etherstub; 4189da14cebeSEric Cheng char devname[MAXLINKNAMELEN]; 4190da14cebeSEric Cheng char vnic_name[MAXLINKNAMELEN]; 4191da14cebeSEric Cheng char mstr[MAXMACADDRLEN * 3]; 4192da14cebeSEric Cheng vnic_fields_buf_t vbuf; 4193da14cebeSEric Cheng 41944ac67f02SAnurag S. Maskey if ((status = dladm_vnic_info(handle, linkid, vnic, state->vs_flags)) != 4195da14cebeSEric Cheng DLADM_STATUS_OK) 4196da14cebeSEric Cheng return (status); 4197da14cebeSEric Cheng 4198da14cebeSEric Cheng is_etherstub = (vnic->va_link_id == DATALINK_INVALID_LINKID); 4199da14cebeSEric Cheng if (state->vs_etherstub != is_etherstub) { 4200da14cebeSEric Cheng /* 4201da14cebeSEric Cheng * Want all etherstub but it's not one, or want 4202da14cebeSEric Cheng * non-etherstub and it's one. 4203da14cebeSEric Cheng */ 4204da14cebeSEric Cheng return (DLADM_STATUS_OK); 4205da14cebeSEric Cheng } 4206da14cebeSEric Cheng 4207da14cebeSEric Cheng if (state->vs_link_id != DATALINK_ALL_LINKID) { 4208da14cebeSEric Cheng if (state->vs_link_id != vnic->va_link_id) 4209da14cebeSEric Cheng return (DLADM_STATUS_OK); 4210da14cebeSEric Cheng } 4211da14cebeSEric Cheng 42124ac67f02SAnurag S. Maskey if (dladm_datalink_id2info(handle, linkid, NULL, NULL, 4213da14cebeSEric Cheng NULL, vnic_name, sizeof (vnic_name)) != DLADM_STATUS_OK) 4214da14cebeSEric Cheng return (DLADM_STATUS_BADARG); 4215da14cebeSEric Cheng 4216da14cebeSEric Cheng bzero(devname, sizeof (devname)); 4217da14cebeSEric Cheng if (!is_etherstub && 42184ac67f02SAnurag S. Maskey dladm_datalink_id2info(handle, vnic->va_link_id, NULL, NULL, 4219da14cebeSEric Cheng NULL, devname, sizeof (devname)) != DLADM_STATUS_OK) 4220da14cebeSEric Cheng return (DLADM_STATUS_BADARG); 4221da14cebeSEric Cheng 4222da14cebeSEric Cheng state->vs_found = B_TRUE; 4223da14cebeSEric Cheng if (state->vs_stats) { 4224da14cebeSEric Cheng /* print vnic statistics */ 4225da14cebeSEric Cheng pktsum_t vnic_stats; 4226da14cebeSEric Cheng 4227da14cebeSEric Cheng if (state->vs_firstonly) { 4228da14cebeSEric Cheng if (state->vs_donefirst) 4229da14cebeSEric Cheng return (0); 4230da14cebeSEric Cheng state->vs_donefirst = B_TRUE; 4231da14cebeSEric Cheng } 4232da14cebeSEric Cheng 4233da14cebeSEric Cheng if (!state->vs_printstats) { 4234da14cebeSEric Cheng /* 4235da14cebeSEric Cheng * get vnic statistics and add to the sum for the 4236da14cebeSEric Cheng * named device. 4237da14cebeSEric Cheng */ 4238da14cebeSEric Cheng get_link_stats(vnic_name, &vnic_stats); 4239da14cebeSEric Cheng dladm_stats_total(&state->vs_totalstats, &vnic_stats, 4240da14cebeSEric Cheng &state->vs_prevstats[vnic->va_vnic_id]); 4241da14cebeSEric Cheng } else { 4242da14cebeSEric Cheng /* get and print vnic statistics */ 4243da14cebeSEric Cheng get_link_stats(vnic_name, &vnic_stats); 4244da14cebeSEric Cheng dump_vnic_stat(vnic_name, linkid, state, &vnic_stats, 4245da14cebeSEric Cheng &state->vs_totalstats); 4246da14cebeSEric Cheng } 4247da14cebeSEric Cheng return (DLADM_STATUS_OK); 4248da14cebeSEric Cheng } else { 4249da14cebeSEric Cheng (void) snprintf(vbuf.vnic_link, sizeof (vbuf.vnic_link), 4250da14cebeSEric Cheng "%s", vnic_name); 4251da14cebeSEric Cheng 4252da14cebeSEric Cheng if (!is_etherstub) { 4253da14cebeSEric Cheng 4254da14cebeSEric Cheng (void) snprintf(vbuf.vnic_over, sizeof (vbuf.vnic_over), 4255da14cebeSEric Cheng "%s", devname); 4256da14cebeSEric Cheng (void) snprintf(vbuf.vnic_speed, 4257da14cebeSEric Cheng sizeof (vbuf.vnic_speed), "%u", 4258da14cebeSEric Cheng (uint_t)((get_ifspeed(vnic_name, B_TRUE)) 4259da14cebeSEric Cheng / 1000000ull)); 4260da14cebeSEric Cheng 4261da14cebeSEric Cheng switch (vnic->va_mac_addr_type) { 4262da14cebeSEric Cheng case VNIC_MAC_ADDR_TYPE_FIXED: 4263da14cebeSEric Cheng case VNIC_MAC_ADDR_TYPE_PRIMARY: 4264da14cebeSEric Cheng (void) snprintf(vbuf.vnic_macaddrtype, 4265da14cebeSEric Cheng sizeof (vbuf.vnic_macaddrtype), 4266da14cebeSEric Cheng gettext("fixed")); 4267da14cebeSEric Cheng break; 4268da14cebeSEric Cheng case VNIC_MAC_ADDR_TYPE_RANDOM: 4269da14cebeSEric Cheng (void) snprintf(vbuf.vnic_macaddrtype, 4270da14cebeSEric Cheng sizeof (vbuf.vnic_macaddrtype), 4271da14cebeSEric Cheng gettext("random")); 4272da14cebeSEric Cheng break; 4273da14cebeSEric Cheng case VNIC_MAC_ADDR_TYPE_FACTORY: 4274da14cebeSEric Cheng (void) snprintf(vbuf.vnic_macaddrtype, 4275da14cebeSEric Cheng sizeof (vbuf.vnic_macaddrtype), 4276da14cebeSEric Cheng gettext("factory, slot %d"), 4277da14cebeSEric Cheng vnic->va_mac_slot); 4278da14cebeSEric Cheng break; 4279da14cebeSEric Cheng } 4280da14cebeSEric Cheng 4281da14cebeSEric Cheng if (strlen(vbuf.vnic_macaddrtype) > 0) { 4282da14cebeSEric Cheng (void) snprintf(vbuf.vnic_macaddr, 4283da14cebeSEric Cheng sizeof (vbuf.vnic_macaddr), "%s", 4284da14cebeSEric Cheng dladm_aggr_macaddr2str(vnic->va_mac_addr, 4285da14cebeSEric Cheng mstr)); 4286da14cebeSEric Cheng } 4287da14cebeSEric Cheng 4288da14cebeSEric Cheng (void) snprintf(vbuf.vnic_vid, sizeof (vbuf.vnic_vid), 4289da14cebeSEric Cheng "%d", vnic->va_vid); 4290da14cebeSEric Cheng } 4291da14cebeSEric Cheng 4292da14cebeSEric Cheng if (!state->vs_parseable && !state->vs_printheader) { 4293da14cebeSEric Cheng print_header(&state->vs_print); 4294da14cebeSEric Cheng state->vs_printheader = B_TRUE; 4295da14cebeSEric Cheng } 4296da14cebeSEric Cheng 4297da14cebeSEric Cheng dladm_print_output(&state->vs_print, state->vs_parseable, 4298da14cebeSEric Cheng dladm_print_field, (void *)&vbuf); 4299da14cebeSEric Cheng 4300da14cebeSEric Cheng return (DLADM_STATUS_OK); 4301da14cebeSEric Cheng } 4302da14cebeSEric Cheng } 4303da14cebeSEric Cheng 43044ac67f02SAnurag S. Maskey /* ARGSUSED */ 4305da14cebeSEric Cheng static int 43064ac67f02SAnurag S. Maskey show_vnic(dladm_handle_t dh, datalink_id_t linkid, void *arg) 4307da14cebeSEric Cheng { 4308da14cebeSEric Cheng show_vnic_state_t *state = arg; 4309da14cebeSEric Cheng 4310da14cebeSEric Cheng state->vs_status = print_vnic(state, linkid); 4311da14cebeSEric Cheng return (DLADM_WALK_CONTINUE); 4312da14cebeSEric Cheng } 4313da14cebeSEric Cheng 4314da14cebeSEric Cheng static void 4315da14cebeSEric Cheng do_show_vnic_common(int argc, char *argv[], const char *use, 4316da14cebeSEric Cheng boolean_t etherstub) 4317da14cebeSEric Cheng { 4318da14cebeSEric Cheng int option; 4319da14cebeSEric Cheng boolean_t s_arg = B_FALSE; 4320da14cebeSEric Cheng boolean_t i_arg = B_FALSE; 4321da14cebeSEric Cheng boolean_t l_arg = B_FALSE; 4322da14cebeSEric Cheng uint32_t interval = 0, flags = DLADM_OPT_ACTIVE; 4323da14cebeSEric Cheng datalink_id_t linkid = DATALINK_ALL_LINKID; 4324da14cebeSEric Cheng datalink_id_t dev_linkid = DATALINK_ALL_LINKID; 4325da14cebeSEric Cheng show_vnic_state_t state; 4326da14cebeSEric Cheng dladm_status_t status; 4327da14cebeSEric Cheng boolean_t o_arg = B_FALSE; 4328da14cebeSEric Cheng char *fields_str = NULL; 4329da14cebeSEric Cheng print_field_t **fields; 4330da14cebeSEric Cheng print_field_t *pf; 4331da14cebeSEric Cheng int pfmax; 4332da14cebeSEric Cheng uint_t nfields; 4333da14cebeSEric Cheng char *all_fields = 4334ae6aa22aSVenugopal Iyer "link,over,speed,macaddress,macaddrtype,vid"; 4335da14cebeSEric Cheng char *all_e_fields = 4336da14cebeSEric Cheng "link"; 4337da14cebeSEric Cheng 4338da14cebeSEric Cheng bzero(&state, sizeof (state)); 4339da14cebeSEric Cheng opterr = 0; 4340da14cebeSEric Cheng while ((option = getopt_long(argc, argv, ":pPl:si:o:", lopts, 4341da14cebeSEric Cheng NULL)) != -1) { 4342da14cebeSEric Cheng switch (option) { 4343da14cebeSEric Cheng case 'p': 4344da14cebeSEric Cheng state.vs_parseable = B_TRUE; 4345da14cebeSEric Cheng break; 4346da14cebeSEric Cheng case 'P': 4347da14cebeSEric Cheng flags = DLADM_OPT_PERSIST; 4348da14cebeSEric Cheng break; 4349da14cebeSEric Cheng case 'l': 4350da14cebeSEric Cheng if (etherstub) 4351da14cebeSEric Cheng die("option not supported for this command"); 4352da14cebeSEric Cheng 4353da14cebeSEric Cheng if (strlcpy(state.vs_link, optarg, MAXLINKNAMELEN) >= 4354da14cebeSEric Cheng MAXLINKNAMELEN) 4355da14cebeSEric Cheng die("link name too long"); 4356da14cebeSEric Cheng 4357da14cebeSEric Cheng l_arg = B_TRUE; 4358da14cebeSEric Cheng break; 4359da14cebeSEric Cheng case 's': 4360da14cebeSEric Cheng if (s_arg) { 4361da14cebeSEric Cheng die("the option -s cannot be specified " 4362da14cebeSEric Cheng "more than once"); 4363da14cebeSEric Cheng } 4364da14cebeSEric Cheng s_arg = B_TRUE; 4365da14cebeSEric Cheng break; 4366da14cebeSEric Cheng case 'i': 4367da14cebeSEric Cheng if (i_arg) { 4368da14cebeSEric Cheng die("the option -i cannot be specified " 4369da14cebeSEric Cheng "more than once"); 4370da14cebeSEric Cheng } 4371da14cebeSEric Cheng i_arg = B_TRUE; 4372*63a6526dSMichael Lim if (!dladm_str2interval(optarg, &interval)) 4373da14cebeSEric Cheng die("invalid interval value '%s'", optarg); 4374da14cebeSEric Cheng break; 4375da14cebeSEric Cheng case 'o': 4376da14cebeSEric Cheng o_arg = B_TRUE; 4377da14cebeSEric Cheng fields_str = optarg; 4378da14cebeSEric Cheng break; 4379da14cebeSEric Cheng default: 4380da14cebeSEric Cheng die_opterr(optopt, option, use); 4381da14cebeSEric Cheng } 4382da14cebeSEric Cheng } 4383da14cebeSEric Cheng 4384ad091ee1SMichael Lim if (state.vs_parseable && !o_arg) 4385ad091ee1SMichael Lim die("-p requires -o"); 4386ad091ee1SMichael Lim 4387ad091ee1SMichael Lim if (state.vs_parseable && strcasecmp(fields_str, "all") == 0) 4388ad091ee1SMichael Lim die("\"-o all\" is invalid with -p"); 4389ad091ee1SMichael Lim 4390da14cebeSEric Cheng if (i_arg && !s_arg) 4391da14cebeSEric Cheng die("the option -i can be used only with -s"); 4392da14cebeSEric Cheng 4393da14cebeSEric Cheng /* get vnic ID (optional last argument) */ 4394da14cebeSEric Cheng if (optind == (argc - 1)) { 43954ac67f02SAnurag S. Maskey status = dladm_name2info(handle, argv[optind], &linkid, NULL, 4396da14cebeSEric Cheng NULL, NULL); 4397da14cebeSEric Cheng if (status != DLADM_STATUS_OK) { 4398da14cebeSEric Cheng die_dlerr(status, "invalid vnic name '%s'", 4399da14cebeSEric Cheng argv[optind]); 4400da14cebeSEric Cheng } 4401da14cebeSEric Cheng (void) strlcpy(state.vs_vnic, argv[optind], MAXLINKNAMELEN); 4402da14cebeSEric Cheng } else if (optind != argc) { 4403da14cebeSEric Cheng usage(); 4404da14cebeSEric Cheng } 4405da14cebeSEric Cheng 4406da14cebeSEric Cheng if (l_arg) { 44074ac67f02SAnurag S. Maskey status = dladm_name2info(handle, state.vs_link, &dev_linkid, 44084ac67f02SAnurag S. Maskey NULL, NULL, NULL); 4409da14cebeSEric Cheng if (status != DLADM_STATUS_OK) { 4410da14cebeSEric Cheng die_dlerr(status, "invalid link name '%s'", 4411da14cebeSEric Cheng state.vs_link); 4412da14cebeSEric Cheng } 4413da14cebeSEric Cheng } 4414da14cebeSEric Cheng 4415da14cebeSEric Cheng state.vs_vnic_id = linkid; 4416da14cebeSEric Cheng state.vs_link_id = dev_linkid; 4417da14cebeSEric Cheng state.vs_etherstub = etherstub; 4418da14cebeSEric Cheng state.vs_found = B_FALSE; 4419da14cebeSEric Cheng state.vs_flags = flags; 4420da14cebeSEric Cheng 4421da14cebeSEric Cheng if (!o_arg || (o_arg && strcasecmp(fields_str, "all") == 0)) { 4422da14cebeSEric Cheng if (etherstub) 4423da14cebeSEric Cheng fields_str = all_e_fields; 4424da14cebeSEric Cheng else 4425da14cebeSEric Cheng fields_str = all_fields; 4426da14cebeSEric Cheng } 4427da14cebeSEric Cheng 4428da14cebeSEric Cheng pf = vnic_fields; 4429da14cebeSEric Cheng pfmax = VNIC_MAX_FIELDS; 4430da14cebeSEric Cheng 4431da14cebeSEric Cheng fields = parse_output_fields(fields_str, pf, pfmax, CMD_TYPE_ANY, 4432da14cebeSEric Cheng &nfields); 4433da14cebeSEric Cheng 4434da14cebeSEric Cheng if (fields == NULL) { 4435da14cebeSEric Cheng die("invalid field(s) specified"); 4436da14cebeSEric Cheng return; 4437da14cebeSEric Cheng } 4438da14cebeSEric Cheng 4439da14cebeSEric Cheng state.vs_print.ps_fields = fields; 4440da14cebeSEric Cheng state.vs_print.ps_nfields = nfields; 4441da14cebeSEric Cheng 4442da14cebeSEric Cheng if (s_arg) { 4443da14cebeSEric Cheng /* Display vnic statistics */ 4444da14cebeSEric Cheng vnic_stats(&state, interval); 4445da14cebeSEric Cheng return; 4446da14cebeSEric Cheng } 4447da14cebeSEric Cheng 4448da14cebeSEric Cheng /* Display vnic information */ 4449da14cebeSEric Cheng state.vs_donefirst = B_FALSE; 4450da14cebeSEric Cheng 4451da14cebeSEric Cheng if (linkid == DATALINK_ALL_LINKID) { 44524ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(show_vnic, handle, &state, 4453da14cebeSEric Cheng DATALINK_CLASS_VNIC | DATALINK_CLASS_ETHERSTUB, 4454da14cebeSEric Cheng DATALINK_ANY_MEDIATYPE, DLADM_OPT_ACTIVE); 4455da14cebeSEric Cheng } else { 44564ac67f02SAnurag S. Maskey (void) show_vnic(handle, linkid, &state); 4457da14cebeSEric Cheng if (state.vs_status != DLADM_STATUS_OK) { 4458da14cebeSEric Cheng die_dlerr(state.vs_status, "failed to show vnic '%s'", 4459da14cebeSEric Cheng state.vs_vnic); 4460da14cebeSEric Cheng } 4461da14cebeSEric Cheng } 4462da14cebeSEric Cheng } 4463da14cebeSEric Cheng 4464da14cebeSEric Cheng static void 4465da14cebeSEric Cheng do_show_vnic(int argc, char *argv[], const char *use) 4466da14cebeSEric Cheng { 4467da14cebeSEric Cheng do_show_vnic_common(argc, argv, use, B_FALSE); 4468da14cebeSEric Cheng } 4469da14cebeSEric Cheng 4470da14cebeSEric Cheng static void 4471da14cebeSEric Cheng do_create_etherstub(int argc, char *argv[], const char *use) 4472da14cebeSEric Cheng { 4473da14cebeSEric Cheng uint32_t flags; 4474da14cebeSEric Cheng char *altroot = NULL; 4475da14cebeSEric Cheng char option; 4476da14cebeSEric Cheng dladm_status_t status; 4477da14cebeSEric Cheng char name[MAXLINKNAMELEN]; 4478da14cebeSEric Cheng uchar_t mac_addr[ETHERADDRL]; 4479da14cebeSEric Cheng 4480da14cebeSEric Cheng name[0] = '\0'; 4481da14cebeSEric Cheng bzero(mac_addr, sizeof (mac_addr)); 4482da14cebeSEric Cheng flags = DLADM_OPT_ANCHOR | DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST; 4483da14cebeSEric Cheng 4484da14cebeSEric Cheng opterr = 0; 4485da14cebeSEric Cheng while ((option = getopt_long(argc, argv, "tR:", 4486da14cebeSEric Cheng etherstub_lopts, NULL)) != -1) { 4487da14cebeSEric Cheng switch (option) { 4488da14cebeSEric Cheng case 't': 4489da14cebeSEric Cheng flags &= ~DLADM_OPT_PERSIST; 4490da14cebeSEric Cheng break; 4491da14cebeSEric Cheng case 'R': 4492da14cebeSEric Cheng altroot = optarg; 4493da14cebeSEric Cheng break; 4494da14cebeSEric Cheng default: 4495da14cebeSEric Cheng die_opterr(optopt, option, use); 4496da14cebeSEric Cheng } 4497da14cebeSEric Cheng } 4498da14cebeSEric Cheng 4499da14cebeSEric Cheng /* the etherstub id is the required operand */ 4500da14cebeSEric Cheng if (optind != (argc - 1)) 4501da14cebeSEric Cheng usage(); 4502da14cebeSEric Cheng 4503da14cebeSEric Cheng if (strlcpy(name, argv[optind], MAXLINKNAMELEN) >= MAXLINKNAMELEN) 4504da14cebeSEric Cheng die("link name too long '%s'", argv[optind]); 4505da14cebeSEric Cheng 4506da14cebeSEric Cheng if (!dladm_valid_linkname(name)) 4507da14cebeSEric Cheng die("invalid link name '%s'", argv[optind]); 4508da14cebeSEric Cheng 4509da14cebeSEric Cheng if (altroot != NULL) 4510da14cebeSEric Cheng altroot_cmd(altroot, argc, argv); 4511da14cebeSEric Cheng 45124ac67f02SAnurag S. Maskey status = dladm_vnic_create(handle, name, DATALINK_INVALID_LINKID, 4513da14cebeSEric Cheng VNIC_MAC_ADDR_TYPE_AUTO, mac_addr, ETHERADDRL, NULL, 0, 0, NULL, 4514da14cebeSEric Cheng NULL, flags); 4515da14cebeSEric Cheng if (status != DLADM_STATUS_OK) 4516da14cebeSEric Cheng die_dlerr(status, "etherstub creation failed"); 4517da14cebeSEric Cheng 4518da14cebeSEric Cheng 4519da14cebeSEric Cheng } 4520da14cebeSEric Cheng 4521da14cebeSEric Cheng static void 4522da14cebeSEric Cheng do_delete_etherstub(int argc, char *argv[], const char *use) 4523da14cebeSEric Cheng { 4524da14cebeSEric Cheng do_delete_vnic_common(argc, argv, use, B_TRUE); 4525da14cebeSEric Cheng } 4526da14cebeSEric Cheng 4527da14cebeSEric Cheng /* ARGSUSED */ 4528da14cebeSEric Cheng static void 4529da14cebeSEric Cheng do_show_etherstub(int argc, char *argv[], const char *use) 4530da14cebeSEric Cheng { 4531da14cebeSEric Cheng do_show_vnic_common(argc, argv, use, B_TRUE); 4532da14cebeSEric Cheng } 4533da14cebeSEric Cheng 4534da14cebeSEric Cheng static void 45356be03d0bSVasumathi Sundaram - Sun Microsystems link_stats(datalink_id_t linkid, uint_t interval, char *fields_str, 45366be03d0bSVasumathi Sundaram - Sun Microsystems show_state_t *state) 4537d62bc4baSyz147064 { 45386be03d0bSVasumathi Sundaram - Sun Microsystems print_field_t **fields; 45396be03d0bSVasumathi Sundaram - Sun Microsystems uint_t nfields; 454033343a97Smeem 4541ae6aa22aSVenugopal Iyer fields = parse_output_fields(fields_str, link_s_fields, 4542ae6aa22aSVenugopal Iyer LINK_S_MAX_FIELDS, CMD_TYPE_ANY, &nfields); 45436be03d0bSVasumathi Sundaram - Sun Microsystems if (fields == NULL) { 45446be03d0bSVasumathi Sundaram - Sun Microsystems die("invalid field(s) specified"); 45456be03d0bSVasumathi Sundaram - Sun Microsystems return; 45466be03d0bSVasumathi Sundaram - Sun Microsystems } 45476be03d0bSVasumathi Sundaram - Sun Microsystems 45486be03d0bSVasumathi Sundaram - Sun Microsystems state->ls_print.ps_fields = fields; 45496be03d0bSVasumathi Sundaram - Sun Microsystems state->ls_print.ps_nfields = nfields; 45507c478bd9Sstevel@tonic-gate 45517c478bd9Sstevel@tonic-gate /* 45527c478bd9Sstevel@tonic-gate * If an interval is specified, continuously show the stats 45537c478bd9Sstevel@tonic-gate * only for the first MAC port. 45547c478bd9Sstevel@tonic-gate */ 45556be03d0bSVasumathi Sundaram - Sun Microsystems state->ls_firstonly = (interval != 0); 45567c478bd9Sstevel@tonic-gate 45576be03d0bSVasumathi Sundaram - Sun Microsystems if (!state->ls_parseable) 45586be03d0bSVasumathi Sundaram - Sun Microsystems print_header(&state->ls_print); 45597c478bd9Sstevel@tonic-gate for (;;) { 45606be03d0bSVasumathi Sundaram - Sun Microsystems state->ls_donefirst = B_FALSE; 4561d62bc4baSyz147064 if (linkid == DATALINK_ALL_LINKID) { 45624ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(show_link_stats, handle, 45634ac67f02SAnurag S. Maskey state, DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE, 4564d62bc4baSyz147064 DLADM_OPT_ACTIVE); 4565d62bc4baSyz147064 } else { 45664ac67f02SAnurag S. Maskey (void) show_link_stats(handle, linkid, state); 4567d62bc4baSyz147064 } 45687c478bd9Sstevel@tonic-gate 45697c478bd9Sstevel@tonic-gate if (interval == 0) 45707c478bd9Sstevel@tonic-gate break; 45717c478bd9Sstevel@tonic-gate 45727c478bd9Sstevel@tonic-gate (void) sleep(interval); 45737c478bd9Sstevel@tonic-gate } 45747c478bd9Sstevel@tonic-gate } 45757c478bd9Sstevel@tonic-gate 45767c478bd9Sstevel@tonic-gate static void 4577d62bc4baSyz147064 aggr_stats(datalink_id_t linkid, show_grp_state_t *state, uint_t interval) 45787c478bd9Sstevel@tonic-gate { 45797c478bd9Sstevel@tonic-gate /* 45807c478bd9Sstevel@tonic-gate * If an interval is specified, continuously show the stats 45817c478bd9Sstevel@tonic-gate * only for the first group. 45827c478bd9Sstevel@tonic-gate */ 4583d62bc4baSyz147064 state->gs_firstonly = (interval != 0); 45847c478bd9Sstevel@tonic-gate 45857c478bd9Sstevel@tonic-gate for (;;) { 4586d62bc4baSyz147064 state->gs_donefirst = B_FALSE; 4587d62bc4baSyz147064 if (linkid == DATALINK_ALL_LINKID) 45884ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(show_aggr, handle, state, 4589d62bc4baSyz147064 DATALINK_CLASS_AGGR, DATALINK_ANY_MEDIATYPE, 4590d62bc4baSyz147064 DLADM_OPT_ACTIVE); 4591d62bc4baSyz147064 else 45924ac67f02SAnurag S. Maskey (void) show_aggr(handle, linkid, state); 45937c478bd9Sstevel@tonic-gate 45947c478bd9Sstevel@tonic-gate if (interval == 0) 45957c478bd9Sstevel@tonic-gate break; 45967c478bd9Sstevel@tonic-gate 45977c478bd9Sstevel@tonic-gate (void) sleep(interval); 45987c478bd9Sstevel@tonic-gate } 45997c478bd9Sstevel@tonic-gate } 46007c478bd9Sstevel@tonic-gate 4601da14cebeSEric Cheng /* ARGSUSED */ 46027c478bd9Sstevel@tonic-gate static void 4603da14cebeSEric Cheng vnic_stats(show_vnic_state_t *sp, uint32_t interval) 46047c478bd9Sstevel@tonic-gate { 4605da14cebeSEric Cheng show_vnic_state_t state; 4606da14cebeSEric Cheng boolean_t specific_link, specific_dev; 46077c478bd9Sstevel@tonic-gate 4608da14cebeSEric Cheng /* Display vnic statistics */ 4609da14cebeSEric Cheng dump_vnics_head(sp->vs_link); 4610e7801d59Ssowmini 4611da14cebeSEric Cheng bzero(&state, sizeof (state)); 4612da14cebeSEric Cheng state.vs_stats = B_TRUE; 4613da14cebeSEric Cheng state.vs_vnic_id = sp->vs_vnic_id; 4614da14cebeSEric Cheng state.vs_link_id = sp->vs_link_id; 46157c478bd9Sstevel@tonic-gate 46167c478bd9Sstevel@tonic-gate /* 4617da14cebeSEric Cheng * If an interval is specified, and a vnic ID is not specified, 4618da14cebeSEric Cheng * continuously show the stats only for the first vnic. 46197c478bd9Sstevel@tonic-gate */ 4620da14cebeSEric Cheng specific_link = (sp->vs_vnic_id != DATALINK_ALL_LINKID); 4621da14cebeSEric Cheng specific_dev = (sp->vs_link_id != DATALINK_ALL_LINKID); 46227c478bd9Sstevel@tonic-gate 46237c478bd9Sstevel@tonic-gate for (;;) { 4624da14cebeSEric Cheng /* Get stats for each vnic */ 4625da14cebeSEric Cheng state.vs_found = B_FALSE; 4626da14cebeSEric Cheng state.vs_donefirst = B_FALSE; 4627da14cebeSEric Cheng state.vs_printstats = B_FALSE; 4628da14cebeSEric Cheng state.vs_flags = DLADM_OPT_ACTIVE; 46297c478bd9Sstevel@tonic-gate 4630da14cebeSEric Cheng if (!specific_link) { 46314ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(show_vnic, handle, &state, 4632da14cebeSEric Cheng DATALINK_CLASS_VNIC, DATALINK_ANY_MEDIATYPE, 4633da14cebeSEric Cheng DLADM_OPT_ACTIVE); 4634da14cebeSEric Cheng } else { 46354ac67f02SAnurag S. Maskey (void) show_vnic(handle, sp->vs_vnic_id, &state); 4636da14cebeSEric Cheng if (state.vs_status != DLADM_STATUS_OK) { 4637da14cebeSEric Cheng die_dlerr(state.vs_status, 4638da14cebeSEric Cheng "failed to show vnic '%s'", sp->vs_vnic); 4639da14cebeSEric Cheng } 4640da14cebeSEric Cheng } 46417c478bd9Sstevel@tonic-gate 4642da14cebeSEric Cheng if (specific_link && !state.vs_found) 4643da14cebeSEric Cheng die("non-existent vnic '%s'", sp->vs_vnic); 4644da14cebeSEric Cheng if (specific_dev && !state.vs_found) 4645da14cebeSEric Cheng die("device %s has no vnics", sp->vs_link); 4646da14cebeSEric Cheng 4647da14cebeSEric Cheng /* Show totals */ 4648da14cebeSEric Cheng if ((specific_link | specific_dev) && !interval) { 4649da14cebeSEric Cheng (void) printf("Total"); 4650da14cebeSEric Cheng (void) printf("\t%-10llu", 4651da14cebeSEric Cheng state.vs_totalstats.ipackets); 4652da14cebeSEric Cheng (void) printf("%-12llu", 4653da14cebeSEric Cheng state.vs_totalstats.rbytes); 4654da14cebeSEric Cheng (void) printf("%-10llu", 4655da14cebeSEric Cheng state.vs_totalstats.opackets); 4656da14cebeSEric Cheng (void) printf("%-12llu\n", 4657da14cebeSEric Cheng state.vs_totalstats.obytes); 4658da14cebeSEric Cheng } 4659da14cebeSEric Cheng 4660da14cebeSEric Cheng /* Show stats for each vnic */ 4661da14cebeSEric Cheng state.vs_donefirst = B_FALSE; 4662da14cebeSEric Cheng state.vs_printstats = B_TRUE; 4663da14cebeSEric Cheng 4664da14cebeSEric Cheng if (!specific_link) { 46654ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(show_vnic, handle, &state, 4666da14cebeSEric Cheng DATALINK_CLASS_VNIC, DATALINK_ANY_MEDIATYPE, 4667da14cebeSEric Cheng DLADM_OPT_ACTIVE); 4668da14cebeSEric Cheng } else { 46694ac67f02SAnurag S. Maskey (void) show_vnic(handle, sp->vs_vnic_id, &state); 4670da14cebeSEric Cheng if (state.vs_status != DLADM_STATUS_OK) { 4671da14cebeSEric Cheng die_dlerr(state.vs_status, 4672da14cebeSEric Cheng "failed to show vnic '%s'", sp->vs_vnic); 4673da14cebeSEric Cheng } 4674da14cebeSEric Cheng } 46757c478bd9Sstevel@tonic-gate 46767c478bd9Sstevel@tonic-gate if (interval == 0) 46777c478bd9Sstevel@tonic-gate break; 46787c478bd9Sstevel@tonic-gate 46797c478bd9Sstevel@tonic-gate (void) sleep(interval); 46807c478bd9Sstevel@tonic-gate } 46817c478bd9Sstevel@tonic-gate } 46827c478bd9Sstevel@tonic-gate 46837c478bd9Sstevel@tonic-gate static void 4684da14cebeSEric Cheng get_mac_stats(const char *dev, pktsum_t *stats) 46857c478bd9Sstevel@tonic-gate { 46867c478bd9Sstevel@tonic-gate kstat_ctl_t *kcp; 46877c478bd9Sstevel@tonic-gate kstat_t *ksp; 4688da14cebeSEric Cheng char module[DLPI_LINKNAME_MAX]; 4689da14cebeSEric Cheng uint_t instance; 4690da14cebeSEric Cheng 4691da14cebeSEric Cheng 4692da14cebeSEric Cheng bzero(stats, sizeof (*stats)); 4693da14cebeSEric Cheng 4694da14cebeSEric Cheng if (dlpi_parselink(dev, module, &instance) != DLPI_SUCCESS) 4695da14cebeSEric Cheng return; 46967c478bd9Sstevel@tonic-gate 46977c478bd9Sstevel@tonic-gate if ((kcp = kstat_open()) == NULL) { 469833343a97Smeem warn("kstat open operation failed"); 46997c478bd9Sstevel@tonic-gate return; 47007c478bd9Sstevel@tonic-gate } 47017c478bd9Sstevel@tonic-gate 4702da14cebeSEric Cheng ksp = dladm_kstat_lookup(kcp, module, instance, "mac", NULL); 4703da14cebeSEric Cheng if (ksp != NULL) 4704da14cebeSEric Cheng dladm_get_stats(kcp, ksp, stats); 4705da14cebeSEric Cheng 47067c478bd9Sstevel@tonic-gate (void) kstat_close(kcp); 47077c478bd9Sstevel@tonic-gate 47087c478bd9Sstevel@tonic-gate } 47097c478bd9Sstevel@tonic-gate 47107c478bd9Sstevel@tonic-gate static void 47117c478bd9Sstevel@tonic-gate get_link_stats(const char *link, pktsum_t *stats) 47127c478bd9Sstevel@tonic-gate { 4713da14cebeSEric Cheng kstat_ctl_t *kcp; 4714da14cebeSEric Cheng kstat_t *ksp; 4715da14cebeSEric Cheng 47167c478bd9Sstevel@tonic-gate bzero(stats, sizeof (*stats)); 4717da14cebeSEric Cheng 4718da14cebeSEric Cheng if ((kcp = kstat_open()) == NULL) { 4719da14cebeSEric Cheng warn("kstat_open operation failed"); 4720da14cebeSEric Cheng return; 4721da14cebeSEric Cheng } 4722da14cebeSEric Cheng 4723da14cebeSEric Cheng ksp = dladm_kstat_lookup(kcp, "link", 0, link, NULL); 4724da14cebeSEric Cheng 4725da14cebeSEric Cheng if (ksp != NULL) 4726da14cebeSEric Cheng dladm_get_stats(kcp, ksp, stats); 4727da14cebeSEric Cheng 4728da14cebeSEric Cheng (void) kstat_close(kcp); 47297c478bd9Sstevel@tonic-gate } 47307c478bd9Sstevel@tonic-gate 4731ba2e4443Sseb static int 4732d62bc4baSyz147064 query_kstat(char *module, int instance, const char *name, const char *stat, 4733d62bc4baSyz147064 uint8_t type, void *val) 47347c478bd9Sstevel@tonic-gate { 47357c478bd9Sstevel@tonic-gate kstat_ctl_t *kcp; 47367c478bd9Sstevel@tonic-gate kstat_t *ksp; 47377c478bd9Sstevel@tonic-gate 47387c478bd9Sstevel@tonic-gate if ((kcp = kstat_open()) == NULL) { 473933343a97Smeem warn("kstat open operation failed"); 4740ba2e4443Sseb return (-1); 47417c478bd9Sstevel@tonic-gate } 47427c478bd9Sstevel@tonic-gate 4743d62bc4baSyz147064 if ((ksp = kstat_lookup(kcp, module, instance, (char *)name)) == NULL) { 47447c478bd9Sstevel@tonic-gate /* 47457c478bd9Sstevel@tonic-gate * The kstat query could fail if the underlying MAC 47467c478bd9Sstevel@tonic-gate * driver was already detached. 47477c478bd9Sstevel@tonic-gate */ 47487c478bd9Sstevel@tonic-gate goto bail; 47497c478bd9Sstevel@tonic-gate } 47507c478bd9Sstevel@tonic-gate 47517c478bd9Sstevel@tonic-gate if (kstat_read(kcp, ksp, NULL) == -1) { 475233343a97Smeem warn("kstat read failed"); 47537c478bd9Sstevel@tonic-gate goto bail; 47547c478bd9Sstevel@tonic-gate } 47557c478bd9Sstevel@tonic-gate 4756e7801d59Ssowmini if (dladm_kstat_value(ksp, stat, type, val) < 0) 47577c478bd9Sstevel@tonic-gate goto bail; 4758ba2e4443Sseb 4759ba2e4443Sseb (void) kstat_close(kcp); 4760ba2e4443Sseb return (0); 47617c478bd9Sstevel@tonic-gate 47627c478bd9Sstevel@tonic-gate bail: 47637c478bd9Sstevel@tonic-gate (void) kstat_close(kcp); 4764ba2e4443Sseb return (-1); 4765ba2e4443Sseb } 4766ba2e4443Sseb 4767d62bc4baSyz147064 static int 4768d62bc4baSyz147064 get_one_kstat(const char *name, const char *stat, uint8_t type, 4769d62bc4baSyz147064 void *val, boolean_t islink) 4770d62bc4baSyz147064 { 4771d62bc4baSyz147064 char module[DLPI_LINKNAME_MAX]; 4772d62bc4baSyz147064 uint_t instance; 4773d62bc4baSyz147064 4774d62bc4baSyz147064 if (islink) { 4775d62bc4baSyz147064 return (query_kstat("link", 0, name, stat, type, val)); 4776d62bc4baSyz147064 } else { 4777d62bc4baSyz147064 if (dlpi_parselink(name, module, &instance) != DLPI_SUCCESS) 4778d62bc4baSyz147064 return (-1); 4779d62bc4baSyz147064 4780d62bc4baSyz147064 return (query_kstat(module, instance, "mac", stat, type, val)); 4781d62bc4baSyz147064 } 4782d62bc4baSyz147064 } 4783d62bc4baSyz147064 4784ba2e4443Sseb static uint64_t 4785d62bc4baSyz147064 get_ifspeed(const char *name, boolean_t islink) 4786ba2e4443Sseb { 4787ba2e4443Sseb uint64_t ifspeed = 0; 4788ba2e4443Sseb 4789d62bc4baSyz147064 (void) get_one_kstat(name, "ifspeed", KSTAT_DATA_UINT64, 4790d62bc4baSyz147064 &ifspeed, islink); 4791d62bc4baSyz147064 47927c478bd9Sstevel@tonic-gate return (ifspeed); 47937c478bd9Sstevel@tonic-gate } 47947c478bd9Sstevel@tonic-gate 4795f595a68aSyz147064 static const char * 4796d62bc4baSyz147064 get_linkstate(const char *name, boolean_t islink, char *buf) 47977c478bd9Sstevel@tonic-gate { 4798d62bc4baSyz147064 link_state_t linkstate; 47997c478bd9Sstevel@tonic-gate 4800d62bc4baSyz147064 if (get_one_kstat(name, "link_state", KSTAT_DATA_UINT32, 4801d62bc4baSyz147064 &linkstate, islink) != 0) { 4802da14cebeSEric Cheng (void) strlcpy(buf, "?", DLADM_STRSIZE); 48033a62633bSyz147064 return (buf); 48047c478bd9Sstevel@tonic-gate } 4805d62bc4baSyz147064 return (dladm_linkstate2str(linkstate, buf)); 48067c478bd9Sstevel@tonic-gate } 48077c478bd9Sstevel@tonic-gate 4808f595a68aSyz147064 static const char * 4809d62bc4baSyz147064 get_linkduplex(const char *name, boolean_t islink, char *buf) 48107c478bd9Sstevel@tonic-gate { 4811d62bc4baSyz147064 link_duplex_t linkduplex; 48127c478bd9Sstevel@tonic-gate 4813d62bc4baSyz147064 if (get_one_kstat(name, "link_duplex", KSTAT_DATA_UINT32, 4814d62bc4baSyz147064 &linkduplex, islink) != 0) { 48153a62633bSyz147064 (void) strlcpy(buf, "unknown", DLADM_STRSIZE); 48163a62633bSyz147064 return (buf); 48177c478bd9Sstevel@tonic-gate } 48187c478bd9Sstevel@tonic-gate 4819d62bc4baSyz147064 return (dladm_linkduplex2str(linkduplex, buf)); 48207c478bd9Sstevel@tonic-gate } 48210ba2cbe9Sxc151355 48220ba2cbe9Sxc151355 typedef struct { 48230ba2cbe9Sxc151355 char *s_buf; 48240ba2cbe9Sxc151355 char **s_fields; /* array of pointer to the fields in s_buf */ 48250ba2cbe9Sxc151355 uint_t s_nfields; /* the number of fields in s_buf */ 48260ba2cbe9Sxc151355 } split_t; 48270ba2cbe9Sxc151355 48280ba2cbe9Sxc151355 /* 48290ba2cbe9Sxc151355 * Free the split_t structure pointed to by `sp'. 48300ba2cbe9Sxc151355 */ 48310ba2cbe9Sxc151355 static void 48320ba2cbe9Sxc151355 splitfree(split_t *sp) 48330ba2cbe9Sxc151355 { 48340ba2cbe9Sxc151355 free(sp->s_buf); 48350ba2cbe9Sxc151355 free(sp->s_fields); 48360ba2cbe9Sxc151355 free(sp); 48370ba2cbe9Sxc151355 } 48380ba2cbe9Sxc151355 48390ba2cbe9Sxc151355 /* 48400ba2cbe9Sxc151355 * Split `str' into at most `maxfields' fields, each field at most `maxlen' in 48410ba2cbe9Sxc151355 * length. Return a pointer to a split_t containing the split fields, or NULL 48420ba2cbe9Sxc151355 * on failure. 48430ba2cbe9Sxc151355 */ 48440ba2cbe9Sxc151355 static split_t * 48450ba2cbe9Sxc151355 split(const char *str, uint_t maxfields, uint_t maxlen) 48460ba2cbe9Sxc151355 { 48470ba2cbe9Sxc151355 char *field, *token, *lasts = NULL; 48480ba2cbe9Sxc151355 split_t *sp; 48490ba2cbe9Sxc151355 48500ba2cbe9Sxc151355 if (*str == '\0' || maxfields == 0 || maxlen == 0) 48510ba2cbe9Sxc151355 return (NULL); 48520ba2cbe9Sxc151355 48530ba2cbe9Sxc151355 sp = calloc(sizeof (split_t), 1); 48540ba2cbe9Sxc151355 if (sp == NULL) 48550ba2cbe9Sxc151355 return (NULL); 48560ba2cbe9Sxc151355 48570ba2cbe9Sxc151355 sp->s_buf = strdup(str); 48580ba2cbe9Sxc151355 sp->s_fields = malloc(sizeof (char *) * maxfields); 48590ba2cbe9Sxc151355 if (sp->s_buf == NULL || sp->s_fields == NULL) 48600ba2cbe9Sxc151355 goto fail; 48610ba2cbe9Sxc151355 48620ba2cbe9Sxc151355 token = sp->s_buf; 48630ba2cbe9Sxc151355 while ((field = strtok_r(token, ",", &lasts)) != NULL) { 48640ba2cbe9Sxc151355 if (sp->s_nfields == maxfields || strlen(field) > maxlen) 48650ba2cbe9Sxc151355 goto fail; 48660ba2cbe9Sxc151355 token = NULL; 48670ba2cbe9Sxc151355 sp->s_fields[sp->s_nfields++] = field; 48680ba2cbe9Sxc151355 } 48690ba2cbe9Sxc151355 return (sp); 48700ba2cbe9Sxc151355 fail: 48710ba2cbe9Sxc151355 splitfree(sp); 48720ba2cbe9Sxc151355 return (NULL); 48730ba2cbe9Sxc151355 } 48740ba2cbe9Sxc151355 48750ba2cbe9Sxc151355 static int 4876e7801d59Ssowmini parse_wifi_fields(char *str, print_field_t ***fields, uint_t *countp, 48770ba2cbe9Sxc151355 uint_t cmdtype) 48780ba2cbe9Sxc151355 { 48790ba2cbe9Sxc151355 48800ba2cbe9Sxc151355 if (cmdtype == WIFI_CMD_SCAN) { 48810ba2cbe9Sxc151355 if (str == NULL) 48820ba2cbe9Sxc151355 str = def_scan_wifi_fields; 48830ba2cbe9Sxc151355 if (strcasecmp(str, "all") == 0) 48840ba2cbe9Sxc151355 str = all_scan_wifi_fields; 48850ba2cbe9Sxc151355 } else if (cmdtype == WIFI_CMD_SHOW) { 48860ba2cbe9Sxc151355 if (str == NULL) 48870ba2cbe9Sxc151355 str = def_show_wifi_fields; 48880ba2cbe9Sxc151355 if (strcasecmp(str, "all") == 0) 48890ba2cbe9Sxc151355 str = all_show_wifi_fields; 48900ba2cbe9Sxc151355 } else { 48910ba2cbe9Sxc151355 return (-1); 48920ba2cbe9Sxc151355 } 4893e7801d59Ssowmini *fields = parse_output_fields(str, wifi_fields, WIFI_MAX_FIELDS, 4894e7801d59Ssowmini cmdtype, countp); 4895e7801d59Ssowmini if (*fields != NULL) 4896e7801d59Ssowmini return (0); 48970ba2cbe9Sxc151355 return (-1); 4898e7801d59Ssowmini } 4899e7801d59Ssowmini static print_field_t ** 4900e7801d59Ssowmini parse_output_fields(char *str, print_field_t *template, int max_fields, 4901e7801d59Ssowmini uint_t cmdtype, uint_t *countp) 4902e7801d59Ssowmini { 4903e7801d59Ssowmini split_t *sp; 4904e7801d59Ssowmini boolean_t good_match = B_FALSE; 4905e7801d59Ssowmini uint_t i, j; 4906e7801d59Ssowmini print_field_t **pf = NULL; 49070ba2cbe9Sxc151355 4908e7801d59Ssowmini sp = split(str, max_fields, MAX_FIELD_LEN); 4909e7801d59Ssowmini 4910e7801d59Ssowmini if (sp == NULL) 4911e7801d59Ssowmini return (NULL); 4912e7801d59Ssowmini 4913e7801d59Ssowmini pf = malloc(sp->s_nfields * sizeof (print_field_t *)); 4914e7801d59Ssowmini if (pf == NULL) 49150ba2cbe9Sxc151355 goto fail; 49160ba2cbe9Sxc151355 49170ba2cbe9Sxc151355 for (i = 0; i < sp->s_nfields; i++) { 4918e7801d59Ssowmini for (j = 0; j < max_fields; j++) { 49190ba2cbe9Sxc151355 if (strcasecmp(sp->s_fields[i], 4920e7801d59Ssowmini template[j].pf_name) == 0) { 4921e7801d59Ssowmini good_match = template[j]. pf_cmdtype & cmdtype; 49220ba2cbe9Sxc151355 break; 49230ba2cbe9Sxc151355 } 49240ba2cbe9Sxc151355 } 49250ba2cbe9Sxc151355 if (!good_match) 49260ba2cbe9Sxc151355 goto fail; 49270ba2cbe9Sxc151355 49280ba2cbe9Sxc151355 good_match = B_FALSE; 4929e7801d59Ssowmini pf[i] = &template[j]; 49300ba2cbe9Sxc151355 } 49310ba2cbe9Sxc151355 *countp = i; 49320ba2cbe9Sxc151355 splitfree(sp); 4933e7801d59Ssowmini return (pf); 49340ba2cbe9Sxc151355 fail: 4935e7801d59Ssowmini free(pf); 49360ba2cbe9Sxc151355 splitfree(sp); 4937e7801d59Ssowmini return (NULL); 49380ba2cbe9Sxc151355 } 49390ba2cbe9Sxc151355 49400ba2cbe9Sxc151355 typedef struct print_wifi_state { 4941d62bc4baSyz147064 char *ws_link; 49420ba2cbe9Sxc151355 boolean_t ws_parseable; 49430ba2cbe9Sxc151355 boolean_t ws_header; 4944e7801d59Ssowmini print_state_t ws_print_state; 49450ba2cbe9Sxc151355 } print_wifi_state_t; 49460ba2cbe9Sxc151355 4947e7801d59Ssowmini typedef struct wlan_scan_args_s { 4948e7801d59Ssowmini print_wifi_state_t *ws_state; 4949e7801d59Ssowmini void *ws_attr; 4950e7801d59Ssowmini } wlan_scan_args_t; 49510ba2cbe9Sxc151355 49520ba2cbe9Sxc151355 static void 4953e7801d59Ssowmini print_field(print_state_t *statep, print_field_t *pfp, const char *value, 4954e7801d59Ssowmini boolean_t parseable) 49550ba2cbe9Sxc151355 { 4956e7801d59Ssowmini uint_t width = pfp->pf_width; 49576be03d0bSVasumathi Sundaram - Sun Microsystems uint_t valwidth; 49580ba2cbe9Sxc151355 uint_t compress; 49590ba2cbe9Sxc151355 49600d365605Sschuster /* 49610d365605Sschuster * Parsable fields are separated by ':'. If such a field contains 49620d365605Sschuster * a ':' or '\', this character is prefixed by a '\'. 49630d365605Sschuster */ 4964e7801d59Ssowmini if (parseable) { 49650d365605Sschuster char c; 49660d365605Sschuster 49670d365605Sschuster if (statep->ps_nfields == 1) { 49680d365605Sschuster (void) printf("%s", value); 49690d365605Sschuster return; 49700d365605Sschuster } 49710d365605Sschuster while ((c = *value++) != '\0') { 49720d365605Sschuster if (c == ':' || c == '\\') 49730d365605Sschuster (void) putchar('\\'); 49740d365605Sschuster (void) putchar(c); 49750d365605Sschuster } 49760d365605Sschuster if (!statep->ps_lastfield) 49770d365605Sschuster (void) putchar(':'); 49780d365605Sschuster return; 49790ba2cbe9Sxc151355 } else { 49800ba2cbe9Sxc151355 if (value[0] == '\0') 4981e7801d59Ssowmini value = STR_UNDEF_VAL; 4982e7801d59Ssowmini if (statep->ps_lastfield) { 49830ba2cbe9Sxc151355 (void) printf("%s", value); 49846be03d0bSVasumathi Sundaram - Sun Microsystems statep->ps_overflow = 0; 49850ba2cbe9Sxc151355 return; 49860ba2cbe9Sxc151355 } 49870ba2cbe9Sxc151355 49886be03d0bSVasumathi Sundaram - Sun Microsystems valwidth = strlen(value); 49890ba2cbe9Sxc151355 if (valwidth > width) { 4990e7801d59Ssowmini statep->ps_overflow += valwidth - width; 4991e7801d59Ssowmini } else if (valwidth < width && statep->ps_overflow > 0) { 4992e7801d59Ssowmini compress = min(statep->ps_overflow, width - valwidth); 4993e7801d59Ssowmini statep->ps_overflow -= compress; 49940ba2cbe9Sxc151355 width -= compress; 49950ba2cbe9Sxc151355 } 49960ba2cbe9Sxc151355 (void) printf("%-*s", width, value); 49970ba2cbe9Sxc151355 } 49980ba2cbe9Sxc151355 4999e7801d59Ssowmini if (!statep->ps_lastfield) 50000ba2cbe9Sxc151355 (void) putchar(' '); 50010ba2cbe9Sxc151355 } 50020ba2cbe9Sxc151355 5003e7801d59Ssowmini static char * 5004e7801d59Ssowmini print_wlan_attr(print_field_t *wfp, void *warg) 50050ba2cbe9Sxc151355 { 5006e7801d59Ssowmini static char buf[DLADM_STRSIZE]; 5007e7801d59Ssowmini wlan_scan_args_t *w = warg; 5008e7801d59Ssowmini print_wifi_state_t *statep = w->ws_state; 5009e7801d59Ssowmini dladm_wlan_attr_t *attrp = w->ws_attr; 50100ba2cbe9Sxc151355 5011e7801d59Ssowmini if (wfp->pf_index == 0) { 5012e7801d59Ssowmini return ((char *)statep->ws_link); 50130ba2cbe9Sxc151355 } 50140ba2cbe9Sxc151355 5015e7801d59Ssowmini if ((wfp->pf_index & attrp->wa_valid) == 0) { 5016e7801d59Ssowmini return (""); 50170ba2cbe9Sxc151355 } 50180ba2cbe9Sxc151355 5019e7801d59Ssowmini switch (wfp->pf_index) { 5020f595a68aSyz147064 case DLADM_WLAN_ATTR_ESSID: 5021e7801d59Ssowmini (void) dladm_wlan_essid2str(&attrp->wa_essid, buf); 50220ba2cbe9Sxc151355 break; 5023f595a68aSyz147064 case DLADM_WLAN_ATTR_BSSID: 5024e7801d59Ssowmini (void) dladm_wlan_bssid2str(&attrp->wa_bssid, buf); 50250ba2cbe9Sxc151355 break; 5026f595a68aSyz147064 case DLADM_WLAN_ATTR_SECMODE: 5027e7801d59Ssowmini (void) dladm_wlan_secmode2str(&attrp->wa_secmode, buf); 50280ba2cbe9Sxc151355 break; 5029f595a68aSyz147064 case DLADM_WLAN_ATTR_STRENGTH: 5030e7801d59Ssowmini (void) dladm_wlan_strength2str(&attrp->wa_strength, buf); 50310ba2cbe9Sxc151355 break; 5032f595a68aSyz147064 case DLADM_WLAN_ATTR_MODE: 5033e7801d59Ssowmini (void) dladm_wlan_mode2str(&attrp->wa_mode, buf); 50340ba2cbe9Sxc151355 break; 5035f595a68aSyz147064 case DLADM_WLAN_ATTR_SPEED: 5036e7801d59Ssowmini (void) dladm_wlan_speed2str(&attrp->wa_speed, buf); 50370ba2cbe9Sxc151355 (void) strlcat(buf, "Mb", sizeof (buf)); 50380ba2cbe9Sxc151355 break; 5039f595a68aSyz147064 case DLADM_WLAN_ATTR_AUTH: 5040e7801d59Ssowmini (void) dladm_wlan_auth2str(&attrp->wa_auth, buf); 50410ba2cbe9Sxc151355 break; 5042f595a68aSyz147064 case DLADM_WLAN_ATTR_BSSTYPE: 5043e7801d59Ssowmini (void) dladm_wlan_bsstype2str(&attrp->wa_bsstype, buf); 50440ba2cbe9Sxc151355 break; 50450ba2cbe9Sxc151355 } 50460ba2cbe9Sxc151355 5047e7801d59Ssowmini return (buf); 50480ba2cbe9Sxc151355 } 50490ba2cbe9Sxc151355 50500ba2cbe9Sxc151355 static boolean_t 5051f595a68aSyz147064 print_scan_results(void *arg, dladm_wlan_attr_t *attrp) 50520ba2cbe9Sxc151355 { 50530ba2cbe9Sxc151355 print_wifi_state_t *statep = arg; 5054e7801d59Ssowmini wlan_scan_args_t warg; 50550ba2cbe9Sxc151355 50560ba2cbe9Sxc151355 if (statep->ws_header) { 50570ba2cbe9Sxc151355 statep->ws_header = B_FALSE; 50580ba2cbe9Sxc151355 if (!statep->ws_parseable) 5059e7801d59Ssowmini print_header(&statep->ws_print_state); 50600ba2cbe9Sxc151355 } 50610ba2cbe9Sxc151355 5062e7801d59Ssowmini statep->ws_print_state.ps_overflow = 0; 5063e7801d59Ssowmini bzero(&warg, sizeof (warg)); 5064e7801d59Ssowmini warg.ws_state = statep; 5065e7801d59Ssowmini warg.ws_attr = attrp; 5066e7801d59Ssowmini dladm_print_output(&statep->ws_print_state, statep->ws_parseable, 5067e7801d59Ssowmini print_wlan_attr, &warg); 50680ba2cbe9Sxc151355 return (B_TRUE); 50690ba2cbe9Sxc151355 } 50700ba2cbe9Sxc151355 5071d62bc4baSyz147064 static int 50724ac67f02SAnurag S. Maskey scan_wifi(dladm_handle_t dh, datalink_id_t linkid, void *arg) 50730ba2cbe9Sxc151355 { 50740ba2cbe9Sxc151355 print_wifi_state_t *statep = arg; 5075f595a68aSyz147064 dladm_status_t status; 5076d62bc4baSyz147064 char link[MAXLINKNAMELEN]; 5077d62bc4baSyz147064 50784ac67f02SAnurag S. Maskey if ((status = dladm_datalink_id2info(dh, linkid, NULL, NULL, NULL, link, 5079e7801d59Ssowmini sizeof (link))) != DLADM_STATUS_OK) { 5080d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 5081d62bc4baSyz147064 } 50820ba2cbe9Sxc151355 50830ba2cbe9Sxc151355 statep->ws_link = link; 50844ac67f02SAnurag S. Maskey status = dladm_wlan_scan(dh, linkid, statep, print_scan_results); 5085f595a68aSyz147064 if (status != DLADM_STATUS_OK) 5086d62bc4baSyz147064 die_dlerr(status, "cannot scan link '%s'", statep->ws_link); 508733343a97Smeem 5088d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 50890ba2cbe9Sxc151355 } 50900ba2cbe9Sxc151355 5091e7801d59Ssowmini static char * 5092e7801d59Ssowmini print_link_attr(print_field_t *wfp, void *warg) 50930ba2cbe9Sxc151355 { 5094e7801d59Ssowmini static char buf[DLADM_STRSIZE]; 5095e7801d59Ssowmini char *ptr; 5096e7801d59Ssowmini wlan_scan_args_t *w = warg, w1; 5097e7801d59Ssowmini print_wifi_state_t *statep = w->ws_state; 5098e7801d59Ssowmini dladm_wlan_linkattr_t *attrp = w->ws_attr; 50990ba2cbe9Sxc151355 5100e7801d59Ssowmini if (strcmp(wfp->pf_name, "status") == 0) { 5101e7801d59Ssowmini if ((wfp->pf_index & attrp->la_valid) != 0) 5102e7801d59Ssowmini (void) dladm_wlan_linkstatus2str( 5103e7801d59Ssowmini &attrp->la_status, buf); 5104e7801d59Ssowmini return (buf); 51050ba2cbe9Sxc151355 } 5106e7801d59Ssowmini statep->ws_print_state.ps_overflow = 0; 5107e7801d59Ssowmini bzero(&w1, sizeof (w1)); 5108e7801d59Ssowmini w1.ws_state = statep; 5109e7801d59Ssowmini w1.ws_attr = &attrp->la_wlan_attr; 5110e7801d59Ssowmini ptr = print_wlan_attr(wfp, &w1); 5111e7801d59Ssowmini return (ptr); 51120ba2cbe9Sxc151355 } 51130ba2cbe9Sxc151355 5114d62bc4baSyz147064 static int 51154ac67f02SAnurag S. Maskey show_wifi(dladm_handle_t dh, datalink_id_t linkid, void *arg) 51160ba2cbe9Sxc151355 { 51170ba2cbe9Sxc151355 print_wifi_state_t *statep = arg; 5118f595a68aSyz147064 dladm_wlan_linkattr_t attr; 5119f595a68aSyz147064 dladm_status_t status; 5120d62bc4baSyz147064 char link[MAXLINKNAMELEN]; 5121e7801d59Ssowmini wlan_scan_args_t warg; 51220ba2cbe9Sxc151355 51234ac67f02SAnurag S. Maskey if ((status = dladm_datalink_id2info(dh, linkid, NULL, NULL, NULL, link, 5124e7801d59Ssowmini sizeof (link))) != DLADM_STATUS_OK) { 5125d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 5126d62bc4baSyz147064 } 5127d62bc4baSyz147064 51285f5c9f54SAnurag S. Maskey /* dladm_wlan_get_linkattr() memsets attr with 0 */ 51294ac67f02SAnurag S. Maskey status = dladm_wlan_get_linkattr(dh, linkid, &attr); 5130f595a68aSyz147064 if (status != DLADM_STATUS_OK) 5131d62bc4baSyz147064 die_dlerr(status, "cannot get link attributes for %s", link); 5132d62bc4baSyz147064 5133d62bc4baSyz147064 statep->ws_link = link; 51340ba2cbe9Sxc151355 51350ba2cbe9Sxc151355 if (statep->ws_header) { 51360ba2cbe9Sxc151355 statep->ws_header = B_FALSE; 51370ba2cbe9Sxc151355 if (!statep->ws_parseable) 5138e7801d59Ssowmini print_header(&statep->ws_print_state); 51390ba2cbe9Sxc151355 } 51400ba2cbe9Sxc151355 5141e7801d59Ssowmini statep->ws_print_state.ps_overflow = 0; 5142e7801d59Ssowmini bzero(&warg, sizeof (warg)); 5143e7801d59Ssowmini warg.ws_state = statep; 5144e7801d59Ssowmini warg.ws_attr = &attr; 5145e7801d59Ssowmini dladm_print_output(&statep->ws_print_state, statep->ws_parseable, 5146e7801d59Ssowmini print_link_attr, &warg); 5147d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 51480ba2cbe9Sxc151355 } 51490ba2cbe9Sxc151355 51500ba2cbe9Sxc151355 static void 51518d5c46e6Sam223141 do_display_wifi(int argc, char **argv, int cmd, const char *use) 51520ba2cbe9Sxc151355 { 51530ba2cbe9Sxc151355 int option; 51540ba2cbe9Sxc151355 char *fields_str = NULL; 5155e7801d59Ssowmini print_field_t **fields; 51564ac67f02SAnurag S. Maskey int (*callback)(dladm_handle_t, datalink_id_t, void *); 51570ba2cbe9Sxc151355 uint_t nfields; 51580ba2cbe9Sxc151355 print_wifi_state_t state; 5159d62bc4baSyz147064 datalink_id_t linkid = DATALINK_ALL_LINKID; 5160f595a68aSyz147064 dladm_status_t status; 51610ba2cbe9Sxc151355 51620ba2cbe9Sxc151355 if (cmd == WIFI_CMD_SCAN) 51630ba2cbe9Sxc151355 callback = scan_wifi; 51640ba2cbe9Sxc151355 else if (cmd == WIFI_CMD_SHOW) 51650ba2cbe9Sxc151355 callback = show_wifi; 51660ba2cbe9Sxc151355 else 51670ba2cbe9Sxc151355 return; 51680ba2cbe9Sxc151355 51690ba2cbe9Sxc151355 state.ws_parseable = B_FALSE; 51700ba2cbe9Sxc151355 state.ws_header = B_TRUE; 51710ba2cbe9Sxc151355 opterr = 0; 51720ba2cbe9Sxc151355 while ((option = getopt_long(argc, argv, ":o:p", 51730ba2cbe9Sxc151355 wifi_longopts, NULL)) != -1) { 51740ba2cbe9Sxc151355 switch (option) { 51750ba2cbe9Sxc151355 case 'o': 51760ba2cbe9Sxc151355 fields_str = optarg; 51770ba2cbe9Sxc151355 break; 51780ba2cbe9Sxc151355 case 'p': 51790ba2cbe9Sxc151355 state.ws_parseable = B_TRUE; 51800ba2cbe9Sxc151355 break; 51810ba2cbe9Sxc151355 default: 51828d5c46e6Sam223141 die_opterr(optopt, option, use); 51830ba2cbe9Sxc151355 } 51840ba2cbe9Sxc151355 } 51850ba2cbe9Sxc151355 51860d365605Sschuster if (state.ws_parseable && fields_str == NULL) 51870d365605Sschuster die("-p requires -o"); 51880d365605Sschuster 51890d365605Sschuster if (state.ws_parseable && strcasecmp(fields_str, "all") == 0) 51900d365605Sschuster die("\"-o all\" is invalid with -p"); 51910d365605Sschuster 5192d62bc4baSyz147064 if (optind == (argc - 1)) { 51934ac67f02SAnurag S. Maskey if ((status = dladm_name2info(handle, argv[optind], &linkid, 51944ac67f02SAnurag S. Maskey NULL, NULL, NULL)) != DLADM_STATUS_OK) { 5195d62bc4baSyz147064 die_dlerr(status, "link %s is not valid", argv[optind]); 5196d62bc4baSyz147064 } 5197d62bc4baSyz147064 } else if (optind != argc) { 51980ba2cbe9Sxc151355 usage(); 5199d62bc4baSyz147064 } 52000ba2cbe9Sxc151355 520133343a97Smeem if (parse_wifi_fields(fields_str, &fields, &nfields, cmd) < 0) 520233343a97Smeem die("invalid field(s) specified"); 520333343a97Smeem 5204e7801d59Ssowmini bzero(&state.ws_print_state, sizeof (state.ws_print_state)); 5205e7801d59Ssowmini state.ws_print_state.ps_fields = fields; 5206e7801d59Ssowmini state.ws_print_state.ps_nfields = nfields; 52070ba2cbe9Sxc151355 5208d62bc4baSyz147064 if (linkid == DATALINK_ALL_LINKID) { 52094ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(callback, handle, &state, 5210d62bc4baSyz147064 DATALINK_CLASS_PHYS, DL_WIFI, DLADM_OPT_ACTIVE); 52110ba2cbe9Sxc151355 } else { 52124ac67f02SAnurag S. Maskey (void) (*callback)(handle, linkid, &state); 52130ba2cbe9Sxc151355 } 52140ba2cbe9Sxc151355 free(fields); 52150ba2cbe9Sxc151355 } 52160ba2cbe9Sxc151355 52170ba2cbe9Sxc151355 static void 52188d5c46e6Sam223141 do_scan_wifi(int argc, char **argv, const char *use) 52190ba2cbe9Sxc151355 { 52208d5c46e6Sam223141 do_display_wifi(argc, argv, WIFI_CMD_SCAN, use); 52210ba2cbe9Sxc151355 } 52220ba2cbe9Sxc151355 52230ba2cbe9Sxc151355 static void 52248d5c46e6Sam223141 do_show_wifi(int argc, char **argv, const char *use) 52250ba2cbe9Sxc151355 { 52268d5c46e6Sam223141 do_display_wifi(argc, argv, WIFI_CMD_SHOW, use); 52270ba2cbe9Sxc151355 } 52280ba2cbe9Sxc151355 52290ba2cbe9Sxc151355 typedef struct wlan_count_attr { 52300ba2cbe9Sxc151355 uint_t wc_count; 5231d62bc4baSyz147064 datalink_id_t wc_linkid; 52320ba2cbe9Sxc151355 } wlan_count_attr_t; 52330ba2cbe9Sxc151355 52344ac67f02SAnurag S. Maskey /* ARGSUSED */ 5235d62bc4baSyz147064 static int 52364ac67f02SAnurag S. Maskey do_count_wlan(dladm_handle_t dh, datalink_id_t linkid, void *arg) 52370ba2cbe9Sxc151355 { 523833343a97Smeem wlan_count_attr_t *cp = arg; 52390ba2cbe9Sxc151355 52400ba2cbe9Sxc151355 if (cp->wc_count == 0) 5241d62bc4baSyz147064 cp->wc_linkid = linkid; 52420ba2cbe9Sxc151355 cp->wc_count++; 5243d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 52440ba2cbe9Sxc151355 } 52450ba2cbe9Sxc151355 52460ba2cbe9Sxc151355 static int 5247a399b765Szf162725 parse_wlan_keys(char *str, dladm_wlan_key_t **keys, uint_t *key_countp) 52480ba2cbe9Sxc151355 { 52490ba2cbe9Sxc151355 uint_t i; 52500ba2cbe9Sxc151355 split_t *sp; 5251a399b765Szf162725 dladm_wlan_key_t *wk; 52520ba2cbe9Sxc151355 5253a399b765Szf162725 sp = split(str, DLADM_WLAN_MAX_WEPKEYS, DLADM_WLAN_MAX_KEYNAME_LEN); 52540ba2cbe9Sxc151355 if (sp == NULL) 52550ba2cbe9Sxc151355 return (-1); 52560ba2cbe9Sxc151355 5257a399b765Szf162725 wk = malloc(sp->s_nfields * sizeof (dladm_wlan_key_t)); 52580ba2cbe9Sxc151355 if (wk == NULL) 52590ba2cbe9Sxc151355 goto fail; 52600ba2cbe9Sxc151355 52610ba2cbe9Sxc151355 for (i = 0; i < sp->s_nfields; i++) { 52620ba2cbe9Sxc151355 char *s; 52630ba2cbe9Sxc151355 dladm_secobj_class_t class; 52640ba2cbe9Sxc151355 dladm_status_t status; 52650ba2cbe9Sxc151355 52660ba2cbe9Sxc151355 (void) strlcpy(wk[i].wk_name, sp->s_fields[i], 5267a399b765Szf162725 DLADM_WLAN_MAX_KEYNAME_LEN); 52680ba2cbe9Sxc151355 52690ba2cbe9Sxc151355 wk[i].wk_idx = 1; 52700ba2cbe9Sxc151355 if ((s = strrchr(wk[i].wk_name, ':')) != NULL) { 52710ba2cbe9Sxc151355 if (s[1] == '\0' || s[2] != '\0' || !isdigit(s[1])) 52720ba2cbe9Sxc151355 goto fail; 52730ba2cbe9Sxc151355 52740ba2cbe9Sxc151355 wk[i].wk_idx = (uint_t)(s[1] - '0'); 52750ba2cbe9Sxc151355 *s = '\0'; 52760ba2cbe9Sxc151355 } 5277a399b765Szf162725 wk[i].wk_len = DLADM_WLAN_MAX_KEY_LEN; 52780ba2cbe9Sxc151355 52794ac67f02SAnurag S. Maskey status = dladm_get_secobj(handle, wk[i].wk_name, &class, 52800ba2cbe9Sxc151355 wk[i].wk_val, &wk[i].wk_len, 0); 52810ba2cbe9Sxc151355 if (status != DLADM_STATUS_OK) { 52820ba2cbe9Sxc151355 if (status == DLADM_STATUS_NOTFOUND) { 52834ac67f02SAnurag S. Maskey status = dladm_get_secobj(handle, wk[i].wk_name, 52840ba2cbe9Sxc151355 &class, wk[i].wk_val, &wk[i].wk_len, 52850ba2cbe9Sxc151355 DLADM_OPT_PERSIST); 52860ba2cbe9Sxc151355 } 52870ba2cbe9Sxc151355 if (status != DLADM_STATUS_OK) 52880ba2cbe9Sxc151355 goto fail; 52890ba2cbe9Sxc151355 } 5290a399b765Szf162725 wk[i].wk_class = class; 52910ba2cbe9Sxc151355 } 52920ba2cbe9Sxc151355 *keys = wk; 52930ba2cbe9Sxc151355 *key_countp = i; 52940ba2cbe9Sxc151355 splitfree(sp); 52950ba2cbe9Sxc151355 return (0); 52960ba2cbe9Sxc151355 fail: 52970ba2cbe9Sxc151355 free(wk); 52980ba2cbe9Sxc151355 splitfree(sp); 52990ba2cbe9Sxc151355 return (-1); 53000ba2cbe9Sxc151355 } 53010ba2cbe9Sxc151355 53020ba2cbe9Sxc151355 static void 53038d5c46e6Sam223141 do_connect_wifi(int argc, char **argv, const char *use) 53040ba2cbe9Sxc151355 { 53050ba2cbe9Sxc151355 int option; 5306f595a68aSyz147064 dladm_wlan_attr_t attr, *attrp; 5307f595a68aSyz147064 dladm_status_t status = DLADM_STATUS_OK; 5308f595a68aSyz147064 int timeout = DLADM_WLAN_CONNECT_TIMEOUT_DEFAULT; 5309d62bc4baSyz147064 datalink_id_t linkid = DATALINK_ALL_LINKID; 5310a399b765Szf162725 dladm_wlan_key_t *keys = NULL; 53110ba2cbe9Sxc151355 uint_t key_count = 0; 53120ba2cbe9Sxc151355 uint_t flags = 0; 5313f595a68aSyz147064 dladm_wlan_secmode_t keysecmode = DLADM_WLAN_SECMODE_NONE; 5314a399b765Szf162725 char buf[DLADM_STRSIZE]; 53150ba2cbe9Sxc151355 53160ba2cbe9Sxc151355 opterr = 0; 53170ba2cbe9Sxc151355 (void) memset(&attr, 0, sizeof (attr)); 53180ba2cbe9Sxc151355 while ((option = getopt_long(argc, argv, ":e:i:a:m:b:s:k:T:c", 53190ba2cbe9Sxc151355 wifi_longopts, NULL)) != -1) { 53200ba2cbe9Sxc151355 switch (option) { 53210ba2cbe9Sxc151355 case 'e': 5322f595a68aSyz147064 status = dladm_wlan_str2essid(optarg, &attr.wa_essid); 5323f595a68aSyz147064 if (status != DLADM_STATUS_OK) 532433343a97Smeem die("invalid ESSID '%s'", optarg); 532533343a97Smeem 5326f595a68aSyz147064 attr.wa_valid |= DLADM_WLAN_ATTR_ESSID; 53270ba2cbe9Sxc151355 /* 53280ba2cbe9Sxc151355 * Try to connect without doing a scan. 53290ba2cbe9Sxc151355 */ 5330f595a68aSyz147064 flags |= DLADM_WLAN_CONNECT_NOSCAN; 53310ba2cbe9Sxc151355 break; 53320ba2cbe9Sxc151355 case 'i': 5333f595a68aSyz147064 status = dladm_wlan_str2bssid(optarg, &attr.wa_bssid); 5334f595a68aSyz147064 if (status != DLADM_STATUS_OK) 533533343a97Smeem die("invalid BSSID %s", optarg); 533633343a97Smeem 5337f595a68aSyz147064 attr.wa_valid |= DLADM_WLAN_ATTR_BSSID; 53380ba2cbe9Sxc151355 break; 53390ba2cbe9Sxc151355 case 'a': 5340f595a68aSyz147064 status = dladm_wlan_str2auth(optarg, &attr.wa_auth); 5341f595a68aSyz147064 if (status != DLADM_STATUS_OK) 534233343a97Smeem die("invalid authentication mode '%s'", optarg); 534333343a97Smeem 5344f595a68aSyz147064 attr.wa_valid |= DLADM_WLAN_ATTR_AUTH; 53450ba2cbe9Sxc151355 break; 53460ba2cbe9Sxc151355 case 'm': 5347f595a68aSyz147064 status = dladm_wlan_str2mode(optarg, &attr.wa_mode); 5348f595a68aSyz147064 if (status != DLADM_STATUS_OK) 534933343a97Smeem die("invalid mode '%s'", optarg); 535033343a97Smeem 5351f595a68aSyz147064 attr.wa_valid |= DLADM_WLAN_ATTR_MODE; 53520ba2cbe9Sxc151355 break; 53530ba2cbe9Sxc151355 case 'b': 5354f595a68aSyz147064 if ((status = dladm_wlan_str2bsstype(optarg, 5355f595a68aSyz147064 &attr.wa_bsstype)) != DLADM_STATUS_OK) { 535633343a97Smeem die("invalid bsstype '%s'", optarg); 5357f595a68aSyz147064 } 535833343a97Smeem 5359f595a68aSyz147064 attr.wa_valid |= DLADM_WLAN_ATTR_BSSTYPE; 53600ba2cbe9Sxc151355 break; 53610ba2cbe9Sxc151355 case 's': 5362f595a68aSyz147064 if ((status = dladm_wlan_str2secmode(optarg, 5363f595a68aSyz147064 &attr.wa_secmode)) != DLADM_STATUS_OK) { 536433343a97Smeem die("invalid security mode '%s'", optarg); 5365f595a68aSyz147064 } 536633343a97Smeem 5367f595a68aSyz147064 attr.wa_valid |= DLADM_WLAN_ATTR_SECMODE; 53680ba2cbe9Sxc151355 break; 53690ba2cbe9Sxc151355 case 'k': 5370a399b765Szf162725 if (parse_wlan_keys(optarg, &keys, &key_count) < 0) 537133343a97Smeem die("invalid key(s) '%s'", optarg); 537233343a97Smeem 5373a399b765Szf162725 if (keys[0].wk_class == DLADM_SECOBJ_CLASS_WEP) 5374f595a68aSyz147064 keysecmode = DLADM_WLAN_SECMODE_WEP; 5375a399b765Szf162725 else 5376a399b765Szf162725 keysecmode = DLADM_WLAN_SECMODE_WPA; 53770ba2cbe9Sxc151355 break; 53780ba2cbe9Sxc151355 case 'T': 53790ba2cbe9Sxc151355 if (strcasecmp(optarg, "forever") == 0) { 53800ba2cbe9Sxc151355 timeout = -1; 53810ba2cbe9Sxc151355 break; 53820ba2cbe9Sxc151355 } 538333343a97Smeem if (!str2int(optarg, &timeout) || timeout < 0) 538433343a97Smeem die("invalid timeout value '%s'", optarg); 53850ba2cbe9Sxc151355 break; 53860ba2cbe9Sxc151355 case 'c': 5387f595a68aSyz147064 flags |= DLADM_WLAN_CONNECT_CREATEIBSS; 5388a399b765Szf162725 flags |= DLADM_WLAN_CONNECT_CREATEIBSS; 53890ba2cbe9Sxc151355 break; 53900ba2cbe9Sxc151355 default: 53918d5c46e6Sam223141 die_opterr(optopt, option, use); 53920ba2cbe9Sxc151355 break; 53930ba2cbe9Sxc151355 } 53940ba2cbe9Sxc151355 } 53950ba2cbe9Sxc151355 5396f595a68aSyz147064 if (keysecmode == DLADM_WLAN_SECMODE_NONE) { 5397a399b765Szf162725 if ((attr.wa_valid & DLADM_WLAN_ATTR_SECMODE) != 0) { 5398a399b765Szf162725 die("key required for security mode '%s'", 5399a399b765Szf162725 dladm_wlan_secmode2str(&attr.wa_secmode, buf)); 5400a399b765Szf162725 } 54010ba2cbe9Sxc151355 } else { 5402f595a68aSyz147064 if ((attr.wa_valid & DLADM_WLAN_ATTR_SECMODE) != 0 && 540333343a97Smeem attr.wa_secmode != keysecmode) 540433343a97Smeem die("incompatible -s and -k options"); 5405f595a68aSyz147064 attr.wa_valid |= DLADM_WLAN_ATTR_SECMODE; 5406a399b765Szf162725 attr.wa_secmode = keysecmode; 5407a399b765Szf162725 } 54080ba2cbe9Sxc151355 5409d62bc4baSyz147064 if (optind == (argc - 1)) { 54104ac67f02SAnurag S. Maskey if ((status = dladm_name2info(handle, argv[optind], &linkid, 54114ac67f02SAnurag S. Maskey NULL, NULL, NULL)) != DLADM_STATUS_OK) { 5412d62bc4baSyz147064 die_dlerr(status, "link %s is not valid", argv[optind]); 5413d62bc4baSyz147064 } 5414d62bc4baSyz147064 } else if (optind != argc) { 54150ba2cbe9Sxc151355 usage(); 5416d62bc4baSyz147064 } 54170ba2cbe9Sxc151355 5418d62bc4baSyz147064 if (linkid == DATALINK_ALL_LINKID) { 54190ba2cbe9Sxc151355 wlan_count_attr_t wcattr; 54200ba2cbe9Sxc151355 5421d62bc4baSyz147064 wcattr.wc_linkid = DATALINK_INVALID_LINKID; 54220ba2cbe9Sxc151355 wcattr.wc_count = 0; 54234ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(do_count_wlan, handle, &wcattr, 5424d62bc4baSyz147064 DATALINK_CLASS_PHYS, DL_WIFI, DLADM_OPT_ACTIVE); 54250ba2cbe9Sxc151355 if (wcattr.wc_count == 0) { 542633343a97Smeem die("no wifi links are available"); 54270ba2cbe9Sxc151355 } else if (wcattr.wc_count > 1) { 542833343a97Smeem die("link name is required when more than one wifi " 542933343a97Smeem "link is available"); 54300ba2cbe9Sxc151355 } 5431d62bc4baSyz147064 linkid = wcattr.wc_linkid; 54320ba2cbe9Sxc151355 } 54330ba2cbe9Sxc151355 attrp = (attr.wa_valid == 0) ? NULL : &attr; 543433343a97Smeem again: 54354ac67f02SAnurag S. Maskey if ((status = dladm_wlan_connect(handle, linkid, attrp, timeout, keys, 5436f595a68aSyz147064 key_count, flags)) != DLADM_STATUS_OK) { 5437f595a68aSyz147064 if ((flags & DLADM_WLAN_CONNECT_NOSCAN) != 0) { 54380ba2cbe9Sxc151355 /* 543933343a97Smeem * Try again with scanning and filtering. 54400ba2cbe9Sxc151355 */ 5441f595a68aSyz147064 flags &= ~DLADM_WLAN_CONNECT_NOSCAN; 544233343a97Smeem goto again; 54430ba2cbe9Sxc151355 } 544433343a97Smeem 5445f595a68aSyz147064 if (status == DLADM_STATUS_NOTFOUND) { 54460ba2cbe9Sxc151355 if (attr.wa_valid == 0) { 544733343a97Smeem die("no wifi networks are available"); 54480ba2cbe9Sxc151355 } else { 544933343a97Smeem die("no wifi networks with the specified " 545033343a97Smeem "criteria are available"); 54510ba2cbe9Sxc151355 } 54520ba2cbe9Sxc151355 } 5453d62bc4baSyz147064 die_dlerr(status, "cannot connect"); 54540ba2cbe9Sxc151355 } 54550ba2cbe9Sxc151355 free(keys); 54560ba2cbe9Sxc151355 } 54570ba2cbe9Sxc151355 54580ba2cbe9Sxc151355 /* ARGSUSED */ 5459d62bc4baSyz147064 static int 54604ac67f02SAnurag S. Maskey do_all_disconnect_wifi(dladm_handle_t dh, datalink_id_t linkid, void *arg) 54610ba2cbe9Sxc151355 { 5462f595a68aSyz147064 dladm_status_t status; 54630ba2cbe9Sxc151355 54644ac67f02SAnurag S. Maskey status = dladm_wlan_disconnect(dh, linkid); 5465f595a68aSyz147064 if (status != DLADM_STATUS_OK) 5466d62bc4baSyz147064 warn_dlerr(status, "cannot disconnect link"); 546733343a97Smeem 5468d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 54690ba2cbe9Sxc151355 } 54700ba2cbe9Sxc151355 54710ba2cbe9Sxc151355 static void 54728d5c46e6Sam223141 do_disconnect_wifi(int argc, char **argv, const char *use) 54730ba2cbe9Sxc151355 { 54740ba2cbe9Sxc151355 int option; 5475d62bc4baSyz147064 datalink_id_t linkid = DATALINK_ALL_LINKID; 54760ba2cbe9Sxc151355 boolean_t all_links = B_FALSE; 5477f595a68aSyz147064 dladm_status_t status; 54780ba2cbe9Sxc151355 wlan_count_attr_t wcattr; 54790ba2cbe9Sxc151355 54800ba2cbe9Sxc151355 opterr = 0; 54810ba2cbe9Sxc151355 while ((option = getopt_long(argc, argv, ":a", 54820ba2cbe9Sxc151355 wifi_longopts, NULL)) != -1) { 54830ba2cbe9Sxc151355 switch (option) { 54840ba2cbe9Sxc151355 case 'a': 54850ba2cbe9Sxc151355 all_links = B_TRUE; 54860ba2cbe9Sxc151355 break; 54870ba2cbe9Sxc151355 default: 54888d5c46e6Sam223141 die_opterr(optopt, option, use); 54890ba2cbe9Sxc151355 break; 54900ba2cbe9Sxc151355 } 54910ba2cbe9Sxc151355 } 54920ba2cbe9Sxc151355 5493d62bc4baSyz147064 if (optind == (argc - 1)) { 54944ac67f02SAnurag S. Maskey if ((status = dladm_name2info(handle, argv[optind], &linkid, 54954ac67f02SAnurag S. Maskey NULL, NULL, NULL)) != DLADM_STATUS_OK) { 5496d62bc4baSyz147064 die_dlerr(status, "link %s is not valid", argv[optind]); 5497d62bc4baSyz147064 } 5498d62bc4baSyz147064 } else if (optind != argc) { 54990ba2cbe9Sxc151355 usage(); 5500d62bc4baSyz147064 } 55010ba2cbe9Sxc151355 5502d62bc4baSyz147064 if (linkid == DATALINK_ALL_LINKID) { 55030ba2cbe9Sxc151355 if (!all_links) { 5504d62bc4baSyz147064 wcattr.wc_linkid = linkid; 55050ba2cbe9Sxc151355 wcattr.wc_count = 0; 55064ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(do_count_wlan, handle, 55074ac67f02SAnurag S. Maskey &wcattr, DATALINK_CLASS_PHYS, DL_WIFI, 55084ac67f02SAnurag S. Maskey DLADM_OPT_ACTIVE); 55090ba2cbe9Sxc151355 if (wcattr.wc_count == 0) { 551033343a97Smeem die("no wifi links are available"); 55110ba2cbe9Sxc151355 } else if (wcattr.wc_count > 1) { 551233343a97Smeem die("link name is required when more than " 551333343a97Smeem "one wifi link is available"); 55140ba2cbe9Sxc151355 } 5515d62bc4baSyz147064 linkid = wcattr.wc_linkid; 55160ba2cbe9Sxc151355 } else { 5517d62bc4baSyz147064 (void) dladm_walk_datalink_id(do_all_disconnect_wifi, 55184ac67f02SAnurag S. Maskey handle, NULL, DATALINK_CLASS_PHYS, DL_WIFI, 5519d62bc4baSyz147064 DLADM_OPT_ACTIVE); 55200ba2cbe9Sxc151355 return; 55210ba2cbe9Sxc151355 } 55220ba2cbe9Sxc151355 } 55234ac67f02SAnurag S. Maskey status = dladm_wlan_disconnect(handle, linkid); 5524f595a68aSyz147064 if (status != DLADM_STATUS_OK) 5525d62bc4baSyz147064 die_dlerr(status, "cannot disconnect"); 55260ba2cbe9Sxc151355 } 55270ba2cbe9Sxc151355 55280ba2cbe9Sxc151355 static void 5529d62bc4baSyz147064 print_linkprop(datalink_id_t linkid, show_linkprop_state_t *statep, 55304ac67f02SAnurag S. Maskey const char *propname, dladm_prop_type_t type, const char *format, 55314ac67f02SAnurag S. Maskey char **pptr) 55320ba2cbe9Sxc151355 { 55330ba2cbe9Sxc151355 int i; 55340ba2cbe9Sxc151355 char *ptr, *lim; 55350ba2cbe9Sxc151355 char buf[DLADM_STRSIZE]; 5536da14cebeSEric Cheng char *unknown = "--", *notsup = ""; 55370ba2cbe9Sxc151355 char **propvals = statep->ls_propvals; 5538d62bc4baSyz147064 uint_t valcnt = DLADM_MAX_PROP_VALCNT; 55390ba2cbe9Sxc151355 dladm_status_t status; 55400ba2cbe9Sxc151355 55414ac67f02SAnurag S. Maskey status = dladm_get_linkprop(handle, linkid, type, propname, propvals, 55424ac67f02SAnurag S. Maskey &valcnt); 55430ba2cbe9Sxc151355 if (status != DLADM_STATUS_OK) { 5544f595a68aSyz147064 if (status == DLADM_STATUS_TEMPONLY) { 5545d62bc4baSyz147064 if (type == DLADM_PROP_VAL_MODIFIABLE && 5546d62bc4baSyz147064 statep->ls_persist) { 5547d62bc4baSyz147064 valcnt = 1; 5548d62bc4baSyz147064 propvals = &unknown; 5549d62bc4baSyz147064 } else { 5550f595a68aSyz147064 statep->ls_status = status; 5551e7801d59Ssowmini statep->ls_retstatus = status; 5552f595a68aSyz147064 return; 5553d62bc4baSyz147064 } 5554f595a68aSyz147064 } else if (status == DLADM_STATUS_NOTSUP || 5555f595a68aSyz147064 statep->ls_persist) { 55560ba2cbe9Sxc151355 valcnt = 1; 5557afdda45fSVasumathi Sundaram - Sun Microsystems if (type == DLADM_PROP_VAL_CURRENT || 5558afdda45fSVasumathi Sundaram - Sun Microsystems type == DLADM_PROP_VAL_PERM) 55590ba2cbe9Sxc151355 propvals = &unknown; 55600ba2cbe9Sxc151355 else 55610ba2cbe9Sxc151355 propvals = ¬sup; 5562149b7eb2SSowmini Varadhan } else if (status == DLADM_STATUS_NOTDEFINED) { 5563149b7eb2SSowmini Varadhan propvals = ¬sup; /* STR_UNDEF_VAL */ 55640ba2cbe9Sxc151355 } else { 5565e7801d59Ssowmini if (statep->ls_proplist && 5566e7801d59Ssowmini statep->ls_status == DLADM_STATUS_OK) { 5567f595a68aSyz147064 warn_dlerr(status, 5568f595a68aSyz147064 "cannot get link property '%s' for %s", 5569f595a68aSyz147064 propname, statep->ls_link); 5570d62bc4baSyz147064 } 5571e7801d59Ssowmini statep->ls_status = status; 5572e7801d59Ssowmini statep->ls_retstatus = status; 5573f595a68aSyz147064 return; 55740ba2cbe9Sxc151355 } 55750ba2cbe9Sxc151355 } 55760ba2cbe9Sxc151355 5577e7801d59Ssowmini statep->ls_status = DLADM_STATUS_OK; 5578e7801d59Ssowmini 55790ba2cbe9Sxc151355 ptr = buf; 55800ba2cbe9Sxc151355 lim = buf + DLADM_STRSIZE; 55810ba2cbe9Sxc151355 for (i = 0; i < valcnt; i++) { 55820ba2cbe9Sxc151355 if (propvals[i][0] == '\0' && !statep->ls_parseable) 5583e7801d59Ssowmini ptr += snprintf(ptr, lim - ptr, STR_UNDEF_VAL","); 55840ba2cbe9Sxc151355 else 55850ba2cbe9Sxc151355 ptr += snprintf(ptr, lim - ptr, "%s,", propvals[i]); 55860ba2cbe9Sxc151355 if (ptr >= lim) 55870ba2cbe9Sxc151355 break; 55880ba2cbe9Sxc151355 } 55890ba2cbe9Sxc151355 if (valcnt > 0) 55900ba2cbe9Sxc151355 buf[strlen(buf) - 1] = '\0'; 55910ba2cbe9Sxc151355 55920ba2cbe9Sxc151355 lim = statep->ls_line + MAX_PROP_LINE; 55930ba2cbe9Sxc151355 if (statep->ls_parseable) { 55940ba2cbe9Sxc151355 *pptr += snprintf(*pptr, lim - *pptr, 5595e7801d59Ssowmini "%s", buf); 55960ba2cbe9Sxc151355 } else { 55970ba2cbe9Sxc151355 *pptr += snprintf(*pptr, lim - *pptr, format, buf); 55980ba2cbe9Sxc151355 } 55990ba2cbe9Sxc151355 } 56000ba2cbe9Sxc151355 5601e7801d59Ssowmini static char * 5602e7801d59Ssowmini linkprop_callback(print_field_t *pf, void *ls_arg) 5603e7801d59Ssowmini { 5604e7801d59Ssowmini linkprop_args_t *arg = ls_arg; 5605e7801d59Ssowmini char *propname = arg->ls_propname; 5606e7801d59Ssowmini show_linkprop_state_t *statep = arg->ls_state; 5607e7801d59Ssowmini char *ptr = statep->ls_line; 5608e7801d59Ssowmini char *lim = ptr + MAX_PROP_LINE; 5609e7801d59Ssowmini datalink_id_t linkid = arg->ls_linkid; 5610e7801d59Ssowmini 5611e7801d59Ssowmini switch (pf->pf_index) { 5612e7801d59Ssowmini case LINKPROP_LINK: 5613e7801d59Ssowmini (void) snprintf(ptr, lim - ptr, "%s", statep->ls_link); 5614e7801d59Ssowmini break; 5615e7801d59Ssowmini case LINKPROP_PROPERTY: 5616e7801d59Ssowmini (void) snprintf(ptr, lim - ptr, "%s", propname); 5617e7801d59Ssowmini break; 5618e7801d59Ssowmini case LINKPROP_VALUE: 5619e7801d59Ssowmini print_linkprop(linkid, statep, propname, 5620e7801d59Ssowmini statep->ls_persist ? DLADM_PROP_VAL_PERSISTENT : 5621e7801d59Ssowmini DLADM_PROP_VAL_CURRENT, "%s", &ptr); 5622e7801d59Ssowmini /* 5623e7801d59Ssowmini * If we failed to query the link property, for example, query 5624e7801d59Ssowmini * the persistent value of a non-persistable link property, 5625e7801d59Ssowmini * simply skip the output. 5626e7801d59Ssowmini */ 5627e7801d59Ssowmini if (statep->ls_status != DLADM_STATUS_OK) 5628e7801d59Ssowmini goto skip; 5629e7801d59Ssowmini ptr = statep->ls_line; 5630e7801d59Ssowmini break; 5631afdda45fSVasumathi Sundaram - Sun Microsystems case LINKPROP_PERM: 5632afdda45fSVasumathi Sundaram - Sun Microsystems print_linkprop(linkid, statep, propname, 5633afdda45fSVasumathi Sundaram - Sun Microsystems DLADM_PROP_VAL_PERM, "%s", &ptr); 5634afdda45fSVasumathi Sundaram - Sun Microsystems if (statep->ls_status != DLADM_STATUS_OK) 5635afdda45fSVasumathi Sundaram - Sun Microsystems goto skip; 5636afdda45fSVasumathi Sundaram - Sun Microsystems ptr = statep->ls_line; 5637afdda45fSVasumathi Sundaram - Sun Microsystems break; 5638e7801d59Ssowmini case LINKPROP_DEFAULT: 5639e7801d59Ssowmini print_linkprop(linkid, statep, propname, 5640e7801d59Ssowmini DLADM_PROP_VAL_DEFAULT, "%s", &ptr); 5641e7801d59Ssowmini if (statep->ls_status != DLADM_STATUS_OK) 5642e7801d59Ssowmini goto skip; 5643e7801d59Ssowmini ptr = statep->ls_line; 5644e7801d59Ssowmini break; 5645e7801d59Ssowmini case LINKPROP_POSSIBLE: 5646e7801d59Ssowmini print_linkprop(linkid, statep, propname, 5647e7801d59Ssowmini DLADM_PROP_VAL_MODIFIABLE, "%s ", &ptr); 5648e7801d59Ssowmini if (statep->ls_status != DLADM_STATUS_OK) 5649e7801d59Ssowmini goto skip; 5650e7801d59Ssowmini ptr = statep->ls_line; 5651e7801d59Ssowmini break; 5652e7801d59Ssowmini default: 5653e7801d59Ssowmini die("invalid input"); 5654e7801d59Ssowmini break; 5655e7801d59Ssowmini } 5656e7801d59Ssowmini return (ptr); 5657e7801d59Ssowmini skip: 5658e7801d59Ssowmini if (statep->ls_status != DLADM_STATUS_OK) 5659e7801d59Ssowmini return (NULL); 5660e7801d59Ssowmini else 5661e7801d59Ssowmini return (""); 5662e7801d59Ssowmini } 5663e7801d59Ssowmini 5664bcb5c89dSSowmini Varadhan static boolean_t 5665bcb5c89dSSowmini Varadhan linkprop_is_supported(datalink_id_t linkid, const char *propname, 5666bcb5c89dSSowmini Varadhan show_linkprop_state_t *statep) 5667bcb5c89dSSowmini Varadhan { 5668bcb5c89dSSowmini Varadhan dladm_status_t status; 5669bcb5c89dSSowmini Varadhan uint_t valcnt = DLADM_MAX_PROP_VALCNT; 5670bcb5c89dSSowmini Varadhan 56714784fcbdSSowmini Varadhan /* if used with -p flag, always print output */ 56724784fcbdSSowmini Varadhan if (statep->ls_proplist != NULL) 56734784fcbdSSowmini Varadhan return (B_TRUE); 56744784fcbdSSowmini Varadhan 56754ac67f02SAnurag S. Maskey status = dladm_get_linkprop(handle, linkid, DLADM_PROP_VAL_DEFAULT, 5676bcb5c89dSSowmini Varadhan propname, statep->ls_propvals, &valcnt); 5677bcb5c89dSSowmini Varadhan 5678149b7eb2SSowmini Varadhan if (status == DLADM_STATUS_OK) 5679149b7eb2SSowmini Varadhan return (B_TRUE); 5680149b7eb2SSowmini Varadhan 5681149b7eb2SSowmini Varadhan /* 5682149b7eb2SSowmini Varadhan * A system wide default value is not available for the 5683149b7eb2SSowmini Varadhan * property. Check if current value can be retrieved. 5684149b7eb2SSowmini Varadhan */ 56854ac67f02SAnurag S. Maskey status = dladm_get_linkprop(handle, linkid, DLADM_PROP_VAL_CURRENT, 5686149b7eb2SSowmini Varadhan propname, statep->ls_propvals, &valcnt); 5687149b7eb2SSowmini Varadhan 5688149b7eb2SSowmini Varadhan return (status == DLADM_STATUS_OK); 5689bcb5c89dSSowmini Varadhan } 5690bcb5c89dSSowmini Varadhan 56914ac67f02SAnurag S. Maskey /* ARGSUSED */ 5692d62bc4baSyz147064 static int 56934ac67f02SAnurag S. Maskey show_linkprop(dladm_handle_t dh, datalink_id_t linkid, const char *propname, 56944ac67f02SAnurag S. Maskey void *arg) 56950ba2cbe9Sxc151355 { 56960ba2cbe9Sxc151355 show_linkprop_state_t *statep = arg; 5697e7801d59Ssowmini linkprop_args_t ls_arg; 56980ba2cbe9Sxc151355 5699e7801d59Ssowmini bzero(&ls_arg, sizeof (ls_arg)); 5700e7801d59Ssowmini ls_arg.ls_state = statep; 5701e7801d59Ssowmini ls_arg.ls_propname = (char *)propname; 5702e7801d59Ssowmini ls_arg.ls_linkid = linkid; 57030ba2cbe9Sxc151355 57040ba2cbe9Sxc151355 if (statep->ls_header) { 57050ba2cbe9Sxc151355 statep->ls_header = B_FALSE; 57060ba2cbe9Sxc151355 if (!statep->ls_parseable) 5707e7801d59Ssowmini print_header(&statep->ls_print); 57080ba2cbe9Sxc151355 } 570962ee1d25SArtem Kachitchkine /* 571062ee1d25SArtem Kachitchkine * This will need to be fixed when kernel interfaces are added 571162ee1d25SArtem Kachitchkine * to enable walking of all known private properties. For now, 571262ee1d25SArtem Kachitchkine * we are limited to walking persistent private properties only. 571362ee1d25SArtem Kachitchkine */ 571462ee1d25SArtem Kachitchkine if ((propname[0] == '_') && !statep->ls_persist && 571562ee1d25SArtem Kachitchkine (statep->ls_proplist == NULL)) 571662ee1d25SArtem Kachitchkine return (DLADM_WALK_CONTINUE); 5717149b7eb2SSowmini Varadhan if (!statep->ls_parseable && 5718149b7eb2SSowmini Varadhan !linkprop_is_supported(linkid, propname, statep)) 5719bcb5c89dSSowmini Varadhan return (DLADM_WALK_CONTINUE); 5720bcb5c89dSSowmini Varadhan 5721e7801d59Ssowmini dladm_print_output(&statep->ls_print, statep->ls_parseable, 5722e7801d59Ssowmini linkprop_callback, (void *)&ls_arg); 5723e7801d59Ssowmini 5724d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 57250ba2cbe9Sxc151355 } 57260ba2cbe9Sxc151355 57270ba2cbe9Sxc151355 static void 57288d5c46e6Sam223141 do_show_linkprop(int argc, char **argv, const char *use) 57290ba2cbe9Sxc151355 { 5730f4b3ec61Sdh155122 int option; 5731*63a6526dSMichael Lim char propstr[DLADM_STRSIZE]; 5732da14cebeSEric Cheng dladm_arg_list_t *proplist = NULL; 5733d62bc4baSyz147064 datalink_id_t linkid = DATALINK_ALL_LINKID; 57340ba2cbe9Sxc151355 show_linkprop_state_t state; 5735d62bc4baSyz147064 uint32_t flags = DLADM_OPT_ACTIVE; 5736d62bc4baSyz147064 dladm_status_t status; 5737e7801d59Ssowmini char *fields_str = NULL; 5738e7801d59Ssowmini print_field_t **fields; 5739e7801d59Ssowmini uint_t nfields; 57400d365605Sschuster boolean_t o_arg = B_FALSE; 5741e7801d59Ssowmini char *all_fields = 5742afdda45fSVasumathi Sundaram - Sun Microsystems "link,property,perm,value,default,possible"; 5743e7801d59Ssowmini 5744e7801d59Ssowmini fields_str = all_fields; 57450ba2cbe9Sxc151355 5746*63a6526dSMichael Lim bzero(propstr, DLADM_STRSIZE); 57470ba2cbe9Sxc151355 opterr = 0; 57480ba2cbe9Sxc151355 state.ls_propvals = NULL; 57490ba2cbe9Sxc151355 state.ls_line = NULL; 57500ba2cbe9Sxc151355 state.ls_parseable = B_FALSE; 57510ba2cbe9Sxc151355 state.ls_persist = B_FALSE; 57520ba2cbe9Sxc151355 state.ls_header = B_TRUE; 5753e7801d59Ssowmini state.ls_retstatus = DLADM_STATUS_OK; 5754*63a6526dSMichael Lim 5755e7801d59Ssowmini while ((option = getopt_long(argc, argv, ":p:cPo:", 57560ba2cbe9Sxc151355 prop_longopts, NULL)) != -1) { 57570ba2cbe9Sxc151355 switch (option) { 57580ba2cbe9Sxc151355 case 'p': 5759*63a6526dSMichael Lim (void) strlcat(propstr, optarg, DLADM_STRSIZE); 5760*63a6526dSMichael Lim if (strlcat(propstr, ",", DLADM_STRSIZE) >= 5761*63a6526dSMichael Lim DLADM_STRSIZE) 5762*63a6526dSMichael Lim die("property list too long '%s'", propstr); 57630ba2cbe9Sxc151355 break; 57640ba2cbe9Sxc151355 case 'c': 57650ba2cbe9Sxc151355 state.ls_parseable = B_TRUE; 57660ba2cbe9Sxc151355 break; 57670ba2cbe9Sxc151355 case 'P': 57680ba2cbe9Sxc151355 state.ls_persist = B_TRUE; 5769d62bc4baSyz147064 flags = DLADM_OPT_PERSIST; 57700ba2cbe9Sxc151355 break; 5771e7801d59Ssowmini case 'o': 57720d365605Sschuster o_arg = B_TRUE; 5773e7801d59Ssowmini if (strcasecmp(optarg, "all") == 0) 5774e7801d59Ssowmini fields_str = all_fields; 5775e7801d59Ssowmini else 5776e7801d59Ssowmini fields_str = optarg; 5777e7801d59Ssowmini break; 57780ba2cbe9Sxc151355 default: 57798d5c46e6Sam223141 die_opterr(optopt, option, use); 57800ba2cbe9Sxc151355 break; 57810ba2cbe9Sxc151355 } 57820ba2cbe9Sxc151355 } 57830ba2cbe9Sxc151355 57840d365605Sschuster if (state.ls_parseable && !o_arg) 57850d365605Sschuster die("-c requires -o"); 57860d365605Sschuster 57870d365605Sschuster if (state.ls_parseable && fields_str == all_fields) 57880d365605Sschuster die("\"-o all\" is invalid with -c"); 57890d365605Sschuster 5790d62bc4baSyz147064 if (optind == (argc - 1)) { 57914ac67f02SAnurag S. Maskey if ((status = dladm_name2info(handle, argv[optind], &linkid, 57924ac67f02SAnurag S. Maskey NULL, NULL, NULL)) != DLADM_STATUS_OK) { 5793d62bc4baSyz147064 die_dlerr(status, "link %s is not valid", argv[optind]); 5794d62bc4baSyz147064 } 5795d62bc4baSyz147064 } else if (optind != argc) { 57960ba2cbe9Sxc151355 usage(); 5797d62bc4baSyz147064 } 57980ba2cbe9Sxc151355 5799*63a6526dSMichael Lim if (dladm_parse_link_props(propstr, &proplist, B_TRUE) 5800*63a6526dSMichael Lim != DLADM_STATUS_OK) 5801*63a6526dSMichael Lim die("invalid link properties specified"); 5802*63a6526dSMichael Lim 5803e7801d59Ssowmini bzero(&state.ls_print, sizeof (print_state_t)); 5804f4b3ec61Sdh155122 state.ls_proplist = proplist; 5805f595a68aSyz147064 state.ls_status = DLADM_STATUS_OK; 5806f4b3ec61Sdh155122 5807e7801d59Ssowmini fields = parse_output_fields(fields_str, linkprop_fields, 5808e7801d59Ssowmini LINKPROP_MAX_FIELDS, CMD_TYPE_ANY, &nfields); 5809e7801d59Ssowmini 5810e7801d59Ssowmini if (fields == NULL) { 5811e7801d59Ssowmini die("invalid field(s) specified"); 5812e7801d59Ssowmini return; 5813e7801d59Ssowmini } 5814e7801d59Ssowmini 5815e7801d59Ssowmini state.ls_print.ps_fields = fields; 5816e7801d59Ssowmini state.ls_print.ps_nfields = nfields; 5817d62bc4baSyz147064 if (linkid == DATALINK_ALL_LINKID) { 58184ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(show_linkprop_onelink, handle, 58194ac67f02SAnurag S. Maskey &state, DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE, flags); 5820f4b3ec61Sdh155122 } else { 58214ac67f02SAnurag S. Maskey (void) show_linkprop_onelink(handle, linkid, &state); 5822f4b3ec61Sdh155122 } 5823da14cebeSEric Cheng dladm_free_props(proplist); 5824f595a68aSyz147064 58254ac67f02SAnurag S. Maskey if (state.ls_retstatus != DLADM_STATUS_OK) { 58264ac67f02SAnurag S. Maskey dladm_close(handle); 5827f595a68aSyz147064 exit(EXIT_FAILURE); 5828f4b3ec61Sdh155122 } 58294ac67f02SAnurag S. Maskey } 5830f4b3ec61Sdh155122 5831d62bc4baSyz147064 static int 58324ac67f02SAnurag S. Maskey show_linkprop_onelink(dladm_handle_t hdl, datalink_id_t linkid, void *arg) 5833f4b3ec61Sdh155122 { 5834948f2876Sss150715 int i; 5835f4b3ec61Sdh155122 char *buf; 5836d62bc4baSyz147064 uint32_t flags; 5837da14cebeSEric Cheng dladm_arg_list_t *proplist = NULL; 5838d62bc4baSyz147064 show_linkprop_state_t *statep = arg; 5839d62bc4baSyz147064 dlpi_handle_t dh = NULL; 5840f4b3ec61Sdh155122 5841d62bc4baSyz147064 statep->ls_status = DLADM_STATUS_OK; 5842d62bc4baSyz147064 58434ac67f02SAnurag S. Maskey if (dladm_datalink_id2info(hdl, linkid, &flags, NULL, NULL, 58444ac67f02SAnurag S. Maskey statep->ls_link, MAXLINKNAMELEN) != DLADM_STATUS_OK) { 5845d62bc4baSyz147064 statep->ls_status = DLADM_STATUS_NOTFOUND; 5846d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 5847d62bc4baSyz147064 } 5848d62bc4baSyz147064 5849d62bc4baSyz147064 if ((statep->ls_persist && !(flags & DLADM_OPT_PERSIST)) || 5850d62bc4baSyz147064 (!statep->ls_persist && !(flags & DLADM_OPT_ACTIVE))) { 5851d62bc4baSyz147064 statep->ls_status = DLADM_STATUS_BADARG; 5852d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 5853d62bc4baSyz147064 } 5854d62bc4baSyz147064 5855f4b3ec61Sdh155122 proplist = statep->ls_proplist; 58560ba2cbe9Sxc151355 58570ba2cbe9Sxc151355 /* 58580ba2cbe9Sxc151355 * When some WiFi links are opened for the first time, their hardware 58590ba2cbe9Sxc151355 * automatically scans for APs and does other slow operations. Thus, 58600ba2cbe9Sxc151355 * if there are no open links, the retrieval of link properties 58610ba2cbe9Sxc151355 * (below) will proceed slowly unless we hold the link open. 5862d62bc4baSyz147064 * 5863d62bc4baSyz147064 * Note that failure of dlpi_open() does not necessarily mean invalid 5864d62bc4baSyz147064 * link properties, because dlpi_open() may fail because of incorrect 5865d62bc4baSyz147064 * autopush configuration. Therefore, we ingore the return value of 5866d62bc4baSyz147064 * dlpi_open(). 58670ba2cbe9Sxc151355 */ 5868d62bc4baSyz147064 if (!statep->ls_persist) 5869d62bc4baSyz147064 (void) dlpi_open(statep->ls_link, &dh, 0); 58700ba2cbe9Sxc151355 5871d62bc4baSyz147064 buf = malloc((sizeof (char *) + DLADM_PROP_VAL_MAX) * 5872d62bc4baSyz147064 DLADM_MAX_PROP_VALCNT + MAX_PROP_LINE); 587333343a97Smeem if (buf == NULL) 587433343a97Smeem die("insufficient memory"); 587533343a97Smeem 5876f4b3ec61Sdh155122 statep->ls_propvals = (char **)(void *)buf; 5877d62bc4baSyz147064 for (i = 0; i < DLADM_MAX_PROP_VALCNT; i++) { 5878d62bc4baSyz147064 statep->ls_propvals[i] = buf + 5879d62bc4baSyz147064 sizeof (char *) * DLADM_MAX_PROP_VALCNT + 58800ba2cbe9Sxc151355 i * DLADM_PROP_VAL_MAX; 58810ba2cbe9Sxc151355 } 5882f4b3ec61Sdh155122 statep->ls_line = buf + 5883d62bc4baSyz147064 (sizeof (char *) + DLADM_PROP_VAL_MAX) * DLADM_MAX_PROP_VALCNT; 58840ba2cbe9Sxc151355 58850ba2cbe9Sxc151355 if (proplist != NULL) { 5886da14cebeSEric Cheng for (i = 0; i < proplist->al_count; i++) { 58874ac67f02SAnurag S. Maskey (void) show_linkprop(hdl, linkid, 5888da14cebeSEric Cheng proplist->al_info[i].ai_name, statep); 58890ba2cbe9Sxc151355 } 5890d62bc4baSyz147064 } else { 58914ac67f02SAnurag S. Maskey (void) dladm_walk_linkprop(hdl, linkid, statep, 58924ac67f02SAnurag S. Maskey show_linkprop); 5893d62bc4baSyz147064 } 5894d62bc4baSyz147064 if (dh != NULL) 5895948f2876Sss150715 dlpi_close(dh); 58960ba2cbe9Sxc151355 free(buf); 5897d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 58980ba2cbe9Sxc151355 } 58990ba2cbe9Sxc151355 59000ba2cbe9Sxc151355 static dladm_status_t 5901d62bc4baSyz147064 set_linkprop_persist(datalink_id_t linkid, const char *prop_name, 5902d62bc4baSyz147064 char **prop_val, uint_t val_cnt, boolean_t reset) 59030ba2cbe9Sxc151355 { 59040ba2cbe9Sxc151355 dladm_status_t status; 59050ba2cbe9Sxc151355 59064ac67f02SAnurag S. Maskey status = dladm_set_linkprop(handle, linkid, prop_name, prop_val, 59074ac67f02SAnurag S. Maskey val_cnt, DLADM_OPT_PERSIST); 59080ba2cbe9Sxc151355 59090ba2cbe9Sxc151355 if (status != DLADM_STATUS_OK) { 5910da14cebeSEric Cheng warn_dlerr(status, "cannot persistently %s link property '%s'", 5911da14cebeSEric Cheng reset ? "reset" : "set", prop_name); 59120ba2cbe9Sxc151355 } 59130ba2cbe9Sxc151355 return (status); 59140ba2cbe9Sxc151355 } 59150ba2cbe9Sxc151355 5916da14cebeSEric Cheng static int 59174ac67f02SAnurag S. Maskey reset_one_linkprop(dladm_handle_t dh, datalink_id_t linkid, 59184ac67f02SAnurag S. Maskey const char *propname, void *arg) 5919da14cebeSEric Cheng { 5920da14cebeSEric Cheng set_linkprop_state_t *statep = arg; 5921da14cebeSEric Cheng dladm_status_t status; 5922da14cebeSEric Cheng 59234ac67f02SAnurag S. Maskey status = dladm_set_linkprop(dh, linkid, propname, NULL, 0, 5924da14cebeSEric Cheng DLADM_OPT_ACTIVE); 5925da14cebeSEric Cheng if (status != DLADM_STATUS_OK) { 5926da14cebeSEric Cheng warn_dlerr(status, "cannot reset link property '%s' on '%s'", 5927da14cebeSEric Cheng propname, statep->ls_name); 5928da14cebeSEric Cheng } 5929da14cebeSEric Cheng if (!statep->ls_temp) { 5930da14cebeSEric Cheng dladm_status_t s; 5931da14cebeSEric Cheng 5932da14cebeSEric Cheng s = set_linkprop_persist(linkid, propname, NULL, 0, 5933da14cebeSEric Cheng statep->ls_reset); 5934da14cebeSEric Cheng if (s != DLADM_STATUS_OK) 5935da14cebeSEric Cheng status = s; 5936da14cebeSEric Cheng } 5937da14cebeSEric Cheng if (status != DLADM_STATUS_OK) 5938da14cebeSEric Cheng statep->ls_status = status; 5939da14cebeSEric Cheng 5940da14cebeSEric Cheng return (DLADM_WALK_CONTINUE); 5941da14cebeSEric Cheng } 5942da14cebeSEric Cheng 59430ba2cbe9Sxc151355 static void 59448d5c46e6Sam223141 set_linkprop(int argc, char **argv, boolean_t reset, const char *use) 59450ba2cbe9Sxc151355 { 59460ba2cbe9Sxc151355 int i, option; 59470ba2cbe9Sxc151355 char errmsg[DLADM_STRSIZE]; 5948d62bc4baSyz147064 char *altroot = NULL; 5949d62bc4baSyz147064 datalink_id_t linkid; 59500ba2cbe9Sxc151355 boolean_t temp = B_FALSE; 59510ba2cbe9Sxc151355 dladm_status_t status = DLADM_STATUS_OK; 5952*63a6526dSMichael Lim char propstr[DLADM_STRSIZE]; 5953da14cebeSEric Cheng dladm_arg_list_t *proplist = NULL; 59540ba2cbe9Sxc151355 59550ba2cbe9Sxc151355 opterr = 0; 5956*63a6526dSMichael Lim bzero(propstr, DLADM_STRSIZE); 5957*63a6526dSMichael Lim 59580ba2cbe9Sxc151355 while ((option = getopt_long(argc, argv, ":p:R:t", 59590ba2cbe9Sxc151355 prop_longopts, NULL)) != -1) { 59600ba2cbe9Sxc151355 switch (option) { 59610ba2cbe9Sxc151355 case 'p': 5962*63a6526dSMichael Lim (void) strlcat(propstr, optarg, DLADM_STRSIZE); 5963*63a6526dSMichael Lim if (strlcat(propstr, ",", DLADM_STRSIZE) >= 5964*63a6526dSMichael Lim DLADM_STRSIZE) 5965*63a6526dSMichael Lim die("property list too long '%s'", propstr); 59660ba2cbe9Sxc151355 break; 59670ba2cbe9Sxc151355 case 't': 59680ba2cbe9Sxc151355 temp = B_TRUE; 59690ba2cbe9Sxc151355 break; 59700ba2cbe9Sxc151355 case 'R': 5971d62bc4baSyz147064 altroot = optarg; 59720ba2cbe9Sxc151355 break; 59730ba2cbe9Sxc151355 default: 59748d5c46e6Sam223141 die_opterr(optopt, option, use); 59758d5c46e6Sam223141 59760ba2cbe9Sxc151355 } 59770ba2cbe9Sxc151355 } 59780ba2cbe9Sxc151355 5979d62bc4baSyz147064 /* get link name (required last argument) */ 5980d62bc4baSyz147064 if (optind != (argc - 1)) 59810ba2cbe9Sxc151355 usage(); 59820ba2cbe9Sxc151355 5983*63a6526dSMichael Lim if (dladm_parse_link_props(propstr, &proplist, reset) != 5984*63a6526dSMichael Lim DLADM_STATUS_OK) 5985*63a6526dSMichael Lim die("invalid link properties specified"); 5986*63a6526dSMichael Lim 5987d62bc4baSyz147064 if (proplist == NULL && !reset) 598833343a97Smeem die("link property must be specified"); 598933343a97Smeem 5990d62bc4baSyz147064 if (altroot != NULL) { 5991da14cebeSEric Cheng dladm_free_props(proplist); 5992d62bc4baSyz147064 altroot_cmd(altroot, argc, argv); 5993d62bc4baSyz147064 } 5994d62bc4baSyz147064 59954ac67f02SAnurag S. Maskey status = dladm_name2info(handle, argv[optind], &linkid, NULL, NULL, 59964ac67f02SAnurag S. Maskey NULL); 5997d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 5998d62bc4baSyz147064 die_dlerr(status, "link %s is not valid", argv[optind]); 5999d62bc4baSyz147064 6000d62bc4baSyz147064 if (proplist == NULL) { 6001da14cebeSEric Cheng set_linkprop_state_t state; 600213994ee8Sxz162242 6003da14cebeSEric Cheng state.ls_name = argv[optind]; 6004da14cebeSEric Cheng state.ls_reset = reset; 6005da14cebeSEric Cheng state.ls_temp = temp; 6006da14cebeSEric Cheng state.ls_status = DLADM_STATUS_OK; 6007da14cebeSEric Cheng 60084ac67f02SAnurag S. Maskey (void) dladm_walk_linkprop(handle, linkid, &state, 60094ac67f02SAnurag S. Maskey reset_one_linkprop); 6010da14cebeSEric Cheng 6011da14cebeSEric Cheng status = state.ls_status; 60120ba2cbe9Sxc151355 goto done; 60130ba2cbe9Sxc151355 } 60140ba2cbe9Sxc151355 6015da14cebeSEric Cheng for (i = 0; i < proplist->al_count; i++) { 6016da14cebeSEric Cheng dladm_arg_info_t *aip = &proplist->al_info[i]; 60170ba2cbe9Sxc151355 char **val; 60180ba2cbe9Sxc151355 uint_t count; 60190ba2cbe9Sxc151355 dladm_status_t s; 60200ba2cbe9Sxc151355 60210ba2cbe9Sxc151355 if (reset) { 60220ba2cbe9Sxc151355 val = NULL; 60230ba2cbe9Sxc151355 count = 0; 60240ba2cbe9Sxc151355 } else { 6025da14cebeSEric Cheng val = aip->ai_val; 6026da14cebeSEric Cheng count = aip->ai_count; 60270ba2cbe9Sxc151355 if (count == 0) { 602833343a97Smeem warn("no value specified for '%s'", 6029da14cebeSEric Cheng aip->ai_name); 60300ba2cbe9Sxc151355 status = DLADM_STATUS_BADARG; 60310ba2cbe9Sxc151355 continue; 60320ba2cbe9Sxc151355 } 60330ba2cbe9Sxc151355 } 60344ac67f02SAnurag S. Maskey s = dladm_set_linkprop(handle, linkid, aip->ai_name, val, count, 6035d62bc4baSyz147064 DLADM_OPT_ACTIVE); 60360ba2cbe9Sxc151355 if (s == DLADM_STATUS_OK) { 60370ba2cbe9Sxc151355 if (!temp) { 6038d62bc4baSyz147064 s = set_linkprop_persist(linkid, 6039da14cebeSEric Cheng aip->ai_name, val, count, reset); 60400ba2cbe9Sxc151355 if (s != DLADM_STATUS_OK) 60410ba2cbe9Sxc151355 status = s; 60420ba2cbe9Sxc151355 } 60430ba2cbe9Sxc151355 continue; 60440ba2cbe9Sxc151355 } 60450ba2cbe9Sxc151355 status = s; 60460ba2cbe9Sxc151355 switch (s) { 60470ba2cbe9Sxc151355 case DLADM_STATUS_NOTFOUND: 6048da14cebeSEric Cheng warn("invalid link property '%s'", aip->ai_name); 60490ba2cbe9Sxc151355 break; 60500ba2cbe9Sxc151355 case DLADM_STATUS_BADVAL: { 60510ba2cbe9Sxc151355 int j; 60520ba2cbe9Sxc151355 char *ptr, *lim; 60530ba2cbe9Sxc151355 char **propvals = NULL; 6054d62bc4baSyz147064 uint_t valcnt = DLADM_MAX_PROP_VALCNT; 60550ba2cbe9Sxc151355 60560ba2cbe9Sxc151355 ptr = malloc((sizeof (char *) + 6057d62bc4baSyz147064 DLADM_PROP_VAL_MAX) * DLADM_MAX_PROP_VALCNT + 60580ba2cbe9Sxc151355 MAX_PROP_LINE); 60590ba2cbe9Sxc151355 60600ba2cbe9Sxc151355 propvals = (char **)(void *)ptr; 606133343a97Smeem if (propvals == NULL) 606233343a97Smeem die("insufficient memory"); 606333343a97Smeem 6064d62bc4baSyz147064 for (j = 0; j < DLADM_MAX_PROP_VALCNT; j++) { 60650ba2cbe9Sxc151355 propvals[j] = ptr + sizeof (char *) * 6066d62bc4baSyz147064 DLADM_MAX_PROP_VALCNT + 60670ba2cbe9Sxc151355 j * DLADM_PROP_VAL_MAX; 60680ba2cbe9Sxc151355 } 60694ac67f02SAnurag S. Maskey s = dladm_get_linkprop(handle, linkid, 6070da14cebeSEric Cheng DLADM_PROP_VAL_MODIFIABLE, aip->ai_name, propvals, 6071d62bc4baSyz147064 &valcnt); 6072d62bc4baSyz147064 6073d62bc4baSyz147064 if (s != DLADM_STATUS_OK) { 6074d62bc4baSyz147064 warn_dlerr(status, "cannot set link property " 6075da14cebeSEric Cheng "'%s' on '%s'", aip->ai_name, argv[optind]); 6076d62bc4baSyz147064 free(propvals); 6077d62bc4baSyz147064 break; 6078d62bc4baSyz147064 } 60790ba2cbe9Sxc151355 60800ba2cbe9Sxc151355 ptr = errmsg; 60810ba2cbe9Sxc151355 lim = ptr + DLADM_STRSIZE; 60820ba2cbe9Sxc151355 *ptr = '\0'; 6083d62bc4baSyz147064 for (j = 0; j < valcnt; j++) { 60840ba2cbe9Sxc151355 ptr += snprintf(ptr, lim - ptr, "%s,", 60850ba2cbe9Sxc151355 propvals[j]); 60860ba2cbe9Sxc151355 if (ptr >= lim) 60870ba2cbe9Sxc151355 break; 60880ba2cbe9Sxc151355 } 6089f4b3ec61Sdh155122 if (ptr > errmsg) { 60900ba2cbe9Sxc151355 *(ptr - 1) = '\0'; 609133343a97Smeem warn("link property '%s' must be one of: %s", 6092da14cebeSEric Cheng aip->ai_name, errmsg); 6093f4b3ec61Sdh155122 } else 6094f4b3ec61Sdh155122 warn("invalid link property '%s'", *val); 60950ba2cbe9Sxc151355 free(propvals); 60960ba2cbe9Sxc151355 break; 60970ba2cbe9Sxc151355 } 60980ba2cbe9Sxc151355 default: 60990ba2cbe9Sxc151355 if (reset) { 610033343a97Smeem warn_dlerr(status, "cannot reset link property " 6101da14cebeSEric Cheng "'%s' on '%s'", aip->ai_name, argv[optind]); 61020ba2cbe9Sxc151355 } else { 610333343a97Smeem warn_dlerr(status, "cannot set link property " 6104da14cebeSEric Cheng "'%s' on '%s'", aip->ai_name, argv[optind]); 61050ba2cbe9Sxc151355 } 61060ba2cbe9Sxc151355 break; 61070ba2cbe9Sxc151355 } 61080ba2cbe9Sxc151355 } 61090ba2cbe9Sxc151355 done: 6110da14cebeSEric Cheng dladm_free_props(proplist); 61114ac67f02SAnurag S. Maskey if (status != DLADM_STATUS_OK) { 61124ac67f02SAnurag S. Maskey dladm_close(handle); 61130ba2cbe9Sxc151355 exit(1); 61140ba2cbe9Sxc151355 } 61154ac67f02SAnurag S. Maskey } 61160ba2cbe9Sxc151355 61170ba2cbe9Sxc151355 static void 61188d5c46e6Sam223141 do_set_linkprop(int argc, char **argv, const char *use) 61190ba2cbe9Sxc151355 { 61208d5c46e6Sam223141 set_linkprop(argc, argv, B_FALSE, use); 61210ba2cbe9Sxc151355 } 61220ba2cbe9Sxc151355 61230ba2cbe9Sxc151355 static void 61248d5c46e6Sam223141 do_reset_linkprop(int argc, char **argv, const char *use) 61250ba2cbe9Sxc151355 { 61268d5c46e6Sam223141 set_linkprop(argc, argv, B_TRUE, use); 61270ba2cbe9Sxc151355 } 61280ba2cbe9Sxc151355 61290ba2cbe9Sxc151355 static int 61300ba2cbe9Sxc151355 convert_secobj(char *buf, uint_t len, uint8_t *obj_val, uint_t *obj_lenp, 61310ba2cbe9Sxc151355 dladm_secobj_class_t class) 61320ba2cbe9Sxc151355 { 61330ba2cbe9Sxc151355 int error = 0; 61340ba2cbe9Sxc151355 6135a399b765Szf162725 if (class == DLADM_SECOBJ_CLASS_WPA) { 6136a399b765Szf162725 if (len < 8 || len > 63) 6137a399b765Szf162725 return (EINVAL); 6138a399b765Szf162725 (void) memcpy(obj_val, buf, len); 6139a399b765Szf162725 *obj_lenp = len; 6140a399b765Szf162725 return (error); 6141a399b765Szf162725 } 61420ba2cbe9Sxc151355 6143a399b765Szf162725 if (class == DLADM_SECOBJ_CLASS_WEP) { 61440ba2cbe9Sxc151355 switch (len) { 61450ba2cbe9Sxc151355 case 5: /* ASCII key sizes */ 61460ba2cbe9Sxc151355 case 13: 61470ba2cbe9Sxc151355 (void) memcpy(obj_val, buf, len); 61480ba2cbe9Sxc151355 *obj_lenp = len; 61490ba2cbe9Sxc151355 break; 61500ba2cbe9Sxc151355 case 10: /* Hex key sizes, not preceded by 0x */ 61510ba2cbe9Sxc151355 case 26: 61520ba2cbe9Sxc151355 error = hexascii_to_octet(buf, len, obj_val, obj_lenp); 61530ba2cbe9Sxc151355 break; 61540ba2cbe9Sxc151355 case 12: /* Hex key sizes, preceded by 0x */ 61550ba2cbe9Sxc151355 case 28: 61560ba2cbe9Sxc151355 if (strncmp(buf, "0x", 2) != 0) 61570ba2cbe9Sxc151355 return (EINVAL); 6158a399b765Szf162725 error = hexascii_to_octet(buf + 2, len - 2, 6159a399b765Szf162725 obj_val, obj_lenp); 61600ba2cbe9Sxc151355 break; 61610ba2cbe9Sxc151355 default: 61620ba2cbe9Sxc151355 return (EINVAL); 61630ba2cbe9Sxc151355 } 61640ba2cbe9Sxc151355 return (error); 61650ba2cbe9Sxc151355 } 61660ba2cbe9Sxc151355 6167a399b765Szf162725 return (ENOENT); 6168a399b765Szf162725 } 6169a399b765Szf162725 61700ba2cbe9Sxc151355 static void 61710ba2cbe9Sxc151355 defersig(int sig) 61720ba2cbe9Sxc151355 { 61730ba2cbe9Sxc151355 signalled = sig; 61740ba2cbe9Sxc151355 } 61750ba2cbe9Sxc151355 61760ba2cbe9Sxc151355 static int 61770ba2cbe9Sxc151355 get_secobj_from_tty(uint_t try, const char *objname, char *buf) 61780ba2cbe9Sxc151355 { 61790ba2cbe9Sxc151355 uint_t len = 0; 61800ba2cbe9Sxc151355 int c; 61810ba2cbe9Sxc151355 struct termios stored, current; 61820ba2cbe9Sxc151355 void (*sigfunc)(int); 61830ba2cbe9Sxc151355 61840ba2cbe9Sxc151355 /* 61850ba2cbe9Sxc151355 * Turn off echo -- but before we do so, defer SIGINT handling 61860ba2cbe9Sxc151355 * so that a ^C doesn't leave the terminal corrupted. 61870ba2cbe9Sxc151355 */ 61880ba2cbe9Sxc151355 sigfunc = signal(SIGINT, defersig); 61890ba2cbe9Sxc151355 (void) fflush(stdin); 61900ba2cbe9Sxc151355 (void) tcgetattr(0, &stored); 61910ba2cbe9Sxc151355 current = stored; 61920ba2cbe9Sxc151355 current.c_lflag &= ~(ICANON|ECHO); 61930ba2cbe9Sxc151355 current.c_cc[VTIME] = 0; 61940ba2cbe9Sxc151355 current.c_cc[VMIN] = 1; 61950ba2cbe9Sxc151355 (void) tcsetattr(0, TCSANOW, ¤t); 61960ba2cbe9Sxc151355 again: 61970ba2cbe9Sxc151355 if (try == 1) 61980ba2cbe9Sxc151355 (void) printf(gettext("provide value for '%s': "), objname); 61990ba2cbe9Sxc151355 else 62000ba2cbe9Sxc151355 (void) printf(gettext("confirm value for '%s': "), objname); 62010ba2cbe9Sxc151355 62020ba2cbe9Sxc151355 (void) fflush(stdout); 62030ba2cbe9Sxc151355 while (signalled == 0) { 62040ba2cbe9Sxc151355 c = getchar(); 62050ba2cbe9Sxc151355 if (c == '\n' || c == '\r') { 62060ba2cbe9Sxc151355 if (len != 0) 62070ba2cbe9Sxc151355 break; 62080ba2cbe9Sxc151355 (void) putchar('\n'); 62090ba2cbe9Sxc151355 goto again; 62100ba2cbe9Sxc151355 } 62110ba2cbe9Sxc151355 62120ba2cbe9Sxc151355 buf[len++] = c; 62130ba2cbe9Sxc151355 if (len >= DLADM_SECOBJ_VAL_MAX - 1) 62140ba2cbe9Sxc151355 break; 62150ba2cbe9Sxc151355 (void) putchar('*'); 62160ba2cbe9Sxc151355 } 62170ba2cbe9Sxc151355 62180ba2cbe9Sxc151355 (void) putchar('\n'); 62190ba2cbe9Sxc151355 (void) fflush(stdin); 62200ba2cbe9Sxc151355 62210ba2cbe9Sxc151355 /* 62220ba2cbe9Sxc151355 * Restore terminal setting and handle deferred signals. 62230ba2cbe9Sxc151355 */ 62240ba2cbe9Sxc151355 (void) tcsetattr(0, TCSANOW, &stored); 62250ba2cbe9Sxc151355 62260ba2cbe9Sxc151355 (void) signal(SIGINT, sigfunc); 62270ba2cbe9Sxc151355 if (signalled != 0) 62280ba2cbe9Sxc151355 (void) kill(getpid(), signalled); 62290ba2cbe9Sxc151355 62300ba2cbe9Sxc151355 return (len); 62310ba2cbe9Sxc151355 } 62320ba2cbe9Sxc151355 62330ba2cbe9Sxc151355 static int 62340ba2cbe9Sxc151355 get_secobj_val(char *obj_name, uint8_t *obj_val, uint_t *obj_lenp, 62350ba2cbe9Sxc151355 dladm_secobj_class_t class, FILE *filep) 62360ba2cbe9Sxc151355 { 62370ba2cbe9Sxc151355 int rval; 62380ba2cbe9Sxc151355 uint_t len, len2; 62390ba2cbe9Sxc151355 char buf[DLADM_SECOBJ_VAL_MAX], buf2[DLADM_SECOBJ_VAL_MAX]; 62400ba2cbe9Sxc151355 62410ba2cbe9Sxc151355 if (filep == NULL) { 62420ba2cbe9Sxc151355 len = get_secobj_from_tty(1, obj_name, buf); 62430ba2cbe9Sxc151355 rval = convert_secobj(buf, len, obj_val, obj_lenp, class); 62440ba2cbe9Sxc151355 if (rval == 0) { 62450ba2cbe9Sxc151355 len2 = get_secobj_from_tty(2, obj_name, buf2); 62460ba2cbe9Sxc151355 if (len != len2 || memcmp(buf, buf2, len) != 0) 62470ba2cbe9Sxc151355 rval = ENOTSUP; 62480ba2cbe9Sxc151355 } 62490ba2cbe9Sxc151355 return (rval); 62500ba2cbe9Sxc151355 } else { 62510ba2cbe9Sxc151355 for (;;) { 62520ba2cbe9Sxc151355 if (fgets(buf, sizeof (buf), filep) == NULL) 62530ba2cbe9Sxc151355 break; 62540ba2cbe9Sxc151355 if (isspace(buf[0])) 62550ba2cbe9Sxc151355 continue; 62560ba2cbe9Sxc151355 62570ba2cbe9Sxc151355 len = strlen(buf); 62580ba2cbe9Sxc151355 if (buf[len - 1] == '\n') { 62590ba2cbe9Sxc151355 buf[len - 1] = '\0'; 62600ba2cbe9Sxc151355 len--; 62610ba2cbe9Sxc151355 } 62620ba2cbe9Sxc151355 break; 62630ba2cbe9Sxc151355 } 62640ba2cbe9Sxc151355 (void) fclose(filep); 62650ba2cbe9Sxc151355 } 62660ba2cbe9Sxc151355 return (convert_secobj(buf, len, obj_val, obj_lenp, class)); 62670ba2cbe9Sxc151355 } 62680ba2cbe9Sxc151355 62690ba2cbe9Sxc151355 static boolean_t 62700ba2cbe9Sxc151355 check_auth(const char *auth) 62710ba2cbe9Sxc151355 { 62720ba2cbe9Sxc151355 struct passwd *pw; 62730ba2cbe9Sxc151355 62740ba2cbe9Sxc151355 if ((pw = getpwuid(getuid())) == NULL) 62750ba2cbe9Sxc151355 return (B_FALSE); 62760ba2cbe9Sxc151355 62770ba2cbe9Sxc151355 return (chkauthattr(auth, pw->pw_name) != 0); 62780ba2cbe9Sxc151355 } 62790ba2cbe9Sxc151355 62800ba2cbe9Sxc151355 static void 62810ba2cbe9Sxc151355 audit_secobj(char *auth, char *class, char *obj, 62820ba2cbe9Sxc151355 boolean_t success, boolean_t create) 62830ba2cbe9Sxc151355 { 62840ba2cbe9Sxc151355 adt_session_data_t *ah; 62850ba2cbe9Sxc151355 adt_event_data_t *event; 62860ba2cbe9Sxc151355 au_event_t flag; 62870ba2cbe9Sxc151355 char *errstr; 62880ba2cbe9Sxc151355 62890ba2cbe9Sxc151355 if (create) { 62900ba2cbe9Sxc151355 flag = ADT_dladm_create_secobj; 62910ba2cbe9Sxc151355 errstr = "ADT_dladm_create_secobj"; 62920ba2cbe9Sxc151355 } else { 62930ba2cbe9Sxc151355 flag = ADT_dladm_delete_secobj; 62940ba2cbe9Sxc151355 errstr = "ADT_dladm_delete_secobj"; 62950ba2cbe9Sxc151355 } 62960ba2cbe9Sxc151355 629733343a97Smeem if (adt_start_session(&ah, NULL, ADT_USE_PROC_DATA) != 0) 629833343a97Smeem die("adt_start_session: %s", strerror(errno)); 62990ba2cbe9Sxc151355 630033343a97Smeem if ((event = adt_alloc_event(ah, flag)) == NULL) 630133343a97Smeem die("adt_alloc_event (%s): %s", errstr, strerror(errno)); 63020ba2cbe9Sxc151355 63030ba2cbe9Sxc151355 /* fill in audit info */ 63040ba2cbe9Sxc151355 if (create) { 63050ba2cbe9Sxc151355 event->adt_dladm_create_secobj.auth_used = auth; 63060ba2cbe9Sxc151355 event->adt_dladm_create_secobj.obj_class = class; 63070ba2cbe9Sxc151355 event->adt_dladm_create_secobj.obj_name = obj; 63080ba2cbe9Sxc151355 } else { 63090ba2cbe9Sxc151355 event->adt_dladm_delete_secobj.auth_used = auth; 63100ba2cbe9Sxc151355 event->adt_dladm_delete_secobj.obj_class = class; 63110ba2cbe9Sxc151355 event->adt_dladm_delete_secobj.obj_name = obj; 63120ba2cbe9Sxc151355 } 63130ba2cbe9Sxc151355 63140ba2cbe9Sxc151355 if (success) { 63150ba2cbe9Sxc151355 if (adt_put_event(event, ADT_SUCCESS, ADT_SUCCESS) != 0) { 631633343a97Smeem die("adt_put_event (%s, success): %s", errstr, 631733343a97Smeem strerror(errno)); 63180ba2cbe9Sxc151355 } 63190ba2cbe9Sxc151355 } else { 63200ba2cbe9Sxc151355 if (adt_put_event(event, ADT_FAILURE, 63210ba2cbe9Sxc151355 ADT_FAIL_VALUE_AUTH) != 0) { 632233343a97Smeem die("adt_put_event: (%s, failure): %s", errstr, 632333343a97Smeem strerror(errno)); 63240ba2cbe9Sxc151355 } 63250ba2cbe9Sxc151355 } 63260ba2cbe9Sxc151355 63270ba2cbe9Sxc151355 adt_free_event(event); 63280ba2cbe9Sxc151355 (void) adt_end_session(ah); 63290ba2cbe9Sxc151355 } 63300ba2cbe9Sxc151355 63310ba2cbe9Sxc151355 #define MAX_SECOBJS 32 63320ba2cbe9Sxc151355 #define MAX_SECOBJ_NAMELEN 32 63330ba2cbe9Sxc151355 static void 63348d5c46e6Sam223141 do_create_secobj(int argc, char **argv, const char *use) 63350ba2cbe9Sxc151355 { 63360ba2cbe9Sxc151355 int option, rval; 63370ba2cbe9Sxc151355 FILE *filep = NULL; 63380ba2cbe9Sxc151355 char *obj_name = NULL; 63390ba2cbe9Sxc151355 char *class_name = NULL; 63400ba2cbe9Sxc151355 uint8_t obj_val[DLADM_SECOBJ_VAL_MAX]; 63410ba2cbe9Sxc151355 uint_t obj_len; 63420ba2cbe9Sxc151355 boolean_t success, temp = B_FALSE; 63430ba2cbe9Sxc151355 dladm_status_t status; 63440ba2cbe9Sxc151355 dladm_secobj_class_t class = -1; 63450ba2cbe9Sxc151355 uid_t euid; 63460ba2cbe9Sxc151355 63470ba2cbe9Sxc151355 opterr = 0; 63480ba2cbe9Sxc151355 (void) memset(obj_val, 0, DLADM_SECOBJ_VAL_MAX); 63490ba2cbe9Sxc151355 while ((option = getopt_long(argc, argv, ":f:c:R:t", 63500ba2cbe9Sxc151355 wifi_longopts, NULL)) != -1) { 63510ba2cbe9Sxc151355 switch (option) { 63520ba2cbe9Sxc151355 case 'f': 63530ba2cbe9Sxc151355 euid = geteuid(); 63540ba2cbe9Sxc151355 (void) seteuid(getuid()); 63550ba2cbe9Sxc151355 filep = fopen(optarg, "r"); 63560ba2cbe9Sxc151355 if (filep == NULL) { 635733343a97Smeem die("cannot open %s: %s", optarg, 635833343a97Smeem strerror(errno)); 63590ba2cbe9Sxc151355 } 63600ba2cbe9Sxc151355 (void) seteuid(euid); 63610ba2cbe9Sxc151355 break; 63620ba2cbe9Sxc151355 case 'c': 63630ba2cbe9Sxc151355 class_name = optarg; 63640ba2cbe9Sxc151355 status = dladm_str2secobjclass(optarg, &class); 63650ba2cbe9Sxc151355 if (status != DLADM_STATUS_OK) { 636633343a97Smeem die("invalid secure object class '%s', " 6367a399b765Szf162725 "valid values are: wep, wpa", optarg); 63680ba2cbe9Sxc151355 } 63690ba2cbe9Sxc151355 break; 63700ba2cbe9Sxc151355 case 't': 63710ba2cbe9Sxc151355 temp = B_TRUE; 63720ba2cbe9Sxc151355 break; 63730ba2cbe9Sxc151355 case 'R': 63740ba2cbe9Sxc151355 status = dladm_set_rootdir(optarg); 63750ba2cbe9Sxc151355 if (status != DLADM_STATUS_OK) { 637633343a97Smeem die_dlerr(status, "invalid directory " 637733343a97Smeem "specified"); 63780ba2cbe9Sxc151355 } 63790ba2cbe9Sxc151355 break; 63800ba2cbe9Sxc151355 default: 63818d5c46e6Sam223141 die_opterr(optopt, option, use); 63820ba2cbe9Sxc151355 break; 63830ba2cbe9Sxc151355 } 63840ba2cbe9Sxc151355 } 63850ba2cbe9Sxc151355 63860ba2cbe9Sxc151355 if (optind == (argc - 1)) 63870ba2cbe9Sxc151355 obj_name = argv[optind]; 63880ba2cbe9Sxc151355 else if (optind != argc) 63890ba2cbe9Sxc151355 usage(); 63900ba2cbe9Sxc151355 639133343a97Smeem if (class == -1) 639233343a97Smeem die("secure object class required"); 63930ba2cbe9Sxc151355 639433343a97Smeem if (obj_name == NULL) 639533343a97Smeem die("secure object name required"); 63960ba2cbe9Sxc151355 6397a9489f61SAnurag S. Maskey if (!dladm_valid_secobj_name(obj_name)) 6398a9489f61SAnurag S. Maskey die("invalid secure object name '%s'", obj_name); 6399a9489f61SAnurag S. Maskey 64000ba2cbe9Sxc151355 success = check_auth(LINK_SEC_AUTH); 64010ba2cbe9Sxc151355 audit_secobj(LINK_SEC_AUTH, class_name, obj_name, success, B_TRUE); 640233343a97Smeem if (!success) 640333343a97Smeem die("authorization '%s' is required", LINK_SEC_AUTH); 64040ba2cbe9Sxc151355 640533343a97Smeem rval = get_secobj_val(obj_name, obj_val, &obj_len, class, filep); 640633343a97Smeem if (rval != 0) { 64070ba2cbe9Sxc151355 switch (rval) { 64080ba2cbe9Sxc151355 case ENOENT: 640933343a97Smeem die("invalid secure object class"); 64100ba2cbe9Sxc151355 break; 64110ba2cbe9Sxc151355 case EINVAL: 641233343a97Smeem die("invalid secure object value"); 64130ba2cbe9Sxc151355 break; 64140ba2cbe9Sxc151355 case ENOTSUP: 641533343a97Smeem die("verification failed"); 64160ba2cbe9Sxc151355 break; 64170ba2cbe9Sxc151355 default: 641833343a97Smeem die("invalid secure object: %s", strerror(rval)); 64190ba2cbe9Sxc151355 break; 64200ba2cbe9Sxc151355 } 64210ba2cbe9Sxc151355 } 64220ba2cbe9Sxc151355 64234ac67f02SAnurag S. Maskey status = dladm_set_secobj(handle, obj_name, class, obj_val, obj_len, 6424d62bc4baSyz147064 DLADM_OPT_CREATE | DLADM_OPT_ACTIVE); 64250ba2cbe9Sxc151355 if (status != DLADM_STATUS_OK) { 642633343a97Smeem die_dlerr(status, "could not create secure object '%s'", 642733343a97Smeem obj_name); 64280ba2cbe9Sxc151355 } 64290ba2cbe9Sxc151355 if (temp) 64300ba2cbe9Sxc151355 return; 64310ba2cbe9Sxc151355 64324ac67f02SAnurag S. Maskey status = dladm_set_secobj(handle, obj_name, class, obj_val, obj_len, 64330ba2cbe9Sxc151355 DLADM_OPT_PERSIST); 64340ba2cbe9Sxc151355 if (status != DLADM_STATUS_OK) { 643533343a97Smeem warn_dlerr(status, "could not persistently create secure " 643633343a97Smeem "object '%s'", obj_name); 64370ba2cbe9Sxc151355 } 64380ba2cbe9Sxc151355 } 64390ba2cbe9Sxc151355 64400ba2cbe9Sxc151355 static void 64418d5c46e6Sam223141 do_delete_secobj(int argc, char **argv, const char *use) 64420ba2cbe9Sxc151355 { 64430ba2cbe9Sxc151355 int i, option; 64440ba2cbe9Sxc151355 boolean_t temp = B_FALSE; 64450ba2cbe9Sxc151355 split_t *sp = NULL; 64460ba2cbe9Sxc151355 boolean_t success; 64470ba2cbe9Sxc151355 dladm_status_t status, pstatus; 64480ba2cbe9Sxc151355 64490ba2cbe9Sxc151355 opterr = 0; 64500ba2cbe9Sxc151355 status = pstatus = DLADM_STATUS_OK; 645133343a97Smeem while ((option = getopt_long(argc, argv, ":R:t", 64520ba2cbe9Sxc151355 wifi_longopts, NULL)) != -1) { 64530ba2cbe9Sxc151355 switch (option) { 64540ba2cbe9Sxc151355 case 't': 64550ba2cbe9Sxc151355 temp = B_TRUE; 64560ba2cbe9Sxc151355 break; 64570ba2cbe9Sxc151355 case 'R': 64580ba2cbe9Sxc151355 status = dladm_set_rootdir(optarg); 64590ba2cbe9Sxc151355 if (status != DLADM_STATUS_OK) { 646033343a97Smeem die_dlerr(status, "invalid directory " 646133343a97Smeem "specified"); 64620ba2cbe9Sxc151355 } 64630ba2cbe9Sxc151355 break; 64640ba2cbe9Sxc151355 default: 64658d5c46e6Sam223141 die_opterr(optopt, option, use); 64660ba2cbe9Sxc151355 break; 64670ba2cbe9Sxc151355 } 64680ba2cbe9Sxc151355 } 64690ba2cbe9Sxc151355 64700ba2cbe9Sxc151355 if (optind == (argc - 1)) { 64710ba2cbe9Sxc151355 sp = split(argv[optind], MAX_SECOBJS, MAX_SECOBJ_NAMELEN); 64720ba2cbe9Sxc151355 if (sp == NULL) { 647333343a97Smeem die("invalid secure object name(s): '%s'", 647433343a97Smeem argv[optind]); 64750ba2cbe9Sxc151355 } 64760ba2cbe9Sxc151355 } else if (optind != argc) 64770ba2cbe9Sxc151355 usage(); 64780ba2cbe9Sxc151355 647933343a97Smeem if (sp == NULL || sp->s_nfields < 1) 648033343a97Smeem die("secure object name required"); 64810ba2cbe9Sxc151355 64820ba2cbe9Sxc151355 success = check_auth(LINK_SEC_AUTH); 6483a399b765Szf162725 audit_secobj(LINK_SEC_AUTH, "unknown", argv[optind], success, B_FALSE); 648433343a97Smeem if (!success) 648533343a97Smeem die("authorization '%s' is required", LINK_SEC_AUTH); 64860ba2cbe9Sxc151355 64870ba2cbe9Sxc151355 for (i = 0; i < sp->s_nfields; i++) { 64884ac67f02SAnurag S. Maskey status = dladm_unset_secobj(handle, sp->s_fields[i], 64894ac67f02SAnurag S. Maskey DLADM_OPT_ACTIVE); 64900ba2cbe9Sxc151355 if (!temp) { 64914ac67f02SAnurag S. Maskey pstatus = dladm_unset_secobj(handle, sp->s_fields[i], 64920ba2cbe9Sxc151355 DLADM_OPT_PERSIST); 64930ba2cbe9Sxc151355 } else { 64940ba2cbe9Sxc151355 pstatus = DLADM_STATUS_OK; 64950ba2cbe9Sxc151355 } 64960ba2cbe9Sxc151355 64970ba2cbe9Sxc151355 if (status != DLADM_STATUS_OK) { 649833343a97Smeem warn_dlerr(status, "could not delete secure object " 649933343a97Smeem "'%s'", sp->s_fields[i]); 65000ba2cbe9Sxc151355 } 65010ba2cbe9Sxc151355 if (pstatus != DLADM_STATUS_OK) { 650233343a97Smeem warn_dlerr(pstatus, "could not persistently delete " 650333343a97Smeem "secure object '%s'", sp->s_fields[i]); 65040ba2cbe9Sxc151355 } 65050ba2cbe9Sxc151355 } 65064ac67f02SAnurag S. Maskey 65074ac67f02SAnurag S. Maskey if (status != DLADM_STATUS_OK || pstatus != DLADM_STATUS_OK) { 65084ac67f02SAnurag S. Maskey dladm_close(handle); 65090ba2cbe9Sxc151355 exit(1); 65100ba2cbe9Sxc151355 } 65114ac67f02SAnurag S. Maskey } 65120ba2cbe9Sxc151355 65130ba2cbe9Sxc151355 typedef struct show_secobj_state { 65140ba2cbe9Sxc151355 boolean_t ss_persist; 65150ba2cbe9Sxc151355 boolean_t ss_parseable; 65160ba2cbe9Sxc151355 boolean_t ss_header; 6517e7801d59Ssowmini print_state_t ss_print; 65180ba2cbe9Sxc151355 } show_secobj_state_t; 65190ba2cbe9Sxc151355 65200ba2cbe9Sxc151355 65210ba2cbe9Sxc151355 static boolean_t 65224ac67f02SAnurag S. Maskey show_secobj(dladm_handle_t dh, void *arg, const char *obj_name) 65230ba2cbe9Sxc151355 { 65240ba2cbe9Sxc151355 uint_t obj_len = DLADM_SECOBJ_VAL_MAX; 65250ba2cbe9Sxc151355 uint8_t obj_val[DLADM_SECOBJ_VAL_MAX]; 65260ba2cbe9Sxc151355 char buf[DLADM_STRSIZE]; 65270ba2cbe9Sxc151355 uint_t flags = 0; 65280ba2cbe9Sxc151355 dladm_secobj_class_t class; 65290ba2cbe9Sxc151355 show_secobj_state_t *statep = arg; 65300ba2cbe9Sxc151355 dladm_status_t status; 6531e7801d59Ssowmini secobj_fields_buf_t sbuf; 65320ba2cbe9Sxc151355 65335f5c9f54SAnurag S. Maskey bzero(&sbuf, sizeof (secobj_fields_buf_t)); 65340ba2cbe9Sxc151355 if (statep->ss_persist) 65350ba2cbe9Sxc151355 flags |= DLADM_OPT_PERSIST; 65360ba2cbe9Sxc151355 65374ac67f02SAnurag S. Maskey status = dladm_get_secobj(dh, obj_name, &class, obj_val, &obj_len, 65384ac67f02SAnurag S. Maskey flags); 653933343a97Smeem if (status != DLADM_STATUS_OK) 654033343a97Smeem die_dlerr(status, "cannot get secure object '%s'", obj_name); 65410ba2cbe9Sxc151355 65420ba2cbe9Sxc151355 if (statep->ss_header) { 65430ba2cbe9Sxc151355 statep->ss_header = B_FALSE; 65440ba2cbe9Sxc151355 if (!statep->ss_parseable) 6545e7801d59Ssowmini print_header(&statep->ss_print); 65460ba2cbe9Sxc151355 } 65470ba2cbe9Sxc151355 6548e7801d59Ssowmini (void) snprintf(sbuf.ss_obj_name, sizeof (sbuf.ss_obj_name), 6549e7801d59Ssowmini obj_name); 6550e7801d59Ssowmini (void) dladm_secobjclass2str(class, buf); 6551e7801d59Ssowmini (void) snprintf(sbuf.ss_class, sizeof (sbuf.ss_class), "%s", buf); 6552e7801d59Ssowmini if (getuid() == 0) { 65530ba2cbe9Sxc151355 char val[DLADM_SECOBJ_VAL_MAX * 2]; 65540ba2cbe9Sxc151355 uint_t len = sizeof (val); 65550ba2cbe9Sxc151355 6556e7801d59Ssowmini if (octet_to_hexascii(obj_val, obj_len, val, &len) == 0) 6557e7801d59Ssowmini (void) snprintf(sbuf.ss_val, 6558e7801d59Ssowmini sizeof (sbuf.ss_val), "%s", val); 65590ba2cbe9Sxc151355 } 6560e7801d59Ssowmini dladm_print_output(&statep->ss_print, statep->ss_parseable, 6561e7801d59Ssowmini dladm_print_field, (void *)&sbuf); 65620ba2cbe9Sxc151355 return (B_TRUE); 65630ba2cbe9Sxc151355 } 65640ba2cbe9Sxc151355 65650ba2cbe9Sxc151355 static void 65668d5c46e6Sam223141 do_show_secobj(int argc, char **argv, const char *use) 65670ba2cbe9Sxc151355 { 65680ba2cbe9Sxc151355 int option; 65690ba2cbe9Sxc151355 show_secobj_state_t state; 65700ba2cbe9Sxc151355 dladm_status_t status; 65710d365605Sschuster boolean_t o_arg = B_FALSE; 65720ba2cbe9Sxc151355 uint_t i; 65730ba2cbe9Sxc151355 split_t *sp; 65740ba2cbe9Sxc151355 uint_t flags; 6575e7801d59Ssowmini char *fields_str = NULL; 6576e7801d59Ssowmini print_field_t **fields; 6577e7801d59Ssowmini uint_t nfields; 6578e7801d59Ssowmini char *def_fields = "object,class"; 6579e7801d59Ssowmini char *all_fields = "object,class,value"; 65800ba2cbe9Sxc151355 65810ba2cbe9Sxc151355 opterr = 0; 6582e7801d59Ssowmini bzero(&state, sizeof (state)); 6583e7801d59Ssowmini state.ss_parseable = B_FALSE; 6584e7801d59Ssowmini fields_str = def_fields; 65850ba2cbe9Sxc151355 state.ss_persist = B_FALSE; 65860ba2cbe9Sxc151355 state.ss_parseable = B_FALSE; 65870ba2cbe9Sxc151355 state.ss_header = B_TRUE; 6588e7801d59Ssowmini while ((option = getopt_long(argc, argv, ":pPo:", 65890ba2cbe9Sxc151355 wifi_longopts, NULL)) != -1) { 65900ba2cbe9Sxc151355 switch (option) { 65910ba2cbe9Sxc151355 case 'p': 65920ba2cbe9Sxc151355 state.ss_parseable = B_TRUE; 65930ba2cbe9Sxc151355 break; 65940ba2cbe9Sxc151355 case 'P': 65950ba2cbe9Sxc151355 state.ss_persist = B_TRUE; 65960ba2cbe9Sxc151355 break; 6597e7801d59Ssowmini case 'o': 65980d365605Sschuster o_arg = B_TRUE; 6599e7801d59Ssowmini if (strcasecmp(optarg, "all") == 0) 6600e7801d59Ssowmini fields_str = all_fields; 6601e7801d59Ssowmini else 6602e7801d59Ssowmini fields_str = optarg; 66030ba2cbe9Sxc151355 break; 66040ba2cbe9Sxc151355 default: 66058d5c46e6Sam223141 die_opterr(optopt, option, use); 66060ba2cbe9Sxc151355 break; 66070ba2cbe9Sxc151355 } 66080ba2cbe9Sxc151355 } 66090ba2cbe9Sxc151355 66100d365605Sschuster if (state.ss_parseable && !o_arg) 66110d365605Sschuster die("option -c requires -o"); 66120d365605Sschuster 66130d365605Sschuster if (state.ss_parseable && fields_str == all_fields) 66140d365605Sschuster die("\"-o all\" is invalid with -p"); 66150d365605Sschuster 6616e7801d59Ssowmini fields = parse_output_fields(fields_str, secobj_fields, 6617e7801d59Ssowmini DEV_SOBJ_FIELDS, CMD_TYPE_ANY, &nfields); 6618e7801d59Ssowmini 6619e7801d59Ssowmini if (fields == NULL) { 6620e7801d59Ssowmini die("invalid field(s) specified"); 6621e7801d59Ssowmini return; 6622e7801d59Ssowmini } 6623e7801d59Ssowmini state.ss_print.ps_fields = fields; 6624e7801d59Ssowmini state.ss_print.ps_nfields = nfields; 6625e7801d59Ssowmini 6626e7801d59Ssowmini flags = state.ss_persist ? DLADM_OPT_PERSIST : 0; 66274ac67f02SAnurag S. Maskey 66280ba2cbe9Sxc151355 if (optind == (argc - 1)) { 66290ba2cbe9Sxc151355 sp = split(argv[optind], MAX_SECOBJS, MAX_SECOBJ_NAMELEN); 66300ba2cbe9Sxc151355 if (sp == NULL) { 663133343a97Smeem die("invalid secure object name(s): '%s'", 663233343a97Smeem argv[optind]); 66330ba2cbe9Sxc151355 } 66340ba2cbe9Sxc151355 for (i = 0; i < sp->s_nfields; i++) { 66354ac67f02SAnurag S. Maskey if (!show_secobj(handle, &state, sp->s_fields[i])) 66360ba2cbe9Sxc151355 break; 66370ba2cbe9Sxc151355 } 66380ba2cbe9Sxc151355 splitfree(sp); 66390ba2cbe9Sxc151355 return; 66400ba2cbe9Sxc151355 } else if (optind != argc) 66410ba2cbe9Sxc151355 usage(); 66420ba2cbe9Sxc151355 66434ac67f02SAnurag S. Maskey status = dladm_walk_secobj(handle, &state, show_secobj, flags); 66444ac67f02SAnurag S. Maskey 664533343a97Smeem if (status != DLADM_STATUS_OK) 664633343a97Smeem die_dlerr(status, "show-secobj"); 66470ba2cbe9Sxc151355 } 66480ba2cbe9Sxc151355 66490ba2cbe9Sxc151355 /*ARGSUSED*/ 6650d62bc4baSyz147064 static int 66514ac67f02SAnurag S. Maskey i_dladm_init_linkprop(dladm_handle_t dh, datalink_id_t linkid, void *arg) 6652d62bc4baSyz147064 { 66534ac67f02SAnurag S. Maskey (void) dladm_init_linkprop(dh, linkid, B_TRUE); 6654d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 6655d62bc4baSyz147064 } 6656d62bc4baSyz147064 66578d5c46e6Sam223141 /*ARGSUSED*/ 6658da14cebeSEric Cheng void 66598d5c46e6Sam223141 do_init_linkprop(int argc, char **argv, const char *use) 66600ba2cbe9Sxc151355 { 666130890389Sartem int option; 666230890389Sartem dladm_status_t status; 666330890389Sartem datalink_id_t linkid = DATALINK_ALL_LINKID; 666430890389Sartem datalink_media_t media = DATALINK_ANY_MEDIATYPE; 666530890389Sartem uint_t any_media = B_TRUE; 666630890389Sartem 666730890389Sartem opterr = 0; 666830890389Sartem while ((option = getopt(argc, argv, ":w")) != -1) { 666930890389Sartem switch (option) { 667030890389Sartem case 'w': 667130890389Sartem media = DL_WIFI; 667230890389Sartem any_media = B_FALSE; 667330890389Sartem break; 667430890389Sartem default: 66758d5c46e6Sam223141 /* 66768d5c46e6Sam223141 * Because init-linkprop is not a public command, 66778d5c46e6Sam223141 * print the usage instead. 66788d5c46e6Sam223141 */ 66798d5c46e6Sam223141 usage(); 668030890389Sartem break; 668130890389Sartem } 668230890389Sartem } 668330890389Sartem 668430890389Sartem if (optind == (argc - 1)) { 66854ac67f02SAnurag S. Maskey if ((status = dladm_name2info(handle, argv[optind], &linkid, 66864ac67f02SAnurag S. Maskey NULL, NULL, NULL)) != DLADM_STATUS_OK) 668730890389Sartem die_dlerr(status, "link %s is not valid", argv[optind]); 668830890389Sartem } else if (optind != argc) { 668930890389Sartem usage(); 669030890389Sartem } 669130890389Sartem 669230890389Sartem if (linkid == DATALINK_ALL_LINKID) { 6693d62bc4baSyz147064 /* 669430890389Sartem * linkprops of links of other classes have been initialized as 6695d62bc4baSyz147064 * part of the dladm up-xxx operation. 6696d62bc4baSyz147064 */ 66974ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(i_dladm_init_linkprop, handle, 66984ac67f02SAnurag S. Maskey NULL, DATALINK_CLASS_PHYS, media, DLADM_OPT_PERSIST); 669930890389Sartem } else { 67004ac67f02SAnurag S. Maskey (void) dladm_init_linkprop(handle, linkid, any_media); 670130890389Sartem } 67020ba2cbe9Sxc151355 } 67030ba2cbe9Sxc151355 67040ba2cbe9Sxc151355 static void 67058d5c46e6Sam223141 do_show_ether(int argc, char **argv, const char *use) 6706e7801d59Ssowmini { 6707e7801d59Ssowmini int option; 6708e7801d59Ssowmini datalink_id_t linkid; 6709e7801d59Ssowmini print_ether_state_t state; 6710e7801d59Ssowmini print_field_t **fields; 67110d365605Sschuster boolean_t o_arg = B_FALSE; 6712e7801d59Ssowmini char *fields_str; 6713e7801d59Ssowmini uint_t nfields; 6714e7801d59Ssowmini char *all_fields = 6715e7801d59Ssowmini "link,ptype,state,auto,speed-duplex,pause,rem_fault"; 6716e7801d59Ssowmini char *default_fields = 6717e7801d59Ssowmini "link,ptype,state,auto,speed-duplex,pause"; 6718e7801d59Ssowmini 6719e7801d59Ssowmini fields_str = default_fields; 6720e7801d59Ssowmini bzero(&state, sizeof (state)); 6721e7801d59Ssowmini state.es_link = NULL; 6722e7801d59Ssowmini state.es_parseable = B_FALSE; 6723e7801d59Ssowmini 6724e7801d59Ssowmini while ((option = getopt_long(argc, argv, "o:px", 6725e7801d59Ssowmini showeth_lopts, NULL)) != -1) { 6726e7801d59Ssowmini switch (option) { 6727e7801d59Ssowmini case 'x': 6728e7801d59Ssowmini state.es_extended = B_TRUE; 6729e7801d59Ssowmini break; 6730e7801d59Ssowmini case 'p': 6731e7801d59Ssowmini state.es_parseable = B_TRUE; 6732e7801d59Ssowmini break; 6733e7801d59Ssowmini case 'o': 67340d365605Sschuster o_arg = B_TRUE; 6735e7801d59Ssowmini if (strcasecmp(optarg, "all") == 0) 6736e7801d59Ssowmini fields_str = all_fields; 6737e7801d59Ssowmini else 6738e7801d59Ssowmini fields_str = optarg; 6739e7801d59Ssowmini break; 6740e7801d59Ssowmini default: 67418d5c46e6Sam223141 die_opterr(optopt, option, use); 6742e7801d59Ssowmini break; 6743e7801d59Ssowmini } 6744e7801d59Ssowmini } 6745e7801d59Ssowmini 67460d365605Sschuster if (state.es_parseable && !o_arg) 67470d365605Sschuster die("-p requires -o"); 67480d365605Sschuster 67490d365605Sschuster if (state.es_parseable && fields_str == all_fields) 67500d365605Sschuster die("\"-o all\" is invalid with -p"); 67510d365605Sschuster 6752e7801d59Ssowmini if (optind == (argc - 1)) 6753e7801d59Ssowmini state.es_link = argv[optind]; 6754e7801d59Ssowmini 6755e7801d59Ssowmini fields = parse_output_fields(fields_str, ether_fields, 6756e7801d59Ssowmini ETHER_MAX_FIELDS, CMD_TYPE_ANY, &nfields); 6757e7801d59Ssowmini 67584ac67f02SAnurag S. Maskey if (fields == NULL) 6759e7801d59Ssowmini die("invalid field(s) specified"); 67604ac67f02SAnurag S. Maskey 6761e7801d59Ssowmini state.es_print.ps_fields = fields; 6762e7801d59Ssowmini state.es_print.ps_nfields = nfields; 6763e7801d59Ssowmini 67644ac67f02SAnurag S. Maskey 6765e7801d59Ssowmini if (state.es_link == NULL) { 67664ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(show_etherprop, handle, &state, 6767e7801d59Ssowmini DATALINK_CLASS_PHYS, DL_ETHER, 6768e7801d59Ssowmini DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST); 6769e7801d59Ssowmini } else { 67704ac67f02SAnurag S. Maskey if (!link_is_ether(state.es_link, &linkid)) 6771e7801d59Ssowmini die("invalid link specified"); 67724ac67f02SAnurag S. Maskey (void) show_etherprop(handle, linkid, &state); 6773e7801d59Ssowmini } 6774e7801d59Ssowmini } 6775e7801d59Ssowmini 6776e7801d59Ssowmini static char * 6777e7801d59Ssowmini dladm_print_field(print_field_t *pf, void *arg) 6778e7801d59Ssowmini { 6779e7801d59Ssowmini char *value; 6780e7801d59Ssowmini 6781e7801d59Ssowmini value = (char *)arg + pf->pf_offset; 6782e7801d59Ssowmini return (value); 6783e7801d59Ssowmini } 6784e7801d59Ssowmini 6785e7801d59Ssowmini static int 67864ac67f02SAnurag S. Maskey show_etherprop(dladm_handle_t dh, datalink_id_t linkid, void *arg) 6787e7801d59Ssowmini { 6788e7801d59Ssowmini print_ether_state_t *statep = arg; 6789e7801d59Ssowmini ether_fields_buf_t ebuf; 67904784fcbdSSowmini Varadhan dladm_ether_info_t eattr; 67914784fcbdSSowmini Varadhan dladm_status_t status; 6792e7801d59Ssowmini 67935f5c9f54SAnurag S. Maskey bzero(&ebuf, sizeof (ether_fields_buf_t)); 67944ac67f02SAnurag S. Maskey if (dladm_datalink_id2info(dh, linkid, NULL, NULL, NULL, 6795e7801d59Ssowmini ebuf.eth_link, sizeof (ebuf.eth_link)) != DLADM_STATUS_OK) { 6796e7801d59Ssowmini return (DLADM_WALK_CONTINUE); 6797e7801d59Ssowmini } 6798e7801d59Ssowmini 6799e7801d59Ssowmini if (!statep->es_header && !statep->es_parseable) { 6800e7801d59Ssowmini print_header(&statep->es_print); 6801e7801d59Ssowmini statep->es_header = B_TRUE; 6802e7801d59Ssowmini } 6803e7801d59Ssowmini 68044ac67f02SAnurag S. Maskey status = dladm_ether_info(dh, linkid, &eattr); 68054784fcbdSSowmini Varadhan if (status != DLADM_STATUS_OK) 68064784fcbdSSowmini Varadhan goto cleanup; 6807e7801d59Ssowmini 68084784fcbdSSowmini Varadhan (void) strlcpy(ebuf.eth_ptype, "current", sizeof (ebuf.eth_ptype)); 6809e7801d59Ssowmini 68104784fcbdSSowmini Varadhan (void) dladm_ether_autoneg2str(ebuf.eth_autoneg, 68114784fcbdSSowmini Varadhan sizeof (ebuf.eth_autoneg), &eattr, CURRENT); 68124784fcbdSSowmini Varadhan (void) dladm_ether_pause2str(ebuf.eth_pause, 68134784fcbdSSowmini Varadhan sizeof (ebuf.eth_pause), &eattr, CURRENT); 68144784fcbdSSowmini Varadhan (void) dladm_ether_spdx2str(ebuf.eth_spdx, 68154784fcbdSSowmini Varadhan sizeof (ebuf.eth_spdx), &eattr, CURRENT); 68164784fcbdSSowmini Varadhan (void) strlcpy(ebuf.eth_state, 68174784fcbdSSowmini Varadhan dladm_linkstate2str(eattr.lei_state, ebuf.eth_state), 68184784fcbdSSowmini Varadhan sizeof (ebuf.eth_state)); 68194784fcbdSSowmini Varadhan (void) strlcpy(ebuf.eth_rem_fault, 68204784fcbdSSowmini Varadhan (eattr.lei_attr[CURRENT].le_fault ? "fault" : "none"), 68214784fcbdSSowmini Varadhan sizeof (ebuf.eth_rem_fault)); 6822e7801d59Ssowmini 6823e7801d59Ssowmini dladm_print_output(&statep->es_print, statep->es_parseable, 6824e7801d59Ssowmini dladm_print_field, &ebuf); 6825e7801d59Ssowmini 6826e7801d59Ssowmini if (statep->es_extended) 68274784fcbdSSowmini Varadhan show_ether_xprop(arg, &eattr); 6828e7801d59Ssowmini 68294784fcbdSSowmini Varadhan cleanup: 68304784fcbdSSowmini Varadhan dladm_ether_info_done(&eattr); 6831e7801d59Ssowmini return (DLADM_WALK_CONTINUE); 6832e7801d59Ssowmini } 6833e7801d59Ssowmini 6834e7801d59Ssowmini /* ARGSUSED */ 6835e7801d59Ssowmini static void 68368d5c46e6Sam223141 do_init_secobj(int argc, char **argv, const char *use) 68370ba2cbe9Sxc151355 { 68380ba2cbe9Sxc151355 dladm_status_t status; 68390ba2cbe9Sxc151355 68404ac67f02SAnurag S. Maskey status = dladm_init_secobj(handle); 684133343a97Smeem if (status != DLADM_STATUS_OK) 684233343a97Smeem die_dlerr(status, "secure object initialization failed"); 684333343a97Smeem } 684433343a97Smeem 6845d62bc4baSyz147064 /* 6846d62bc4baSyz147064 * "-R" option support. It is used for live upgrading. Append dladm commands 6847d62bc4baSyz147064 * to a upgrade script which will be run when the alternative root boots up: 6848d62bc4baSyz147064 * 6849b9e076dcSyz147064 * - If the /etc/dladm/datalink.conf file exists on the alternative root, 6850b9e076dcSyz147064 * append dladm commands to the <altroot>/var/svc/profile/upgrade_datalink 6851b9e076dcSyz147064 * script. This script will be run as part of the network/physical service. 6852b9e076dcSyz147064 * We cannot defer this to /var/svc/profile/upgrade because then the 6853b9e076dcSyz147064 * configuration will not be able to take effect before network/physical 6854b9e076dcSyz147064 * plumbs various interfaces. 6855d62bc4baSyz147064 * 6856b9e076dcSyz147064 * - If the /etc/dladm/datalink.conf file does not exist on the alternative 6857b9e076dcSyz147064 * root, append dladm commands to the <altroot>/var/svc/profile/upgrade script, 6858b9e076dcSyz147064 * which will be run in the manifest-import service. 6859d62bc4baSyz147064 * 6860d62bc4baSyz147064 * Note that the SMF team is considering to move the manifest-import service 6861d62bc4baSyz147064 * to be run at the very begining of boot. Once that is done, the need for 6862d62bc4baSyz147064 * the /var/svc/profile/upgrade_datalink script will not exist any more. 6863d62bc4baSyz147064 */ 6864d62bc4baSyz147064 static void 6865d62bc4baSyz147064 altroot_cmd(char *altroot, int argc, char *argv[]) 6866d62bc4baSyz147064 { 6867d62bc4baSyz147064 char path[MAXPATHLEN]; 6868d62bc4baSyz147064 struct stat stbuf; 6869d62bc4baSyz147064 FILE *fp; 6870d62bc4baSyz147064 int i; 6871d62bc4baSyz147064 6872d62bc4baSyz147064 /* 6873b9e076dcSyz147064 * Check for the existence of the /etc/dladm/datalink.conf 6874b9e076dcSyz147064 * configuration file, and determine the name of script file. 6875d62bc4baSyz147064 */ 6876b9e076dcSyz147064 (void) snprintf(path, MAXPATHLEN, "/%s/etc/dladm/datalink.conf", 6877b9e076dcSyz147064 altroot); 6878d62bc4baSyz147064 if (stat(path, &stbuf) < 0) { 6879d62bc4baSyz147064 (void) snprintf(path, MAXPATHLEN, "/%s/%s", altroot, 6880d62bc4baSyz147064 SMF_UPGRADE_FILE); 6881d62bc4baSyz147064 } else { 6882d62bc4baSyz147064 (void) snprintf(path, MAXPATHLEN, "/%s/%s", altroot, 6883d62bc4baSyz147064 SMF_UPGRADEDATALINK_FILE); 6884d62bc4baSyz147064 } 6885d62bc4baSyz147064 6886d62bc4baSyz147064 if ((fp = fopen(path, "a+")) == NULL) 6887d62bc4baSyz147064 die("operation not supported on %s", altroot); 6888d62bc4baSyz147064 6889d62bc4baSyz147064 (void) fprintf(fp, "/sbin/dladm "); 6890d62bc4baSyz147064 for (i = 0; i < argc; i++) { 6891d62bc4baSyz147064 /* 6892d62bc4baSyz147064 * Directly write to the file if it is not the "-R <altroot>" 6893d62bc4baSyz147064 * option. In which case, skip it. 6894d62bc4baSyz147064 */ 6895d62bc4baSyz147064 if (strcmp(argv[i], "-R") != 0) 6896d62bc4baSyz147064 (void) fprintf(fp, "%s ", argv[i]); 6897d62bc4baSyz147064 else 6898d62bc4baSyz147064 i ++; 6899d62bc4baSyz147064 } 6900d62bc4baSyz147064 (void) fprintf(fp, "%s\n", SMF_DLADM_UPGRADE_MSG); 6901d62bc4baSyz147064 (void) fclose(fp); 69024ac67f02SAnurag S. Maskey dladm_close(handle); 6903d62bc4baSyz147064 exit(0); 6904d62bc4baSyz147064 } 6905d62bc4baSyz147064 6906d62bc4baSyz147064 /* 6907d62bc4baSyz147064 * Convert the string to an integer. Note that the string must not have any 6908d62bc4baSyz147064 * trailing non-integer characters. 6909d62bc4baSyz147064 */ 691033343a97Smeem static boolean_t 691133343a97Smeem str2int(const char *str, int *valp) 691233343a97Smeem { 691333343a97Smeem int val; 691433343a97Smeem char *endp = NULL; 691533343a97Smeem 691633343a97Smeem errno = 0; 691733343a97Smeem val = strtol(str, &endp, 10); 691833343a97Smeem if (errno != 0 || *endp != '\0') 691933343a97Smeem return (B_FALSE); 692033343a97Smeem 692133343a97Smeem *valp = val; 692233343a97Smeem return (B_TRUE); 692333343a97Smeem } 692433343a97Smeem 692533343a97Smeem /* PRINTFLIKE1 */ 692633343a97Smeem static void 692733343a97Smeem warn(const char *format, ...) 692833343a97Smeem { 692933343a97Smeem va_list alist; 693033343a97Smeem 693133343a97Smeem format = gettext(format); 693233343a97Smeem (void) fprintf(stderr, "%s: warning: ", progname); 693333343a97Smeem 693433343a97Smeem va_start(alist, format); 693533343a97Smeem (void) vfprintf(stderr, format, alist); 693633343a97Smeem va_end(alist); 693733343a97Smeem 693833343a97Smeem (void) putchar('\n'); 693933343a97Smeem } 694033343a97Smeem 694133343a97Smeem /* PRINTFLIKE2 */ 694233343a97Smeem static void 694333343a97Smeem warn_dlerr(dladm_status_t err, const char *format, ...) 694433343a97Smeem { 694533343a97Smeem va_list alist; 694633343a97Smeem char errmsg[DLADM_STRSIZE]; 694733343a97Smeem 694833343a97Smeem format = gettext(format); 694933343a97Smeem (void) fprintf(stderr, gettext("%s: warning: "), progname); 695033343a97Smeem 695133343a97Smeem va_start(alist, format); 695233343a97Smeem (void) vfprintf(stderr, format, alist); 695333343a97Smeem va_end(alist); 695433343a97Smeem (void) fprintf(stderr, ": %s\n", dladm_status2str(err, errmsg)); 695533343a97Smeem } 695633343a97Smeem 69574ac67f02SAnurag S. Maskey /* 69584ac67f02SAnurag S. Maskey * Also closes the dladm handle if it is not NULL. 69594ac67f02SAnurag S. Maskey */ 696033343a97Smeem /* PRINTFLIKE2 */ 696133343a97Smeem static void 696233343a97Smeem die_dlerr(dladm_status_t err, const char *format, ...) 696333343a97Smeem { 696433343a97Smeem va_list alist; 696533343a97Smeem char errmsg[DLADM_STRSIZE]; 696633343a97Smeem 696733343a97Smeem format = gettext(format); 696833343a97Smeem (void) fprintf(stderr, "%s: ", progname); 696933343a97Smeem 697033343a97Smeem va_start(alist, format); 697133343a97Smeem (void) vfprintf(stderr, format, alist); 697233343a97Smeem va_end(alist); 697333343a97Smeem (void) fprintf(stderr, ": %s\n", dladm_status2str(err, errmsg)); 697433343a97Smeem 69754ac67f02SAnurag S. Maskey /* close dladm handle if it was opened */ 69764ac67f02SAnurag S. Maskey if (handle != NULL) 69774ac67f02SAnurag S. Maskey dladm_close(handle); 69784ac67f02SAnurag S. Maskey 697933343a97Smeem exit(EXIT_FAILURE); 698033343a97Smeem } 698133343a97Smeem 698233343a97Smeem /* PRINTFLIKE1 */ 698333343a97Smeem static void 698433343a97Smeem die(const char *format, ...) 698533343a97Smeem { 698633343a97Smeem va_list alist; 698733343a97Smeem 698833343a97Smeem format = gettext(format); 698933343a97Smeem (void) fprintf(stderr, "%s: ", progname); 699033343a97Smeem 699133343a97Smeem va_start(alist, format); 699233343a97Smeem (void) vfprintf(stderr, format, alist); 699333343a97Smeem va_end(alist); 699433343a97Smeem 699533343a97Smeem (void) putchar('\n'); 69964ac67f02SAnurag S. Maskey 69974ac67f02SAnurag S. Maskey /* close dladm handle if it was opened */ 69984ac67f02SAnurag S. Maskey if (handle != NULL) 69994ac67f02SAnurag S. Maskey dladm_close(handle); 70004ac67f02SAnurag S. Maskey 700133343a97Smeem exit(EXIT_FAILURE); 700233343a97Smeem } 700333343a97Smeem 700433343a97Smeem static void 700533343a97Smeem die_optdup(int opt) 700633343a97Smeem { 700733343a97Smeem die("the option -%c cannot be specified more than once", opt); 700833343a97Smeem } 700933343a97Smeem 701033343a97Smeem static void 70118d5c46e6Sam223141 die_opterr(int opt, int opterr, const char *usage) 701233343a97Smeem { 701333343a97Smeem switch (opterr) { 701433343a97Smeem case ':': 70158d5c46e6Sam223141 die("option '-%c' requires a value\nusage: %s", opt, 70168d5c46e6Sam223141 gettext(usage)); 701733343a97Smeem break; 701833343a97Smeem case '?': 701933343a97Smeem default: 70208d5c46e6Sam223141 die("unrecognized option '-%c'\nusage: %s", opt, 70218d5c46e6Sam223141 gettext(usage)); 702233343a97Smeem break; 70230ba2cbe9Sxc151355 } 70240ba2cbe9Sxc151355 } 7025e7801d59Ssowmini 7026e7801d59Ssowmini static void 70274784fcbdSSowmini Varadhan show_ether_xprop(void *arg, dladm_ether_info_t *eattr) 7028e7801d59Ssowmini { 7029e7801d59Ssowmini print_ether_state_t *statep = arg; 7030e7801d59Ssowmini ether_fields_buf_t ebuf; 70314784fcbdSSowmini Varadhan int i; 7032e7801d59Ssowmini 70334784fcbdSSowmini Varadhan for (i = CAPABLE; i <= PEERADV; i++) { 7034e7801d59Ssowmini bzero(&ebuf, sizeof (ebuf)); 70354784fcbdSSowmini Varadhan (void) strlcpy(ebuf.eth_ptype, ptype[i], 70364784fcbdSSowmini Varadhan sizeof (ebuf.eth_ptype)); 70374784fcbdSSowmini Varadhan (void) dladm_ether_autoneg2str(ebuf.eth_autoneg, 70384784fcbdSSowmini Varadhan sizeof (ebuf.eth_autoneg), eattr, i); 70394784fcbdSSowmini Varadhan (void) dladm_ether_spdx2str(ebuf.eth_spdx, 70404784fcbdSSowmini Varadhan sizeof (ebuf.eth_spdx), eattr, i); 70414784fcbdSSowmini Varadhan (void) dladm_ether_pause2str(ebuf.eth_pause, 70424784fcbdSSowmini Varadhan sizeof (ebuf.eth_pause), eattr, i); 70434784fcbdSSowmini Varadhan (void) strlcpy(ebuf.eth_rem_fault, 70444784fcbdSSowmini Varadhan (eattr->lei_attr[i].le_fault ? "fault" : "none"), 70454784fcbdSSowmini Varadhan sizeof (ebuf.eth_rem_fault)); 7046e7801d59Ssowmini dladm_print_output(&statep->es_print, statep->es_parseable, 7047e7801d59Ssowmini dladm_print_field, &ebuf); 7048e7801d59Ssowmini } 7049e7801d59Ssowmini 7050e7801d59Ssowmini } 7051e7801d59Ssowmini 7052e7801d59Ssowmini static void 7053e7801d59Ssowmini dladm_print_output(print_state_t *statep, boolean_t parseable, 7054e7801d59Ssowmini print_callback_t fn, void *arg) 7055e7801d59Ssowmini { 7056e7801d59Ssowmini int i; 7057e7801d59Ssowmini char *value; 7058e7801d59Ssowmini print_field_t **pf; 7059e7801d59Ssowmini 7060e7801d59Ssowmini pf = statep->ps_fields; 7061e7801d59Ssowmini for (i = 0; i < statep->ps_nfields; i++) { 7062e7801d59Ssowmini statep->ps_lastfield = (i + 1 == statep->ps_nfields); 7063e7801d59Ssowmini value = (*fn)(pf[i], arg); 7064e7801d59Ssowmini if (value != NULL) 7065e7801d59Ssowmini print_field(statep, pf[i], value, parseable); 7066e7801d59Ssowmini } 7067e7801d59Ssowmini (void) putchar('\n'); 7068e7801d59Ssowmini } 7069e7801d59Ssowmini 7070e7801d59Ssowmini static void 7071e7801d59Ssowmini print_header(print_state_t *ps) 7072e7801d59Ssowmini { 7073e7801d59Ssowmini int i; 7074e7801d59Ssowmini print_field_t **pf; 7075e7801d59Ssowmini 7076e7801d59Ssowmini pf = ps->ps_fields; 7077e7801d59Ssowmini for (i = 0; i < ps->ps_nfields; i++) { 7078e7801d59Ssowmini ps->ps_lastfield = (i + 1 == ps->ps_nfields); 7079e7801d59Ssowmini print_field(ps, pf[i], pf[i]->pf_header, B_FALSE); 7080e7801d59Ssowmini } 7081e7801d59Ssowmini (void) putchar('\n'); 7082e7801d59Ssowmini } 7083e7801d59Ssowmini 7084e7801d59Ssowmini static boolean_t 7085e7801d59Ssowmini link_is_ether(const char *link, datalink_id_t *linkid) 7086e7801d59Ssowmini { 7087e7801d59Ssowmini uint32_t media; 7088e7801d59Ssowmini datalink_class_t class; 7089e7801d59Ssowmini 70904ac67f02SAnurag S. Maskey if (dladm_name2info(handle, link, linkid, NULL, &class, &media) == 7091e7801d59Ssowmini DLADM_STATUS_OK) { 7092e7801d59Ssowmini if (class == DATALINK_CLASS_PHYS && media == DL_ETHER) 7093e7801d59Ssowmini return (B_TRUE); 7094e7801d59Ssowmini } 7095e7801d59Ssowmini return (B_FALSE); 7096e7801d59Ssowmini } 7097