17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5219a2a31Shl157128 * Common Development and Distribution License (the "License"). 6219a2a31Shl157128 * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 22d62bc4baSyz147064 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate #include <stdio.h> 270ba2cbe9Sxc151355 #include <ctype.h> 287c478bd9Sstevel@tonic-gate #include <locale.h> 290ba2cbe9Sxc151355 #include <signal.h> 307c478bd9Sstevel@tonic-gate #include <stdarg.h> 317c478bd9Sstevel@tonic-gate #include <stdlib.h> 327c478bd9Sstevel@tonic-gate #include <fcntl.h> 337c478bd9Sstevel@tonic-gate #include <string.h> 347c478bd9Sstevel@tonic-gate #include <stropts.h> 35d62bc4baSyz147064 #include <sys/stat.h> 367c478bd9Sstevel@tonic-gate #include <errno.h> 377c478bd9Sstevel@tonic-gate #include <kstat.h> 387c478bd9Sstevel@tonic-gate #include <strings.h> 397c478bd9Sstevel@tonic-gate #include <getopt.h> 407c478bd9Sstevel@tonic-gate #include <unistd.h> 41cd93090eSericheng #include <priv.h> 420ba2cbe9Sxc151355 #include <termios.h> 430ba2cbe9Sxc151355 #include <pwd.h> 440ba2cbe9Sxc151355 #include <auth_attr.h> 450ba2cbe9Sxc151355 #include <auth_list.h> 467c478bd9Sstevel@tonic-gate #include <libintl.h> 47d62bc4baSyz147064 #include <libdevinfo.h> 487c478bd9Sstevel@tonic-gate #include <libdlpi.h> 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) 195*4ac67f02SAnurag 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; 255da14cebeSEric Cheng print_state_t us_print; 256da14cebeSEric Cheng } show_usage_state_t; 257da14cebeSEric Cheng 2588d5c46e6Sam223141 typedef void cmdfunc_t(int, char **, const char *); 2590ba2cbe9Sxc151355 260da14cebeSEric Cheng static cmdfunc_t do_show_link, do_show_wifi, do_show_phys; 2610ba2cbe9Sxc151355 static cmdfunc_t do_create_aggr, do_delete_aggr, do_add_aggr, do_remove_aggr; 262d62bc4baSyz147064 static cmdfunc_t do_modify_aggr, do_show_aggr, do_up_aggr; 2630ba2cbe9Sxc151355 static cmdfunc_t do_scan_wifi, do_connect_wifi, do_disconnect_wifi; 2640ba2cbe9Sxc151355 static cmdfunc_t do_show_linkprop, do_set_linkprop, do_reset_linkprop; 2650ba2cbe9Sxc151355 static cmdfunc_t do_create_secobj, do_delete_secobj, do_show_secobj; 2660ba2cbe9Sxc151355 static cmdfunc_t do_init_linkprop, do_init_secobj; 267d62bc4baSyz147064 static cmdfunc_t do_create_vlan, do_delete_vlan, do_up_vlan, do_show_vlan; 268d62bc4baSyz147064 static cmdfunc_t do_rename_link, do_delete_phys, do_init_phys; 269d62bc4baSyz147064 static cmdfunc_t do_show_linkmap; 270e7801d59Ssowmini static cmdfunc_t do_show_ether; 271da14cebeSEric Cheng static cmdfunc_t do_create_vnic, do_delete_vnic, do_show_vnic; 272da14cebeSEric Cheng static cmdfunc_t do_up_vnic; 273da14cebeSEric Cheng static cmdfunc_t do_create_etherstub, do_delete_etherstub, do_show_etherstub; 274da14cebeSEric Cheng static cmdfunc_t do_show_usage; 275da14cebeSEric Cheng 276da14cebeSEric Cheng static void do_up_vnic_common(int, char **, const char *, boolean_t); 2777c478bd9Sstevel@tonic-gate 278d62bc4baSyz147064 static void altroot_cmd(char *, int, char **); 279*4ac67f02SAnurag S. Maskey static int show_linkprop_onelink(dladm_handle_t, datalink_id_t, void *); 280f4b3ec61Sdh155122 2816be03d0bSVasumathi Sundaram - Sun Microsystems static void link_stats(datalink_id_t, uint_t, char *, show_state_t *); 282d62bc4baSyz147064 static void aggr_stats(datalink_id_t, show_grp_state_t *, uint_t); 283da14cebeSEric Cheng static void vnic_stats(show_vnic_state_t *, uint32_t); 2847c478bd9Sstevel@tonic-gate 285d62bc4baSyz147064 static int get_one_kstat(const char *, const char *, uint8_t, 286d62bc4baSyz147064 void *, boolean_t); 287ba2e4443Sseb static void get_mac_stats(const char *, pktsum_t *); 2887c478bd9Sstevel@tonic-gate static void get_link_stats(const char *, pktsum_t *); 289d62bc4baSyz147064 static uint64_t get_ifspeed(const char *, boolean_t); 290d62bc4baSyz147064 static const char *get_linkstate(const char *, boolean_t, char *); 291d62bc4baSyz147064 static const char *get_linkduplex(const char *, boolean_t, char *); 2927c478bd9Sstevel@tonic-gate 293*4ac67f02SAnurag S. Maskey static int show_etherprop(dladm_handle_t, datalink_id_t, void *); 2944784fcbdSSowmini Varadhan static void show_ether_xprop(void *, dladm_ether_info_t *); 295e7801d59Ssowmini static boolean_t link_is_ether(const char *, datalink_id_t *); 296e7801d59Ssowmini 29733343a97Smeem static boolean_t str2int(const char *, int *); 29833343a97Smeem static void die(const char *, ...); 29933343a97Smeem static void die_optdup(int); 3008d5c46e6Sam223141 static void die_opterr(int, int, const char *); 30133343a97Smeem static void die_dlerr(dladm_status_t, const char *, ...); 30233343a97Smeem static void warn(const char *, ...); 30333343a97Smeem static void warn_dlerr(dladm_status_t, const char *, ...); 30433343a97Smeem 3057c478bd9Sstevel@tonic-gate typedef struct cmd { 3067c478bd9Sstevel@tonic-gate char *c_name; 3070ba2cbe9Sxc151355 cmdfunc_t *c_fn; 3088d5c46e6Sam223141 const char *c_usage; 3097c478bd9Sstevel@tonic-gate } cmd_t; 3107c478bd9Sstevel@tonic-gate 3117c478bd9Sstevel@tonic-gate static cmd_t cmds[] = { 3128d5c46e6Sam223141 { "show-link", do_show_link, 3138d5c46e6Sam223141 "\tshow-link\t[-pP] [-o <field>,..] [-s [-i <interval>]] [<link>]"}, 3148d5c46e6Sam223141 { "rename-link", do_rename_link, 3158d5c46e6Sam223141 "\trename-link\t[-R <root-dir>] <oldlink> <newlink>\n" }, 3168d5c46e6Sam223141 { "create-aggr", do_create_aggr, 3178d5c46e6Sam223141 "\tcreate-aggr\t[-t] [-R <root-dir>] [-P <policy>] [-L <mode>]\n" 3188d5c46e6Sam223141 "\t\t\t[-T <time>] [-u <address>] [-l <link>] ... <link>" }, 3198d5c46e6Sam223141 { "delete-aggr", do_delete_aggr, 3208d5c46e6Sam223141 "\tdelete-aggr\t[-t] [-R <root-dir>] <link>" }, 3218d5c46e6Sam223141 { "add-aggr", do_add_aggr, 3228d5c46e6Sam223141 "\tadd-aggr\t[-t] [-R <root-dir>] [-l <link>] ... <link>" }, 3238d5c46e6Sam223141 { "remove-aggr", do_remove_aggr, 3248d5c46e6Sam223141 "\tremove-aggr\t[-t] [-R <root-dir>] [-l <link>] ... <link>"}, 3258d5c46e6Sam223141 { "modify-aggr", do_modify_aggr, 3268d5c46e6Sam223141 "\tmodify-aggr\t[-t] [-R <root-dir>] [-P <policy>] [-L <mode>]\n" 3278d5c46e6Sam223141 "\t\t\t[-T <time>] [-u <address>] <link>" }, 3288d5c46e6Sam223141 { "show-aggr", do_show_aggr, 3298d5c46e6Sam223141 "\tshow-aggr\t[-pPLx] [-o <field>,..] [-s [-i <interval>]] " 3308d5c46e6Sam223141 "[<link>]\n" }, 3318d5c46e6Sam223141 { "up-aggr", do_up_aggr, NULL }, 3328d5c46e6Sam223141 { "scan-wifi", do_scan_wifi, 3338d5c46e6Sam223141 "\tscan-wifi\t[-p] [-o <field>,...] [<link>]" }, 3348d5c46e6Sam223141 { "connect-wifi", do_connect_wifi, 3358d5c46e6Sam223141 "\tconnect-wifi\t[-e <essid>] [-i <bssid>] [-k <key>,...] " 3368d5c46e6Sam223141 "[-s wep|wpa]\n" 3378d5c46e6Sam223141 "\t\t\t[-a open|shared] [-b bss|ibss] [-c] [-m a|b|g]\n" 3388d5c46e6Sam223141 "\t\t\t[-T <time>] [<link>]" }, 3398d5c46e6Sam223141 { "disconnect-wifi", do_disconnect_wifi, 3408d5c46e6Sam223141 "\tdisconnect-wifi\t[-a] [<link>]" }, 3418d5c46e6Sam223141 { "show-wifi", do_show_wifi, 3428d5c46e6Sam223141 "\tshow-wifi\t[-p] [-o <field>,...] [<link>]\n" }, 3438d5c46e6Sam223141 { "show-linkprop", do_show_linkprop, 3448d5c46e6Sam223141 "\tshow-linkprop\t[-cP] [-o <field>,...] [-p <prop>,...] <name>"}, 3458d5c46e6Sam223141 { "set-linkprop", do_set_linkprop, 3468d5c46e6Sam223141 "\tset-linkprop\t[-t] [-R <root-dir>] -p <prop>=<value>[,...] " 3478d5c46e6Sam223141 "<name>" }, 3488d5c46e6Sam223141 { "reset-linkprop", do_reset_linkprop, 3498d5c46e6Sam223141 "\treset-linkprop\t[-t] [-R <root-dir>] [-p <prop>,...] <name>\n" }, 3508d5c46e6Sam223141 { "show-ether", do_show_ether, 3518d5c46e6Sam223141 "\tshow-ether\t[-px][-o <field>,...] <link>\n" }, 3528d5c46e6Sam223141 { "create-secobj", do_create_secobj, 3538d5c46e6Sam223141 "\tcreate-secobj\t[-t] [-R <root-dir>] [-f <file>] -c <class> " 3548d5c46e6Sam223141 "<secobj>" }, 3558d5c46e6Sam223141 { "delete-secobj", do_delete_secobj, 3568d5c46e6Sam223141 "\tdelete-secobj\t[-t] [-R <root-dir>] <secobj>[,...]" }, 3578d5c46e6Sam223141 { "show-secobj", do_show_secobj, 3588d5c46e6Sam223141 "\tshow-secobj\t[-pP] [-o <field>,...] [<secobj>,...]\n" }, 3598d5c46e6Sam223141 { "init-linkprop", do_init_linkprop, NULL }, 3608d5c46e6Sam223141 { "init-secobj", do_init_secobj, NULL }, 3618d5c46e6Sam223141 { "create-vlan", do_create_vlan, 3628d5c46e6Sam223141 "\tcreate-vlan\t[-ft] [-R <root-dir>] -l <link> -v <vid> [link]" }, 3638d5c46e6Sam223141 { "delete-vlan", do_delete_vlan, 3648d5c46e6Sam223141 "\tdelete-vlan\t[-t] [-R <root-dir>] <link>" }, 3658d5c46e6Sam223141 { "show-vlan", do_show_vlan, 3668d5c46e6Sam223141 "\tshow-vlan\t[-pP] [-o <field>,..] [<link>]\n" }, 3678d5c46e6Sam223141 { "up-vlan", do_up_vlan, NULL }, 3688d5c46e6Sam223141 { "delete-phys", do_delete_phys, 3698d5c46e6Sam223141 "\tdelete-phys\t<link>" }, 3708d5c46e6Sam223141 { "show-phys", do_show_phys, 371da14cebeSEric Cheng "\tshow-phys\t[-pP] [-o <field>,..] [-H] [<link>]" }, 3728d5c46e6Sam223141 { "init-phys", do_init_phys, NULL }, 373da14cebeSEric Cheng { "show-linkmap", do_show_linkmap, NULL }, 374da14cebeSEric Cheng { "create-vnic", do_create_vnic, 375da14cebeSEric Cheng "\tcreate-vnic [-t] [-R <root-dir>] -l <link> [-m <value> |" 376da14cebeSEric Cheng " auto |\n" 377da14cebeSEric Cheng "\t {factory [-n <slot-identifier>]} |\n" 378da14cebeSEric Cheng "\t {random [-r <prefix>]}] [-v vlan-tag [-f]]\n" 379da14cebeSEric Cheng "\t -p <prop>=<value>[,...] [-H]" 380da14cebeSEric Cheng " <vnic-link>\n" }, 381da14cebeSEric Cheng { "delete-vnic", do_delete_vnic, 382da14cebeSEric Cheng "\tdelete-vnic [-t] [-R <root-dir>] <vnic-link>\n" }, 383da14cebeSEric Cheng { "show-vnic", do_show_vnic, 384da14cebeSEric Cheng "\tshow-vnic [-pP] [-l <link>] [-s [-i <interval>]]" }, 385da14cebeSEric Cheng { "up-vnic", do_up_vnic, NULL }, 386da14cebeSEric Cheng { "create-etherstub", do_create_etherstub, 387da14cebeSEric Cheng "\tcreate-etherstub [-t] [-R <root-dir>] <link>\n" }, 388da14cebeSEric Cheng { "delete-etherstub", do_delete_etherstub, 389da14cebeSEric Cheng "\tdelete-etherstub [-t] [-R <root-dir>] <link>\n" }, 390da14cebeSEric Cheng { "show-etherstub", do_show_etherstub, 391da14cebeSEric Cheng "\tshow-etherstub [-t] [-R <root-dir>] [<link>]\n" }, 392da14cebeSEric Cheng { "show-usage", do_show_usage, 393da14cebeSEric Cheng "\tshow-usage [-d|-p -F <format>] [-f <filename>]\n" 394da14cebeSEric Cheng "\t [-s <time>] [-e <time>] <link>\n" } 3957c478bd9Sstevel@tonic-gate }; 3967c478bd9Sstevel@tonic-gate 397d62bc4baSyz147064 static const struct option lopts[] = { 3987c478bd9Sstevel@tonic-gate {"vlan-id", required_argument, 0, 'v'}, 399e7801d59Ssowmini {"output", required_argument, 0, 'o'}, 4007c478bd9Sstevel@tonic-gate {"dev", required_argument, 0, 'd'}, 4017c478bd9Sstevel@tonic-gate {"policy", required_argument, 0, 'P'}, 402d62bc4baSyz147064 {"lacp-mode", required_argument, 0, 'L'}, 4037c478bd9Sstevel@tonic-gate {"lacp-timer", required_argument, 0, 'T'}, 4047c478bd9Sstevel@tonic-gate {"unicast", required_argument, 0, 'u'}, 405d62bc4baSyz147064 {"temporary", no_argument, 0, 't'}, 406d62bc4baSyz147064 {"root-dir", required_argument, 0, 'R'}, 407d62bc4baSyz147064 {"link", required_argument, 0, 'l'}, 408d62bc4baSyz147064 {"forcible", no_argument, 0, 'f'}, 409da14cebeSEric Cheng {"bw-limit", required_argument, 0, 'b'}, 410da14cebeSEric Cheng {"mac-address", required_argument, 0, 'm'}, 411da14cebeSEric Cheng {"slot", required_argument, 0, 'n'}, 412d62bc4baSyz147064 { 0, 0, 0, 0 } 413d62bc4baSyz147064 }; 414d62bc4baSyz147064 415d62bc4baSyz147064 static const struct option show_lopts[] = { 4167c478bd9Sstevel@tonic-gate {"statistics", no_argument, 0, 's'}, 417da14cebeSEric Cheng {"continuous", no_argument, 0, 'S'}, 4187c478bd9Sstevel@tonic-gate {"interval", required_argument, 0, 'i'}, 4197c478bd9Sstevel@tonic-gate {"parseable", no_argument, 0, 'p'}, 420d62bc4baSyz147064 {"extended", no_argument, 0, 'x'}, 421e7801d59Ssowmini {"output", required_argument, 0, 'o'}, 422d62bc4baSyz147064 {"persistent", no_argument, 0, 'P'}, 423d62bc4baSyz147064 {"lacp", no_argument, 0, 'L'}, 4247c478bd9Sstevel@tonic-gate { 0, 0, 0, 0 } 4257c478bd9Sstevel@tonic-gate }; 4267c478bd9Sstevel@tonic-gate 4270ba2cbe9Sxc151355 static const struct option prop_longopts[] = { 4280ba2cbe9Sxc151355 {"temporary", no_argument, 0, 't' }, 429e7801d59Ssowmini {"output", required_argument, 0, 'o' }, 4300ba2cbe9Sxc151355 {"root-dir", required_argument, 0, 'R' }, 4310ba2cbe9Sxc151355 {"prop", required_argument, 0, 'p' }, 4320ba2cbe9Sxc151355 {"parseable", no_argument, 0, 'c' }, 4330ba2cbe9Sxc151355 {"persistent", no_argument, 0, 'P' }, 4340ba2cbe9Sxc151355 { 0, 0, 0, 0 } 4350ba2cbe9Sxc151355 }; 4360ba2cbe9Sxc151355 4370ba2cbe9Sxc151355 static const struct option wifi_longopts[] = { 4380ba2cbe9Sxc151355 {"parseable", no_argument, 0, 'p' }, 4390ba2cbe9Sxc151355 {"output", required_argument, 0, 'o' }, 4400ba2cbe9Sxc151355 {"essid", required_argument, 0, 'e' }, 4410ba2cbe9Sxc151355 {"bsstype", required_argument, 0, 'b' }, 4420ba2cbe9Sxc151355 {"mode", required_argument, 0, 'm' }, 4430ba2cbe9Sxc151355 {"key", required_argument, 0, 'k' }, 4440ba2cbe9Sxc151355 {"sec", required_argument, 0, 's' }, 4450ba2cbe9Sxc151355 {"auth", required_argument, 0, 'a' }, 4460ba2cbe9Sxc151355 {"create-ibss", required_argument, 0, 'c' }, 4470ba2cbe9Sxc151355 {"timeout", required_argument, 0, 'T' }, 4480ba2cbe9Sxc151355 {"all-links", no_argument, 0, 'a' }, 4490ba2cbe9Sxc151355 {"temporary", no_argument, 0, 't' }, 4500ba2cbe9Sxc151355 {"root-dir", required_argument, 0, 'R' }, 4510ba2cbe9Sxc151355 {"persistent", no_argument, 0, 'P' }, 4520ba2cbe9Sxc151355 {"file", required_argument, 0, 'f' }, 4530ba2cbe9Sxc151355 { 0, 0, 0, 0 } 4540ba2cbe9Sxc151355 }; 455e7801d59Ssowmini static const struct option showeth_lopts[] = { 456e7801d59Ssowmini {"parseable", no_argument, 0, 'p' }, 457e7801d59Ssowmini {"extended", no_argument, 0, 'x' }, 458e7801d59Ssowmini {"output", required_argument, 0, 'o' }, 459e7801d59Ssowmini { 0, 0, 0, 0 } 460e7801d59Ssowmini }; 461e7801d59Ssowmini 462da14cebeSEric Cheng static const struct option vnic_lopts[] = { 463da14cebeSEric Cheng {"temporary", no_argument, 0, 't' }, 464da14cebeSEric Cheng {"root-dir", required_argument, 0, 'R' }, 465da14cebeSEric Cheng {"dev", required_argument, 0, 'd' }, 466da14cebeSEric Cheng {"mac-address", required_argument, 0, 'm' }, 467da14cebeSEric Cheng {"cpus", required_argument, 0, 'c' }, 468da14cebeSEric Cheng {"bw-limit", required_argument, 0, 'b' }, 469da14cebeSEric Cheng {"slot", required_argument, 0, 'n' }, 470da14cebeSEric Cheng {"mac-prefix", required_argument, 0, 'r' }, 471da14cebeSEric Cheng { 0, 0, 0, 0 } 472da14cebeSEric Cheng }; 473da14cebeSEric Cheng 474da14cebeSEric Cheng static const struct option etherstub_lopts[] = { 475da14cebeSEric Cheng {"temporary", no_argument, 0, 't' }, 476da14cebeSEric Cheng {"root-dir", required_argument, 0, 'R' }, 477da14cebeSEric Cheng { 0, 0, 0, 0 } 478da14cebeSEric Cheng }; 479da14cebeSEric Cheng 480e7801d59Ssowmini /* 481e7801d59Ssowmini * structures for 'dladm show-ether' 482e7801d59Ssowmini */ 4834784fcbdSSowmini Varadhan static const char *ptype[] = {LEI_ATTR_NAMES}; 4844784fcbdSSowmini Varadhan 485e7801d59Ssowmini typedef struct ether_fields_buf_s 486e7801d59Ssowmini { 487e7801d59Ssowmini char eth_link[15]; 488e7801d59Ssowmini char eth_ptype[8]; 489e7801d59Ssowmini char eth_state[8]; 490e7801d59Ssowmini char eth_autoneg[5]; 491e7801d59Ssowmini char eth_spdx[31]; 492e7801d59Ssowmini char eth_pause[6]; 493e7801d59Ssowmini char eth_rem_fault[16]; 494e7801d59Ssowmini } ether_fields_buf_t; 495e7801d59Ssowmini 496e7801d59Ssowmini static print_field_t ether_fields[] = { 497e7801d59Ssowmini /* name, header, field width, offset, cmdtype */ 498e7801d59Ssowmini { "link", "LINK", 15, 499e7801d59Ssowmini offsetof(ether_fields_buf_t, eth_link), CMD_TYPE_ANY}, 500e7801d59Ssowmini { "ptype", "PTYPE", 8, 501e7801d59Ssowmini offsetof(ether_fields_buf_t, eth_ptype), CMD_TYPE_ANY}, 502e7801d59Ssowmini { "state", "STATE", 8, 503e7801d59Ssowmini offsetof(ether_fields_buf_t, eth_state), CMD_TYPE_ANY}, 504e7801d59Ssowmini { "auto", "AUTO", 5, 505e7801d59Ssowmini offsetof(ether_fields_buf_t, eth_autoneg), CMD_TYPE_ANY}, 506e7801d59Ssowmini { "speed-duplex", "SPEED-DUPLEX", 31, 507e7801d59Ssowmini offsetof(ether_fields_buf_t, eth_spdx), CMD_TYPE_ANY}, 508e7801d59Ssowmini { "pause", "PAUSE", 6, 509e7801d59Ssowmini offsetof(ether_fields_buf_t, eth_pause), CMD_TYPE_ANY}, 510e7801d59Ssowmini { "rem_fault", "REM_FAULT", 16, 511e7801d59Ssowmini offsetof(ether_fields_buf_t, eth_rem_fault), CMD_TYPE_ANY}} 512e7801d59Ssowmini ; 513e7801d59Ssowmini #define ETHER_MAX_FIELDS (sizeof (ether_fields) / sizeof (print_field_t)) 514e7801d59Ssowmini 515e7801d59Ssowmini typedef struct print_ether_state { 516e7801d59Ssowmini const char *es_link; 517e7801d59Ssowmini boolean_t es_parseable; 518e7801d59Ssowmini boolean_t es_header; 519e7801d59Ssowmini boolean_t es_extended; 520e7801d59Ssowmini print_state_t es_print; 521e7801d59Ssowmini } print_ether_state_t; 522e7801d59Ssowmini 523e7801d59Ssowmini /* 524da14cebeSEric Cheng * structures for 'dladm show-link -s' (print statistics) 525e7801d59Ssowmini */ 526e7801d59Ssowmini typedef enum { 527e7801d59Ssowmini DEVS_LINK, 528e7801d59Ssowmini DEVS_IPKTS, 529e7801d59Ssowmini DEVS_RBYTES, 530e7801d59Ssowmini DEVS_IERRORS, 531e7801d59Ssowmini DEVS_OPKTS, 532e7801d59Ssowmini DEVS_OBYTES, 533e7801d59Ssowmini DEVS_OERRORS 534e7801d59Ssowmini } devs_field_index_t; 535e7801d59Ssowmini 536e7801d59Ssowmini static print_field_t devs_fields[] = { 537e7801d59Ssowmini /* name, header, field width, index, cmdtype */ 538e7801d59Ssowmini { "link", "LINK", 15, DEVS_LINK, CMD_TYPE_ANY}, 539e7801d59Ssowmini { "ipackets", "IPACKETS", 10, DEVS_IPKTS, CMD_TYPE_ANY}, 540e7801d59Ssowmini { "rbytes", "RBYTES", 8, DEVS_RBYTES, CMD_TYPE_ANY}, 541e7801d59Ssowmini { "ierrors", "IERRORS", 10, DEVS_IERRORS, CMD_TYPE_ANY}, 542e7801d59Ssowmini { "opackets", "OPACKETS", 12, DEVS_OPKTS, CMD_TYPE_ANY}, 543e7801d59Ssowmini { "obytes", "OBYTES", 12, DEVS_OBYTES, CMD_TYPE_ANY}, 544e7801d59Ssowmini { "oerrors", "OERRORS", 8, DEVS_OERRORS, CMD_TYPE_ANY}} 545e7801d59Ssowmini ; 546e7801d59Ssowmini #define DEVS_MAX_FIELDS (sizeof (devs_fields) / sizeof (print_field_t)) 547e7801d59Ssowmini 548e7801d59Ssowmini /* 549e7801d59Ssowmini * buffer used by print functions for show-{link,phys,vlan} commands. 550e7801d59Ssowmini */ 551e7801d59Ssowmini typedef struct link_fields_buf_s { 552e7801d59Ssowmini char link_name[MAXLINKNAMELEN]; 553e7801d59Ssowmini char link_class[DLADM_STRSIZE]; 554c08e5e1aSdr146992 char link_mtu[11]; 555e7801d59Ssowmini char link_state[DLADM_STRSIZE]; 556e7801d59Ssowmini char link_over[MAXLINKNAMELEN]; 5574045d941Ssowmini char link_phys_state[DLADM_STRSIZE]; 558e7801d59Ssowmini char link_phys_media[DLADM_STRSIZE]; 559e7801d59Ssowmini char link_phys_speed[DLADM_STRSIZE]; 560e7801d59Ssowmini char link_phys_duplex[DLPI_LINKNAME_MAX]; 561e7801d59Ssowmini char link_phys_device[DLPI_LINKNAME_MAX]; 562e7801d59Ssowmini char link_flags[6]; 563e7801d59Ssowmini char link_vlan_vid[6]; 564e7801d59Ssowmini } link_fields_buf_t; 565e7801d59Ssowmini 566e7801d59Ssowmini /* 567e7801d59Ssowmini * structures for 'dladm show-link' 568e7801d59Ssowmini */ 569e7801d59Ssowmini static print_field_t link_fields[] = { 570e7801d59Ssowmini /* name, header, field width, offset, cmdtype */ 571e7801d59Ssowmini { "link", "LINK", 11, 572e7801d59Ssowmini offsetof(link_fields_buf_t, link_name), CMD_TYPE_ANY}, 573e7801d59Ssowmini { "class", "CLASS", 8, 574e7801d59Ssowmini offsetof(link_fields_buf_t, link_class), CMD_TYPE_ANY}, 575e7801d59Ssowmini { "mtu", "MTU", 6, 576e7801d59Ssowmini offsetof(link_fields_buf_t, link_mtu), CMD_TYPE_ANY}, 577e7801d59Ssowmini { "state", "STATE", 8, 578e7801d59Ssowmini offsetof(link_fields_buf_t, link_state), CMD_TYPE_ANY}, 579e7801d59Ssowmini { "over", "OVER", DLPI_LINKNAME_MAX, 580e7801d59Ssowmini offsetof(link_fields_buf_t, link_over), CMD_TYPE_ANY}} 581e7801d59Ssowmini ; 582e7801d59Ssowmini #define DEV_LINK_FIELDS (sizeof (link_fields) / sizeof (print_field_t)) 583e7801d59Ssowmini 584e7801d59Ssowmini /* 585e7801d59Ssowmini * structures for 'dladm show-aggr' 586e7801d59Ssowmini */ 587e7801d59Ssowmini typedef struct laggr_fields_buf_s { 588e7801d59Ssowmini char laggr_name[DLPI_LINKNAME_MAX]; 589e7801d59Ssowmini char laggr_policy[9]; 590e7801d59Ssowmini char laggr_addrpolicy[ETHERADDRL * 3 + 3]; 591e7801d59Ssowmini char laggr_lacpactivity[14]; 592e7801d59Ssowmini char laggr_lacptimer[DLADM_STRSIZE]; 593e7801d59Ssowmini char laggr_flags[7]; 594e7801d59Ssowmini } laggr_fields_buf_t; 595e7801d59Ssowmini 596e7801d59Ssowmini typedef struct laggr_args_s { 597e7801d59Ssowmini int laggr_lport; /* -1 indicates the aggr itself */ 598e7801d59Ssowmini const char *laggr_link; 599e7801d59Ssowmini dladm_aggr_grp_attr_t *laggr_ginfop; 600e7801d59Ssowmini dladm_status_t *laggr_status; 601e7801d59Ssowmini pktsum_t *laggr_pktsumtot; /* -s only */ 602e7801d59Ssowmini pktsum_t *laggr_prevstats; /* -s only */ 603e7801d59Ssowmini boolean_t laggr_parseable; 604e7801d59Ssowmini } laggr_args_t; 605e7801d59Ssowmini 606e7801d59Ssowmini static print_field_t laggr_fields[] = { 607e7801d59Ssowmini /* name, header, field width, offset, cmdtype */ 608e7801d59Ssowmini { "link", "LINK", 15, 609e7801d59Ssowmini offsetof(laggr_fields_buf_t, laggr_name), CMD_TYPE_ANY}, 610e7801d59Ssowmini { "policy", "POLICY", 8, 611e7801d59Ssowmini offsetof(laggr_fields_buf_t, laggr_policy), CMD_TYPE_ANY}, 612e7801d59Ssowmini { "addrpolicy", "ADDRPOLICY", ETHERADDRL * 3 + 2, 613e7801d59Ssowmini offsetof(laggr_fields_buf_t, laggr_addrpolicy), CMD_TYPE_ANY}, 614e7801d59Ssowmini { "lacpactivity", "LACPACTIVITY", 13, 615e7801d59Ssowmini offsetof(laggr_fields_buf_t, laggr_lacpactivity), CMD_TYPE_ANY}, 616e7801d59Ssowmini { "lacptimer", "LACPTIMER", 11, 617e7801d59Ssowmini offsetof(laggr_fields_buf_t, laggr_lacptimer), CMD_TYPE_ANY}, 618e7801d59Ssowmini { "flags", "FLAGS", 7, 619e7801d59Ssowmini offsetof(laggr_fields_buf_t, laggr_flags), CMD_TYPE_ANY}} 620e7801d59Ssowmini ; 621e7801d59Ssowmini #define LAGGR_MAX_FIELDS (sizeof (laggr_fields) / sizeof (print_field_t)) 622e7801d59Ssowmini 623e7801d59Ssowmini /* 624e7801d59Ssowmini * structures for 'dladm show-aggr -x'. 625e7801d59Ssowmini */ 626e7801d59Ssowmini typedef enum { 627e7801d59Ssowmini AGGR_X_LINK, 628e7801d59Ssowmini AGGR_X_PORT, 629e7801d59Ssowmini AGGR_X_SPEED, 630e7801d59Ssowmini AGGR_X_DUPLEX, 631e7801d59Ssowmini AGGR_X_STATE, 632e7801d59Ssowmini AGGR_X_ADDRESS, 633e7801d59Ssowmini AGGR_X_PORTSTATE 634e7801d59Ssowmini } aggr_x_field_index_t; 635e7801d59Ssowmini 636e7801d59Ssowmini static print_field_t aggr_x_fields[] = { 637e7801d59Ssowmini /* name, header, field width, index, cmdtype */ 638e7801d59Ssowmini { "link", "LINK", 11, AGGR_X_LINK, CMD_TYPE_ANY}, 639e7801d59Ssowmini { "port", "PORT", 14, AGGR_X_PORT, CMD_TYPE_ANY}, 640e7801d59Ssowmini { "speed", "SPEED", 4, AGGR_X_SPEED, CMD_TYPE_ANY}, 641e7801d59Ssowmini { "duplex", "DUPLEX", 9, AGGR_X_DUPLEX, CMD_TYPE_ANY}, 642e7801d59Ssowmini { "state", "STATE", 9, AGGR_X_STATE, CMD_TYPE_ANY}, 643e7801d59Ssowmini { "address", "ADDRESS", 18, AGGR_X_ADDRESS, CMD_TYPE_ANY}, 644e7801d59Ssowmini { "portstate", "PORTSTATE", 15, AGGR_X_PORTSTATE, CMD_TYPE_ANY}} 645e7801d59Ssowmini ; 646e7801d59Ssowmini #define AGGR_X_MAX_FIELDS \ 647e7801d59Ssowmini (sizeof (aggr_x_fields) / sizeof (print_field_t)) 648e7801d59Ssowmini 649e7801d59Ssowmini /* 650e7801d59Ssowmini * structures for 'dladm show-aggr -s'. 651e7801d59Ssowmini */ 652e7801d59Ssowmini typedef enum { 653e7801d59Ssowmini AGGR_S_LINK, 654e7801d59Ssowmini AGGR_S_PORT, 655e7801d59Ssowmini AGGR_S_IPKTS, 656e7801d59Ssowmini AGGR_S_RBYTES, 657e7801d59Ssowmini AGGR_S_OPKTS, 658e7801d59Ssowmini AGGR_S_OBYTES, 659e7801d59Ssowmini AGGR_S_IPKTDIST, 660e7801d59Ssowmini AGGR_S_OPKTDIST 661e7801d59Ssowmini } aggr_s_field_index_t; 662e7801d59Ssowmini 663e7801d59Ssowmini static print_field_t aggr_s_fields[] = { 664e7801d59Ssowmini /* name, header, field width, index, cmdtype */ 665e7801d59Ssowmini { "link", "LINK", 11, AGGR_S_LINK, 666e7801d59Ssowmini CMD_TYPE_ANY}, 667e7801d59Ssowmini { "port", "PORT", 9, AGGR_S_PORT, 668e7801d59Ssowmini CMD_TYPE_ANY}, 669e7801d59Ssowmini { "ipackets", "IPACKETS", 7, AGGR_S_IPKTS, 670e7801d59Ssowmini CMD_TYPE_ANY}, 671e7801d59Ssowmini { "rbytes", "RBYTES", 7, AGGR_S_RBYTES, 672e7801d59Ssowmini CMD_TYPE_ANY}, 673e7801d59Ssowmini { "opackets", "OPACKETS", 7, AGGR_S_OPKTS, 674e7801d59Ssowmini CMD_TYPE_ANY}, 675e7801d59Ssowmini { "obytes", "OBYTES", 7, AGGR_S_OBYTES, 676e7801d59Ssowmini CMD_TYPE_ANY}, 677e7801d59Ssowmini { "ipktdist", "IPKTDIST", 8, AGGR_S_IPKTDIST, 678e7801d59Ssowmini CMD_TYPE_ANY}, 679e7801d59Ssowmini { "opktdist", "OPKTDIST", 14, AGGR_S_OPKTDIST, 680e7801d59Ssowmini CMD_TYPE_ANY}} 681e7801d59Ssowmini ; 682e7801d59Ssowmini #define AGGR_S_MAX_FIELDS \ 683da14cebeSEric Cheng (sizeof (aggr_s_fields) / sizeof (print_field_t)) 684e7801d59Ssowmini 685e7801d59Ssowmini /* 686da14cebeSEric Cheng * structures for 'dladm show-aggr -L'. 687e7801d59Ssowmini */ 688e7801d59Ssowmini typedef enum { 689e7801d59Ssowmini AGGR_L_LINK, 690e7801d59Ssowmini AGGR_L_PORT, 691e7801d59Ssowmini AGGR_L_AGGREGATABLE, 692e7801d59Ssowmini AGGR_L_SYNC, 693e7801d59Ssowmini AGGR_L_COLL, 694e7801d59Ssowmini AGGR_L_DIST, 695e7801d59Ssowmini AGGR_L_DEFAULTED, 696e7801d59Ssowmini AGGR_L_EXPIRED 697e7801d59Ssowmini } aggr_l_field_index_t; 698e7801d59Ssowmini 699e7801d59Ssowmini static print_field_t aggr_l_fields[] = { 700e7801d59Ssowmini /* name, header, field width, index, cmdtype */ 701e7801d59Ssowmini { "link", "LINK", 11, AGGR_L_LINK, 702e7801d59Ssowmini CMD_TYPE_ANY}, 703e7801d59Ssowmini { "port", "PORT", 12, AGGR_L_PORT, 704e7801d59Ssowmini CMD_TYPE_ANY}, 705e7801d59Ssowmini { "aggregatable", "AGGREGATABLE", 12, AGGR_L_AGGREGATABLE, 706e7801d59Ssowmini CMD_TYPE_ANY}, 707e7801d59Ssowmini { "sync", "SYNC", 4, AGGR_L_SYNC, 708e7801d59Ssowmini CMD_TYPE_ANY}, 709e7801d59Ssowmini { "coll", "COLL", 4, AGGR_L_COLL, 710e7801d59Ssowmini CMD_TYPE_ANY}, 711e7801d59Ssowmini { "dist", "DIST", 4, AGGR_L_DIST, 712e7801d59Ssowmini CMD_TYPE_ANY}, 713e7801d59Ssowmini { "defaulted", "DEFAULTED", 9, AGGR_L_DEFAULTED, 714e7801d59Ssowmini CMD_TYPE_ANY}, 715e7801d59Ssowmini { "expired", "EXPIRED", 14, AGGR_L_EXPIRED, 716e7801d59Ssowmini CMD_TYPE_ANY}} 717e7801d59Ssowmini ; 718e7801d59Ssowmini #define AGGR_L_MAX_FIELDS \ 719e7801d59Ssowmini (sizeof (aggr_l_fields) / sizeof (print_field_t)) 720e7801d59Ssowmini 721e7801d59Ssowmini /* 722e7801d59Ssowmini * structures for 'dladm show-phys' 723e7801d59Ssowmini */ 724e7801d59Ssowmini 725e7801d59Ssowmini static print_field_t phys_fields[] = { 726e7801d59Ssowmini /* name, header, field width, offset, cmdtype */ 727e7801d59Ssowmini { "link", "LINK", 12, 728e7801d59Ssowmini offsetof(link_fields_buf_t, link_name), CMD_TYPE_ANY}, 729e7801d59Ssowmini { "media", "MEDIA", 20, 730e7801d59Ssowmini offsetof(link_fields_buf_t, link_phys_media), CMD_TYPE_ANY}, 731e7801d59Ssowmini { "state", "STATE", 10, 732e7801d59Ssowmini offsetof(link_fields_buf_t, link_phys_state), CMD_TYPE_ANY}, 7336be03d0bSVasumathi Sundaram - Sun Microsystems { "speed", "SPEED", 6, 734e7801d59Ssowmini offsetof(link_fields_buf_t, link_phys_speed), CMD_TYPE_ANY}, 735e7801d59Ssowmini { "duplex", "DUPLEX", 9, 736e7801d59Ssowmini offsetof(link_fields_buf_t, link_phys_duplex), CMD_TYPE_ANY}, 737e7801d59Ssowmini { "device", "DEVICE", 12, 738e7801d59Ssowmini offsetof(link_fields_buf_t, link_phys_device), CMD_TYPE_ANY}, 739e7801d59Ssowmini { "flags", "FLAGS", 6, 740e7801d59Ssowmini offsetof(link_fields_buf_t, link_flags), CMD_TYPE_ANY}} 741e7801d59Ssowmini ; 742e7801d59Ssowmini #define PHYS_MAX_FIELDS (sizeof (phys_fields) / sizeof (print_field_t)) 743e7801d59Ssowmini 744e7801d59Ssowmini /* 745da14cebeSEric Cheng * structures for 'dladm show-phys -m' 746da14cebeSEric Cheng */ 747da14cebeSEric Cheng 748da14cebeSEric Cheng typedef enum { 749da14cebeSEric Cheng PHYS_M_LINK, 750da14cebeSEric Cheng PHYS_M_SLOT, 751da14cebeSEric Cheng PHYS_M_ADDRESS, 752da14cebeSEric Cheng PHYS_M_INUSE, 753da14cebeSEric Cheng PHYS_M_CLIENT 754da14cebeSEric Cheng } phys_m_field_index_t; 755da14cebeSEric Cheng 756da14cebeSEric Cheng static print_field_t phys_m_fields[] = { 757da14cebeSEric Cheng /* name, header, field width, offset, cmdtype */ 758da14cebeSEric Cheng { "link", "LINK", 12, PHYS_M_LINK, CMD_TYPE_ANY}, 759da14cebeSEric Cheng { "slot", "SLOT", 8, PHYS_M_SLOT, CMD_TYPE_ANY}, 760da14cebeSEric Cheng { "address", "ADDRESS", 18, PHYS_M_ADDRESS, CMD_TYPE_ANY}, 761da14cebeSEric Cheng { "inuse", "INUSE", 4, PHYS_M_INUSE, CMD_TYPE_ANY}, 762da14cebeSEric Cheng { "client", "CLIENT", 12, PHYS_M_CLIENT, CMD_TYPE_ANY}} 763da14cebeSEric Cheng ; 764da14cebeSEric Cheng #define PHYS_M_MAX_FIELDS (sizeof (phys_m_fields) / sizeof (print_field_t)) 765da14cebeSEric Cheng 766da14cebeSEric Cheng /* 767da14cebeSEric Cheng * structures for 'dladm show-phys -H' 768da14cebeSEric Cheng */ 769da14cebeSEric Cheng 770da14cebeSEric Cheng typedef enum { 771da14cebeSEric Cheng PHYS_H_LINK, 772da14cebeSEric Cheng PHYS_H_GROUP, 773da14cebeSEric Cheng PHYS_H_GRPTYPE, 774da14cebeSEric Cheng PHYS_H_RINGS, 775da14cebeSEric Cheng PHYS_H_CLIENTS 776da14cebeSEric Cheng } phys_h_field_index_t; 777da14cebeSEric Cheng 778da14cebeSEric Cheng static print_field_t phys_h_fields[] = { 779da14cebeSEric Cheng /* name, header, field width, offset, cmdtype */ 780da14cebeSEric Cheng { "link", "LINK", 12, PHYS_H_LINK, CMD_TYPE_ANY}, 781da14cebeSEric Cheng { "group", "GROUP", 8, PHYS_H_GROUP, CMD_TYPE_ANY}, 782da14cebeSEric Cheng { "grouptype", "TYPE", 6, PHYS_H_GRPTYPE, CMD_TYPE_ANY}, 783da14cebeSEric Cheng { "rings", "NUM-RINGS", 16, PHYS_H_RINGS, CMD_TYPE_ANY}, 784da14cebeSEric Cheng { "clients", "CLIENTS", 20, PHYS_H_CLIENTS, CMD_TYPE_ANY}} 785da14cebeSEric Cheng ; 786da14cebeSEric Cheng #define PHYS_H_MAX_FIELDS (sizeof (phys_h_fields) / sizeof (print_field_t)) 787da14cebeSEric Cheng 788da14cebeSEric Cheng /* 789e7801d59Ssowmini * structures for 'dladm show-vlan' 790e7801d59Ssowmini */ 791e7801d59Ssowmini static print_field_t vlan_fields[] = { 792e7801d59Ssowmini /* name, header, field width, offset, cmdtype */ 793e7801d59Ssowmini { "link", "LINK", 15, 794e7801d59Ssowmini offsetof(link_fields_buf_t, link_name), CMD_TYPE_ANY}, 795e7801d59Ssowmini { "vid", "VID", 8, 796e7801d59Ssowmini offsetof(link_fields_buf_t, link_vlan_vid), CMD_TYPE_ANY}, 797e7801d59Ssowmini { "over", "OVER", 12, 798e7801d59Ssowmini offsetof(link_fields_buf_t, link_over), CMD_TYPE_ANY}, 799e7801d59Ssowmini { "flags", "FLAGS", 6, 800e7801d59Ssowmini offsetof(link_fields_buf_t, link_flags), CMD_TYPE_ANY}} 801e7801d59Ssowmini ; 802e7801d59Ssowmini #define VLAN_MAX_FIELDS (sizeof (vlan_fields) / sizeof (print_field_t)) 803e7801d59Ssowmini 804da14cebeSEric Cheng 805e7801d59Ssowmini /* 806e7801d59Ssowmini * structures for 'dladm show-wifi' 807e7801d59Ssowmini */ 808e7801d59Ssowmini static print_field_t wifi_fields[] = { 809e7801d59Ssowmini { "link", "LINK", 10, 0, WIFI_CMD_ALL}, 810e7801d59Ssowmini { "essid", "ESSID", 19, DLADM_WLAN_ATTR_ESSID, WIFI_CMD_ALL}, 811e7801d59Ssowmini { "bssid", "BSSID/IBSSID", 17, DLADM_WLAN_ATTR_BSSID, WIFI_CMD_ALL}, 812e7801d59Ssowmini { "ibssid", "BSSID/IBSSID", 17, DLADM_WLAN_ATTR_BSSID, WIFI_CMD_ALL}, 813e7801d59Ssowmini { "mode", "MODE", 6, DLADM_WLAN_ATTR_MODE, WIFI_CMD_ALL}, 814e7801d59Ssowmini { "speed", "SPEED", 6, DLADM_WLAN_ATTR_SPEED, WIFI_CMD_ALL}, 815e7801d59Ssowmini { "auth", "AUTH", 8, DLADM_WLAN_ATTR_AUTH, WIFI_CMD_SHOW}, 816e7801d59Ssowmini { "bsstype", "BSSTYPE", 8, DLADM_WLAN_ATTR_BSSTYPE, WIFI_CMD_ALL}, 817e7801d59Ssowmini { "sec", "SEC", 6, DLADM_WLAN_ATTR_SECMODE, WIFI_CMD_ALL}, 818e7801d59Ssowmini { "status", "STATUS", 17, DLADM_WLAN_LINKATTR_STATUS, WIFI_CMD_SHOW}, 819e7801d59Ssowmini { "strength", "STRENGTH", 10, DLADM_WLAN_ATTR_STRENGTH, WIFI_CMD_ALL}} 820e7801d59Ssowmini ; 821e7801d59Ssowmini 822e7801d59Ssowmini static char *all_scan_wifi_fields = 823e7801d59Ssowmini "link,essid,bssid,sec,strength,mode,speed,bsstype"; 824e7801d59Ssowmini static char *all_show_wifi_fields = 825e7801d59Ssowmini "link,status,essid,sec,strength,mode,speed,auth,bssid,bsstype"; 826e7801d59Ssowmini static char *def_scan_wifi_fields = 827e7801d59Ssowmini "link,essid,bssid,sec,strength,mode,speed"; 828e7801d59Ssowmini static char *def_show_wifi_fields = 829e7801d59Ssowmini "link,status,essid,sec,strength,mode,speed"; 830e7801d59Ssowmini 831e7801d59Ssowmini #define WIFI_MAX_FIELDS (sizeof (wifi_fields) / sizeof (print_field_t)) 832e7801d59Ssowmini 833e7801d59Ssowmini /* 834e7801d59Ssowmini * structures for 'dladm show-linkprop' 835e7801d59Ssowmini */ 836e7801d59Ssowmini typedef enum { 837e7801d59Ssowmini LINKPROP_LINK, 838e7801d59Ssowmini LINKPROP_PROPERTY, 839afdda45fSVasumathi Sundaram - Sun Microsystems LINKPROP_PERM, 840e7801d59Ssowmini LINKPROP_VALUE, 841e7801d59Ssowmini LINKPROP_DEFAULT, 842e7801d59Ssowmini LINKPROP_POSSIBLE 843e7801d59Ssowmini } linkprop_field_index_t; 844e7801d59Ssowmini 845e7801d59Ssowmini static print_field_t linkprop_fields[] = { 846e7801d59Ssowmini /* name, header, field width, index, cmdtype */ 847e7801d59Ssowmini { "link", "LINK", 12, LINKPROP_LINK, CMD_TYPE_ANY}, 848e7801d59Ssowmini { "property", "PROPERTY", 15, LINKPROP_PROPERTY, CMD_TYPE_ANY}, 849afdda45fSVasumathi Sundaram - Sun Microsystems { "perm", "PERM", 4, LINKPROP_PERM, CMD_TYPE_ANY}, 850e7801d59Ssowmini { "value", "VALUE", 14, LINKPROP_VALUE, CMD_TYPE_ANY}, 851e7801d59Ssowmini { "default", "DEFAULT", 14, LINKPROP_DEFAULT, CMD_TYPE_ANY}, 852e7801d59Ssowmini { "possible", "POSSIBLE", 20, LINKPROP_POSSIBLE, CMD_TYPE_ANY}} 853e7801d59Ssowmini ; 854e7801d59Ssowmini #define LINKPROP_MAX_FIELDS \ 855e7801d59Ssowmini (sizeof (linkprop_fields) / sizeof (print_field_t)) 856e7801d59Ssowmini 857e7801d59Ssowmini #define MAX_PROP_LINE 512 858e7801d59Ssowmini 859e7801d59Ssowmini typedef struct show_linkprop_state { 860e7801d59Ssowmini char ls_link[MAXLINKNAMELEN]; 861e7801d59Ssowmini char *ls_line; 862e7801d59Ssowmini char **ls_propvals; 863da14cebeSEric Cheng dladm_arg_list_t *ls_proplist; 864e7801d59Ssowmini boolean_t ls_parseable; 865e7801d59Ssowmini boolean_t ls_persist; 866e7801d59Ssowmini boolean_t ls_header; 867e7801d59Ssowmini dladm_status_t ls_status; 868e7801d59Ssowmini dladm_status_t ls_retstatus; 869e7801d59Ssowmini print_state_t ls_print; 870e7801d59Ssowmini } show_linkprop_state_t; 871e7801d59Ssowmini 872da14cebeSEric Cheng typedef struct set_linkprop_state { 873da14cebeSEric Cheng const char *ls_name; 874da14cebeSEric Cheng boolean_t ls_reset; 875da14cebeSEric Cheng boolean_t ls_temp; 876da14cebeSEric Cheng dladm_status_t ls_status; 877da14cebeSEric Cheng } set_linkprop_state_t; 878da14cebeSEric Cheng 879e7801d59Ssowmini typedef struct linkprop_args_s { 880e7801d59Ssowmini show_linkprop_state_t *ls_state; 881e7801d59Ssowmini char *ls_propname; 882e7801d59Ssowmini datalink_id_t ls_linkid; 883e7801d59Ssowmini } linkprop_args_t; 884e7801d59Ssowmini 885e7801d59Ssowmini /* 886e7801d59Ssowmini * structures for 'dladm show-secobj' 887e7801d59Ssowmini */ 888e7801d59Ssowmini typedef struct secobj_fields_buf_s { 889e7801d59Ssowmini char ss_obj_name[DLADM_SECOBJ_VAL_MAX]; 890e7801d59Ssowmini char ss_class[20]; 891e7801d59Ssowmini char ss_val[30]; 892e7801d59Ssowmini } secobj_fields_buf_t; 893e7801d59Ssowmini static print_field_t secobj_fields[] = { 894e7801d59Ssowmini /* name, header, field width, offset, cmdtype */ 895e7801d59Ssowmini { "object", "OBJECT", 20, 896e7801d59Ssowmini offsetof(secobj_fields_buf_t, ss_obj_name), CMD_TYPE_ANY}, 897e7801d59Ssowmini { "class", "CLASS", 20, 898e7801d59Ssowmini offsetof(secobj_fields_buf_t, ss_class), CMD_TYPE_ANY}, 899e7801d59Ssowmini { "value", "VALUE", 30, 900e7801d59Ssowmini offsetof(secobj_fields_buf_t, ss_val), CMD_TYPE_ANY}} 901e7801d59Ssowmini ; 902e7801d59Ssowmini #define DEV_SOBJ_FIELDS (sizeof (secobj_fields) / sizeof (print_field_t)) 9030ba2cbe9Sxc151355 904da14cebeSEric Cheng /* 905da14cebeSEric Cheng * structures for 'dladm show-vnic' 906da14cebeSEric Cheng */ 907da14cebeSEric Cheng typedef struct vnic_fields_buf_s 908da14cebeSEric Cheng { 909da14cebeSEric Cheng char vnic_link[DLPI_LINKNAME_MAX]; 910da14cebeSEric Cheng char vnic_over[DLPI_LINKNAME_MAX]; 911da14cebeSEric Cheng char vnic_speed[6]; 912da14cebeSEric Cheng char vnic_macaddr[19]; 913da14cebeSEric Cheng char vnic_macaddrtype[19]; 914da14cebeSEric Cheng char vnic_vid[6]; 915da14cebeSEric Cheng } vnic_fields_buf_t; 916da14cebeSEric Cheng 917da14cebeSEric Cheng static print_field_t vnic_fields[] = { 918da14cebeSEric Cheng /* name, header, field width, offset, cmdtype */ 919da14cebeSEric Cheng { "link", "LINK", 12, 920da14cebeSEric Cheng offsetof(vnic_fields_buf_t, vnic_link), CMD_TYPE_ANY}, 921da14cebeSEric Cheng { "over", "OVER", 12, 922da14cebeSEric Cheng offsetof(vnic_fields_buf_t, vnic_over), CMD_TYPE_ANY}, 923da14cebeSEric Cheng { "speed", "SPEED", 6, 924da14cebeSEric Cheng offsetof(vnic_fields_buf_t, vnic_speed), CMD_TYPE_ANY}, 925da14cebeSEric Cheng { "macaddr", "MACADDRESS", 20, 926da14cebeSEric Cheng offsetof(vnic_fields_buf_t, vnic_macaddr), CMD_TYPE_ANY}, 927da14cebeSEric Cheng { "macaddrtype", "MACADDRTYPE", 19, 928da14cebeSEric Cheng offsetof(vnic_fields_buf_t, vnic_macaddrtype), CMD_TYPE_ANY}, 929da14cebeSEric Cheng { "vid", "VID", 6, 930da14cebeSEric Cheng offsetof(vnic_fields_buf_t, vnic_vid), CMD_TYPE_ANY}} 931da14cebeSEric Cheng ; 932da14cebeSEric Cheng #define VNIC_MAX_FIELDS (sizeof (vnic_fields) / sizeof (print_field_t)) 933da14cebeSEric Cheng 934da14cebeSEric Cheng /* 935da14cebeSEric Cheng * structures for 'dladm show-usage' 936da14cebeSEric Cheng */ 937da14cebeSEric Cheng 938da14cebeSEric Cheng typedef struct usage_fields_buf_s { 939da14cebeSEric Cheng char usage_link[12]; 940da14cebeSEric Cheng char usage_duration[10]; 941da14cebeSEric Cheng char usage_ipackets[9]; 942da14cebeSEric Cheng char usage_rbytes[10]; 943da14cebeSEric Cheng char usage_opackets[9]; 944da14cebeSEric Cheng char usage_obytes[10]; 945da14cebeSEric Cheng char usage_bandwidth[14]; 946da14cebeSEric Cheng } usage_fields_buf_t; 947da14cebeSEric Cheng 948da14cebeSEric Cheng static print_field_t usage_fields[] = { 949da14cebeSEric Cheng /* name, header, field width, offset, cmdtype */ 950da14cebeSEric Cheng { "link", "LINK", 12, 951da14cebeSEric Cheng offsetof(usage_fields_buf_t, usage_link), CMD_TYPE_ANY}, 952da14cebeSEric Cheng { "duration", "DURATION", 10, 953da14cebeSEric Cheng offsetof(usage_fields_buf_t, usage_duration), CMD_TYPE_ANY}, 954da14cebeSEric Cheng { "ipackets", "IPACKETS", 9, 955da14cebeSEric Cheng offsetof(usage_fields_buf_t, usage_ipackets), CMD_TYPE_ANY}, 956da14cebeSEric Cheng { "rbytes", "RBYTES", 10, 957da14cebeSEric Cheng offsetof(usage_fields_buf_t, usage_rbytes), CMD_TYPE_ANY}, 958da14cebeSEric Cheng { "opackets", "OPACKETS", 9, 959da14cebeSEric Cheng offsetof(usage_fields_buf_t, usage_opackets), CMD_TYPE_ANY}, 960da14cebeSEric Cheng { "obytes", "OBYTES", 10, 961da14cebeSEric Cheng offsetof(usage_fields_buf_t, usage_obytes), CMD_TYPE_ANY}, 962da14cebeSEric Cheng { "bandwidth", "BANDWIDTH", 14, 963da14cebeSEric Cheng offsetof(usage_fields_buf_t, usage_bandwidth), CMD_TYPE_ANY}} 964da14cebeSEric Cheng ; 965da14cebeSEric Cheng 966da14cebeSEric Cheng #define USAGE_MAX_FIELDS (sizeof (usage_fields) / sizeof (print_field_t)) 967da14cebeSEric Cheng 968da14cebeSEric Cheng /* 969da14cebeSEric Cheng * structures for 'dladm show-usage link' 970da14cebeSEric Cheng */ 971da14cebeSEric Cheng 972da14cebeSEric Cheng typedef struct usage_l_fields_buf_s { 973da14cebeSEric Cheng char usage_l_link[12]; 974da14cebeSEric Cheng char usage_l_stime[13]; 975da14cebeSEric Cheng char usage_l_etime[13]; 976da14cebeSEric Cheng char usage_l_rbytes[8]; 977da14cebeSEric Cheng char usage_l_obytes[8]; 978da14cebeSEric Cheng char usage_l_bandwidth[14]; 979da14cebeSEric Cheng } usage_l_fields_buf_t; 980da14cebeSEric Cheng 981da14cebeSEric Cheng static print_field_t usage_l_fields[] = { 982da14cebeSEric Cheng /* name, header, field width, offset, cmdtype */ 983da14cebeSEric Cheng { "link", "LINK", 12, 984da14cebeSEric Cheng offsetof(usage_l_fields_buf_t, usage_l_link), CMD_TYPE_ANY}, 985da14cebeSEric Cheng { "start", "START", 13, 986da14cebeSEric Cheng offsetof(usage_l_fields_buf_t, usage_l_stime), CMD_TYPE_ANY}, 987da14cebeSEric Cheng { "end", "END", 13, 988da14cebeSEric Cheng offsetof(usage_l_fields_buf_t, usage_l_etime), CMD_TYPE_ANY}, 989da14cebeSEric Cheng { "rbytes", "RBYTES", 8, 990da14cebeSEric Cheng offsetof(usage_l_fields_buf_t, usage_l_rbytes), CMD_TYPE_ANY}, 991da14cebeSEric Cheng { "obytes", "OBYTES", 8, 992da14cebeSEric Cheng offsetof(usage_l_fields_buf_t, usage_l_obytes), CMD_TYPE_ANY}, 993da14cebeSEric Cheng { "bandwidth", "BANDWIDTH", 14, 994da14cebeSEric Cheng offsetof(usage_l_fields_buf_t, usage_l_bandwidth), CMD_TYPE_ANY}} 995da14cebeSEric Cheng ; 996da14cebeSEric Cheng 997da14cebeSEric Cheng #define USAGE_L_MAX_FIELDS \ 998da14cebeSEric Cheng (sizeof (usage_l_fields) /sizeof (print_field_t)) 999da14cebeSEric Cheng 10007c478bd9Sstevel@tonic-gate static char *progname; 10010ba2cbe9Sxc151355 static sig_atomic_t signalled; 10027c478bd9Sstevel@tonic-gate 1003*4ac67f02SAnurag S. Maskey /* 1004*4ac67f02SAnurag S. Maskey * Handle to libdladm. Opened in main() before the sub-command 1005*4ac67f02SAnurag S. Maskey * specific function is called. 1006*4ac67f02SAnurag S. Maskey */ 1007*4ac67f02SAnurag S. Maskey static dladm_handle_t handle = NULL; 1008*4ac67f02SAnurag S. Maskey 1009da14cebeSEric Cheng #define DLADM_ETHERSTUB_NAME "etherstub" 1010da14cebeSEric Cheng #define DLADM_IS_ETHERSTUB(id) (id == DATALINK_INVALID_LINKID) 1011da14cebeSEric Cheng 10127c478bd9Sstevel@tonic-gate static void 10137c478bd9Sstevel@tonic-gate usage(void) 10147c478bd9Sstevel@tonic-gate { 10158d5c46e6Sam223141 int i; 10168d5c46e6Sam223141 cmd_t *cmdp; 10178d5c46e6Sam223141 (void) fprintf(stderr, gettext("usage: dladm <subcommand> <args> ..." 10188d5c46e6Sam223141 "\n")); 10198d5c46e6Sam223141 for (i = 0; i < sizeof (cmds) / sizeof (cmds[0]); i++) { 10208d5c46e6Sam223141 cmdp = &cmds[i]; 10218d5c46e6Sam223141 if (cmdp->c_usage != NULL) 10228d5c46e6Sam223141 (void) fprintf(stderr, "%s\n", gettext(cmdp->c_usage)); 10238d5c46e6Sam223141 } 1024*4ac67f02SAnurag S. Maskey 1025*4ac67f02SAnurag S. Maskey /* close dladm handle if it was opened */ 1026*4ac67f02SAnurag S. Maskey if (handle != NULL) 1027*4ac67f02SAnurag S. Maskey dladm_close(handle); 1028*4ac67f02SAnurag S. Maskey 10297c478bd9Sstevel@tonic-gate exit(1); 10307c478bd9Sstevel@tonic-gate } 10317c478bd9Sstevel@tonic-gate 10327c478bd9Sstevel@tonic-gate int 10337c478bd9Sstevel@tonic-gate main(int argc, char *argv[]) 10347c478bd9Sstevel@tonic-gate { 10357c478bd9Sstevel@tonic-gate int i; 10367c478bd9Sstevel@tonic-gate cmd_t *cmdp; 1037*4ac67f02SAnurag S. Maskey dladm_status_t status; 10387c478bd9Sstevel@tonic-gate 10397c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, ""); 10407c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN) 10417c478bd9Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST" 10427c478bd9Sstevel@tonic-gate #endif 10437c478bd9Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN); 10447c478bd9Sstevel@tonic-gate 10457c478bd9Sstevel@tonic-gate progname = argv[0]; 10467c478bd9Sstevel@tonic-gate 10477c478bd9Sstevel@tonic-gate if (argc < 2) 10487c478bd9Sstevel@tonic-gate usage(); 10497c478bd9Sstevel@tonic-gate 10507c478bd9Sstevel@tonic-gate for (i = 0; i < sizeof (cmds) / sizeof (cmds[0]); i++) { 10517c478bd9Sstevel@tonic-gate cmdp = &cmds[i]; 10527c478bd9Sstevel@tonic-gate if (strcmp(argv[1], cmdp->c_name) == 0) { 1053*4ac67f02SAnurag S. Maskey /* Open the libdladm handle */ 1054*4ac67f02SAnurag S. Maskey if ((status = dladm_open(&handle)) != DLADM_STATUS_OK) { 1055*4ac67f02SAnurag S. Maskey die_dlerr(status, 1056*4ac67f02SAnurag S. Maskey "could not open /dev/dld"); 1057*4ac67f02SAnurag S. Maskey } 1058*4ac67f02SAnurag S. Maskey 10598d5c46e6Sam223141 cmdp->c_fn(argc - 1, &argv[1], cmdp->c_usage); 1060*4ac67f02SAnurag S. Maskey 1061*4ac67f02SAnurag S. Maskey dladm_close(handle); 10627c478bd9Sstevel@tonic-gate exit(0); 10637c478bd9Sstevel@tonic-gate } 10647c478bd9Sstevel@tonic-gate } 10657c478bd9Sstevel@tonic-gate 10667c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("%s: unknown subcommand '%s'\n"), 10677c478bd9Sstevel@tonic-gate progname, argv[1]); 10687c478bd9Sstevel@tonic-gate usage(); 10697c478bd9Sstevel@tonic-gate 10707c478bd9Sstevel@tonic-gate return (0); 10717c478bd9Sstevel@tonic-gate } 10727c478bd9Sstevel@tonic-gate 1073da14cebeSEric Cheng /*ARGSUSED*/ 1074da14cebeSEric Cheng static int 1075da14cebeSEric Cheng show_usage_date(dladm_usage_t *usage, void *arg) 1076da14cebeSEric Cheng { 1077da14cebeSEric Cheng 1078da14cebeSEric Cheng time_t stime; 1079da14cebeSEric Cheng char timebuf[20]; 1080da14cebeSEric Cheng 1081da14cebeSEric Cheng stime = usage->du_stime; 1082da14cebeSEric Cheng (void) strftime(timebuf, sizeof (timebuf), "%m/%d/%Y", 1083da14cebeSEric Cheng localtime(&stime)); 1084da14cebeSEric Cheng (void) printf("%s\n", timebuf); 1085da14cebeSEric Cheng 1086da14cebeSEric Cheng return (DLADM_STATUS_OK); 1087da14cebeSEric Cheng } 1088da14cebeSEric Cheng 1089da14cebeSEric Cheng static int 1090da14cebeSEric Cheng show_usage_time(dladm_usage_t *usage, void *arg) 1091da14cebeSEric Cheng { 1092da14cebeSEric Cheng show_usage_state_t *state = (show_usage_state_t *)arg; 1093da14cebeSEric Cheng char buf[DLADM_STRSIZE]; 1094da14cebeSEric Cheng usage_l_fields_buf_t ubuf; 1095da14cebeSEric Cheng time_t time; 1096da14cebeSEric Cheng double bw; 1097da14cebeSEric Cheng 1098da14cebeSEric Cheng if (state->us_plot) { 1099da14cebeSEric Cheng if (!state->us_printheader) { 1100da14cebeSEric Cheng if (state->us_first) { 1101da14cebeSEric Cheng (void) printf("# Time"); 1102da14cebeSEric Cheng state->us_first = B_FALSE; 1103da14cebeSEric Cheng } 1104da14cebeSEric Cheng (void) printf(" %s", usage->du_name); 1105da14cebeSEric Cheng if (usage->du_last) { 1106da14cebeSEric Cheng (void) printf("\n"); 1107da14cebeSEric Cheng state->us_first = B_TRUE; 1108da14cebeSEric Cheng state->us_printheader = B_TRUE; 1109da14cebeSEric Cheng } 1110da14cebeSEric Cheng } else { 1111da14cebeSEric Cheng if (state->us_first) { 1112da14cebeSEric Cheng time = usage->du_etime; 1113da14cebeSEric Cheng (void) strftime(buf, sizeof (buf), "%T", 1114da14cebeSEric Cheng localtime(&time)); 1115da14cebeSEric Cheng state->us_first = B_FALSE; 1116da14cebeSEric Cheng (void) printf("%s", buf); 1117da14cebeSEric Cheng } 1118da14cebeSEric Cheng bw = (double)usage->du_bandwidth/1000; 1119da14cebeSEric Cheng (void) printf(" %.2f", bw); 1120da14cebeSEric Cheng if (usage->du_last) { 1121da14cebeSEric Cheng (void) printf("\n"); 1122da14cebeSEric Cheng state->us_first = B_TRUE; 1123da14cebeSEric Cheng } 1124da14cebeSEric Cheng } 1125da14cebeSEric Cheng return (DLADM_STATUS_OK); 1126da14cebeSEric Cheng } 1127da14cebeSEric Cheng 1128da14cebeSEric Cheng bzero(&ubuf, sizeof (ubuf)); 1129da14cebeSEric Cheng 1130da14cebeSEric Cheng (void) snprintf(ubuf.usage_l_link, sizeof (ubuf.usage_l_link), "%s", 1131da14cebeSEric Cheng usage->du_name); 1132da14cebeSEric Cheng time = usage->du_stime; 1133da14cebeSEric Cheng (void) strftime(buf, sizeof (buf), "%T", localtime(&time)); 1134da14cebeSEric Cheng (void) snprintf(ubuf.usage_l_stime, sizeof (ubuf.usage_l_stime), "%s", 1135da14cebeSEric Cheng buf); 1136da14cebeSEric Cheng time = usage->du_etime; 1137da14cebeSEric Cheng (void) strftime(buf, sizeof (buf), "%T", localtime(&time)); 1138da14cebeSEric Cheng (void) snprintf(ubuf.usage_l_etime, sizeof (ubuf.usage_l_etime), "%s", 1139da14cebeSEric Cheng buf); 1140da14cebeSEric Cheng (void) snprintf(ubuf.usage_l_rbytes, sizeof (ubuf.usage_l_rbytes), 1141da14cebeSEric Cheng "%llu", usage->du_rbytes); 1142da14cebeSEric Cheng (void) snprintf(ubuf.usage_l_obytes, sizeof (ubuf.usage_l_obytes), 1143da14cebeSEric Cheng "%llu", usage->du_obytes); 1144da14cebeSEric Cheng (void) snprintf(ubuf.usage_l_bandwidth, sizeof (ubuf.usage_l_bandwidth), 1145da14cebeSEric Cheng "%s Mbps", dladm_bw2str(usage->du_bandwidth, buf)); 1146da14cebeSEric Cheng 1147da14cebeSEric Cheng if (!state->us_parseable && !state->us_printheader) { 1148da14cebeSEric Cheng print_header(&state->us_print); 1149da14cebeSEric Cheng state->us_printheader = B_TRUE; 1150da14cebeSEric Cheng } 1151da14cebeSEric Cheng 1152da14cebeSEric Cheng dladm_print_output(&state->us_print, state->us_parseable, 1153da14cebeSEric Cheng dladm_print_field, (void *)&ubuf); 1154da14cebeSEric Cheng 1155da14cebeSEric Cheng return (DLADM_STATUS_OK); 1156da14cebeSEric Cheng } 1157da14cebeSEric Cheng 1158da14cebeSEric Cheng static int 1159da14cebeSEric Cheng show_usage_res(dladm_usage_t *usage, void *arg) 1160da14cebeSEric Cheng { 1161da14cebeSEric Cheng show_usage_state_t *state = (show_usage_state_t *)arg; 1162da14cebeSEric Cheng char buf[DLADM_STRSIZE]; 1163da14cebeSEric Cheng usage_fields_buf_t ubuf; 1164da14cebeSEric Cheng 1165da14cebeSEric Cheng bzero(&ubuf, sizeof (ubuf)); 1166da14cebeSEric Cheng 1167da14cebeSEric Cheng (void) snprintf(ubuf.usage_link, sizeof (ubuf.usage_link), "%s", 1168da14cebeSEric Cheng usage->du_name); 1169da14cebeSEric Cheng (void) snprintf(ubuf.usage_duration, sizeof (ubuf.usage_duration), 1170da14cebeSEric Cheng "%llu", usage->du_duration); 1171da14cebeSEric Cheng (void) snprintf(ubuf.usage_ipackets, sizeof (ubuf.usage_ipackets), 1172da14cebeSEric Cheng "%llu", usage->du_ipackets); 1173da14cebeSEric Cheng (void) snprintf(ubuf.usage_rbytes, sizeof (ubuf.usage_rbytes), 1174da14cebeSEric Cheng "%llu", usage->du_rbytes); 1175da14cebeSEric Cheng (void) snprintf(ubuf.usage_opackets, sizeof (ubuf.usage_opackets), 1176da14cebeSEric Cheng "%llu", usage->du_opackets); 1177da14cebeSEric Cheng (void) snprintf(ubuf.usage_obytes, sizeof (ubuf.usage_obytes), 1178da14cebeSEric Cheng "%llu", usage->du_obytes); 1179da14cebeSEric Cheng (void) snprintf(ubuf.usage_bandwidth, sizeof (ubuf.usage_bandwidth), 1180da14cebeSEric Cheng "%s Mbps", dladm_bw2str(usage->du_bandwidth, buf)); 1181da14cebeSEric Cheng 1182da14cebeSEric Cheng if (!state->us_parseable && !state->us_printheader) { 1183da14cebeSEric Cheng print_header(&state->us_print); 1184da14cebeSEric Cheng state->us_printheader = B_TRUE; 1185da14cebeSEric Cheng } 1186da14cebeSEric Cheng 1187da14cebeSEric Cheng dladm_print_output(&state->us_print, state->us_parseable, 1188da14cebeSEric Cheng dladm_print_field, (void *)&ubuf); 1189da14cebeSEric Cheng 1190da14cebeSEric Cheng return (DLADM_STATUS_OK); 1191da14cebeSEric Cheng } 1192da14cebeSEric Cheng 1193da14cebeSEric Cheng static boolean_t 1194da14cebeSEric Cheng valid_formatspec(char *formatspec_str) 1195da14cebeSEric Cheng { 1196da14cebeSEric Cheng if (strcmp(formatspec_str, "gnuplot") == 0) 1197da14cebeSEric Cheng return (B_TRUE); 1198da14cebeSEric Cheng return (B_FALSE); 1199da14cebeSEric Cheng 1200da14cebeSEric Cheng } 1201da14cebeSEric Cheng 1202da14cebeSEric Cheng /*ARGSUSED*/ 1203da14cebeSEric Cheng static void 1204da14cebeSEric Cheng do_show_usage(int argc, char *argv[], const char *use) 1205da14cebeSEric Cheng { 1206da14cebeSEric Cheng char *file = NULL; 1207da14cebeSEric Cheng int opt; 1208da14cebeSEric Cheng dladm_status_t status; 1209da14cebeSEric Cheng boolean_t d_arg = B_FALSE; 1210da14cebeSEric Cheng boolean_t p_arg = B_FALSE; 1211da14cebeSEric Cheng char *stime = NULL; 1212da14cebeSEric Cheng char *etime = NULL; 1213da14cebeSEric Cheng char *resource = NULL; 1214da14cebeSEric Cheng show_usage_state_t state; 1215da14cebeSEric Cheng boolean_t o_arg = B_FALSE; 1216da14cebeSEric Cheng boolean_t F_arg = B_FALSE; 1217da14cebeSEric Cheng char *fields_str = NULL; 1218da14cebeSEric Cheng char *formatspec_str = NULL; 1219da14cebeSEric Cheng print_field_t **fields; 1220da14cebeSEric Cheng uint_t nfields; 1221da14cebeSEric Cheng char *all_fields = 1222da14cebeSEric Cheng "link,duration,ipackets,rbytes,opackets,obytes,bandwidth"; 1223da14cebeSEric Cheng char *all_l_fields = 1224da14cebeSEric Cheng "link,start,end,rbytes,obytes,bandwidth"; 1225da14cebeSEric Cheng 1226da14cebeSEric Cheng bzero(&state, sizeof (show_usage_state_t)); 1227da14cebeSEric Cheng state.us_parseable = B_FALSE; 1228da14cebeSEric Cheng state.us_printheader = B_FALSE; 1229da14cebeSEric Cheng state.us_plot = B_FALSE; 1230da14cebeSEric Cheng state.us_first = B_TRUE; 1231da14cebeSEric Cheng 1232da14cebeSEric Cheng while ((opt = getopt(argc, argv, "dps:e:o:f:F:")) != -1) { 1233da14cebeSEric Cheng switch (opt) { 1234da14cebeSEric Cheng case 'd': 1235da14cebeSEric Cheng d_arg = B_TRUE; 1236da14cebeSEric Cheng break; 1237da14cebeSEric Cheng case 'p': 1238da14cebeSEric Cheng state.us_plot = p_arg = B_TRUE; 1239da14cebeSEric Cheng break; 1240da14cebeSEric Cheng case 'f': 1241da14cebeSEric Cheng file = optarg; 1242da14cebeSEric Cheng break; 1243da14cebeSEric Cheng case 's': 1244da14cebeSEric Cheng stime = optarg; 1245da14cebeSEric Cheng break; 1246da14cebeSEric Cheng case 'e': 1247da14cebeSEric Cheng etime = optarg; 1248da14cebeSEric Cheng break; 1249da14cebeSEric Cheng case 'o': 1250da14cebeSEric Cheng o_arg = B_TRUE; 1251da14cebeSEric Cheng fields_str = optarg; 1252da14cebeSEric Cheng break; 1253da14cebeSEric Cheng case 'F': 1254da14cebeSEric Cheng F_arg = B_TRUE; 1255da14cebeSEric Cheng formatspec_str = optarg; 1256da14cebeSEric Cheng break; 1257da14cebeSEric Cheng default: 1258da14cebeSEric Cheng die_opterr(optopt, opt, use); 1259da14cebeSEric Cheng break; 1260da14cebeSEric Cheng } 1261da14cebeSEric Cheng } 1262da14cebeSEric Cheng 1263da14cebeSEric Cheng if (file == NULL) 1264da14cebeSEric Cheng die("show-usage requires a file"); 1265da14cebeSEric Cheng 1266da14cebeSEric Cheng if (optind == (argc-1)) { 1267da14cebeSEric Cheng resource = argv[optind]; 1268da14cebeSEric Cheng } 1269da14cebeSEric Cheng 1270da14cebeSEric Cheng if (resource == NULL && stime == NULL && etime == NULL) { 1271da14cebeSEric Cheng if (!o_arg || (o_arg && strcasecmp(fields_str, "all") == 0)) 1272da14cebeSEric Cheng fields_str = all_fields; 1273da14cebeSEric Cheng fields = parse_output_fields(fields_str, usage_fields, 1274da14cebeSEric Cheng USAGE_MAX_FIELDS, CMD_TYPE_ANY, &nfields); 1275da14cebeSEric Cheng } else { 1276da14cebeSEric Cheng if (!o_arg || (o_arg && strcasecmp(fields_str, "all") == 0)) 1277da14cebeSEric Cheng fields_str = all_l_fields; 1278da14cebeSEric Cheng fields = parse_output_fields(fields_str, usage_l_fields, 1279da14cebeSEric Cheng USAGE_L_MAX_FIELDS, CMD_TYPE_ANY, &nfields); 1280da14cebeSEric Cheng } 1281da14cebeSEric Cheng 1282da14cebeSEric Cheng if (fields == NULL) { 1283da14cebeSEric Cheng die("invalid fields(s) specified"); 1284da14cebeSEric Cheng return; 1285da14cebeSEric Cheng } 1286da14cebeSEric Cheng state.us_print.ps_fields = fields; 1287da14cebeSEric Cheng state.us_print.ps_nfields = nfields; 1288da14cebeSEric Cheng 1289da14cebeSEric Cheng if (p_arg && d_arg) 1290da14cebeSEric Cheng die("plot and date options are incompatible"); 1291da14cebeSEric Cheng 1292da14cebeSEric Cheng if (p_arg && !F_arg) 1293da14cebeSEric Cheng die("specify format speicifier: -F <format>"); 1294da14cebeSEric Cheng 1295da14cebeSEric Cheng if (F_arg && valid_formatspec(formatspec_str) == B_FALSE) 1296da14cebeSEric Cheng die("Format specifier %s not supported", formatspec_str); 1297da14cebeSEric Cheng 1298da14cebeSEric Cheng if (d_arg) { 1299da14cebeSEric Cheng /* Print log dates */ 1300da14cebeSEric Cheng status = dladm_usage_dates(show_usage_date, 1301da14cebeSEric Cheng DLADM_LOGTYPE_LINK, file, resource, &state); 1302da14cebeSEric Cheng } else if (resource == NULL && stime == NULL && etime == NULL && 1303da14cebeSEric Cheng !p_arg) { 1304da14cebeSEric Cheng /* Print summary */ 1305da14cebeSEric Cheng status = dladm_usage_summary(show_usage_res, 1306da14cebeSEric Cheng DLADM_LOGTYPE_LINK, file, &state); 1307da14cebeSEric Cheng } else if (resource != NULL) { 1308da14cebeSEric Cheng /* Print log entries for named resource */ 1309da14cebeSEric Cheng status = dladm_walk_usage_res(show_usage_time, 1310da14cebeSEric Cheng DLADM_LOGTYPE_LINK, file, resource, stime, etime, &state); 1311da14cebeSEric Cheng } else { 1312da14cebeSEric Cheng /* Print time and information for each link */ 1313da14cebeSEric Cheng status = dladm_walk_usage_time(show_usage_time, 1314da14cebeSEric Cheng DLADM_LOGTYPE_LINK, file, stime, etime, &state); 1315da14cebeSEric Cheng } 1316da14cebeSEric Cheng 1317da14cebeSEric Cheng if (status != DLADM_STATUS_OK) 1318da14cebeSEric Cheng die_dlerr(status, "show-usage"); 1319da14cebeSEric Cheng } 1320da14cebeSEric Cheng 13217c478bd9Sstevel@tonic-gate static void 13228d5c46e6Sam223141 do_create_aggr(int argc, char *argv[], const char *use) 13237c478bd9Sstevel@tonic-gate { 13247c478bd9Sstevel@tonic-gate char option; 1325d62bc4baSyz147064 int key = 0; 13267c478bd9Sstevel@tonic-gate uint32_t policy = AGGR_POLICY_L4; 13277c478bd9Sstevel@tonic-gate aggr_lacp_mode_t lacp_mode = AGGR_LACP_OFF; 13287c478bd9Sstevel@tonic-gate aggr_lacp_timer_t lacp_timer = AGGR_LACP_TIMER_SHORT; 1329f595a68aSyz147064 dladm_aggr_port_attr_db_t port[MAXPORT]; 1330d62bc4baSyz147064 uint_t n, ndev, nlink; 13317c478bd9Sstevel@tonic-gate uint8_t mac_addr[ETHERADDRL]; 13327c478bd9Sstevel@tonic-gate boolean_t mac_addr_fixed = B_FALSE; 13337c478bd9Sstevel@tonic-gate boolean_t P_arg = B_FALSE; 13347c478bd9Sstevel@tonic-gate boolean_t l_arg = B_FALSE; 13357c478bd9Sstevel@tonic-gate boolean_t u_arg = B_FALSE; 13367c478bd9Sstevel@tonic-gate boolean_t T_arg = B_FALSE; 1337d62bc4baSyz147064 uint32_t flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST; 13387c478bd9Sstevel@tonic-gate char *altroot = NULL; 1339d62bc4baSyz147064 char name[MAXLINKNAMELEN]; 1340d62bc4baSyz147064 char *devs[MAXPORT]; 1341d62bc4baSyz147064 char *links[MAXPORT]; 1342f595a68aSyz147064 dladm_status_t status; 1343da14cebeSEric Cheng dladm_status_t pstatus; 1344da14cebeSEric Cheng dladm_arg_list_t *proplist = NULL; 1345da14cebeSEric Cheng int i; 1346da14cebeSEric Cheng datalink_id_t linkid; 13477c478bd9Sstevel@tonic-gate 1348d62bc4baSyz147064 ndev = nlink = opterr = 0; 1349da14cebeSEric Cheng while ((option = getopt_long(argc, argv, ":d:l:L:P:R:tfu:T:p:", 1350d62bc4baSyz147064 lopts, NULL)) != -1) { 13517c478bd9Sstevel@tonic-gate switch (option) { 13527c478bd9Sstevel@tonic-gate case 'd': 1353d62bc4baSyz147064 if (ndev + nlink >= MAXPORT) 1354d62bc4baSyz147064 die("too many ports specified"); 13557c478bd9Sstevel@tonic-gate 1356d62bc4baSyz147064 devs[ndev++] = optarg; 13577c478bd9Sstevel@tonic-gate break; 13587c478bd9Sstevel@tonic-gate case 'P': 135933343a97Smeem if (P_arg) 136033343a97Smeem die_optdup(option); 13617c478bd9Sstevel@tonic-gate 13627c478bd9Sstevel@tonic-gate P_arg = B_TRUE; 1363f595a68aSyz147064 if (!dladm_aggr_str2policy(optarg, &policy)) 136433343a97Smeem die("invalid policy '%s'", optarg); 13657c478bd9Sstevel@tonic-gate break; 13667c478bd9Sstevel@tonic-gate case 'u': 136733343a97Smeem if (u_arg) 136833343a97Smeem die_optdup(option); 13697c478bd9Sstevel@tonic-gate 13707c478bd9Sstevel@tonic-gate u_arg = B_TRUE; 1371f595a68aSyz147064 if (!dladm_aggr_str2macaddr(optarg, &mac_addr_fixed, 137233343a97Smeem mac_addr)) 137333343a97Smeem die("invalid MAC address '%s'", optarg); 13747c478bd9Sstevel@tonic-gate break; 13757c478bd9Sstevel@tonic-gate case 'l': 1376d62bc4baSyz147064 if (isdigit(optarg[strlen(optarg) - 1])) { 1377d62bc4baSyz147064 1378d62bc4baSyz147064 /* 1379d62bc4baSyz147064 * Ended with digit, possibly a link name. 1380d62bc4baSyz147064 */ 1381d62bc4baSyz147064 if (ndev + nlink >= MAXPORT) 1382d62bc4baSyz147064 die("too many ports specified"); 1383d62bc4baSyz147064 1384d62bc4baSyz147064 links[nlink++] = optarg; 1385d62bc4baSyz147064 break; 1386d62bc4baSyz147064 } 1387d62bc4baSyz147064 /* FALLTHROUGH */ 1388d62bc4baSyz147064 case 'L': 138933343a97Smeem if (l_arg) 139033343a97Smeem die_optdup(option); 13917c478bd9Sstevel@tonic-gate 13927c478bd9Sstevel@tonic-gate l_arg = B_TRUE; 1393f595a68aSyz147064 if (!dladm_aggr_str2lacpmode(optarg, &lacp_mode)) 139433343a97Smeem die("invalid LACP mode '%s'", optarg); 13957c478bd9Sstevel@tonic-gate break; 13967c478bd9Sstevel@tonic-gate case 'T': 139733343a97Smeem if (T_arg) 139833343a97Smeem die_optdup(option); 13997c478bd9Sstevel@tonic-gate 14007c478bd9Sstevel@tonic-gate T_arg = B_TRUE; 1401f595a68aSyz147064 if (!dladm_aggr_str2lacptimer(optarg, &lacp_timer)) 140233343a97Smeem die("invalid LACP timer value '%s'", optarg); 14037c478bd9Sstevel@tonic-gate break; 14047c478bd9Sstevel@tonic-gate case 't': 1405d62bc4baSyz147064 flags &= ~DLADM_OPT_PERSIST; 1406d62bc4baSyz147064 break; 1407d62bc4baSyz147064 case 'f': 1408d62bc4baSyz147064 flags |= DLADM_OPT_FORCE; 14097c478bd9Sstevel@tonic-gate break; 14107c478bd9Sstevel@tonic-gate case 'R': 14117c478bd9Sstevel@tonic-gate altroot = optarg; 14127c478bd9Sstevel@tonic-gate break; 1413da14cebeSEric Cheng case 'p': 1414da14cebeSEric Cheng if (dladm_parse_link_props(optarg, &proplist, B_FALSE) 1415da14cebeSEric Cheng != DLADM_STATUS_OK) 1416da14cebeSEric Cheng die("invalid aggregation property"); 1417da14cebeSEric Cheng break; 14187c478bd9Sstevel@tonic-gate default: 14198d5c46e6Sam223141 die_opterr(optopt, option, use); 142033343a97Smeem break; 14217c478bd9Sstevel@tonic-gate } 14227c478bd9Sstevel@tonic-gate } 14237c478bd9Sstevel@tonic-gate 1424d62bc4baSyz147064 if (ndev + nlink == 0) 14257c478bd9Sstevel@tonic-gate usage(); 14267c478bd9Sstevel@tonic-gate 1427d62bc4baSyz147064 /* get key value or the aggregation name (required last argument) */ 14287c478bd9Sstevel@tonic-gate if (optind != (argc-1)) 14297c478bd9Sstevel@tonic-gate usage(); 14307c478bd9Sstevel@tonic-gate 1431d62bc4baSyz147064 if (!str2int(argv[optind], &key)) { 1432d62bc4baSyz147064 if (strlcpy(name, argv[optind], MAXLINKNAMELEN) >= 1433d62bc4baSyz147064 MAXLINKNAMELEN) { 1434d62bc4baSyz147064 die("link name too long '%s'", argv[optind]); 1435d62bc4baSyz147064 } 14367c478bd9Sstevel@tonic-gate 1437d62bc4baSyz147064 if (!dladm_valid_linkname(name)) 1438d62bc4baSyz147064 die("invalid link name '%s'", argv[optind]); 1439d62bc4baSyz147064 } else { 1440d62bc4baSyz147064 (void) snprintf(name, MAXLINKNAMELEN, "aggr%d", key); 1441d62bc4baSyz147064 } 1442d62bc4baSyz147064 1443d62bc4baSyz147064 if (altroot != NULL) 1444d62bc4baSyz147064 altroot_cmd(altroot, argc, argv); 1445d62bc4baSyz147064 1446d62bc4baSyz147064 for (n = 0; n < ndev; n++) { 1447*4ac67f02SAnurag S. Maskey if ((status = dladm_dev2linkid(handle, devs[n], 1448*4ac67f02SAnurag S. Maskey &port[n].lp_linkid)) != DLADM_STATUS_OK) { 1449*4ac67f02SAnurag S. Maskey die_dlerr(status, "invalid dev name '%s'", devs[n]); 1450d62bc4baSyz147064 } 1451d62bc4baSyz147064 } 1452d62bc4baSyz147064 1453d62bc4baSyz147064 for (n = 0; n < nlink; n++) { 1454*4ac67f02SAnurag S. Maskey if ((status = dladm_name2info(handle, links[n], 1455*4ac67f02SAnurag S. Maskey &port[ndev + n].lp_linkid, NULL, NULL, NULL)) != 1456*4ac67f02SAnurag S. Maskey DLADM_STATUS_OK) { 1457*4ac67f02SAnurag S. Maskey die_dlerr(status, "invalid link name '%s'", links[n]); 1458d62bc4baSyz147064 } 1459d62bc4baSyz147064 } 1460d62bc4baSyz147064 1461*4ac67f02SAnurag S. Maskey status = dladm_aggr_create(handle, name, key, ndev + nlink, port, 1462*4ac67f02SAnurag S. Maskey policy, mac_addr_fixed, (const uchar_t *)mac_addr, lacp_mode, 1463d62bc4baSyz147064 lacp_timer, flags); 1464da14cebeSEric Cheng if (status != DLADM_STATUS_OK) 1465da14cebeSEric Cheng goto done; 1466da14cebeSEric Cheng 1467da14cebeSEric Cheng if (proplist == NULL) 1468da14cebeSEric Cheng return; 1469da14cebeSEric Cheng 1470*4ac67f02SAnurag S. Maskey status = dladm_name2info(handle, name, &linkid, NULL, NULL, NULL); 1471da14cebeSEric Cheng if (status != DLADM_STATUS_OK) 1472da14cebeSEric Cheng goto done; 1473da14cebeSEric Cheng 1474da14cebeSEric Cheng for (i = 0; i < proplist->al_count; i++) { 1475da14cebeSEric Cheng dladm_arg_info_t *aip = &proplist->al_info[i]; 1476da14cebeSEric Cheng 1477*4ac67f02SAnurag S. Maskey pstatus = dladm_set_linkprop(handle, linkid, aip->ai_name, 1478da14cebeSEric Cheng aip->ai_val, aip->ai_count, flags); 1479da14cebeSEric Cheng 1480da14cebeSEric Cheng if (pstatus != DLADM_STATUS_OK) { 1481da14cebeSEric Cheng die_dlerr(pstatus, 1482da14cebeSEric Cheng "aggr creation succeeded but " 1483da14cebeSEric Cheng "could not set property '%s'", aip->ai_name); 1484da14cebeSEric Cheng } 1485da14cebeSEric Cheng } 1486d62bc4baSyz147064 done: 1487da14cebeSEric Cheng dladm_free_props(proplist); 1488d62bc4baSyz147064 if (status != DLADM_STATUS_OK) { 1489d62bc4baSyz147064 if (status == DLADM_STATUS_NONOTIF) { 1490d62bc4baSyz147064 die_dlerr(status, "not all links have link up/down " 1491d62bc4baSyz147064 "detection; must use -f (see dladm(1M))\n"); 1492d62bc4baSyz147064 } else { 1493f595a68aSyz147064 die_dlerr(status, "create operation failed"); 14947c478bd9Sstevel@tonic-gate } 1495d62bc4baSyz147064 } 1496d62bc4baSyz147064 } 1497d62bc4baSyz147064 1498d62bc4baSyz147064 /* 1499d62bc4baSyz147064 * arg is either the key or the aggr name. Validate it and convert it to 1500d62bc4baSyz147064 * the linkid if altroot is NULL. 1501d62bc4baSyz147064 */ 1502d62bc4baSyz147064 static dladm_status_t 1503d62bc4baSyz147064 i_dladm_aggr_get_linkid(const char *altroot, const char *arg, 1504d62bc4baSyz147064 datalink_id_t *linkidp, uint32_t flags) 1505d62bc4baSyz147064 { 1506d62bc4baSyz147064 int key = 0; 1507d62bc4baSyz147064 char *aggr = NULL; 1508d62bc4baSyz147064 dladm_status_t status; 1509d62bc4baSyz147064 1510d62bc4baSyz147064 if (!str2int(arg, &key)) 1511d62bc4baSyz147064 aggr = (char *)arg; 1512d62bc4baSyz147064 1513d62bc4baSyz147064 if (aggr == NULL && key == 0) 1514d62bc4baSyz147064 return (DLADM_STATUS_LINKINVAL); 1515d62bc4baSyz147064 1516d62bc4baSyz147064 if (altroot != NULL) 1517d62bc4baSyz147064 return (DLADM_STATUS_OK); 1518d62bc4baSyz147064 1519d62bc4baSyz147064 if (aggr != NULL) { 1520*4ac67f02SAnurag S. Maskey status = dladm_name2info(handle, aggr, linkidp, NULL, NULL, 1521*4ac67f02SAnurag S. Maskey NULL); 1522d62bc4baSyz147064 } else { 1523*4ac67f02SAnurag S. Maskey status = dladm_key2linkid(handle, key, linkidp, flags); 1524d62bc4baSyz147064 } 1525d62bc4baSyz147064 1526d62bc4baSyz147064 return (status); 1527d62bc4baSyz147064 } 15287c478bd9Sstevel@tonic-gate 15297c478bd9Sstevel@tonic-gate static void 15308d5c46e6Sam223141 do_delete_aggr(int argc, char *argv[], const char *use) 15317c478bd9Sstevel@tonic-gate { 15327c478bd9Sstevel@tonic-gate char option; 15337c478bd9Sstevel@tonic-gate char *altroot = NULL; 1534d62bc4baSyz147064 uint32_t flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST; 1535f595a68aSyz147064 dladm_status_t status; 1536d62bc4baSyz147064 datalink_id_t linkid; 15377c478bd9Sstevel@tonic-gate 15387c478bd9Sstevel@tonic-gate opterr = 0; 1539d62bc4baSyz147064 while ((option = getopt_long(argc, argv, ":R:t", lopts, NULL)) != -1) { 15407c478bd9Sstevel@tonic-gate switch (option) { 15417c478bd9Sstevel@tonic-gate case 't': 1542d62bc4baSyz147064 flags &= ~DLADM_OPT_PERSIST; 15437c478bd9Sstevel@tonic-gate break; 15447c478bd9Sstevel@tonic-gate case 'R': 15457c478bd9Sstevel@tonic-gate altroot = optarg; 15467c478bd9Sstevel@tonic-gate break; 15477c478bd9Sstevel@tonic-gate default: 15488d5c46e6Sam223141 die_opterr(optopt, option, use); 15497c478bd9Sstevel@tonic-gate break; 15507c478bd9Sstevel@tonic-gate } 15517c478bd9Sstevel@tonic-gate } 15527c478bd9Sstevel@tonic-gate 1553d62bc4baSyz147064 /* get key value or the aggregation name (required last argument) */ 15547c478bd9Sstevel@tonic-gate if (optind != (argc-1)) 15557c478bd9Sstevel@tonic-gate usage(); 15567c478bd9Sstevel@tonic-gate 1557d62bc4baSyz147064 status = i_dladm_aggr_get_linkid(altroot, argv[optind], &linkid, flags); 1558d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 1559d62bc4baSyz147064 goto done; 15607c478bd9Sstevel@tonic-gate 1561d62bc4baSyz147064 if (altroot != NULL) 1562d62bc4baSyz147064 altroot_cmd(altroot, argc, argv); 1563d62bc4baSyz147064 1564*4ac67f02SAnurag S. Maskey status = dladm_aggr_delete(handle, linkid, flags); 1565d62bc4baSyz147064 done: 1566f595a68aSyz147064 if (status != DLADM_STATUS_OK) 1567f595a68aSyz147064 die_dlerr(status, "delete operation failed"); 15687c478bd9Sstevel@tonic-gate } 15697c478bd9Sstevel@tonic-gate 15707c478bd9Sstevel@tonic-gate static void 15718d5c46e6Sam223141 do_add_aggr(int argc, char *argv[], const char *use) 15727c478bd9Sstevel@tonic-gate { 15737c478bd9Sstevel@tonic-gate char option; 1574d62bc4baSyz147064 uint_t n, ndev, nlink; 15757c478bd9Sstevel@tonic-gate char *altroot = NULL; 1576d62bc4baSyz147064 uint32_t flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST; 1577d62bc4baSyz147064 datalink_id_t linkid; 1578f595a68aSyz147064 dladm_status_t status; 1579d62bc4baSyz147064 dladm_aggr_port_attr_db_t port[MAXPORT]; 1580d62bc4baSyz147064 char *devs[MAXPORT]; 1581d62bc4baSyz147064 char *links[MAXPORT]; 15827c478bd9Sstevel@tonic-gate 1583d62bc4baSyz147064 ndev = nlink = opterr = 0; 1584d62bc4baSyz147064 while ((option = getopt_long(argc, argv, ":d:l:R:tf", lopts, 15857c478bd9Sstevel@tonic-gate NULL)) != -1) { 15867c478bd9Sstevel@tonic-gate switch (option) { 15877c478bd9Sstevel@tonic-gate case 'd': 1588d62bc4baSyz147064 if (ndev + nlink >= MAXPORT) 1589d62bc4baSyz147064 die("too many ports specified"); 15907c478bd9Sstevel@tonic-gate 1591d62bc4baSyz147064 devs[ndev++] = optarg; 1592d62bc4baSyz147064 break; 1593d62bc4baSyz147064 case 'l': 1594d62bc4baSyz147064 if (ndev + nlink >= MAXPORT) 1595d62bc4baSyz147064 die("too many ports specified"); 159633343a97Smeem 1597d62bc4baSyz147064 links[nlink++] = optarg; 15987c478bd9Sstevel@tonic-gate break; 15997c478bd9Sstevel@tonic-gate case 't': 1600d62bc4baSyz147064 flags &= ~DLADM_OPT_PERSIST; 1601d62bc4baSyz147064 break; 1602d62bc4baSyz147064 case 'f': 1603d62bc4baSyz147064 flags |= DLADM_OPT_FORCE; 16047c478bd9Sstevel@tonic-gate break; 16057c478bd9Sstevel@tonic-gate case 'R': 16067c478bd9Sstevel@tonic-gate altroot = optarg; 16077c478bd9Sstevel@tonic-gate break; 16087c478bd9Sstevel@tonic-gate default: 16098d5c46e6Sam223141 die_opterr(optopt, option, use); 161033343a97Smeem break; 16117c478bd9Sstevel@tonic-gate } 16127c478bd9Sstevel@tonic-gate } 16137c478bd9Sstevel@tonic-gate 1614d62bc4baSyz147064 if (ndev + nlink == 0) 16157c478bd9Sstevel@tonic-gate usage(); 16167c478bd9Sstevel@tonic-gate 1617d62bc4baSyz147064 /* get key value or the aggregation name (required last argument) */ 16187c478bd9Sstevel@tonic-gate if (optind != (argc-1)) 16197c478bd9Sstevel@tonic-gate usage(); 16207c478bd9Sstevel@tonic-gate 1621d62bc4baSyz147064 if ((status = i_dladm_aggr_get_linkid(altroot, argv[optind], &linkid, 1622d62bc4baSyz147064 flags & (DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST))) != 1623d62bc4baSyz147064 DLADM_STATUS_OK) { 1624d62bc4baSyz147064 goto done; 1625d62bc4baSyz147064 } 16267c478bd9Sstevel@tonic-gate 1627d62bc4baSyz147064 if (altroot != NULL) 1628d62bc4baSyz147064 altroot_cmd(altroot, argc, argv); 1629d62bc4baSyz147064 1630d62bc4baSyz147064 for (n = 0; n < ndev; n++) { 1631*4ac67f02SAnurag S. Maskey if ((status = dladm_dev2linkid(handle, devs[n], 1632*4ac67f02SAnurag S. Maskey &(port[n].lp_linkid))) != DLADM_STATUS_OK) { 1633*4ac67f02SAnurag S. Maskey die_dlerr(status, "invalid <dev> '%s'", devs[n]); 1634d62bc4baSyz147064 } 1635d62bc4baSyz147064 } 1636d62bc4baSyz147064 1637d62bc4baSyz147064 for (n = 0; n < nlink; n++) { 1638*4ac67f02SAnurag S. Maskey if ((status = dladm_name2info(handle, links[n], 1639*4ac67f02SAnurag S. Maskey &port[n + ndev].lp_linkid, NULL, NULL, NULL)) != 1640*4ac67f02SAnurag S. Maskey DLADM_STATUS_OK) { 1641*4ac67f02SAnurag S. Maskey die_dlerr(status, "invalid <link> '%s'", links[n]); 1642d62bc4baSyz147064 } 1643d62bc4baSyz147064 } 1644d62bc4baSyz147064 1645*4ac67f02SAnurag S. Maskey status = dladm_aggr_add(handle, linkid, ndev + nlink, port, flags); 1646d62bc4baSyz147064 done: 1647f595a68aSyz147064 if (status != DLADM_STATUS_OK) { 1648219a2a31Shl157128 /* 1649f595a68aSyz147064 * checking DLADM_STATUS_NOTSUP is a temporary workaround 1650219a2a31Shl157128 * and should be removed once 6399681 is fixed. 1651219a2a31Shl157128 */ 1652f595a68aSyz147064 if (status == DLADM_STATUS_NOTSUP) { 1653219a2a31Shl157128 (void) fprintf(stderr, 1654219a2a31Shl157128 gettext("%s: add operation failed: %s\n"), 1655219a2a31Shl157128 progname, 1656d62bc4baSyz147064 gettext("link capabilities don't match")); 1657*4ac67f02SAnurag S. Maskey dladm_close(handle); 1658219a2a31Shl157128 exit(ENOTSUP); 1659d62bc4baSyz147064 } else if (status == DLADM_STATUS_NONOTIF) { 1660d62bc4baSyz147064 die_dlerr(status, "not all links have link up/down " 1661d62bc4baSyz147064 "detection; must use -f (see dladm(1M))\n"); 1662d62bc4baSyz147064 } else { 1663f595a68aSyz147064 die_dlerr(status, "add operation failed"); 16647c478bd9Sstevel@tonic-gate } 16657c478bd9Sstevel@tonic-gate } 1666d62bc4baSyz147064 } 16677c478bd9Sstevel@tonic-gate 16687c478bd9Sstevel@tonic-gate static void 16698d5c46e6Sam223141 do_remove_aggr(int argc, char *argv[], const char *use) 16707c478bd9Sstevel@tonic-gate { 16717c478bd9Sstevel@tonic-gate char option; 1672f595a68aSyz147064 dladm_aggr_port_attr_db_t port[MAXPORT]; 1673d62bc4baSyz147064 uint_t n, ndev, nlink; 1674d62bc4baSyz147064 char *devs[MAXPORT]; 1675d62bc4baSyz147064 char *links[MAXPORT]; 16767c478bd9Sstevel@tonic-gate char *altroot = NULL; 1677d62bc4baSyz147064 uint32_t flags; 1678d62bc4baSyz147064 datalink_id_t linkid; 1679f595a68aSyz147064 dladm_status_t status; 16807c478bd9Sstevel@tonic-gate 1681d62bc4baSyz147064 flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST; 1682d62bc4baSyz147064 ndev = nlink = opterr = 0; 1683d62bc4baSyz147064 while ((option = getopt_long(argc, argv, ":d:l:R:t", 1684d62bc4baSyz147064 lopts, NULL)) != -1) { 16857c478bd9Sstevel@tonic-gate switch (option) { 16867c478bd9Sstevel@tonic-gate case 'd': 1687d62bc4baSyz147064 if (ndev + nlink >= MAXPORT) 1688d62bc4baSyz147064 die("too many ports specified"); 16897c478bd9Sstevel@tonic-gate 1690d62bc4baSyz147064 devs[ndev++] = optarg; 1691d62bc4baSyz147064 break; 1692d62bc4baSyz147064 case 'l': 1693d62bc4baSyz147064 if (ndev + nlink >= MAXPORT) 1694d62bc4baSyz147064 die("too many ports specified"); 169533343a97Smeem 1696d62bc4baSyz147064 links[nlink++] = optarg; 16977c478bd9Sstevel@tonic-gate break; 16987c478bd9Sstevel@tonic-gate case 't': 1699d62bc4baSyz147064 flags &= ~DLADM_OPT_PERSIST; 17007c478bd9Sstevel@tonic-gate break; 17017c478bd9Sstevel@tonic-gate case 'R': 17027c478bd9Sstevel@tonic-gate altroot = optarg; 17037c478bd9Sstevel@tonic-gate break; 17047c478bd9Sstevel@tonic-gate default: 17058d5c46e6Sam223141 die_opterr(optopt, option, use); 170633343a97Smeem break; 17077c478bd9Sstevel@tonic-gate } 17087c478bd9Sstevel@tonic-gate } 17097c478bd9Sstevel@tonic-gate 1710d62bc4baSyz147064 if (ndev + nlink == 0) 17117c478bd9Sstevel@tonic-gate usage(); 17127c478bd9Sstevel@tonic-gate 1713d62bc4baSyz147064 /* get key value or the aggregation name (required last argument) */ 17147c478bd9Sstevel@tonic-gate if (optind != (argc-1)) 17157c478bd9Sstevel@tonic-gate usage(); 17167c478bd9Sstevel@tonic-gate 1717d62bc4baSyz147064 status = i_dladm_aggr_get_linkid(altroot, argv[optind], &linkid, flags); 1718d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 1719d62bc4baSyz147064 goto done; 17207c478bd9Sstevel@tonic-gate 1721d62bc4baSyz147064 if (altroot != NULL) 1722d62bc4baSyz147064 altroot_cmd(altroot, argc, argv); 1723d62bc4baSyz147064 1724d62bc4baSyz147064 for (n = 0; n < ndev; n++) { 1725*4ac67f02SAnurag S. Maskey if ((status = dladm_dev2linkid(handle, devs[n], 1726*4ac67f02SAnurag S. Maskey &(port[n].lp_linkid))) != DLADM_STATUS_OK) { 1727*4ac67f02SAnurag S. Maskey die_dlerr(status, "invalid <dev> '%s'", devs[n]); 1728d62bc4baSyz147064 } 1729d62bc4baSyz147064 } 1730d62bc4baSyz147064 1731d62bc4baSyz147064 for (n = 0; n < nlink; n++) { 1732*4ac67f02SAnurag S. Maskey if ((status = dladm_name2info(handle, links[n], 1733*4ac67f02SAnurag S. Maskey &port[n + ndev].lp_linkid, NULL, NULL, NULL)) != 1734*4ac67f02SAnurag S. Maskey DLADM_STATUS_OK) { 1735*4ac67f02SAnurag S. Maskey die_dlerr(status, "invalid <link> '%s'", links[n]); 1736d62bc4baSyz147064 } 1737d62bc4baSyz147064 } 1738d62bc4baSyz147064 1739*4ac67f02SAnurag S. Maskey status = dladm_aggr_remove(handle, linkid, ndev + nlink, port, flags); 1740d62bc4baSyz147064 done: 1741f595a68aSyz147064 if (status != DLADM_STATUS_OK) 1742f595a68aSyz147064 die_dlerr(status, "remove operation failed"); 17437c478bd9Sstevel@tonic-gate } 17447c478bd9Sstevel@tonic-gate 17457c478bd9Sstevel@tonic-gate static void 17468d5c46e6Sam223141 do_modify_aggr(int argc, char *argv[], const char *use) 17477c478bd9Sstevel@tonic-gate { 17487c478bd9Sstevel@tonic-gate char option; 17497c478bd9Sstevel@tonic-gate uint32_t policy = AGGR_POLICY_L4; 17507c478bd9Sstevel@tonic-gate aggr_lacp_mode_t lacp_mode = AGGR_LACP_OFF; 17517c478bd9Sstevel@tonic-gate aggr_lacp_timer_t lacp_timer = AGGR_LACP_TIMER_SHORT; 17527c478bd9Sstevel@tonic-gate uint8_t mac_addr[ETHERADDRL]; 17537c478bd9Sstevel@tonic-gate boolean_t mac_addr_fixed = B_FALSE; 17547c478bd9Sstevel@tonic-gate uint8_t modify_mask = 0; 17557c478bd9Sstevel@tonic-gate char *altroot = NULL; 1756d62bc4baSyz147064 uint32_t flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST; 1757d62bc4baSyz147064 datalink_id_t linkid; 1758f595a68aSyz147064 dladm_status_t status; 17597c478bd9Sstevel@tonic-gate 17607c478bd9Sstevel@tonic-gate opterr = 0; 1761d62bc4baSyz147064 while ((option = getopt_long(argc, argv, ":L:l:P:R:tu:T:", lopts, 17627c478bd9Sstevel@tonic-gate NULL)) != -1) { 17637c478bd9Sstevel@tonic-gate switch (option) { 17647c478bd9Sstevel@tonic-gate case 'P': 1765f595a68aSyz147064 if (modify_mask & DLADM_AGGR_MODIFY_POLICY) 176633343a97Smeem die_optdup(option); 17677c478bd9Sstevel@tonic-gate 1768f595a68aSyz147064 modify_mask |= DLADM_AGGR_MODIFY_POLICY; 17697c478bd9Sstevel@tonic-gate 1770f595a68aSyz147064 if (!dladm_aggr_str2policy(optarg, &policy)) 177133343a97Smeem die("invalid policy '%s'", optarg); 17727c478bd9Sstevel@tonic-gate break; 17737c478bd9Sstevel@tonic-gate case 'u': 1774f595a68aSyz147064 if (modify_mask & DLADM_AGGR_MODIFY_MAC) 177533343a97Smeem die_optdup(option); 17767c478bd9Sstevel@tonic-gate 1777f595a68aSyz147064 modify_mask |= DLADM_AGGR_MODIFY_MAC; 17787c478bd9Sstevel@tonic-gate 1779f595a68aSyz147064 if (!dladm_aggr_str2macaddr(optarg, &mac_addr_fixed, 178033343a97Smeem mac_addr)) 178133343a97Smeem die("invalid MAC address '%s'", optarg); 17827c478bd9Sstevel@tonic-gate break; 17837c478bd9Sstevel@tonic-gate case 'l': 1784d62bc4baSyz147064 case 'L': 1785f595a68aSyz147064 if (modify_mask & DLADM_AGGR_MODIFY_LACP_MODE) 178633343a97Smeem die_optdup(option); 17877c478bd9Sstevel@tonic-gate 1788f595a68aSyz147064 modify_mask |= DLADM_AGGR_MODIFY_LACP_MODE; 17897c478bd9Sstevel@tonic-gate 1790f595a68aSyz147064 if (!dladm_aggr_str2lacpmode(optarg, &lacp_mode)) 179133343a97Smeem die("invalid LACP mode '%s'", optarg); 17927c478bd9Sstevel@tonic-gate break; 17937c478bd9Sstevel@tonic-gate case 'T': 1794f595a68aSyz147064 if (modify_mask & DLADM_AGGR_MODIFY_LACP_TIMER) 179533343a97Smeem die_optdup(option); 17967c478bd9Sstevel@tonic-gate 1797f595a68aSyz147064 modify_mask |= DLADM_AGGR_MODIFY_LACP_TIMER; 17987c478bd9Sstevel@tonic-gate 1799f595a68aSyz147064 if (!dladm_aggr_str2lacptimer(optarg, &lacp_timer)) 180033343a97Smeem die("invalid LACP timer value '%s'", optarg); 18017c478bd9Sstevel@tonic-gate break; 18027c478bd9Sstevel@tonic-gate case 't': 1803d62bc4baSyz147064 flags &= ~DLADM_OPT_PERSIST; 18047c478bd9Sstevel@tonic-gate break; 18057c478bd9Sstevel@tonic-gate case 'R': 18067c478bd9Sstevel@tonic-gate altroot = optarg; 18077c478bd9Sstevel@tonic-gate break; 18087c478bd9Sstevel@tonic-gate default: 18098d5c46e6Sam223141 die_opterr(optopt, option, use); 181033343a97Smeem break; 18117c478bd9Sstevel@tonic-gate } 18127c478bd9Sstevel@tonic-gate } 18137c478bd9Sstevel@tonic-gate 181433343a97Smeem if (modify_mask == 0) 181533343a97Smeem die("at least one of the -PulT options must be specified"); 18167c478bd9Sstevel@tonic-gate 1817d62bc4baSyz147064 /* get key value or the aggregation name (required last argument) */ 18187c478bd9Sstevel@tonic-gate if (optind != (argc-1)) 18197c478bd9Sstevel@tonic-gate usage(); 18207c478bd9Sstevel@tonic-gate 1821d62bc4baSyz147064 status = i_dladm_aggr_get_linkid(altroot, argv[optind], &linkid, flags); 1822d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 1823d62bc4baSyz147064 goto done; 18247c478bd9Sstevel@tonic-gate 1825d62bc4baSyz147064 if (altroot != NULL) 1826d62bc4baSyz147064 altroot_cmd(altroot, argc, argv); 1827d62bc4baSyz147064 1828*4ac67f02SAnurag S. Maskey status = dladm_aggr_modify(handle, linkid, modify_mask, policy, 1829*4ac67f02SAnurag S. Maskey mac_addr_fixed, (const uchar_t *)mac_addr, lacp_mode, lacp_timer, 1830*4ac67f02SAnurag S. Maskey flags); 1831d62bc4baSyz147064 1832d62bc4baSyz147064 done: 1833f595a68aSyz147064 if (status != DLADM_STATUS_OK) 1834f595a68aSyz147064 die_dlerr(status, "modify operation failed"); 18357c478bd9Sstevel@tonic-gate } 18367c478bd9Sstevel@tonic-gate 18378d5c46e6Sam223141 /*ARGSUSED*/ 18387c478bd9Sstevel@tonic-gate static void 18398d5c46e6Sam223141 do_up_aggr(int argc, char *argv[], const char *use) 18407c478bd9Sstevel@tonic-gate { 1841d62bc4baSyz147064 datalink_id_t linkid = DATALINK_ALL_LINKID; 1842f595a68aSyz147064 dladm_status_t status; 18437c478bd9Sstevel@tonic-gate 1844d62bc4baSyz147064 /* 1845d62bc4baSyz147064 * get the key or the name of the aggregation (optional last argument) 1846d62bc4baSyz147064 */ 18477c478bd9Sstevel@tonic-gate if (argc == 2) { 1848d62bc4baSyz147064 if ((status = i_dladm_aggr_get_linkid(NULL, argv[1], &linkid, 1849*4ac67f02SAnurag S. Maskey DLADM_OPT_PERSIST)) != DLADM_STATUS_OK) 1850d62bc4baSyz147064 goto done; 18517c478bd9Sstevel@tonic-gate } else if (argc > 2) { 18527c478bd9Sstevel@tonic-gate usage(); 18537c478bd9Sstevel@tonic-gate } 18547c478bd9Sstevel@tonic-gate 1855*4ac67f02SAnurag S. Maskey status = dladm_aggr_up(handle, linkid); 1856d62bc4baSyz147064 done: 1857d62bc4baSyz147064 if (status != DLADM_STATUS_OK) { 1858d62bc4baSyz147064 if (argc == 2) { 1859d62bc4baSyz147064 die_dlerr(status, 1860d62bc4baSyz147064 "could not bring up aggregation '%s'", argv[1]); 18617c478bd9Sstevel@tonic-gate } else { 1862f595a68aSyz147064 die_dlerr(status, "could not bring aggregations up"); 18637c478bd9Sstevel@tonic-gate } 18647c478bd9Sstevel@tonic-gate } 18657c478bd9Sstevel@tonic-gate } 18667c478bd9Sstevel@tonic-gate 18677c478bd9Sstevel@tonic-gate static void 18688d5c46e6Sam223141 do_create_vlan(int argc, char *argv[], const char *use) 18697c478bd9Sstevel@tonic-gate { 1870d62bc4baSyz147064 char *link = NULL; 1871d62bc4baSyz147064 char drv[DLPI_LINKNAME_MAX]; 1872d62bc4baSyz147064 uint_t ppa; 1873d62bc4baSyz147064 datalink_id_t linkid; 1874da14cebeSEric Cheng datalink_id_t dev_linkid; 1875d62bc4baSyz147064 int vid = 0; 1876d62bc4baSyz147064 char option; 1877d62bc4baSyz147064 uint32_t flags = (DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST); 1878d62bc4baSyz147064 char *altroot = NULL; 1879d62bc4baSyz147064 char vlan[MAXLINKNAMELEN]; 1880da14cebeSEric Cheng dladm_arg_list_t *proplist = NULL; 1881f595a68aSyz147064 dladm_status_t status; 18827c478bd9Sstevel@tonic-gate 1883d62bc4baSyz147064 opterr = 0; 1884da14cebeSEric Cheng while ((option = getopt_long(argc, argv, ":tfR:l:v:p:", 1885d62bc4baSyz147064 lopts, NULL)) != -1) { 1886d62bc4baSyz147064 switch (option) { 1887d62bc4baSyz147064 case 'v': 1888d62bc4baSyz147064 if (vid != 0) 1889d62bc4baSyz147064 die_optdup(option); 1890d62bc4baSyz147064 1891d62bc4baSyz147064 if (!str2int(optarg, &vid) || vid < 1 || vid > 4094) 1892d62bc4baSyz147064 die("invalid VLAN identifier '%s'", optarg); 1893d62bc4baSyz147064 1894d62bc4baSyz147064 break; 1895d62bc4baSyz147064 case 'l': 1896d62bc4baSyz147064 if (link != NULL) 1897d62bc4baSyz147064 die_optdup(option); 1898d62bc4baSyz147064 1899d62bc4baSyz147064 link = optarg; 1900d62bc4baSyz147064 break; 1901d62bc4baSyz147064 case 't': 1902d62bc4baSyz147064 flags &= ~DLADM_OPT_PERSIST; 1903d62bc4baSyz147064 break; 1904d62bc4baSyz147064 case 'R': 1905d62bc4baSyz147064 altroot = optarg; 1906d62bc4baSyz147064 break; 1907da14cebeSEric Cheng case 'p': 1908da14cebeSEric Cheng if (dladm_parse_link_props(optarg, &proplist, B_FALSE) 1909da14cebeSEric Cheng != DLADM_STATUS_OK) { 1910da14cebeSEric Cheng die("invalid vlan property"); 1911da14cebeSEric Cheng } 1912da14cebeSEric Cheng break; 1913da14cebeSEric Cheng case 'f': 1914da14cebeSEric Cheng flags |= DLADM_OPT_FORCE; 1915da14cebeSEric Cheng break; 1916d62bc4baSyz147064 default: 19178d5c46e6Sam223141 die_opterr(optopt, option, use); 1918d62bc4baSyz147064 break; 1919d62bc4baSyz147064 } 1920d62bc4baSyz147064 } 1921d62bc4baSyz147064 1922d62bc4baSyz147064 /* get vlan name if there is any */ 1923d62bc4baSyz147064 if ((vid == 0) || (link == NULL) || (argc - optind > 1)) 19247c478bd9Sstevel@tonic-gate usage(); 1925d62bc4baSyz147064 1926d62bc4baSyz147064 if (optind == (argc - 1)) { 1927d62bc4baSyz147064 if (strlcpy(vlan, argv[optind], MAXLINKNAMELEN) >= 1928d62bc4baSyz147064 MAXLINKNAMELEN) { 1929d62bc4baSyz147064 die("vlan name too long '%s'", argv[optind]); 1930d62bc4baSyz147064 } 1931d62bc4baSyz147064 } else { 1932d62bc4baSyz147064 if ((dlpi_parselink(link, drv, &ppa) != DLPI_SUCCESS) || 1933d62bc4baSyz147064 (ppa >= 1000) || 1934d62bc4baSyz147064 (dlpi_makelink(vlan, drv, vid * 1000 + ppa) != 1935d62bc4baSyz147064 DLPI_SUCCESS)) { 1936d62bc4baSyz147064 die("invalid link name '%s'", link); 1937d62bc4baSyz147064 } 19387c478bd9Sstevel@tonic-gate } 19397c478bd9Sstevel@tonic-gate 1940d62bc4baSyz147064 if (altroot != NULL) 1941d62bc4baSyz147064 altroot_cmd(altroot, argc, argv); 1942d62bc4baSyz147064 1943*4ac67f02SAnurag S. Maskey if (dladm_name2info(handle, link, &dev_linkid, NULL, NULL, NULL) != 1944d62bc4baSyz147064 DLADM_STATUS_OK) { 1945d62bc4baSyz147064 die("invalid link name '%s'", link); 1946d62bc4baSyz147064 } 1947d62bc4baSyz147064 1948*4ac67f02SAnurag S. Maskey if ((status = dladm_vlan_create(handle, vlan, dev_linkid, vid, proplist, 1949*4ac67f02SAnurag S. Maskey flags, &linkid)) != DLADM_STATUS_OK) { 1950da14cebeSEric Cheng die_dlerr(status, "create operation over %s failed", link); 1951d62bc4baSyz147064 } 1952d62bc4baSyz147064 } 1953d62bc4baSyz147064 1954d62bc4baSyz147064 static void 19558d5c46e6Sam223141 do_delete_vlan(int argc, char *argv[], const char *use) 1956d62bc4baSyz147064 { 1957d62bc4baSyz147064 char option; 1958d62bc4baSyz147064 uint32_t flags = (DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST); 1959d62bc4baSyz147064 char *altroot = NULL; 1960d62bc4baSyz147064 datalink_id_t linkid; 1961d62bc4baSyz147064 dladm_status_t status; 1962d62bc4baSyz147064 1963d62bc4baSyz147064 opterr = 0; 1964d62bc4baSyz147064 while ((option = getopt_long(argc, argv, ":R:t", lopts, NULL)) != -1) { 1965d62bc4baSyz147064 switch (option) { 1966d62bc4baSyz147064 case 't': 1967d62bc4baSyz147064 flags &= ~DLADM_OPT_PERSIST; 1968d62bc4baSyz147064 break; 1969d62bc4baSyz147064 case 'R': 1970d62bc4baSyz147064 altroot = optarg; 1971d62bc4baSyz147064 break; 1972d62bc4baSyz147064 default: 19738d5c46e6Sam223141 die_opterr(optopt, option, use); 1974d62bc4baSyz147064 break; 1975d62bc4baSyz147064 } 1976d62bc4baSyz147064 } 1977d62bc4baSyz147064 1978d62bc4baSyz147064 /* get VLAN link name (required last argument) */ 1979d62bc4baSyz147064 if (optind != (argc - 1)) 1980d62bc4baSyz147064 usage(); 1981d62bc4baSyz147064 1982d62bc4baSyz147064 if (altroot != NULL) 1983d62bc4baSyz147064 altroot_cmd(altroot, argc, argv); 1984d62bc4baSyz147064 1985*4ac67f02SAnurag S. Maskey status = dladm_name2info(handle, argv[optind], &linkid, NULL, NULL, 1986*4ac67f02SAnurag S. Maskey NULL); 1987d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 1988d62bc4baSyz147064 goto done; 1989d62bc4baSyz147064 1990*4ac67f02SAnurag S. Maskey status = dladm_vlan_delete(handle, linkid, flags); 1991d62bc4baSyz147064 done: 1992d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 1993d62bc4baSyz147064 die_dlerr(status, "delete operation failed"); 1994d62bc4baSyz147064 } 1995d62bc4baSyz147064 19968d5c46e6Sam223141 /*ARGSUSED*/ 1997d62bc4baSyz147064 static void 19988d5c46e6Sam223141 do_up_vlan(int argc, char *argv[], const char *use) 1999d62bc4baSyz147064 { 2000da14cebeSEric Cheng do_up_vnic_common(argc, argv, use, B_TRUE); 20017c478bd9Sstevel@tonic-gate } 20027c478bd9Sstevel@tonic-gate 2003210db224Sericheng static void 20048d5c46e6Sam223141 do_rename_link(int argc, char *argv[], const char *use) 2005210db224Sericheng { 2006d62bc4baSyz147064 char option; 2007d62bc4baSyz147064 char *link1, *link2; 2008d62bc4baSyz147064 char *altroot = NULL; 2009d62bc4baSyz147064 dladm_status_t status; 2010210db224Sericheng 2011d62bc4baSyz147064 opterr = 0; 2012d62bc4baSyz147064 while ((option = getopt_long(argc, argv, ":R:", lopts, NULL)) != -1) { 2013d62bc4baSyz147064 switch (option) { 2014d62bc4baSyz147064 case 'R': 2015d62bc4baSyz147064 altroot = optarg; 2016d62bc4baSyz147064 break; 2017d62bc4baSyz147064 default: 20188d5c46e6Sam223141 die_opterr(optopt, option, use); 2019d62bc4baSyz147064 break; 2020210db224Sericheng } 2021210db224Sericheng } 2022210db224Sericheng 2023d62bc4baSyz147064 /* get link1 and link2 name (required the last 2 arguments) */ 2024d62bc4baSyz147064 if (optind != (argc - 2)) 2025d62bc4baSyz147064 usage(); 2026d62bc4baSyz147064 2027d62bc4baSyz147064 if (altroot != NULL) 2028d62bc4baSyz147064 altroot_cmd(altroot, argc, argv); 2029d62bc4baSyz147064 2030d62bc4baSyz147064 link1 = argv[optind++]; 2031d62bc4baSyz147064 link2 = argv[optind]; 2032*4ac67f02SAnurag S. Maskey if ((status = dladm_rename_link(handle, link1, link2)) != 2033*4ac67f02SAnurag S. Maskey DLADM_STATUS_OK) 2034d62bc4baSyz147064 die_dlerr(status, "rename operation failed"); 2035d62bc4baSyz147064 } 2036d62bc4baSyz147064 20378d5c46e6Sam223141 /*ARGSUSED*/ 2038d62bc4baSyz147064 static void 20398d5c46e6Sam223141 do_delete_phys(int argc, char *argv[], const char *use) 2040d62bc4baSyz147064 { 2041d62bc4baSyz147064 datalink_id_t linkid = DATALINK_ALL_LINKID; 2042d62bc4baSyz147064 dladm_status_t status; 2043d62bc4baSyz147064 2044d62bc4baSyz147064 /* get link name (required the last argument) */ 2045d62bc4baSyz147064 if (argc > 2) 2046d62bc4baSyz147064 usage(); 2047d62bc4baSyz147064 2048d62bc4baSyz147064 if (argc == 2) { 2049*4ac67f02SAnurag S. Maskey if ((status = dladm_name2info(handle, argv[1], &linkid, NULL, 2050*4ac67f02SAnurag S. Maskey NULL, NULL)) != DLADM_STATUS_OK) 2051d62bc4baSyz147064 die_dlerr(status, "cannot delete '%s'", argv[1]); 2052d62bc4baSyz147064 } 2053d62bc4baSyz147064 2054*4ac67f02SAnurag S. Maskey if ((status = dladm_phys_delete(handle, linkid)) != DLADM_STATUS_OK) { 2055d62bc4baSyz147064 if (argc == 2) 2056d62bc4baSyz147064 die_dlerr(status, "cannot delete '%s'", argv[1]); 2057d62bc4baSyz147064 else 2058d62bc4baSyz147064 die_dlerr(status, "delete operation failed"); 2059d62bc4baSyz147064 } 2060d62bc4baSyz147064 } 2061d62bc4baSyz147064 2062d62bc4baSyz147064 /*ARGSUSED*/ 2063210db224Sericheng static int 2064*4ac67f02SAnurag S. Maskey i_dladm_walk_linkmap(dladm_handle_t dh, datalink_id_t linkid, void *arg) 2065210db224Sericheng { 2066d62bc4baSyz147064 char name[MAXLINKNAMELEN]; 2067d62bc4baSyz147064 char mediabuf[DLADM_STRSIZE]; 2068d62bc4baSyz147064 char classbuf[DLADM_STRSIZE]; 2069d62bc4baSyz147064 datalink_class_t class; 2070d62bc4baSyz147064 uint32_t media; 2071d62bc4baSyz147064 uint32_t flags; 2072210db224Sericheng 2073*4ac67f02SAnurag S. Maskey if (dladm_datalink_id2info(dh, linkid, &flags, &class, &media, name, 2074d62bc4baSyz147064 MAXLINKNAMELEN) == DLADM_STATUS_OK) { 2075d62bc4baSyz147064 (void) dladm_class2str(class, classbuf); 2076d62bc4baSyz147064 (void) dladm_media2str(media, mediabuf); 2077d62bc4baSyz147064 (void) printf("%-12s%8d %-12s%-20s %6d\n", name, 2078d62bc4baSyz147064 linkid, classbuf, mediabuf, flags); 2079210db224Sericheng } 2080d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 2081210db224Sericheng } 20827c478bd9Sstevel@tonic-gate 20837c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 20847c478bd9Sstevel@tonic-gate static void 20858d5c46e6Sam223141 do_show_linkmap(int argc, char *argv[], const char *use) 20867c478bd9Sstevel@tonic-gate { 2087d62bc4baSyz147064 if (argc != 1) 2088d62bc4baSyz147064 die("invalid arguments"); 20897c478bd9Sstevel@tonic-gate 2090d62bc4baSyz147064 (void) printf("%-12s%8s %-12s%-20s %6s\n", "NAME", "LINKID", 2091d62bc4baSyz147064 "CLASS", "MEDIA", "FLAGS"); 2092*4ac67f02SAnurag S. Maskey 2093*4ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(i_dladm_walk_linkmap, handle, NULL, 2094d62bc4baSyz147064 DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE, 2095d62bc4baSyz147064 DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST); 20967c478bd9Sstevel@tonic-gate } 2097d62bc4baSyz147064 2098d62bc4baSyz147064 /* 2099d62bc4baSyz147064 * Delete inactive physical links. 2100d62bc4baSyz147064 */ 2101d62bc4baSyz147064 /*ARGSUSED*/ 2102d62bc4baSyz147064 static int 2103*4ac67f02SAnurag S. Maskey purge_phys(dladm_handle_t dh, datalink_id_t linkid, void *arg) 2104d62bc4baSyz147064 { 2105d62bc4baSyz147064 datalink_class_t class; 2106d62bc4baSyz147064 uint32_t flags; 2107d62bc4baSyz147064 2108*4ac67f02SAnurag S. Maskey if (dladm_datalink_id2info(dh, linkid, &flags, &class, NULL, NULL, 0) 2109*4ac67f02SAnurag S. Maskey != DLADM_STATUS_OK) { 2110d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 2111d62bc4baSyz147064 } 2112d62bc4baSyz147064 2113d62bc4baSyz147064 if (class == DATALINK_CLASS_PHYS && !(flags & DLADM_OPT_ACTIVE)) 2114*4ac67f02SAnurag S. Maskey (void) dladm_phys_delete(dh, linkid); 2115d62bc4baSyz147064 2116d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 2117d62bc4baSyz147064 } 2118d62bc4baSyz147064 2119d62bc4baSyz147064 /*ARGSUSED*/ 2120d62bc4baSyz147064 static void 21218d5c46e6Sam223141 do_init_phys(int argc, char *argv[], const char *use) 2122d62bc4baSyz147064 { 2123d62bc4baSyz147064 di_node_t devtree; 2124d62bc4baSyz147064 2125d62bc4baSyz147064 if (argc > 1) 2126d62bc4baSyz147064 usage(); 2127d62bc4baSyz147064 2128d62bc4baSyz147064 /* 2129d62bc4baSyz147064 * Force all the devices to attach, therefore all the network physical 2130d62bc4baSyz147064 * devices can be known to the dlmgmtd daemon. 2131d62bc4baSyz147064 */ 2132d62bc4baSyz147064 if ((devtree = di_init("/", DINFOFORCE | DINFOSUBTREE)) != DI_NODE_NIL) 2133d62bc4baSyz147064 di_fini(devtree); 2134d62bc4baSyz147064 2135*4ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(purge_phys, handle, NULL, 2136d62bc4baSyz147064 DATALINK_CLASS_PHYS, DATALINK_ANY_MEDIATYPE, DLADM_OPT_PERSIST); 21377c478bd9Sstevel@tonic-gate } 21387c478bd9Sstevel@tonic-gate 2139d62bc4baSyz147064 2140d62bc4baSyz147064 /* 2141d62bc4baSyz147064 * Print the active topology information. 2142d62bc4baSyz147064 */ 2143d62bc4baSyz147064 static dladm_status_t 2144d62bc4baSyz147064 print_link_topology(show_state_t *state, datalink_id_t linkid, 2145e7801d59Ssowmini datalink_class_t class, link_fields_buf_t *lbuf) 2146d62bc4baSyz147064 { 2147d62bc4baSyz147064 uint32_t flags = state->ls_flags; 2148d62bc4baSyz147064 dladm_status_t status = DLADM_STATUS_OK; 21496b9e797cSsowmini char tmpbuf[MAXLINKNAMELEN]; 2150d62bc4baSyz147064 2151e7801d59Ssowmini if (!state->ls_parseable) 2152e7801d59Ssowmini (void) sprintf(lbuf->link_over, STR_UNDEF_VAL); 2153d62bc4baSyz147064 else 2154e7801d59Ssowmini (void) sprintf(lbuf->link_over, ""); 2155d62bc4baSyz147064 2156d62bc4baSyz147064 if (class == DATALINK_CLASS_VLAN) { 2157d62bc4baSyz147064 dladm_vlan_attr_t vinfo; 2158d62bc4baSyz147064 2159*4ac67f02SAnurag S. Maskey status = dladm_vlan_info(handle, linkid, &vinfo, flags); 2160d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 2161d62bc4baSyz147064 goto done; 2162*4ac67f02SAnurag S. Maskey status = dladm_datalink_id2info(handle, vinfo.dv_linkid, NULL, 2163*4ac67f02SAnurag S. Maskey NULL, NULL, lbuf->link_over, sizeof (lbuf->link_over)); 2164d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 2165d62bc4baSyz147064 goto done; 2166d62bc4baSyz147064 } else if (class == DATALINK_CLASS_AGGR) { 2167d62bc4baSyz147064 dladm_aggr_grp_attr_t ginfo; 2168d62bc4baSyz147064 int i; 2169d62bc4baSyz147064 21706b9e797cSsowmini (void) sprintf(lbuf->link_over, ""); 21716b9e797cSsowmini 2172*4ac67f02SAnurag S. Maskey status = dladm_aggr_info(handle, linkid, &ginfo, flags); 2173d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 2174d62bc4baSyz147064 goto done; 2175d62bc4baSyz147064 2176d62bc4baSyz147064 if (ginfo.lg_nports == 0) { 2177d62bc4baSyz147064 status = DLADM_STATUS_BADVAL; 2178d62bc4baSyz147064 goto done; 2179d62bc4baSyz147064 } 2180d62bc4baSyz147064 for (i = 0; i < ginfo.lg_nports; i++) { 2181*4ac67f02SAnurag S. Maskey status = dladm_datalink_id2info(handle, 2182e7801d59Ssowmini ginfo.lg_ports[i].lp_linkid, NULL, NULL, NULL, 21836b9e797cSsowmini tmpbuf, sizeof (tmpbuf)); 2184d62bc4baSyz147064 if (status != DLADM_STATUS_OK) { 2185d62bc4baSyz147064 free(ginfo.lg_ports); 2186d62bc4baSyz147064 goto done; 2187d62bc4baSyz147064 } 21886b9e797cSsowmini (void) strlcat(lbuf->link_over, tmpbuf, 21896b9e797cSsowmini sizeof (lbuf->link_over)); 21906b9e797cSsowmini if (i != (ginfo.lg_nports - 1)) { 21916b9e797cSsowmini (void) strlcat(lbuf->link_over, " ", 21926b9e797cSsowmini sizeof (lbuf->link_over)); 21936b9e797cSsowmini } 2194d62bc4baSyz147064 } 2195d62bc4baSyz147064 free(ginfo.lg_ports); 2196d62bc4baSyz147064 } else if (class == DATALINK_CLASS_VNIC) { 2197da14cebeSEric Cheng dladm_vnic_attr_t vinfo; 2198d62bc4baSyz147064 2199*4ac67f02SAnurag S. Maskey if ((status = dladm_vnic_info(handle, linkid, &vinfo, flags)) != 2200*4ac67f02SAnurag S. Maskey DLADM_STATUS_OK || 2201*4ac67f02SAnurag S. Maskey (status = dladm_datalink_id2info(handle, vinfo.va_link_id, 2202*4ac67f02SAnurag S. Maskey NULL, NULL, NULL, lbuf->link_over, 2203e7801d59Ssowmini sizeof (lbuf->link_over)) != DLADM_STATUS_OK)) { 2204d62bc4baSyz147064 goto done; 2205d62bc4baSyz147064 } 2206d62bc4baSyz147064 } 2207d62bc4baSyz147064 done: 2208d62bc4baSyz147064 return (status); 2209d62bc4baSyz147064 } 2210d62bc4baSyz147064 2211d62bc4baSyz147064 static dladm_status_t 2212e7801d59Ssowmini print_link(show_state_t *state, datalink_id_t linkid, link_fields_buf_t *lbuf) 2213d62bc4baSyz147064 { 2214d62bc4baSyz147064 char link[MAXLINKNAMELEN]; 2215d62bc4baSyz147064 datalink_class_t class; 2216d62bc4baSyz147064 uint_t mtu; 2217d62bc4baSyz147064 uint32_t flags; 2218d62bc4baSyz147064 dladm_status_t status; 2219d62bc4baSyz147064 2220*4ac67f02SAnurag S. Maskey if ((status = dladm_datalink_id2info(handle, linkid, &flags, &class, 2221*4ac67f02SAnurag S. Maskey NULL, link, sizeof (link))) != DLADM_STATUS_OK) { 2222d62bc4baSyz147064 goto done; 2223d62bc4baSyz147064 } 2224d62bc4baSyz147064 2225d62bc4baSyz147064 if (!(state->ls_flags & flags)) { 2226d62bc4baSyz147064 status = DLADM_STATUS_NOTFOUND; 2227d62bc4baSyz147064 goto done; 2228d62bc4baSyz147064 } 2229d62bc4baSyz147064 2230d62bc4baSyz147064 if (state->ls_flags == DLADM_OPT_ACTIVE) { 2231d62bc4baSyz147064 dladm_attr_t dlattr; 2232d62bc4baSyz147064 2233d62bc4baSyz147064 if (class == DATALINK_CLASS_PHYS) { 2234d62bc4baSyz147064 dladm_phys_attr_t dpa; 2235d62bc4baSyz147064 dlpi_handle_t dh; 2236d62bc4baSyz147064 dlpi_info_t dlinfo; 2237d62bc4baSyz147064 2238*4ac67f02SAnurag S. Maskey if ((status = dladm_phys_info(handle, linkid, &dpa, 2239d62bc4baSyz147064 DLADM_OPT_ACTIVE)) != DLADM_STATUS_OK) { 2240d62bc4baSyz147064 goto done; 2241d62bc4baSyz147064 } 2242d62bc4baSyz147064 2243d62bc4baSyz147064 if (!dpa.dp_novanity) 2244d62bc4baSyz147064 goto link_mtu; 2245d62bc4baSyz147064 2246d62bc4baSyz147064 /* 2247d62bc4baSyz147064 * This is a physical link that does not have 2248d62bc4baSyz147064 * vanity naming support. 2249d62bc4baSyz147064 */ 2250d62bc4baSyz147064 if (dlpi_open(dpa.dp_dev, &dh, DLPI_DEVONLY) != 2251d62bc4baSyz147064 DLPI_SUCCESS) { 2252d62bc4baSyz147064 status = DLADM_STATUS_NOTFOUND; 2253d62bc4baSyz147064 goto done; 2254d62bc4baSyz147064 } 2255d62bc4baSyz147064 2256d62bc4baSyz147064 if (dlpi_info(dh, &dlinfo, 0) != DLPI_SUCCESS) { 2257d62bc4baSyz147064 dlpi_close(dh); 2258d62bc4baSyz147064 status = DLADM_STATUS_BADARG; 2259d62bc4baSyz147064 goto done; 2260d62bc4baSyz147064 } 2261d62bc4baSyz147064 2262d62bc4baSyz147064 dlpi_close(dh); 2263d62bc4baSyz147064 mtu = dlinfo.di_max_sdu; 2264d62bc4baSyz147064 } else { 2265d62bc4baSyz147064 link_mtu: 2266*4ac67f02SAnurag S. Maskey status = dladm_info(handle, linkid, &dlattr); 2267d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 2268d62bc4baSyz147064 goto done; 2269d62bc4baSyz147064 mtu = dlattr.da_max_sdu; 2270d62bc4baSyz147064 } 2271d62bc4baSyz147064 } 2272d62bc4baSyz147064 2273e7801d59Ssowmini (void) snprintf(lbuf->link_name, sizeof (lbuf->link_name), 2274e7801d59Ssowmini "%s", link); 2275e7801d59Ssowmini (void) dladm_class2str(class, lbuf->link_class); 2276d62bc4baSyz147064 if (state->ls_flags == DLADM_OPT_ACTIVE) { 2277e7801d59Ssowmini (void) snprintf(lbuf->link_mtu, sizeof (lbuf->link_mtu), 2278c08e5e1aSdr146992 "%u", mtu); 2279e7801d59Ssowmini (void) get_linkstate(link, B_TRUE, lbuf->link_state); 2280d62bc4baSyz147064 } 2281d62bc4baSyz147064 2282e7801d59Ssowmini status = print_link_topology(state, linkid, class, lbuf); 2283d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 2284d62bc4baSyz147064 goto done; 2285d62bc4baSyz147064 2286d62bc4baSyz147064 done: 2287d62bc4baSyz147064 return (status); 2288d62bc4baSyz147064 } 2289d62bc4baSyz147064 2290*4ac67f02SAnurag S. Maskey /* ARGSUSED */ 2291d62bc4baSyz147064 static int 2292*4ac67f02SAnurag S. Maskey show_link(dladm_handle_t dh, datalink_id_t linkid, void *arg) 2293d62bc4baSyz147064 { 2294e7801d59Ssowmini show_state_t *state = (show_state_t *)arg; 2295d62bc4baSyz147064 dladm_status_t status; 2296e7801d59Ssowmini link_fields_buf_t lbuf; 2297d62bc4baSyz147064 2298e7801d59Ssowmini /* 2299e7801d59Ssowmini * first get all the link attributes into lbuf; 2300e7801d59Ssowmini */ 23015f5c9f54SAnurag S. Maskey bzero(&lbuf, sizeof (link_fields_buf_t)); 2302e7801d59Ssowmini status = print_link(state, linkid, &lbuf); 2303e7801d59Ssowmini 2304d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 2305d62bc4baSyz147064 goto done; 2306e7801d59Ssowmini 2307e7801d59Ssowmini if (!state->ls_parseable && !state->ls_printheader) { 2308e7801d59Ssowmini print_header(&state->ls_print); 2309e7801d59Ssowmini state->ls_printheader = B_TRUE; 2310e7801d59Ssowmini } 2311e7801d59Ssowmini 2312e7801d59Ssowmini dladm_print_output(&state->ls_print, state->ls_parseable, 2313e7801d59Ssowmini dladm_print_field, (void *)&lbuf); 2314d62bc4baSyz147064 2315d62bc4baSyz147064 done: 2316d62bc4baSyz147064 state->ls_status = status; 2317d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 2318d62bc4baSyz147064 } 2319d62bc4baSyz147064 2320d62bc4baSyz147064 static int 2321*4ac67f02SAnurag S. Maskey show_link_stats(dladm_handle_t dh, datalink_id_t linkid, void *arg) 2322d62bc4baSyz147064 { 2323e7801d59Ssowmini char link[DLPI_LINKNAME_MAX]; 2324d62bc4baSyz147064 datalink_class_t class; 2325e7801d59Ssowmini show_state_t *state = (show_state_t *)arg; 23267c478bd9Sstevel@tonic-gate pktsum_t stats, diff_stats; 2327d62bc4baSyz147064 dladm_phys_attr_t dpa; 23287c478bd9Sstevel@tonic-gate 23297c478bd9Sstevel@tonic-gate if (state->ls_firstonly) { 23307c478bd9Sstevel@tonic-gate if (state->ls_donefirst) 2331d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 23327c478bd9Sstevel@tonic-gate state->ls_donefirst = B_TRUE; 23337c478bd9Sstevel@tonic-gate } else { 23347c478bd9Sstevel@tonic-gate bzero(&state->ls_prevstats, sizeof (state->ls_prevstats)); 23357c478bd9Sstevel@tonic-gate } 23367c478bd9Sstevel@tonic-gate 2337*4ac67f02SAnurag S. Maskey if (dladm_datalink_id2info(dh, linkid, NULL, &class, NULL, link, 2338e7801d59Ssowmini DLPI_LINKNAME_MAX) != DLADM_STATUS_OK) { 2339d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 2340d62bc4baSyz147064 } 2341d62bc4baSyz147064 2342d62bc4baSyz147064 if (class == DATALINK_CLASS_PHYS) { 2343*4ac67f02SAnurag S. Maskey if (dladm_phys_info(dh, linkid, &dpa, DLADM_OPT_ACTIVE) != 2344d62bc4baSyz147064 DLADM_STATUS_OK) { 2345d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 2346d62bc4baSyz147064 } 2347d62bc4baSyz147064 if (dpa.dp_novanity) 2348d62bc4baSyz147064 get_mac_stats(dpa.dp_dev, &stats); 2349d62bc4baSyz147064 else 2350d62bc4baSyz147064 get_link_stats(link, &stats); 2351d62bc4baSyz147064 } else { 2352d62bc4baSyz147064 get_link_stats(link, &stats); 2353d62bc4baSyz147064 } 2354da14cebeSEric Cheng dladm_stats_diff(&diff_stats, &stats, &state->ls_prevstats); 23557c478bd9Sstevel@tonic-gate 2356da14cebeSEric Cheng (void) printf("%-12s", link); 2357da14cebeSEric Cheng (void) printf("%-10llu", diff_stats.ipackets); 2358da14cebeSEric Cheng (void) printf("%-12llu", diff_stats.rbytes); 2359da14cebeSEric Cheng (void) printf("%-8llu", diff_stats.ierrors); 2360da14cebeSEric Cheng (void) printf("%-10llu", diff_stats.opackets); 2361da14cebeSEric Cheng (void) printf("%-12llu", diff_stats.obytes); 2362da14cebeSEric Cheng (void) printf("%-8llu\n", diff_stats.oerrors); 23637c478bd9Sstevel@tonic-gate 23647c478bd9Sstevel@tonic-gate state->ls_prevstats = stats; 2365d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 23667c478bd9Sstevel@tonic-gate } 23677c478bd9Sstevel@tonic-gate 2368d62bc4baSyz147064 2369d62bc4baSyz147064 static dladm_status_t 2370d62bc4baSyz147064 print_aggr_info(show_grp_state_t *state, const char *link, 2371e7801d59Ssowmini dladm_aggr_grp_attr_t *ginfop) 2372d62bc4baSyz147064 { 2373d62bc4baSyz147064 char addr_str[ETHERADDRL * 3]; 2374e7801d59Ssowmini laggr_fields_buf_t lbuf; 2375d62bc4baSyz147064 2376e7801d59Ssowmini (void) snprintf(lbuf.laggr_name, sizeof (lbuf.laggr_name), 2377e7801d59Ssowmini "%s", link); 2378e7801d59Ssowmini 2379e7801d59Ssowmini (void) dladm_aggr_policy2str(ginfop->lg_policy, 2380e7801d59Ssowmini lbuf.laggr_policy); 2381d62bc4baSyz147064 2382d62bc4baSyz147064 if (ginfop->lg_mac_fixed) { 2383d62bc4baSyz147064 (void) dladm_aggr_macaddr2str(ginfop->lg_mac, addr_str); 2384e7801d59Ssowmini (void) snprintf(lbuf.laggr_addrpolicy, 2385e7801d59Ssowmini sizeof (lbuf.laggr_addrpolicy), "fixed (%s)", addr_str); 2386d62bc4baSyz147064 } else { 2387e7801d59Ssowmini (void) snprintf(lbuf.laggr_addrpolicy, 2388e7801d59Ssowmini sizeof (lbuf.laggr_addrpolicy), "auto"); 2389d62bc4baSyz147064 } 2390d62bc4baSyz147064 2391d62bc4baSyz147064 2392e7801d59Ssowmini (void) dladm_aggr_lacpmode2str(ginfop->lg_lacp_mode, 2393e7801d59Ssowmini lbuf.laggr_lacpactivity); 2394e7801d59Ssowmini (void) dladm_aggr_lacptimer2str(ginfop->lg_lacp_timer, 2395e7801d59Ssowmini lbuf.laggr_lacptimer); 2396e7801d59Ssowmini (void) snprintf(lbuf.laggr_flags, sizeof (lbuf.laggr_flags), "%c----", 2397d62bc4baSyz147064 ginfop->lg_force ? 'f' : '-'); 2398e7801d59Ssowmini 2399e7801d59Ssowmini if (!state->gs_parseable && !state->gs_printheader) { 2400e7801d59Ssowmini print_header(&state->gs_print); 2401e7801d59Ssowmini state->gs_printheader = B_TRUE; 2402d62bc4baSyz147064 } 2403d62bc4baSyz147064 2404e7801d59Ssowmini dladm_print_output(&state->gs_print, state->gs_parseable, 2405e7801d59Ssowmini dladm_print_field, (void *)&lbuf); 2406e7801d59Ssowmini 2407d62bc4baSyz147064 return (DLADM_STATUS_OK); 2408d62bc4baSyz147064 } 2409d62bc4baSyz147064 2410e7801d59Ssowmini static char * 2411e7801d59Ssowmini print_xaggr_callback(print_field_t *pf, void *arg) 2412d62bc4baSyz147064 { 2413e7801d59Ssowmini const laggr_args_t *l = arg; 2414e7801d59Ssowmini int portnum; 2415e7801d59Ssowmini static char buf[DLADM_STRSIZE]; 2416e7801d59Ssowmini boolean_t is_port = (l->laggr_lport >= 0); 2417e7801d59Ssowmini dladm_aggr_port_attr_t *portp; 2418d62bc4baSyz147064 dladm_phys_attr_t dpa; 2419e7801d59Ssowmini dladm_status_t *stat, status; 2420d62bc4baSyz147064 2421e7801d59Ssowmini stat = l->laggr_status; 2422e7801d59Ssowmini *stat = DLADM_STATUS_OK; 2423d62bc4baSyz147064 2424e7801d59Ssowmini if (is_port) { 2425e7801d59Ssowmini portnum = l->laggr_lport; 2426e7801d59Ssowmini portp = &(l->laggr_ginfop->lg_ports[portnum]); 2427*4ac67f02SAnurag S. Maskey if ((status = dladm_datalink_id2info(handle, 2428*4ac67f02SAnurag S. Maskey portp->lp_linkid, NULL, NULL, NULL, buf, sizeof (buf))) != 2429e7801d59Ssowmini DLADM_STATUS_OK) { 2430e7801d59Ssowmini goto err; 2431d62bc4baSyz147064 } 2432*4ac67f02SAnurag S. Maskey 2433*4ac67f02SAnurag S. Maskey if ((status = dladm_phys_info(handle, portp->lp_linkid, 2434*4ac67f02SAnurag S. Maskey &dpa, DLADM_OPT_ACTIVE)) != DLADM_STATUS_OK) { 2435e7801d59Ssowmini goto err; 2436e7801d59Ssowmini } 2437d62bc4baSyz147064 } 2438d62bc4baSyz147064 2439e7801d59Ssowmini switch (pf->pf_index) { 2440e7801d59Ssowmini case AGGR_X_LINK: 2441e7801d59Ssowmini (void) snprintf(buf, sizeof (buf), "%s", 2442e7801d59Ssowmini (is_port && !l->laggr_parseable ? " " : l->laggr_link)); 2443e7801d59Ssowmini break; 2444e7801d59Ssowmini case AGGR_X_PORT: 2445e7801d59Ssowmini if (is_port) 2446e7801d59Ssowmini break; 2447e7801d59Ssowmini return (""); 2448e7801d59Ssowmini break; 2449d62bc4baSyz147064 2450e7801d59Ssowmini case AGGR_X_SPEED: 2451e7801d59Ssowmini if (is_port) { 2452e7801d59Ssowmini (void) snprintf(buf, sizeof (buf), "%uMb", 2453e7801d59Ssowmini (uint_t)((get_ifspeed(dpa.dp_dev, 2454e7801d59Ssowmini B_FALSE)) / 1000000ull)); 2455e7801d59Ssowmini } else { 2456e7801d59Ssowmini (void) snprintf(buf, sizeof (buf), "%uMb", 2457e7801d59Ssowmini (uint_t)((get_ifspeed(l->laggr_link, 2458e7801d59Ssowmini B_TRUE)) / 1000000ull)); 2459e7801d59Ssowmini } 2460e7801d59Ssowmini break; 2461e7801d59Ssowmini 2462e7801d59Ssowmini case AGGR_X_DUPLEX: 2463e7801d59Ssowmini if (is_port) 2464e7801d59Ssowmini (void) get_linkduplex(dpa.dp_dev, B_FALSE, buf); 2465d62bc4baSyz147064 else 2466e7801d59Ssowmini (void) get_linkduplex(l->laggr_link, B_TRUE, buf); 2467e7801d59Ssowmini break; 2468d62bc4baSyz147064 2469e7801d59Ssowmini case AGGR_X_STATE: 24701a1811a0Svs226613 if (is_port) 24711a1811a0Svs226613 (void) get_linkstate(dpa.dp_dev, B_FALSE, buf); 24721a1811a0Svs226613 else 24731a1811a0Svs226613 (void) get_linkstate(l->laggr_link, B_TRUE, buf); 2474e7801d59Ssowmini break; 2475e7801d59Ssowmini case AGGR_X_ADDRESS: 2476e7801d59Ssowmini (void) dladm_aggr_macaddr2str( 2477e7801d59Ssowmini (is_port ? portp->lp_mac : l->laggr_ginfop->lg_mac), 2478e7801d59Ssowmini buf); 2479e7801d59Ssowmini break; 2480e7801d59Ssowmini case AGGR_X_PORTSTATE: 24810d365605Sschuster if (is_port) 24820d365605Sschuster (void) dladm_aggr_portstate2str( 24830d365605Sschuster portp->lp_state, buf); 24840d365605Sschuster else 24850d365605Sschuster return (""); 2486e7801d59Ssowmini break; 2487e7801d59Ssowmini } 2488e7801d59Ssowmini return (buf); 2489e7801d59Ssowmini 2490e7801d59Ssowmini err: 2491e7801d59Ssowmini *stat = status; 2492e7801d59Ssowmini buf[0] = '\0'; 2493e7801d59Ssowmini return (buf); 2494e7801d59Ssowmini } 2495e7801d59Ssowmini 2496e7801d59Ssowmini static dladm_status_t 2497e7801d59Ssowmini print_aggr_extended(show_grp_state_t *state, const char *link, 2498e7801d59Ssowmini dladm_aggr_grp_attr_t *ginfop) 2499e7801d59Ssowmini { 2500e7801d59Ssowmini int i; 2501e7801d59Ssowmini dladm_status_t status; 2502e7801d59Ssowmini laggr_args_t largs; 2503e7801d59Ssowmini 2504e7801d59Ssowmini if (!state->gs_parseable && !state->gs_printheader) { 2505e7801d59Ssowmini print_header(&state->gs_print); 2506e7801d59Ssowmini state->gs_printheader = B_TRUE; 2507e7801d59Ssowmini } 2508e7801d59Ssowmini 2509e7801d59Ssowmini largs.laggr_lport = -1; 2510e7801d59Ssowmini largs.laggr_link = link; 2511e7801d59Ssowmini largs.laggr_ginfop = ginfop; 2512e7801d59Ssowmini largs.laggr_status = &status; 2513e7801d59Ssowmini largs.laggr_parseable = state->gs_parseable; 2514e7801d59Ssowmini 2515e7801d59Ssowmini dladm_print_output(&state->gs_print, state->gs_parseable, 2516e7801d59Ssowmini print_xaggr_callback, &largs); 2517e7801d59Ssowmini 2518e7801d59Ssowmini if (status != DLADM_STATUS_OK) 2519e7801d59Ssowmini goto done; 2520e7801d59Ssowmini 2521e7801d59Ssowmini for (i = 0; i < ginfop->lg_nports; i++) { 2522e7801d59Ssowmini largs.laggr_lport = i; 2523e7801d59Ssowmini dladm_print_output(&state->gs_print, state->gs_parseable, 2524e7801d59Ssowmini print_xaggr_callback, &largs); 2525e7801d59Ssowmini if (status != DLADM_STATUS_OK) 2526e7801d59Ssowmini goto done; 2527d62bc4baSyz147064 } 2528d62bc4baSyz147064 2529d62bc4baSyz147064 status = DLADM_STATUS_OK; 2530d62bc4baSyz147064 done: 2531d62bc4baSyz147064 return (status); 2532d62bc4baSyz147064 } 2533d62bc4baSyz147064 2534e7801d59Ssowmini 2535e7801d59Ssowmini static char * 2536e7801d59Ssowmini print_lacp_callback(print_field_t *pf, void *arg) 2537e7801d59Ssowmini { 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; 2543e7801d59Ssowmini dladm_status_t *stat, status; 2544e7801d59Ssowmini aggr_lacp_state_t *lstate; 2545e7801d59Ssowmini 2546e7801d59Ssowmini if (!is_port) { 2547e7801d59Ssowmini return (NULL); /* cannot happen! */ 2548e7801d59Ssowmini } 2549e7801d59Ssowmini 2550e7801d59Ssowmini stat = l->laggr_status; 2551e7801d59Ssowmini 2552e7801d59Ssowmini portnum = l->laggr_lport; 2553e7801d59Ssowmini portp = &(l->laggr_ginfop->lg_ports[portnum]); 2554*4ac67f02SAnurag S. Maskey 2555*4ac67f02SAnurag S. Maskey if ((status = dladm_datalink_id2info(handle, portp->lp_linkid, 2556e7801d59Ssowmini NULL, NULL, NULL, buf, sizeof (buf))) != DLADM_STATUS_OK) { 2557e7801d59Ssowmini goto err; 2558e7801d59Ssowmini } 2559e7801d59Ssowmini lstate = &(portp->lp_lacp_state); 2560e7801d59Ssowmini 2561e7801d59Ssowmini switch (pf->pf_index) { 2562e7801d59Ssowmini case AGGR_L_LINK: 2563e7801d59Ssowmini (void) snprintf(buf, sizeof (buf), "%s", 2564e7801d59Ssowmini (portnum > 0 ? "" : l->laggr_link)); 2565e7801d59Ssowmini break; 2566e7801d59Ssowmini 2567e7801d59Ssowmini case AGGR_L_PORT: 2568e7801d59Ssowmini break; 2569e7801d59Ssowmini 2570e7801d59Ssowmini case AGGR_L_AGGREGATABLE: 2571e7801d59Ssowmini (void) snprintf(buf, sizeof (buf), "%s", 2572e7801d59Ssowmini (lstate->bit.aggregation ? "yes" : "no")); 2573e7801d59Ssowmini break; 2574e7801d59Ssowmini 2575e7801d59Ssowmini case AGGR_L_SYNC: 2576e7801d59Ssowmini (void) snprintf(buf, sizeof (buf), "%s", 2577e7801d59Ssowmini (lstate->bit.sync ? "yes" : "no")); 2578e7801d59Ssowmini break; 2579e7801d59Ssowmini 2580e7801d59Ssowmini case AGGR_L_COLL: 2581e7801d59Ssowmini (void) snprintf(buf, sizeof (buf), "%s", 2582e7801d59Ssowmini (lstate->bit.collecting ? "yes" : "no")); 2583e7801d59Ssowmini break; 2584e7801d59Ssowmini 2585e7801d59Ssowmini case AGGR_L_DIST: 2586e7801d59Ssowmini (void) snprintf(buf, sizeof (buf), "%s", 2587e7801d59Ssowmini (lstate->bit.distributing ? "yes" : "no")); 2588e7801d59Ssowmini break; 2589e7801d59Ssowmini 2590e7801d59Ssowmini case AGGR_L_DEFAULTED: 2591e7801d59Ssowmini (void) snprintf(buf, sizeof (buf), "%s", 2592e7801d59Ssowmini (lstate->bit.defaulted ? "yes" : "no")); 2593e7801d59Ssowmini break; 2594e7801d59Ssowmini 2595e7801d59Ssowmini case AGGR_L_EXPIRED: 2596e7801d59Ssowmini (void) snprintf(buf, sizeof (buf), "%s", 2597e7801d59Ssowmini (lstate->bit.expired ? "yes" : "no")); 2598e7801d59Ssowmini break; 2599e7801d59Ssowmini } 2600e7801d59Ssowmini 2601e7801d59Ssowmini *stat = DLADM_STATUS_OK; 2602e7801d59Ssowmini return (buf); 2603e7801d59Ssowmini 2604e7801d59Ssowmini err: 2605e7801d59Ssowmini *stat = status; 2606e7801d59Ssowmini buf[0] = '\0'; 2607e7801d59Ssowmini return (buf); 2608e7801d59Ssowmini } 2609e7801d59Ssowmini 2610d62bc4baSyz147064 static dladm_status_t 2611d62bc4baSyz147064 print_aggr_lacp(show_grp_state_t *state, const char *link, 2612e7801d59Ssowmini dladm_aggr_grp_attr_t *ginfop) 2613d62bc4baSyz147064 { 2614d62bc4baSyz147064 int i; 2615d62bc4baSyz147064 dladm_status_t status; 2616e7801d59Ssowmini laggr_args_t largs; 2617d62bc4baSyz147064 2618e7801d59Ssowmini if (!state->gs_parseable && !state->gs_printheader) { 2619e7801d59Ssowmini print_header(&state->gs_print); 2620e7801d59Ssowmini state->gs_printheader = B_TRUE; 2621d62bc4baSyz147064 } 2622d62bc4baSyz147064 2623e7801d59Ssowmini largs.laggr_link = link; 2624e7801d59Ssowmini largs.laggr_ginfop = ginfop; 2625e7801d59Ssowmini largs.laggr_status = &status; 2626d62bc4baSyz147064 2627e7801d59Ssowmini for (i = 0; i < ginfop->lg_nports; i++) { 2628e7801d59Ssowmini largs.laggr_lport = i; 2629e7801d59Ssowmini dladm_print_output(&state->gs_print, state->gs_parseable, 2630e7801d59Ssowmini print_lacp_callback, &largs); 2631d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 2632d62bc4baSyz147064 goto done; 2633d62bc4baSyz147064 } 2634d62bc4baSyz147064 2635d62bc4baSyz147064 status = DLADM_STATUS_OK; 2636d62bc4baSyz147064 done: 2637d62bc4baSyz147064 return (status); 2638d62bc4baSyz147064 } 2639d62bc4baSyz147064 2640e7801d59Ssowmini static char * 2641e7801d59Ssowmini print_aggr_stats_callback(print_field_t *pf, void *arg) 2642e7801d59Ssowmini { 2643e7801d59Ssowmini const laggr_args_t *l = arg; 2644e7801d59Ssowmini int portnum; 2645e7801d59Ssowmini static char buf[DLADM_STRSIZE]; 2646e7801d59Ssowmini boolean_t is_port = (l->laggr_lport >= 0); 2647e7801d59Ssowmini dladm_aggr_port_attr_t *portp; 2648e7801d59Ssowmini dladm_phys_attr_t dpa; 2649e7801d59Ssowmini dladm_status_t *stat, status; 2650e7801d59Ssowmini pktsum_t port_stat, diff_stats; 2651e7801d59Ssowmini 2652e7801d59Ssowmini stat = l->laggr_status; 2653e7801d59Ssowmini *stat = DLADM_STATUS_OK; 2654e7801d59Ssowmini 2655e7801d59Ssowmini if (is_port) { 2656e7801d59Ssowmini portnum = l->laggr_lport; 2657e7801d59Ssowmini portp = &(l->laggr_ginfop->lg_ports[portnum]); 2658*4ac67f02SAnurag S. Maskey if ((status = dladm_phys_info(handle, portp->lp_linkid, 2659*4ac67f02SAnurag S. Maskey &dpa, DLADM_OPT_ACTIVE)) != DLADM_STATUS_OK) { 2660e7801d59Ssowmini goto err; 2661e7801d59Ssowmini } 2662e7801d59Ssowmini 2663e7801d59Ssowmini get_mac_stats(dpa.dp_dev, &port_stat); 2664e7801d59Ssowmini 2665*4ac67f02SAnurag S. Maskey if ((status = dladm_datalink_id2info(handle, 2666*4ac67f02SAnurag S. Maskey portp->lp_linkid, NULL, NULL, NULL, buf, sizeof (buf))) != 2667*4ac67f02SAnurag S. Maskey DLADM_STATUS_OK) { 2668e7801d59Ssowmini goto err; 2669e7801d59Ssowmini } 2670e7801d59Ssowmini 2671da14cebeSEric Cheng dladm_stats_diff(&diff_stats, &port_stat, l->laggr_prevstats); 2672e7801d59Ssowmini } 2673e7801d59Ssowmini 2674e7801d59Ssowmini switch (pf->pf_index) { 2675e7801d59Ssowmini case AGGR_S_LINK: 2676e7801d59Ssowmini (void) snprintf(buf, sizeof (buf), "%s", 2677e7801d59Ssowmini (is_port ? "" : l->laggr_link)); 2678e7801d59Ssowmini break; 2679e7801d59Ssowmini case AGGR_S_PORT: 2680e7801d59Ssowmini if (is_port) 2681e7801d59Ssowmini break; 26820d365605Sschuster return (""); 2683e7801d59Ssowmini break; 2684e7801d59Ssowmini 2685e7801d59Ssowmini case AGGR_S_IPKTS: 2686e7801d59Ssowmini if (is_port) { 2687e7801d59Ssowmini (void) snprintf(buf, sizeof (buf), "%llu", 2688e7801d59Ssowmini diff_stats.ipackets); 2689e7801d59Ssowmini } else { 2690e7801d59Ssowmini (void) snprintf(buf, sizeof (buf), "%llu", 2691e7801d59Ssowmini l->laggr_pktsumtot->ipackets); 2692e7801d59Ssowmini } 2693e7801d59Ssowmini break; 2694e7801d59Ssowmini 2695e7801d59Ssowmini case AGGR_S_RBYTES: 2696e7801d59Ssowmini if (is_port) { 2697e7801d59Ssowmini (void) snprintf(buf, sizeof (buf), "%llu", 2698e7801d59Ssowmini diff_stats.rbytes); 2699e7801d59Ssowmini } else { 2700e7801d59Ssowmini (void) snprintf(buf, sizeof (buf), "%llu", 2701e7801d59Ssowmini l->laggr_pktsumtot->rbytes); 2702e7801d59Ssowmini } 2703e7801d59Ssowmini break; 2704e7801d59Ssowmini 2705e7801d59Ssowmini case AGGR_S_OPKTS: 2706e7801d59Ssowmini if (is_port) { 2707e7801d59Ssowmini (void) snprintf(buf, sizeof (buf), "%llu", 2708e7801d59Ssowmini diff_stats.opackets); 2709e7801d59Ssowmini } else { 2710e7801d59Ssowmini (void) snprintf(buf, sizeof (buf), "%llu", 2711e7801d59Ssowmini l->laggr_pktsumtot->opackets); 2712e7801d59Ssowmini } 2713e7801d59Ssowmini break; 2714e7801d59Ssowmini case AGGR_S_OBYTES: 2715e7801d59Ssowmini if (is_port) { 2716e7801d59Ssowmini (void) snprintf(buf, sizeof (buf), "%llu", 2717e7801d59Ssowmini diff_stats.obytes); 2718e7801d59Ssowmini } else { 2719e7801d59Ssowmini (void) snprintf(buf, sizeof (buf), "%llu", 2720e7801d59Ssowmini l->laggr_pktsumtot->obytes); 2721e7801d59Ssowmini } 2722e7801d59Ssowmini break; 2723e7801d59Ssowmini 2724e7801d59Ssowmini case AGGR_S_IPKTDIST: 2725e7801d59Ssowmini if (is_port) { 2726e7801d59Ssowmini (void) snprintf(buf, sizeof (buf), "%-6.1f", 2727e7801d59Ssowmini (double)diff_stats.opackets/ 2728e7801d59Ssowmini (double)l->laggr_pktsumtot->ipackets * 100); 2729e7801d59Ssowmini } else { 27300d365605Sschuster return (""); 2731e7801d59Ssowmini } 2732e7801d59Ssowmini break; 2733e7801d59Ssowmini case AGGR_S_OPKTDIST: 2734e7801d59Ssowmini if (is_port) { 2735e7801d59Ssowmini (void) snprintf(buf, sizeof (buf), "%-6.1f", 2736e7801d59Ssowmini (double)diff_stats.opackets/ 2737e7801d59Ssowmini (double)l->laggr_pktsumtot->opackets * 100); 2738e7801d59Ssowmini } else { 27390d365605Sschuster return (""); 2740e7801d59Ssowmini } 2741e7801d59Ssowmini break; 2742e7801d59Ssowmini } 2743e7801d59Ssowmini return (buf); 2744e7801d59Ssowmini 2745e7801d59Ssowmini err: 2746e7801d59Ssowmini *stat = status; 2747e7801d59Ssowmini buf[0] = '\0'; 2748e7801d59Ssowmini return (buf); 2749e7801d59Ssowmini } 2750e7801d59Ssowmini 2751d62bc4baSyz147064 static dladm_status_t 2752d62bc4baSyz147064 print_aggr_stats(show_grp_state_t *state, const char *link, 2753e7801d59Ssowmini dladm_aggr_grp_attr_t *ginfop) 2754d62bc4baSyz147064 { 2755d62bc4baSyz147064 dladm_phys_attr_t dpa; 2756d62bc4baSyz147064 dladm_aggr_port_attr_t *portp; 2757d62bc4baSyz147064 pktsum_t pktsumtot, port_stat; 2758d62bc4baSyz147064 dladm_status_t status; 2759d62bc4baSyz147064 int i; 2760e7801d59Ssowmini laggr_args_t largs; 27617c478bd9Sstevel@tonic-gate 27627c478bd9Sstevel@tonic-gate /* sum the ports statistics */ 27637c478bd9Sstevel@tonic-gate bzero(&pktsumtot, sizeof (pktsumtot)); 2764d62bc4baSyz147064 2765d62bc4baSyz147064 for (i = 0; i < ginfop->lg_nports; i++) { 2766d62bc4baSyz147064 2767d62bc4baSyz147064 portp = &(ginfop->lg_ports[i]); 2768*4ac67f02SAnurag S. Maskey if ((status = dladm_phys_info(handle, portp->lp_linkid, &dpa, 2769d62bc4baSyz147064 DLADM_OPT_ACTIVE)) != DLADM_STATUS_OK) { 2770d62bc4baSyz147064 goto done; 27717c478bd9Sstevel@tonic-gate } 27727c478bd9Sstevel@tonic-gate 2773d62bc4baSyz147064 get_mac_stats(dpa.dp_dev, &port_stat); 2774da14cebeSEric Cheng dladm_stats_total(&pktsumtot, &port_stat, 2775da14cebeSEric Cheng &state->gs_prevstats[i]); 27767c478bd9Sstevel@tonic-gate } 27777c478bd9Sstevel@tonic-gate 2778e7801d59Ssowmini if (!state->gs_parseable && !state->gs_printheader) { 2779e7801d59Ssowmini print_header(&state->gs_print); 2780e7801d59Ssowmini state->gs_printheader = B_TRUE; 2781e7801d59Ssowmini } 2782e7801d59Ssowmini 2783e7801d59Ssowmini largs.laggr_lport = -1; 2784e7801d59Ssowmini largs.laggr_link = link; 2785e7801d59Ssowmini largs.laggr_ginfop = ginfop; 2786e7801d59Ssowmini largs.laggr_status = &status; 2787e7801d59Ssowmini largs.laggr_pktsumtot = &pktsumtot; 2788e7801d59Ssowmini 2789e7801d59Ssowmini dladm_print_output(&state->gs_print, state->gs_parseable, 2790e7801d59Ssowmini print_aggr_stats_callback, &largs); 2791e7801d59Ssowmini 2792e7801d59Ssowmini if (status != DLADM_STATUS_OK) 2793e7801d59Ssowmini goto done; 2794d62bc4baSyz147064 2795d62bc4baSyz147064 for (i = 0; i < ginfop->lg_nports; i++) { 2796e7801d59Ssowmini largs.laggr_lport = i; 2797e7801d59Ssowmini largs.laggr_prevstats = &state->gs_prevstats[i]; 2798e7801d59Ssowmini dladm_print_output(&state->gs_print, state->gs_parseable, 2799e7801d59Ssowmini print_aggr_stats_callback, &largs); 2800e7801d59Ssowmini if (status != DLADM_STATUS_OK) 2801d62bc4baSyz147064 goto done; 2802d62bc4baSyz147064 } 2803d62bc4baSyz147064 2804d62bc4baSyz147064 status = DLADM_STATUS_OK; 2805d62bc4baSyz147064 done: 2806d62bc4baSyz147064 return (status); 2807d62bc4baSyz147064 } 2808d62bc4baSyz147064 2809d62bc4baSyz147064 static dladm_status_t 2810e7801d59Ssowmini print_aggr(show_grp_state_t *state, datalink_id_t linkid) 2811d62bc4baSyz147064 { 2812d62bc4baSyz147064 char link[MAXLINKNAMELEN]; 2813d62bc4baSyz147064 dladm_aggr_grp_attr_t ginfo; 2814d62bc4baSyz147064 uint32_t flags; 2815d62bc4baSyz147064 dladm_status_t status; 2816d62bc4baSyz147064 28175f5c9f54SAnurag S. Maskey bzero(&ginfo, sizeof (dladm_aggr_grp_attr_t)); 2818*4ac67f02SAnurag S. Maskey if ((status = dladm_datalink_id2info(handle, linkid, &flags, NULL, 2819*4ac67f02SAnurag S. Maskey NULL, link, MAXLINKNAMELEN)) != DLADM_STATUS_OK) { 2820d62bc4baSyz147064 return (status); 2821d62bc4baSyz147064 } 2822d62bc4baSyz147064 2823d62bc4baSyz147064 if (!(state->gs_flags & flags)) 2824d62bc4baSyz147064 return (DLADM_STATUS_NOTFOUND); 2825d62bc4baSyz147064 2826*4ac67f02SAnurag S. Maskey status = dladm_aggr_info(handle, linkid, &ginfo, state->gs_flags); 2827d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 2828d62bc4baSyz147064 return (status); 2829d62bc4baSyz147064 2830d62bc4baSyz147064 if (state->gs_lacp) 2831e7801d59Ssowmini status = print_aggr_lacp(state, link, &ginfo); 2832d62bc4baSyz147064 else if (state->gs_extended) 2833e7801d59Ssowmini status = print_aggr_extended(state, link, &ginfo); 2834d62bc4baSyz147064 else if (state->gs_stats) 2835e7801d59Ssowmini status = print_aggr_stats(state, link, &ginfo); 2836*4ac67f02SAnurag S. Maskey else 2837e7801d59Ssowmini status = print_aggr_info(state, link, &ginfo); 2838d62bc4baSyz147064 2839d62bc4baSyz147064 done: 2840d62bc4baSyz147064 free(ginfo.lg_ports); 2841d62bc4baSyz147064 return (status); 2842d62bc4baSyz147064 } 2843d62bc4baSyz147064 2844*4ac67f02SAnurag S. Maskey /* ARGSUSED */ 2845d62bc4baSyz147064 static int 2846*4ac67f02SAnurag S. Maskey show_aggr(dladm_handle_t dh, datalink_id_t linkid, void *arg) 2847d62bc4baSyz147064 { 2848d62bc4baSyz147064 show_grp_state_t *state = arg; 2849d62bc4baSyz147064 dladm_status_t status; 2850d62bc4baSyz147064 2851*4ac67f02SAnurag S. Maskey if ((status = print_aggr(state, linkid)) != DLADM_STATUS_OK) 2852d62bc4baSyz147064 goto done; 2853d62bc4baSyz147064 2854d62bc4baSyz147064 done: 2855d62bc4baSyz147064 state->gs_status = status; 2856d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 28577c478bd9Sstevel@tonic-gate } 28587c478bd9Sstevel@tonic-gate 28597c478bd9Sstevel@tonic-gate static void 28608d5c46e6Sam223141 do_show_link(int argc, char *argv[], const char *use) 28617c478bd9Sstevel@tonic-gate { 28627c478bd9Sstevel@tonic-gate int option; 28637c478bd9Sstevel@tonic-gate boolean_t s_arg = B_FALSE; 2864da14cebeSEric Cheng boolean_t S_arg = B_FALSE; 28657c478bd9Sstevel@tonic-gate boolean_t i_arg = B_FALSE; 2866d62bc4baSyz147064 uint32_t flags = DLADM_OPT_ACTIVE; 2867d62bc4baSyz147064 boolean_t p_arg = B_FALSE; 2868d62bc4baSyz147064 datalink_id_t linkid = DATALINK_ALL_LINKID; 2869da14cebeSEric Cheng char linkname[MAXLINKNAMELEN]; 287033343a97Smeem int interval = 0; 2871d62bc4baSyz147064 show_state_t state; 2872d62bc4baSyz147064 dladm_status_t status; 2873e7801d59Ssowmini boolean_t o_arg = B_FALSE; 2874e7801d59Ssowmini char *fields_str = NULL; 2875e7801d59Ssowmini print_field_t **fields; 2876e7801d59Ssowmini uint_t nfields; 2877e7801d59Ssowmini char *all_active_fields = "link,class,mtu,state,over"; 2878e7801d59Ssowmini char *all_inactive_fields = "link,class,over"; 28796be03d0bSVasumathi Sundaram - Sun Microsystems char *allstat_fields = 28806be03d0bSVasumathi Sundaram - Sun Microsystems "link,ipackets,rbytes,ierrors,opackets,obytes,oerrors"; 2881e7801d59Ssowmini 2882e7801d59Ssowmini bzero(&state, sizeof (state)); 28837c478bd9Sstevel@tonic-gate 28847c478bd9Sstevel@tonic-gate opterr = 0; 2885da14cebeSEric Cheng while ((option = getopt_long(argc, argv, ":pPsSi:o:", 2886d62bc4baSyz147064 show_lopts, NULL)) != -1) { 28877c478bd9Sstevel@tonic-gate switch (option) { 28887c478bd9Sstevel@tonic-gate case 'p': 2889d62bc4baSyz147064 if (p_arg) 2890d62bc4baSyz147064 die_optdup(option); 2891d62bc4baSyz147064 2892d62bc4baSyz147064 p_arg = B_TRUE; 28937c478bd9Sstevel@tonic-gate break; 28947c478bd9Sstevel@tonic-gate case 's': 289533343a97Smeem if (s_arg) 289633343a97Smeem die_optdup(option); 28977c478bd9Sstevel@tonic-gate 28987c478bd9Sstevel@tonic-gate s_arg = B_TRUE; 28997c478bd9Sstevel@tonic-gate break; 2900d62bc4baSyz147064 case 'P': 2901d62bc4baSyz147064 if (flags != DLADM_OPT_ACTIVE) 2902d62bc4baSyz147064 die_optdup(option); 2903d62bc4baSyz147064 2904d62bc4baSyz147064 flags = DLADM_OPT_PERSIST; 2905d62bc4baSyz147064 break; 2906da14cebeSEric Cheng case 'S': 2907da14cebeSEric Cheng if (S_arg) 2908da14cebeSEric Cheng die_optdup(option); 2909da14cebeSEric Cheng 2910da14cebeSEric Cheng S_arg = B_TRUE; 2911da14cebeSEric Cheng break; 2912e7801d59Ssowmini case 'o': 2913e7801d59Ssowmini o_arg = B_TRUE; 2914e7801d59Ssowmini fields_str = optarg; 2915e7801d59Ssowmini break; 29167c478bd9Sstevel@tonic-gate case 'i': 291733343a97Smeem if (i_arg) 291833343a97Smeem die_optdup(option); 29197c478bd9Sstevel@tonic-gate 29207c478bd9Sstevel@tonic-gate i_arg = B_TRUE; 292133343a97Smeem if (!str2int(optarg, &interval) || interval == 0) 292233343a97Smeem die("invalid interval value '%s'", optarg); 29237c478bd9Sstevel@tonic-gate break; 29247c478bd9Sstevel@tonic-gate default: 29258d5c46e6Sam223141 die_opterr(optopt, option, use); 292633343a97Smeem break; 29277c478bd9Sstevel@tonic-gate } 29287c478bd9Sstevel@tonic-gate } 29297c478bd9Sstevel@tonic-gate 2930da14cebeSEric Cheng if (i_arg && !(s_arg || S_arg)) 2931da14cebeSEric Cheng die("the option -i can be used only with -s or -S"); 2932da14cebeSEric Cheng 2933da14cebeSEric Cheng if (s_arg && S_arg) 2934da14cebeSEric Cheng die("the -s option cannot be used with -S"); 29357c478bd9Sstevel@tonic-gate 29366be03d0bSVasumathi Sundaram - Sun Microsystems if (s_arg && flags != DLADM_OPT_ACTIVE) 29376be03d0bSVasumathi Sundaram - Sun Microsystems die("the option -P cannot be used with -s"); 2938d62bc4baSyz147064 2939da14cebeSEric Cheng if (S_arg && (p_arg || flags != DLADM_OPT_ACTIVE)) 2940da14cebeSEric Cheng die("the option -%c cannot be used with -S", p_arg ? 'p' : 'P'); 2941da14cebeSEric Cheng 29427c478bd9Sstevel@tonic-gate /* get link name (optional last argument) */ 2943d62bc4baSyz147064 if (optind == (argc-1)) { 2944d62bc4baSyz147064 uint32_t f; 2945d62bc4baSyz147064 2946da14cebeSEric Cheng if (strlcpy(linkname, argv[optind], MAXLINKNAMELEN) 2947da14cebeSEric Cheng >= MAXLINKNAMELEN) { 2948da14cebeSEric Cheng (void) fprintf(stderr, 2949da14cebeSEric Cheng gettext("%s: link name too long\n"), 2950da14cebeSEric Cheng progname); 2951*4ac67f02SAnurag S. Maskey dladm_close(handle); 2952da14cebeSEric Cheng exit(1); 2953da14cebeSEric Cheng } 2954*4ac67f02SAnurag S. Maskey if ((status = dladm_name2info(handle, linkname, &linkid, &f, 2955d62bc4baSyz147064 NULL, NULL)) != DLADM_STATUS_OK) { 2956da14cebeSEric Cheng die_dlerr(status, "link %s is not valid", linkname); 2957d62bc4baSyz147064 } 2958d62bc4baSyz147064 2959d62bc4baSyz147064 if (!(f & flags)) { 2960d62bc4baSyz147064 die_dlerr(DLADM_STATUS_BADARG, "link %s is %s", 2961d62bc4baSyz147064 argv[optind], flags == DLADM_OPT_PERSIST ? 2962d62bc4baSyz147064 "a temporary link" : "temporarily removed"); 2963d62bc4baSyz147064 } 2964d62bc4baSyz147064 } else if (optind != argc) { 29657c478bd9Sstevel@tonic-gate usage(); 2966d62bc4baSyz147064 } 29677c478bd9Sstevel@tonic-gate 29680d365605Sschuster if (p_arg && !o_arg) 29690d365605Sschuster die("-p requires -o"); 29700d365605Sschuster 2971da14cebeSEric Cheng if (S_arg) { 2972*4ac67f02SAnurag S. Maskey dladm_continuous(handle, linkid, NULL, interval, LINK_REPORT); 2973da14cebeSEric Cheng return; 2974da14cebeSEric Cheng } 2975da14cebeSEric Cheng 29760d365605Sschuster if (p_arg && strcasecmp(fields_str, "all") == 0) 29770d365605Sschuster die("\"-o all\" is invalid with -p"); 29780d365605Sschuster 2979e7801d59Ssowmini if (!o_arg || (o_arg && strcasecmp(fields_str, "all") == 0)) { 29806be03d0bSVasumathi Sundaram - Sun Microsystems if (s_arg) 29816be03d0bSVasumathi Sundaram - Sun Microsystems fields_str = allstat_fields; 29826be03d0bSVasumathi Sundaram - Sun Microsystems else if (flags & DLADM_OPT_ACTIVE) 2983e7801d59Ssowmini fields_str = all_active_fields; 2984e7801d59Ssowmini else 2985e7801d59Ssowmini fields_str = all_inactive_fields; 2986e7801d59Ssowmini } 2987e7801d59Ssowmini 29886be03d0bSVasumathi Sundaram - Sun Microsystems state.ls_parseable = p_arg; 29896be03d0bSVasumathi Sundaram - Sun Microsystems state.ls_flags = flags; 29906be03d0bSVasumathi Sundaram - Sun Microsystems state.ls_donefirst = B_FALSE; 29916be03d0bSVasumathi Sundaram - Sun Microsystems 29926be03d0bSVasumathi Sundaram - Sun Microsystems if (s_arg) { 29936be03d0bSVasumathi Sundaram - Sun Microsystems link_stats(linkid, interval, fields_str, &state); 29946be03d0bSVasumathi Sundaram - Sun Microsystems return; 29956be03d0bSVasumathi Sundaram - Sun Microsystems } 29966be03d0bSVasumathi Sundaram - Sun Microsystems 2997e7801d59Ssowmini fields = parse_output_fields(fields_str, link_fields, DEV_LINK_FIELDS, 2998e7801d59Ssowmini CMD_TYPE_ANY, &nfields); 2999e7801d59Ssowmini 30000d365605Sschuster if (fields == NULL) 3001e7801d59Ssowmini die("invalid field(s) specified"); 3002e7801d59Ssowmini 3003e7801d59Ssowmini state.ls_print.ps_fields = fields; 3004e7801d59Ssowmini state.ls_print.ps_nfields = nfields; 3005e7801d59Ssowmini 3006d62bc4baSyz147064 if (linkid == DATALINK_ALL_LINKID) { 3007*4ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(show_link, handle, &state, 3008d62bc4baSyz147064 DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE, flags); 3009210db224Sericheng } else { 3010*4ac67f02SAnurag S. Maskey (void) show_link(handle, linkid, &state); 3011d62bc4baSyz147064 if (state.ls_status != DLADM_STATUS_OK) { 3012d62bc4baSyz147064 die_dlerr(state.ls_status, "failed to show link %s", 3013d62bc4baSyz147064 argv[optind]); 3014d62bc4baSyz147064 } 30157c478bd9Sstevel@tonic-gate } 3016210db224Sericheng } 30177c478bd9Sstevel@tonic-gate 30187c478bd9Sstevel@tonic-gate static void 30198d5c46e6Sam223141 do_show_aggr(int argc, char *argv[], const char *use) 30207c478bd9Sstevel@tonic-gate { 30217c478bd9Sstevel@tonic-gate boolean_t L_arg = B_FALSE; 30227c478bd9Sstevel@tonic-gate boolean_t s_arg = B_FALSE; 30237c478bd9Sstevel@tonic-gate boolean_t i_arg = B_FALSE; 3024d62bc4baSyz147064 boolean_t p_arg = B_FALSE; 3025d62bc4baSyz147064 boolean_t x_arg = B_FALSE; 30267c478bd9Sstevel@tonic-gate show_grp_state_t state; 3027d62bc4baSyz147064 uint32_t flags = DLADM_OPT_ACTIVE; 3028d62bc4baSyz147064 datalink_id_t linkid = DATALINK_ALL_LINKID; 3029d62bc4baSyz147064 int option; 303033343a97Smeem int interval = 0; 3031d62bc4baSyz147064 int key; 3032d62bc4baSyz147064 dladm_status_t status; 3033e7801d59Ssowmini boolean_t o_arg = B_FALSE; 3034e7801d59Ssowmini char *fields_str = NULL; 3035e7801d59Ssowmini print_field_t **fields; 3036e7801d59Ssowmini uint_t nfields; 3037e7801d59Ssowmini char *all_fields = 3038e7801d59Ssowmini "link,policy,addrpolicy,lacpactivity,lacptimer,flags"; 3039e7801d59Ssowmini char *all_lacp_fields = 3040e7801d59Ssowmini "link,port,aggregatable,sync,coll,dist,defaulted,expired"; 3041e7801d59Ssowmini char *all_stats_fields = 3042e7801d59Ssowmini "link,port,ipackets,rbytes,opackets,obytes,ipktdist,opktdist"; 3043e7801d59Ssowmini char *all_extended_fields = 3044e7801d59Ssowmini "link,port,speed,duplex,state,address,portstate"; 3045e7801d59Ssowmini print_field_t *pf; 3046e7801d59Ssowmini int pfmax; 3047e7801d59Ssowmini 3048e7801d59Ssowmini bzero(&state, sizeof (state)); 30497c478bd9Sstevel@tonic-gate 30507c478bd9Sstevel@tonic-gate opterr = 0; 3051e7801d59Ssowmini while ((option = getopt_long(argc, argv, ":LpPxsi:o:", 3052d62bc4baSyz147064 show_lopts, NULL)) != -1) { 30537c478bd9Sstevel@tonic-gate switch (option) { 30547c478bd9Sstevel@tonic-gate case 'L': 305533343a97Smeem if (L_arg) 305633343a97Smeem die_optdup(option); 30577c478bd9Sstevel@tonic-gate 30587c478bd9Sstevel@tonic-gate L_arg = B_TRUE; 30597c478bd9Sstevel@tonic-gate break; 30607c478bd9Sstevel@tonic-gate case 'p': 3061d62bc4baSyz147064 if (p_arg) 3062d62bc4baSyz147064 die_optdup(option); 3063d62bc4baSyz147064 3064d62bc4baSyz147064 p_arg = B_TRUE; 3065d62bc4baSyz147064 break; 3066d62bc4baSyz147064 case 'x': 3067d62bc4baSyz147064 if (x_arg) 3068d62bc4baSyz147064 die_optdup(option); 3069d62bc4baSyz147064 3070d62bc4baSyz147064 x_arg = B_TRUE; 3071d62bc4baSyz147064 break; 3072d62bc4baSyz147064 case 'P': 3073d62bc4baSyz147064 if (flags != DLADM_OPT_ACTIVE) 3074d62bc4baSyz147064 die_optdup(option); 3075d62bc4baSyz147064 3076d62bc4baSyz147064 flags = DLADM_OPT_PERSIST; 30777c478bd9Sstevel@tonic-gate break; 30787c478bd9Sstevel@tonic-gate case 's': 307933343a97Smeem if (s_arg) 308033343a97Smeem die_optdup(option); 30817c478bd9Sstevel@tonic-gate 30827c478bd9Sstevel@tonic-gate s_arg = B_TRUE; 30837c478bd9Sstevel@tonic-gate break; 3084e7801d59Ssowmini case 'o': 3085e7801d59Ssowmini o_arg = B_TRUE; 3086e7801d59Ssowmini fields_str = optarg; 3087e7801d59Ssowmini break; 30887c478bd9Sstevel@tonic-gate case 'i': 308933343a97Smeem if (i_arg) 309033343a97Smeem die_optdup(option); 30917c478bd9Sstevel@tonic-gate 30927c478bd9Sstevel@tonic-gate i_arg = B_TRUE; 309333343a97Smeem if (!str2int(optarg, &interval) || interval == 0) 309433343a97Smeem die("invalid interval value '%s'", optarg); 30957c478bd9Sstevel@tonic-gate break; 30967c478bd9Sstevel@tonic-gate default: 30978d5c46e6Sam223141 die_opterr(optopt, option, use); 309833343a97Smeem break; 30997c478bd9Sstevel@tonic-gate } 31007c478bd9Sstevel@tonic-gate } 31017c478bd9Sstevel@tonic-gate 31020d365605Sschuster if (p_arg && !o_arg) 31030d365605Sschuster die("-p requires -o"); 31040d365605Sschuster 31050d365605Sschuster if (p_arg && strcasecmp(fields_str, "all") == 0) 31060d365605Sschuster die("\"-o all\" is invalid with -p"); 31070d365605Sschuster 310833343a97Smeem if (i_arg && !s_arg) 310933343a97Smeem die("the option -i can be used only with -s"); 31107c478bd9Sstevel@tonic-gate 3111d62bc4baSyz147064 if (s_arg && (L_arg || p_arg || x_arg || flags != DLADM_OPT_ACTIVE)) { 3112d62bc4baSyz147064 die("the option -%c cannot be used with -s", 3113d62bc4baSyz147064 L_arg ? 'L' : (p_arg ? 'p' : (x_arg ? 'x' : 'P'))); 3114d62bc4baSyz147064 } 3115d62bc4baSyz147064 3116d62bc4baSyz147064 if (L_arg && flags != DLADM_OPT_ACTIVE) 3117d62bc4baSyz147064 die("the option -P cannot be used with -L"); 3118d62bc4baSyz147064 3119d62bc4baSyz147064 if (x_arg && (L_arg || flags != DLADM_OPT_ACTIVE)) 3120d62bc4baSyz147064 die("the option -%c cannot be used with -x", L_arg ? 'L' : 'P'); 3121d62bc4baSyz147064 3122d62bc4baSyz147064 /* get aggregation key or aggrname (optional last argument) */ 31237c478bd9Sstevel@tonic-gate if (optind == (argc-1)) { 3124d62bc4baSyz147064 if (!str2int(argv[optind], &key)) { 3125*4ac67f02SAnurag S. Maskey status = dladm_name2info(handle, argv[optind], 3126*4ac67f02SAnurag S. Maskey &linkid, NULL, NULL, NULL); 3127d62bc4baSyz147064 } else { 3128*4ac67f02SAnurag S. Maskey status = dladm_key2linkid(handle, (uint16_t)key, 3129d62bc4baSyz147064 &linkid, DLADM_OPT_ACTIVE); 3130d62bc4baSyz147064 } 3131d62bc4baSyz147064 3132d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 3133d62bc4baSyz147064 die("non-existent aggregation '%s'", argv[optind]); 3134d62bc4baSyz147064 31357c478bd9Sstevel@tonic-gate } else if (optind != argc) { 31367c478bd9Sstevel@tonic-gate usage(); 31377c478bd9Sstevel@tonic-gate } 31387c478bd9Sstevel@tonic-gate 3139d62bc4baSyz147064 bzero(&state, sizeof (state)); 3140d62bc4baSyz147064 state.gs_lacp = L_arg; 3141d62bc4baSyz147064 state.gs_stats = s_arg; 3142d62bc4baSyz147064 state.gs_flags = flags; 3143d62bc4baSyz147064 state.gs_parseable = p_arg; 3144d62bc4baSyz147064 state.gs_extended = x_arg; 3145d62bc4baSyz147064 3146e7801d59Ssowmini if (!o_arg || (o_arg && strcasecmp(fields_str, "all") == 0)) { 3147e7801d59Ssowmini if (state.gs_lacp) 3148e7801d59Ssowmini fields_str = all_lacp_fields; 3149e7801d59Ssowmini else if (state.gs_stats) 3150e7801d59Ssowmini fields_str = all_stats_fields; 3151e7801d59Ssowmini else if (state.gs_extended) 3152e7801d59Ssowmini fields_str = all_extended_fields; 3153e7801d59Ssowmini else 3154e7801d59Ssowmini fields_str = all_fields; 3155e7801d59Ssowmini } 3156e7801d59Ssowmini 3157e7801d59Ssowmini if (state.gs_lacp) { 3158e7801d59Ssowmini pf = aggr_l_fields; 3159e7801d59Ssowmini pfmax = AGGR_L_MAX_FIELDS; 3160e7801d59Ssowmini } else if (state.gs_stats) { 3161e7801d59Ssowmini pf = aggr_s_fields; 3162e7801d59Ssowmini pfmax = AGGR_S_MAX_FIELDS; 3163e7801d59Ssowmini } else if (state.gs_extended) { 3164e7801d59Ssowmini pf = aggr_x_fields; 3165e7801d59Ssowmini pfmax = AGGR_X_MAX_FIELDS; 3166e7801d59Ssowmini } else { 3167e7801d59Ssowmini pf = laggr_fields; 3168e7801d59Ssowmini pfmax = LAGGR_MAX_FIELDS; 3169e7801d59Ssowmini } 3170e7801d59Ssowmini fields = parse_output_fields(fields_str, pf, pfmax, CMD_TYPE_ANY, 3171e7801d59Ssowmini &nfields); 3172e7801d59Ssowmini 3173e7801d59Ssowmini if (fields == NULL) { 3174e7801d59Ssowmini die("invalid field(s) specified"); 3175e7801d59Ssowmini return; 3176e7801d59Ssowmini } 3177e7801d59Ssowmini 3178e7801d59Ssowmini state.gs_print.ps_fields = fields; 3179e7801d59Ssowmini state.gs_print.ps_nfields = nfields; 3180e7801d59Ssowmini 31817c478bd9Sstevel@tonic-gate if (s_arg) { 3182d62bc4baSyz147064 aggr_stats(linkid, &state, interval); 31837c478bd9Sstevel@tonic-gate return; 31847c478bd9Sstevel@tonic-gate } 31857c478bd9Sstevel@tonic-gate 3186d62bc4baSyz147064 if (linkid == DATALINK_ALL_LINKID) { 3187*4ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(show_aggr, handle, &state, 3188d62bc4baSyz147064 DATALINK_CLASS_AGGR, DATALINK_ANY_MEDIATYPE, flags); 3189d62bc4baSyz147064 } else { 3190*4ac67f02SAnurag S. Maskey (void) show_aggr(handle, linkid, &state); 3191d62bc4baSyz147064 if (state.gs_status != DLADM_STATUS_OK) { 3192d62bc4baSyz147064 die_dlerr(state.gs_status, "failed to show aggr %s", 3193d62bc4baSyz147064 argv[optind]); 3194d62bc4baSyz147064 } 3195d62bc4baSyz147064 } 31967c478bd9Sstevel@tonic-gate } 31977c478bd9Sstevel@tonic-gate 3198da14cebeSEric Cheng static dladm_status_t 3199da14cebeSEric Cheng print_phys_default(show_state_t *state, datalink_id_t linkid, 3200da14cebeSEric Cheng const char *link, uint32_t flags, uint32_t media) 32017c478bd9Sstevel@tonic-gate { 3202da14cebeSEric Cheng dladm_phys_attr_t dpa; 3203da14cebeSEric Cheng dladm_status_t status; 3204da14cebeSEric Cheng link_fields_buf_t pattr; 3205e7801d59Ssowmini 3206*4ac67f02SAnurag S. Maskey status = dladm_phys_info(handle, linkid, &dpa, state->ls_flags); 3207da14cebeSEric Cheng if (status != DLADM_STATUS_OK) 3208da14cebeSEric Cheng goto done; 32097c478bd9Sstevel@tonic-gate 3210da14cebeSEric Cheng (void) snprintf(pattr.link_phys_device, 3211da14cebeSEric Cheng sizeof (pattr.link_phys_device), "%s", dpa.dp_dev); 3212da14cebeSEric Cheng (void) dladm_media2str(media, pattr.link_phys_media); 3213da14cebeSEric Cheng if (state->ls_flags == DLADM_OPT_ACTIVE) { 3214da14cebeSEric Cheng boolean_t islink; 3215d62bc4baSyz147064 3216da14cebeSEric Cheng if (!dpa.dp_novanity) { 3217da14cebeSEric Cheng (void) strlcpy(pattr.link_name, link, 3218da14cebeSEric Cheng sizeof (pattr.link_name)); 3219da14cebeSEric Cheng islink = B_TRUE; 3220d62bc4baSyz147064 } else { 3221da14cebeSEric Cheng /* 3222da14cebeSEric Cheng * This is a physical link that does not have 3223da14cebeSEric Cheng * vanity naming support. 3224da14cebeSEric Cheng */ 3225da14cebeSEric Cheng (void) strlcpy(pattr.link_name, dpa.dp_dev, 3226da14cebeSEric Cheng sizeof (pattr.link_name)); 3227da14cebeSEric Cheng islink = B_FALSE; 32287c478bd9Sstevel@tonic-gate } 32297c478bd9Sstevel@tonic-gate 3230da14cebeSEric Cheng (void) get_linkstate(pattr.link_name, islink, 3231da14cebeSEric Cheng pattr.link_phys_state); 3232da14cebeSEric Cheng (void) snprintf(pattr.link_phys_speed, 3233da14cebeSEric Cheng sizeof (pattr.link_phys_speed), "%u", 3234da14cebeSEric Cheng (uint_t)((get_ifspeed(pattr.link_name, 3235da14cebeSEric Cheng islink)) / 1000000ull)); 3236da14cebeSEric Cheng (void) get_linkduplex(pattr.link_name, islink, 3237da14cebeSEric Cheng pattr.link_phys_duplex); 3238da14cebeSEric Cheng } else { 3239da14cebeSEric Cheng (void) snprintf(pattr.link_name, sizeof (pattr.link_name), 3240da14cebeSEric Cheng "%s", link); 3241da14cebeSEric Cheng (void) snprintf(pattr.link_flags, sizeof (pattr.link_flags), 3242da14cebeSEric Cheng "%c----", flags & DLADM_OPT_ACTIVE ? '-' : 'r'); 3243da14cebeSEric Cheng } 3244da14cebeSEric Cheng 3245da14cebeSEric Cheng if (!state->ls_parseable && !state->ls_printheader) { 3246da14cebeSEric Cheng print_header(&state->ls_print); 3247da14cebeSEric Cheng state->ls_printheader = B_TRUE; 3248da14cebeSEric Cheng } 3249da14cebeSEric Cheng 3250da14cebeSEric Cheng dladm_print_output(&state->ls_print, state->ls_parseable, 3251da14cebeSEric Cheng dladm_print_field, (void *)&pattr); 3252da14cebeSEric Cheng 3253da14cebeSEric Cheng done: 3254da14cebeSEric Cheng return (status); 3255da14cebeSEric Cheng } 3256da14cebeSEric Cheng 3257da14cebeSEric Cheng typedef struct { 3258da14cebeSEric Cheng show_state_t *ms_state; 3259da14cebeSEric Cheng char *ms_link; 3260da14cebeSEric Cheng dladm_macaddr_attr_t *ms_mac_attr; 3261da14cebeSEric Cheng } print_phys_mac_state_t; 3262da14cebeSEric Cheng 3263da14cebeSEric Cheng /* callback of dladm_print_output() */ 3264da14cebeSEric Cheng static char * 3265da14cebeSEric Cheng print_phys_one_mac_callback(print_field_t *pf, void *arg) 3266da14cebeSEric Cheng { 3267da14cebeSEric Cheng print_phys_mac_state_t *mac_state = arg; 3268da14cebeSEric Cheng dladm_macaddr_attr_t *attr = mac_state->ms_mac_attr; 3269da14cebeSEric Cheng static char buf[DLADM_STRSIZE]; 3270da14cebeSEric Cheng boolean_t is_primary = (attr->ma_slot == 0); 3271da14cebeSEric Cheng boolean_t is_parseable = mac_state->ms_state->ls_parseable; 3272da14cebeSEric Cheng 3273da14cebeSEric Cheng switch (pf->pf_index) { 3274da14cebeSEric Cheng case PHYS_M_LINK: 3275da14cebeSEric Cheng (void) snprintf(buf, sizeof (buf), "%s", 3276da14cebeSEric Cheng (is_primary || is_parseable) ? mac_state->ms_link : " "); 3277da14cebeSEric Cheng break; 3278da14cebeSEric Cheng case PHYS_M_SLOT: 3279da14cebeSEric Cheng if (is_primary) 3280da14cebeSEric Cheng (void) snprintf(buf, sizeof (buf), gettext("primary")); 3281da14cebeSEric Cheng else 3282da14cebeSEric Cheng (void) snprintf(buf, sizeof (buf), "%d", attr->ma_slot); 3283da14cebeSEric Cheng break; 3284da14cebeSEric Cheng case PHYS_M_ADDRESS: 3285da14cebeSEric Cheng (void) dladm_aggr_macaddr2str(attr->ma_addr, buf); 3286da14cebeSEric Cheng break; 3287da14cebeSEric Cheng case PHYS_M_INUSE: 3288da14cebeSEric Cheng (void) snprintf(buf, sizeof (buf), "%s", 3289da14cebeSEric Cheng attr->ma_flags & DLADM_MACADDR_USED ? gettext("yes") : 3290da14cebeSEric Cheng gettext("no")); 3291da14cebeSEric Cheng break; 3292da14cebeSEric Cheng case PHYS_M_CLIENT: 3293da14cebeSEric Cheng /* 3294da14cebeSEric Cheng * CR 6678526: resolve link id to actual link name if 3295da14cebeSEric Cheng * it is valid. 3296da14cebeSEric Cheng */ 3297da14cebeSEric Cheng (void) snprintf(buf, sizeof (buf), "%s", attr->ma_client_name); 3298da14cebeSEric Cheng break; 3299da14cebeSEric Cheng } 3300da14cebeSEric Cheng 3301da14cebeSEric Cheng return (buf); 3302da14cebeSEric Cheng } 3303da14cebeSEric Cheng 3304da14cebeSEric Cheng typedef struct { 3305da14cebeSEric Cheng show_state_t *hs_state; 3306da14cebeSEric Cheng char *hs_link; 3307da14cebeSEric Cheng dladm_hwgrp_attr_t *hs_grp_attr; 3308da14cebeSEric Cheng } print_phys_hwgrp_state_t; 3309da14cebeSEric Cheng 3310da14cebeSEric Cheng static char * 3311da14cebeSEric Cheng print_phys_one_hwgrp_callback(print_field_t *pf, void *arg) 3312da14cebeSEric Cheng { 3313da14cebeSEric Cheng print_phys_hwgrp_state_t *hg_state = arg; 3314da14cebeSEric Cheng dladm_hwgrp_attr_t *attr = hg_state->hs_grp_attr; 3315da14cebeSEric Cheng static char buf[DLADM_STRSIZE]; 3316da14cebeSEric Cheng 3317da14cebeSEric Cheng switch (pf->pf_index) { 3318da14cebeSEric Cheng case PHYS_H_LINK: 3319da14cebeSEric Cheng (void) snprintf(buf, sizeof (buf), "%s", attr->hg_link_name); 3320da14cebeSEric Cheng break; 3321da14cebeSEric Cheng case PHYS_H_GROUP: 3322da14cebeSEric Cheng (void) snprintf(buf, sizeof (buf), "%d", attr->hg_grp_num); 3323da14cebeSEric Cheng break; 3324da14cebeSEric Cheng case PHYS_H_GRPTYPE: 3325da14cebeSEric Cheng (void) snprintf(buf, sizeof (buf), "%s", 3326da14cebeSEric Cheng attr->hg_grp_type == DLADM_HWGRP_TYPE_RX ? "RX" : "TX"); 3327da14cebeSEric Cheng break; 3328da14cebeSEric Cheng case PHYS_H_RINGS: 3329da14cebeSEric Cheng (void) snprintf(buf, sizeof (buf), "%d", attr->hg_n_rings); 3330da14cebeSEric Cheng break; 3331da14cebeSEric Cheng case PHYS_H_CLIENTS: 3332da14cebeSEric Cheng if (attr->hg_client_names[0] == '\0') { 3333da14cebeSEric Cheng (void) snprintf(buf, sizeof (buf), "--"); 3334da14cebeSEric Cheng } else { 3335da14cebeSEric Cheng (void) snprintf(buf, sizeof (buf), "%s ", 3336da14cebeSEric Cheng attr->hg_client_names); 3337da14cebeSEric Cheng } 3338da14cebeSEric Cheng break; 3339da14cebeSEric Cheng } 3340da14cebeSEric Cheng 3341da14cebeSEric Cheng return (buf); 3342da14cebeSEric Cheng } 3343da14cebeSEric Cheng 3344da14cebeSEric Cheng /* callback of dladm_walk_macaddr, invoked for each MAC address slot */ 3345da14cebeSEric Cheng static boolean_t 3346da14cebeSEric Cheng print_phys_mac_callback(void *arg, dladm_macaddr_attr_t *attr) 3347da14cebeSEric Cheng { 3348da14cebeSEric Cheng print_phys_mac_state_t *mac_state = arg; 3349da14cebeSEric Cheng show_state_t *state = mac_state->ms_state; 3350da14cebeSEric Cheng 3351da14cebeSEric Cheng if (!state->ls_parseable && !state->ls_printheader) { 3352da14cebeSEric Cheng print_header(&state->ls_print); 3353da14cebeSEric Cheng state->ls_printheader = B_TRUE; 3354da14cebeSEric Cheng } 3355da14cebeSEric Cheng 3356da14cebeSEric Cheng mac_state->ms_mac_attr = attr; 3357da14cebeSEric Cheng dladm_print_output(&state->ls_print, state->ls_parseable, 3358da14cebeSEric Cheng print_phys_one_mac_callback, mac_state); 3359da14cebeSEric Cheng 3360da14cebeSEric Cheng return (B_TRUE); 3361da14cebeSEric Cheng } 3362da14cebeSEric Cheng 3363da14cebeSEric Cheng /* invoked by show-phys -m for each physical data-link */ 3364da14cebeSEric Cheng static dladm_status_t 3365da14cebeSEric Cheng print_phys_mac(show_state_t *state, datalink_id_t linkid, char *link) 3366da14cebeSEric Cheng { 3367da14cebeSEric Cheng print_phys_mac_state_t mac_state; 3368da14cebeSEric Cheng 3369da14cebeSEric Cheng mac_state.ms_state = state; 3370da14cebeSEric Cheng mac_state.ms_link = link; 3371da14cebeSEric Cheng 3372*4ac67f02SAnurag S. Maskey return (dladm_walk_macaddr(handle, linkid, &mac_state, 3373da14cebeSEric Cheng print_phys_mac_callback)); 3374da14cebeSEric Cheng } 3375da14cebeSEric Cheng 3376da14cebeSEric Cheng /* callback of dladm_walk_hwgrp, invoked for each MAC hwgrp */ 3377da14cebeSEric Cheng static boolean_t 3378da14cebeSEric Cheng print_phys_hwgrp_callback(void *arg, dladm_hwgrp_attr_t *attr) 3379da14cebeSEric Cheng { 3380da14cebeSEric Cheng print_phys_hwgrp_state_t *hwgrp_state = arg; 3381da14cebeSEric Cheng show_state_t *state = hwgrp_state->hs_state; 3382da14cebeSEric Cheng 3383da14cebeSEric Cheng if (!state->ls_parseable && !state->ls_printheader) { 3384da14cebeSEric Cheng print_header(&state->ls_print); 3385da14cebeSEric Cheng state->ls_printheader = B_TRUE; 3386da14cebeSEric Cheng } 3387da14cebeSEric Cheng hwgrp_state->hs_grp_attr = attr; 3388da14cebeSEric Cheng dladm_print_output(&state->ls_print, state->ls_parseable, 3389da14cebeSEric Cheng print_phys_one_hwgrp_callback, hwgrp_state); 3390da14cebeSEric Cheng 3391da14cebeSEric Cheng return (B_TRUE); 3392da14cebeSEric Cheng } 3393da14cebeSEric Cheng 3394da14cebeSEric Cheng /* invoked by show-phys -H for each physical data-link */ 3395da14cebeSEric Cheng static dladm_status_t 3396da14cebeSEric Cheng print_phys_hwgrp(show_state_t *state, datalink_id_t linkid, char *link) 3397da14cebeSEric Cheng { 3398da14cebeSEric Cheng print_phys_hwgrp_state_t hwgrp_state; 3399da14cebeSEric Cheng 3400da14cebeSEric Cheng hwgrp_state.hs_state = state; 3401da14cebeSEric Cheng hwgrp_state.hs_link = link; 3402*4ac67f02SAnurag S. Maskey return (dladm_walk_hwgrp(handle, linkid, &hwgrp_state, 3403da14cebeSEric Cheng print_phys_hwgrp_callback)); 3404da14cebeSEric Cheng } 3405d62bc4baSyz147064 3406d62bc4baSyz147064 static dladm_status_t 3407da14cebeSEric Cheng print_phys(show_state_t *state, datalink_id_t linkid) 3408d62bc4baSyz147064 { 3409d62bc4baSyz147064 char link[MAXLINKNAMELEN]; 3410d62bc4baSyz147064 uint32_t flags; 3411da14cebeSEric Cheng dladm_status_t status; 3412d62bc4baSyz147064 datalink_class_t class; 3413d62bc4baSyz147064 uint32_t media; 3414d62bc4baSyz147064 3415*4ac67f02SAnurag S. Maskey if ((status = dladm_datalink_id2info(handle, linkid, &flags, &class, 3416*4ac67f02SAnurag S. Maskey &media, link, MAXLINKNAMELEN)) != DLADM_STATUS_OK) { 3417d62bc4baSyz147064 goto done; 3418d62bc4baSyz147064 } 3419d62bc4baSyz147064 3420d62bc4baSyz147064 if (class != DATALINK_CLASS_PHYS) { 3421d62bc4baSyz147064 status = DLADM_STATUS_BADARG; 3422d62bc4baSyz147064 goto done; 3423d62bc4baSyz147064 } 3424d62bc4baSyz147064 3425d62bc4baSyz147064 if (!(state->ls_flags & flags)) { 3426d62bc4baSyz147064 status = DLADM_STATUS_NOTFOUND; 3427d62bc4baSyz147064 goto done; 3428d62bc4baSyz147064 } 3429d62bc4baSyz147064 3430da14cebeSEric Cheng if (state->ls_mac) 3431da14cebeSEric Cheng status = print_phys_mac(state, linkid, link); 3432da14cebeSEric Cheng else if (state->ls_hwgrp) 3433da14cebeSEric Cheng status = print_phys_hwgrp(state, linkid, link); 3434da14cebeSEric Cheng else 3435da14cebeSEric Cheng status = print_phys_default(state, linkid, link, flags, media); 3436d62bc4baSyz147064 3437d62bc4baSyz147064 done: 3438d62bc4baSyz147064 return (status); 3439d62bc4baSyz147064 } 3440d62bc4baSyz147064 3441*4ac67f02SAnurag S. Maskey /* ARGSUSED */ 3442d62bc4baSyz147064 static int 3443*4ac67f02SAnurag S. Maskey show_phys(dladm_handle_t dh, datalink_id_t linkid, void *arg) 3444d62bc4baSyz147064 { 3445d62bc4baSyz147064 show_state_t *state = arg; 3446d62bc4baSyz147064 3447da14cebeSEric Cheng state->ls_status = print_phys(state, linkid); 3448d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 3449d62bc4baSyz147064 } 3450d62bc4baSyz147064 3451d62bc4baSyz147064 /* 3452d62bc4baSyz147064 * Print the active topology information. 3453d62bc4baSyz147064 */ 3454d62bc4baSyz147064 static dladm_status_t 3455e7801d59Ssowmini print_vlan(show_state_t *state, datalink_id_t linkid, link_fields_buf_t *l) 3456d62bc4baSyz147064 { 3457d62bc4baSyz147064 dladm_vlan_attr_t vinfo; 3458d62bc4baSyz147064 uint32_t flags; 3459d62bc4baSyz147064 dladm_status_t status; 3460d62bc4baSyz147064 3461*4ac67f02SAnurag S. Maskey if ((status = dladm_datalink_id2info(handle, linkid, &flags, NULL, NULL, 3462e7801d59Ssowmini l->link_name, sizeof (l->link_name))) != DLADM_STATUS_OK) { 3463d62bc4baSyz147064 goto done; 3464d62bc4baSyz147064 } 3465d62bc4baSyz147064 3466d62bc4baSyz147064 if (!(state->ls_flags & flags)) { 3467d62bc4baSyz147064 status = DLADM_STATUS_NOTFOUND; 3468d62bc4baSyz147064 goto done; 3469d62bc4baSyz147064 } 3470d62bc4baSyz147064 3471*4ac67f02SAnurag S. Maskey if ((status = dladm_vlan_info(handle, linkid, &vinfo, 3472*4ac67f02SAnurag S. Maskey state->ls_flags)) != DLADM_STATUS_OK || 3473*4ac67f02SAnurag S. Maskey (status = dladm_datalink_id2info(handle, vinfo.dv_linkid, NULL, 3474*4ac67f02SAnurag S. Maskey NULL, NULL, l->link_over, sizeof (l->link_over))) != 3475*4ac67f02SAnurag S. Maskey DLADM_STATUS_OK) { 3476d62bc4baSyz147064 goto done; 3477d62bc4baSyz147064 } 3478d62bc4baSyz147064 3479e7801d59Ssowmini (void) snprintf(l->link_vlan_vid, sizeof (l->link_vlan_vid), "%d", 3480e7801d59Ssowmini vinfo.dv_vid); 3481da14cebeSEric Cheng (void) snprintf(l->link_flags, sizeof (l->link_flags), "%c----", 3482da14cebeSEric Cheng vinfo.dv_force ? 'f' : '-'); 3483d62bc4baSyz147064 3484d62bc4baSyz147064 done: 3485d62bc4baSyz147064 return (status); 3486d62bc4baSyz147064 } 3487d62bc4baSyz147064 3488*4ac67f02SAnurag S. Maskey /* ARGSUSED */ 3489d62bc4baSyz147064 static int 3490*4ac67f02SAnurag S. Maskey show_vlan(dladm_handle_t dh, datalink_id_t linkid, void *arg) 3491d62bc4baSyz147064 { 3492d62bc4baSyz147064 show_state_t *state = arg; 3493d62bc4baSyz147064 dladm_status_t status; 3494e7801d59Ssowmini link_fields_buf_t lbuf; 3495d62bc4baSyz147064 34965f5c9f54SAnurag S. Maskey bzero(&lbuf, sizeof (link_fields_buf_t)); 3497e7801d59Ssowmini status = print_vlan(state, linkid, &lbuf); 3498d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 3499d62bc4baSyz147064 goto done; 3500e7801d59Ssowmini 3501e7801d59Ssowmini if (!state->ls_parseable && !state->ls_printheader) { 3502e7801d59Ssowmini print_header(&state->ls_print); 3503e7801d59Ssowmini state->ls_printheader = B_TRUE; 3504e7801d59Ssowmini } 3505e7801d59Ssowmini 3506e7801d59Ssowmini dladm_print_output(&state->ls_print, state->ls_parseable, 3507e7801d59Ssowmini dladm_print_field, (void *)&lbuf); 3508d62bc4baSyz147064 3509d62bc4baSyz147064 done: 3510d62bc4baSyz147064 state->ls_status = status; 3511d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 3512d62bc4baSyz147064 } 3513d62bc4baSyz147064 3514d62bc4baSyz147064 static void 35158d5c46e6Sam223141 do_show_phys(int argc, char *argv[], const char *use) 3516d62bc4baSyz147064 { 3517d62bc4baSyz147064 int option; 3518d62bc4baSyz147064 uint32_t flags = DLADM_OPT_ACTIVE; 3519d62bc4baSyz147064 boolean_t p_arg = B_FALSE; 3520e7801d59Ssowmini boolean_t o_arg = B_FALSE; 3521da14cebeSEric Cheng boolean_t m_arg = B_FALSE; 3522da14cebeSEric Cheng boolean_t H_arg = B_FALSE; 3523d62bc4baSyz147064 datalink_id_t linkid = DATALINK_ALL_LINKID; 3524d62bc4baSyz147064 show_state_t state; 3525d62bc4baSyz147064 dladm_status_t status; 3526e7801d59Ssowmini char *fields_str = NULL; 3527e7801d59Ssowmini print_field_t **fields; 3528e7801d59Ssowmini uint_t nfields; 3529e7801d59Ssowmini char *all_active_fields = 3530e7801d59Ssowmini "link,media,state,speed,duplex,device"; 35315f5c9f54SAnurag S. Maskey char *all_inactive_fields = "link,device,media,flags"; 3532da14cebeSEric Cheng char *all_mac_fields = "link,slot,address,inuse,client"; 3533da14cebeSEric Cheng char *all_hwgrp_fields = 3534da14cebeSEric Cheng "link,group,grouptype,rings,clients"; 3535da14cebeSEric Cheng print_field_t *pf; 3536da14cebeSEric Cheng int pfmax; 3537d62bc4baSyz147064 3538e7801d59Ssowmini bzero(&state, sizeof (state)); 3539d62bc4baSyz147064 opterr = 0; 3540da14cebeSEric Cheng while ((option = getopt_long(argc, argv, ":pPo:mH", 3541d62bc4baSyz147064 show_lopts, NULL)) != -1) { 3542d62bc4baSyz147064 switch (option) { 3543d62bc4baSyz147064 case 'p': 3544d62bc4baSyz147064 if (p_arg) 3545d62bc4baSyz147064 die_optdup(option); 3546d62bc4baSyz147064 3547d62bc4baSyz147064 p_arg = B_TRUE; 3548d62bc4baSyz147064 break; 3549d62bc4baSyz147064 case 'P': 3550d62bc4baSyz147064 if (flags != DLADM_OPT_ACTIVE) 3551d62bc4baSyz147064 die_optdup(option); 3552d62bc4baSyz147064 3553d62bc4baSyz147064 flags = DLADM_OPT_PERSIST; 3554d62bc4baSyz147064 break; 3555e7801d59Ssowmini case 'o': 3556e7801d59Ssowmini o_arg = B_TRUE; 3557e7801d59Ssowmini fields_str = optarg; 3558e7801d59Ssowmini break; 3559da14cebeSEric Cheng case 'm': 3560da14cebeSEric Cheng m_arg = B_TRUE; 3561da14cebeSEric Cheng break; 3562da14cebeSEric Cheng case 'H': 3563da14cebeSEric Cheng H_arg = B_TRUE; 3564da14cebeSEric Cheng break; 3565d62bc4baSyz147064 default: 35668d5c46e6Sam223141 die_opterr(optopt, option, use); 3567d62bc4baSyz147064 break; 3568d62bc4baSyz147064 } 3569d62bc4baSyz147064 } 3570d62bc4baSyz147064 35710d365605Sschuster if (p_arg && !o_arg) 35720d365605Sschuster die("-p requires -o"); 35730d365605Sschuster 3574da14cebeSEric Cheng if (m_arg && H_arg) 3575da14cebeSEric Cheng die("-m cannot combine with -H"); 3576da14cebeSEric Cheng 35770d365605Sschuster if (p_arg && strcasecmp(fields_str, "all") == 0) 35780d365605Sschuster die("\"-o all\" is invalid with -p"); 35790d365605Sschuster 3580d62bc4baSyz147064 /* get link name (optional last argument) */ 3581d62bc4baSyz147064 if (optind == (argc-1)) { 3582*4ac67f02SAnurag S. Maskey if ((status = dladm_name2info(handle, argv[optind], &linkid, 3583*4ac67f02SAnurag S. Maskey NULL, NULL, NULL)) != DLADM_STATUS_OK) { 3584d62bc4baSyz147064 die_dlerr(status, "link %s is not valid", argv[optind]); 3585d62bc4baSyz147064 } 3586d62bc4baSyz147064 } else if (optind != argc) { 3587d62bc4baSyz147064 usage(); 3588d62bc4baSyz147064 } 3589d62bc4baSyz147064 3590d62bc4baSyz147064 state.ls_parseable = p_arg; 3591d62bc4baSyz147064 state.ls_flags = flags; 3592d62bc4baSyz147064 state.ls_donefirst = B_FALSE; 3593da14cebeSEric Cheng state.ls_mac = m_arg; 3594da14cebeSEric Cheng state.ls_hwgrp = H_arg; 3595d62bc4baSyz147064 3596da14cebeSEric Cheng if (m_arg && !(flags & DLADM_OPT_ACTIVE)) { 3597da14cebeSEric Cheng /* 3598da14cebeSEric Cheng * We can only display the factory MAC addresses of 3599da14cebeSEric Cheng * active data-links. 3600da14cebeSEric Cheng */ 3601da14cebeSEric Cheng die("-m not compatible with -P"); 3602e7801d59Ssowmini } 3603e7801d59Ssowmini 3604da14cebeSEric Cheng if (!o_arg || (o_arg && strcasecmp(fields_str, "all") == 0)) { 3605da14cebeSEric Cheng if (state.ls_mac) 3606da14cebeSEric Cheng fields_str = all_mac_fields; 3607da14cebeSEric Cheng else if (state.ls_hwgrp) 3608da14cebeSEric Cheng fields_str = all_hwgrp_fields; 3609da14cebeSEric Cheng else if (state.ls_flags & DLADM_OPT_ACTIVE) { 3610da14cebeSEric Cheng fields_str = all_active_fields; 3611da14cebeSEric Cheng } else { 3612da14cebeSEric Cheng fields_str = all_inactive_fields; 3613da14cebeSEric Cheng } 3614da14cebeSEric Cheng } 3615da14cebeSEric Cheng 3616da14cebeSEric Cheng if (state.ls_mac) { 3617da14cebeSEric Cheng pf = phys_m_fields; 3618da14cebeSEric Cheng pfmax = PHYS_M_MAX_FIELDS; 3619da14cebeSEric Cheng } else if (state.ls_hwgrp) { 3620da14cebeSEric Cheng pf = phys_h_fields; 3621da14cebeSEric Cheng pfmax = PHYS_H_MAX_FIELDS; 3622da14cebeSEric Cheng } else { 3623da14cebeSEric Cheng pf = phys_fields; 3624da14cebeSEric Cheng pfmax = PHYS_MAX_FIELDS; 3625da14cebeSEric Cheng } 3626da14cebeSEric Cheng 3627da14cebeSEric Cheng fields = parse_output_fields(fields_str, pf, 3628da14cebeSEric Cheng pfmax, CMD_TYPE_ANY, &nfields); 3629e7801d59Ssowmini 3630e7801d59Ssowmini if (fields == NULL) { 3631e7801d59Ssowmini die("invalid field(s) specified"); 3632e7801d59Ssowmini return; 3633e7801d59Ssowmini } 3634e7801d59Ssowmini 3635e7801d59Ssowmini state.ls_print.ps_fields = fields; 3636e7801d59Ssowmini state.ls_print.ps_nfields = nfields; 3637e7801d59Ssowmini 3638d62bc4baSyz147064 if (linkid == DATALINK_ALL_LINKID) { 3639*4ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(show_phys, handle, &state, 3640d62bc4baSyz147064 DATALINK_CLASS_PHYS, DATALINK_ANY_MEDIATYPE, flags); 3641d62bc4baSyz147064 } else { 3642*4ac67f02SAnurag S. Maskey (void) show_phys(handle, linkid, &state); 3643d62bc4baSyz147064 if (state.ls_status != DLADM_STATUS_OK) { 3644d62bc4baSyz147064 die_dlerr(state.ls_status, 3645d62bc4baSyz147064 "failed to show physical link %s", argv[optind]); 3646d62bc4baSyz147064 } 3647d62bc4baSyz147064 } 3648d62bc4baSyz147064 } 3649d62bc4baSyz147064 3650d62bc4baSyz147064 static void 36518d5c46e6Sam223141 do_show_vlan(int argc, char *argv[], const char *use) 3652d62bc4baSyz147064 { 3653d62bc4baSyz147064 int option; 3654d62bc4baSyz147064 uint32_t flags = DLADM_OPT_ACTIVE; 3655d62bc4baSyz147064 boolean_t p_arg = B_FALSE; 3656d62bc4baSyz147064 datalink_id_t linkid = DATALINK_ALL_LINKID; 3657d62bc4baSyz147064 show_state_t state; 3658d62bc4baSyz147064 dladm_status_t status; 3659e7801d59Ssowmini boolean_t o_arg = B_FALSE; 3660e7801d59Ssowmini char *fields_str = NULL; 3661e7801d59Ssowmini print_field_t **fields; 3662e7801d59Ssowmini uint_t nfields; 3663e7801d59Ssowmini char *all_fields = "link,vid,over,flags"; 3664e7801d59Ssowmini 3665e7801d59Ssowmini bzero(&state, sizeof (state)); 3666d62bc4baSyz147064 3667d62bc4baSyz147064 opterr = 0; 3668e7801d59Ssowmini while ((option = getopt_long(argc, argv, ":pPo:", 3669d62bc4baSyz147064 show_lopts, NULL)) != -1) { 3670d62bc4baSyz147064 switch (option) { 3671d62bc4baSyz147064 case 'p': 3672d62bc4baSyz147064 if (p_arg) 3673d62bc4baSyz147064 die_optdup(option); 3674d62bc4baSyz147064 3675d62bc4baSyz147064 p_arg = B_TRUE; 3676d62bc4baSyz147064 break; 3677d62bc4baSyz147064 case 'P': 3678d62bc4baSyz147064 if (flags != DLADM_OPT_ACTIVE) 3679d62bc4baSyz147064 die_optdup(option); 3680d62bc4baSyz147064 3681d62bc4baSyz147064 flags = DLADM_OPT_PERSIST; 3682d62bc4baSyz147064 break; 3683e7801d59Ssowmini case 'o': 3684e7801d59Ssowmini o_arg = B_TRUE; 3685e7801d59Ssowmini fields_str = optarg; 3686e7801d59Ssowmini break; 3687d62bc4baSyz147064 default: 36888d5c46e6Sam223141 die_opterr(optopt, option, use); 3689d62bc4baSyz147064 break; 3690d62bc4baSyz147064 } 3691d62bc4baSyz147064 } 3692d62bc4baSyz147064 36930d365605Sschuster if (p_arg && !o_arg) 36940d365605Sschuster die("-p requires -o"); 36950d365605Sschuster 36960d365605Sschuster if (p_arg && strcasecmp(fields_str, "all") == 0) 36970d365605Sschuster die("\"-o all\" is invalid with -p"); 36980d365605Sschuster 3699d62bc4baSyz147064 /* get link name (optional last argument) */ 3700d62bc4baSyz147064 if (optind == (argc-1)) { 3701*4ac67f02SAnurag S. Maskey if ((status = dladm_name2info(handle, argv[optind], &linkid, 3702*4ac67f02SAnurag S. Maskey NULL, NULL, NULL)) != DLADM_STATUS_OK) { 3703d62bc4baSyz147064 die_dlerr(status, "link %s is not valid", argv[optind]); 3704d62bc4baSyz147064 } 3705d62bc4baSyz147064 } else if (optind != argc) { 3706d62bc4baSyz147064 usage(); 3707d62bc4baSyz147064 } 3708d62bc4baSyz147064 3709d62bc4baSyz147064 state.ls_parseable = p_arg; 3710d62bc4baSyz147064 state.ls_flags = flags; 3711d62bc4baSyz147064 state.ls_donefirst = B_FALSE; 3712d62bc4baSyz147064 3713e7801d59Ssowmini if (!o_arg || (o_arg && strcasecmp(fields_str, "all") == 0)) 3714e7801d59Ssowmini fields_str = all_fields; 3715e7801d59Ssowmini 3716e7801d59Ssowmini fields = parse_output_fields(fields_str, vlan_fields, VLAN_MAX_FIELDS, 3717e7801d59Ssowmini CMD_TYPE_ANY, &nfields); 3718e7801d59Ssowmini 3719e7801d59Ssowmini if (fields == NULL) { 3720e7801d59Ssowmini die("invalid field(s) specified"); 3721e7801d59Ssowmini return; 3722e7801d59Ssowmini } 3723e7801d59Ssowmini state.ls_print.ps_fields = fields; 3724e7801d59Ssowmini state.ls_print.ps_nfields = nfields; 3725e7801d59Ssowmini 3726d62bc4baSyz147064 if (linkid == DATALINK_ALL_LINKID) { 3727*4ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(show_vlan, handle, &state, 3728d62bc4baSyz147064 DATALINK_CLASS_VLAN, DATALINK_ANY_MEDIATYPE, flags); 3729d62bc4baSyz147064 } else { 3730*4ac67f02SAnurag S. Maskey (void) show_vlan(handle, linkid, &state); 3731d62bc4baSyz147064 if (state.ls_status != DLADM_STATUS_OK) { 3732d62bc4baSyz147064 die_dlerr(state.ls_status, "failed to show vlan %s", 3733d62bc4baSyz147064 argv[optind]); 3734d62bc4baSyz147064 } 3735d62bc4baSyz147064 } 3736d62bc4baSyz147064 } 3737d62bc4baSyz147064 3738d62bc4baSyz147064 static void 3739da14cebeSEric Cheng do_create_vnic(int argc, char *argv[], const char *use) 3740da14cebeSEric Cheng { 3741da14cebeSEric Cheng datalink_id_t linkid, dev_linkid; 3742da14cebeSEric Cheng char devname[MAXLINKNAMELEN]; 3743da14cebeSEric Cheng char name[MAXLINKNAMELEN]; 3744da14cebeSEric Cheng boolean_t l_arg = B_FALSE; 3745da14cebeSEric Cheng uint32_t flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST; 3746da14cebeSEric Cheng char *altroot = NULL; 3747da14cebeSEric Cheng char option; 3748da14cebeSEric Cheng char *endp = NULL; 3749da14cebeSEric Cheng dladm_status_t status; 3750da14cebeSEric Cheng vnic_mac_addr_type_t mac_addr_type = VNIC_MAC_ADDR_TYPE_AUTO; 3751da14cebeSEric Cheng uchar_t *mac_addr; 3752da14cebeSEric Cheng int mac_slot = -1, maclen = 0, mac_prefix_len = 0; 3753da14cebeSEric Cheng dladm_arg_list_t *proplist = NULL; 3754da14cebeSEric Cheng uint16_t vid = 0; 3755da14cebeSEric Cheng 3756da14cebeSEric Cheng opterr = 0; 3757da14cebeSEric Cheng while ((option = getopt_long(argc, argv, ":tfR:l:m:n:p:r:v:H", 3758da14cebeSEric Cheng vnic_lopts, NULL)) != -1) { 3759da14cebeSEric Cheng switch (option) { 3760da14cebeSEric Cheng case 't': 3761da14cebeSEric Cheng flags &= ~DLADM_OPT_PERSIST; 3762da14cebeSEric Cheng break; 3763da14cebeSEric Cheng case 'R': 3764da14cebeSEric Cheng altroot = optarg; 3765da14cebeSEric Cheng break; 3766da14cebeSEric Cheng case 'l': 3767da14cebeSEric Cheng if (strlcpy(devname, optarg, MAXLINKNAMELEN) >= 3768da14cebeSEric Cheng MAXLINKNAMELEN) 3769da14cebeSEric Cheng die("link name too long"); 3770da14cebeSEric Cheng l_arg = B_TRUE; 3771da14cebeSEric Cheng break; 3772da14cebeSEric Cheng case 'm': 3773da14cebeSEric Cheng if (strcmp(optarg, "fixed") == 0) { 3774da14cebeSEric Cheng /* 3775da14cebeSEric Cheng * A fixed MAC address must be specified 3776da14cebeSEric Cheng * by its value, not by the keyword 'fixed'. 3777da14cebeSEric Cheng */ 3778da14cebeSEric Cheng die("'fixed' is not a valid MAC address"); 3779da14cebeSEric Cheng } 3780da14cebeSEric Cheng if (dladm_vnic_str2macaddrtype(optarg, 3781da14cebeSEric Cheng &mac_addr_type) != DLADM_STATUS_OK) { 3782da14cebeSEric Cheng mac_addr_type = VNIC_MAC_ADDR_TYPE_FIXED; 3783da14cebeSEric Cheng /* MAC address specified by value */ 3784da14cebeSEric Cheng mac_addr = _link_aton(optarg, &maclen); 3785da14cebeSEric Cheng if (mac_addr == NULL) { 3786da14cebeSEric Cheng if (maclen == -1) 3787da14cebeSEric Cheng die("invalid MAC address"); 3788da14cebeSEric Cheng else 3789da14cebeSEric Cheng die("out of memory"); 3790da14cebeSEric Cheng } 3791da14cebeSEric Cheng } 3792da14cebeSEric Cheng break; 3793da14cebeSEric Cheng case 'n': 3794da14cebeSEric Cheng errno = 0; 3795da14cebeSEric Cheng mac_slot = (int)strtol(optarg, &endp, 10); 3796da14cebeSEric Cheng if (errno != 0 || *endp != '\0') 3797da14cebeSEric Cheng die("invalid slot number"); 3798da14cebeSEric Cheng break; 3799da14cebeSEric Cheng case 'p': 3800da14cebeSEric Cheng if (dladm_parse_link_props(optarg, &proplist, B_FALSE) 3801da14cebeSEric Cheng != DLADM_STATUS_OK) 3802da14cebeSEric Cheng die("invalid vnic property"); 3803da14cebeSEric Cheng break; 3804da14cebeSEric Cheng case 'r': 3805da14cebeSEric Cheng mac_addr = _link_aton(optarg, &mac_prefix_len); 3806da14cebeSEric Cheng if (mac_addr == NULL) { 3807da14cebeSEric Cheng if (mac_prefix_len == -1) 3808da14cebeSEric Cheng die("invalid MAC address"); 3809da14cebeSEric Cheng else 3810da14cebeSEric Cheng die("out of memory"); 3811da14cebeSEric Cheng } 3812da14cebeSEric Cheng break; 3813da14cebeSEric Cheng case 'v': 3814da14cebeSEric Cheng vid = (int)strtol(optarg, &endp, 10); 3815da14cebeSEric Cheng if (errno != 0 || *endp != '\0' || vid == 0) 3816da14cebeSEric Cheng /* VID of 0 is invalid */ 3817da14cebeSEric Cheng die("invalid VLAN id"); 3818da14cebeSEric Cheng break; 3819da14cebeSEric Cheng case 'f': 3820da14cebeSEric Cheng flags |= DLADM_OPT_FORCE; 3821da14cebeSEric Cheng break; 3822da14cebeSEric Cheng case 'H': 3823da14cebeSEric Cheng flags |= DLADM_OPT_HWRINGS; 3824da14cebeSEric Cheng break; 3825da14cebeSEric Cheng default: 3826da14cebeSEric Cheng die_opterr(optopt, option, use); 3827da14cebeSEric Cheng } 3828da14cebeSEric Cheng } 3829da14cebeSEric Cheng 3830da14cebeSEric Cheng /* 3831da14cebeSEric Cheng * 'f' - force, flag can be specified only with 'v' - vlan. 3832da14cebeSEric Cheng */ 3833da14cebeSEric Cheng if ((flags & DLADM_OPT_FORCE) != 0 && vid == 0) 3834da14cebeSEric Cheng die("-f option can only be used with -v"); 3835da14cebeSEric Cheng 3836da14cebeSEric Cheng if (mac_prefix_len != 0 && mac_addr_type != VNIC_MAC_ADDR_TYPE_RANDOM && 3837da14cebeSEric Cheng mac_addr_type != VNIC_MAC_ADDR_TYPE_FIXED) 3838da14cebeSEric Cheng usage(); 3839da14cebeSEric Cheng 3840da14cebeSEric Cheng /* check required options */ 3841da14cebeSEric Cheng if (!l_arg) 3842da14cebeSEric Cheng usage(); 3843da14cebeSEric Cheng 3844da14cebeSEric Cheng if (mac_slot != -1 && mac_addr_type != VNIC_MAC_ADDR_TYPE_FACTORY) 3845da14cebeSEric Cheng usage(); 3846da14cebeSEric Cheng 3847da14cebeSEric Cheng /* the VNIC id is the required operand */ 3848da14cebeSEric Cheng if (optind != (argc - 1)) 3849da14cebeSEric Cheng usage(); 3850da14cebeSEric Cheng 3851da14cebeSEric Cheng if (strlcpy(name, argv[optind], MAXLINKNAMELEN) >= MAXLINKNAMELEN) 3852da14cebeSEric Cheng die("link name too long '%s'", argv[optind]); 3853da14cebeSEric Cheng 3854da14cebeSEric Cheng if (!dladm_valid_linkname(name)) 3855da14cebeSEric Cheng die("invalid link name '%s'", argv[optind]); 3856da14cebeSEric Cheng 3857da14cebeSEric Cheng if (altroot != NULL) 3858da14cebeSEric Cheng altroot_cmd(altroot, argc, argv); 3859da14cebeSEric Cheng 3860*4ac67f02SAnurag S. Maskey if (dladm_name2info(handle, devname, &dev_linkid, NULL, NULL, NULL) != 3861da14cebeSEric Cheng DLADM_STATUS_OK) 3862da14cebeSEric Cheng die("invalid link name '%s'", devname); 3863da14cebeSEric Cheng 3864*4ac67f02SAnurag S. Maskey status = dladm_vnic_create(handle, name, dev_linkid, mac_addr_type, 3865*4ac67f02SAnurag S. Maskey mac_addr, maclen, &mac_slot, mac_prefix_len, vid, &linkid, proplist, 3866*4ac67f02SAnurag S. Maskey flags); 3867da14cebeSEric Cheng if (status != DLADM_STATUS_OK) 3868da14cebeSEric Cheng die_dlerr(status, "vnic creation over %s failed", devname); 3869da14cebeSEric Cheng 3870da14cebeSEric Cheng dladm_free_props(proplist); 3871da14cebeSEric Cheng } 3872da14cebeSEric Cheng 3873da14cebeSEric Cheng static void 3874da14cebeSEric Cheng do_etherstub_check(const char *name, datalink_id_t linkid, boolean_t etherstub, 3875da14cebeSEric Cheng uint32_t flags) 3876da14cebeSEric Cheng { 3877da14cebeSEric Cheng boolean_t is_etherstub; 3878da14cebeSEric Cheng dladm_vnic_attr_t attr; 3879da14cebeSEric Cheng 3880*4ac67f02SAnurag S. Maskey if (dladm_vnic_info(handle, linkid, &attr, flags) != DLADM_STATUS_OK) { 3881da14cebeSEric Cheng /* 3882da14cebeSEric Cheng * Let the delete continue anyway. 3883da14cebeSEric Cheng */ 3884da14cebeSEric Cheng return; 3885da14cebeSEric Cheng } 3886da14cebeSEric Cheng is_etherstub = (attr.va_link_id == DATALINK_INVALID_LINKID); 3887da14cebeSEric Cheng if (is_etherstub != etherstub) { 3888da14cebeSEric Cheng die("'%s' is not %s", name, 3889da14cebeSEric Cheng (is_etherstub ? "a vnic" : "an etherstub")); 3890da14cebeSEric Cheng } 3891da14cebeSEric Cheng } 3892da14cebeSEric Cheng 3893da14cebeSEric Cheng static void 3894da14cebeSEric Cheng do_delete_vnic_common(int argc, char *argv[], const char *use, 3895da14cebeSEric Cheng boolean_t etherstub) 3896da14cebeSEric Cheng { 3897da14cebeSEric Cheng char option; 3898da14cebeSEric Cheng uint32_t flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST; 3899da14cebeSEric Cheng datalink_id_t linkid; 3900da14cebeSEric Cheng char *altroot = NULL; 3901da14cebeSEric Cheng dladm_status_t status; 3902da14cebeSEric Cheng 3903da14cebeSEric Cheng opterr = 0; 3904da14cebeSEric Cheng while ((option = getopt_long(argc, argv, ":R:t", lopts, 3905da14cebeSEric Cheng NULL)) != -1) { 3906da14cebeSEric Cheng switch (option) { 3907da14cebeSEric Cheng case 't': 3908da14cebeSEric Cheng flags &= ~DLADM_OPT_PERSIST; 3909da14cebeSEric Cheng break; 3910da14cebeSEric Cheng case 'R': 3911da14cebeSEric Cheng altroot = optarg; 3912da14cebeSEric Cheng break; 3913da14cebeSEric Cheng default: 3914da14cebeSEric Cheng die_opterr(optopt, option, use); 3915da14cebeSEric Cheng } 3916da14cebeSEric Cheng } 3917da14cebeSEric Cheng 3918da14cebeSEric Cheng /* get vnic name (required last argument) */ 3919da14cebeSEric Cheng if (optind != (argc - 1)) 3920da14cebeSEric Cheng usage(); 3921da14cebeSEric Cheng 3922da14cebeSEric Cheng if (altroot != NULL) 3923da14cebeSEric Cheng altroot_cmd(altroot, argc, argv); 3924da14cebeSEric Cheng 3925*4ac67f02SAnurag S. Maskey status = dladm_name2info(handle, argv[optind], &linkid, NULL, NULL, 3926*4ac67f02SAnurag S. Maskey NULL); 3927da14cebeSEric Cheng if (status != DLADM_STATUS_OK) 3928da14cebeSEric Cheng die("invalid link name '%s'", argv[optind]); 3929da14cebeSEric Cheng 3930da14cebeSEric Cheng if ((flags & DLADM_OPT_ACTIVE) != 0) { 3931da14cebeSEric Cheng do_etherstub_check(argv[optind], linkid, etherstub, 3932da14cebeSEric Cheng DLADM_OPT_ACTIVE); 3933da14cebeSEric Cheng } 3934da14cebeSEric Cheng if ((flags & DLADM_OPT_PERSIST) != 0) { 3935da14cebeSEric Cheng do_etherstub_check(argv[optind], linkid, etherstub, 3936da14cebeSEric Cheng DLADM_OPT_PERSIST); 3937da14cebeSEric Cheng } 3938da14cebeSEric Cheng 3939*4ac67f02SAnurag S. Maskey status = dladm_vnic_delete(handle, linkid, flags); 3940da14cebeSEric Cheng if (status != DLADM_STATUS_OK) 3941da14cebeSEric Cheng die_dlerr(status, "vnic deletion failed"); 3942da14cebeSEric Cheng } 3943da14cebeSEric Cheng 3944da14cebeSEric Cheng static void 3945da14cebeSEric Cheng do_delete_vnic(int argc, char *argv[], const char *use) 3946da14cebeSEric Cheng { 3947da14cebeSEric Cheng do_delete_vnic_common(argc, argv, use, B_FALSE); 3948da14cebeSEric Cheng } 3949da14cebeSEric Cheng 3950da14cebeSEric Cheng /* ARGSUSED */ 3951da14cebeSEric Cheng static void 3952da14cebeSEric Cheng do_up_vnic_common(int argc, char *argv[], const char *use, boolean_t vlan) 3953da14cebeSEric Cheng { 3954da14cebeSEric Cheng datalink_id_t linkid = DATALINK_ALL_LINKID; 3955da14cebeSEric Cheng dladm_status_t status; 3956da14cebeSEric Cheng char *type; 3957da14cebeSEric Cheng 3958da14cebeSEric Cheng type = vlan ? "vlan" : "vnic"; 3959da14cebeSEric Cheng 3960da14cebeSEric Cheng /* 3961da14cebeSEric Cheng * get the id or the name of the vnic/vlan (optional last argument) 3962da14cebeSEric Cheng */ 3963da14cebeSEric Cheng if (argc == 2) { 3964*4ac67f02SAnurag S. Maskey status = dladm_name2info(handle, argv[1], &linkid, NULL, NULL, 3965*4ac67f02SAnurag S. Maskey NULL); 3966da14cebeSEric Cheng if (status != DLADM_STATUS_OK) 3967da14cebeSEric Cheng goto done; 3968da14cebeSEric Cheng 3969da14cebeSEric Cheng } else if (argc > 2) { 3970da14cebeSEric Cheng usage(); 3971da14cebeSEric Cheng } 3972da14cebeSEric Cheng 3973da14cebeSEric Cheng if (vlan) 3974*4ac67f02SAnurag S. Maskey status = dladm_vlan_up(handle, linkid); 3975da14cebeSEric Cheng else 3976*4ac67f02SAnurag S. Maskey status = dladm_vnic_up(handle, linkid, 0); 3977da14cebeSEric Cheng 3978da14cebeSEric Cheng done: 3979da14cebeSEric Cheng if (status != DLADM_STATUS_OK) { 3980da14cebeSEric Cheng if (argc == 2) { 3981da14cebeSEric Cheng die_dlerr(status, 3982da14cebeSEric Cheng "could not bring up %s '%s'", type, argv[1]); 3983da14cebeSEric Cheng } else { 3984da14cebeSEric Cheng die_dlerr(status, "could not bring %ss up", type); 3985da14cebeSEric Cheng } 3986da14cebeSEric Cheng } 3987da14cebeSEric Cheng } 3988da14cebeSEric Cheng 3989da14cebeSEric Cheng static void 3990da14cebeSEric Cheng do_up_vnic(int argc, char *argv[], const char *use) 3991da14cebeSEric Cheng { 3992da14cebeSEric Cheng do_up_vnic_common(argc, argv, use, B_FALSE); 3993da14cebeSEric Cheng } 3994da14cebeSEric Cheng 3995da14cebeSEric Cheng static void 3996da14cebeSEric Cheng dump_vnics_head(const char *dev) 3997da14cebeSEric Cheng { 3998da14cebeSEric Cheng if (strlen(dev)) 3999da14cebeSEric Cheng (void) printf("%s", dev); 4000da14cebeSEric Cheng 4001da14cebeSEric Cheng (void) printf("\tipackets rbytes opackets obytes "); 4002da14cebeSEric Cheng 4003da14cebeSEric Cheng if (strlen(dev)) 4004da14cebeSEric Cheng (void) printf("%%ipkts %%opkts\n"); 4005da14cebeSEric Cheng else 4006da14cebeSEric Cheng (void) printf("\n"); 4007da14cebeSEric Cheng } 4008da14cebeSEric Cheng 4009da14cebeSEric Cheng static void 4010da14cebeSEric Cheng dump_vnic_stat(const char *name, datalink_id_t vnic_id, 4011da14cebeSEric Cheng show_vnic_state_t *state, pktsum_t *vnic_stats, pktsum_t *tot_stats) 4012da14cebeSEric Cheng { 4013da14cebeSEric Cheng pktsum_t diff_stats; 4014da14cebeSEric Cheng pktsum_t *old_stats = &state->vs_prevstats[vnic_id]; 4015da14cebeSEric Cheng 4016da14cebeSEric Cheng dladm_stats_diff(&diff_stats, vnic_stats, old_stats); 4017da14cebeSEric Cheng 4018da14cebeSEric Cheng (void) printf("%s", name); 4019da14cebeSEric Cheng 4020da14cebeSEric Cheng (void) printf("\t%-10llu", diff_stats.ipackets); 4021da14cebeSEric Cheng (void) printf("%-12llu", diff_stats.rbytes); 4022da14cebeSEric Cheng (void) printf("%-10llu", diff_stats.opackets); 4023da14cebeSEric Cheng (void) printf("%-12llu", diff_stats.obytes); 4024da14cebeSEric Cheng 4025da14cebeSEric Cheng if (tot_stats) { 4026da14cebeSEric Cheng if (tot_stats->ipackets == 0) { 4027da14cebeSEric Cheng (void) printf("\t-"); 4028da14cebeSEric Cheng } else { 4029da14cebeSEric Cheng (void) printf("\t%-6.1f", (double)diff_stats.ipackets/ 4030da14cebeSEric Cheng (double)tot_stats->ipackets * 100); 4031da14cebeSEric Cheng } 4032da14cebeSEric Cheng if (tot_stats->opackets == 0) { 4033da14cebeSEric Cheng (void) printf("\t-"); 4034da14cebeSEric Cheng } else { 4035da14cebeSEric Cheng (void) printf("\t%-6.1f", (double)diff_stats.opackets/ 4036da14cebeSEric Cheng (double)tot_stats->opackets * 100); 4037da14cebeSEric Cheng } 4038da14cebeSEric Cheng } 4039da14cebeSEric Cheng (void) printf("\n"); 4040da14cebeSEric Cheng 4041da14cebeSEric Cheng *old_stats = *vnic_stats; 4042da14cebeSEric Cheng } 4043da14cebeSEric Cheng 4044da14cebeSEric Cheng /* 4045da14cebeSEric Cheng * Called from the walker dladm_vnic_walk_sys() for each vnic to display 4046da14cebeSEric Cheng * vnic information or statistics. 4047da14cebeSEric Cheng */ 4048da14cebeSEric Cheng static dladm_status_t 4049da14cebeSEric Cheng print_vnic(show_vnic_state_t *state, datalink_id_t linkid) 4050da14cebeSEric Cheng { 4051da14cebeSEric Cheng dladm_vnic_attr_t attr, *vnic = &attr; 4052da14cebeSEric Cheng dladm_status_t status; 4053da14cebeSEric Cheng boolean_t is_etherstub; 4054da14cebeSEric Cheng char devname[MAXLINKNAMELEN]; 4055da14cebeSEric Cheng char vnic_name[MAXLINKNAMELEN]; 4056da14cebeSEric Cheng char mstr[MAXMACADDRLEN * 3]; 4057da14cebeSEric Cheng vnic_fields_buf_t vbuf; 4058da14cebeSEric Cheng 4059*4ac67f02SAnurag S. Maskey if ((status = dladm_vnic_info(handle, linkid, vnic, state->vs_flags)) != 4060da14cebeSEric Cheng DLADM_STATUS_OK) 4061da14cebeSEric Cheng return (status); 4062da14cebeSEric Cheng 4063da14cebeSEric Cheng is_etherstub = (vnic->va_link_id == DATALINK_INVALID_LINKID); 4064da14cebeSEric Cheng if (state->vs_etherstub != is_etherstub) { 4065da14cebeSEric Cheng /* 4066da14cebeSEric Cheng * Want all etherstub but it's not one, or want 4067da14cebeSEric Cheng * non-etherstub and it's one. 4068da14cebeSEric Cheng */ 4069da14cebeSEric Cheng return (DLADM_STATUS_OK); 4070da14cebeSEric Cheng } 4071da14cebeSEric Cheng 4072da14cebeSEric Cheng if (state->vs_link_id != DATALINK_ALL_LINKID) { 4073da14cebeSEric Cheng if (state->vs_link_id != vnic->va_link_id) 4074da14cebeSEric Cheng return (DLADM_STATUS_OK); 4075da14cebeSEric Cheng } 4076da14cebeSEric Cheng 4077*4ac67f02SAnurag S. Maskey if (dladm_datalink_id2info(handle, linkid, NULL, NULL, 4078da14cebeSEric Cheng NULL, vnic_name, sizeof (vnic_name)) != DLADM_STATUS_OK) 4079da14cebeSEric Cheng return (DLADM_STATUS_BADARG); 4080da14cebeSEric Cheng 4081da14cebeSEric Cheng bzero(devname, sizeof (devname)); 4082da14cebeSEric Cheng if (!is_etherstub && 4083*4ac67f02SAnurag S. Maskey dladm_datalink_id2info(handle, vnic->va_link_id, NULL, NULL, 4084da14cebeSEric Cheng NULL, devname, sizeof (devname)) != DLADM_STATUS_OK) 4085da14cebeSEric Cheng return (DLADM_STATUS_BADARG); 4086da14cebeSEric Cheng 4087da14cebeSEric Cheng state->vs_found = B_TRUE; 4088da14cebeSEric Cheng if (state->vs_stats) { 4089da14cebeSEric Cheng /* print vnic statistics */ 4090da14cebeSEric Cheng pktsum_t vnic_stats; 4091da14cebeSEric Cheng 4092da14cebeSEric Cheng if (state->vs_firstonly) { 4093da14cebeSEric Cheng if (state->vs_donefirst) 4094da14cebeSEric Cheng return (0); 4095da14cebeSEric Cheng state->vs_donefirst = B_TRUE; 4096da14cebeSEric Cheng } 4097da14cebeSEric Cheng 4098da14cebeSEric Cheng if (!state->vs_printstats) { 4099da14cebeSEric Cheng /* 4100da14cebeSEric Cheng * get vnic statistics and add to the sum for the 4101da14cebeSEric Cheng * named device. 4102da14cebeSEric Cheng */ 4103da14cebeSEric Cheng get_link_stats(vnic_name, &vnic_stats); 4104da14cebeSEric Cheng dladm_stats_total(&state->vs_totalstats, &vnic_stats, 4105da14cebeSEric Cheng &state->vs_prevstats[vnic->va_vnic_id]); 4106da14cebeSEric Cheng } else { 4107da14cebeSEric Cheng /* get and print vnic statistics */ 4108da14cebeSEric Cheng get_link_stats(vnic_name, &vnic_stats); 4109da14cebeSEric Cheng dump_vnic_stat(vnic_name, linkid, state, &vnic_stats, 4110da14cebeSEric Cheng &state->vs_totalstats); 4111da14cebeSEric Cheng } 4112da14cebeSEric Cheng return (DLADM_STATUS_OK); 4113da14cebeSEric Cheng } else { 4114da14cebeSEric Cheng (void) snprintf(vbuf.vnic_link, sizeof (vbuf.vnic_link), 4115da14cebeSEric Cheng "%s", vnic_name); 4116da14cebeSEric Cheng 4117da14cebeSEric Cheng if (!is_etherstub) { 4118da14cebeSEric Cheng 4119da14cebeSEric Cheng (void) snprintf(vbuf.vnic_over, sizeof (vbuf.vnic_over), 4120da14cebeSEric Cheng "%s", devname); 4121da14cebeSEric Cheng (void) snprintf(vbuf.vnic_speed, 4122da14cebeSEric Cheng sizeof (vbuf.vnic_speed), "%u", 4123da14cebeSEric Cheng (uint_t)((get_ifspeed(vnic_name, B_TRUE)) 4124da14cebeSEric Cheng / 1000000ull)); 4125da14cebeSEric Cheng 4126da14cebeSEric Cheng switch (vnic->va_mac_addr_type) { 4127da14cebeSEric Cheng case VNIC_MAC_ADDR_TYPE_FIXED: 4128da14cebeSEric Cheng case VNIC_MAC_ADDR_TYPE_PRIMARY: 4129da14cebeSEric Cheng (void) snprintf(vbuf.vnic_macaddrtype, 4130da14cebeSEric Cheng sizeof (vbuf.vnic_macaddrtype), 4131da14cebeSEric Cheng gettext("fixed")); 4132da14cebeSEric Cheng break; 4133da14cebeSEric Cheng case VNIC_MAC_ADDR_TYPE_RANDOM: 4134da14cebeSEric Cheng (void) snprintf(vbuf.vnic_macaddrtype, 4135da14cebeSEric Cheng sizeof (vbuf.vnic_macaddrtype), 4136da14cebeSEric Cheng gettext("random")); 4137da14cebeSEric Cheng break; 4138da14cebeSEric Cheng case VNIC_MAC_ADDR_TYPE_FACTORY: 4139da14cebeSEric Cheng (void) snprintf(vbuf.vnic_macaddrtype, 4140da14cebeSEric Cheng sizeof (vbuf.vnic_macaddrtype), 4141da14cebeSEric Cheng gettext("factory, slot %d"), 4142da14cebeSEric Cheng vnic->va_mac_slot); 4143da14cebeSEric Cheng break; 4144da14cebeSEric Cheng } 4145da14cebeSEric Cheng 4146da14cebeSEric Cheng if (strlen(vbuf.vnic_macaddrtype) > 0) { 4147da14cebeSEric Cheng (void) snprintf(vbuf.vnic_macaddr, 4148da14cebeSEric Cheng sizeof (vbuf.vnic_macaddr), "%s", 4149da14cebeSEric Cheng dladm_aggr_macaddr2str(vnic->va_mac_addr, 4150da14cebeSEric Cheng mstr)); 4151da14cebeSEric Cheng } 4152da14cebeSEric Cheng 4153da14cebeSEric Cheng (void) snprintf(vbuf.vnic_vid, sizeof (vbuf.vnic_vid), 4154da14cebeSEric Cheng "%d", vnic->va_vid); 4155da14cebeSEric Cheng } 4156da14cebeSEric Cheng 4157da14cebeSEric Cheng if (!state->vs_parseable && !state->vs_printheader) { 4158da14cebeSEric Cheng print_header(&state->vs_print); 4159da14cebeSEric Cheng state->vs_printheader = B_TRUE; 4160da14cebeSEric Cheng } 4161da14cebeSEric Cheng 4162da14cebeSEric Cheng dladm_print_output(&state->vs_print, state->vs_parseable, 4163da14cebeSEric Cheng dladm_print_field, (void *)&vbuf); 4164da14cebeSEric Cheng 4165da14cebeSEric Cheng return (DLADM_STATUS_OK); 4166da14cebeSEric Cheng } 4167da14cebeSEric Cheng } 4168da14cebeSEric Cheng 4169*4ac67f02SAnurag S. Maskey /* ARGSUSED */ 4170da14cebeSEric Cheng static int 4171*4ac67f02SAnurag S. Maskey show_vnic(dladm_handle_t dh, datalink_id_t linkid, void *arg) 4172da14cebeSEric Cheng { 4173da14cebeSEric Cheng show_vnic_state_t *state = arg; 4174da14cebeSEric Cheng 4175da14cebeSEric Cheng state->vs_status = print_vnic(state, linkid); 4176da14cebeSEric Cheng return (DLADM_WALK_CONTINUE); 4177da14cebeSEric Cheng } 4178da14cebeSEric Cheng 4179da14cebeSEric Cheng static void 4180da14cebeSEric Cheng do_show_vnic_common(int argc, char *argv[], const char *use, 4181da14cebeSEric Cheng boolean_t etherstub) 4182da14cebeSEric Cheng { 4183da14cebeSEric Cheng int option; 4184da14cebeSEric Cheng boolean_t s_arg = B_FALSE; 4185da14cebeSEric Cheng boolean_t i_arg = B_FALSE; 4186da14cebeSEric Cheng boolean_t l_arg = B_FALSE; 4187da14cebeSEric Cheng char *endp = NULL; 4188da14cebeSEric Cheng uint32_t interval = 0, flags = DLADM_OPT_ACTIVE; 4189da14cebeSEric Cheng datalink_id_t linkid = DATALINK_ALL_LINKID; 4190da14cebeSEric Cheng datalink_id_t dev_linkid = DATALINK_ALL_LINKID; 4191da14cebeSEric Cheng show_vnic_state_t state; 4192da14cebeSEric Cheng dladm_status_t status; 4193da14cebeSEric Cheng boolean_t o_arg = B_FALSE; 4194da14cebeSEric Cheng char *fields_str = NULL; 4195da14cebeSEric Cheng print_field_t **fields; 4196da14cebeSEric Cheng print_field_t *pf; 4197da14cebeSEric Cheng int pfmax; 4198da14cebeSEric Cheng uint_t nfields; 4199da14cebeSEric Cheng char *all_fields = 4200da14cebeSEric Cheng "link,over,speed,macaddr,macaddrtype,vid"; 4201da14cebeSEric Cheng char *all_e_fields = 4202da14cebeSEric Cheng "link"; 4203da14cebeSEric Cheng 4204da14cebeSEric Cheng bzero(&state, sizeof (state)); 4205da14cebeSEric Cheng opterr = 0; 4206da14cebeSEric Cheng while ((option = getopt_long(argc, argv, ":pPl:si:o:", lopts, 4207da14cebeSEric Cheng NULL)) != -1) { 4208da14cebeSEric Cheng switch (option) { 4209da14cebeSEric Cheng case 'p': 4210da14cebeSEric Cheng state.vs_parseable = B_TRUE; 4211da14cebeSEric Cheng break; 4212da14cebeSEric Cheng case 'P': 4213da14cebeSEric Cheng flags = DLADM_OPT_PERSIST; 4214da14cebeSEric Cheng break; 4215da14cebeSEric Cheng case 'l': 4216da14cebeSEric Cheng if (etherstub) 4217da14cebeSEric Cheng die("option not supported for this command"); 4218da14cebeSEric Cheng 4219da14cebeSEric Cheng if (strlcpy(state.vs_link, optarg, MAXLINKNAMELEN) >= 4220da14cebeSEric Cheng MAXLINKNAMELEN) 4221da14cebeSEric Cheng die("link name too long"); 4222da14cebeSEric Cheng 4223da14cebeSEric Cheng l_arg = B_TRUE; 4224da14cebeSEric Cheng break; 4225da14cebeSEric Cheng case 's': 4226da14cebeSEric Cheng if (s_arg) { 4227da14cebeSEric Cheng die("the option -s cannot be specified " 4228da14cebeSEric Cheng "more than once"); 4229da14cebeSEric Cheng } 4230da14cebeSEric Cheng s_arg = B_TRUE; 4231da14cebeSEric Cheng break; 4232da14cebeSEric Cheng case 'i': 4233da14cebeSEric Cheng if (i_arg) { 4234da14cebeSEric Cheng die("the option -i cannot be specified " 4235da14cebeSEric Cheng "more than once"); 4236da14cebeSEric Cheng } 4237da14cebeSEric Cheng i_arg = B_TRUE; 4238da14cebeSEric Cheng interval = (int)strtol(optarg, &endp, 10); 4239da14cebeSEric Cheng if (errno != 0 || interval == 0 || *endp != '\0') 4240da14cebeSEric Cheng die("invalid interval value '%s'", optarg); 4241da14cebeSEric Cheng break; 4242da14cebeSEric Cheng case 'o': 4243da14cebeSEric Cheng o_arg = B_TRUE; 4244da14cebeSEric Cheng fields_str = optarg; 4245da14cebeSEric Cheng break; 4246da14cebeSEric Cheng default: 4247da14cebeSEric Cheng die_opterr(optopt, option, use); 4248da14cebeSEric Cheng } 4249da14cebeSEric Cheng } 4250da14cebeSEric Cheng 4251da14cebeSEric Cheng if (i_arg && !s_arg) 4252da14cebeSEric Cheng die("the option -i can be used only with -s"); 4253da14cebeSEric Cheng 4254da14cebeSEric Cheng /* get vnic ID (optional last argument) */ 4255da14cebeSEric Cheng if (optind == (argc - 1)) { 4256*4ac67f02SAnurag S. Maskey status = dladm_name2info(handle, argv[optind], &linkid, NULL, 4257da14cebeSEric Cheng NULL, NULL); 4258da14cebeSEric Cheng if (status != DLADM_STATUS_OK) { 4259da14cebeSEric Cheng die_dlerr(status, "invalid vnic name '%s'", 4260da14cebeSEric Cheng argv[optind]); 4261da14cebeSEric Cheng } 4262da14cebeSEric Cheng (void) strlcpy(state.vs_vnic, argv[optind], MAXLINKNAMELEN); 4263da14cebeSEric Cheng } else if (optind != argc) { 4264da14cebeSEric Cheng usage(); 4265da14cebeSEric Cheng } 4266da14cebeSEric Cheng 4267da14cebeSEric Cheng if (l_arg) { 4268*4ac67f02SAnurag S. Maskey status = dladm_name2info(handle, state.vs_link, &dev_linkid, 4269*4ac67f02SAnurag S. Maskey NULL, NULL, NULL); 4270da14cebeSEric Cheng if (status != DLADM_STATUS_OK) { 4271da14cebeSEric Cheng die_dlerr(status, "invalid link name '%s'", 4272da14cebeSEric Cheng state.vs_link); 4273da14cebeSEric Cheng } 4274da14cebeSEric Cheng } 4275da14cebeSEric Cheng 4276da14cebeSEric Cheng state.vs_vnic_id = linkid; 4277da14cebeSEric Cheng state.vs_link_id = dev_linkid; 4278da14cebeSEric Cheng state.vs_etherstub = etherstub; 4279da14cebeSEric Cheng state.vs_found = B_FALSE; 4280da14cebeSEric Cheng state.vs_flags = flags; 4281da14cebeSEric Cheng 4282da14cebeSEric Cheng if (!o_arg || (o_arg && strcasecmp(fields_str, "all") == 0)) { 4283da14cebeSEric Cheng if (etherstub) 4284da14cebeSEric Cheng fields_str = all_e_fields; 4285da14cebeSEric Cheng else 4286da14cebeSEric Cheng fields_str = all_fields; 4287da14cebeSEric Cheng } 4288da14cebeSEric Cheng 4289da14cebeSEric Cheng pf = vnic_fields; 4290da14cebeSEric Cheng pfmax = VNIC_MAX_FIELDS; 4291da14cebeSEric Cheng 4292da14cebeSEric Cheng fields = parse_output_fields(fields_str, pf, pfmax, CMD_TYPE_ANY, 4293da14cebeSEric Cheng &nfields); 4294da14cebeSEric Cheng 4295da14cebeSEric Cheng if (fields == NULL) { 4296da14cebeSEric Cheng die("invalid field(s) specified"); 4297da14cebeSEric Cheng return; 4298da14cebeSEric Cheng } 4299da14cebeSEric Cheng 4300da14cebeSEric Cheng state.vs_print.ps_fields = fields; 4301da14cebeSEric Cheng state.vs_print.ps_nfields = nfields; 4302da14cebeSEric Cheng 4303da14cebeSEric Cheng if (s_arg) { 4304da14cebeSEric Cheng /* Display vnic statistics */ 4305da14cebeSEric Cheng vnic_stats(&state, interval); 4306da14cebeSEric Cheng return; 4307da14cebeSEric Cheng } 4308da14cebeSEric Cheng 4309da14cebeSEric Cheng /* Display vnic information */ 4310da14cebeSEric Cheng state.vs_donefirst = B_FALSE; 4311da14cebeSEric Cheng 4312da14cebeSEric Cheng if (linkid == DATALINK_ALL_LINKID) { 4313*4ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(show_vnic, handle, &state, 4314da14cebeSEric Cheng DATALINK_CLASS_VNIC | DATALINK_CLASS_ETHERSTUB, 4315da14cebeSEric Cheng DATALINK_ANY_MEDIATYPE, DLADM_OPT_ACTIVE); 4316da14cebeSEric Cheng } else { 4317*4ac67f02SAnurag S. Maskey (void) show_vnic(handle, linkid, &state); 4318da14cebeSEric Cheng if (state.vs_status != DLADM_STATUS_OK) { 4319da14cebeSEric Cheng die_dlerr(state.vs_status, "failed to show vnic '%s'", 4320da14cebeSEric Cheng state.vs_vnic); 4321da14cebeSEric Cheng } 4322da14cebeSEric Cheng } 4323da14cebeSEric Cheng } 4324da14cebeSEric Cheng 4325da14cebeSEric Cheng static void 4326da14cebeSEric Cheng do_show_vnic(int argc, char *argv[], const char *use) 4327da14cebeSEric Cheng { 4328da14cebeSEric Cheng do_show_vnic_common(argc, argv, use, B_FALSE); 4329da14cebeSEric Cheng } 4330da14cebeSEric Cheng 4331da14cebeSEric Cheng static void 4332da14cebeSEric Cheng do_create_etherstub(int argc, char *argv[], const char *use) 4333da14cebeSEric Cheng { 4334da14cebeSEric Cheng uint32_t flags; 4335da14cebeSEric Cheng char *altroot = NULL; 4336da14cebeSEric Cheng char option; 4337da14cebeSEric Cheng dladm_status_t status; 4338da14cebeSEric Cheng char name[MAXLINKNAMELEN]; 4339da14cebeSEric Cheng uchar_t mac_addr[ETHERADDRL]; 4340da14cebeSEric Cheng 4341da14cebeSEric Cheng name[0] = '\0'; 4342da14cebeSEric Cheng bzero(mac_addr, sizeof (mac_addr)); 4343da14cebeSEric Cheng flags = DLADM_OPT_ANCHOR | DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST; 4344da14cebeSEric Cheng 4345da14cebeSEric Cheng opterr = 0; 4346da14cebeSEric Cheng while ((option = getopt_long(argc, argv, "tR:", 4347da14cebeSEric Cheng etherstub_lopts, NULL)) != -1) { 4348da14cebeSEric Cheng switch (option) { 4349da14cebeSEric Cheng case 't': 4350da14cebeSEric Cheng flags &= ~DLADM_OPT_PERSIST; 4351da14cebeSEric Cheng break; 4352da14cebeSEric Cheng case 'R': 4353da14cebeSEric Cheng altroot = optarg; 4354da14cebeSEric Cheng break; 4355da14cebeSEric Cheng default: 4356da14cebeSEric Cheng die_opterr(optopt, option, use); 4357da14cebeSEric Cheng } 4358da14cebeSEric Cheng } 4359da14cebeSEric Cheng 4360da14cebeSEric Cheng /* the etherstub id is the required operand */ 4361da14cebeSEric Cheng if (optind != (argc - 1)) 4362da14cebeSEric Cheng usage(); 4363da14cebeSEric Cheng 4364da14cebeSEric Cheng if (strlcpy(name, argv[optind], MAXLINKNAMELEN) >= MAXLINKNAMELEN) 4365da14cebeSEric Cheng die("link name too long '%s'", argv[optind]); 4366da14cebeSEric Cheng 4367da14cebeSEric Cheng if (!dladm_valid_linkname(name)) 4368da14cebeSEric Cheng die("invalid link name '%s'", argv[optind]); 4369da14cebeSEric Cheng 4370da14cebeSEric Cheng if (altroot != NULL) 4371da14cebeSEric Cheng altroot_cmd(altroot, argc, argv); 4372da14cebeSEric Cheng 4373*4ac67f02SAnurag S. Maskey status = dladm_vnic_create(handle, name, DATALINK_INVALID_LINKID, 4374da14cebeSEric Cheng VNIC_MAC_ADDR_TYPE_AUTO, mac_addr, ETHERADDRL, NULL, 0, 0, NULL, 4375da14cebeSEric Cheng NULL, flags); 4376da14cebeSEric Cheng if (status != DLADM_STATUS_OK) 4377da14cebeSEric Cheng die_dlerr(status, "etherstub creation failed"); 4378da14cebeSEric Cheng 4379da14cebeSEric Cheng 4380da14cebeSEric Cheng } 4381da14cebeSEric Cheng 4382da14cebeSEric Cheng static void 4383da14cebeSEric Cheng do_delete_etherstub(int argc, char *argv[], const char *use) 4384da14cebeSEric Cheng { 4385da14cebeSEric Cheng do_delete_vnic_common(argc, argv, use, B_TRUE); 4386da14cebeSEric Cheng } 4387da14cebeSEric Cheng 4388da14cebeSEric Cheng /* ARGSUSED */ 4389da14cebeSEric Cheng static void 4390da14cebeSEric Cheng do_show_etherstub(int argc, char *argv[], const char *use) 4391da14cebeSEric Cheng { 4392da14cebeSEric Cheng do_show_vnic_common(argc, argv, use, B_TRUE); 4393da14cebeSEric Cheng } 4394da14cebeSEric Cheng 4395da14cebeSEric Cheng static void 43966be03d0bSVasumathi Sundaram - Sun Microsystems link_stats(datalink_id_t linkid, uint_t interval, char *fields_str, 43976be03d0bSVasumathi Sundaram - Sun Microsystems show_state_t *state) 4398d62bc4baSyz147064 { 43996be03d0bSVasumathi Sundaram - Sun Microsystems print_field_t **fields; 44006be03d0bSVasumathi Sundaram - Sun Microsystems uint_t nfields; 440133343a97Smeem 44026be03d0bSVasumathi Sundaram - Sun Microsystems fields = parse_output_fields(fields_str, devs_fields, DEVS_MAX_FIELDS, 44036be03d0bSVasumathi Sundaram - Sun Microsystems CMD_TYPE_ANY, &nfields); 44046be03d0bSVasumathi Sundaram - Sun Microsystems if (fields == NULL) { 44056be03d0bSVasumathi Sundaram - Sun Microsystems die("invalid field(s) specified"); 44066be03d0bSVasumathi Sundaram - Sun Microsystems return; 44076be03d0bSVasumathi Sundaram - Sun Microsystems } 44086be03d0bSVasumathi Sundaram - Sun Microsystems 44096be03d0bSVasumathi Sundaram - Sun Microsystems state->ls_print.ps_fields = fields; 44106be03d0bSVasumathi Sundaram - Sun Microsystems state->ls_print.ps_nfields = nfields; 44117c478bd9Sstevel@tonic-gate 44127c478bd9Sstevel@tonic-gate /* 44137c478bd9Sstevel@tonic-gate * If an interval is specified, continuously show the stats 44147c478bd9Sstevel@tonic-gate * only for the first MAC port. 44157c478bd9Sstevel@tonic-gate */ 44166be03d0bSVasumathi Sundaram - Sun Microsystems state->ls_firstonly = (interval != 0); 44177c478bd9Sstevel@tonic-gate 44186be03d0bSVasumathi Sundaram - Sun Microsystems if (!state->ls_parseable) 44196be03d0bSVasumathi Sundaram - Sun Microsystems print_header(&state->ls_print); 44207c478bd9Sstevel@tonic-gate for (;;) { 44216be03d0bSVasumathi Sundaram - Sun Microsystems state->ls_donefirst = B_FALSE; 4422d62bc4baSyz147064 if (linkid == DATALINK_ALL_LINKID) { 4423*4ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(show_link_stats, handle, 4424*4ac67f02SAnurag S. Maskey state, DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE, 4425d62bc4baSyz147064 DLADM_OPT_ACTIVE); 4426d62bc4baSyz147064 } else { 4427*4ac67f02SAnurag S. Maskey (void) show_link_stats(handle, linkid, state); 4428d62bc4baSyz147064 } 44297c478bd9Sstevel@tonic-gate 44307c478bd9Sstevel@tonic-gate if (interval == 0) 44317c478bd9Sstevel@tonic-gate break; 44327c478bd9Sstevel@tonic-gate 44337c478bd9Sstevel@tonic-gate (void) sleep(interval); 44347c478bd9Sstevel@tonic-gate } 44357c478bd9Sstevel@tonic-gate } 44367c478bd9Sstevel@tonic-gate 44377c478bd9Sstevel@tonic-gate static void 4438d62bc4baSyz147064 aggr_stats(datalink_id_t linkid, show_grp_state_t *state, uint_t interval) 44397c478bd9Sstevel@tonic-gate { 44407c478bd9Sstevel@tonic-gate /* 44417c478bd9Sstevel@tonic-gate * If an interval is specified, continuously show the stats 44427c478bd9Sstevel@tonic-gate * only for the first group. 44437c478bd9Sstevel@tonic-gate */ 4444d62bc4baSyz147064 state->gs_firstonly = (interval != 0); 44457c478bd9Sstevel@tonic-gate 44467c478bd9Sstevel@tonic-gate for (;;) { 4447d62bc4baSyz147064 state->gs_donefirst = B_FALSE; 4448d62bc4baSyz147064 if (linkid == DATALINK_ALL_LINKID) 4449*4ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(show_aggr, handle, state, 4450d62bc4baSyz147064 DATALINK_CLASS_AGGR, DATALINK_ANY_MEDIATYPE, 4451d62bc4baSyz147064 DLADM_OPT_ACTIVE); 4452d62bc4baSyz147064 else 4453*4ac67f02SAnurag S. Maskey (void) show_aggr(handle, linkid, state); 44547c478bd9Sstevel@tonic-gate 44557c478bd9Sstevel@tonic-gate if (interval == 0) 44567c478bd9Sstevel@tonic-gate break; 44577c478bd9Sstevel@tonic-gate 44587c478bd9Sstevel@tonic-gate (void) sleep(interval); 44597c478bd9Sstevel@tonic-gate } 44607c478bd9Sstevel@tonic-gate } 44617c478bd9Sstevel@tonic-gate 4462da14cebeSEric Cheng /* ARGSUSED */ 44637c478bd9Sstevel@tonic-gate static void 4464da14cebeSEric Cheng vnic_stats(show_vnic_state_t *sp, uint32_t interval) 44657c478bd9Sstevel@tonic-gate { 4466da14cebeSEric Cheng show_vnic_state_t state; 4467da14cebeSEric Cheng boolean_t specific_link, specific_dev; 44687c478bd9Sstevel@tonic-gate 4469da14cebeSEric Cheng /* Display vnic statistics */ 4470da14cebeSEric Cheng dump_vnics_head(sp->vs_link); 4471e7801d59Ssowmini 4472da14cebeSEric Cheng bzero(&state, sizeof (state)); 4473da14cebeSEric Cheng state.vs_stats = B_TRUE; 4474da14cebeSEric Cheng state.vs_vnic_id = sp->vs_vnic_id; 4475da14cebeSEric Cheng state.vs_link_id = sp->vs_link_id; 44767c478bd9Sstevel@tonic-gate 44777c478bd9Sstevel@tonic-gate /* 4478da14cebeSEric Cheng * If an interval is specified, and a vnic ID is not specified, 4479da14cebeSEric Cheng * continuously show the stats only for the first vnic. 44807c478bd9Sstevel@tonic-gate */ 4481da14cebeSEric Cheng specific_link = (sp->vs_vnic_id != DATALINK_ALL_LINKID); 4482da14cebeSEric Cheng specific_dev = (sp->vs_link_id != DATALINK_ALL_LINKID); 44837c478bd9Sstevel@tonic-gate 44847c478bd9Sstevel@tonic-gate for (;;) { 4485da14cebeSEric Cheng /* Get stats for each vnic */ 4486da14cebeSEric Cheng state.vs_found = B_FALSE; 4487da14cebeSEric Cheng state.vs_donefirst = B_FALSE; 4488da14cebeSEric Cheng state.vs_printstats = B_FALSE; 4489da14cebeSEric Cheng state.vs_flags = DLADM_OPT_ACTIVE; 44907c478bd9Sstevel@tonic-gate 4491da14cebeSEric Cheng if (!specific_link) { 4492*4ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(show_vnic, handle, &state, 4493da14cebeSEric Cheng DATALINK_CLASS_VNIC, DATALINK_ANY_MEDIATYPE, 4494da14cebeSEric Cheng DLADM_OPT_ACTIVE); 4495da14cebeSEric Cheng } else { 4496*4ac67f02SAnurag S. Maskey (void) show_vnic(handle, sp->vs_vnic_id, &state); 4497da14cebeSEric Cheng if (state.vs_status != DLADM_STATUS_OK) { 4498da14cebeSEric Cheng die_dlerr(state.vs_status, 4499da14cebeSEric Cheng "failed to show vnic '%s'", sp->vs_vnic); 4500da14cebeSEric Cheng } 4501da14cebeSEric Cheng } 45027c478bd9Sstevel@tonic-gate 4503da14cebeSEric Cheng if (specific_link && !state.vs_found) 4504da14cebeSEric Cheng die("non-existent vnic '%s'", sp->vs_vnic); 4505da14cebeSEric Cheng if (specific_dev && !state.vs_found) 4506da14cebeSEric Cheng die("device %s has no vnics", sp->vs_link); 4507da14cebeSEric Cheng 4508da14cebeSEric Cheng /* Show totals */ 4509da14cebeSEric Cheng if ((specific_link | specific_dev) && !interval) { 4510da14cebeSEric Cheng (void) printf("Total"); 4511da14cebeSEric Cheng (void) printf("\t%-10llu", 4512da14cebeSEric Cheng state.vs_totalstats.ipackets); 4513da14cebeSEric Cheng (void) printf("%-12llu", 4514da14cebeSEric Cheng state.vs_totalstats.rbytes); 4515da14cebeSEric Cheng (void) printf("%-10llu", 4516da14cebeSEric Cheng state.vs_totalstats.opackets); 4517da14cebeSEric Cheng (void) printf("%-12llu\n", 4518da14cebeSEric Cheng state.vs_totalstats.obytes); 4519da14cebeSEric Cheng } 4520da14cebeSEric Cheng 4521da14cebeSEric Cheng /* Show stats for each vnic */ 4522da14cebeSEric Cheng state.vs_donefirst = B_FALSE; 4523da14cebeSEric Cheng state.vs_printstats = B_TRUE; 4524da14cebeSEric Cheng 4525da14cebeSEric Cheng if (!specific_link) { 4526*4ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(show_vnic, handle, &state, 4527da14cebeSEric Cheng DATALINK_CLASS_VNIC, DATALINK_ANY_MEDIATYPE, 4528da14cebeSEric Cheng DLADM_OPT_ACTIVE); 4529da14cebeSEric Cheng } else { 4530*4ac67f02SAnurag S. Maskey (void) show_vnic(handle, sp->vs_vnic_id, &state); 4531da14cebeSEric Cheng if (state.vs_status != DLADM_STATUS_OK) { 4532da14cebeSEric Cheng die_dlerr(state.vs_status, 4533da14cebeSEric Cheng "failed to show vnic '%s'", sp->vs_vnic); 4534da14cebeSEric Cheng } 4535da14cebeSEric Cheng } 45367c478bd9Sstevel@tonic-gate 45377c478bd9Sstevel@tonic-gate if (interval == 0) 45387c478bd9Sstevel@tonic-gate break; 45397c478bd9Sstevel@tonic-gate 45407c478bd9Sstevel@tonic-gate (void) sleep(interval); 45417c478bd9Sstevel@tonic-gate } 45427c478bd9Sstevel@tonic-gate } 45437c478bd9Sstevel@tonic-gate 45447c478bd9Sstevel@tonic-gate static void 4545da14cebeSEric Cheng get_mac_stats(const char *dev, pktsum_t *stats) 45467c478bd9Sstevel@tonic-gate { 45477c478bd9Sstevel@tonic-gate kstat_ctl_t *kcp; 45487c478bd9Sstevel@tonic-gate kstat_t *ksp; 4549da14cebeSEric Cheng char module[DLPI_LINKNAME_MAX]; 4550da14cebeSEric Cheng uint_t instance; 4551da14cebeSEric Cheng 4552da14cebeSEric Cheng 4553da14cebeSEric Cheng bzero(stats, sizeof (*stats)); 4554da14cebeSEric Cheng 4555da14cebeSEric Cheng if (dlpi_parselink(dev, module, &instance) != DLPI_SUCCESS) 4556da14cebeSEric Cheng return; 45577c478bd9Sstevel@tonic-gate 45587c478bd9Sstevel@tonic-gate if ((kcp = kstat_open()) == NULL) { 455933343a97Smeem warn("kstat open operation failed"); 45607c478bd9Sstevel@tonic-gate return; 45617c478bd9Sstevel@tonic-gate } 45627c478bd9Sstevel@tonic-gate 4563da14cebeSEric Cheng ksp = dladm_kstat_lookup(kcp, module, instance, "mac", NULL); 4564da14cebeSEric Cheng if (ksp != NULL) 4565da14cebeSEric Cheng dladm_get_stats(kcp, ksp, stats); 4566da14cebeSEric Cheng 45677c478bd9Sstevel@tonic-gate (void) kstat_close(kcp); 45687c478bd9Sstevel@tonic-gate 45697c478bd9Sstevel@tonic-gate } 45707c478bd9Sstevel@tonic-gate 45717c478bd9Sstevel@tonic-gate static void 45727c478bd9Sstevel@tonic-gate get_link_stats(const char *link, pktsum_t *stats) 45737c478bd9Sstevel@tonic-gate { 4574da14cebeSEric Cheng kstat_ctl_t *kcp; 4575da14cebeSEric Cheng kstat_t *ksp; 4576da14cebeSEric Cheng 45777c478bd9Sstevel@tonic-gate bzero(stats, sizeof (*stats)); 4578da14cebeSEric Cheng 4579da14cebeSEric Cheng if ((kcp = kstat_open()) == NULL) { 4580da14cebeSEric Cheng warn("kstat_open operation failed"); 4581da14cebeSEric Cheng return; 4582da14cebeSEric Cheng } 4583da14cebeSEric Cheng 4584da14cebeSEric Cheng ksp = dladm_kstat_lookup(kcp, "link", 0, link, NULL); 4585da14cebeSEric Cheng 4586da14cebeSEric Cheng if (ksp != NULL) 4587da14cebeSEric Cheng dladm_get_stats(kcp, ksp, stats); 4588da14cebeSEric Cheng 4589da14cebeSEric Cheng (void) kstat_close(kcp); 45907c478bd9Sstevel@tonic-gate } 45917c478bd9Sstevel@tonic-gate 4592ba2e4443Sseb static int 4593d62bc4baSyz147064 query_kstat(char *module, int instance, const char *name, const char *stat, 4594d62bc4baSyz147064 uint8_t type, void *val) 45957c478bd9Sstevel@tonic-gate { 45967c478bd9Sstevel@tonic-gate kstat_ctl_t *kcp; 45977c478bd9Sstevel@tonic-gate kstat_t *ksp; 45987c478bd9Sstevel@tonic-gate 45997c478bd9Sstevel@tonic-gate if ((kcp = kstat_open()) == NULL) { 460033343a97Smeem warn("kstat open operation failed"); 4601ba2e4443Sseb return (-1); 46027c478bd9Sstevel@tonic-gate } 46037c478bd9Sstevel@tonic-gate 4604d62bc4baSyz147064 if ((ksp = kstat_lookup(kcp, module, instance, (char *)name)) == NULL) { 46057c478bd9Sstevel@tonic-gate /* 46067c478bd9Sstevel@tonic-gate * The kstat query could fail if the underlying MAC 46077c478bd9Sstevel@tonic-gate * driver was already detached. 46087c478bd9Sstevel@tonic-gate */ 46097c478bd9Sstevel@tonic-gate goto bail; 46107c478bd9Sstevel@tonic-gate } 46117c478bd9Sstevel@tonic-gate 46127c478bd9Sstevel@tonic-gate if (kstat_read(kcp, ksp, NULL) == -1) { 461333343a97Smeem warn("kstat read failed"); 46147c478bd9Sstevel@tonic-gate goto bail; 46157c478bd9Sstevel@tonic-gate } 46167c478bd9Sstevel@tonic-gate 4617e7801d59Ssowmini if (dladm_kstat_value(ksp, stat, type, val) < 0) 46187c478bd9Sstevel@tonic-gate goto bail; 4619ba2e4443Sseb 4620ba2e4443Sseb (void) kstat_close(kcp); 4621ba2e4443Sseb return (0); 46227c478bd9Sstevel@tonic-gate 46237c478bd9Sstevel@tonic-gate bail: 46247c478bd9Sstevel@tonic-gate (void) kstat_close(kcp); 4625ba2e4443Sseb return (-1); 4626ba2e4443Sseb } 4627ba2e4443Sseb 4628d62bc4baSyz147064 static int 4629d62bc4baSyz147064 get_one_kstat(const char *name, const char *stat, uint8_t type, 4630d62bc4baSyz147064 void *val, boolean_t islink) 4631d62bc4baSyz147064 { 4632d62bc4baSyz147064 char module[DLPI_LINKNAME_MAX]; 4633d62bc4baSyz147064 uint_t instance; 4634d62bc4baSyz147064 4635d62bc4baSyz147064 if (islink) { 4636d62bc4baSyz147064 return (query_kstat("link", 0, name, stat, type, val)); 4637d62bc4baSyz147064 } else { 4638d62bc4baSyz147064 if (dlpi_parselink(name, module, &instance) != DLPI_SUCCESS) 4639d62bc4baSyz147064 return (-1); 4640d62bc4baSyz147064 4641d62bc4baSyz147064 return (query_kstat(module, instance, "mac", stat, type, val)); 4642d62bc4baSyz147064 } 4643d62bc4baSyz147064 } 4644d62bc4baSyz147064 4645ba2e4443Sseb static uint64_t 4646d62bc4baSyz147064 get_ifspeed(const char *name, boolean_t islink) 4647ba2e4443Sseb { 4648ba2e4443Sseb uint64_t ifspeed = 0; 4649ba2e4443Sseb 4650d62bc4baSyz147064 (void) get_one_kstat(name, "ifspeed", KSTAT_DATA_UINT64, 4651d62bc4baSyz147064 &ifspeed, islink); 4652d62bc4baSyz147064 46537c478bd9Sstevel@tonic-gate return (ifspeed); 46547c478bd9Sstevel@tonic-gate } 46557c478bd9Sstevel@tonic-gate 4656f595a68aSyz147064 static const char * 4657d62bc4baSyz147064 get_linkstate(const char *name, boolean_t islink, char *buf) 46587c478bd9Sstevel@tonic-gate { 4659d62bc4baSyz147064 link_state_t linkstate; 46607c478bd9Sstevel@tonic-gate 4661d62bc4baSyz147064 if (get_one_kstat(name, "link_state", KSTAT_DATA_UINT32, 4662d62bc4baSyz147064 &linkstate, islink) != 0) { 4663da14cebeSEric Cheng (void) strlcpy(buf, "?", DLADM_STRSIZE); 46643a62633bSyz147064 return (buf); 46657c478bd9Sstevel@tonic-gate } 4666d62bc4baSyz147064 return (dladm_linkstate2str(linkstate, buf)); 46677c478bd9Sstevel@tonic-gate } 46687c478bd9Sstevel@tonic-gate 4669f595a68aSyz147064 static const char * 4670d62bc4baSyz147064 get_linkduplex(const char *name, boolean_t islink, char *buf) 46717c478bd9Sstevel@tonic-gate { 4672d62bc4baSyz147064 link_duplex_t linkduplex; 46737c478bd9Sstevel@tonic-gate 4674d62bc4baSyz147064 if (get_one_kstat(name, "link_duplex", KSTAT_DATA_UINT32, 4675d62bc4baSyz147064 &linkduplex, islink) != 0) { 46763a62633bSyz147064 (void) strlcpy(buf, "unknown", DLADM_STRSIZE); 46773a62633bSyz147064 return (buf); 46787c478bd9Sstevel@tonic-gate } 46797c478bd9Sstevel@tonic-gate 4680d62bc4baSyz147064 return (dladm_linkduplex2str(linkduplex, buf)); 46817c478bd9Sstevel@tonic-gate } 46820ba2cbe9Sxc151355 46830ba2cbe9Sxc151355 typedef struct { 46840ba2cbe9Sxc151355 char *s_buf; 46850ba2cbe9Sxc151355 char **s_fields; /* array of pointer to the fields in s_buf */ 46860ba2cbe9Sxc151355 uint_t s_nfields; /* the number of fields in s_buf */ 46870ba2cbe9Sxc151355 } split_t; 46880ba2cbe9Sxc151355 46890ba2cbe9Sxc151355 /* 46900ba2cbe9Sxc151355 * Free the split_t structure pointed to by `sp'. 46910ba2cbe9Sxc151355 */ 46920ba2cbe9Sxc151355 static void 46930ba2cbe9Sxc151355 splitfree(split_t *sp) 46940ba2cbe9Sxc151355 { 46950ba2cbe9Sxc151355 free(sp->s_buf); 46960ba2cbe9Sxc151355 free(sp->s_fields); 46970ba2cbe9Sxc151355 free(sp); 46980ba2cbe9Sxc151355 } 46990ba2cbe9Sxc151355 47000ba2cbe9Sxc151355 /* 47010ba2cbe9Sxc151355 * Split `str' into at most `maxfields' fields, each field at most `maxlen' in 47020ba2cbe9Sxc151355 * length. Return a pointer to a split_t containing the split fields, or NULL 47030ba2cbe9Sxc151355 * on failure. 47040ba2cbe9Sxc151355 */ 47050ba2cbe9Sxc151355 static split_t * 47060ba2cbe9Sxc151355 split(const char *str, uint_t maxfields, uint_t maxlen) 47070ba2cbe9Sxc151355 { 47080ba2cbe9Sxc151355 char *field, *token, *lasts = NULL; 47090ba2cbe9Sxc151355 split_t *sp; 47100ba2cbe9Sxc151355 47110ba2cbe9Sxc151355 if (*str == '\0' || maxfields == 0 || maxlen == 0) 47120ba2cbe9Sxc151355 return (NULL); 47130ba2cbe9Sxc151355 47140ba2cbe9Sxc151355 sp = calloc(sizeof (split_t), 1); 47150ba2cbe9Sxc151355 if (sp == NULL) 47160ba2cbe9Sxc151355 return (NULL); 47170ba2cbe9Sxc151355 47180ba2cbe9Sxc151355 sp->s_buf = strdup(str); 47190ba2cbe9Sxc151355 sp->s_fields = malloc(sizeof (char *) * maxfields); 47200ba2cbe9Sxc151355 if (sp->s_buf == NULL || sp->s_fields == NULL) 47210ba2cbe9Sxc151355 goto fail; 47220ba2cbe9Sxc151355 47230ba2cbe9Sxc151355 token = sp->s_buf; 47240ba2cbe9Sxc151355 while ((field = strtok_r(token, ",", &lasts)) != NULL) { 47250ba2cbe9Sxc151355 if (sp->s_nfields == maxfields || strlen(field) > maxlen) 47260ba2cbe9Sxc151355 goto fail; 47270ba2cbe9Sxc151355 token = NULL; 47280ba2cbe9Sxc151355 sp->s_fields[sp->s_nfields++] = field; 47290ba2cbe9Sxc151355 } 47300ba2cbe9Sxc151355 return (sp); 47310ba2cbe9Sxc151355 fail: 47320ba2cbe9Sxc151355 splitfree(sp); 47330ba2cbe9Sxc151355 return (NULL); 47340ba2cbe9Sxc151355 } 47350ba2cbe9Sxc151355 47360ba2cbe9Sxc151355 static int 4737e7801d59Ssowmini parse_wifi_fields(char *str, print_field_t ***fields, uint_t *countp, 47380ba2cbe9Sxc151355 uint_t cmdtype) 47390ba2cbe9Sxc151355 { 47400ba2cbe9Sxc151355 47410ba2cbe9Sxc151355 if (cmdtype == WIFI_CMD_SCAN) { 47420ba2cbe9Sxc151355 if (str == NULL) 47430ba2cbe9Sxc151355 str = def_scan_wifi_fields; 47440ba2cbe9Sxc151355 if (strcasecmp(str, "all") == 0) 47450ba2cbe9Sxc151355 str = all_scan_wifi_fields; 47460ba2cbe9Sxc151355 } else if (cmdtype == WIFI_CMD_SHOW) { 47470ba2cbe9Sxc151355 if (str == NULL) 47480ba2cbe9Sxc151355 str = def_show_wifi_fields; 47490ba2cbe9Sxc151355 if (strcasecmp(str, "all") == 0) 47500ba2cbe9Sxc151355 str = all_show_wifi_fields; 47510ba2cbe9Sxc151355 } else { 47520ba2cbe9Sxc151355 return (-1); 47530ba2cbe9Sxc151355 } 4754e7801d59Ssowmini *fields = parse_output_fields(str, wifi_fields, WIFI_MAX_FIELDS, 4755e7801d59Ssowmini cmdtype, countp); 4756e7801d59Ssowmini if (*fields != NULL) 4757e7801d59Ssowmini return (0); 47580ba2cbe9Sxc151355 return (-1); 4759e7801d59Ssowmini } 4760e7801d59Ssowmini static print_field_t ** 4761e7801d59Ssowmini parse_output_fields(char *str, print_field_t *template, int max_fields, 4762e7801d59Ssowmini uint_t cmdtype, uint_t *countp) 4763e7801d59Ssowmini { 4764e7801d59Ssowmini split_t *sp; 4765e7801d59Ssowmini boolean_t good_match = B_FALSE; 4766e7801d59Ssowmini uint_t i, j; 4767e7801d59Ssowmini print_field_t **pf = NULL; 47680ba2cbe9Sxc151355 4769e7801d59Ssowmini sp = split(str, max_fields, MAX_FIELD_LEN); 4770e7801d59Ssowmini 4771e7801d59Ssowmini if (sp == NULL) 4772e7801d59Ssowmini return (NULL); 4773e7801d59Ssowmini 4774e7801d59Ssowmini pf = malloc(sp->s_nfields * sizeof (print_field_t *)); 4775e7801d59Ssowmini if (pf == NULL) 47760ba2cbe9Sxc151355 goto fail; 47770ba2cbe9Sxc151355 47780ba2cbe9Sxc151355 for (i = 0; i < sp->s_nfields; i++) { 4779e7801d59Ssowmini for (j = 0; j < max_fields; j++) { 47800ba2cbe9Sxc151355 if (strcasecmp(sp->s_fields[i], 4781e7801d59Ssowmini template[j].pf_name) == 0) { 4782e7801d59Ssowmini good_match = template[j]. pf_cmdtype & cmdtype; 47830ba2cbe9Sxc151355 break; 47840ba2cbe9Sxc151355 } 47850ba2cbe9Sxc151355 } 47860ba2cbe9Sxc151355 if (!good_match) 47870ba2cbe9Sxc151355 goto fail; 47880ba2cbe9Sxc151355 47890ba2cbe9Sxc151355 good_match = B_FALSE; 4790e7801d59Ssowmini pf[i] = &template[j]; 47910ba2cbe9Sxc151355 } 47920ba2cbe9Sxc151355 *countp = i; 47930ba2cbe9Sxc151355 splitfree(sp); 4794e7801d59Ssowmini return (pf); 47950ba2cbe9Sxc151355 fail: 4796e7801d59Ssowmini free(pf); 47970ba2cbe9Sxc151355 splitfree(sp); 4798e7801d59Ssowmini return (NULL); 47990ba2cbe9Sxc151355 } 48000ba2cbe9Sxc151355 48010ba2cbe9Sxc151355 typedef struct print_wifi_state { 4802d62bc4baSyz147064 char *ws_link; 48030ba2cbe9Sxc151355 boolean_t ws_parseable; 48040ba2cbe9Sxc151355 boolean_t ws_header; 4805e7801d59Ssowmini print_state_t ws_print_state; 48060ba2cbe9Sxc151355 } print_wifi_state_t; 48070ba2cbe9Sxc151355 4808e7801d59Ssowmini typedef struct wlan_scan_args_s { 4809e7801d59Ssowmini print_wifi_state_t *ws_state; 4810e7801d59Ssowmini void *ws_attr; 4811e7801d59Ssowmini } wlan_scan_args_t; 48120ba2cbe9Sxc151355 48130ba2cbe9Sxc151355 static void 4814e7801d59Ssowmini print_field(print_state_t *statep, print_field_t *pfp, const char *value, 4815e7801d59Ssowmini boolean_t parseable) 48160ba2cbe9Sxc151355 { 4817e7801d59Ssowmini uint_t width = pfp->pf_width; 48186be03d0bSVasumathi Sundaram - Sun Microsystems uint_t valwidth; 48190ba2cbe9Sxc151355 uint_t compress; 48200ba2cbe9Sxc151355 48210d365605Sschuster /* 48220d365605Sschuster * Parsable fields are separated by ':'. If such a field contains 48230d365605Sschuster * a ':' or '\', this character is prefixed by a '\'. 48240d365605Sschuster */ 4825e7801d59Ssowmini if (parseable) { 48260d365605Sschuster char c; 48270d365605Sschuster 48280d365605Sschuster if (statep->ps_nfields == 1) { 48290d365605Sschuster (void) printf("%s", value); 48300d365605Sschuster return; 48310d365605Sschuster } 48320d365605Sschuster while ((c = *value++) != '\0') { 48330d365605Sschuster if (c == ':' || c == '\\') 48340d365605Sschuster (void) putchar('\\'); 48350d365605Sschuster (void) putchar(c); 48360d365605Sschuster } 48370d365605Sschuster if (!statep->ps_lastfield) 48380d365605Sschuster (void) putchar(':'); 48390d365605Sschuster return; 48400ba2cbe9Sxc151355 } else { 48410ba2cbe9Sxc151355 if (value[0] == '\0') 4842e7801d59Ssowmini value = STR_UNDEF_VAL; 4843e7801d59Ssowmini if (statep->ps_lastfield) { 48440ba2cbe9Sxc151355 (void) printf("%s", value); 48456be03d0bSVasumathi Sundaram - Sun Microsystems statep->ps_overflow = 0; 48460ba2cbe9Sxc151355 return; 48470ba2cbe9Sxc151355 } 48480ba2cbe9Sxc151355 48496be03d0bSVasumathi Sundaram - Sun Microsystems valwidth = strlen(value); 48500ba2cbe9Sxc151355 if (valwidth > width) { 4851e7801d59Ssowmini statep->ps_overflow += valwidth - width; 4852e7801d59Ssowmini } else if (valwidth < width && statep->ps_overflow > 0) { 4853e7801d59Ssowmini compress = min(statep->ps_overflow, width - valwidth); 4854e7801d59Ssowmini statep->ps_overflow -= compress; 48550ba2cbe9Sxc151355 width -= compress; 48560ba2cbe9Sxc151355 } 48570ba2cbe9Sxc151355 (void) printf("%-*s", width, value); 48580ba2cbe9Sxc151355 } 48590ba2cbe9Sxc151355 4860e7801d59Ssowmini if (!statep->ps_lastfield) 48610ba2cbe9Sxc151355 (void) putchar(' '); 48620ba2cbe9Sxc151355 } 48630ba2cbe9Sxc151355 4864e7801d59Ssowmini static char * 4865e7801d59Ssowmini print_wlan_attr(print_field_t *wfp, void *warg) 48660ba2cbe9Sxc151355 { 4867e7801d59Ssowmini static char buf[DLADM_STRSIZE]; 4868e7801d59Ssowmini wlan_scan_args_t *w = warg; 4869e7801d59Ssowmini print_wifi_state_t *statep = w->ws_state; 4870e7801d59Ssowmini dladm_wlan_attr_t *attrp = w->ws_attr; 48710ba2cbe9Sxc151355 4872e7801d59Ssowmini if (wfp->pf_index == 0) { 4873e7801d59Ssowmini return ((char *)statep->ws_link); 48740ba2cbe9Sxc151355 } 48750ba2cbe9Sxc151355 4876e7801d59Ssowmini if ((wfp->pf_index & attrp->wa_valid) == 0) { 4877e7801d59Ssowmini return (""); 48780ba2cbe9Sxc151355 } 48790ba2cbe9Sxc151355 4880e7801d59Ssowmini switch (wfp->pf_index) { 4881f595a68aSyz147064 case DLADM_WLAN_ATTR_ESSID: 4882e7801d59Ssowmini (void) dladm_wlan_essid2str(&attrp->wa_essid, buf); 48830ba2cbe9Sxc151355 break; 4884f595a68aSyz147064 case DLADM_WLAN_ATTR_BSSID: 4885e7801d59Ssowmini (void) dladm_wlan_bssid2str(&attrp->wa_bssid, buf); 48860ba2cbe9Sxc151355 break; 4887f595a68aSyz147064 case DLADM_WLAN_ATTR_SECMODE: 4888e7801d59Ssowmini (void) dladm_wlan_secmode2str(&attrp->wa_secmode, buf); 48890ba2cbe9Sxc151355 break; 4890f595a68aSyz147064 case DLADM_WLAN_ATTR_STRENGTH: 4891e7801d59Ssowmini (void) dladm_wlan_strength2str(&attrp->wa_strength, buf); 48920ba2cbe9Sxc151355 break; 4893f595a68aSyz147064 case DLADM_WLAN_ATTR_MODE: 4894e7801d59Ssowmini (void) dladm_wlan_mode2str(&attrp->wa_mode, buf); 48950ba2cbe9Sxc151355 break; 4896f595a68aSyz147064 case DLADM_WLAN_ATTR_SPEED: 4897e7801d59Ssowmini (void) dladm_wlan_speed2str(&attrp->wa_speed, buf); 48980ba2cbe9Sxc151355 (void) strlcat(buf, "Mb", sizeof (buf)); 48990ba2cbe9Sxc151355 break; 4900f595a68aSyz147064 case DLADM_WLAN_ATTR_AUTH: 4901e7801d59Ssowmini (void) dladm_wlan_auth2str(&attrp->wa_auth, buf); 49020ba2cbe9Sxc151355 break; 4903f595a68aSyz147064 case DLADM_WLAN_ATTR_BSSTYPE: 4904e7801d59Ssowmini (void) dladm_wlan_bsstype2str(&attrp->wa_bsstype, buf); 49050ba2cbe9Sxc151355 break; 49060ba2cbe9Sxc151355 } 49070ba2cbe9Sxc151355 4908e7801d59Ssowmini return (buf); 49090ba2cbe9Sxc151355 } 49100ba2cbe9Sxc151355 49110ba2cbe9Sxc151355 static boolean_t 4912f595a68aSyz147064 print_scan_results(void *arg, dladm_wlan_attr_t *attrp) 49130ba2cbe9Sxc151355 { 49140ba2cbe9Sxc151355 print_wifi_state_t *statep = arg; 4915e7801d59Ssowmini wlan_scan_args_t warg; 49160ba2cbe9Sxc151355 49170ba2cbe9Sxc151355 if (statep->ws_header) { 49180ba2cbe9Sxc151355 statep->ws_header = B_FALSE; 49190ba2cbe9Sxc151355 if (!statep->ws_parseable) 4920e7801d59Ssowmini print_header(&statep->ws_print_state); 49210ba2cbe9Sxc151355 } 49220ba2cbe9Sxc151355 4923e7801d59Ssowmini statep->ws_print_state.ps_overflow = 0; 4924e7801d59Ssowmini bzero(&warg, sizeof (warg)); 4925e7801d59Ssowmini warg.ws_state = statep; 4926e7801d59Ssowmini warg.ws_attr = attrp; 4927e7801d59Ssowmini dladm_print_output(&statep->ws_print_state, statep->ws_parseable, 4928e7801d59Ssowmini print_wlan_attr, &warg); 49290ba2cbe9Sxc151355 return (B_TRUE); 49300ba2cbe9Sxc151355 } 49310ba2cbe9Sxc151355 4932d62bc4baSyz147064 static int 4933*4ac67f02SAnurag S. Maskey scan_wifi(dladm_handle_t dh, datalink_id_t linkid, void *arg) 49340ba2cbe9Sxc151355 { 49350ba2cbe9Sxc151355 print_wifi_state_t *statep = arg; 4936f595a68aSyz147064 dladm_status_t status; 4937d62bc4baSyz147064 char link[MAXLINKNAMELEN]; 4938d62bc4baSyz147064 4939*4ac67f02SAnurag S. Maskey if ((status = dladm_datalink_id2info(dh, linkid, NULL, NULL, NULL, link, 4940e7801d59Ssowmini sizeof (link))) != DLADM_STATUS_OK) { 4941d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 4942d62bc4baSyz147064 } 49430ba2cbe9Sxc151355 49440ba2cbe9Sxc151355 statep->ws_link = link; 4945*4ac67f02SAnurag S. Maskey status = dladm_wlan_scan(dh, linkid, statep, print_scan_results); 4946f595a68aSyz147064 if (status != DLADM_STATUS_OK) 4947d62bc4baSyz147064 die_dlerr(status, "cannot scan link '%s'", statep->ws_link); 494833343a97Smeem 4949d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 49500ba2cbe9Sxc151355 } 49510ba2cbe9Sxc151355 4952e7801d59Ssowmini static char * 4953e7801d59Ssowmini print_link_attr(print_field_t *wfp, void *warg) 49540ba2cbe9Sxc151355 { 4955e7801d59Ssowmini static char buf[DLADM_STRSIZE]; 4956e7801d59Ssowmini char *ptr; 4957e7801d59Ssowmini wlan_scan_args_t *w = warg, w1; 4958e7801d59Ssowmini print_wifi_state_t *statep = w->ws_state; 4959e7801d59Ssowmini dladm_wlan_linkattr_t *attrp = w->ws_attr; 49600ba2cbe9Sxc151355 4961e7801d59Ssowmini if (strcmp(wfp->pf_name, "status") == 0) { 4962e7801d59Ssowmini if ((wfp->pf_index & attrp->la_valid) != 0) 4963e7801d59Ssowmini (void) dladm_wlan_linkstatus2str( 4964e7801d59Ssowmini &attrp->la_status, buf); 4965e7801d59Ssowmini return (buf); 49660ba2cbe9Sxc151355 } 4967e7801d59Ssowmini statep->ws_print_state.ps_overflow = 0; 4968e7801d59Ssowmini bzero(&w1, sizeof (w1)); 4969e7801d59Ssowmini w1.ws_state = statep; 4970e7801d59Ssowmini w1.ws_attr = &attrp->la_wlan_attr; 4971e7801d59Ssowmini ptr = print_wlan_attr(wfp, &w1); 4972e7801d59Ssowmini return (ptr); 49730ba2cbe9Sxc151355 } 49740ba2cbe9Sxc151355 4975d62bc4baSyz147064 static int 4976*4ac67f02SAnurag S. Maskey show_wifi(dladm_handle_t dh, datalink_id_t linkid, void *arg) 49770ba2cbe9Sxc151355 { 49780ba2cbe9Sxc151355 print_wifi_state_t *statep = arg; 4979f595a68aSyz147064 dladm_wlan_linkattr_t attr; 4980f595a68aSyz147064 dladm_status_t status; 4981d62bc4baSyz147064 char link[MAXLINKNAMELEN]; 4982e7801d59Ssowmini wlan_scan_args_t warg; 49830ba2cbe9Sxc151355 4984*4ac67f02SAnurag S. Maskey if ((status = dladm_datalink_id2info(dh, linkid, NULL, NULL, NULL, link, 4985e7801d59Ssowmini sizeof (link))) != DLADM_STATUS_OK) { 4986d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 4987d62bc4baSyz147064 } 4988d62bc4baSyz147064 49895f5c9f54SAnurag S. Maskey /* dladm_wlan_get_linkattr() memsets attr with 0 */ 4990*4ac67f02SAnurag S. Maskey status = dladm_wlan_get_linkattr(dh, linkid, &attr); 4991f595a68aSyz147064 if (status != DLADM_STATUS_OK) 4992d62bc4baSyz147064 die_dlerr(status, "cannot get link attributes for %s", link); 4993d62bc4baSyz147064 4994d62bc4baSyz147064 statep->ws_link = link; 49950ba2cbe9Sxc151355 49960ba2cbe9Sxc151355 if (statep->ws_header) { 49970ba2cbe9Sxc151355 statep->ws_header = B_FALSE; 49980ba2cbe9Sxc151355 if (!statep->ws_parseable) 4999e7801d59Ssowmini print_header(&statep->ws_print_state); 50000ba2cbe9Sxc151355 } 50010ba2cbe9Sxc151355 5002e7801d59Ssowmini statep->ws_print_state.ps_overflow = 0; 5003e7801d59Ssowmini bzero(&warg, sizeof (warg)); 5004e7801d59Ssowmini warg.ws_state = statep; 5005e7801d59Ssowmini warg.ws_attr = &attr; 5006e7801d59Ssowmini dladm_print_output(&statep->ws_print_state, statep->ws_parseable, 5007e7801d59Ssowmini print_link_attr, &warg); 5008d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 50090ba2cbe9Sxc151355 } 50100ba2cbe9Sxc151355 50110ba2cbe9Sxc151355 static void 50128d5c46e6Sam223141 do_display_wifi(int argc, char **argv, int cmd, const char *use) 50130ba2cbe9Sxc151355 { 50140ba2cbe9Sxc151355 int option; 50150ba2cbe9Sxc151355 char *fields_str = NULL; 5016e7801d59Ssowmini print_field_t **fields; 5017*4ac67f02SAnurag S. Maskey int (*callback)(dladm_handle_t, datalink_id_t, void *); 50180ba2cbe9Sxc151355 uint_t nfields; 50190ba2cbe9Sxc151355 print_wifi_state_t state; 5020d62bc4baSyz147064 datalink_id_t linkid = DATALINK_ALL_LINKID; 5021f595a68aSyz147064 dladm_status_t status; 50220ba2cbe9Sxc151355 50230ba2cbe9Sxc151355 if (cmd == WIFI_CMD_SCAN) 50240ba2cbe9Sxc151355 callback = scan_wifi; 50250ba2cbe9Sxc151355 else if (cmd == WIFI_CMD_SHOW) 50260ba2cbe9Sxc151355 callback = show_wifi; 50270ba2cbe9Sxc151355 else 50280ba2cbe9Sxc151355 return; 50290ba2cbe9Sxc151355 50300ba2cbe9Sxc151355 state.ws_parseable = B_FALSE; 50310ba2cbe9Sxc151355 state.ws_header = B_TRUE; 50320ba2cbe9Sxc151355 opterr = 0; 50330ba2cbe9Sxc151355 while ((option = getopt_long(argc, argv, ":o:p", 50340ba2cbe9Sxc151355 wifi_longopts, NULL)) != -1) { 50350ba2cbe9Sxc151355 switch (option) { 50360ba2cbe9Sxc151355 case 'o': 50370ba2cbe9Sxc151355 fields_str = optarg; 50380ba2cbe9Sxc151355 break; 50390ba2cbe9Sxc151355 case 'p': 50400ba2cbe9Sxc151355 state.ws_parseable = B_TRUE; 50410ba2cbe9Sxc151355 break; 50420ba2cbe9Sxc151355 default: 50438d5c46e6Sam223141 die_opterr(optopt, option, use); 50440ba2cbe9Sxc151355 } 50450ba2cbe9Sxc151355 } 50460ba2cbe9Sxc151355 50470d365605Sschuster if (state.ws_parseable && fields_str == NULL) 50480d365605Sschuster die("-p requires -o"); 50490d365605Sschuster 50500d365605Sschuster if (state.ws_parseable && strcasecmp(fields_str, "all") == 0) 50510d365605Sschuster die("\"-o all\" is invalid with -p"); 50520d365605Sschuster 5053d62bc4baSyz147064 if (optind == (argc - 1)) { 5054*4ac67f02SAnurag S. Maskey if ((status = dladm_name2info(handle, argv[optind], &linkid, 5055*4ac67f02SAnurag S. Maskey NULL, NULL, NULL)) != DLADM_STATUS_OK) { 5056d62bc4baSyz147064 die_dlerr(status, "link %s is not valid", argv[optind]); 5057d62bc4baSyz147064 } 5058d62bc4baSyz147064 } else if (optind != argc) { 50590ba2cbe9Sxc151355 usage(); 5060d62bc4baSyz147064 } 50610ba2cbe9Sxc151355 506233343a97Smeem if (parse_wifi_fields(fields_str, &fields, &nfields, cmd) < 0) 506333343a97Smeem die("invalid field(s) specified"); 506433343a97Smeem 5065e7801d59Ssowmini bzero(&state.ws_print_state, sizeof (state.ws_print_state)); 5066e7801d59Ssowmini state.ws_print_state.ps_fields = fields; 5067e7801d59Ssowmini state.ws_print_state.ps_nfields = nfields; 50680ba2cbe9Sxc151355 5069d62bc4baSyz147064 if (linkid == DATALINK_ALL_LINKID) { 5070*4ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(callback, handle, &state, 5071d62bc4baSyz147064 DATALINK_CLASS_PHYS, DL_WIFI, DLADM_OPT_ACTIVE); 50720ba2cbe9Sxc151355 } else { 5073*4ac67f02SAnurag S. Maskey (void) (*callback)(handle, linkid, &state); 50740ba2cbe9Sxc151355 } 50750ba2cbe9Sxc151355 free(fields); 50760ba2cbe9Sxc151355 } 50770ba2cbe9Sxc151355 50780ba2cbe9Sxc151355 static void 50798d5c46e6Sam223141 do_scan_wifi(int argc, char **argv, const char *use) 50800ba2cbe9Sxc151355 { 50818d5c46e6Sam223141 do_display_wifi(argc, argv, WIFI_CMD_SCAN, use); 50820ba2cbe9Sxc151355 } 50830ba2cbe9Sxc151355 50840ba2cbe9Sxc151355 static void 50858d5c46e6Sam223141 do_show_wifi(int argc, char **argv, const char *use) 50860ba2cbe9Sxc151355 { 50878d5c46e6Sam223141 do_display_wifi(argc, argv, WIFI_CMD_SHOW, use); 50880ba2cbe9Sxc151355 } 50890ba2cbe9Sxc151355 50900ba2cbe9Sxc151355 typedef struct wlan_count_attr { 50910ba2cbe9Sxc151355 uint_t wc_count; 5092d62bc4baSyz147064 datalink_id_t wc_linkid; 50930ba2cbe9Sxc151355 } wlan_count_attr_t; 50940ba2cbe9Sxc151355 5095*4ac67f02SAnurag S. Maskey /* ARGSUSED */ 5096d62bc4baSyz147064 static int 5097*4ac67f02SAnurag S. Maskey do_count_wlan(dladm_handle_t dh, datalink_id_t linkid, void *arg) 50980ba2cbe9Sxc151355 { 509933343a97Smeem wlan_count_attr_t *cp = arg; 51000ba2cbe9Sxc151355 51010ba2cbe9Sxc151355 if (cp->wc_count == 0) 5102d62bc4baSyz147064 cp->wc_linkid = linkid; 51030ba2cbe9Sxc151355 cp->wc_count++; 5104d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 51050ba2cbe9Sxc151355 } 51060ba2cbe9Sxc151355 51070ba2cbe9Sxc151355 static int 5108a399b765Szf162725 parse_wlan_keys(char *str, dladm_wlan_key_t **keys, uint_t *key_countp) 51090ba2cbe9Sxc151355 { 51100ba2cbe9Sxc151355 uint_t i; 51110ba2cbe9Sxc151355 split_t *sp; 5112a399b765Szf162725 dladm_wlan_key_t *wk; 51130ba2cbe9Sxc151355 5114a399b765Szf162725 sp = split(str, DLADM_WLAN_MAX_WEPKEYS, DLADM_WLAN_MAX_KEYNAME_LEN); 51150ba2cbe9Sxc151355 if (sp == NULL) 51160ba2cbe9Sxc151355 return (-1); 51170ba2cbe9Sxc151355 5118a399b765Szf162725 wk = malloc(sp->s_nfields * sizeof (dladm_wlan_key_t)); 51190ba2cbe9Sxc151355 if (wk == NULL) 51200ba2cbe9Sxc151355 goto fail; 51210ba2cbe9Sxc151355 51220ba2cbe9Sxc151355 for (i = 0; i < sp->s_nfields; i++) { 51230ba2cbe9Sxc151355 char *s; 51240ba2cbe9Sxc151355 dladm_secobj_class_t class; 51250ba2cbe9Sxc151355 dladm_status_t status; 51260ba2cbe9Sxc151355 51270ba2cbe9Sxc151355 (void) strlcpy(wk[i].wk_name, sp->s_fields[i], 5128a399b765Szf162725 DLADM_WLAN_MAX_KEYNAME_LEN); 51290ba2cbe9Sxc151355 51300ba2cbe9Sxc151355 wk[i].wk_idx = 1; 51310ba2cbe9Sxc151355 if ((s = strrchr(wk[i].wk_name, ':')) != NULL) { 51320ba2cbe9Sxc151355 if (s[1] == '\0' || s[2] != '\0' || !isdigit(s[1])) 51330ba2cbe9Sxc151355 goto fail; 51340ba2cbe9Sxc151355 51350ba2cbe9Sxc151355 wk[i].wk_idx = (uint_t)(s[1] - '0'); 51360ba2cbe9Sxc151355 *s = '\0'; 51370ba2cbe9Sxc151355 } 5138a399b765Szf162725 wk[i].wk_len = DLADM_WLAN_MAX_KEY_LEN; 51390ba2cbe9Sxc151355 5140*4ac67f02SAnurag S. Maskey status = dladm_get_secobj(handle, wk[i].wk_name, &class, 51410ba2cbe9Sxc151355 wk[i].wk_val, &wk[i].wk_len, 0); 51420ba2cbe9Sxc151355 if (status != DLADM_STATUS_OK) { 51430ba2cbe9Sxc151355 if (status == DLADM_STATUS_NOTFOUND) { 5144*4ac67f02SAnurag S. Maskey status = dladm_get_secobj(handle, wk[i].wk_name, 51450ba2cbe9Sxc151355 &class, wk[i].wk_val, &wk[i].wk_len, 51460ba2cbe9Sxc151355 DLADM_OPT_PERSIST); 51470ba2cbe9Sxc151355 } 51480ba2cbe9Sxc151355 if (status != DLADM_STATUS_OK) 51490ba2cbe9Sxc151355 goto fail; 51500ba2cbe9Sxc151355 } 5151a399b765Szf162725 wk[i].wk_class = class; 51520ba2cbe9Sxc151355 } 51530ba2cbe9Sxc151355 *keys = wk; 51540ba2cbe9Sxc151355 *key_countp = i; 51550ba2cbe9Sxc151355 splitfree(sp); 51560ba2cbe9Sxc151355 return (0); 51570ba2cbe9Sxc151355 fail: 51580ba2cbe9Sxc151355 free(wk); 51590ba2cbe9Sxc151355 splitfree(sp); 51600ba2cbe9Sxc151355 return (-1); 51610ba2cbe9Sxc151355 } 51620ba2cbe9Sxc151355 51630ba2cbe9Sxc151355 static void 51648d5c46e6Sam223141 do_connect_wifi(int argc, char **argv, const char *use) 51650ba2cbe9Sxc151355 { 51660ba2cbe9Sxc151355 int option; 5167f595a68aSyz147064 dladm_wlan_attr_t attr, *attrp; 5168f595a68aSyz147064 dladm_status_t status = DLADM_STATUS_OK; 5169f595a68aSyz147064 int timeout = DLADM_WLAN_CONNECT_TIMEOUT_DEFAULT; 5170d62bc4baSyz147064 datalink_id_t linkid = DATALINK_ALL_LINKID; 5171a399b765Szf162725 dladm_wlan_key_t *keys = NULL; 51720ba2cbe9Sxc151355 uint_t key_count = 0; 51730ba2cbe9Sxc151355 uint_t flags = 0; 5174f595a68aSyz147064 dladm_wlan_secmode_t keysecmode = DLADM_WLAN_SECMODE_NONE; 5175a399b765Szf162725 char buf[DLADM_STRSIZE]; 51760ba2cbe9Sxc151355 51770ba2cbe9Sxc151355 opterr = 0; 51780ba2cbe9Sxc151355 (void) memset(&attr, 0, sizeof (attr)); 51790ba2cbe9Sxc151355 while ((option = getopt_long(argc, argv, ":e:i:a:m:b:s:k:T:c", 51800ba2cbe9Sxc151355 wifi_longopts, NULL)) != -1) { 51810ba2cbe9Sxc151355 switch (option) { 51820ba2cbe9Sxc151355 case 'e': 5183f595a68aSyz147064 status = dladm_wlan_str2essid(optarg, &attr.wa_essid); 5184f595a68aSyz147064 if (status != DLADM_STATUS_OK) 518533343a97Smeem die("invalid ESSID '%s'", optarg); 518633343a97Smeem 5187f595a68aSyz147064 attr.wa_valid |= DLADM_WLAN_ATTR_ESSID; 51880ba2cbe9Sxc151355 /* 51890ba2cbe9Sxc151355 * Try to connect without doing a scan. 51900ba2cbe9Sxc151355 */ 5191f595a68aSyz147064 flags |= DLADM_WLAN_CONNECT_NOSCAN; 51920ba2cbe9Sxc151355 break; 51930ba2cbe9Sxc151355 case 'i': 5194f595a68aSyz147064 status = dladm_wlan_str2bssid(optarg, &attr.wa_bssid); 5195f595a68aSyz147064 if (status != DLADM_STATUS_OK) 519633343a97Smeem die("invalid BSSID %s", optarg); 519733343a97Smeem 5198f595a68aSyz147064 attr.wa_valid |= DLADM_WLAN_ATTR_BSSID; 51990ba2cbe9Sxc151355 break; 52000ba2cbe9Sxc151355 case 'a': 5201f595a68aSyz147064 status = dladm_wlan_str2auth(optarg, &attr.wa_auth); 5202f595a68aSyz147064 if (status != DLADM_STATUS_OK) 520333343a97Smeem die("invalid authentication mode '%s'", optarg); 520433343a97Smeem 5205f595a68aSyz147064 attr.wa_valid |= DLADM_WLAN_ATTR_AUTH; 52060ba2cbe9Sxc151355 break; 52070ba2cbe9Sxc151355 case 'm': 5208f595a68aSyz147064 status = dladm_wlan_str2mode(optarg, &attr.wa_mode); 5209f595a68aSyz147064 if (status != DLADM_STATUS_OK) 521033343a97Smeem die("invalid mode '%s'", optarg); 521133343a97Smeem 5212f595a68aSyz147064 attr.wa_valid |= DLADM_WLAN_ATTR_MODE; 52130ba2cbe9Sxc151355 break; 52140ba2cbe9Sxc151355 case 'b': 5215f595a68aSyz147064 if ((status = dladm_wlan_str2bsstype(optarg, 5216f595a68aSyz147064 &attr.wa_bsstype)) != DLADM_STATUS_OK) { 521733343a97Smeem die("invalid bsstype '%s'", optarg); 5218f595a68aSyz147064 } 521933343a97Smeem 5220f595a68aSyz147064 attr.wa_valid |= DLADM_WLAN_ATTR_BSSTYPE; 52210ba2cbe9Sxc151355 break; 52220ba2cbe9Sxc151355 case 's': 5223f595a68aSyz147064 if ((status = dladm_wlan_str2secmode(optarg, 5224f595a68aSyz147064 &attr.wa_secmode)) != DLADM_STATUS_OK) { 522533343a97Smeem die("invalid security mode '%s'", optarg); 5226f595a68aSyz147064 } 522733343a97Smeem 5228f595a68aSyz147064 attr.wa_valid |= DLADM_WLAN_ATTR_SECMODE; 52290ba2cbe9Sxc151355 break; 52300ba2cbe9Sxc151355 case 'k': 5231a399b765Szf162725 if (parse_wlan_keys(optarg, &keys, &key_count) < 0) 523233343a97Smeem die("invalid key(s) '%s'", optarg); 523333343a97Smeem 5234a399b765Szf162725 if (keys[0].wk_class == DLADM_SECOBJ_CLASS_WEP) 5235f595a68aSyz147064 keysecmode = DLADM_WLAN_SECMODE_WEP; 5236a399b765Szf162725 else 5237a399b765Szf162725 keysecmode = DLADM_WLAN_SECMODE_WPA; 52380ba2cbe9Sxc151355 break; 52390ba2cbe9Sxc151355 case 'T': 52400ba2cbe9Sxc151355 if (strcasecmp(optarg, "forever") == 0) { 52410ba2cbe9Sxc151355 timeout = -1; 52420ba2cbe9Sxc151355 break; 52430ba2cbe9Sxc151355 } 524433343a97Smeem if (!str2int(optarg, &timeout) || timeout < 0) 524533343a97Smeem die("invalid timeout value '%s'", optarg); 52460ba2cbe9Sxc151355 break; 52470ba2cbe9Sxc151355 case 'c': 5248f595a68aSyz147064 flags |= DLADM_WLAN_CONNECT_CREATEIBSS; 5249a399b765Szf162725 flags |= DLADM_WLAN_CONNECT_CREATEIBSS; 52500ba2cbe9Sxc151355 break; 52510ba2cbe9Sxc151355 default: 52528d5c46e6Sam223141 die_opterr(optopt, option, use); 52530ba2cbe9Sxc151355 break; 52540ba2cbe9Sxc151355 } 52550ba2cbe9Sxc151355 } 52560ba2cbe9Sxc151355 5257f595a68aSyz147064 if (keysecmode == DLADM_WLAN_SECMODE_NONE) { 5258a399b765Szf162725 if ((attr.wa_valid & DLADM_WLAN_ATTR_SECMODE) != 0) { 5259a399b765Szf162725 die("key required for security mode '%s'", 5260a399b765Szf162725 dladm_wlan_secmode2str(&attr.wa_secmode, buf)); 5261a399b765Szf162725 } 52620ba2cbe9Sxc151355 } else { 5263f595a68aSyz147064 if ((attr.wa_valid & DLADM_WLAN_ATTR_SECMODE) != 0 && 526433343a97Smeem attr.wa_secmode != keysecmode) 526533343a97Smeem die("incompatible -s and -k options"); 5266f595a68aSyz147064 attr.wa_valid |= DLADM_WLAN_ATTR_SECMODE; 5267a399b765Szf162725 attr.wa_secmode = keysecmode; 5268a399b765Szf162725 } 52690ba2cbe9Sxc151355 5270d62bc4baSyz147064 if (optind == (argc - 1)) { 5271*4ac67f02SAnurag S. Maskey if ((status = dladm_name2info(handle, argv[optind], &linkid, 5272*4ac67f02SAnurag S. Maskey NULL, NULL, NULL)) != DLADM_STATUS_OK) { 5273d62bc4baSyz147064 die_dlerr(status, "link %s is not valid", argv[optind]); 5274d62bc4baSyz147064 } 5275d62bc4baSyz147064 } else if (optind != argc) { 52760ba2cbe9Sxc151355 usage(); 5277d62bc4baSyz147064 } 52780ba2cbe9Sxc151355 5279d62bc4baSyz147064 if (linkid == DATALINK_ALL_LINKID) { 52800ba2cbe9Sxc151355 wlan_count_attr_t wcattr; 52810ba2cbe9Sxc151355 5282d62bc4baSyz147064 wcattr.wc_linkid = DATALINK_INVALID_LINKID; 52830ba2cbe9Sxc151355 wcattr.wc_count = 0; 5284*4ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(do_count_wlan, handle, &wcattr, 5285d62bc4baSyz147064 DATALINK_CLASS_PHYS, DL_WIFI, DLADM_OPT_ACTIVE); 52860ba2cbe9Sxc151355 if (wcattr.wc_count == 0) { 528733343a97Smeem die("no wifi links are available"); 52880ba2cbe9Sxc151355 } else if (wcattr.wc_count > 1) { 528933343a97Smeem die("link name is required when more than one wifi " 529033343a97Smeem "link is available"); 52910ba2cbe9Sxc151355 } 5292d62bc4baSyz147064 linkid = wcattr.wc_linkid; 52930ba2cbe9Sxc151355 } 52940ba2cbe9Sxc151355 attrp = (attr.wa_valid == 0) ? NULL : &attr; 529533343a97Smeem again: 5296*4ac67f02SAnurag S. Maskey if ((status = dladm_wlan_connect(handle, linkid, attrp, timeout, keys, 5297f595a68aSyz147064 key_count, flags)) != DLADM_STATUS_OK) { 5298f595a68aSyz147064 if ((flags & DLADM_WLAN_CONNECT_NOSCAN) != 0) { 52990ba2cbe9Sxc151355 /* 530033343a97Smeem * Try again with scanning and filtering. 53010ba2cbe9Sxc151355 */ 5302f595a68aSyz147064 flags &= ~DLADM_WLAN_CONNECT_NOSCAN; 530333343a97Smeem goto again; 53040ba2cbe9Sxc151355 } 530533343a97Smeem 5306f595a68aSyz147064 if (status == DLADM_STATUS_NOTFOUND) { 53070ba2cbe9Sxc151355 if (attr.wa_valid == 0) { 530833343a97Smeem die("no wifi networks are available"); 53090ba2cbe9Sxc151355 } else { 531033343a97Smeem die("no wifi networks with the specified " 531133343a97Smeem "criteria are available"); 53120ba2cbe9Sxc151355 } 53130ba2cbe9Sxc151355 } 5314d62bc4baSyz147064 die_dlerr(status, "cannot connect"); 53150ba2cbe9Sxc151355 } 53160ba2cbe9Sxc151355 free(keys); 53170ba2cbe9Sxc151355 } 53180ba2cbe9Sxc151355 53190ba2cbe9Sxc151355 /* ARGSUSED */ 5320d62bc4baSyz147064 static int 5321*4ac67f02SAnurag S. Maskey do_all_disconnect_wifi(dladm_handle_t dh, datalink_id_t linkid, void *arg) 53220ba2cbe9Sxc151355 { 5323f595a68aSyz147064 dladm_status_t status; 53240ba2cbe9Sxc151355 5325*4ac67f02SAnurag S. Maskey status = dladm_wlan_disconnect(dh, linkid); 5326f595a68aSyz147064 if (status != DLADM_STATUS_OK) 5327d62bc4baSyz147064 warn_dlerr(status, "cannot disconnect link"); 532833343a97Smeem 5329d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 53300ba2cbe9Sxc151355 } 53310ba2cbe9Sxc151355 53320ba2cbe9Sxc151355 static void 53338d5c46e6Sam223141 do_disconnect_wifi(int argc, char **argv, const char *use) 53340ba2cbe9Sxc151355 { 53350ba2cbe9Sxc151355 int option; 5336d62bc4baSyz147064 datalink_id_t linkid = DATALINK_ALL_LINKID; 53370ba2cbe9Sxc151355 boolean_t all_links = B_FALSE; 5338f595a68aSyz147064 dladm_status_t status; 53390ba2cbe9Sxc151355 wlan_count_attr_t wcattr; 53400ba2cbe9Sxc151355 53410ba2cbe9Sxc151355 opterr = 0; 53420ba2cbe9Sxc151355 while ((option = getopt_long(argc, argv, ":a", 53430ba2cbe9Sxc151355 wifi_longopts, NULL)) != -1) { 53440ba2cbe9Sxc151355 switch (option) { 53450ba2cbe9Sxc151355 case 'a': 53460ba2cbe9Sxc151355 all_links = B_TRUE; 53470ba2cbe9Sxc151355 break; 53480ba2cbe9Sxc151355 default: 53498d5c46e6Sam223141 die_opterr(optopt, option, use); 53500ba2cbe9Sxc151355 break; 53510ba2cbe9Sxc151355 } 53520ba2cbe9Sxc151355 } 53530ba2cbe9Sxc151355 5354d62bc4baSyz147064 if (optind == (argc - 1)) { 5355*4ac67f02SAnurag S. Maskey if ((status = dladm_name2info(handle, argv[optind], &linkid, 5356*4ac67f02SAnurag S. Maskey NULL, NULL, NULL)) != DLADM_STATUS_OK) { 5357d62bc4baSyz147064 die_dlerr(status, "link %s is not valid", argv[optind]); 5358d62bc4baSyz147064 } 5359d62bc4baSyz147064 } else if (optind != argc) { 53600ba2cbe9Sxc151355 usage(); 5361d62bc4baSyz147064 } 53620ba2cbe9Sxc151355 5363d62bc4baSyz147064 if (linkid == DATALINK_ALL_LINKID) { 53640ba2cbe9Sxc151355 if (!all_links) { 5365d62bc4baSyz147064 wcattr.wc_linkid = linkid; 53660ba2cbe9Sxc151355 wcattr.wc_count = 0; 5367*4ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(do_count_wlan, handle, 5368*4ac67f02SAnurag S. Maskey &wcattr, DATALINK_CLASS_PHYS, DL_WIFI, 5369*4ac67f02SAnurag S. Maskey DLADM_OPT_ACTIVE); 53700ba2cbe9Sxc151355 if (wcattr.wc_count == 0) { 537133343a97Smeem die("no wifi links are available"); 53720ba2cbe9Sxc151355 } else if (wcattr.wc_count > 1) { 537333343a97Smeem die("link name is required when more than " 537433343a97Smeem "one wifi link is available"); 53750ba2cbe9Sxc151355 } 5376d62bc4baSyz147064 linkid = wcattr.wc_linkid; 53770ba2cbe9Sxc151355 } else { 5378d62bc4baSyz147064 (void) dladm_walk_datalink_id(do_all_disconnect_wifi, 5379*4ac67f02SAnurag S. Maskey handle, NULL, DATALINK_CLASS_PHYS, DL_WIFI, 5380d62bc4baSyz147064 DLADM_OPT_ACTIVE); 53810ba2cbe9Sxc151355 return; 53820ba2cbe9Sxc151355 } 53830ba2cbe9Sxc151355 } 5384*4ac67f02SAnurag S. Maskey status = dladm_wlan_disconnect(handle, linkid); 5385f595a68aSyz147064 if (status != DLADM_STATUS_OK) 5386d62bc4baSyz147064 die_dlerr(status, "cannot disconnect"); 53870ba2cbe9Sxc151355 } 53880ba2cbe9Sxc151355 53890ba2cbe9Sxc151355 static void 5390d62bc4baSyz147064 print_linkprop(datalink_id_t linkid, show_linkprop_state_t *statep, 5391*4ac67f02SAnurag S. Maskey const char *propname, dladm_prop_type_t type, const char *format, 5392*4ac67f02SAnurag S. Maskey char **pptr) 53930ba2cbe9Sxc151355 { 53940ba2cbe9Sxc151355 int i; 53950ba2cbe9Sxc151355 char *ptr, *lim; 53960ba2cbe9Sxc151355 char buf[DLADM_STRSIZE]; 5397da14cebeSEric Cheng char *unknown = "--", *notsup = ""; 53980ba2cbe9Sxc151355 char **propvals = statep->ls_propvals; 5399d62bc4baSyz147064 uint_t valcnt = DLADM_MAX_PROP_VALCNT; 54000ba2cbe9Sxc151355 dladm_status_t status; 54010ba2cbe9Sxc151355 5402*4ac67f02SAnurag S. Maskey status = dladm_get_linkprop(handle, linkid, type, propname, propvals, 5403*4ac67f02SAnurag S. Maskey &valcnt); 54040ba2cbe9Sxc151355 if (status != DLADM_STATUS_OK) { 5405f595a68aSyz147064 if (status == DLADM_STATUS_TEMPONLY) { 5406d62bc4baSyz147064 if (type == DLADM_PROP_VAL_MODIFIABLE && 5407d62bc4baSyz147064 statep->ls_persist) { 5408d62bc4baSyz147064 valcnt = 1; 5409d62bc4baSyz147064 propvals = &unknown; 5410d62bc4baSyz147064 } else { 5411f595a68aSyz147064 statep->ls_status = status; 5412e7801d59Ssowmini statep->ls_retstatus = status; 5413f595a68aSyz147064 return; 5414d62bc4baSyz147064 } 5415f595a68aSyz147064 } else if (status == DLADM_STATUS_NOTSUP || 5416f595a68aSyz147064 statep->ls_persist) { 54170ba2cbe9Sxc151355 valcnt = 1; 5418afdda45fSVasumathi Sundaram - Sun Microsystems if (type == DLADM_PROP_VAL_CURRENT || 5419afdda45fSVasumathi Sundaram - Sun Microsystems type == DLADM_PROP_VAL_PERM) 54200ba2cbe9Sxc151355 propvals = &unknown; 54210ba2cbe9Sxc151355 else 54220ba2cbe9Sxc151355 propvals = ¬sup; 5423149b7eb2SSowmini Varadhan } else if (status == DLADM_STATUS_NOTDEFINED) { 5424149b7eb2SSowmini Varadhan propvals = ¬sup; /* STR_UNDEF_VAL */ 54250ba2cbe9Sxc151355 } else { 5426e7801d59Ssowmini if (statep->ls_proplist && 5427e7801d59Ssowmini statep->ls_status == DLADM_STATUS_OK) { 5428f595a68aSyz147064 warn_dlerr(status, 5429f595a68aSyz147064 "cannot get link property '%s' for %s", 5430f595a68aSyz147064 propname, statep->ls_link); 5431d62bc4baSyz147064 } 5432e7801d59Ssowmini statep->ls_status = status; 5433e7801d59Ssowmini statep->ls_retstatus = status; 5434f595a68aSyz147064 return; 54350ba2cbe9Sxc151355 } 54360ba2cbe9Sxc151355 } 54370ba2cbe9Sxc151355 5438e7801d59Ssowmini statep->ls_status = DLADM_STATUS_OK; 5439e7801d59Ssowmini 54400ba2cbe9Sxc151355 ptr = buf; 54410ba2cbe9Sxc151355 lim = buf + DLADM_STRSIZE; 54420ba2cbe9Sxc151355 for (i = 0; i < valcnt; i++) { 54430ba2cbe9Sxc151355 if (propvals[i][0] == '\0' && !statep->ls_parseable) 5444e7801d59Ssowmini ptr += snprintf(ptr, lim - ptr, STR_UNDEF_VAL","); 54450ba2cbe9Sxc151355 else 54460ba2cbe9Sxc151355 ptr += snprintf(ptr, lim - ptr, "%s,", propvals[i]); 54470ba2cbe9Sxc151355 if (ptr >= lim) 54480ba2cbe9Sxc151355 break; 54490ba2cbe9Sxc151355 } 54500ba2cbe9Sxc151355 if (valcnt > 0) 54510ba2cbe9Sxc151355 buf[strlen(buf) - 1] = '\0'; 54520ba2cbe9Sxc151355 54530ba2cbe9Sxc151355 lim = statep->ls_line + MAX_PROP_LINE; 54540ba2cbe9Sxc151355 if (statep->ls_parseable) { 54550ba2cbe9Sxc151355 *pptr += snprintf(*pptr, lim - *pptr, 5456e7801d59Ssowmini "%s", buf); 54570ba2cbe9Sxc151355 } else { 54580ba2cbe9Sxc151355 *pptr += snprintf(*pptr, lim - *pptr, format, buf); 54590ba2cbe9Sxc151355 } 54600ba2cbe9Sxc151355 } 54610ba2cbe9Sxc151355 5462e7801d59Ssowmini static char * 5463e7801d59Ssowmini linkprop_callback(print_field_t *pf, void *ls_arg) 5464e7801d59Ssowmini { 5465e7801d59Ssowmini linkprop_args_t *arg = ls_arg; 5466e7801d59Ssowmini char *propname = arg->ls_propname; 5467e7801d59Ssowmini show_linkprop_state_t *statep = arg->ls_state; 5468e7801d59Ssowmini char *ptr = statep->ls_line; 5469e7801d59Ssowmini char *lim = ptr + MAX_PROP_LINE; 5470e7801d59Ssowmini datalink_id_t linkid = arg->ls_linkid; 5471e7801d59Ssowmini 5472e7801d59Ssowmini switch (pf->pf_index) { 5473e7801d59Ssowmini case LINKPROP_LINK: 5474e7801d59Ssowmini (void) snprintf(ptr, lim - ptr, "%s", statep->ls_link); 5475e7801d59Ssowmini break; 5476e7801d59Ssowmini case LINKPROP_PROPERTY: 5477e7801d59Ssowmini (void) snprintf(ptr, lim - ptr, "%s", propname); 5478e7801d59Ssowmini break; 5479e7801d59Ssowmini case LINKPROP_VALUE: 5480e7801d59Ssowmini print_linkprop(linkid, statep, propname, 5481e7801d59Ssowmini statep->ls_persist ? DLADM_PROP_VAL_PERSISTENT : 5482e7801d59Ssowmini DLADM_PROP_VAL_CURRENT, "%s", &ptr); 5483e7801d59Ssowmini /* 5484e7801d59Ssowmini * If we failed to query the link property, for example, query 5485e7801d59Ssowmini * the persistent value of a non-persistable link property, 5486e7801d59Ssowmini * simply skip the output. 5487e7801d59Ssowmini */ 5488e7801d59Ssowmini if (statep->ls_status != DLADM_STATUS_OK) 5489e7801d59Ssowmini goto skip; 5490e7801d59Ssowmini ptr = statep->ls_line; 5491e7801d59Ssowmini break; 5492afdda45fSVasumathi Sundaram - Sun Microsystems case LINKPROP_PERM: 5493afdda45fSVasumathi Sundaram - Sun Microsystems print_linkprop(linkid, statep, propname, 5494afdda45fSVasumathi Sundaram - Sun Microsystems DLADM_PROP_VAL_PERM, "%s", &ptr); 5495afdda45fSVasumathi Sundaram - Sun Microsystems if (statep->ls_status != DLADM_STATUS_OK) 5496afdda45fSVasumathi Sundaram - Sun Microsystems goto skip; 5497afdda45fSVasumathi Sundaram - Sun Microsystems ptr = statep->ls_line; 5498afdda45fSVasumathi Sundaram - Sun Microsystems break; 5499e7801d59Ssowmini case LINKPROP_DEFAULT: 5500e7801d59Ssowmini print_linkprop(linkid, statep, propname, 5501e7801d59Ssowmini DLADM_PROP_VAL_DEFAULT, "%s", &ptr); 5502e7801d59Ssowmini if (statep->ls_status != DLADM_STATUS_OK) 5503e7801d59Ssowmini goto skip; 5504e7801d59Ssowmini ptr = statep->ls_line; 5505e7801d59Ssowmini break; 5506e7801d59Ssowmini case LINKPROP_POSSIBLE: 5507e7801d59Ssowmini print_linkprop(linkid, statep, propname, 5508e7801d59Ssowmini DLADM_PROP_VAL_MODIFIABLE, "%s ", &ptr); 5509e7801d59Ssowmini if (statep->ls_status != DLADM_STATUS_OK) 5510e7801d59Ssowmini goto skip; 5511e7801d59Ssowmini ptr = statep->ls_line; 5512e7801d59Ssowmini break; 5513e7801d59Ssowmini default: 5514e7801d59Ssowmini die("invalid input"); 5515e7801d59Ssowmini break; 5516e7801d59Ssowmini } 5517e7801d59Ssowmini return (ptr); 5518e7801d59Ssowmini skip: 5519e7801d59Ssowmini if (statep->ls_status != DLADM_STATUS_OK) 5520e7801d59Ssowmini return (NULL); 5521e7801d59Ssowmini else 5522e7801d59Ssowmini return (""); 5523e7801d59Ssowmini } 5524e7801d59Ssowmini 5525bcb5c89dSSowmini Varadhan static boolean_t 5526bcb5c89dSSowmini Varadhan linkprop_is_supported(datalink_id_t linkid, const char *propname, 5527bcb5c89dSSowmini Varadhan show_linkprop_state_t *statep) 5528bcb5c89dSSowmini Varadhan { 5529bcb5c89dSSowmini Varadhan dladm_status_t status; 5530bcb5c89dSSowmini Varadhan uint_t valcnt = DLADM_MAX_PROP_VALCNT; 5531bcb5c89dSSowmini Varadhan 55324784fcbdSSowmini Varadhan /* if used with -p flag, always print output */ 55334784fcbdSSowmini Varadhan if (statep->ls_proplist != NULL) 55344784fcbdSSowmini Varadhan return (B_TRUE); 55354784fcbdSSowmini Varadhan 5536*4ac67f02SAnurag S. Maskey status = dladm_get_linkprop(handle, linkid, DLADM_PROP_VAL_DEFAULT, 5537bcb5c89dSSowmini Varadhan propname, statep->ls_propvals, &valcnt); 5538bcb5c89dSSowmini Varadhan 5539149b7eb2SSowmini Varadhan if (status == DLADM_STATUS_OK) 5540149b7eb2SSowmini Varadhan return (B_TRUE); 5541149b7eb2SSowmini Varadhan 5542149b7eb2SSowmini Varadhan /* 5543149b7eb2SSowmini Varadhan * A system wide default value is not available for the 5544149b7eb2SSowmini Varadhan * property. Check if current value can be retrieved. 5545149b7eb2SSowmini Varadhan */ 5546*4ac67f02SAnurag S. Maskey status = dladm_get_linkprop(handle, linkid, DLADM_PROP_VAL_CURRENT, 5547149b7eb2SSowmini Varadhan propname, statep->ls_propvals, &valcnt); 5548149b7eb2SSowmini Varadhan 5549149b7eb2SSowmini Varadhan return (status == DLADM_STATUS_OK); 5550bcb5c89dSSowmini Varadhan } 5551bcb5c89dSSowmini Varadhan 5552*4ac67f02SAnurag S. Maskey /* ARGSUSED */ 5553d62bc4baSyz147064 static int 5554*4ac67f02SAnurag S. Maskey show_linkprop(dladm_handle_t dh, datalink_id_t linkid, const char *propname, 5555*4ac67f02SAnurag S. Maskey void *arg) 55560ba2cbe9Sxc151355 { 55570ba2cbe9Sxc151355 show_linkprop_state_t *statep = arg; 5558e7801d59Ssowmini linkprop_args_t ls_arg; 55590ba2cbe9Sxc151355 5560e7801d59Ssowmini bzero(&ls_arg, sizeof (ls_arg)); 5561e7801d59Ssowmini ls_arg.ls_state = statep; 5562e7801d59Ssowmini ls_arg.ls_propname = (char *)propname; 5563e7801d59Ssowmini ls_arg.ls_linkid = linkid; 55640ba2cbe9Sxc151355 55650ba2cbe9Sxc151355 if (statep->ls_header) { 55660ba2cbe9Sxc151355 statep->ls_header = B_FALSE; 55670ba2cbe9Sxc151355 if (!statep->ls_parseable) 5568e7801d59Ssowmini print_header(&statep->ls_print); 55690ba2cbe9Sxc151355 } 5570149b7eb2SSowmini Varadhan if (!statep->ls_parseable && 5571149b7eb2SSowmini Varadhan !linkprop_is_supported(linkid, propname, statep)) 5572bcb5c89dSSowmini Varadhan return (DLADM_WALK_CONTINUE); 5573bcb5c89dSSowmini Varadhan 5574e7801d59Ssowmini dladm_print_output(&statep->ls_print, statep->ls_parseable, 5575e7801d59Ssowmini linkprop_callback, (void *)&ls_arg); 5576e7801d59Ssowmini 5577d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 55780ba2cbe9Sxc151355 } 55790ba2cbe9Sxc151355 55800ba2cbe9Sxc151355 static void 55818d5c46e6Sam223141 do_show_linkprop(int argc, char **argv, const char *use) 55820ba2cbe9Sxc151355 { 5583f4b3ec61Sdh155122 int option; 5584da14cebeSEric Cheng dladm_arg_list_t *proplist = NULL; 5585d62bc4baSyz147064 datalink_id_t linkid = DATALINK_ALL_LINKID; 55860ba2cbe9Sxc151355 show_linkprop_state_t state; 5587d62bc4baSyz147064 uint32_t flags = DLADM_OPT_ACTIVE; 5588d62bc4baSyz147064 dladm_status_t status; 5589e7801d59Ssowmini char *fields_str = NULL; 5590e7801d59Ssowmini print_field_t **fields; 5591e7801d59Ssowmini uint_t nfields; 55920d365605Sschuster boolean_t o_arg = B_FALSE; 5593e7801d59Ssowmini char *all_fields = 5594afdda45fSVasumathi Sundaram - Sun Microsystems "link,property,perm,value,default,possible"; 5595e7801d59Ssowmini 5596e7801d59Ssowmini fields_str = all_fields; 55970ba2cbe9Sxc151355 55980ba2cbe9Sxc151355 opterr = 0; 55990ba2cbe9Sxc151355 state.ls_propvals = NULL; 56000ba2cbe9Sxc151355 state.ls_line = NULL; 56010ba2cbe9Sxc151355 state.ls_parseable = B_FALSE; 56020ba2cbe9Sxc151355 state.ls_persist = B_FALSE; 56030ba2cbe9Sxc151355 state.ls_header = B_TRUE; 5604e7801d59Ssowmini state.ls_retstatus = DLADM_STATUS_OK; 5605e7801d59Ssowmini while ((option = getopt_long(argc, argv, ":p:cPo:", 56060ba2cbe9Sxc151355 prop_longopts, NULL)) != -1) { 56070ba2cbe9Sxc151355 switch (option) { 56080ba2cbe9Sxc151355 case 'p': 5609da14cebeSEric Cheng if (dladm_parse_link_props(optarg, &proplist, B_TRUE) 5610da14cebeSEric Cheng != DLADM_STATUS_OK) 561113994ee8Sxz162242 die("invalid link properties specified"); 56120ba2cbe9Sxc151355 break; 56130ba2cbe9Sxc151355 case 'c': 56140ba2cbe9Sxc151355 state.ls_parseable = B_TRUE; 56150ba2cbe9Sxc151355 break; 56160ba2cbe9Sxc151355 case 'P': 56170ba2cbe9Sxc151355 state.ls_persist = B_TRUE; 5618d62bc4baSyz147064 flags = DLADM_OPT_PERSIST; 56190ba2cbe9Sxc151355 break; 5620e7801d59Ssowmini case 'o': 56210d365605Sschuster o_arg = B_TRUE; 5622e7801d59Ssowmini if (strcasecmp(optarg, "all") == 0) 5623e7801d59Ssowmini fields_str = all_fields; 5624e7801d59Ssowmini else 5625e7801d59Ssowmini fields_str = optarg; 5626e7801d59Ssowmini break; 56270ba2cbe9Sxc151355 default: 56288d5c46e6Sam223141 die_opterr(optopt, option, use); 56290ba2cbe9Sxc151355 break; 56300ba2cbe9Sxc151355 } 56310ba2cbe9Sxc151355 } 56320ba2cbe9Sxc151355 56330d365605Sschuster if (state.ls_parseable && !o_arg) 56340d365605Sschuster die("-c requires -o"); 56350d365605Sschuster 56360d365605Sschuster if (state.ls_parseable && fields_str == all_fields) 56370d365605Sschuster die("\"-o all\" is invalid with -c"); 56380d365605Sschuster 5639d62bc4baSyz147064 if (optind == (argc - 1)) { 5640*4ac67f02SAnurag S. Maskey if ((status = dladm_name2info(handle, argv[optind], &linkid, 5641*4ac67f02SAnurag S. Maskey NULL, NULL, NULL)) != DLADM_STATUS_OK) { 5642d62bc4baSyz147064 die_dlerr(status, "link %s is not valid", argv[optind]); 5643d62bc4baSyz147064 } 5644d62bc4baSyz147064 } else if (optind != argc) { 56450ba2cbe9Sxc151355 usage(); 5646d62bc4baSyz147064 } 56470ba2cbe9Sxc151355 5648e7801d59Ssowmini bzero(&state.ls_print, sizeof (print_state_t)); 5649f4b3ec61Sdh155122 state.ls_proplist = proplist; 5650f595a68aSyz147064 state.ls_status = DLADM_STATUS_OK; 5651f4b3ec61Sdh155122 5652e7801d59Ssowmini fields = parse_output_fields(fields_str, linkprop_fields, 5653e7801d59Ssowmini LINKPROP_MAX_FIELDS, CMD_TYPE_ANY, &nfields); 5654e7801d59Ssowmini 5655e7801d59Ssowmini if (fields == NULL) { 5656e7801d59Ssowmini die("invalid field(s) specified"); 5657e7801d59Ssowmini return; 5658e7801d59Ssowmini } 5659e7801d59Ssowmini 5660e7801d59Ssowmini state.ls_print.ps_fields = fields; 5661e7801d59Ssowmini state.ls_print.ps_nfields = nfields; 5662d62bc4baSyz147064 if (linkid == DATALINK_ALL_LINKID) { 5663*4ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(show_linkprop_onelink, handle, 5664*4ac67f02SAnurag S. Maskey &state, DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE, flags); 5665f4b3ec61Sdh155122 } else { 5666*4ac67f02SAnurag S. Maskey (void) show_linkprop_onelink(handle, linkid, &state); 5667f4b3ec61Sdh155122 } 5668da14cebeSEric Cheng dladm_free_props(proplist); 5669f595a68aSyz147064 5670*4ac67f02SAnurag S. Maskey if (state.ls_retstatus != DLADM_STATUS_OK) { 5671*4ac67f02SAnurag S. Maskey dladm_close(handle); 5672f595a68aSyz147064 exit(EXIT_FAILURE); 5673f4b3ec61Sdh155122 } 5674*4ac67f02SAnurag S. Maskey } 5675f4b3ec61Sdh155122 5676d62bc4baSyz147064 static int 5677*4ac67f02SAnurag S. Maskey show_linkprop_onelink(dladm_handle_t hdl, datalink_id_t linkid, void *arg) 5678f4b3ec61Sdh155122 { 5679948f2876Sss150715 int i; 5680f4b3ec61Sdh155122 char *buf; 5681d62bc4baSyz147064 uint32_t flags; 5682da14cebeSEric Cheng dladm_arg_list_t *proplist = NULL; 5683d62bc4baSyz147064 show_linkprop_state_t *statep = arg; 5684d62bc4baSyz147064 dlpi_handle_t dh = NULL; 5685f4b3ec61Sdh155122 5686d62bc4baSyz147064 statep->ls_status = DLADM_STATUS_OK; 5687d62bc4baSyz147064 5688*4ac67f02SAnurag S. Maskey if (dladm_datalink_id2info(hdl, linkid, &flags, NULL, NULL, 5689*4ac67f02SAnurag S. Maskey statep->ls_link, MAXLINKNAMELEN) != DLADM_STATUS_OK) { 5690d62bc4baSyz147064 statep->ls_status = DLADM_STATUS_NOTFOUND; 5691d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 5692d62bc4baSyz147064 } 5693d62bc4baSyz147064 5694d62bc4baSyz147064 if ((statep->ls_persist && !(flags & DLADM_OPT_PERSIST)) || 5695d62bc4baSyz147064 (!statep->ls_persist && !(flags & DLADM_OPT_ACTIVE))) { 5696d62bc4baSyz147064 statep->ls_status = DLADM_STATUS_BADARG; 5697d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 5698d62bc4baSyz147064 } 5699d62bc4baSyz147064 5700f4b3ec61Sdh155122 proplist = statep->ls_proplist; 57010ba2cbe9Sxc151355 57020ba2cbe9Sxc151355 /* 57030ba2cbe9Sxc151355 * When some WiFi links are opened for the first time, their hardware 57040ba2cbe9Sxc151355 * automatically scans for APs and does other slow operations. Thus, 57050ba2cbe9Sxc151355 * if there are no open links, the retrieval of link properties 57060ba2cbe9Sxc151355 * (below) will proceed slowly unless we hold the link open. 5707d62bc4baSyz147064 * 5708d62bc4baSyz147064 * Note that failure of dlpi_open() does not necessarily mean invalid 5709d62bc4baSyz147064 * link properties, because dlpi_open() may fail because of incorrect 5710d62bc4baSyz147064 * autopush configuration. Therefore, we ingore the return value of 5711d62bc4baSyz147064 * dlpi_open(). 57120ba2cbe9Sxc151355 */ 5713d62bc4baSyz147064 if (!statep->ls_persist) 5714d62bc4baSyz147064 (void) dlpi_open(statep->ls_link, &dh, 0); 57150ba2cbe9Sxc151355 5716d62bc4baSyz147064 buf = malloc((sizeof (char *) + DLADM_PROP_VAL_MAX) * 5717d62bc4baSyz147064 DLADM_MAX_PROP_VALCNT + MAX_PROP_LINE); 571833343a97Smeem if (buf == NULL) 571933343a97Smeem die("insufficient memory"); 572033343a97Smeem 5721f4b3ec61Sdh155122 statep->ls_propvals = (char **)(void *)buf; 5722d62bc4baSyz147064 for (i = 0; i < DLADM_MAX_PROP_VALCNT; i++) { 5723d62bc4baSyz147064 statep->ls_propvals[i] = buf + 5724d62bc4baSyz147064 sizeof (char *) * DLADM_MAX_PROP_VALCNT + 57250ba2cbe9Sxc151355 i * DLADM_PROP_VAL_MAX; 57260ba2cbe9Sxc151355 } 5727f4b3ec61Sdh155122 statep->ls_line = buf + 5728d62bc4baSyz147064 (sizeof (char *) + DLADM_PROP_VAL_MAX) * DLADM_MAX_PROP_VALCNT; 57290ba2cbe9Sxc151355 57300ba2cbe9Sxc151355 if (proplist != NULL) { 5731da14cebeSEric Cheng for (i = 0; i < proplist->al_count; i++) { 5732*4ac67f02SAnurag S. Maskey (void) show_linkprop(hdl, linkid, 5733da14cebeSEric Cheng proplist->al_info[i].ai_name, statep); 57340ba2cbe9Sxc151355 } 5735d62bc4baSyz147064 } else { 5736*4ac67f02SAnurag S. Maskey (void) dladm_walk_linkprop(hdl, linkid, statep, 5737*4ac67f02SAnurag S. Maskey show_linkprop); 5738d62bc4baSyz147064 } 5739d62bc4baSyz147064 if (dh != NULL) 5740948f2876Sss150715 dlpi_close(dh); 57410ba2cbe9Sxc151355 free(buf); 5742d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 57430ba2cbe9Sxc151355 } 57440ba2cbe9Sxc151355 57450ba2cbe9Sxc151355 static dladm_status_t 5746d62bc4baSyz147064 set_linkprop_persist(datalink_id_t linkid, const char *prop_name, 5747d62bc4baSyz147064 char **prop_val, uint_t val_cnt, boolean_t reset) 57480ba2cbe9Sxc151355 { 57490ba2cbe9Sxc151355 dladm_status_t status; 57500ba2cbe9Sxc151355 5751*4ac67f02SAnurag S. Maskey status = dladm_set_linkprop(handle, linkid, prop_name, prop_val, 5752*4ac67f02SAnurag S. Maskey val_cnt, DLADM_OPT_PERSIST); 57530ba2cbe9Sxc151355 57540ba2cbe9Sxc151355 if (status != DLADM_STATUS_OK) { 5755da14cebeSEric Cheng warn_dlerr(status, "cannot persistently %s link property '%s'", 5756da14cebeSEric Cheng reset ? "reset" : "set", prop_name); 57570ba2cbe9Sxc151355 } 57580ba2cbe9Sxc151355 return (status); 57590ba2cbe9Sxc151355 } 57600ba2cbe9Sxc151355 5761da14cebeSEric Cheng static int 5762*4ac67f02SAnurag S. Maskey reset_one_linkprop(dladm_handle_t dh, datalink_id_t linkid, 5763*4ac67f02SAnurag S. Maskey const char *propname, void *arg) 5764da14cebeSEric Cheng { 5765da14cebeSEric Cheng set_linkprop_state_t *statep = arg; 5766da14cebeSEric Cheng dladm_status_t status; 5767da14cebeSEric Cheng 5768*4ac67f02SAnurag S. Maskey status = dladm_set_linkprop(dh, linkid, propname, NULL, 0, 5769da14cebeSEric Cheng DLADM_OPT_ACTIVE); 5770da14cebeSEric Cheng if (status != DLADM_STATUS_OK) { 5771da14cebeSEric Cheng warn_dlerr(status, "cannot reset link property '%s' on '%s'", 5772da14cebeSEric Cheng propname, statep->ls_name); 5773da14cebeSEric Cheng } 5774da14cebeSEric Cheng if (!statep->ls_temp) { 5775da14cebeSEric Cheng dladm_status_t s; 5776da14cebeSEric Cheng 5777da14cebeSEric Cheng s = set_linkprop_persist(linkid, propname, NULL, 0, 5778da14cebeSEric Cheng statep->ls_reset); 5779da14cebeSEric Cheng if (s != DLADM_STATUS_OK) 5780da14cebeSEric Cheng status = s; 5781da14cebeSEric Cheng } 5782da14cebeSEric Cheng if (status != DLADM_STATUS_OK) 5783da14cebeSEric Cheng statep->ls_status = status; 5784da14cebeSEric Cheng 5785da14cebeSEric Cheng return (DLADM_WALK_CONTINUE); 5786da14cebeSEric Cheng } 5787da14cebeSEric Cheng 57880ba2cbe9Sxc151355 static void 57898d5c46e6Sam223141 set_linkprop(int argc, char **argv, boolean_t reset, const char *use) 57900ba2cbe9Sxc151355 { 57910ba2cbe9Sxc151355 int i, option; 57920ba2cbe9Sxc151355 char errmsg[DLADM_STRSIZE]; 5793d62bc4baSyz147064 char *altroot = NULL; 5794d62bc4baSyz147064 datalink_id_t linkid; 57950ba2cbe9Sxc151355 boolean_t temp = B_FALSE; 57960ba2cbe9Sxc151355 dladm_status_t status = DLADM_STATUS_OK; 5797da14cebeSEric Cheng dladm_arg_list_t *proplist = NULL; 57980ba2cbe9Sxc151355 57990ba2cbe9Sxc151355 opterr = 0; 58000ba2cbe9Sxc151355 while ((option = getopt_long(argc, argv, ":p:R:t", 58010ba2cbe9Sxc151355 prop_longopts, NULL)) != -1) { 58020ba2cbe9Sxc151355 switch (option) { 58030ba2cbe9Sxc151355 case 'p': 5804da14cebeSEric Cheng if (dladm_parse_link_props(optarg, &proplist, reset) != 5805da14cebeSEric Cheng DLADM_STATUS_OK) { 580633343a97Smeem die("invalid link properties specified"); 5807da14cebeSEric Cheng } 58080ba2cbe9Sxc151355 break; 58090ba2cbe9Sxc151355 case 't': 58100ba2cbe9Sxc151355 temp = B_TRUE; 58110ba2cbe9Sxc151355 break; 58120ba2cbe9Sxc151355 case 'R': 5813d62bc4baSyz147064 altroot = optarg; 58140ba2cbe9Sxc151355 break; 58150ba2cbe9Sxc151355 default: 58168d5c46e6Sam223141 die_opterr(optopt, option, use); 58178d5c46e6Sam223141 58180ba2cbe9Sxc151355 } 58190ba2cbe9Sxc151355 } 58200ba2cbe9Sxc151355 5821d62bc4baSyz147064 /* get link name (required last argument) */ 5822d62bc4baSyz147064 if (optind != (argc - 1)) 58230ba2cbe9Sxc151355 usage(); 58240ba2cbe9Sxc151355 5825d62bc4baSyz147064 if (proplist == NULL && !reset) 582633343a97Smeem die("link property must be specified"); 582733343a97Smeem 5828d62bc4baSyz147064 if (altroot != NULL) { 5829da14cebeSEric Cheng dladm_free_props(proplist); 5830d62bc4baSyz147064 altroot_cmd(altroot, argc, argv); 5831d62bc4baSyz147064 } 5832d62bc4baSyz147064 5833*4ac67f02SAnurag S. Maskey status = dladm_name2info(handle, argv[optind], &linkid, NULL, NULL, 5834*4ac67f02SAnurag S. Maskey NULL); 5835d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 5836d62bc4baSyz147064 die_dlerr(status, "link %s is not valid", argv[optind]); 5837d62bc4baSyz147064 5838d62bc4baSyz147064 if (proplist == NULL) { 5839da14cebeSEric Cheng set_linkprop_state_t state; 584013994ee8Sxz162242 5841da14cebeSEric Cheng state.ls_name = argv[optind]; 5842da14cebeSEric Cheng state.ls_reset = reset; 5843da14cebeSEric Cheng state.ls_temp = temp; 5844da14cebeSEric Cheng state.ls_status = DLADM_STATUS_OK; 5845da14cebeSEric Cheng 5846*4ac67f02SAnurag S. Maskey (void) dladm_walk_linkprop(handle, linkid, &state, 5847*4ac67f02SAnurag S. Maskey reset_one_linkprop); 5848da14cebeSEric Cheng 5849da14cebeSEric Cheng status = state.ls_status; 58500ba2cbe9Sxc151355 goto done; 58510ba2cbe9Sxc151355 } 58520ba2cbe9Sxc151355 5853da14cebeSEric Cheng for (i = 0; i < proplist->al_count; i++) { 5854da14cebeSEric Cheng dladm_arg_info_t *aip = &proplist->al_info[i]; 58550ba2cbe9Sxc151355 char **val; 58560ba2cbe9Sxc151355 uint_t count; 58570ba2cbe9Sxc151355 dladm_status_t s; 58580ba2cbe9Sxc151355 58590ba2cbe9Sxc151355 if (reset) { 58600ba2cbe9Sxc151355 val = NULL; 58610ba2cbe9Sxc151355 count = 0; 58620ba2cbe9Sxc151355 } else { 5863da14cebeSEric Cheng val = aip->ai_val; 5864da14cebeSEric Cheng count = aip->ai_count; 58650ba2cbe9Sxc151355 if (count == 0) { 586633343a97Smeem warn("no value specified for '%s'", 5867da14cebeSEric Cheng aip->ai_name); 58680ba2cbe9Sxc151355 status = DLADM_STATUS_BADARG; 58690ba2cbe9Sxc151355 continue; 58700ba2cbe9Sxc151355 } 58710ba2cbe9Sxc151355 } 5872*4ac67f02SAnurag S. Maskey s = dladm_set_linkprop(handle, linkid, aip->ai_name, val, count, 5873d62bc4baSyz147064 DLADM_OPT_ACTIVE); 58740ba2cbe9Sxc151355 if (s == DLADM_STATUS_OK) { 58750ba2cbe9Sxc151355 if (!temp) { 5876d62bc4baSyz147064 s = set_linkprop_persist(linkid, 5877da14cebeSEric Cheng aip->ai_name, val, count, reset); 58780ba2cbe9Sxc151355 if (s != DLADM_STATUS_OK) 58790ba2cbe9Sxc151355 status = s; 58800ba2cbe9Sxc151355 } 58810ba2cbe9Sxc151355 continue; 58820ba2cbe9Sxc151355 } 58830ba2cbe9Sxc151355 status = s; 58840ba2cbe9Sxc151355 switch (s) { 58850ba2cbe9Sxc151355 case DLADM_STATUS_NOTFOUND: 5886da14cebeSEric Cheng warn("invalid link property '%s'", aip->ai_name); 58870ba2cbe9Sxc151355 break; 58880ba2cbe9Sxc151355 case DLADM_STATUS_BADVAL: { 58890ba2cbe9Sxc151355 int j; 58900ba2cbe9Sxc151355 char *ptr, *lim; 58910ba2cbe9Sxc151355 char **propvals = NULL; 5892d62bc4baSyz147064 uint_t valcnt = DLADM_MAX_PROP_VALCNT; 58930ba2cbe9Sxc151355 58940ba2cbe9Sxc151355 ptr = malloc((sizeof (char *) + 5895d62bc4baSyz147064 DLADM_PROP_VAL_MAX) * DLADM_MAX_PROP_VALCNT + 58960ba2cbe9Sxc151355 MAX_PROP_LINE); 58970ba2cbe9Sxc151355 58980ba2cbe9Sxc151355 propvals = (char **)(void *)ptr; 589933343a97Smeem if (propvals == NULL) 590033343a97Smeem die("insufficient memory"); 590133343a97Smeem 5902d62bc4baSyz147064 for (j = 0; j < DLADM_MAX_PROP_VALCNT; j++) { 59030ba2cbe9Sxc151355 propvals[j] = ptr + sizeof (char *) * 5904d62bc4baSyz147064 DLADM_MAX_PROP_VALCNT + 59050ba2cbe9Sxc151355 j * DLADM_PROP_VAL_MAX; 59060ba2cbe9Sxc151355 } 5907*4ac67f02SAnurag S. Maskey s = dladm_get_linkprop(handle, linkid, 5908da14cebeSEric Cheng DLADM_PROP_VAL_MODIFIABLE, aip->ai_name, propvals, 5909d62bc4baSyz147064 &valcnt); 5910d62bc4baSyz147064 5911d62bc4baSyz147064 if (s != DLADM_STATUS_OK) { 5912d62bc4baSyz147064 warn_dlerr(status, "cannot set link property " 5913da14cebeSEric Cheng "'%s' on '%s'", aip->ai_name, argv[optind]); 5914d62bc4baSyz147064 free(propvals); 5915d62bc4baSyz147064 break; 5916d62bc4baSyz147064 } 59170ba2cbe9Sxc151355 59180ba2cbe9Sxc151355 ptr = errmsg; 59190ba2cbe9Sxc151355 lim = ptr + DLADM_STRSIZE; 59200ba2cbe9Sxc151355 *ptr = '\0'; 5921d62bc4baSyz147064 for (j = 0; j < valcnt; j++) { 59220ba2cbe9Sxc151355 ptr += snprintf(ptr, lim - ptr, "%s,", 59230ba2cbe9Sxc151355 propvals[j]); 59240ba2cbe9Sxc151355 if (ptr >= lim) 59250ba2cbe9Sxc151355 break; 59260ba2cbe9Sxc151355 } 5927f4b3ec61Sdh155122 if (ptr > errmsg) { 59280ba2cbe9Sxc151355 *(ptr - 1) = '\0'; 592933343a97Smeem warn("link property '%s' must be one of: %s", 5930da14cebeSEric Cheng aip->ai_name, errmsg); 5931f4b3ec61Sdh155122 } else 5932f4b3ec61Sdh155122 warn("invalid link property '%s'", *val); 59330ba2cbe9Sxc151355 free(propvals); 59340ba2cbe9Sxc151355 break; 59350ba2cbe9Sxc151355 } 59360ba2cbe9Sxc151355 default: 59370ba2cbe9Sxc151355 if (reset) { 593833343a97Smeem warn_dlerr(status, "cannot reset link property " 5939da14cebeSEric Cheng "'%s' on '%s'", aip->ai_name, argv[optind]); 59400ba2cbe9Sxc151355 } else { 594133343a97Smeem warn_dlerr(status, "cannot set link property " 5942da14cebeSEric Cheng "'%s' on '%s'", aip->ai_name, argv[optind]); 59430ba2cbe9Sxc151355 } 59440ba2cbe9Sxc151355 break; 59450ba2cbe9Sxc151355 } 59460ba2cbe9Sxc151355 } 59470ba2cbe9Sxc151355 done: 5948da14cebeSEric Cheng dladm_free_props(proplist); 5949*4ac67f02SAnurag S. Maskey if (status != DLADM_STATUS_OK) { 5950*4ac67f02SAnurag S. Maskey dladm_close(handle); 59510ba2cbe9Sxc151355 exit(1); 59520ba2cbe9Sxc151355 } 5953*4ac67f02SAnurag S. Maskey } 59540ba2cbe9Sxc151355 59550ba2cbe9Sxc151355 static void 59568d5c46e6Sam223141 do_set_linkprop(int argc, char **argv, const char *use) 59570ba2cbe9Sxc151355 { 59588d5c46e6Sam223141 set_linkprop(argc, argv, B_FALSE, use); 59590ba2cbe9Sxc151355 } 59600ba2cbe9Sxc151355 59610ba2cbe9Sxc151355 static void 59628d5c46e6Sam223141 do_reset_linkprop(int argc, char **argv, const char *use) 59630ba2cbe9Sxc151355 { 59648d5c46e6Sam223141 set_linkprop(argc, argv, B_TRUE, use); 59650ba2cbe9Sxc151355 } 59660ba2cbe9Sxc151355 59670ba2cbe9Sxc151355 static int 59680ba2cbe9Sxc151355 convert_secobj(char *buf, uint_t len, uint8_t *obj_val, uint_t *obj_lenp, 59690ba2cbe9Sxc151355 dladm_secobj_class_t class) 59700ba2cbe9Sxc151355 { 59710ba2cbe9Sxc151355 int error = 0; 59720ba2cbe9Sxc151355 5973a399b765Szf162725 if (class == DLADM_SECOBJ_CLASS_WPA) { 5974a399b765Szf162725 if (len < 8 || len > 63) 5975a399b765Szf162725 return (EINVAL); 5976a399b765Szf162725 (void) memcpy(obj_val, buf, len); 5977a399b765Szf162725 *obj_lenp = len; 5978a399b765Szf162725 return (error); 5979a399b765Szf162725 } 59800ba2cbe9Sxc151355 5981a399b765Szf162725 if (class == DLADM_SECOBJ_CLASS_WEP) { 59820ba2cbe9Sxc151355 switch (len) { 59830ba2cbe9Sxc151355 case 5: /* ASCII key sizes */ 59840ba2cbe9Sxc151355 case 13: 59850ba2cbe9Sxc151355 (void) memcpy(obj_val, buf, len); 59860ba2cbe9Sxc151355 *obj_lenp = len; 59870ba2cbe9Sxc151355 break; 59880ba2cbe9Sxc151355 case 10: /* Hex key sizes, not preceded by 0x */ 59890ba2cbe9Sxc151355 case 26: 59900ba2cbe9Sxc151355 error = hexascii_to_octet(buf, len, obj_val, obj_lenp); 59910ba2cbe9Sxc151355 break; 59920ba2cbe9Sxc151355 case 12: /* Hex key sizes, preceded by 0x */ 59930ba2cbe9Sxc151355 case 28: 59940ba2cbe9Sxc151355 if (strncmp(buf, "0x", 2) != 0) 59950ba2cbe9Sxc151355 return (EINVAL); 5996a399b765Szf162725 error = hexascii_to_octet(buf + 2, len - 2, 5997a399b765Szf162725 obj_val, obj_lenp); 59980ba2cbe9Sxc151355 break; 59990ba2cbe9Sxc151355 default: 60000ba2cbe9Sxc151355 return (EINVAL); 60010ba2cbe9Sxc151355 } 60020ba2cbe9Sxc151355 return (error); 60030ba2cbe9Sxc151355 } 60040ba2cbe9Sxc151355 6005a399b765Szf162725 return (ENOENT); 6006a399b765Szf162725 } 6007a399b765Szf162725 60080ba2cbe9Sxc151355 static void 60090ba2cbe9Sxc151355 defersig(int sig) 60100ba2cbe9Sxc151355 { 60110ba2cbe9Sxc151355 signalled = sig; 60120ba2cbe9Sxc151355 } 60130ba2cbe9Sxc151355 60140ba2cbe9Sxc151355 static int 60150ba2cbe9Sxc151355 get_secobj_from_tty(uint_t try, const char *objname, char *buf) 60160ba2cbe9Sxc151355 { 60170ba2cbe9Sxc151355 uint_t len = 0; 60180ba2cbe9Sxc151355 int c; 60190ba2cbe9Sxc151355 struct termios stored, current; 60200ba2cbe9Sxc151355 void (*sigfunc)(int); 60210ba2cbe9Sxc151355 60220ba2cbe9Sxc151355 /* 60230ba2cbe9Sxc151355 * Turn off echo -- but before we do so, defer SIGINT handling 60240ba2cbe9Sxc151355 * so that a ^C doesn't leave the terminal corrupted. 60250ba2cbe9Sxc151355 */ 60260ba2cbe9Sxc151355 sigfunc = signal(SIGINT, defersig); 60270ba2cbe9Sxc151355 (void) fflush(stdin); 60280ba2cbe9Sxc151355 (void) tcgetattr(0, &stored); 60290ba2cbe9Sxc151355 current = stored; 60300ba2cbe9Sxc151355 current.c_lflag &= ~(ICANON|ECHO); 60310ba2cbe9Sxc151355 current.c_cc[VTIME] = 0; 60320ba2cbe9Sxc151355 current.c_cc[VMIN] = 1; 60330ba2cbe9Sxc151355 (void) tcsetattr(0, TCSANOW, ¤t); 60340ba2cbe9Sxc151355 again: 60350ba2cbe9Sxc151355 if (try == 1) 60360ba2cbe9Sxc151355 (void) printf(gettext("provide value for '%s': "), objname); 60370ba2cbe9Sxc151355 else 60380ba2cbe9Sxc151355 (void) printf(gettext("confirm value for '%s': "), objname); 60390ba2cbe9Sxc151355 60400ba2cbe9Sxc151355 (void) fflush(stdout); 60410ba2cbe9Sxc151355 while (signalled == 0) { 60420ba2cbe9Sxc151355 c = getchar(); 60430ba2cbe9Sxc151355 if (c == '\n' || c == '\r') { 60440ba2cbe9Sxc151355 if (len != 0) 60450ba2cbe9Sxc151355 break; 60460ba2cbe9Sxc151355 (void) putchar('\n'); 60470ba2cbe9Sxc151355 goto again; 60480ba2cbe9Sxc151355 } 60490ba2cbe9Sxc151355 60500ba2cbe9Sxc151355 buf[len++] = c; 60510ba2cbe9Sxc151355 if (len >= DLADM_SECOBJ_VAL_MAX - 1) 60520ba2cbe9Sxc151355 break; 60530ba2cbe9Sxc151355 (void) putchar('*'); 60540ba2cbe9Sxc151355 } 60550ba2cbe9Sxc151355 60560ba2cbe9Sxc151355 (void) putchar('\n'); 60570ba2cbe9Sxc151355 (void) fflush(stdin); 60580ba2cbe9Sxc151355 60590ba2cbe9Sxc151355 /* 60600ba2cbe9Sxc151355 * Restore terminal setting and handle deferred signals. 60610ba2cbe9Sxc151355 */ 60620ba2cbe9Sxc151355 (void) tcsetattr(0, TCSANOW, &stored); 60630ba2cbe9Sxc151355 60640ba2cbe9Sxc151355 (void) signal(SIGINT, sigfunc); 60650ba2cbe9Sxc151355 if (signalled != 0) 60660ba2cbe9Sxc151355 (void) kill(getpid(), signalled); 60670ba2cbe9Sxc151355 60680ba2cbe9Sxc151355 return (len); 60690ba2cbe9Sxc151355 } 60700ba2cbe9Sxc151355 60710ba2cbe9Sxc151355 static int 60720ba2cbe9Sxc151355 get_secobj_val(char *obj_name, uint8_t *obj_val, uint_t *obj_lenp, 60730ba2cbe9Sxc151355 dladm_secobj_class_t class, FILE *filep) 60740ba2cbe9Sxc151355 { 60750ba2cbe9Sxc151355 int rval; 60760ba2cbe9Sxc151355 uint_t len, len2; 60770ba2cbe9Sxc151355 char buf[DLADM_SECOBJ_VAL_MAX], buf2[DLADM_SECOBJ_VAL_MAX]; 60780ba2cbe9Sxc151355 60790ba2cbe9Sxc151355 if (filep == NULL) { 60800ba2cbe9Sxc151355 len = get_secobj_from_tty(1, obj_name, buf); 60810ba2cbe9Sxc151355 rval = convert_secobj(buf, len, obj_val, obj_lenp, class); 60820ba2cbe9Sxc151355 if (rval == 0) { 60830ba2cbe9Sxc151355 len2 = get_secobj_from_tty(2, obj_name, buf2); 60840ba2cbe9Sxc151355 if (len != len2 || memcmp(buf, buf2, len) != 0) 60850ba2cbe9Sxc151355 rval = ENOTSUP; 60860ba2cbe9Sxc151355 } 60870ba2cbe9Sxc151355 return (rval); 60880ba2cbe9Sxc151355 } else { 60890ba2cbe9Sxc151355 for (;;) { 60900ba2cbe9Sxc151355 if (fgets(buf, sizeof (buf), filep) == NULL) 60910ba2cbe9Sxc151355 break; 60920ba2cbe9Sxc151355 if (isspace(buf[0])) 60930ba2cbe9Sxc151355 continue; 60940ba2cbe9Sxc151355 60950ba2cbe9Sxc151355 len = strlen(buf); 60960ba2cbe9Sxc151355 if (buf[len - 1] == '\n') { 60970ba2cbe9Sxc151355 buf[len - 1] = '\0'; 60980ba2cbe9Sxc151355 len--; 60990ba2cbe9Sxc151355 } 61000ba2cbe9Sxc151355 break; 61010ba2cbe9Sxc151355 } 61020ba2cbe9Sxc151355 (void) fclose(filep); 61030ba2cbe9Sxc151355 } 61040ba2cbe9Sxc151355 return (convert_secobj(buf, len, obj_val, obj_lenp, class)); 61050ba2cbe9Sxc151355 } 61060ba2cbe9Sxc151355 61070ba2cbe9Sxc151355 static boolean_t 61080ba2cbe9Sxc151355 check_auth(const char *auth) 61090ba2cbe9Sxc151355 { 61100ba2cbe9Sxc151355 struct passwd *pw; 61110ba2cbe9Sxc151355 61120ba2cbe9Sxc151355 if ((pw = getpwuid(getuid())) == NULL) 61130ba2cbe9Sxc151355 return (B_FALSE); 61140ba2cbe9Sxc151355 61150ba2cbe9Sxc151355 return (chkauthattr(auth, pw->pw_name) != 0); 61160ba2cbe9Sxc151355 } 61170ba2cbe9Sxc151355 61180ba2cbe9Sxc151355 static void 61190ba2cbe9Sxc151355 audit_secobj(char *auth, char *class, char *obj, 61200ba2cbe9Sxc151355 boolean_t success, boolean_t create) 61210ba2cbe9Sxc151355 { 61220ba2cbe9Sxc151355 adt_session_data_t *ah; 61230ba2cbe9Sxc151355 adt_event_data_t *event; 61240ba2cbe9Sxc151355 au_event_t flag; 61250ba2cbe9Sxc151355 char *errstr; 61260ba2cbe9Sxc151355 61270ba2cbe9Sxc151355 if (create) { 61280ba2cbe9Sxc151355 flag = ADT_dladm_create_secobj; 61290ba2cbe9Sxc151355 errstr = "ADT_dladm_create_secobj"; 61300ba2cbe9Sxc151355 } else { 61310ba2cbe9Sxc151355 flag = ADT_dladm_delete_secobj; 61320ba2cbe9Sxc151355 errstr = "ADT_dladm_delete_secobj"; 61330ba2cbe9Sxc151355 } 61340ba2cbe9Sxc151355 613533343a97Smeem if (adt_start_session(&ah, NULL, ADT_USE_PROC_DATA) != 0) 613633343a97Smeem die("adt_start_session: %s", strerror(errno)); 61370ba2cbe9Sxc151355 613833343a97Smeem if ((event = adt_alloc_event(ah, flag)) == NULL) 613933343a97Smeem die("adt_alloc_event (%s): %s", errstr, strerror(errno)); 61400ba2cbe9Sxc151355 61410ba2cbe9Sxc151355 /* fill in audit info */ 61420ba2cbe9Sxc151355 if (create) { 61430ba2cbe9Sxc151355 event->adt_dladm_create_secobj.auth_used = auth; 61440ba2cbe9Sxc151355 event->adt_dladm_create_secobj.obj_class = class; 61450ba2cbe9Sxc151355 event->adt_dladm_create_secobj.obj_name = obj; 61460ba2cbe9Sxc151355 } else { 61470ba2cbe9Sxc151355 event->adt_dladm_delete_secobj.auth_used = auth; 61480ba2cbe9Sxc151355 event->adt_dladm_delete_secobj.obj_class = class; 61490ba2cbe9Sxc151355 event->adt_dladm_delete_secobj.obj_name = obj; 61500ba2cbe9Sxc151355 } 61510ba2cbe9Sxc151355 61520ba2cbe9Sxc151355 if (success) { 61530ba2cbe9Sxc151355 if (adt_put_event(event, ADT_SUCCESS, ADT_SUCCESS) != 0) { 615433343a97Smeem die("adt_put_event (%s, success): %s", errstr, 615533343a97Smeem strerror(errno)); 61560ba2cbe9Sxc151355 } 61570ba2cbe9Sxc151355 } else { 61580ba2cbe9Sxc151355 if (adt_put_event(event, ADT_FAILURE, 61590ba2cbe9Sxc151355 ADT_FAIL_VALUE_AUTH) != 0) { 616033343a97Smeem die("adt_put_event: (%s, failure): %s", errstr, 616133343a97Smeem strerror(errno)); 61620ba2cbe9Sxc151355 } 61630ba2cbe9Sxc151355 } 61640ba2cbe9Sxc151355 61650ba2cbe9Sxc151355 adt_free_event(event); 61660ba2cbe9Sxc151355 (void) adt_end_session(ah); 61670ba2cbe9Sxc151355 } 61680ba2cbe9Sxc151355 61690ba2cbe9Sxc151355 #define MAX_SECOBJS 32 61700ba2cbe9Sxc151355 #define MAX_SECOBJ_NAMELEN 32 61710ba2cbe9Sxc151355 static void 61728d5c46e6Sam223141 do_create_secobj(int argc, char **argv, const char *use) 61730ba2cbe9Sxc151355 { 61740ba2cbe9Sxc151355 int option, rval; 61750ba2cbe9Sxc151355 FILE *filep = NULL; 61760ba2cbe9Sxc151355 char *obj_name = NULL; 61770ba2cbe9Sxc151355 char *class_name = NULL; 61780ba2cbe9Sxc151355 uint8_t obj_val[DLADM_SECOBJ_VAL_MAX]; 61790ba2cbe9Sxc151355 uint_t obj_len; 61800ba2cbe9Sxc151355 boolean_t success, temp = B_FALSE; 61810ba2cbe9Sxc151355 dladm_status_t status; 61820ba2cbe9Sxc151355 dladm_secobj_class_t class = -1; 61830ba2cbe9Sxc151355 uid_t euid; 61840ba2cbe9Sxc151355 61850ba2cbe9Sxc151355 opterr = 0; 61860ba2cbe9Sxc151355 (void) memset(obj_val, 0, DLADM_SECOBJ_VAL_MAX); 61870ba2cbe9Sxc151355 while ((option = getopt_long(argc, argv, ":f:c:R:t", 61880ba2cbe9Sxc151355 wifi_longopts, NULL)) != -1) { 61890ba2cbe9Sxc151355 switch (option) { 61900ba2cbe9Sxc151355 case 'f': 61910ba2cbe9Sxc151355 euid = geteuid(); 61920ba2cbe9Sxc151355 (void) seteuid(getuid()); 61930ba2cbe9Sxc151355 filep = fopen(optarg, "r"); 61940ba2cbe9Sxc151355 if (filep == NULL) { 619533343a97Smeem die("cannot open %s: %s", optarg, 619633343a97Smeem strerror(errno)); 61970ba2cbe9Sxc151355 } 61980ba2cbe9Sxc151355 (void) seteuid(euid); 61990ba2cbe9Sxc151355 break; 62000ba2cbe9Sxc151355 case 'c': 62010ba2cbe9Sxc151355 class_name = optarg; 62020ba2cbe9Sxc151355 status = dladm_str2secobjclass(optarg, &class); 62030ba2cbe9Sxc151355 if (status != DLADM_STATUS_OK) { 620433343a97Smeem die("invalid secure object class '%s', " 6205a399b765Szf162725 "valid values are: wep, wpa", optarg); 62060ba2cbe9Sxc151355 } 62070ba2cbe9Sxc151355 break; 62080ba2cbe9Sxc151355 case 't': 62090ba2cbe9Sxc151355 temp = B_TRUE; 62100ba2cbe9Sxc151355 break; 62110ba2cbe9Sxc151355 case 'R': 62120ba2cbe9Sxc151355 status = dladm_set_rootdir(optarg); 62130ba2cbe9Sxc151355 if (status != DLADM_STATUS_OK) { 621433343a97Smeem die_dlerr(status, "invalid directory " 621533343a97Smeem "specified"); 62160ba2cbe9Sxc151355 } 62170ba2cbe9Sxc151355 break; 62180ba2cbe9Sxc151355 default: 62198d5c46e6Sam223141 die_opterr(optopt, option, use); 62200ba2cbe9Sxc151355 break; 62210ba2cbe9Sxc151355 } 62220ba2cbe9Sxc151355 } 62230ba2cbe9Sxc151355 62240ba2cbe9Sxc151355 if (optind == (argc - 1)) 62250ba2cbe9Sxc151355 obj_name = argv[optind]; 62260ba2cbe9Sxc151355 else if (optind != argc) 62270ba2cbe9Sxc151355 usage(); 62280ba2cbe9Sxc151355 622933343a97Smeem if (class == -1) 623033343a97Smeem die("secure object class required"); 62310ba2cbe9Sxc151355 623233343a97Smeem if (obj_name == NULL) 623333343a97Smeem die("secure object name required"); 62340ba2cbe9Sxc151355 6235a9489f61SAnurag S. Maskey if (!dladm_valid_secobj_name(obj_name)) 6236a9489f61SAnurag S. Maskey die("invalid secure object name '%s'", obj_name); 6237a9489f61SAnurag S. Maskey 62380ba2cbe9Sxc151355 success = check_auth(LINK_SEC_AUTH); 62390ba2cbe9Sxc151355 audit_secobj(LINK_SEC_AUTH, class_name, obj_name, success, B_TRUE); 624033343a97Smeem if (!success) 624133343a97Smeem die("authorization '%s' is required", LINK_SEC_AUTH); 62420ba2cbe9Sxc151355 624333343a97Smeem rval = get_secobj_val(obj_name, obj_val, &obj_len, class, filep); 624433343a97Smeem if (rval != 0) { 62450ba2cbe9Sxc151355 switch (rval) { 62460ba2cbe9Sxc151355 case ENOENT: 624733343a97Smeem die("invalid secure object class"); 62480ba2cbe9Sxc151355 break; 62490ba2cbe9Sxc151355 case EINVAL: 625033343a97Smeem die("invalid secure object value"); 62510ba2cbe9Sxc151355 break; 62520ba2cbe9Sxc151355 case ENOTSUP: 625333343a97Smeem die("verification failed"); 62540ba2cbe9Sxc151355 break; 62550ba2cbe9Sxc151355 default: 625633343a97Smeem die("invalid secure object: %s", strerror(rval)); 62570ba2cbe9Sxc151355 break; 62580ba2cbe9Sxc151355 } 62590ba2cbe9Sxc151355 } 62600ba2cbe9Sxc151355 6261*4ac67f02SAnurag S. Maskey status = dladm_set_secobj(handle, obj_name, class, obj_val, obj_len, 6262d62bc4baSyz147064 DLADM_OPT_CREATE | DLADM_OPT_ACTIVE); 62630ba2cbe9Sxc151355 if (status != DLADM_STATUS_OK) { 626433343a97Smeem die_dlerr(status, "could not create secure object '%s'", 626533343a97Smeem obj_name); 62660ba2cbe9Sxc151355 } 62670ba2cbe9Sxc151355 if (temp) 62680ba2cbe9Sxc151355 return; 62690ba2cbe9Sxc151355 6270*4ac67f02SAnurag S. Maskey status = dladm_set_secobj(handle, obj_name, class, obj_val, obj_len, 62710ba2cbe9Sxc151355 DLADM_OPT_PERSIST); 62720ba2cbe9Sxc151355 if (status != DLADM_STATUS_OK) { 627333343a97Smeem warn_dlerr(status, "could not persistently create secure " 627433343a97Smeem "object '%s'", obj_name); 62750ba2cbe9Sxc151355 } 62760ba2cbe9Sxc151355 } 62770ba2cbe9Sxc151355 62780ba2cbe9Sxc151355 static void 62798d5c46e6Sam223141 do_delete_secobj(int argc, char **argv, const char *use) 62800ba2cbe9Sxc151355 { 62810ba2cbe9Sxc151355 int i, option; 62820ba2cbe9Sxc151355 boolean_t temp = B_FALSE; 62830ba2cbe9Sxc151355 split_t *sp = NULL; 62840ba2cbe9Sxc151355 boolean_t success; 62850ba2cbe9Sxc151355 dladm_status_t status, pstatus; 62860ba2cbe9Sxc151355 62870ba2cbe9Sxc151355 opterr = 0; 62880ba2cbe9Sxc151355 status = pstatus = DLADM_STATUS_OK; 628933343a97Smeem while ((option = getopt_long(argc, argv, ":R:t", 62900ba2cbe9Sxc151355 wifi_longopts, NULL)) != -1) { 62910ba2cbe9Sxc151355 switch (option) { 62920ba2cbe9Sxc151355 case 't': 62930ba2cbe9Sxc151355 temp = B_TRUE; 62940ba2cbe9Sxc151355 break; 62950ba2cbe9Sxc151355 case 'R': 62960ba2cbe9Sxc151355 status = dladm_set_rootdir(optarg); 62970ba2cbe9Sxc151355 if (status != DLADM_STATUS_OK) { 629833343a97Smeem die_dlerr(status, "invalid directory " 629933343a97Smeem "specified"); 63000ba2cbe9Sxc151355 } 63010ba2cbe9Sxc151355 break; 63020ba2cbe9Sxc151355 default: 63038d5c46e6Sam223141 die_opterr(optopt, option, use); 63040ba2cbe9Sxc151355 break; 63050ba2cbe9Sxc151355 } 63060ba2cbe9Sxc151355 } 63070ba2cbe9Sxc151355 63080ba2cbe9Sxc151355 if (optind == (argc - 1)) { 63090ba2cbe9Sxc151355 sp = split(argv[optind], MAX_SECOBJS, MAX_SECOBJ_NAMELEN); 63100ba2cbe9Sxc151355 if (sp == NULL) { 631133343a97Smeem die("invalid secure object name(s): '%s'", 631233343a97Smeem argv[optind]); 63130ba2cbe9Sxc151355 } 63140ba2cbe9Sxc151355 } else if (optind != argc) 63150ba2cbe9Sxc151355 usage(); 63160ba2cbe9Sxc151355 631733343a97Smeem if (sp == NULL || sp->s_nfields < 1) 631833343a97Smeem die("secure object name required"); 63190ba2cbe9Sxc151355 63200ba2cbe9Sxc151355 success = check_auth(LINK_SEC_AUTH); 6321a399b765Szf162725 audit_secobj(LINK_SEC_AUTH, "unknown", argv[optind], success, B_FALSE); 632233343a97Smeem if (!success) 632333343a97Smeem die("authorization '%s' is required", LINK_SEC_AUTH); 63240ba2cbe9Sxc151355 63250ba2cbe9Sxc151355 for (i = 0; i < sp->s_nfields; i++) { 6326*4ac67f02SAnurag S. Maskey status = dladm_unset_secobj(handle, sp->s_fields[i], 6327*4ac67f02SAnurag S. Maskey DLADM_OPT_ACTIVE); 63280ba2cbe9Sxc151355 if (!temp) { 6329*4ac67f02SAnurag S. Maskey pstatus = dladm_unset_secobj(handle, sp->s_fields[i], 63300ba2cbe9Sxc151355 DLADM_OPT_PERSIST); 63310ba2cbe9Sxc151355 } else { 63320ba2cbe9Sxc151355 pstatus = DLADM_STATUS_OK; 63330ba2cbe9Sxc151355 } 63340ba2cbe9Sxc151355 63350ba2cbe9Sxc151355 if (status != DLADM_STATUS_OK) { 633633343a97Smeem warn_dlerr(status, "could not delete secure object " 633733343a97Smeem "'%s'", sp->s_fields[i]); 63380ba2cbe9Sxc151355 } 63390ba2cbe9Sxc151355 if (pstatus != DLADM_STATUS_OK) { 634033343a97Smeem warn_dlerr(pstatus, "could not persistently delete " 634133343a97Smeem "secure object '%s'", sp->s_fields[i]); 63420ba2cbe9Sxc151355 } 63430ba2cbe9Sxc151355 } 6344*4ac67f02SAnurag S. Maskey 6345*4ac67f02SAnurag S. Maskey if (status != DLADM_STATUS_OK || pstatus != DLADM_STATUS_OK) { 6346*4ac67f02SAnurag S. Maskey dladm_close(handle); 63470ba2cbe9Sxc151355 exit(1); 63480ba2cbe9Sxc151355 } 6349*4ac67f02SAnurag S. Maskey } 63500ba2cbe9Sxc151355 63510ba2cbe9Sxc151355 typedef struct show_secobj_state { 63520ba2cbe9Sxc151355 boolean_t ss_persist; 63530ba2cbe9Sxc151355 boolean_t ss_parseable; 63540ba2cbe9Sxc151355 boolean_t ss_header; 6355e7801d59Ssowmini print_state_t ss_print; 63560ba2cbe9Sxc151355 } show_secobj_state_t; 63570ba2cbe9Sxc151355 63580ba2cbe9Sxc151355 63590ba2cbe9Sxc151355 static boolean_t 6360*4ac67f02SAnurag S. Maskey show_secobj(dladm_handle_t dh, void *arg, const char *obj_name) 63610ba2cbe9Sxc151355 { 63620ba2cbe9Sxc151355 uint_t obj_len = DLADM_SECOBJ_VAL_MAX; 63630ba2cbe9Sxc151355 uint8_t obj_val[DLADM_SECOBJ_VAL_MAX]; 63640ba2cbe9Sxc151355 char buf[DLADM_STRSIZE]; 63650ba2cbe9Sxc151355 uint_t flags = 0; 63660ba2cbe9Sxc151355 dladm_secobj_class_t class; 63670ba2cbe9Sxc151355 show_secobj_state_t *statep = arg; 63680ba2cbe9Sxc151355 dladm_status_t status; 6369e7801d59Ssowmini secobj_fields_buf_t sbuf; 63700ba2cbe9Sxc151355 63715f5c9f54SAnurag S. Maskey bzero(&sbuf, sizeof (secobj_fields_buf_t)); 63720ba2cbe9Sxc151355 if (statep->ss_persist) 63730ba2cbe9Sxc151355 flags |= DLADM_OPT_PERSIST; 63740ba2cbe9Sxc151355 6375*4ac67f02SAnurag S. Maskey status = dladm_get_secobj(dh, obj_name, &class, obj_val, &obj_len, 6376*4ac67f02SAnurag S. Maskey flags); 637733343a97Smeem if (status != DLADM_STATUS_OK) 637833343a97Smeem die_dlerr(status, "cannot get secure object '%s'", obj_name); 63790ba2cbe9Sxc151355 63800ba2cbe9Sxc151355 if (statep->ss_header) { 63810ba2cbe9Sxc151355 statep->ss_header = B_FALSE; 63820ba2cbe9Sxc151355 if (!statep->ss_parseable) 6383e7801d59Ssowmini print_header(&statep->ss_print); 63840ba2cbe9Sxc151355 } 63850ba2cbe9Sxc151355 6386e7801d59Ssowmini (void) snprintf(sbuf.ss_obj_name, sizeof (sbuf.ss_obj_name), 6387e7801d59Ssowmini obj_name); 6388e7801d59Ssowmini (void) dladm_secobjclass2str(class, buf); 6389e7801d59Ssowmini (void) snprintf(sbuf.ss_class, sizeof (sbuf.ss_class), "%s", buf); 6390e7801d59Ssowmini if (getuid() == 0) { 63910ba2cbe9Sxc151355 char val[DLADM_SECOBJ_VAL_MAX * 2]; 63920ba2cbe9Sxc151355 uint_t len = sizeof (val); 63930ba2cbe9Sxc151355 6394e7801d59Ssowmini if (octet_to_hexascii(obj_val, obj_len, val, &len) == 0) 6395e7801d59Ssowmini (void) snprintf(sbuf.ss_val, 6396e7801d59Ssowmini sizeof (sbuf.ss_val), "%s", val); 63970ba2cbe9Sxc151355 } 6398e7801d59Ssowmini dladm_print_output(&statep->ss_print, statep->ss_parseable, 6399e7801d59Ssowmini dladm_print_field, (void *)&sbuf); 64000ba2cbe9Sxc151355 return (B_TRUE); 64010ba2cbe9Sxc151355 } 64020ba2cbe9Sxc151355 64030ba2cbe9Sxc151355 static void 64048d5c46e6Sam223141 do_show_secobj(int argc, char **argv, const char *use) 64050ba2cbe9Sxc151355 { 64060ba2cbe9Sxc151355 int option; 64070ba2cbe9Sxc151355 show_secobj_state_t state; 64080ba2cbe9Sxc151355 dladm_status_t status; 64090d365605Sschuster boolean_t o_arg = B_FALSE; 64100ba2cbe9Sxc151355 uint_t i; 64110ba2cbe9Sxc151355 split_t *sp; 64120ba2cbe9Sxc151355 uint_t flags; 6413e7801d59Ssowmini char *fields_str = NULL; 6414e7801d59Ssowmini print_field_t **fields; 6415e7801d59Ssowmini uint_t nfields; 6416e7801d59Ssowmini char *def_fields = "object,class"; 6417e7801d59Ssowmini char *all_fields = "object,class,value"; 64180ba2cbe9Sxc151355 64190ba2cbe9Sxc151355 opterr = 0; 6420e7801d59Ssowmini bzero(&state, sizeof (state)); 6421e7801d59Ssowmini state.ss_parseable = B_FALSE; 6422e7801d59Ssowmini fields_str = def_fields; 64230ba2cbe9Sxc151355 state.ss_persist = B_FALSE; 64240ba2cbe9Sxc151355 state.ss_parseable = B_FALSE; 64250ba2cbe9Sxc151355 state.ss_header = B_TRUE; 6426e7801d59Ssowmini while ((option = getopt_long(argc, argv, ":pPo:", 64270ba2cbe9Sxc151355 wifi_longopts, NULL)) != -1) { 64280ba2cbe9Sxc151355 switch (option) { 64290ba2cbe9Sxc151355 case 'p': 64300ba2cbe9Sxc151355 state.ss_parseable = B_TRUE; 64310ba2cbe9Sxc151355 break; 64320ba2cbe9Sxc151355 case 'P': 64330ba2cbe9Sxc151355 state.ss_persist = B_TRUE; 64340ba2cbe9Sxc151355 break; 6435e7801d59Ssowmini case 'o': 64360d365605Sschuster o_arg = B_TRUE; 6437e7801d59Ssowmini if (strcasecmp(optarg, "all") == 0) 6438e7801d59Ssowmini fields_str = all_fields; 6439e7801d59Ssowmini else 6440e7801d59Ssowmini fields_str = optarg; 64410ba2cbe9Sxc151355 break; 64420ba2cbe9Sxc151355 default: 64438d5c46e6Sam223141 die_opterr(optopt, option, use); 64440ba2cbe9Sxc151355 break; 64450ba2cbe9Sxc151355 } 64460ba2cbe9Sxc151355 } 64470ba2cbe9Sxc151355 64480d365605Sschuster if (state.ss_parseable && !o_arg) 64490d365605Sschuster die("option -c requires -o"); 64500d365605Sschuster 64510d365605Sschuster if (state.ss_parseable && fields_str == all_fields) 64520d365605Sschuster die("\"-o all\" is invalid with -p"); 64530d365605Sschuster 6454e7801d59Ssowmini fields = parse_output_fields(fields_str, secobj_fields, 6455e7801d59Ssowmini DEV_SOBJ_FIELDS, CMD_TYPE_ANY, &nfields); 6456e7801d59Ssowmini 6457e7801d59Ssowmini if (fields == NULL) { 6458e7801d59Ssowmini die("invalid field(s) specified"); 6459e7801d59Ssowmini return; 6460e7801d59Ssowmini } 6461e7801d59Ssowmini state.ss_print.ps_fields = fields; 6462e7801d59Ssowmini state.ss_print.ps_nfields = nfields; 6463e7801d59Ssowmini 6464e7801d59Ssowmini flags = state.ss_persist ? DLADM_OPT_PERSIST : 0; 6465*4ac67f02SAnurag S. Maskey 64660ba2cbe9Sxc151355 if (optind == (argc - 1)) { 64670ba2cbe9Sxc151355 sp = split(argv[optind], MAX_SECOBJS, MAX_SECOBJ_NAMELEN); 64680ba2cbe9Sxc151355 if (sp == NULL) { 646933343a97Smeem die("invalid secure object name(s): '%s'", 647033343a97Smeem argv[optind]); 64710ba2cbe9Sxc151355 } 64720ba2cbe9Sxc151355 for (i = 0; i < sp->s_nfields; i++) { 6473*4ac67f02SAnurag S. Maskey if (!show_secobj(handle, &state, sp->s_fields[i])) 64740ba2cbe9Sxc151355 break; 64750ba2cbe9Sxc151355 } 64760ba2cbe9Sxc151355 splitfree(sp); 64770ba2cbe9Sxc151355 return; 64780ba2cbe9Sxc151355 } else if (optind != argc) 64790ba2cbe9Sxc151355 usage(); 64800ba2cbe9Sxc151355 6481*4ac67f02SAnurag S. Maskey status = dladm_walk_secobj(handle, &state, show_secobj, flags); 6482*4ac67f02SAnurag S. Maskey 648333343a97Smeem if (status != DLADM_STATUS_OK) 648433343a97Smeem die_dlerr(status, "show-secobj"); 64850ba2cbe9Sxc151355 } 64860ba2cbe9Sxc151355 64870ba2cbe9Sxc151355 /*ARGSUSED*/ 6488d62bc4baSyz147064 static int 6489*4ac67f02SAnurag S. Maskey i_dladm_init_linkprop(dladm_handle_t dh, datalink_id_t linkid, void *arg) 6490d62bc4baSyz147064 { 6491*4ac67f02SAnurag S. Maskey (void) dladm_init_linkprop(dh, linkid, B_TRUE); 6492d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 6493d62bc4baSyz147064 } 6494d62bc4baSyz147064 64958d5c46e6Sam223141 /*ARGSUSED*/ 6496da14cebeSEric Cheng void 64978d5c46e6Sam223141 do_init_linkprop(int argc, char **argv, const char *use) 64980ba2cbe9Sxc151355 { 649930890389Sartem int option; 650030890389Sartem dladm_status_t status; 650130890389Sartem datalink_id_t linkid = DATALINK_ALL_LINKID; 650230890389Sartem datalink_media_t media = DATALINK_ANY_MEDIATYPE; 650330890389Sartem uint_t any_media = B_TRUE; 650430890389Sartem 650530890389Sartem opterr = 0; 650630890389Sartem while ((option = getopt(argc, argv, ":w")) != -1) { 650730890389Sartem switch (option) { 650830890389Sartem case 'w': 650930890389Sartem media = DL_WIFI; 651030890389Sartem any_media = B_FALSE; 651130890389Sartem break; 651230890389Sartem default: 65138d5c46e6Sam223141 /* 65148d5c46e6Sam223141 * Because init-linkprop is not a public command, 65158d5c46e6Sam223141 * print the usage instead. 65168d5c46e6Sam223141 */ 65178d5c46e6Sam223141 usage(); 651830890389Sartem break; 651930890389Sartem } 652030890389Sartem } 652130890389Sartem 652230890389Sartem if (optind == (argc - 1)) { 6523*4ac67f02SAnurag S. Maskey if ((status = dladm_name2info(handle, argv[optind], &linkid, 6524*4ac67f02SAnurag S. Maskey NULL, NULL, NULL)) != DLADM_STATUS_OK) 652530890389Sartem die_dlerr(status, "link %s is not valid", argv[optind]); 652630890389Sartem } else if (optind != argc) { 652730890389Sartem usage(); 652830890389Sartem } 652930890389Sartem 653030890389Sartem if (linkid == DATALINK_ALL_LINKID) { 6531d62bc4baSyz147064 /* 653230890389Sartem * linkprops of links of other classes have been initialized as 6533d62bc4baSyz147064 * part of the dladm up-xxx operation. 6534d62bc4baSyz147064 */ 6535*4ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(i_dladm_init_linkprop, handle, 6536*4ac67f02SAnurag S. Maskey NULL, DATALINK_CLASS_PHYS, media, DLADM_OPT_PERSIST); 653730890389Sartem } else { 6538*4ac67f02SAnurag S. Maskey (void) dladm_init_linkprop(handle, linkid, any_media); 653930890389Sartem } 65400ba2cbe9Sxc151355 } 65410ba2cbe9Sxc151355 65420ba2cbe9Sxc151355 static void 65438d5c46e6Sam223141 do_show_ether(int argc, char **argv, const char *use) 6544e7801d59Ssowmini { 6545e7801d59Ssowmini int option; 6546e7801d59Ssowmini datalink_id_t linkid; 6547e7801d59Ssowmini print_ether_state_t state; 6548e7801d59Ssowmini print_field_t **fields; 65490d365605Sschuster boolean_t o_arg = B_FALSE; 6550e7801d59Ssowmini char *fields_str; 6551e7801d59Ssowmini uint_t nfields; 6552e7801d59Ssowmini char *all_fields = 6553e7801d59Ssowmini "link,ptype,state,auto,speed-duplex,pause,rem_fault"; 6554e7801d59Ssowmini char *default_fields = 6555e7801d59Ssowmini "link,ptype,state,auto,speed-duplex,pause"; 6556e7801d59Ssowmini 6557e7801d59Ssowmini fields_str = default_fields; 6558e7801d59Ssowmini bzero(&state, sizeof (state)); 6559e7801d59Ssowmini state.es_link = NULL; 6560e7801d59Ssowmini state.es_parseable = B_FALSE; 6561e7801d59Ssowmini 6562e7801d59Ssowmini while ((option = getopt_long(argc, argv, "o:px", 6563e7801d59Ssowmini showeth_lopts, NULL)) != -1) { 6564e7801d59Ssowmini switch (option) { 6565e7801d59Ssowmini case 'x': 6566e7801d59Ssowmini state.es_extended = B_TRUE; 6567e7801d59Ssowmini break; 6568e7801d59Ssowmini case 'p': 6569e7801d59Ssowmini state.es_parseable = B_TRUE; 6570e7801d59Ssowmini break; 6571e7801d59Ssowmini case 'o': 65720d365605Sschuster o_arg = B_TRUE; 6573e7801d59Ssowmini if (strcasecmp(optarg, "all") == 0) 6574e7801d59Ssowmini fields_str = all_fields; 6575e7801d59Ssowmini else 6576e7801d59Ssowmini fields_str = optarg; 6577e7801d59Ssowmini break; 6578e7801d59Ssowmini default: 65798d5c46e6Sam223141 die_opterr(optopt, option, use); 6580e7801d59Ssowmini break; 6581e7801d59Ssowmini } 6582e7801d59Ssowmini } 6583e7801d59Ssowmini 65840d365605Sschuster if (state.es_parseable && !o_arg) 65850d365605Sschuster die("-p requires -o"); 65860d365605Sschuster 65870d365605Sschuster if (state.es_parseable && fields_str == all_fields) 65880d365605Sschuster die("\"-o all\" is invalid with -p"); 65890d365605Sschuster 6590e7801d59Ssowmini if (optind == (argc - 1)) 6591e7801d59Ssowmini state.es_link = argv[optind]; 6592e7801d59Ssowmini 6593e7801d59Ssowmini fields = parse_output_fields(fields_str, ether_fields, 6594e7801d59Ssowmini ETHER_MAX_FIELDS, CMD_TYPE_ANY, &nfields); 6595e7801d59Ssowmini 6596*4ac67f02SAnurag S. Maskey if (fields == NULL) 6597e7801d59Ssowmini die("invalid field(s) specified"); 6598*4ac67f02SAnurag S. Maskey 6599e7801d59Ssowmini state.es_print.ps_fields = fields; 6600e7801d59Ssowmini state.es_print.ps_nfields = nfields; 6601e7801d59Ssowmini 6602*4ac67f02SAnurag S. Maskey 6603e7801d59Ssowmini if (state.es_link == NULL) { 6604*4ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(show_etherprop, handle, &state, 6605e7801d59Ssowmini DATALINK_CLASS_PHYS, DL_ETHER, 6606e7801d59Ssowmini DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST); 6607e7801d59Ssowmini } else { 6608*4ac67f02SAnurag S. Maskey if (!link_is_ether(state.es_link, &linkid)) 6609e7801d59Ssowmini die("invalid link specified"); 6610*4ac67f02SAnurag S. Maskey (void) show_etherprop(handle, linkid, &state); 6611e7801d59Ssowmini } 6612e7801d59Ssowmini } 6613e7801d59Ssowmini 6614e7801d59Ssowmini static char * 6615e7801d59Ssowmini dladm_print_field(print_field_t *pf, void *arg) 6616e7801d59Ssowmini { 6617e7801d59Ssowmini char *value; 6618e7801d59Ssowmini 6619e7801d59Ssowmini value = (char *)arg + pf->pf_offset; 6620e7801d59Ssowmini return (value); 6621e7801d59Ssowmini } 6622e7801d59Ssowmini 6623e7801d59Ssowmini static int 6624*4ac67f02SAnurag S. Maskey show_etherprop(dladm_handle_t dh, datalink_id_t linkid, void *arg) 6625e7801d59Ssowmini { 6626e7801d59Ssowmini print_ether_state_t *statep = arg; 6627e7801d59Ssowmini ether_fields_buf_t ebuf; 66284784fcbdSSowmini Varadhan dladm_ether_info_t eattr; 66294784fcbdSSowmini Varadhan dladm_status_t status; 6630e7801d59Ssowmini 66315f5c9f54SAnurag S. Maskey bzero(&ebuf, sizeof (ether_fields_buf_t)); 6632*4ac67f02SAnurag S. Maskey if (dladm_datalink_id2info(dh, linkid, NULL, NULL, NULL, 6633e7801d59Ssowmini ebuf.eth_link, sizeof (ebuf.eth_link)) != DLADM_STATUS_OK) { 6634e7801d59Ssowmini return (DLADM_WALK_CONTINUE); 6635e7801d59Ssowmini } 6636e7801d59Ssowmini 6637e7801d59Ssowmini if (!statep->es_header && !statep->es_parseable) { 6638e7801d59Ssowmini print_header(&statep->es_print); 6639e7801d59Ssowmini statep->es_header = B_TRUE; 6640e7801d59Ssowmini } 6641e7801d59Ssowmini 6642*4ac67f02SAnurag S. Maskey status = dladm_ether_info(dh, linkid, &eattr); 66434784fcbdSSowmini Varadhan if (status != DLADM_STATUS_OK) 66444784fcbdSSowmini Varadhan goto cleanup; 6645e7801d59Ssowmini 66464784fcbdSSowmini Varadhan (void) strlcpy(ebuf.eth_ptype, "current", sizeof (ebuf.eth_ptype)); 6647e7801d59Ssowmini 66484784fcbdSSowmini Varadhan (void) dladm_ether_autoneg2str(ebuf.eth_autoneg, 66494784fcbdSSowmini Varadhan sizeof (ebuf.eth_autoneg), &eattr, CURRENT); 66504784fcbdSSowmini Varadhan (void) dladm_ether_pause2str(ebuf.eth_pause, 66514784fcbdSSowmini Varadhan sizeof (ebuf.eth_pause), &eattr, CURRENT); 66524784fcbdSSowmini Varadhan (void) dladm_ether_spdx2str(ebuf.eth_spdx, 66534784fcbdSSowmini Varadhan sizeof (ebuf.eth_spdx), &eattr, CURRENT); 66544784fcbdSSowmini Varadhan (void) strlcpy(ebuf.eth_state, 66554784fcbdSSowmini Varadhan dladm_linkstate2str(eattr.lei_state, ebuf.eth_state), 66564784fcbdSSowmini Varadhan sizeof (ebuf.eth_state)); 66574784fcbdSSowmini Varadhan (void) strlcpy(ebuf.eth_rem_fault, 66584784fcbdSSowmini Varadhan (eattr.lei_attr[CURRENT].le_fault ? "fault" : "none"), 66594784fcbdSSowmini Varadhan sizeof (ebuf.eth_rem_fault)); 6660e7801d59Ssowmini 6661e7801d59Ssowmini dladm_print_output(&statep->es_print, statep->es_parseable, 6662e7801d59Ssowmini dladm_print_field, &ebuf); 6663e7801d59Ssowmini 6664e7801d59Ssowmini if (statep->es_extended) 66654784fcbdSSowmini Varadhan show_ether_xprop(arg, &eattr); 6666e7801d59Ssowmini 66674784fcbdSSowmini Varadhan cleanup: 66684784fcbdSSowmini Varadhan dladm_ether_info_done(&eattr); 6669e7801d59Ssowmini return (DLADM_WALK_CONTINUE); 6670e7801d59Ssowmini } 6671e7801d59Ssowmini 6672e7801d59Ssowmini /* ARGSUSED */ 6673e7801d59Ssowmini static void 66748d5c46e6Sam223141 do_init_secobj(int argc, char **argv, const char *use) 66750ba2cbe9Sxc151355 { 66760ba2cbe9Sxc151355 dladm_status_t status; 66770ba2cbe9Sxc151355 6678*4ac67f02SAnurag S. Maskey status = dladm_init_secobj(handle); 667933343a97Smeem if (status != DLADM_STATUS_OK) 668033343a97Smeem die_dlerr(status, "secure object initialization failed"); 668133343a97Smeem } 668233343a97Smeem 6683d62bc4baSyz147064 /* 6684d62bc4baSyz147064 * "-R" option support. It is used for live upgrading. Append dladm commands 6685d62bc4baSyz147064 * to a upgrade script which will be run when the alternative root boots up: 6686d62bc4baSyz147064 * 6687b9e076dcSyz147064 * - If the /etc/dladm/datalink.conf file exists on the alternative root, 6688b9e076dcSyz147064 * append dladm commands to the <altroot>/var/svc/profile/upgrade_datalink 6689b9e076dcSyz147064 * script. This script will be run as part of the network/physical service. 6690b9e076dcSyz147064 * We cannot defer this to /var/svc/profile/upgrade because then the 6691b9e076dcSyz147064 * configuration will not be able to take effect before network/physical 6692b9e076dcSyz147064 * plumbs various interfaces. 6693d62bc4baSyz147064 * 6694b9e076dcSyz147064 * - If the /etc/dladm/datalink.conf file does not exist on the alternative 6695b9e076dcSyz147064 * root, append dladm commands to the <altroot>/var/svc/profile/upgrade script, 6696b9e076dcSyz147064 * which will be run in the manifest-import service. 6697d62bc4baSyz147064 * 6698d62bc4baSyz147064 * Note that the SMF team is considering to move the manifest-import service 6699d62bc4baSyz147064 * to be run at the very begining of boot. Once that is done, the need for 6700d62bc4baSyz147064 * the /var/svc/profile/upgrade_datalink script will not exist any more. 6701d62bc4baSyz147064 */ 6702d62bc4baSyz147064 static void 6703d62bc4baSyz147064 altroot_cmd(char *altroot, int argc, char *argv[]) 6704d62bc4baSyz147064 { 6705d62bc4baSyz147064 char path[MAXPATHLEN]; 6706d62bc4baSyz147064 struct stat stbuf; 6707d62bc4baSyz147064 FILE *fp; 6708d62bc4baSyz147064 int i; 6709d62bc4baSyz147064 6710d62bc4baSyz147064 /* 6711b9e076dcSyz147064 * Check for the existence of the /etc/dladm/datalink.conf 6712b9e076dcSyz147064 * configuration file, and determine the name of script file. 6713d62bc4baSyz147064 */ 6714b9e076dcSyz147064 (void) snprintf(path, MAXPATHLEN, "/%s/etc/dladm/datalink.conf", 6715b9e076dcSyz147064 altroot); 6716d62bc4baSyz147064 if (stat(path, &stbuf) < 0) { 6717d62bc4baSyz147064 (void) snprintf(path, MAXPATHLEN, "/%s/%s", altroot, 6718d62bc4baSyz147064 SMF_UPGRADE_FILE); 6719d62bc4baSyz147064 } else { 6720d62bc4baSyz147064 (void) snprintf(path, MAXPATHLEN, "/%s/%s", altroot, 6721d62bc4baSyz147064 SMF_UPGRADEDATALINK_FILE); 6722d62bc4baSyz147064 } 6723d62bc4baSyz147064 6724d62bc4baSyz147064 if ((fp = fopen(path, "a+")) == NULL) 6725d62bc4baSyz147064 die("operation not supported on %s", altroot); 6726d62bc4baSyz147064 6727d62bc4baSyz147064 (void) fprintf(fp, "/sbin/dladm "); 6728d62bc4baSyz147064 for (i = 0; i < argc; i++) { 6729d62bc4baSyz147064 /* 6730d62bc4baSyz147064 * Directly write to the file if it is not the "-R <altroot>" 6731d62bc4baSyz147064 * option. In which case, skip it. 6732d62bc4baSyz147064 */ 6733d62bc4baSyz147064 if (strcmp(argv[i], "-R") != 0) 6734d62bc4baSyz147064 (void) fprintf(fp, "%s ", argv[i]); 6735d62bc4baSyz147064 else 6736d62bc4baSyz147064 i ++; 6737d62bc4baSyz147064 } 6738d62bc4baSyz147064 (void) fprintf(fp, "%s\n", SMF_DLADM_UPGRADE_MSG); 6739d62bc4baSyz147064 (void) fclose(fp); 6740*4ac67f02SAnurag S. Maskey dladm_close(handle); 6741d62bc4baSyz147064 exit(0); 6742d62bc4baSyz147064 } 6743d62bc4baSyz147064 6744d62bc4baSyz147064 /* 6745d62bc4baSyz147064 * Convert the string to an integer. Note that the string must not have any 6746d62bc4baSyz147064 * trailing non-integer characters. 6747d62bc4baSyz147064 */ 674833343a97Smeem static boolean_t 674933343a97Smeem str2int(const char *str, int *valp) 675033343a97Smeem { 675133343a97Smeem int val; 675233343a97Smeem char *endp = NULL; 675333343a97Smeem 675433343a97Smeem errno = 0; 675533343a97Smeem val = strtol(str, &endp, 10); 675633343a97Smeem if (errno != 0 || *endp != '\0') 675733343a97Smeem return (B_FALSE); 675833343a97Smeem 675933343a97Smeem *valp = val; 676033343a97Smeem return (B_TRUE); 676133343a97Smeem } 676233343a97Smeem 676333343a97Smeem /* PRINTFLIKE1 */ 676433343a97Smeem static void 676533343a97Smeem warn(const char *format, ...) 676633343a97Smeem { 676733343a97Smeem va_list alist; 676833343a97Smeem 676933343a97Smeem format = gettext(format); 677033343a97Smeem (void) fprintf(stderr, "%s: warning: ", progname); 677133343a97Smeem 677233343a97Smeem va_start(alist, format); 677333343a97Smeem (void) vfprintf(stderr, format, alist); 677433343a97Smeem va_end(alist); 677533343a97Smeem 677633343a97Smeem (void) putchar('\n'); 677733343a97Smeem } 677833343a97Smeem 677933343a97Smeem /* PRINTFLIKE2 */ 678033343a97Smeem static void 678133343a97Smeem warn_dlerr(dladm_status_t err, const char *format, ...) 678233343a97Smeem { 678333343a97Smeem va_list alist; 678433343a97Smeem char errmsg[DLADM_STRSIZE]; 678533343a97Smeem 678633343a97Smeem format = gettext(format); 678733343a97Smeem (void) fprintf(stderr, gettext("%s: warning: "), progname); 678833343a97Smeem 678933343a97Smeem va_start(alist, format); 679033343a97Smeem (void) vfprintf(stderr, format, alist); 679133343a97Smeem va_end(alist); 679233343a97Smeem (void) fprintf(stderr, ": %s\n", dladm_status2str(err, errmsg)); 679333343a97Smeem } 679433343a97Smeem 6795*4ac67f02SAnurag S. Maskey /* 6796*4ac67f02SAnurag S. Maskey * Also closes the dladm handle if it is not NULL. 6797*4ac67f02SAnurag S. Maskey */ 679833343a97Smeem /* PRINTFLIKE2 */ 679933343a97Smeem static void 680033343a97Smeem die_dlerr(dladm_status_t err, const char *format, ...) 680133343a97Smeem { 680233343a97Smeem va_list alist; 680333343a97Smeem char errmsg[DLADM_STRSIZE]; 680433343a97Smeem 680533343a97Smeem format = gettext(format); 680633343a97Smeem (void) fprintf(stderr, "%s: ", progname); 680733343a97Smeem 680833343a97Smeem va_start(alist, format); 680933343a97Smeem (void) vfprintf(stderr, format, alist); 681033343a97Smeem va_end(alist); 681133343a97Smeem (void) fprintf(stderr, ": %s\n", dladm_status2str(err, errmsg)); 681233343a97Smeem 6813*4ac67f02SAnurag S. Maskey /* close dladm handle if it was opened */ 6814*4ac67f02SAnurag S. Maskey if (handle != NULL) 6815*4ac67f02SAnurag S. Maskey dladm_close(handle); 6816*4ac67f02SAnurag S. Maskey 681733343a97Smeem exit(EXIT_FAILURE); 681833343a97Smeem } 681933343a97Smeem 682033343a97Smeem /* PRINTFLIKE1 */ 682133343a97Smeem static void 682233343a97Smeem die(const char *format, ...) 682333343a97Smeem { 682433343a97Smeem va_list alist; 682533343a97Smeem 682633343a97Smeem format = gettext(format); 682733343a97Smeem (void) fprintf(stderr, "%s: ", progname); 682833343a97Smeem 682933343a97Smeem va_start(alist, format); 683033343a97Smeem (void) vfprintf(stderr, format, alist); 683133343a97Smeem va_end(alist); 683233343a97Smeem 683333343a97Smeem (void) putchar('\n'); 6834*4ac67f02SAnurag S. Maskey 6835*4ac67f02SAnurag S. Maskey /* close dladm handle if it was opened */ 6836*4ac67f02SAnurag S. Maskey if (handle != NULL) 6837*4ac67f02SAnurag S. Maskey dladm_close(handle); 6838*4ac67f02SAnurag S. Maskey 683933343a97Smeem exit(EXIT_FAILURE); 684033343a97Smeem } 684133343a97Smeem 684233343a97Smeem static void 684333343a97Smeem die_optdup(int opt) 684433343a97Smeem { 684533343a97Smeem die("the option -%c cannot be specified more than once", opt); 684633343a97Smeem } 684733343a97Smeem 684833343a97Smeem static void 68498d5c46e6Sam223141 die_opterr(int opt, int opterr, const char *usage) 685033343a97Smeem { 685133343a97Smeem switch (opterr) { 685233343a97Smeem case ':': 68538d5c46e6Sam223141 die("option '-%c' requires a value\nusage: %s", opt, 68548d5c46e6Sam223141 gettext(usage)); 685533343a97Smeem break; 685633343a97Smeem case '?': 685733343a97Smeem default: 68588d5c46e6Sam223141 die("unrecognized option '-%c'\nusage: %s", opt, 68598d5c46e6Sam223141 gettext(usage)); 686033343a97Smeem break; 68610ba2cbe9Sxc151355 } 68620ba2cbe9Sxc151355 } 6863e7801d59Ssowmini 6864e7801d59Ssowmini static void 68654784fcbdSSowmini Varadhan show_ether_xprop(void *arg, dladm_ether_info_t *eattr) 6866e7801d59Ssowmini { 6867e7801d59Ssowmini print_ether_state_t *statep = arg; 6868e7801d59Ssowmini ether_fields_buf_t ebuf; 68694784fcbdSSowmini Varadhan int i; 6870e7801d59Ssowmini 68714784fcbdSSowmini Varadhan for (i = CAPABLE; i <= PEERADV; i++) { 6872e7801d59Ssowmini bzero(&ebuf, sizeof (ebuf)); 68734784fcbdSSowmini Varadhan (void) strlcpy(ebuf.eth_ptype, ptype[i], 68744784fcbdSSowmini Varadhan sizeof (ebuf.eth_ptype)); 68754784fcbdSSowmini Varadhan (void) dladm_ether_autoneg2str(ebuf.eth_autoneg, 68764784fcbdSSowmini Varadhan sizeof (ebuf.eth_autoneg), eattr, i); 68774784fcbdSSowmini Varadhan (void) dladm_ether_spdx2str(ebuf.eth_spdx, 68784784fcbdSSowmini Varadhan sizeof (ebuf.eth_spdx), eattr, i); 68794784fcbdSSowmini Varadhan (void) dladm_ether_pause2str(ebuf.eth_pause, 68804784fcbdSSowmini Varadhan sizeof (ebuf.eth_pause), eattr, i); 68814784fcbdSSowmini Varadhan (void) strlcpy(ebuf.eth_rem_fault, 68824784fcbdSSowmini Varadhan (eattr->lei_attr[i].le_fault ? "fault" : "none"), 68834784fcbdSSowmini Varadhan sizeof (ebuf.eth_rem_fault)); 6884e7801d59Ssowmini dladm_print_output(&statep->es_print, statep->es_parseable, 6885e7801d59Ssowmini dladm_print_field, &ebuf); 6886e7801d59Ssowmini } 6887e7801d59Ssowmini 6888e7801d59Ssowmini } 6889e7801d59Ssowmini 6890e7801d59Ssowmini static void 6891e7801d59Ssowmini dladm_print_output(print_state_t *statep, boolean_t parseable, 6892e7801d59Ssowmini print_callback_t fn, void *arg) 6893e7801d59Ssowmini { 6894e7801d59Ssowmini int i; 6895e7801d59Ssowmini char *value; 6896e7801d59Ssowmini print_field_t **pf; 6897e7801d59Ssowmini 6898e7801d59Ssowmini pf = statep->ps_fields; 6899e7801d59Ssowmini for (i = 0; i < statep->ps_nfields; i++) { 6900e7801d59Ssowmini statep->ps_lastfield = (i + 1 == statep->ps_nfields); 6901e7801d59Ssowmini value = (*fn)(pf[i], arg); 6902e7801d59Ssowmini if (value != NULL) 6903e7801d59Ssowmini print_field(statep, pf[i], value, parseable); 6904e7801d59Ssowmini } 6905e7801d59Ssowmini (void) putchar('\n'); 6906e7801d59Ssowmini } 6907e7801d59Ssowmini 6908e7801d59Ssowmini static void 6909e7801d59Ssowmini print_header(print_state_t *ps) 6910e7801d59Ssowmini { 6911e7801d59Ssowmini int i; 6912e7801d59Ssowmini print_field_t **pf; 6913e7801d59Ssowmini 6914e7801d59Ssowmini pf = ps->ps_fields; 6915e7801d59Ssowmini for (i = 0; i < ps->ps_nfields; i++) { 6916e7801d59Ssowmini ps->ps_lastfield = (i + 1 == ps->ps_nfields); 6917e7801d59Ssowmini print_field(ps, pf[i], pf[i]->pf_header, B_FALSE); 6918e7801d59Ssowmini } 6919e7801d59Ssowmini (void) putchar('\n'); 6920e7801d59Ssowmini } 6921e7801d59Ssowmini 6922e7801d59Ssowmini static boolean_t 6923e7801d59Ssowmini link_is_ether(const char *link, datalink_id_t *linkid) 6924e7801d59Ssowmini { 6925e7801d59Ssowmini uint32_t media; 6926e7801d59Ssowmini datalink_class_t class; 6927e7801d59Ssowmini 6928*4ac67f02SAnurag S. Maskey if (dladm_name2info(handle, link, linkid, NULL, &class, &media) == 6929e7801d59Ssowmini DLADM_STATUS_OK) { 6930e7801d59Ssowmini if (class == DATALINK_CLASS_PHYS && media == DL_ETHER) 6931e7801d59Ssowmini return (B_TRUE); 6932e7801d59Ssowmini } 6933e7801d59Ssowmini return (B_FALSE); 6934e7801d59Ssowmini } 6935