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 /* 22219a2a31Shl157128 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 277c478bd9Sstevel@tonic-gate 287c478bd9Sstevel@tonic-gate #include <stdio.h> 29*0ba2cbe9Sxc151355 #include <ctype.h> 307c478bd9Sstevel@tonic-gate #include <locale.h> 31*0ba2cbe9Sxc151355 #include <signal.h> 327c478bd9Sstevel@tonic-gate #include <stdarg.h> 337c478bd9Sstevel@tonic-gate #include <stdlib.h> 347c478bd9Sstevel@tonic-gate #include <fcntl.h> 357c478bd9Sstevel@tonic-gate #include <string.h> 367c478bd9Sstevel@tonic-gate #include <stropts.h> 377c478bd9Sstevel@tonic-gate #include <errno.h> 387c478bd9Sstevel@tonic-gate #include <kstat.h> 397c478bd9Sstevel@tonic-gate #include <strings.h> 407c478bd9Sstevel@tonic-gate #include <getopt.h> 417c478bd9Sstevel@tonic-gate #include <unistd.h> 42cd93090eSericheng #include <priv.h> 43*0ba2cbe9Sxc151355 #include <termios.h> 44*0ba2cbe9Sxc151355 #include <pwd.h> 45*0ba2cbe9Sxc151355 #include <auth_attr.h> 46*0ba2cbe9Sxc151355 #include <auth_list.h> 477c478bd9Sstevel@tonic-gate #include <libintl.h> 487c478bd9Sstevel@tonic-gate #include <libdlpi.h> 497c478bd9Sstevel@tonic-gate #include <libdladm.h> 507c478bd9Sstevel@tonic-gate #include <liblaadm.h> 517c478bd9Sstevel@tonic-gate #include <libmacadm.h> 52*0ba2cbe9Sxc151355 #include <libwladm.h> 53*0ba2cbe9Sxc151355 #include <libinetutil.h> 54*0ba2cbe9Sxc151355 #include <bsm/adt.h> 55*0ba2cbe9Sxc151355 #include <bsm/adt_event.h> 567c478bd9Sstevel@tonic-gate 57ba2e4443Sseb #define AGGR_DRV "aggr" 587c478bd9Sstevel@tonic-gate #define MAXPORT 256 597c478bd9Sstevel@tonic-gate #define DUMP_LACP_FORMAT " %-9s %-8s %-7s %-12s " \ 607c478bd9Sstevel@tonic-gate "%-5s %-4s %-4s %-9s %-7s\n" 617c478bd9Sstevel@tonic-gate 627c478bd9Sstevel@tonic-gate typedef struct pktsum_s { 637c478bd9Sstevel@tonic-gate uint64_t ipackets; 647c478bd9Sstevel@tonic-gate uint64_t opackets; 657c478bd9Sstevel@tonic-gate uint64_t rbytes; 667c478bd9Sstevel@tonic-gate uint64_t obytes; 677c478bd9Sstevel@tonic-gate uint32_t ierrors; 687c478bd9Sstevel@tonic-gate uint32_t oerrors; 697c478bd9Sstevel@tonic-gate } pktsum_t; 707c478bd9Sstevel@tonic-gate 717c478bd9Sstevel@tonic-gate typedef struct show_link_state { 727c478bd9Sstevel@tonic-gate boolean_t ls_firstonly; 737c478bd9Sstevel@tonic-gate boolean_t ls_donefirst; 747c478bd9Sstevel@tonic-gate boolean_t ls_stats; 757c478bd9Sstevel@tonic-gate pktsum_t ls_prevstats; 767c478bd9Sstevel@tonic-gate boolean_t ls_parseable; 777c478bd9Sstevel@tonic-gate } show_link_state_t; 787c478bd9Sstevel@tonic-gate 797c478bd9Sstevel@tonic-gate typedef struct show_grp_state { 807c478bd9Sstevel@tonic-gate uint32_t gs_key; 817c478bd9Sstevel@tonic-gate boolean_t gs_lacp; 827c478bd9Sstevel@tonic-gate boolean_t gs_found; 837c478bd9Sstevel@tonic-gate boolean_t gs_stats; 847c478bd9Sstevel@tonic-gate boolean_t gs_firstonly; 857c478bd9Sstevel@tonic-gate pktsum_t gs_prevstats[MAXPORT]; 867c478bd9Sstevel@tonic-gate boolean_t gs_parseable; 877c478bd9Sstevel@tonic-gate } show_grp_state_t; 887c478bd9Sstevel@tonic-gate 897c478bd9Sstevel@tonic-gate typedef struct show_mac_state { 907c478bd9Sstevel@tonic-gate boolean_t ms_firstonly; 917c478bd9Sstevel@tonic-gate boolean_t ms_donefirst; 927c478bd9Sstevel@tonic-gate pktsum_t ms_prevstats; 937c478bd9Sstevel@tonic-gate boolean_t ms_parseable; 947c478bd9Sstevel@tonic-gate } show_mac_state_t; 957c478bd9Sstevel@tonic-gate 967c478bd9Sstevel@tonic-gate typedef struct port_state { 977c478bd9Sstevel@tonic-gate char *state_name; 987c478bd9Sstevel@tonic-gate aggr_port_state_t state_num; 997c478bd9Sstevel@tonic-gate } port_state_t; 1007c478bd9Sstevel@tonic-gate 1017c478bd9Sstevel@tonic-gate static port_state_t port_states[] = { 1027c478bd9Sstevel@tonic-gate {"standby", AGGR_PORT_STATE_STANDBY }, 1037c478bd9Sstevel@tonic-gate {"attached", AGGR_PORT_STATE_ATTACHED } 1047c478bd9Sstevel@tonic-gate }; 1057c478bd9Sstevel@tonic-gate 1067c478bd9Sstevel@tonic-gate #define NPORTSTATES (sizeof (port_states) / sizeof (port_state_t)) 1077c478bd9Sstevel@tonic-gate 108*0ba2cbe9Sxc151355 typedef void cmdfunc_t(int, char **); 109*0ba2cbe9Sxc151355 110*0ba2cbe9Sxc151355 static cmdfunc_t do_show_link, do_show_dev, do_show_wifi; 111*0ba2cbe9Sxc151355 static cmdfunc_t do_create_aggr, do_delete_aggr, do_add_aggr, do_remove_aggr; 112*0ba2cbe9Sxc151355 static cmdfunc_t do_modify_aggr, do_show_aggr, do_up_aggr, do_down_aggr; 113*0ba2cbe9Sxc151355 static cmdfunc_t do_scan_wifi, do_connect_wifi, do_disconnect_wifi; 114*0ba2cbe9Sxc151355 static cmdfunc_t do_show_linkprop, do_set_linkprop, do_reset_linkprop; 115*0ba2cbe9Sxc151355 static cmdfunc_t do_create_secobj, do_delete_secobj, do_show_secobj; 116*0ba2cbe9Sxc151355 static cmdfunc_t do_init_linkprop, do_init_secobj; 1177c478bd9Sstevel@tonic-gate 1187c478bd9Sstevel@tonic-gate static void link_stats(const char *, uint32_t); 1197c478bd9Sstevel@tonic-gate static void aggr_stats(uint16_t, uint32_t); 1207c478bd9Sstevel@tonic-gate static void dev_stats(const char *dev, uint32_t); 1217c478bd9Sstevel@tonic-gate 122ba2e4443Sseb static void get_mac_stats(const char *, pktsum_t *); 1237c478bd9Sstevel@tonic-gate static void get_link_stats(const char *, pktsum_t *); 124ba2e4443Sseb static uint64_t mac_ifspeed(const char *); 125ba2e4443Sseb static char *mac_link_state(const char *); 126ba2e4443Sseb static char *mac_link_duplex(const char *); 1277c478bd9Sstevel@tonic-gate static void stats_total(pktsum_t *, pktsum_t *, pktsum_t *); 1287c478bd9Sstevel@tonic-gate static void stats_diff(pktsum_t *, pktsum_t *, pktsum_t *); 1297c478bd9Sstevel@tonic-gate 1307c478bd9Sstevel@tonic-gate typedef struct cmd { 1317c478bd9Sstevel@tonic-gate char *c_name; 132*0ba2cbe9Sxc151355 cmdfunc_t *c_fn; 1337c478bd9Sstevel@tonic-gate } cmd_t; 1347c478bd9Sstevel@tonic-gate 1357c478bd9Sstevel@tonic-gate static cmd_t cmds[] = { 1367c478bd9Sstevel@tonic-gate { "show-link", do_show_link }, 137210db224Sericheng { "show-dev", do_show_dev }, 1387c478bd9Sstevel@tonic-gate { "create-aggr", do_create_aggr }, 1397c478bd9Sstevel@tonic-gate { "delete-aggr", do_delete_aggr }, 1407c478bd9Sstevel@tonic-gate { "add-aggr", do_add_aggr }, 1417c478bd9Sstevel@tonic-gate { "remove-aggr", do_remove_aggr }, 1427c478bd9Sstevel@tonic-gate { "modify-aggr", do_modify_aggr }, 1437c478bd9Sstevel@tonic-gate { "show-aggr", do_show_aggr }, 1447c478bd9Sstevel@tonic-gate { "up-aggr", do_up_aggr }, 145*0ba2cbe9Sxc151355 { "down-aggr", do_down_aggr }, 146*0ba2cbe9Sxc151355 { "scan-wifi", do_scan_wifi }, 147*0ba2cbe9Sxc151355 { "connect-wifi", do_connect_wifi }, 148*0ba2cbe9Sxc151355 { "disconnect-wifi", do_disconnect_wifi }, 149*0ba2cbe9Sxc151355 { "show-wifi", do_show_wifi }, 150*0ba2cbe9Sxc151355 { "show-linkprop", do_show_linkprop }, 151*0ba2cbe9Sxc151355 { "set-linkprop", do_set_linkprop }, 152*0ba2cbe9Sxc151355 { "reset-linkprop", do_reset_linkprop }, 153*0ba2cbe9Sxc151355 { "create-secobj", do_create_secobj }, 154*0ba2cbe9Sxc151355 { "delete-secobj", do_delete_secobj }, 155*0ba2cbe9Sxc151355 { "show-secobj", do_show_secobj }, 156*0ba2cbe9Sxc151355 { "init-linkprop", do_init_linkprop }, 157*0ba2cbe9Sxc151355 { "init-secobj", do_init_secobj } 1587c478bd9Sstevel@tonic-gate }; 1597c478bd9Sstevel@tonic-gate 1607c478bd9Sstevel@tonic-gate static const struct option longopts[] = { 1617c478bd9Sstevel@tonic-gate {"vlan-id", required_argument, 0, 'v' }, 1627c478bd9Sstevel@tonic-gate {"dev", required_argument, 0, 'd' }, 1637c478bd9Sstevel@tonic-gate {"policy", required_argument, 0, 'P' }, 1647c478bd9Sstevel@tonic-gate {"lacp-mode", required_argument, 0, 'l' }, 1657c478bd9Sstevel@tonic-gate {"lacp-timer", required_argument, 0, 'T' }, 1667c478bd9Sstevel@tonic-gate {"unicast", required_argument, 0, 'u' }, 1677c478bd9Sstevel@tonic-gate {"statistics", no_argument, 0, 's' }, 1687c478bd9Sstevel@tonic-gate {"interval", required_argument, 0, 'i' }, 1697c478bd9Sstevel@tonic-gate {"lacp", no_argument, 0, 'L' }, 1707c478bd9Sstevel@tonic-gate {"temporary", no_argument, 0, 't' }, 1717c478bd9Sstevel@tonic-gate {"root-dir", required_argument, 0, 'r' }, 1727c478bd9Sstevel@tonic-gate {"parseable", no_argument, 0, 'p' }, 1737c478bd9Sstevel@tonic-gate { 0, 0, 0, 0 } 1747c478bd9Sstevel@tonic-gate }; 1757c478bd9Sstevel@tonic-gate 176*0ba2cbe9Sxc151355 static const struct option prop_longopts[] = { 177*0ba2cbe9Sxc151355 {"temporary", no_argument, 0, 't' }, 178*0ba2cbe9Sxc151355 {"root-dir", required_argument, 0, 'R' }, 179*0ba2cbe9Sxc151355 {"prop", required_argument, 0, 'p' }, 180*0ba2cbe9Sxc151355 {"parseable", no_argument, 0, 'c' }, 181*0ba2cbe9Sxc151355 {"persistent", no_argument, 0, 'P' }, 182*0ba2cbe9Sxc151355 { 0, 0, 0, 0 } 183*0ba2cbe9Sxc151355 }; 184*0ba2cbe9Sxc151355 185*0ba2cbe9Sxc151355 static const struct option wifi_longopts[] = { 186*0ba2cbe9Sxc151355 {"parseable", no_argument, 0, 'p' }, 187*0ba2cbe9Sxc151355 {"output", required_argument, 0, 'o' }, 188*0ba2cbe9Sxc151355 {"essid", required_argument, 0, 'e' }, 189*0ba2cbe9Sxc151355 {"bsstype", required_argument, 0, 'b' }, 190*0ba2cbe9Sxc151355 {"mode", required_argument, 0, 'm' }, 191*0ba2cbe9Sxc151355 {"key", required_argument, 0, 'k' }, 192*0ba2cbe9Sxc151355 {"sec", required_argument, 0, 's' }, 193*0ba2cbe9Sxc151355 {"auth", required_argument, 0, 'a' }, 194*0ba2cbe9Sxc151355 {"create-ibss", required_argument, 0, 'c' }, 195*0ba2cbe9Sxc151355 {"timeout", required_argument, 0, 'T' }, 196*0ba2cbe9Sxc151355 {"all-links", no_argument, 0, 'a' }, 197*0ba2cbe9Sxc151355 {"temporary", no_argument, 0, 't' }, 198*0ba2cbe9Sxc151355 {"root-dir", required_argument, 0, 'R' }, 199*0ba2cbe9Sxc151355 {"persistent", no_argument, 0, 'P' }, 200*0ba2cbe9Sxc151355 {"file", required_argument, 0, 'f' }, 201*0ba2cbe9Sxc151355 { 0, 0, 0, 0 } 202*0ba2cbe9Sxc151355 }; 203*0ba2cbe9Sxc151355 2047c478bd9Sstevel@tonic-gate static char *progname; 205*0ba2cbe9Sxc151355 static sig_atomic_t signalled; 2067c478bd9Sstevel@tonic-gate 2077c478bd9Sstevel@tonic-gate #define PRINT_ERR_DIAG(s, diag, func) { \ 2087c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(s), progname, strerror(errno)); \ 2097c478bd9Sstevel@tonic-gate if (diag != 0) \ 2107c478bd9Sstevel@tonic-gate (void) fprintf(stderr, " (%s)", func(diag)); \ 2117c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "\n"); \ 2127c478bd9Sstevel@tonic-gate } 2137c478bd9Sstevel@tonic-gate 2147c478bd9Sstevel@tonic-gate static void 2157c478bd9Sstevel@tonic-gate usage(void) 2167c478bd9Sstevel@tonic-gate { 217*0ba2cbe9Sxc151355 (void) fprintf(stderr, gettext("usage: dladm <subcommand> <args> ...\n" 218*0ba2cbe9Sxc151355 "\tshow-link [-p] [-s [-i <interval>]] [<name>]\n" 219*0ba2cbe9Sxc151355 "\tshow-dev [-p] [-s [-i <interval>]] [<dev>]\n" 220*0ba2cbe9Sxc151355 "\n" 221*0ba2cbe9Sxc151355 "\tcreate-aggr [-t] [-R <root-dir>] [-P <policy>] [-l <mode>]\n" 222*0ba2cbe9Sxc151355 "\t [-T <time>] [-u <address>] -d <dev> ... <key>\n" 223*0ba2cbe9Sxc151355 "\tmodify-aggr [-t] [-R <root-dir>] [-P <policy>] [-l <mode>]\n" 224*0ba2cbe9Sxc151355 "\t [-T <time>] [-u <address>] <key>\n" 225*0ba2cbe9Sxc151355 "\tdelete-aggr [-t] [-R <root-dir>] <key>\n" 226*0ba2cbe9Sxc151355 "\tadd-aggr [-t] [-R <root-dir>] -d <dev> ... <key>\n" 227*0ba2cbe9Sxc151355 "\tremove-aggr [-t] [-R <root-dir>] -d <dev> ... <key>\n" 228*0ba2cbe9Sxc151355 "\tshow-aggr [-pL][-s [-i <interval>]] [<key>]\n" 229*0ba2cbe9Sxc151355 "\n" 230*0ba2cbe9Sxc151355 "\tscan-wifi [-p] [-o <field>,...] [<name>]\n" 231*0ba2cbe9Sxc151355 "\tconnect-wifi [-e <essid>] [-i <bssid>] [-k <key>,...]" 232*0ba2cbe9Sxc151355 " [-s wep]\n" 233*0ba2cbe9Sxc151355 "\t [-a open|shared] [-b bss|ibss] [-c] [-m a|b|g]\n" 234*0ba2cbe9Sxc151355 "\t [-T <time>] [<name>]\n" 235*0ba2cbe9Sxc151355 "\tdisconnect-wifi [-a] [<name>]\n" 236*0ba2cbe9Sxc151355 "\tshow-wifi [-p] [-o <field>,...] [<name>]\n" 237*0ba2cbe9Sxc151355 "\n" 238*0ba2cbe9Sxc151355 "\tset-linkprop [-t] [-R <root-dir>] -p <prop>=<value>[,...]" 239*0ba2cbe9Sxc151355 " <name>\n" 240*0ba2cbe9Sxc151355 "\treset-linkprop [-t] [-R <root-dir>] [-p <prop>,...] <name>\n" 241*0ba2cbe9Sxc151355 "\tshow-linkprop [-cP][-p <prop>,...] <name>\n" 242*0ba2cbe9Sxc151355 "\n" 243*0ba2cbe9Sxc151355 "\tcreate-secobj [-t] [-R <root-dir>] [-f <file>] -c <class>" 244*0ba2cbe9Sxc151355 " <secobj>\n" 245*0ba2cbe9Sxc151355 "\tdelete-secobj [-t] [-R <root-dir>] <secobj>[,...]\n" 246*0ba2cbe9Sxc151355 "\tshow-secobj [-pP][<secobj>,...]\n")); 2477c478bd9Sstevel@tonic-gate exit(1); 2487c478bd9Sstevel@tonic-gate } 2497c478bd9Sstevel@tonic-gate 2507c478bd9Sstevel@tonic-gate int 2517c478bd9Sstevel@tonic-gate main(int argc, char *argv[]) 2527c478bd9Sstevel@tonic-gate { 2537c478bd9Sstevel@tonic-gate int i; 2547c478bd9Sstevel@tonic-gate cmd_t *cmdp; 2557c478bd9Sstevel@tonic-gate 2567c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, ""); 2577c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN) 2587c478bd9Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST" 2597c478bd9Sstevel@tonic-gate #endif 2607c478bd9Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN); 2617c478bd9Sstevel@tonic-gate 2627c478bd9Sstevel@tonic-gate progname = argv[0]; 2637c478bd9Sstevel@tonic-gate 2647c478bd9Sstevel@tonic-gate if (argc < 2) 2657c478bd9Sstevel@tonic-gate usage(); 2667c478bd9Sstevel@tonic-gate 267cd93090eSericheng if (!priv_ineffect(PRIV_SYS_NET_CONFIG) || 268cd93090eSericheng !priv_ineffect(PRIV_NET_RAWACCESS)) { 269cd93090eSericheng (void) fprintf(stderr, 270cd93090eSericheng gettext("%s: insufficient privileges\n"), progname); 271cd93090eSericheng exit(1); 272cd93090eSericheng } 273cd93090eSericheng 2747c478bd9Sstevel@tonic-gate for (i = 0; i < sizeof (cmds) / sizeof (cmds[0]); i++) { 2757c478bd9Sstevel@tonic-gate cmdp = &cmds[i]; 2767c478bd9Sstevel@tonic-gate if (strcmp(argv[1], cmdp->c_name) == 0) { 2777c478bd9Sstevel@tonic-gate cmdp->c_fn(argc - 1, &argv[1]); 2787c478bd9Sstevel@tonic-gate exit(0); 2797c478bd9Sstevel@tonic-gate } 2807c478bd9Sstevel@tonic-gate } 2817c478bd9Sstevel@tonic-gate 2827c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("%s: unknown subcommand '%s'\n"), 2837c478bd9Sstevel@tonic-gate progname, argv[1]); 2847c478bd9Sstevel@tonic-gate usage(); 2857c478bd9Sstevel@tonic-gate 2867c478bd9Sstevel@tonic-gate return (0); 2877c478bd9Sstevel@tonic-gate } 2887c478bd9Sstevel@tonic-gate 2897c478bd9Sstevel@tonic-gate 2907c478bd9Sstevel@tonic-gate static void 2917c478bd9Sstevel@tonic-gate do_create_aggr(int argc, char *argv[]) 2927c478bd9Sstevel@tonic-gate { 2937c478bd9Sstevel@tonic-gate char option; 2947c478bd9Sstevel@tonic-gate uint16_t key; 2957c478bd9Sstevel@tonic-gate uint32_t policy = AGGR_POLICY_L4; 2967c478bd9Sstevel@tonic-gate aggr_lacp_mode_t lacp_mode = AGGR_LACP_OFF; 2977c478bd9Sstevel@tonic-gate aggr_lacp_timer_t lacp_timer = AGGR_LACP_TIMER_SHORT; 2987c478bd9Sstevel@tonic-gate laadm_port_attr_db_t port[MAXPORT]; 2997c478bd9Sstevel@tonic-gate uint_t nport = 0; 3007c478bd9Sstevel@tonic-gate uint8_t mac_addr[ETHERADDRL]; 3017c478bd9Sstevel@tonic-gate boolean_t mac_addr_fixed = B_FALSE; 3027c478bd9Sstevel@tonic-gate boolean_t P_arg = B_FALSE; 3037c478bd9Sstevel@tonic-gate boolean_t l_arg = B_FALSE; 3047c478bd9Sstevel@tonic-gate boolean_t t_arg = B_FALSE; 3057c478bd9Sstevel@tonic-gate boolean_t u_arg = B_FALSE; 3067c478bd9Sstevel@tonic-gate boolean_t T_arg = B_FALSE; 3077c478bd9Sstevel@tonic-gate char *altroot = NULL; 3087c478bd9Sstevel@tonic-gate char *endp = NULL; 3097c478bd9Sstevel@tonic-gate laadm_diag_t diag = 0; 3107c478bd9Sstevel@tonic-gate 3117c478bd9Sstevel@tonic-gate opterr = 0; 3127c478bd9Sstevel@tonic-gate while ((option = getopt_long(argc, argv, ":d:l:P:R:tu:T:", 3137c478bd9Sstevel@tonic-gate longopts, NULL)) != -1) { 3147c478bd9Sstevel@tonic-gate switch (option) { 3157c478bd9Sstevel@tonic-gate case 'd': 3167c478bd9Sstevel@tonic-gate if (nport >= MAXPORT) { 3177c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 3187c478bd9Sstevel@tonic-gate gettext("%s: too many <dev> arguments\n"), 3197c478bd9Sstevel@tonic-gate progname); 3207c478bd9Sstevel@tonic-gate exit(1); 3217c478bd9Sstevel@tonic-gate } 3227c478bd9Sstevel@tonic-gate 3237c478bd9Sstevel@tonic-gate if (strlcpy(port[nport].lp_devname, optarg, 3247c478bd9Sstevel@tonic-gate MAXNAMELEN) >= MAXNAMELEN) { 3257c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 3267c478bd9Sstevel@tonic-gate gettext("%s: device name too long\n"), 3277c478bd9Sstevel@tonic-gate progname); 3287c478bd9Sstevel@tonic-gate exit(1); 3297c478bd9Sstevel@tonic-gate } 3307c478bd9Sstevel@tonic-gate 3317c478bd9Sstevel@tonic-gate nport++; 3327c478bd9Sstevel@tonic-gate break; 3337c478bd9Sstevel@tonic-gate case 'P': 3347c478bd9Sstevel@tonic-gate if (P_arg) { 3357c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 3367c478bd9Sstevel@tonic-gate "%s: the option -P cannot be specified " 3377c478bd9Sstevel@tonic-gate "more than once\n"), progname); 3387c478bd9Sstevel@tonic-gate usage(); 3397c478bd9Sstevel@tonic-gate } 3407c478bd9Sstevel@tonic-gate 3417c478bd9Sstevel@tonic-gate P_arg = B_TRUE; 3427c478bd9Sstevel@tonic-gate 3437c478bd9Sstevel@tonic-gate if (!laadm_str_to_policy(optarg, &policy)) { 3447c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 3457c478bd9Sstevel@tonic-gate gettext("%s: invalid policy '%s'\n"), 3467c478bd9Sstevel@tonic-gate progname, optarg); 3477c478bd9Sstevel@tonic-gate exit(1); 3487c478bd9Sstevel@tonic-gate } 3497c478bd9Sstevel@tonic-gate break; 3507c478bd9Sstevel@tonic-gate case 'u': 3517c478bd9Sstevel@tonic-gate if (u_arg) { 3527c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 3537c478bd9Sstevel@tonic-gate "%s: the option -u cannot be specified " 3547c478bd9Sstevel@tonic-gate "more than once\n"), progname); 3557c478bd9Sstevel@tonic-gate usage(); 3567c478bd9Sstevel@tonic-gate } 3577c478bd9Sstevel@tonic-gate 3587c478bd9Sstevel@tonic-gate u_arg = B_TRUE; 3597c478bd9Sstevel@tonic-gate 3607c478bd9Sstevel@tonic-gate if (!laadm_str_to_mac_addr(optarg, &mac_addr_fixed, 3617c478bd9Sstevel@tonic-gate mac_addr)) { 3627c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 3637c478bd9Sstevel@tonic-gate gettext("%s: invalid MAC address '%s'\n"), 3647c478bd9Sstevel@tonic-gate progname, optarg); 3657c478bd9Sstevel@tonic-gate exit(1); 3667c478bd9Sstevel@tonic-gate } 3677c478bd9Sstevel@tonic-gate 3687c478bd9Sstevel@tonic-gate break; 3697c478bd9Sstevel@tonic-gate case 'l': 3707c478bd9Sstevel@tonic-gate if (l_arg) { 3717c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 3727c478bd9Sstevel@tonic-gate "%s: the option -l cannot be specified " 3737c478bd9Sstevel@tonic-gate "more than once\n"), progname); 3747c478bd9Sstevel@tonic-gate usage(); 3757c478bd9Sstevel@tonic-gate } 3767c478bd9Sstevel@tonic-gate 3777c478bd9Sstevel@tonic-gate l_arg = B_TRUE; 3787c478bd9Sstevel@tonic-gate 3797c478bd9Sstevel@tonic-gate if (!laadm_str_to_lacp_mode(optarg, &lacp_mode)) { 3807c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 3817c478bd9Sstevel@tonic-gate gettext("%s: invalid LACP mode '%s'\n"), 3827c478bd9Sstevel@tonic-gate progname, optarg); 3837c478bd9Sstevel@tonic-gate exit(1); 3847c478bd9Sstevel@tonic-gate } 3857c478bd9Sstevel@tonic-gate 3867c478bd9Sstevel@tonic-gate break; 3877c478bd9Sstevel@tonic-gate case 'T': 3887c478bd9Sstevel@tonic-gate if (T_arg) { 3897c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 3907c478bd9Sstevel@tonic-gate "%s: the option -T cannot be specified " 3917c478bd9Sstevel@tonic-gate "more than once\n"), progname); 3927c478bd9Sstevel@tonic-gate usage(); 3937c478bd9Sstevel@tonic-gate } 3947c478bd9Sstevel@tonic-gate 3957c478bd9Sstevel@tonic-gate T_arg = B_TRUE; 3967c478bd9Sstevel@tonic-gate 3977c478bd9Sstevel@tonic-gate if (!laadm_str_to_lacp_timer(optarg, &lacp_timer)) { 3987c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 3997c478bd9Sstevel@tonic-gate gettext("%s: invalid LACP timer value" 4007c478bd9Sstevel@tonic-gate " '%s'\n"), 4017c478bd9Sstevel@tonic-gate progname, optarg); 4027c478bd9Sstevel@tonic-gate exit(1); 4037c478bd9Sstevel@tonic-gate } 4047c478bd9Sstevel@tonic-gate 4057c478bd9Sstevel@tonic-gate break; 4067c478bd9Sstevel@tonic-gate case 't': 4077c478bd9Sstevel@tonic-gate t_arg = B_TRUE; 4087c478bd9Sstevel@tonic-gate break; 4097c478bd9Sstevel@tonic-gate case 'R': 4107c478bd9Sstevel@tonic-gate altroot = optarg; 4117c478bd9Sstevel@tonic-gate break; 4127c478bd9Sstevel@tonic-gate case ':': 4137c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 4147c478bd9Sstevel@tonic-gate gettext("%s: option requires a value '-%c'\n"), 4157c478bd9Sstevel@tonic-gate progname, optopt); 4167c478bd9Sstevel@tonic-gate exit(1); 4177c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 4187c478bd9Sstevel@tonic-gate case '?': 4197c478bd9Sstevel@tonic-gate default: 4207c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 4217c478bd9Sstevel@tonic-gate gettext("%s: unrecognized option '-%c'\n"), 4227c478bd9Sstevel@tonic-gate progname, optopt); 4237c478bd9Sstevel@tonic-gate exit(1); 4247c478bd9Sstevel@tonic-gate } 4257c478bd9Sstevel@tonic-gate } 4267c478bd9Sstevel@tonic-gate 4277c478bd9Sstevel@tonic-gate if (nport == 0) 4287c478bd9Sstevel@tonic-gate usage(); 4297c478bd9Sstevel@tonic-gate 4307c478bd9Sstevel@tonic-gate /* get key value (required last argument) */ 4317c478bd9Sstevel@tonic-gate if (optind != (argc-1)) 4327c478bd9Sstevel@tonic-gate usage(); 4337c478bd9Sstevel@tonic-gate 4347c478bd9Sstevel@tonic-gate errno = 0; 4357c478bd9Sstevel@tonic-gate key = (int)strtol(argv[optind], &endp, 10); 4367c478bd9Sstevel@tonic-gate if (errno != 0 || key < 1 || *endp != '\0') { 4377c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 4387c478bd9Sstevel@tonic-gate gettext("%s: illegal key value '%d'\n"), 4397c478bd9Sstevel@tonic-gate progname, key); 4407c478bd9Sstevel@tonic-gate exit(1); 4417c478bd9Sstevel@tonic-gate } 4427c478bd9Sstevel@tonic-gate 4437c478bd9Sstevel@tonic-gate if (laadm_create(key, nport, port, policy, mac_addr_fixed, 4447c478bd9Sstevel@tonic-gate mac_addr, lacp_mode, lacp_timer, t_arg, altroot, &diag) < 0) { 4457c478bd9Sstevel@tonic-gate PRINT_ERR_DIAG("%s: create operation failed: %s", diag, 4467c478bd9Sstevel@tonic-gate laadm_diag); 4477c478bd9Sstevel@tonic-gate exit(1); 4487c478bd9Sstevel@tonic-gate } 4497c478bd9Sstevel@tonic-gate } 4507c478bd9Sstevel@tonic-gate 4517c478bd9Sstevel@tonic-gate static void 4527c478bd9Sstevel@tonic-gate do_delete_aggr(int argc, char *argv[]) 4537c478bd9Sstevel@tonic-gate { 4547c478bd9Sstevel@tonic-gate uint16_t key; 4557c478bd9Sstevel@tonic-gate char option; 4567c478bd9Sstevel@tonic-gate boolean_t t_arg = B_FALSE; 4577c478bd9Sstevel@tonic-gate char *altroot = NULL; 4587c478bd9Sstevel@tonic-gate char *endp = NULL; 4597c478bd9Sstevel@tonic-gate laadm_diag_t diag = 0; 4607c478bd9Sstevel@tonic-gate 4617c478bd9Sstevel@tonic-gate opterr = 0; 4627c478bd9Sstevel@tonic-gate while ((option = getopt_long(argc, argv, ":R:t", longopts, 4637c478bd9Sstevel@tonic-gate NULL)) != -1) { 4647c478bd9Sstevel@tonic-gate switch (option) { 4657c478bd9Sstevel@tonic-gate 4667c478bd9Sstevel@tonic-gate case 't': 4677c478bd9Sstevel@tonic-gate t_arg = B_TRUE; 4687c478bd9Sstevel@tonic-gate break; 4697c478bd9Sstevel@tonic-gate case 'R': 4707c478bd9Sstevel@tonic-gate altroot = optarg; 4717c478bd9Sstevel@tonic-gate break; 4727c478bd9Sstevel@tonic-gate case ':': 4737c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 4747c478bd9Sstevel@tonic-gate gettext("%s: option requires a value '-%c'\n"), 4757c478bd9Sstevel@tonic-gate progname, optopt); 4767c478bd9Sstevel@tonic-gate exit(1); 4777c478bd9Sstevel@tonic-gate break; 4787c478bd9Sstevel@tonic-gate case '?': 4797c478bd9Sstevel@tonic-gate default: 4807c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 4817c478bd9Sstevel@tonic-gate gettext("%s: unrecognized option '-%c'\n"), 4827c478bd9Sstevel@tonic-gate progname, optopt); 4837c478bd9Sstevel@tonic-gate exit(1); 4847c478bd9Sstevel@tonic-gate break; 4857c478bd9Sstevel@tonic-gate } 4867c478bd9Sstevel@tonic-gate } 4877c478bd9Sstevel@tonic-gate 4887c478bd9Sstevel@tonic-gate /* get key value (required last argument) */ 4897c478bd9Sstevel@tonic-gate if (optind != (argc-1)) 4907c478bd9Sstevel@tonic-gate usage(); 4917c478bd9Sstevel@tonic-gate 4927c478bd9Sstevel@tonic-gate errno = 0; 4937c478bd9Sstevel@tonic-gate key = (int)strtol(argv[optind], &endp, 10); 4947c478bd9Sstevel@tonic-gate if (errno != 0 || key < 1 || *endp != '\0') { 4957c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 4967c478bd9Sstevel@tonic-gate gettext("%s: illegal key value '%d'\n"), 4977c478bd9Sstevel@tonic-gate progname, key); 4987c478bd9Sstevel@tonic-gate exit(1); 4997c478bd9Sstevel@tonic-gate } 5007c478bd9Sstevel@tonic-gate 5017c478bd9Sstevel@tonic-gate if (laadm_delete(key, t_arg, altroot, &diag) < 0) { 5027c478bd9Sstevel@tonic-gate PRINT_ERR_DIAG("%s: delete operation failed: %s", diag, 5037c478bd9Sstevel@tonic-gate laadm_diag); 5047c478bd9Sstevel@tonic-gate exit(1); 5057c478bd9Sstevel@tonic-gate } 5067c478bd9Sstevel@tonic-gate } 5077c478bd9Sstevel@tonic-gate 5087c478bd9Sstevel@tonic-gate static void 5097c478bd9Sstevel@tonic-gate do_add_aggr(int argc, char *argv[]) 5107c478bd9Sstevel@tonic-gate { 5117c478bd9Sstevel@tonic-gate char option; 5127c478bd9Sstevel@tonic-gate uint16_t key; 5137c478bd9Sstevel@tonic-gate laadm_port_attr_db_t port[MAXPORT]; 5147c478bd9Sstevel@tonic-gate uint_t nport = 0; 5157c478bd9Sstevel@tonic-gate boolean_t t_arg = B_FALSE; 5167c478bd9Sstevel@tonic-gate char *altroot = NULL; 5177c478bd9Sstevel@tonic-gate char *endp = NULL; 5187c478bd9Sstevel@tonic-gate laadm_diag_t diag = 0; 5197c478bd9Sstevel@tonic-gate 5207c478bd9Sstevel@tonic-gate opterr = 0; 5217c478bd9Sstevel@tonic-gate while ((option = getopt_long(argc, argv, ":d:R:t", longopts, 5227c478bd9Sstevel@tonic-gate NULL)) != -1) { 5237c478bd9Sstevel@tonic-gate switch (option) { 5247c478bd9Sstevel@tonic-gate case 'd': 5257c478bd9Sstevel@tonic-gate if (nport >= MAXPORT) { 5267c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 5277c478bd9Sstevel@tonic-gate gettext("%s: too many <dev> arguments\n"), 5287c478bd9Sstevel@tonic-gate progname); 5297c478bd9Sstevel@tonic-gate exit(1); 5307c478bd9Sstevel@tonic-gate } 5317c478bd9Sstevel@tonic-gate 5327c478bd9Sstevel@tonic-gate if (strlcpy(port[nport].lp_devname, optarg, 5337c478bd9Sstevel@tonic-gate MAXNAMELEN) >= MAXNAMELEN) { 5347c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 5357c478bd9Sstevel@tonic-gate gettext("%s: device name too long\n"), 5367c478bd9Sstevel@tonic-gate progname); 5377c478bd9Sstevel@tonic-gate exit(1); 5387c478bd9Sstevel@tonic-gate } 5397c478bd9Sstevel@tonic-gate nport++; 5407c478bd9Sstevel@tonic-gate break; 5417c478bd9Sstevel@tonic-gate case 't': 5427c478bd9Sstevel@tonic-gate t_arg = B_TRUE; 5437c478bd9Sstevel@tonic-gate break; 5447c478bd9Sstevel@tonic-gate case 'R': 5457c478bd9Sstevel@tonic-gate altroot = optarg; 5467c478bd9Sstevel@tonic-gate break; 5477c478bd9Sstevel@tonic-gate case ':': 5487c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 5497c478bd9Sstevel@tonic-gate gettext("%s: option requires a value '-%c'\n"), 5507c478bd9Sstevel@tonic-gate progname, optopt); 5517c478bd9Sstevel@tonic-gate exit(1); 5527c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 5537c478bd9Sstevel@tonic-gate case '?': 5547c478bd9Sstevel@tonic-gate default: 5557c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 5567c478bd9Sstevel@tonic-gate gettext("%s: unrecognized option '-%c'\n"), 5577c478bd9Sstevel@tonic-gate progname, optopt); 5587c478bd9Sstevel@tonic-gate exit(1); 5597c478bd9Sstevel@tonic-gate } 5607c478bd9Sstevel@tonic-gate } 5617c478bd9Sstevel@tonic-gate 5627c478bd9Sstevel@tonic-gate if (nport == 0) 5637c478bd9Sstevel@tonic-gate usage(); 5647c478bd9Sstevel@tonic-gate 5657c478bd9Sstevel@tonic-gate /* get key value (required last argument) */ 5667c478bd9Sstevel@tonic-gate if (optind != (argc-1)) 5677c478bd9Sstevel@tonic-gate usage(); 5687c478bd9Sstevel@tonic-gate 5697c478bd9Sstevel@tonic-gate errno = 0; 5707c478bd9Sstevel@tonic-gate key = (int)strtol(argv[optind], &endp, 10); 5717c478bd9Sstevel@tonic-gate if (errno != 0 || key < 1 || *endp != '\0') { 5727c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 5737c478bd9Sstevel@tonic-gate gettext("%s: illegal key value '%d'\n"), 5747c478bd9Sstevel@tonic-gate progname, key); 5757c478bd9Sstevel@tonic-gate exit(1); 5767c478bd9Sstevel@tonic-gate } 5777c478bd9Sstevel@tonic-gate 5787c478bd9Sstevel@tonic-gate if (laadm_add(key, nport, port, t_arg, altroot, &diag) < 0) { 579219a2a31Shl157128 /* 580219a2a31Shl157128 * checking ENOTSUP is a temporary workaround 581219a2a31Shl157128 * and should be removed once 6399681 is fixed. 582219a2a31Shl157128 */ 583219a2a31Shl157128 if (errno == ENOTSUP) { 584219a2a31Shl157128 (void) fprintf(stderr, 585219a2a31Shl157128 gettext("%s: add operation failed: %s\n"), 586219a2a31Shl157128 progname, 587219a2a31Shl157128 gettext("device capabilities don't match")); 588219a2a31Shl157128 exit(ENOTSUP); 589219a2a31Shl157128 } 5907c478bd9Sstevel@tonic-gate PRINT_ERR_DIAG("%s: add operation failed: %s", diag, 5917c478bd9Sstevel@tonic-gate laadm_diag); 5927c478bd9Sstevel@tonic-gate exit(1); 5937c478bd9Sstevel@tonic-gate } 5947c478bd9Sstevel@tonic-gate } 5957c478bd9Sstevel@tonic-gate 5967c478bd9Sstevel@tonic-gate static void 5977c478bd9Sstevel@tonic-gate do_remove_aggr(int argc, char *argv[]) 5987c478bd9Sstevel@tonic-gate { 5997c478bd9Sstevel@tonic-gate char option; 6007c478bd9Sstevel@tonic-gate uint16_t key; 6017c478bd9Sstevel@tonic-gate laadm_port_attr_db_t port[MAXPORT]; 6027c478bd9Sstevel@tonic-gate uint_t nport = 0; 6037c478bd9Sstevel@tonic-gate boolean_t t_arg = B_FALSE; 6047c478bd9Sstevel@tonic-gate char *altroot = NULL; 6057c478bd9Sstevel@tonic-gate char *endp = NULL; 6067c478bd9Sstevel@tonic-gate laadm_diag_t diag = 0; 6077c478bd9Sstevel@tonic-gate 6087c478bd9Sstevel@tonic-gate opterr = 0; 6097c478bd9Sstevel@tonic-gate while ((option = getopt_long(argc, argv, ":d:R:t", 6107c478bd9Sstevel@tonic-gate longopts, NULL)) != -1) { 6117c478bd9Sstevel@tonic-gate switch (option) { 6127c478bd9Sstevel@tonic-gate case 'd': 6137c478bd9Sstevel@tonic-gate if (nport >= MAXPORT) { 6147c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 6157c478bd9Sstevel@tonic-gate gettext("%s: too many <dev> arguments\n"), 6167c478bd9Sstevel@tonic-gate progname); 6177c478bd9Sstevel@tonic-gate exit(1); 6187c478bd9Sstevel@tonic-gate } 6197c478bd9Sstevel@tonic-gate 6207c478bd9Sstevel@tonic-gate if (strlcpy(port[nport].lp_devname, optarg, 6217c478bd9Sstevel@tonic-gate MAXNAMELEN) >= MAXNAMELEN) { 6227c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 6237c478bd9Sstevel@tonic-gate gettext("%s: device name too long\n"), 6247c478bd9Sstevel@tonic-gate progname); 6257c478bd9Sstevel@tonic-gate exit(1); 6267c478bd9Sstevel@tonic-gate } 6277c478bd9Sstevel@tonic-gate nport++; 6287c478bd9Sstevel@tonic-gate break; 6297c478bd9Sstevel@tonic-gate case 't': 6307c478bd9Sstevel@tonic-gate t_arg = B_TRUE; 6317c478bd9Sstevel@tonic-gate break; 6327c478bd9Sstevel@tonic-gate case 'R': 6337c478bd9Sstevel@tonic-gate altroot = optarg; 6347c478bd9Sstevel@tonic-gate break; 6357c478bd9Sstevel@tonic-gate case ':': 6367c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 6377c478bd9Sstevel@tonic-gate gettext("%s: option requires a value '-%c'\n"), 6387c478bd9Sstevel@tonic-gate progname, optopt); 6397c478bd9Sstevel@tonic-gate exit(1); 6407c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 6417c478bd9Sstevel@tonic-gate case '?': 6427c478bd9Sstevel@tonic-gate default: 6437c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 6447c478bd9Sstevel@tonic-gate gettext("%s: unrecognized option '-%c'\n"), 6457c478bd9Sstevel@tonic-gate progname, optopt); 6467c478bd9Sstevel@tonic-gate exit(1); 6477c478bd9Sstevel@tonic-gate } 6487c478bd9Sstevel@tonic-gate } 6497c478bd9Sstevel@tonic-gate 6507c478bd9Sstevel@tonic-gate if (nport == 0) 6517c478bd9Sstevel@tonic-gate usage(); 6527c478bd9Sstevel@tonic-gate 6537c478bd9Sstevel@tonic-gate /* get key value (required last argument) */ 6547c478bd9Sstevel@tonic-gate if (optind != (argc-1)) 6557c478bd9Sstevel@tonic-gate usage(); 6567c478bd9Sstevel@tonic-gate 6577c478bd9Sstevel@tonic-gate errno = 0; 6587c478bd9Sstevel@tonic-gate key = (int)strtol(argv[optind], &endp, 10); 6597c478bd9Sstevel@tonic-gate if (errno != 0 || key < 1 || *endp != '\0') { 6607c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 6617c478bd9Sstevel@tonic-gate gettext("%s: illegal key value '%d'\n"), 6627c478bd9Sstevel@tonic-gate progname, key); 6637c478bd9Sstevel@tonic-gate exit(1); 6647c478bd9Sstevel@tonic-gate } 6657c478bd9Sstevel@tonic-gate 6667c478bd9Sstevel@tonic-gate if (laadm_remove(key, nport, port, t_arg, altroot, &diag) < 0) { 6677c478bd9Sstevel@tonic-gate PRINT_ERR_DIAG("%s: remove operation failed: %s", diag, 6687c478bd9Sstevel@tonic-gate laadm_diag); 6697c478bd9Sstevel@tonic-gate exit(1); 6707c478bd9Sstevel@tonic-gate } 6717c478bd9Sstevel@tonic-gate } 6727c478bd9Sstevel@tonic-gate 6737c478bd9Sstevel@tonic-gate static void 6747c478bd9Sstevel@tonic-gate do_modify_aggr(int argc, char *argv[]) 6757c478bd9Sstevel@tonic-gate { 6767c478bd9Sstevel@tonic-gate char option; 6777c478bd9Sstevel@tonic-gate uint16_t key; 6787c478bd9Sstevel@tonic-gate uint32_t policy = AGGR_POLICY_L4; 6797c478bd9Sstevel@tonic-gate aggr_lacp_mode_t lacp_mode = AGGR_LACP_OFF; 6807c478bd9Sstevel@tonic-gate aggr_lacp_timer_t lacp_timer = AGGR_LACP_TIMER_SHORT; 6817c478bd9Sstevel@tonic-gate uint8_t mac_addr[ETHERADDRL]; 6827c478bd9Sstevel@tonic-gate boolean_t mac_addr_fixed = B_FALSE; 6837c478bd9Sstevel@tonic-gate uint8_t modify_mask = 0; 6847c478bd9Sstevel@tonic-gate boolean_t t_arg = B_FALSE; 6857c478bd9Sstevel@tonic-gate char *altroot = NULL; 6867c478bd9Sstevel@tonic-gate char *endp = NULL; 6877c478bd9Sstevel@tonic-gate laadm_diag_t diag = 0; 6887c478bd9Sstevel@tonic-gate 6897c478bd9Sstevel@tonic-gate opterr = 0; 6907c478bd9Sstevel@tonic-gate while ((option = getopt_long(argc, argv, ":l:P:R:tu:T:", longopts, 6917c478bd9Sstevel@tonic-gate NULL)) != -1) { 6927c478bd9Sstevel@tonic-gate switch (option) { 6937c478bd9Sstevel@tonic-gate case 'P': 6947c478bd9Sstevel@tonic-gate if (modify_mask & LAADM_MODIFY_POLICY) { 6957c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 6967c478bd9Sstevel@tonic-gate "%s: the option -P cannot be specified " 6977c478bd9Sstevel@tonic-gate "more than once\n"), progname); 6987c478bd9Sstevel@tonic-gate usage(); 6997c478bd9Sstevel@tonic-gate } 7007c478bd9Sstevel@tonic-gate 7017c478bd9Sstevel@tonic-gate modify_mask |= LAADM_MODIFY_POLICY; 7027c478bd9Sstevel@tonic-gate 7037c478bd9Sstevel@tonic-gate if (!laadm_str_to_policy(optarg, &policy)) { 7047c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 7057c478bd9Sstevel@tonic-gate gettext("%s: invalid policy '%s'\n"), 7067c478bd9Sstevel@tonic-gate progname, optarg); 7077c478bd9Sstevel@tonic-gate exit(1); 7087c478bd9Sstevel@tonic-gate } 7097c478bd9Sstevel@tonic-gate break; 7107c478bd9Sstevel@tonic-gate case 'u': 7117c478bd9Sstevel@tonic-gate if (modify_mask & LAADM_MODIFY_MAC) { 7127c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 7137c478bd9Sstevel@tonic-gate "%s: the option -u cannot be specified " 7147c478bd9Sstevel@tonic-gate "more than once\n"), progname); 7157c478bd9Sstevel@tonic-gate usage(); 7167c478bd9Sstevel@tonic-gate } 7177c478bd9Sstevel@tonic-gate 7187c478bd9Sstevel@tonic-gate modify_mask |= LAADM_MODIFY_MAC; 7197c478bd9Sstevel@tonic-gate 7207c478bd9Sstevel@tonic-gate if (!laadm_str_to_mac_addr(optarg, &mac_addr_fixed, 7217c478bd9Sstevel@tonic-gate mac_addr)) { 7227c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 7237c478bd9Sstevel@tonic-gate gettext("%s: invalid MAC address '%s'\n"), 7247c478bd9Sstevel@tonic-gate progname, optarg); 7257c478bd9Sstevel@tonic-gate exit(1); 7267c478bd9Sstevel@tonic-gate } 7277c478bd9Sstevel@tonic-gate 7287c478bd9Sstevel@tonic-gate break; 7297c478bd9Sstevel@tonic-gate case 'l': 7307c478bd9Sstevel@tonic-gate if (modify_mask & LAADM_MODIFY_LACP_MODE) { 7317c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 7327c478bd9Sstevel@tonic-gate "%s: the option -l cannot be specified " 7337c478bd9Sstevel@tonic-gate "more than once\n"), progname); 7347c478bd9Sstevel@tonic-gate usage(); 7357c478bd9Sstevel@tonic-gate } 7367c478bd9Sstevel@tonic-gate 7377c478bd9Sstevel@tonic-gate modify_mask |= LAADM_MODIFY_LACP_MODE; 7387c478bd9Sstevel@tonic-gate 7397c478bd9Sstevel@tonic-gate if (!laadm_str_to_lacp_mode(optarg, &lacp_mode)) { 7407c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 7417c478bd9Sstevel@tonic-gate gettext("%s: invalid LACP mode '%s'\n"), 7427c478bd9Sstevel@tonic-gate progname, optarg); 7437c478bd9Sstevel@tonic-gate exit(1); 7447c478bd9Sstevel@tonic-gate } 7457c478bd9Sstevel@tonic-gate 7467c478bd9Sstevel@tonic-gate break; 7477c478bd9Sstevel@tonic-gate case 'T': 7487c478bd9Sstevel@tonic-gate if (modify_mask & LAADM_MODIFY_LACP_TIMER) { 7497c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 7507c478bd9Sstevel@tonic-gate "%s: the option -T cannot be specified " 7517c478bd9Sstevel@tonic-gate "more than once\n"), progname); 7527c478bd9Sstevel@tonic-gate usage(); 7537c478bd9Sstevel@tonic-gate } 7547c478bd9Sstevel@tonic-gate 7557c478bd9Sstevel@tonic-gate modify_mask |= LAADM_MODIFY_LACP_TIMER; 7567c478bd9Sstevel@tonic-gate 7577c478bd9Sstevel@tonic-gate if (!laadm_str_to_lacp_timer(optarg, &lacp_timer)) { 7587c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 7597c478bd9Sstevel@tonic-gate gettext("%s: invalid LACP timer value" 7607c478bd9Sstevel@tonic-gate " '%s'\n"), 7617c478bd9Sstevel@tonic-gate progname, optarg); 7627c478bd9Sstevel@tonic-gate exit(1); 7637c478bd9Sstevel@tonic-gate } 7647c478bd9Sstevel@tonic-gate 7657c478bd9Sstevel@tonic-gate break; 7667c478bd9Sstevel@tonic-gate case 't': 7677c478bd9Sstevel@tonic-gate t_arg = B_TRUE; 7687c478bd9Sstevel@tonic-gate break; 7697c478bd9Sstevel@tonic-gate case 'R': 7707c478bd9Sstevel@tonic-gate altroot = optarg; 7717c478bd9Sstevel@tonic-gate break; 7727c478bd9Sstevel@tonic-gate case ':': 7737c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 7747c478bd9Sstevel@tonic-gate gettext("%s: option requires a value '-%c'\n"), 7757c478bd9Sstevel@tonic-gate progname, optopt); 7767c478bd9Sstevel@tonic-gate exit(1); 7777c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 7787c478bd9Sstevel@tonic-gate case '?': 7797c478bd9Sstevel@tonic-gate default: 7807c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 7817c478bd9Sstevel@tonic-gate gettext("%s: unrecognized option '-%c'\n"), 7827c478bd9Sstevel@tonic-gate progname, optopt); 7837c478bd9Sstevel@tonic-gate exit(1); 7847c478bd9Sstevel@tonic-gate } 7857c478bd9Sstevel@tonic-gate } 7867c478bd9Sstevel@tonic-gate 7877c478bd9Sstevel@tonic-gate if (modify_mask == 0) { 7887c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("%s: at least one of the " 7897c478bd9Sstevel@tonic-gate "-PulT options must be specified\n"), progname); 7907c478bd9Sstevel@tonic-gate usage(); 7917c478bd9Sstevel@tonic-gate } 7927c478bd9Sstevel@tonic-gate 7937c478bd9Sstevel@tonic-gate /* get key value (required last argument) */ 7947c478bd9Sstevel@tonic-gate if (optind != (argc-1)) 7957c478bd9Sstevel@tonic-gate usage(); 7967c478bd9Sstevel@tonic-gate 7977c478bd9Sstevel@tonic-gate errno = 0; 7987c478bd9Sstevel@tonic-gate key = (int)strtol(argv[optind], &endp, 10); 7997c478bd9Sstevel@tonic-gate if (errno != 0 || key < 1 || *endp != '\0') { 8007c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 8017c478bd9Sstevel@tonic-gate gettext("%s: illegal key value '%d'\n"), 8027c478bd9Sstevel@tonic-gate progname, key); 8037c478bd9Sstevel@tonic-gate exit(1); 8047c478bd9Sstevel@tonic-gate } 8057c478bd9Sstevel@tonic-gate 8067c478bd9Sstevel@tonic-gate 8077c478bd9Sstevel@tonic-gate if (laadm_modify(key, modify_mask, policy, mac_addr_fixed, mac_addr, 8087c478bd9Sstevel@tonic-gate lacp_mode, lacp_timer, t_arg, altroot, &diag) < 0) { 8097c478bd9Sstevel@tonic-gate PRINT_ERR_DIAG("%s: modify operation failed: %s", diag, 8107c478bd9Sstevel@tonic-gate laadm_diag); 8117c478bd9Sstevel@tonic-gate exit(1); 8127c478bd9Sstevel@tonic-gate } 8137c478bd9Sstevel@tonic-gate } 8147c478bd9Sstevel@tonic-gate 8157c478bd9Sstevel@tonic-gate static void 8167c478bd9Sstevel@tonic-gate do_up_aggr(int argc, char *argv[]) 8177c478bd9Sstevel@tonic-gate { 8187c478bd9Sstevel@tonic-gate uint16_t key = 0; 8197c478bd9Sstevel@tonic-gate char *endp = NULL; 8207c478bd9Sstevel@tonic-gate laadm_diag_t diag = 0; 8217c478bd9Sstevel@tonic-gate 8227c478bd9Sstevel@tonic-gate /* get aggregation key (optional last argument) */ 8237c478bd9Sstevel@tonic-gate if (argc == 2) { 8247c478bd9Sstevel@tonic-gate errno = 0; 8257c478bd9Sstevel@tonic-gate key = (int)strtol(argv[1], &endp, 10); 8267c478bd9Sstevel@tonic-gate if (errno != 0 || key < 1 || *endp != '\0') { 8277c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 8287c478bd9Sstevel@tonic-gate gettext("%s: illegal key value '%d'\n"), 8297c478bd9Sstevel@tonic-gate progname, key); 8307c478bd9Sstevel@tonic-gate exit(1); 8317c478bd9Sstevel@tonic-gate } 8327c478bd9Sstevel@tonic-gate } else if (argc > 2) { 8337c478bd9Sstevel@tonic-gate usage(); 8347c478bd9Sstevel@tonic-gate } 8357c478bd9Sstevel@tonic-gate 8367c478bd9Sstevel@tonic-gate if (laadm_up(key, NULL, &diag) < 0) { 8377c478bd9Sstevel@tonic-gate if (key != 0) { 8387c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 8397c478bd9Sstevel@tonic-gate gettext("%s: could not bring up aggregation" 8407c478bd9Sstevel@tonic-gate " '%u' : %s"), progname, key, strerror(errno)); 8417c478bd9Sstevel@tonic-gate if (diag != 0) 8427c478bd9Sstevel@tonic-gate (void) fprintf(stderr, " (%s)", 8437c478bd9Sstevel@tonic-gate laadm_diag(diag)); 8447c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "\n"); 8457c478bd9Sstevel@tonic-gate } else { 8467c478bd9Sstevel@tonic-gate PRINT_ERR_DIAG( 8477c478bd9Sstevel@tonic-gate "%s: could not bring aggregations up: %s", 8487c478bd9Sstevel@tonic-gate diag, laadm_diag); 8497c478bd9Sstevel@tonic-gate } 8507c478bd9Sstevel@tonic-gate exit(1); 8517c478bd9Sstevel@tonic-gate } 8527c478bd9Sstevel@tonic-gate } 8537c478bd9Sstevel@tonic-gate 8547c478bd9Sstevel@tonic-gate static void 8557c478bd9Sstevel@tonic-gate do_down_aggr(int argc, char *argv[]) 8567c478bd9Sstevel@tonic-gate { 8577c478bd9Sstevel@tonic-gate uint16_t key = 0; 8587c478bd9Sstevel@tonic-gate char *endp = NULL; 8597c478bd9Sstevel@tonic-gate 8607c478bd9Sstevel@tonic-gate /* get aggregation key (optional last argument) */ 8617c478bd9Sstevel@tonic-gate if (argc == 2) { 8627c478bd9Sstevel@tonic-gate errno = 0; 8637c478bd9Sstevel@tonic-gate key = (int)strtol(argv[1], &endp, 10); 8647c478bd9Sstevel@tonic-gate if (errno != 0 || key < 1 || *endp != '\0') { 8657c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 8667c478bd9Sstevel@tonic-gate gettext("%s: illegal key value '%d'\n"), 8677c478bd9Sstevel@tonic-gate progname, key); 8687c478bd9Sstevel@tonic-gate exit(1); 8697c478bd9Sstevel@tonic-gate } 8707c478bd9Sstevel@tonic-gate } else if (argc > 2) { 8717c478bd9Sstevel@tonic-gate usage(); 8727c478bd9Sstevel@tonic-gate } 8737c478bd9Sstevel@tonic-gate 8747c478bd9Sstevel@tonic-gate if (laadm_down(key) < 0) { 8757c478bd9Sstevel@tonic-gate if (key != 0) { 8767c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 8777c478bd9Sstevel@tonic-gate gettext("%s: could not bring aggregation" 8787c478bd9Sstevel@tonic-gate " down '%u' : %s"), 8797c478bd9Sstevel@tonic-gate progname, key, strerror(errno)); 8807c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "\n"); 8817c478bd9Sstevel@tonic-gate } else { 8827c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 8837c478bd9Sstevel@tonic-gate gettext("%s: could not bring aggregations" 8847c478bd9Sstevel@tonic-gate " down: %s"), progname, strerror(errno)); 8857c478bd9Sstevel@tonic-gate } 8867c478bd9Sstevel@tonic-gate exit(1); 8877c478bd9Sstevel@tonic-gate } 8887c478bd9Sstevel@tonic-gate } 8897c478bd9Sstevel@tonic-gate 8907c478bd9Sstevel@tonic-gate #define TYPE_WIDTH 10 891210db224Sericheng 892210db224Sericheng static void 893210db224Sericheng print_link_parseable(const char *name, dladm_attr_t *dap, boolean_t legacy) 894210db224Sericheng { 895210db224Sericheng char type[TYPE_WIDTH]; 896210db224Sericheng 897210db224Sericheng if (!legacy) { 898ba2e4443Sseb char drv[LIFNAMSIZ]; 899ba2e4443Sseb int instance; 900ba2e4443Sseb 901210db224Sericheng if (dap->da_vid != 0) { 902210db224Sericheng (void) snprintf(type, TYPE_WIDTH, "vlan %u", 903210db224Sericheng dap->da_vid); 904210db224Sericheng } else { 905210db224Sericheng (void) snprintf(type, TYPE_WIDTH, "non-vlan"); 906210db224Sericheng } 907ba2e4443Sseb if (dlpi_if_parse(dap->da_dev, drv, &instance) != 0) 908ba2e4443Sseb return; 909ba2e4443Sseb if (strncmp(drv, AGGR_DRV, sizeof (AGGR_DRV)) == 0) { 910210db224Sericheng (void) printf("%s type=%s mtu=%d key=%u\n", 911ba2e4443Sseb name, type, dap->da_max_sdu, instance); 912210db224Sericheng } else { 913210db224Sericheng (void) printf("%s type=%s mtu=%d device=%s\n", 914210db224Sericheng name, type, dap->da_max_sdu, dap->da_dev); 915210db224Sericheng } 916210db224Sericheng } else { 917210db224Sericheng (void) printf("%s type=legacy mtu=%d device=%s\n", 918210db224Sericheng name, dap->da_max_sdu, name); 919210db224Sericheng } 920210db224Sericheng } 921210db224Sericheng 922210db224Sericheng static void 923210db224Sericheng print_link(const char *name, dladm_attr_t *dap, boolean_t legacy) 924210db224Sericheng { 925210db224Sericheng char type[TYPE_WIDTH]; 926210db224Sericheng 927210db224Sericheng if (!legacy) { 928ba2e4443Sseb char drv[LIFNAMSIZ]; 929ba2e4443Sseb int instance; 930ba2e4443Sseb 931210db224Sericheng if (dap->da_vid != 0) { 932210db224Sericheng (void) snprintf(type, TYPE_WIDTH, gettext("vlan %u"), 933210db224Sericheng dap->da_vid); 934210db224Sericheng } else { 935210db224Sericheng (void) snprintf(type, TYPE_WIDTH, gettext("non-vlan")); 936210db224Sericheng } 937ba2e4443Sseb if (dlpi_if_parse(dap->da_dev, drv, &instance) != 0) 938ba2e4443Sseb return; 939ba2e4443Sseb if (strncmp(drv, AGGR_DRV, sizeof (AGGR_DRV)) == 0) { 940210db224Sericheng (void) printf(gettext("%-9s\ttype: %s\tmtu: %d" 941210db224Sericheng "\taggregation: key %u\n"), name, type, 942ba2e4443Sseb dap->da_max_sdu, instance); 943210db224Sericheng } else { 944210db224Sericheng (void) printf(gettext("%-9s\ttype: %s\tmtu: " 945210db224Sericheng "%d\tdevice: %s\n"), name, type, dap->da_max_sdu, 946210db224Sericheng dap->da_dev); 947210db224Sericheng } 948210db224Sericheng } else { 949210db224Sericheng (void) printf(gettext("%-9s\ttype: legacy\tmtu: " 950210db224Sericheng "%d\tdevice: %s\n"), name, dap->da_max_sdu, name); 951210db224Sericheng } 952210db224Sericheng } 953210db224Sericheng 954210db224Sericheng static int 955210db224Sericheng get_if_info(const char *name, dladm_attr_t *dlattrp, boolean_t *legacy) 956210db224Sericheng { 957210db224Sericheng int err; 958210db224Sericheng 959210db224Sericheng if ((err = dladm_info(name, dlattrp)) == 0) { 960210db224Sericheng *legacy = B_FALSE; 961210db224Sericheng } else if (err < 0 && errno == ENODEV) { 962210db224Sericheng int fd; 963210db224Sericheng dlpi_if_attr_t dia; 964210db224Sericheng dl_info_ack_t dlia; 965210db224Sericheng 966210db224Sericheng /* 967210db224Sericheng * A return value of ENODEV means that the specified 968210db224Sericheng * device is not gldv3. 969210db224Sericheng */ 970210db224Sericheng if ((fd = dlpi_if_open(name, &dia, B_FALSE)) != -1 && 971210db224Sericheng dlpi_info(fd, -1, &dlia, NULL, NULL, NULL, NULL, 972210db224Sericheng NULL, NULL) != -1) { 973210db224Sericheng (void) dlpi_close(fd); 974210db224Sericheng 975210db224Sericheng *legacy = B_TRUE; 976210db224Sericheng bzero(dlattrp, sizeof (*dlattrp)); 977210db224Sericheng dlattrp->da_max_sdu = (uint_t)dlia.dl_max_sdu; 978210db224Sericheng } else { 979210db224Sericheng errno = ENOENT; 980210db224Sericheng return (-1); 981210db224Sericheng } 982210db224Sericheng } else { 983210db224Sericheng /* 984210db224Sericheng * If the return value is not ENODEV, this means that 985210db224Sericheng * user is either passing in a bogus interface name 986210db224Sericheng * or a vlan interface name that doesn't exist yet. 987210db224Sericheng */ 988210db224Sericheng errno = ENOENT; 989210db224Sericheng return (-1); 990210db224Sericheng } 991210db224Sericheng return (0); 992210db224Sericheng } 9937c478bd9Sstevel@tonic-gate 9947c478bd9Sstevel@tonic-gate /* ARGSUSED */ 9957c478bd9Sstevel@tonic-gate static void 9967c478bd9Sstevel@tonic-gate show_link(void *arg, const char *name) 9977c478bd9Sstevel@tonic-gate { 9987c478bd9Sstevel@tonic-gate dladm_attr_t dlattr; 999210db224Sericheng boolean_t legacy = B_TRUE; 10007c478bd9Sstevel@tonic-gate show_link_state_t *state = (show_link_state_t *)arg; 10017c478bd9Sstevel@tonic-gate 1002210db224Sericheng if (get_if_info(name, &dlattr, &legacy) < 0) { 1003210db224Sericheng (void) fprintf(stderr, gettext("%s: invalid device '%s'\n"), 10047c478bd9Sstevel@tonic-gate progname, name); 10057c478bd9Sstevel@tonic-gate exit(1); 10067c478bd9Sstevel@tonic-gate } 10077c478bd9Sstevel@tonic-gate 1008210db224Sericheng if (state->ls_parseable) { 1009210db224Sericheng print_link_parseable(name, &dlattr, legacy); 10107c478bd9Sstevel@tonic-gate } else { 1011210db224Sericheng print_link(name, &dlattr, legacy); 10127c478bd9Sstevel@tonic-gate } 10137c478bd9Sstevel@tonic-gate } 10147c478bd9Sstevel@tonic-gate 10157c478bd9Sstevel@tonic-gate static void 10167c478bd9Sstevel@tonic-gate show_link_stats(void *arg, const char *name) 10177c478bd9Sstevel@tonic-gate { 10187c478bd9Sstevel@tonic-gate show_link_state_t *state = (show_link_state_t *)arg; 10197c478bd9Sstevel@tonic-gate pktsum_t stats, diff_stats; 10207c478bd9Sstevel@tonic-gate 10217c478bd9Sstevel@tonic-gate if (state->ls_firstonly) { 10227c478bd9Sstevel@tonic-gate if (state->ls_donefirst) 10237c478bd9Sstevel@tonic-gate return; 10247c478bd9Sstevel@tonic-gate state->ls_donefirst = B_TRUE; 10257c478bd9Sstevel@tonic-gate } else { 10267c478bd9Sstevel@tonic-gate bzero(&state->ls_prevstats, sizeof (state->ls_prevstats)); 10277c478bd9Sstevel@tonic-gate } 10287c478bd9Sstevel@tonic-gate 10297c478bd9Sstevel@tonic-gate get_link_stats(name, &stats); 10307c478bd9Sstevel@tonic-gate stats_diff(&diff_stats, &stats, &state->ls_prevstats); 10317c478bd9Sstevel@tonic-gate 10327c478bd9Sstevel@tonic-gate (void) printf("%s", name); 10337c478bd9Sstevel@tonic-gate (void) printf("\t\t%-10llu", diff_stats.ipackets); 10347c478bd9Sstevel@tonic-gate (void) printf("%-12llu", diff_stats.rbytes); 10357c478bd9Sstevel@tonic-gate (void) printf("%-8u", diff_stats.ierrors); 10367c478bd9Sstevel@tonic-gate (void) printf("%-10llu", diff_stats.opackets); 10377c478bd9Sstevel@tonic-gate (void) printf("%-12llu", diff_stats.obytes); 10387c478bd9Sstevel@tonic-gate (void) printf("%-8u\n", diff_stats.oerrors); 10397c478bd9Sstevel@tonic-gate 10407c478bd9Sstevel@tonic-gate state->ls_prevstats = stats; 10417c478bd9Sstevel@tonic-gate } 10427c478bd9Sstevel@tonic-gate 10437c478bd9Sstevel@tonic-gate static void 10447c478bd9Sstevel@tonic-gate dump_grp(laadm_grp_attr_sys_t *grp, boolean_t parseable) 10457c478bd9Sstevel@tonic-gate { 10467c478bd9Sstevel@tonic-gate char policy_str[LAADM_POLICY_STR_LEN]; 10477c478bd9Sstevel@tonic-gate char addr_str[ETHERADDRL * 3]; 10487c478bd9Sstevel@tonic-gate 10497c478bd9Sstevel@tonic-gate if (!parseable) { 10507c478bd9Sstevel@tonic-gate (void) printf(gettext("key: %d (0x%04x)"), 10517c478bd9Sstevel@tonic-gate grp->lg_key, grp->lg_key); 10527c478bd9Sstevel@tonic-gate 10537c478bd9Sstevel@tonic-gate (void) printf(gettext("\tpolicy: %s"), 10547c478bd9Sstevel@tonic-gate laadm_policy_to_str(grp->lg_policy, policy_str)); 10557c478bd9Sstevel@tonic-gate 10567c478bd9Sstevel@tonic-gate (void) printf(gettext("\taddress: %s (%s)\n"), 10577c478bd9Sstevel@tonic-gate laadm_mac_addr_to_str(grp->lg_mac, addr_str), 10587c478bd9Sstevel@tonic-gate (grp->lg_mac_fixed) ? gettext("fixed") : gettext("auto")); 10597c478bd9Sstevel@tonic-gate } else { 10607c478bd9Sstevel@tonic-gate (void) printf("aggr key=%d", grp->lg_key); 10617c478bd9Sstevel@tonic-gate 10627c478bd9Sstevel@tonic-gate (void) printf(" policy=%s", 10637c478bd9Sstevel@tonic-gate laadm_policy_to_str(grp->lg_policy, policy_str)); 10647c478bd9Sstevel@tonic-gate 10657c478bd9Sstevel@tonic-gate (void) printf(" address=%s", 10667c478bd9Sstevel@tonic-gate laadm_mac_addr_to_str(grp->lg_mac, addr_str)); 10677c478bd9Sstevel@tonic-gate 10687c478bd9Sstevel@tonic-gate (void) printf(" address-type=%s\n", 10697c478bd9Sstevel@tonic-gate (grp->lg_mac_fixed) ? "fixed" : "auto"); 10707c478bd9Sstevel@tonic-gate } 10717c478bd9Sstevel@tonic-gate } 10727c478bd9Sstevel@tonic-gate 10737c478bd9Sstevel@tonic-gate static void 10747c478bd9Sstevel@tonic-gate dump_grp_lacp(laadm_grp_attr_sys_t *grp, boolean_t parseable) 10757c478bd9Sstevel@tonic-gate { 10767c478bd9Sstevel@tonic-gate const char *lacp_mode_str = laadm_lacp_mode_to_str(grp->lg_lacp_mode); 10777c478bd9Sstevel@tonic-gate const char *lacp_timer_str = 10787c478bd9Sstevel@tonic-gate laadm_lacp_timer_to_str(grp->lg_lacp_timer); 10797c478bd9Sstevel@tonic-gate 10807c478bd9Sstevel@tonic-gate if (!parseable) { 10817c478bd9Sstevel@tonic-gate (void) printf(gettext("\t\tLACP mode: %s"), lacp_mode_str); 10827c478bd9Sstevel@tonic-gate (void) printf(gettext("\tLACP timer: %s\n"), lacp_timer_str); 10837c478bd9Sstevel@tonic-gate } else { 10847c478bd9Sstevel@tonic-gate (void) printf(" lacp-mode=%s", lacp_mode_str); 10857c478bd9Sstevel@tonic-gate (void) printf(" lacp-timer=%s\n", lacp_timer_str); 10867c478bd9Sstevel@tonic-gate } 10877c478bd9Sstevel@tonic-gate } 10887c478bd9Sstevel@tonic-gate 10897c478bd9Sstevel@tonic-gate static void 10907c478bd9Sstevel@tonic-gate dump_grp_stats(laadm_grp_attr_sys_t *grp) 10917c478bd9Sstevel@tonic-gate { 10927c478bd9Sstevel@tonic-gate (void) printf("key: %d", grp->lg_key); 10937c478bd9Sstevel@tonic-gate (void) printf("\tipackets rbytes opackets obytes "); 10947c478bd9Sstevel@tonic-gate (void) printf("%%ipkts %%opkts\n"); 10957c478bd9Sstevel@tonic-gate } 10967c478bd9Sstevel@tonic-gate 10977c478bd9Sstevel@tonic-gate static void 10987c478bd9Sstevel@tonic-gate dump_ports_lacp_head(void) 10997c478bd9Sstevel@tonic-gate { 11007c478bd9Sstevel@tonic-gate (void) printf(DUMP_LACP_FORMAT, gettext("device"), gettext("activity"), 11017c478bd9Sstevel@tonic-gate gettext("timeout"), gettext("aggregatable"), gettext("sync"), 11027c478bd9Sstevel@tonic-gate gettext("coll"), gettext("dist"), gettext("defaulted"), 11037c478bd9Sstevel@tonic-gate gettext("expired")); 11047c478bd9Sstevel@tonic-gate } 11057c478bd9Sstevel@tonic-gate 11067c478bd9Sstevel@tonic-gate static void 11077c478bd9Sstevel@tonic-gate dump_ports_head(void) 11087c478bd9Sstevel@tonic-gate { 11097c478bd9Sstevel@tonic-gate (void) printf(gettext(" device\taddress\t\t speed\t\tduplex\tlink\t" 11107c478bd9Sstevel@tonic-gate "state\n")); 11117c478bd9Sstevel@tonic-gate } 11127c478bd9Sstevel@tonic-gate 11137c478bd9Sstevel@tonic-gate static char * 11147c478bd9Sstevel@tonic-gate port_state_to_str(aggr_port_state_t state_num) 11157c478bd9Sstevel@tonic-gate { 11167c478bd9Sstevel@tonic-gate int i; 11177c478bd9Sstevel@tonic-gate port_state_t *state; 11187c478bd9Sstevel@tonic-gate 11197c478bd9Sstevel@tonic-gate for (i = 0; i < NPORTSTATES; i++) { 11207c478bd9Sstevel@tonic-gate state = &port_states[i]; 11217c478bd9Sstevel@tonic-gate if (state->state_num == state_num) 11227c478bd9Sstevel@tonic-gate return (state->state_name); 11237c478bd9Sstevel@tonic-gate } 11247c478bd9Sstevel@tonic-gate 11257c478bd9Sstevel@tonic-gate return ("unknown"); 11267c478bd9Sstevel@tonic-gate } 11277c478bd9Sstevel@tonic-gate 11287c478bd9Sstevel@tonic-gate static void 11297c478bd9Sstevel@tonic-gate dump_port(laadm_port_attr_sys_t *port, boolean_t parseable) 11307c478bd9Sstevel@tonic-gate { 11317c478bd9Sstevel@tonic-gate char *dev = port->lp_devname; 11327c478bd9Sstevel@tonic-gate char buf[ETHERADDRL * 3]; 11337c478bd9Sstevel@tonic-gate 11347c478bd9Sstevel@tonic-gate if (!parseable) { 11357c478bd9Sstevel@tonic-gate (void) printf(" %-9s\t%s", dev, laadm_mac_addr_to_str( 11367c478bd9Sstevel@tonic-gate port->lp_mac, buf)); 1137ba2e4443Sseb (void) printf("\t %-5u Mbps", (int)(mac_ifspeed(dev) / 11387c478bd9Sstevel@tonic-gate 1000000ull)); 1139ba2e4443Sseb (void) printf("\t%s", mac_link_duplex(dev)); 1140ba2e4443Sseb (void) printf("\t%s", mac_link_state(dev)); 11417c478bd9Sstevel@tonic-gate (void) printf("\t%s\n", port_state_to_str(port->lp_state)); 11427c478bd9Sstevel@tonic-gate 11437c478bd9Sstevel@tonic-gate } else { 11447c478bd9Sstevel@tonic-gate (void) printf(" device=%s address=%s", dev, 11457c478bd9Sstevel@tonic-gate laadm_mac_addr_to_str(port->lp_mac, buf)); 1146ba2e4443Sseb (void) printf(" speed=%u", (int)(mac_ifspeed(dev) / 11477c478bd9Sstevel@tonic-gate 1000000ull)); 1148ba2e4443Sseb (void) printf(" duplex=%s", mac_link_duplex(dev)); 1149ba2e4443Sseb (void) printf(" link=%s", mac_link_state(dev)); 11507c478bd9Sstevel@tonic-gate (void) printf(" port=%s", port_state_to_str(port->lp_state)); 11517c478bd9Sstevel@tonic-gate } 11527c478bd9Sstevel@tonic-gate } 11537c478bd9Sstevel@tonic-gate 11547c478bd9Sstevel@tonic-gate static void 11557c478bd9Sstevel@tonic-gate dump_port_lacp(laadm_port_attr_sys_t *port) 11567c478bd9Sstevel@tonic-gate { 11577c478bd9Sstevel@tonic-gate aggr_lacp_state_t *state = &port->lp_lacp_state; 11587c478bd9Sstevel@tonic-gate 11597c478bd9Sstevel@tonic-gate (void) printf(DUMP_LACP_FORMAT, 11607c478bd9Sstevel@tonic-gate port->lp_devname, state->bit.activity ? "active" : "passive", 11617c478bd9Sstevel@tonic-gate state->bit.timeout ? "short" : "long", 11627c478bd9Sstevel@tonic-gate state->bit.aggregation ? "yes" : "no", 11637c478bd9Sstevel@tonic-gate state->bit.sync ? "yes" : "no", 11647c478bd9Sstevel@tonic-gate state->bit.collecting ? "yes" : "no", 11657c478bd9Sstevel@tonic-gate state->bit.distributing ? "yes" : "no", 11667c478bd9Sstevel@tonic-gate state->bit.defaulted ? "yes" : "no", 11677c478bd9Sstevel@tonic-gate state->bit.expired ? "yes" : "no"); 11687c478bd9Sstevel@tonic-gate } 11697c478bd9Sstevel@tonic-gate 11707c478bd9Sstevel@tonic-gate static void 11717c478bd9Sstevel@tonic-gate dump_port_stat(int index, show_grp_state_t *state, pktsum_t *port_stats, 11727c478bd9Sstevel@tonic-gate pktsum_t *tot_stats) 11737c478bd9Sstevel@tonic-gate { 11747c478bd9Sstevel@tonic-gate pktsum_t diff_stats; 11757c478bd9Sstevel@tonic-gate pktsum_t *old_stats = &state->gs_prevstats[index]; 11767c478bd9Sstevel@tonic-gate 11777c478bd9Sstevel@tonic-gate stats_diff(&diff_stats, port_stats, old_stats); 11787c478bd9Sstevel@tonic-gate 11797c478bd9Sstevel@tonic-gate (void) printf("\t%-10llu", diff_stats.ipackets); 11807c478bd9Sstevel@tonic-gate (void) printf("%-12llu", diff_stats.rbytes); 11817c478bd9Sstevel@tonic-gate (void) printf("%-10llu", diff_stats.opackets); 11827c478bd9Sstevel@tonic-gate (void) printf("%-12llu", diff_stats.obytes); 11837c478bd9Sstevel@tonic-gate 11847c478bd9Sstevel@tonic-gate if (tot_stats->ipackets == 0) 11857c478bd9Sstevel@tonic-gate (void) printf("\t-"); 11867c478bd9Sstevel@tonic-gate else 11877c478bd9Sstevel@tonic-gate (void) printf("\t%-6.1f", (double)diff_stats.ipackets/ 11887c478bd9Sstevel@tonic-gate (double)tot_stats->ipackets * 100); 11897c478bd9Sstevel@tonic-gate 11907c478bd9Sstevel@tonic-gate if (tot_stats->opackets == 0) 11917c478bd9Sstevel@tonic-gate (void) printf("\t-"); 11927c478bd9Sstevel@tonic-gate else 11937c478bd9Sstevel@tonic-gate (void) printf("\t%-6.1f", (double)diff_stats.opackets/ 11947c478bd9Sstevel@tonic-gate (double)tot_stats->opackets * 100); 11957c478bd9Sstevel@tonic-gate 11967c478bd9Sstevel@tonic-gate (void) printf("\n"); 11977c478bd9Sstevel@tonic-gate 11987c478bd9Sstevel@tonic-gate *old_stats = *port_stats; 11997c478bd9Sstevel@tonic-gate } 12007c478bd9Sstevel@tonic-gate 12017c478bd9Sstevel@tonic-gate static int 12027c478bd9Sstevel@tonic-gate show_key(void *arg, laadm_grp_attr_sys_t *grp) 12037c478bd9Sstevel@tonic-gate { 12047c478bd9Sstevel@tonic-gate show_grp_state_t *state = (show_grp_state_t *)arg; 12057c478bd9Sstevel@tonic-gate int i; 12067c478bd9Sstevel@tonic-gate pktsum_t pktsumtot, port_stat; 12077c478bd9Sstevel@tonic-gate 12087c478bd9Sstevel@tonic-gate if (state->gs_key != 0 && state->gs_key != grp->lg_key) 12097c478bd9Sstevel@tonic-gate return (0); 12107c478bd9Sstevel@tonic-gate if (state->gs_firstonly) { 12117c478bd9Sstevel@tonic-gate if (state->gs_found) 12127c478bd9Sstevel@tonic-gate return (0); 12137c478bd9Sstevel@tonic-gate } else { 12147c478bd9Sstevel@tonic-gate bzero(&state->gs_prevstats, sizeof (state->gs_prevstats)); 12157c478bd9Sstevel@tonic-gate } 12167c478bd9Sstevel@tonic-gate 12177c478bd9Sstevel@tonic-gate state->gs_found = B_TRUE; 12187c478bd9Sstevel@tonic-gate 12197c478bd9Sstevel@tonic-gate if (state->gs_stats) { 12207c478bd9Sstevel@tonic-gate /* show statistics */ 12217c478bd9Sstevel@tonic-gate dump_grp_stats(grp); 12227c478bd9Sstevel@tonic-gate 12237c478bd9Sstevel@tonic-gate /* sum the ports statistics */ 12247c478bd9Sstevel@tonic-gate bzero(&pktsumtot, sizeof (pktsumtot)); 12257c478bd9Sstevel@tonic-gate for (i = 0; i < grp->lg_nports; i++) { 1226ba2e4443Sseb get_mac_stats(grp->lg_ports[i].lp_devname, &port_stat); 12277c478bd9Sstevel@tonic-gate stats_total(&pktsumtot, &port_stat, 12287c478bd9Sstevel@tonic-gate &state->gs_prevstats[i]); 12297c478bd9Sstevel@tonic-gate } 12307c478bd9Sstevel@tonic-gate 12317c478bd9Sstevel@tonic-gate (void) printf(" Total"); 12327c478bd9Sstevel@tonic-gate (void) printf("\t%-10llu", pktsumtot.ipackets); 12337c478bd9Sstevel@tonic-gate (void) printf("%-12llu", pktsumtot.rbytes); 12347c478bd9Sstevel@tonic-gate (void) printf("%-10llu", pktsumtot.opackets); 12357c478bd9Sstevel@tonic-gate (void) printf("%-12llu\n", pktsumtot.obytes); 12367c478bd9Sstevel@tonic-gate 12377c478bd9Sstevel@tonic-gate for (i = 0; i < grp->lg_nports; i++) { 1238ba2e4443Sseb get_mac_stats(grp->lg_ports[i].lp_devname, &port_stat); 12397c478bd9Sstevel@tonic-gate (void) printf(" %s", grp->lg_ports[i].lp_devname); 12407c478bd9Sstevel@tonic-gate dump_port_stat(i, state, &port_stat, &pktsumtot); 12417c478bd9Sstevel@tonic-gate } 12427c478bd9Sstevel@tonic-gate } else if (state->gs_lacp) { 12437c478bd9Sstevel@tonic-gate /* show LACP info */ 12447c478bd9Sstevel@tonic-gate dump_grp(grp, state->gs_parseable); 12457c478bd9Sstevel@tonic-gate dump_grp_lacp(grp, state->gs_parseable); 12467c478bd9Sstevel@tonic-gate dump_ports_lacp_head(); 12477c478bd9Sstevel@tonic-gate for (i = 0; i < grp->lg_nports; i++) 12487c478bd9Sstevel@tonic-gate dump_port_lacp(&grp->lg_ports[i]); 12497c478bd9Sstevel@tonic-gate } else { 12507c478bd9Sstevel@tonic-gate dump_grp(grp, state->gs_parseable); 12517c478bd9Sstevel@tonic-gate if (!state->gs_parseable) 12527c478bd9Sstevel@tonic-gate dump_ports_head(); 12537c478bd9Sstevel@tonic-gate for (i = 0; i < grp->lg_nports; i++) { 12547c478bd9Sstevel@tonic-gate if (state->gs_parseable) 12557c478bd9Sstevel@tonic-gate (void) printf("dev key=%d", grp->lg_key); 12567c478bd9Sstevel@tonic-gate dump_port(&grp->lg_ports[i], state->gs_parseable); 12577c478bd9Sstevel@tonic-gate if (state->gs_parseable) 12587c478bd9Sstevel@tonic-gate (void) printf("\n"); 12597c478bd9Sstevel@tonic-gate } 12607c478bd9Sstevel@tonic-gate } 12617c478bd9Sstevel@tonic-gate 12627c478bd9Sstevel@tonic-gate return (0); 12637c478bd9Sstevel@tonic-gate } 12647c478bd9Sstevel@tonic-gate 12657c478bd9Sstevel@tonic-gate static int 12667c478bd9Sstevel@tonic-gate kstat_value(kstat_t *ksp, const char *name, uint8_t type, void *buf) 12677c478bd9Sstevel@tonic-gate { 12687c478bd9Sstevel@tonic-gate kstat_named_t *knp; 12697c478bd9Sstevel@tonic-gate 12707c478bd9Sstevel@tonic-gate if ((knp = kstat_data_lookup(ksp, (char *)name)) == NULL) 12717c478bd9Sstevel@tonic-gate return (-1); 12727c478bd9Sstevel@tonic-gate 12737c478bd9Sstevel@tonic-gate if (knp->data_type != type) 12747c478bd9Sstevel@tonic-gate return (-1); 12757c478bd9Sstevel@tonic-gate 12767c478bd9Sstevel@tonic-gate switch (type) { 12777c478bd9Sstevel@tonic-gate case KSTAT_DATA_UINT64: 12787c478bd9Sstevel@tonic-gate *(uint64_t *)buf = knp->value.ui64; 12797c478bd9Sstevel@tonic-gate break; 12807c478bd9Sstevel@tonic-gate case KSTAT_DATA_UINT32: 12817c478bd9Sstevel@tonic-gate *(uint32_t *)buf = knp->value.ui32; 12827c478bd9Sstevel@tonic-gate break; 12837c478bd9Sstevel@tonic-gate default: 12847c478bd9Sstevel@tonic-gate return (-1); 12857c478bd9Sstevel@tonic-gate } 12867c478bd9Sstevel@tonic-gate 12877c478bd9Sstevel@tonic-gate return (0); 12887c478bd9Sstevel@tonic-gate } 12897c478bd9Sstevel@tonic-gate 12907c478bd9Sstevel@tonic-gate static void 1291210db224Sericheng show_dev(void *arg, const char *dev) 12927c478bd9Sstevel@tonic-gate { 12937c478bd9Sstevel@tonic-gate show_mac_state_t *state = (show_mac_state_t *)arg; 12947c478bd9Sstevel@tonic-gate 12957c478bd9Sstevel@tonic-gate (void) printf("%s", dev); 12967c478bd9Sstevel@tonic-gate 12977c478bd9Sstevel@tonic-gate if (!state->ms_parseable) { 12987c478bd9Sstevel@tonic-gate (void) printf(gettext("\t\tlink: %s"), 1299ba2e4443Sseb mac_link_state(dev)); 13007c478bd9Sstevel@tonic-gate (void) printf(gettext("\tspeed: %-5u Mbps"), 1301ba2e4443Sseb (unsigned int)(mac_ifspeed(dev) / 1000000ull)); 13027c478bd9Sstevel@tonic-gate (void) printf(gettext("\tduplex: %s\n"), 1303ba2e4443Sseb mac_link_duplex(dev)); 13047c478bd9Sstevel@tonic-gate } else { 1305ba2e4443Sseb (void) printf(" link=%s", mac_link_state(dev)); 13067c478bd9Sstevel@tonic-gate (void) printf(" speed=%u", 1307ba2e4443Sseb (unsigned int)(mac_ifspeed(dev) / 1000000ull)); 1308ba2e4443Sseb (void) printf(" duplex=%s\n", mac_link_duplex(dev)); 13097c478bd9Sstevel@tonic-gate } 13107c478bd9Sstevel@tonic-gate } 13117c478bd9Sstevel@tonic-gate 13127c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 13137c478bd9Sstevel@tonic-gate static void 1314210db224Sericheng show_dev_stats(void *arg, const char *dev) 13157c478bd9Sstevel@tonic-gate { 13167c478bd9Sstevel@tonic-gate show_mac_state_t *state = (show_mac_state_t *)arg; 13177c478bd9Sstevel@tonic-gate pktsum_t stats, diff_stats; 13187c478bd9Sstevel@tonic-gate 13197c478bd9Sstevel@tonic-gate if (state->ms_firstonly) { 13207c478bd9Sstevel@tonic-gate if (state->ms_donefirst) 13217c478bd9Sstevel@tonic-gate return; 13227c478bd9Sstevel@tonic-gate state->ms_donefirst = B_TRUE; 13237c478bd9Sstevel@tonic-gate } else { 13247c478bd9Sstevel@tonic-gate bzero(&state->ms_prevstats, sizeof (state->ms_prevstats)); 13257c478bd9Sstevel@tonic-gate } 13267c478bd9Sstevel@tonic-gate 1327ba2e4443Sseb get_mac_stats(dev, &stats); 13287c478bd9Sstevel@tonic-gate stats_diff(&diff_stats, &stats, &state->ms_prevstats); 13297c478bd9Sstevel@tonic-gate 13307c478bd9Sstevel@tonic-gate (void) printf("%s", dev); 13317c478bd9Sstevel@tonic-gate (void) printf("\t\t%-10llu", diff_stats.ipackets); 13327c478bd9Sstevel@tonic-gate (void) printf("%-12llu", diff_stats.rbytes); 13337c478bd9Sstevel@tonic-gate (void) printf("%-8u", diff_stats.ierrors); 13347c478bd9Sstevel@tonic-gate (void) printf("%-10llu", diff_stats.opackets); 13357c478bd9Sstevel@tonic-gate (void) printf("%-12llu", diff_stats.obytes); 13367c478bd9Sstevel@tonic-gate (void) printf("%-8u\n", diff_stats.oerrors); 13377c478bd9Sstevel@tonic-gate 13387c478bd9Sstevel@tonic-gate state->ms_prevstats = stats; 13397c478bd9Sstevel@tonic-gate } 13407c478bd9Sstevel@tonic-gate 13417c478bd9Sstevel@tonic-gate static void 13427c478bd9Sstevel@tonic-gate do_show_link(int argc, char *argv[]) 13437c478bd9Sstevel@tonic-gate { 13447c478bd9Sstevel@tonic-gate char *name = NULL; 13457c478bd9Sstevel@tonic-gate int option; 13467c478bd9Sstevel@tonic-gate boolean_t s_arg = B_FALSE; 13477c478bd9Sstevel@tonic-gate boolean_t i_arg = B_FALSE; 13487c478bd9Sstevel@tonic-gate uint32_t interval = 0; 13497c478bd9Sstevel@tonic-gate show_link_state_t state; 13507c478bd9Sstevel@tonic-gate char *endp = NULL; 13517c478bd9Sstevel@tonic-gate 13527c478bd9Sstevel@tonic-gate state.ls_stats = B_FALSE; 13537c478bd9Sstevel@tonic-gate state.ls_parseable = B_FALSE; 13547c478bd9Sstevel@tonic-gate 13557c478bd9Sstevel@tonic-gate opterr = 0; 13567c478bd9Sstevel@tonic-gate while ((option = getopt_long(argc, argv, ":psi:", 13577c478bd9Sstevel@tonic-gate longopts, NULL)) != -1) { 13587c478bd9Sstevel@tonic-gate switch (option) { 13597c478bd9Sstevel@tonic-gate case 'p': 13607c478bd9Sstevel@tonic-gate state.ls_parseable = B_TRUE; 13617c478bd9Sstevel@tonic-gate break; 13627c478bd9Sstevel@tonic-gate case 's': 13637c478bd9Sstevel@tonic-gate if (s_arg) { 13647c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 13657c478bd9Sstevel@tonic-gate "%s: the option -s cannot be specified " 13667c478bd9Sstevel@tonic-gate "more than once\n"), progname); 13677c478bd9Sstevel@tonic-gate usage(); 13687c478bd9Sstevel@tonic-gate } 13697c478bd9Sstevel@tonic-gate 13707c478bd9Sstevel@tonic-gate s_arg = B_TRUE; 13717c478bd9Sstevel@tonic-gate break; 13727c478bd9Sstevel@tonic-gate case 'i': 13737c478bd9Sstevel@tonic-gate if (i_arg) { 13747c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 13757c478bd9Sstevel@tonic-gate "%s: the option -i cannot be specified " 13767c478bd9Sstevel@tonic-gate "more than once\n"), progname); 13777c478bd9Sstevel@tonic-gate usage(); 13787c478bd9Sstevel@tonic-gate } 13797c478bd9Sstevel@tonic-gate 13807c478bd9Sstevel@tonic-gate i_arg = B_TRUE; 13817c478bd9Sstevel@tonic-gate 13827c478bd9Sstevel@tonic-gate errno = 0; 13837c478bd9Sstevel@tonic-gate interval = (int)strtol(optarg, &endp, 10); 13847c478bd9Sstevel@tonic-gate if (errno != 0 || interval == 0 || *endp != '\0') { 13857c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 13867c478bd9Sstevel@tonic-gate gettext("%s: invalid interval value" 13877c478bd9Sstevel@tonic-gate " '%d'\n"), 13887c478bd9Sstevel@tonic-gate progname, interval); 13897c478bd9Sstevel@tonic-gate exit(1); 13907c478bd9Sstevel@tonic-gate } 13917c478bd9Sstevel@tonic-gate break; 13927c478bd9Sstevel@tonic-gate case ':': 13937c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 13947c478bd9Sstevel@tonic-gate gettext("%s: option requires a value '-%c'\n"), 13957c478bd9Sstevel@tonic-gate progname, optopt); 13967c478bd9Sstevel@tonic-gate exit(1); 13977c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 13987c478bd9Sstevel@tonic-gate case '?': 13997c478bd9Sstevel@tonic-gate default: 14007c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 14017c478bd9Sstevel@tonic-gate gettext("%s: unrecognized option '-%c'\n"), 14027c478bd9Sstevel@tonic-gate progname, optopt); 14037c478bd9Sstevel@tonic-gate exit(1); 14047c478bd9Sstevel@tonic-gate } 14057c478bd9Sstevel@tonic-gate } 14067c478bd9Sstevel@tonic-gate 14077c478bd9Sstevel@tonic-gate if (i_arg && !s_arg) { 14087c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("%s: the option -i " 14097c478bd9Sstevel@tonic-gate "can be used only with -s\n"), progname); 14107c478bd9Sstevel@tonic-gate usage(); 14117c478bd9Sstevel@tonic-gate } 14127c478bd9Sstevel@tonic-gate 14137c478bd9Sstevel@tonic-gate 14147c478bd9Sstevel@tonic-gate /* get link name (optional last argument) */ 14157c478bd9Sstevel@tonic-gate if (optind == (argc-1)) 14167c478bd9Sstevel@tonic-gate name = argv[optind]; 14177c478bd9Sstevel@tonic-gate else if (optind != argc) 14187c478bd9Sstevel@tonic-gate usage(); 14197c478bd9Sstevel@tonic-gate 14207c478bd9Sstevel@tonic-gate if (s_arg) { 14217c478bd9Sstevel@tonic-gate link_stats(name, interval); 14227c478bd9Sstevel@tonic-gate return; 14237c478bd9Sstevel@tonic-gate } 14247c478bd9Sstevel@tonic-gate 1425210db224Sericheng if (name == NULL) { 14267c478bd9Sstevel@tonic-gate (void) dladm_walk(show_link, &state); 1427210db224Sericheng } else { 14287c478bd9Sstevel@tonic-gate show_link(&state, name); 14297c478bd9Sstevel@tonic-gate } 1430210db224Sericheng } 14317c478bd9Sstevel@tonic-gate 14327c478bd9Sstevel@tonic-gate static void 14337c478bd9Sstevel@tonic-gate do_show_aggr(int argc, char *argv[]) 14347c478bd9Sstevel@tonic-gate { 14357c478bd9Sstevel@tonic-gate int option; 14367c478bd9Sstevel@tonic-gate uint16_t key = 0; 14377c478bd9Sstevel@tonic-gate boolean_t L_arg = B_FALSE; 14387c478bd9Sstevel@tonic-gate boolean_t s_arg = B_FALSE; 14397c478bd9Sstevel@tonic-gate boolean_t i_arg = B_FALSE; 14407c478bd9Sstevel@tonic-gate show_grp_state_t state; 14417c478bd9Sstevel@tonic-gate uint32_t interval = 0; 14427c478bd9Sstevel@tonic-gate char *endp = NULL; 14437c478bd9Sstevel@tonic-gate 14447c478bd9Sstevel@tonic-gate state.gs_stats = B_FALSE; 14457c478bd9Sstevel@tonic-gate state.gs_lacp = B_FALSE; 14467c478bd9Sstevel@tonic-gate state.gs_parseable = B_FALSE; 14477c478bd9Sstevel@tonic-gate 14487c478bd9Sstevel@tonic-gate opterr = 0; 14497c478bd9Sstevel@tonic-gate while ((option = getopt_long(argc, argv, ":Lpsi:", 14507c478bd9Sstevel@tonic-gate longopts, NULL)) != -1) { 14517c478bd9Sstevel@tonic-gate switch (option) { 14527c478bd9Sstevel@tonic-gate case 'L': 14537c478bd9Sstevel@tonic-gate if (L_arg) { 14547c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 14557c478bd9Sstevel@tonic-gate "%s: the option -L cannot be specified " 14567c478bd9Sstevel@tonic-gate "more than once\n"), progname); 14577c478bd9Sstevel@tonic-gate usage(); 14587c478bd9Sstevel@tonic-gate } 14597c478bd9Sstevel@tonic-gate 14607c478bd9Sstevel@tonic-gate if (s_arg || i_arg) { 14617c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 14627c478bd9Sstevel@tonic-gate "%s: the option -L cannot be used with " 14637c478bd9Sstevel@tonic-gate "any of -is\n"), progname); 14647c478bd9Sstevel@tonic-gate usage(); 14657c478bd9Sstevel@tonic-gate } 14667c478bd9Sstevel@tonic-gate 14677c478bd9Sstevel@tonic-gate L_arg = B_TRUE; 14687c478bd9Sstevel@tonic-gate 14697c478bd9Sstevel@tonic-gate state.gs_lacp = B_TRUE; 14707c478bd9Sstevel@tonic-gate break; 14717c478bd9Sstevel@tonic-gate case 'p': 14727c478bd9Sstevel@tonic-gate state.gs_parseable = B_TRUE; 14737c478bd9Sstevel@tonic-gate break; 14747c478bd9Sstevel@tonic-gate case 's': 14757c478bd9Sstevel@tonic-gate if (s_arg) { 14767c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 14777c478bd9Sstevel@tonic-gate "%s: the option -s cannot be specified " 14787c478bd9Sstevel@tonic-gate "more than once\n"), progname); 14797c478bd9Sstevel@tonic-gate usage(); 14807c478bd9Sstevel@tonic-gate } 14817c478bd9Sstevel@tonic-gate 14827c478bd9Sstevel@tonic-gate if (L_arg) { 14837c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 14847c478bd9Sstevel@tonic-gate "%s: the option -L cannot be used " 14857c478bd9Sstevel@tonic-gate "with -k\n"), progname); 14867c478bd9Sstevel@tonic-gate usage(); 14877c478bd9Sstevel@tonic-gate } 14887c478bd9Sstevel@tonic-gate 14897c478bd9Sstevel@tonic-gate s_arg = B_TRUE; 14907c478bd9Sstevel@tonic-gate break; 14917c478bd9Sstevel@tonic-gate case 'i': 14927c478bd9Sstevel@tonic-gate if (i_arg) { 14937c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 14947c478bd9Sstevel@tonic-gate "%s: the option -i cannot be specified " 14957c478bd9Sstevel@tonic-gate "more than once\n"), progname); 14967c478bd9Sstevel@tonic-gate usage(); 14977c478bd9Sstevel@tonic-gate } 14987c478bd9Sstevel@tonic-gate 14997c478bd9Sstevel@tonic-gate if (L_arg) { 15007c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 15017c478bd9Sstevel@tonic-gate "%s: the option -i cannot be used " 15027c478bd9Sstevel@tonic-gate "with -L\n"), progname); 15037c478bd9Sstevel@tonic-gate usage(); 15047c478bd9Sstevel@tonic-gate } 15057c478bd9Sstevel@tonic-gate 15067c478bd9Sstevel@tonic-gate i_arg = B_TRUE; 15077c478bd9Sstevel@tonic-gate 15087c478bd9Sstevel@tonic-gate errno = 0; 15097c478bd9Sstevel@tonic-gate interval = (int)strtol(optarg, &endp, 10); 15107c478bd9Sstevel@tonic-gate if (errno != 0 || interval == 0 || *endp != '\0') { 15117c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 15127c478bd9Sstevel@tonic-gate gettext("%s: invalid interval value" 15137c478bd9Sstevel@tonic-gate " '%d'\n"), 15147c478bd9Sstevel@tonic-gate progname, interval); 15157c478bd9Sstevel@tonic-gate exit(1); 15167c478bd9Sstevel@tonic-gate } 15177c478bd9Sstevel@tonic-gate break; 15187c478bd9Sstevel@tonic-gate case ':': 15197c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 15207c478bd9Sstevel@tonic-gate gettext("%s: option requires a value '-%c'\n"), 15217c478bd9Sstevel@tonic-gate progname, optopt); 15227c478bd9Sstevel@tonic-gate exit(1); 15237c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 15247c478bd9Sstevel@tonic-gate case '?': 15257c478bd9Sstevel@tonic-gate default: 15267c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 15277c478bd9Sstevel@tonic-gate gettext("%s: unrecognized option '-%c'\n"), 15287c478bd9Sstevel@tonic-gate progname, optopt); 15297c478bd9Sstevel@tonic-gate exit(1); 15307c478bd9Sstevel@tonic-gate } 15317c478bd9Sstevel@tonic-gate } 15327c478bd9Sstevel@tonic-gate 15337c478bd9Sstevel@tonic-gate if (i_arg && !s_arg) { 15347c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("%s: the option -i " 15357c478bd9Sstevel@tonic-gate "can be used only with -s\n"), progname); 15367c478bd9Sstevel@tonic-gate usage(); 15377c478bd9Sstevel@tonic-gate } 15387c478bd9Sstevel@tonic-gate 15397c478bd9Sstevel@tonic-gate /* get aggregation key (optional last argument) */ 15407c478bd9Sstevel@tonic-gate if (optind == (argc-1)) { 15417c478bd9Sstevel@tonic-gate errno = 0; 15427c478bd9Sstevel@tonic-gate key = (int)strtol(argv[optind], &endp, 10); 15437c478bd9Sstevel@tonic-gate if (errno != 0 || key < 1 || *endp != '\0') { 15447c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 15457c478bd9Sstevel@tonic-gate gettext("%s: illegal key value '%d'\n"), 15467c478bd9Sstevel@tonic-gate progname, key); 15477c478bd9Sstevel@tonic-gate exit(1); 15487c478bd9Sstevel@tonic-gate } 15497c478bd9Sstevel@tonic-gate } else if (optind != argc) { 15507c478bd9Sstevel@tonic-gate usage(); 15517c478bd9Sstevel@tonic-gate } 15527c478bd9Sstevel@tonic-gate 15537c478bd9Sstevel@tonic-gate if (s_arg) { 15547c478bd9Sstevel@tonic-gate aggr_stats(key, interval); 15557c478bd9Sstevel@tonic-gate return; 15567c478bd9Sstevel@tonic-gate } 15577c478bd9Sstevel@tonic-gate 15587c478bd9Sstevel@tonic-gate state.gs_key = key; 15597c478bd9Sstevel@tonic-gate state.gs_found = B_FALSE; 15607c478bd9Sstevel@tonic-gate 15617c478bd9Sstevel@tonic-gate (void) laadm_walk_sys(show_key, &state); 15627c478bd9Sstevel@tonic-gate 15637c478bd9Sstevel@tonic-gate if (key != 0 && !state.gs_found) { 15647c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 15657c478bd9Sstevel@tonic-gate gettext("%s: non-existent aggregation key '%u'\n"), 15667c478bd9Sstevel@tonic-gate progname, key); 15677c478bd9Sstevel@tonic-gate exit(1); 15687c478bd9Sstevel@tonic-gate } 15697c478bd9Sstevel@tonic-gate } 15707c478bd9Sstevel@tonic-gate 15717c478bd9Sstevel@tonic-gate static void 15727c478bd9Sstevel@tonic-gate do_show_dev(int argc, char *argv[]) 15737c478bd9Sstevel@tonic-gate { 15747c478bd9Sstevel@tonic-gate int option; 15757c478bd9Sstevel@tonic-gate char *dev = NULL; 15767c478bd9Sstevel@tonic-gate boolean_t s_arg = B_FALSE; 15777c478bd9Sstevel@tonic-gate boolean_t i_arg = B_FALSE; 15787c478bd9Sstevel@tonic-gate uint32_t interval = 0; 15797c478bd9Sstevel@tonic-gate show_mac_state_t state; 15807c478bd9Sstevel@tonic-gate char *endp = NULL; 15817c478bd9Sstevel@tonic-gate 15827c478bd9Sstevel@tonic-gate state.ms_parseable = B_FALSE; 15837c478bd9Sstevel@tonic-gate 15847c478bd9Sstevel@tonic-gate opterr = 0; 15857c478bd9Sstevel@tonic-gate while ((option = getopt_long(argc, argv, ":psi:", 15867c478bd9Sstevel@tonic-gate longopts, NULL)) != -1) { 15877c478bd9Sstevel@tonic-gate switch (option) { 15887c478bd9Sstevel@tonic-gate case 'p': 15897c478bd9Sstevel@tonic-gate state.ms_parseable = B_TRUE; 15907c478bd9Sstevel@tonic-gate break; 15917c478bd9Sstevel@tonic-gate case 's': 15927c478bd9Sstevel@tonic-gate if (s_arg) { 15937c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 15947c478bd9Sstevel@tonic-gate "%s: the option -s cannot be specified " 15957c478bd9Sstevel@tonic-gate "more than once\n"), progname); 15967c478bd9Sstevel@tonic-gate usage(); 15977c478bd9Sstevel@tonic-gate } 15987c478bd9Sstevel@tonic-gate 15997c478bd9Sstevel@tonic-gate s_arg = B_TRUE; 16007c478bd9Sstevel@tonic-gate break; 16017c478bd9Sstevel@tonic-gate case 'i': 16027c478bd9Sstevel@tonic-gate if (i_arg) { 16037c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 16047c478bd9Sstevel@tonic-gate "%s: the option -i cannot be specified " 16057c478bd9Sstevel@tonic-gate "more than once\n"), progname); 16067c478bd9Sstevel@tonic-gate usage(); 16077c478bd9Sstevel@tonic-gate } 16087c478bd9Sstevel@tonic-gate 16097c478bd9Sstevel@tonic-gate i_arg = B_TRUE; 16107c478bd9Sstevel@tonic-gate 16117c478bd9Sstevel@tonic-gate errno = 0; 16127c478bd9Sstevel@tonic-gate interval = (int)strtol(optarg, &endp, 10); 16137c478bd9Sstevel@tonic-gate if (errno != 0 || interval == 0 || *endp != '\0') { 16147c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 16157c478bd9Sstevel@tonic-gate gettext("%s: invalid interval value" 16167c478bd9Sstevel@tonic-gate " '%d'\n"), 16177c478bd9Sstevel@tonic-gate progname, interval); 16187c478bd9Sstevel@tonic-gate exit(1); 16197c478bd9Sstevel@tonic-gate } 16207c478bd9Sstevel@tonic-gate break; 16217c478bd9Sstevel@tonic-gate case ':': 16227c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 16237c478bd9Sstevel@tonic-gate gettext("%s: option requires a value '-%c'\n"), 16247c478bd9Sstevel@tonic-gate progname, optopt); 16257c478bd9Sstevel@tonic-gate exit(1); 16267c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 16277c478bd9Sstevel@tonic-gate case '?': 16287c478bd9Sstevel@tonic-gate default: 16297c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 16307c478bd9Sstevel@tonic-gate gettext("%s: unrecognized option '-%c'\n"), 16317c478bd9Sstevel@tonic-gate progname, optopt); 16327c478bd9Sstevel@tonic-gate exit(1); 16337c478bd9Sstevel@tonic-gate } 16347c478bd9Sstevel@tonic-gate } 16357c478bd9Sstevel@tonic-gate 16367c478bd9Sstevel@tonic-gate if (i_arg && !s_arg) { 16377c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("%s: the option -i " 16387c478bd9Sstevel@tonic-gate "can be used only with -s\n"), progname); 16397c478bd9Sstevel@tonic-gate usage(); 16407c478bd9Sstevel@tonic-gate } 16417c478bd9Sstevel@tonic-gate 16427c478bd9Sstevel@tonic-gate /* get dev name (optional last argument) */ 16437c478bd9Sstevel@tonic-gate if (optind == (argc-1)) 16447c478bd9Sstevel@tonic-gate dev = argv[optind]; 16457c478bd9Sstevel@tonic-gate else if (optind != argc) 16467c478bd9Sstevel@tonic-gate usage(); 16477c478bd9Sstevel@tonic-gate 1648cd93090eSericheng if (dev != NULL) { 1649cd93090eSericheng int index; 1650cd93090eSericheng char drv[LIFNAMSIZ]; 1651cd93090eSericheng dladm_attr_t dlattr; 1652cd93090eSericheng boolean_t legacy; 1653cd93090eSericheng 1654cd93090eSericheng /* 1655cd93090eSericheng * Check for invalid devices. 1656cd93090eSericheng * aggregations and vlans are not considered devices. 1657cd93090eSericheng */ 1658cd93090eSericheng if (strncmp(dev, "aggr", 4) == 0 || 1659cd93090eSericheng dlpi_if_parse(dev, drv, &index) < 0 || 1660cd93090eSericheng index >= 1000 || 1661cd93090eSericheng get_if_info(dev, &dlattr, &legacy) < 0) { 16627c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 1663cd93090eSericheng gettext("%s: invalid device '%s'\n"), 16647c478bd9Sstevel@tonic-gate progname, dev); 16657c478bd9Sstevel@tonic-gate exit(1); 16667c478bd9Sstevel@tonic-gate } 1667cd93090eSericheng } 16687c478bd9Sstevel@tonic-gate 16697c478bd9Sstevel@tonic-gate if (s_arg) { 16707c478bd9Sstevel@tonic-gate dev_stats(dev, interval); 16717c478bd9Sstevel@tonic-gate return; 16727c478bd9Sstevel@tonic-gate } 16737c478bd9Sstevel@tonic-gate 16747c478bd9Sstevel@tonic-gate if (dev == NULL) 16757c478bd9Sstevel@tonic-gate (void) macadm_walk(show_dev, &state, B_TRUE); 16767c478bd9Sstevel@tonic-gate else 1677210db224Sericheng show_dev(&state, dev); 16787c478bd9Sstevel@tonic-gate } 16797c478bd9Sstevel@tonic-gate 16807c478bd9Sstevel@tonic-gate /* ARGSUSED */ 16817c478bd9Sstevel@tonic-gate static void 16827c478bd9Sstevel@tonic-gate link_stats(const char *link, uint32_t interval) 16837c478bd9Sstevel@tonic-gate { 1684210db224Sericheng dladm_attr_t dlattr; 1685210db224Sericheng boolean_t legacy; 16867c478bd9Sstevel@tonic-gate show_link_state_t state; 16877c478bd9Sstevel@tonic-gate 1688210db224Sericheng if (link != NULL && get_if_info(link, &dlattr, &legacy) < 0) { 1689210db224Sericheng (void) fprintf(stderr, gettext("%s: invalid device '%s'\n"), 16907c478bd9Sstevel@tonic-gate progname, link); 16917c478bd9Sstevel@tonic-gate exit(1); 16927c478bd9Sstevel@tonic-gate } 16937c478bd9Sstevel@tonic-gate bzero(&state, sizeof (state)); 16947c478bd9Sstevel@tonic-gate 16957c478bd9Sstevel@tonic-gate /* 16967c478bd9Sstevel@tonic-gate * If an interval is specified, continuously show the stats 16977c478bd9Sstevel@tonic-gate * only for the first MAC port. 16987c478bd9Sstevel@tonic-gate */ 16997c478bd9Sstevel@tonic-gate state.ls_firstonly = (interval != 0); 17007c478bd9Sstevel@tonic-gate 17017c478bd9Sstevel@tonic-gate for (;;) { 17027c478bd9Sstevel@tonic-gate (void) printf("\t\tipackets rbytes ierrors "); 17037c478bd9Sstevel@tonic-gate (void) printf("opackets obytes oerrors\n"); 17047c478bd9Sstevel@tonic-gate 17057c478bd9Sstevel@tonic-gate state.ls_donefirst = B_FALSE; 17067c478bd9Sstevel@tonic-gate if (link == NULL) 17077c478bd9Sstevel@tonic-gate (void) dladm_walk(show_link_stats, &state); 17087c478bd9Sstevel@tonic-gate else 17097c478bd9Sstevel@tonic-gate show_link_stats(&state, link); 17107c478bd9Sstevel@tonic-gate 17117c478bd9Sstevel@tonic-gate if (interval == 0) 17127c478bd9Sstevel@tonic-gate break; 17137c478bd9Sstevel@tonic-gate 17147c478bd9Sstevel@tonic-gate (void) sleep(interval); 17157c478bd9Sstevel@tonic-gate } 17167c478bd9Sstevel@tonic-gate } 17177c478bd9Sstevel@tonic-gate 17187c478bd9Sstevel@tonic-gate /* ARGSUSED */ 17197c478bd9Sstevel@tonic-gate static void 17207c478bd9Sstevel@tonic-gate aggr_stats(uint16_t key, uint32_t interval) 17217c478bd9Sstevel@tonic-gate { 17227c478bd9Sstevel@tonic-gate show_grp_state_t state; 17237c478bd9Sstevel@tonic-gate 17247c478bd9Sstevel@tonic-gate bzero(&state, sizeof (state)); 17257c478bd9Sstevel@tonic-gate state.gs_stats = B_TRUE; 17267c478bd9Sstevel@tonic-gate state.gs_key = key; 17277c478bd9Sstevel@tonic-gate 17287c478bd9Sstevel@tonic-gate /* 17297c478bd9Sstevel@tonic-gate * If an interval is specified, continuously show the stats 17307c478bd9Sstevel@tonic-gate * only for the first group. 17317c478bd9Sstevel@tonic-gate */ 17327c478bd9Sstevel@tonic-gate state.gs_firstonly = (interval != 0); 17337c478bd9Sstevel@tonic-gate 17347c478bd9Sstevel@tonic-gate for (;;) { 17357c478bd9Sstevel@tonic-gate state.gs_found = B_FALSE; 17367c478bd9Sstevel@tonic-gate (void) laadm_walk_sys(show_key, &state); 17377c478bd9Sstevel@tonic-gate if (state.gs_key != 0 && !state.gs_found) { 17387c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 17397c478bd9Sstevel@tonic-gate gettext("%s: non-existent aggregation key '%u'\n"), 17407c478bd9Sstevel@tonic-gate progname, key); 17417c478bd9Sstevel@tonic-gate exit(1); 17427c478bd9Sstevel@tonic-gate } 17437c478bd9Sstevel@tonic-gate 17447c478bd9Sstevel@tonic-gate if (interval == 0) 17457c478bd9Sstevel@tonic-gate break; 17467c478bd9Sstevel@tonic-gate 17477c478bd9Sstevel@tonic-gate (void) sleep(interval); 17487c478bd9Sstevel@tonic-gate } 17497c478bd9Sstevel@tonic-gate } 17507c478bd9Sstevel@tonic-gate 17517c478bd9Sstevel@tonic-gate /* ARGSUSED */ 17527c478bd9Sstevel@tonic-gate static void 17537c478bd9Sstevel@tonic-gate dev_stats(const char *dev, uint32_t interval) 17547c478bd9Sstevel@tonic-gate { 17557c478bd9Sstevel@tonic-gate show_mac_state_t state; 17567c478bd9Sstevel@tonic-gate 17577c478bd9Sstevel@tonic-gate bzero(&state, sizeof (state)); 17587c478bd9Sstevel@tonic-gate 17597c478bd9Sstevel@tonic-gate /* 17607c478bd9Sstevel@tonic-gate * If an interval is specified, continuously show the stats 17617c478bd9Sstevel@tonic-gate * only for the first MAC port. 17627c478bd9Sstevel@tonic-gate */ 17637c478bd9Sstevel@tonic-gate state.ms_firstonly = (interval != 0); 17647c478bd9Sstevel@tonic-gate 17657c478bd9Sstevel@tonic-gate for (;;) { 17667c478bd9Sstevel@tonic-gate 17677c478bd9Sstevel@tonic-gate (void) printf("\t\tipackets rbytes ierrors "); 17687c478bd9Sstevel@tonic-gate (void) printf("opackets obytes oerrors\n"); 17697c478bd9Sstevel@tonic-gate 17707c478bd9Sstevel@tonic-gate state.ms_donefirst = B_FALSE; 1771210db224Sericheng if (dev == NULL) 17727c478bd9Sstevel@tonic-gate (void) macadm_walk(show_dev_stats, &state, B_TRUE); 1773210db224Sericheng else 1774210db224Sericheng show_dev_stats(&state, dev); 17757c478bd9Sstevel@tonic-gate 17767c478bd9Sstevel@tonic-gate if (interval == 0) 17777c478bd9Sstevel@tonic-gate break; 17787c478bd9Sstevel@tonic-gate 17797c478bd9Sstevel@tonic-gate (void) sleep(interval); 17807c478bd9Sstevel@tonic-gate } 17817c478bd9Sstevel@tonic-gate } 17827c478bd9Sstevel@tonic-gate 17837c478bd9Sstevel@tonic-gate /* accumulate stats (s1 += (s2 - s3)) */ 17847c478bd9Sstevel@tonic-gate static void 17857c478bd9Sstevel@tonic-gate stats_total(pktsum_t *s1, pktsum_t *s2, pktsum_t *s3) 17867c478bd9Sstevel@tonic-gate { 17877c478bd9Sstevel@tonic-gate s1->ipackets += (s2->ipackets - s3->ipackets); 17887c478bd9Sstevel@tonic-gate s1->opackets += (s2->opackets - s3->opackets); 17897c478bd9Sstevel@tonic-gate s1->rbytes += (s2->rbytes - s3->rbytes); 17907c478bd9Sstevel@tonic-gate s1->obytes += (s2->obytes - s3->obytes); 17917c478bd9Sstevel@tonic-gate s1->ierrors += (s2->ierrors - s3->ierrors); 17927c478bd9Sstevel@tonic-gate s1->oerrors += (s2->oerrors - s3->oerrors); 17937c478bd9Sstevel@tonic-gate } 17947c478bd9Sstevel@tonic-gate 17957c478bd9Sstevel@tonic-gate /* compute stats differences (s1 = s2 - s3) */ 17967c478bd9Sstevel@tonic-gate static void 17977c478bd9Sstevel@tonic-gate stats_diff(pktsum_t *s1, pktsum_t *s2, pktsum_t *s3) 17987c478bd9Sstevel@tonic-gate { 17997c478bd9Sstevel@tonic-gate s1->ipackets = s2->ipackets - s3->ipackets; 18007c478bd9Sstevel@tonic-gate s1->opackets = s2->opackets - s3->opackets; 18017c478bd9Sstevel@tonic-gate s1->rbytes = s2->rbytes - s3->rbytes; 18027c478bd9Sstevel@tonic-gate s1->obytes = s2->obytes - s3->obytes; 18037c478bd9Sstevel@tonic-gate s1->ierrors = s2->ierrors - s3->ierrors; 18047c478bd9Sstevel@tonic-gate s1->oerrors = s2->oerrors - s3->oerrors; 18057c478bd9Sstevel@tonic-gate } 18067c478bd9Sstevel@tonic-gate 1807cd93090eSericheng /* 1808ba2e4443Sseb * In the following routines, we do the first kstat_lookup() assuming that 1809ba2e4443Sseb * the device is gldv3-based and that the kstat name is the one passed in 1810ba2e4443Sseb * as the "name" argument. If the lookup fails, we redo the kstat_lookup() 1811ba2e4443Sseb * omitting the kstat name. This second lookup is needed for getting kstats 1812ba2e4443Sseb * from legacy devices. This can fail too if the device is not attached or 1813ba2e4443Sseb * the device is legacy and doesn't export the kstats we need. 1814cd93090eSericheng */ 18157c478bd9Sstevel@tonic-gate static void 18167c478bd9Sstevel@tonic-gate get_stats(char *module, int instance, char *name, pktsum_t *stats) 18177c478bd9Sstevel@tonic-gate { 18187c478bd9Sstevel@tonic-gate kstat_ctl_t *kcp; 18197c478bd9Sstevel@tonic-gate kstat_t *ksp; 18207c478bd9Sstevel@tonic-gate 18217c478bd9Sstevel@tonic-gate if ((kcp = kstat_open()) == NULL) { 18227c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 18237c478bd9Sstevel@tonic-gate gettext("%s: kstat open operation failed\n"), 18247c478bd9Sstevel@tonic-gate progname); 18257c478bd9Sstevel@tonic-gate return; 18267c478bd9Sstevel@tonic-gate } 18277c478bd9Sstevel@tonic-gate 1828cd93090eSericheng if ((ksp = kstat_lookup(kcp, module, instance, name)) == NULL && 1829ba2e4443Sseb (ksp = kstat_lookup(kcp, module, instance, NULL)) == NULL) { 18307c478bd9Sstevel@tonic-gate /* 18317c478bd9Sstevel@tonic-gate * The kstat query could fail if the underlying MAC 18327c478bd9Sstevel@tonic-gate * driver was already detached. 18337c478bd9Sstevel@tonic-gate */ 18347c478bd9Sstevel@tonic-gate (void) kstat_close(kcp); 18357c478bd9Sstevel@tonic-gate return; 18367c478bd9Sstevel@tonic-gate } 18377c478bd9Sstevel@tonic-gate 18387c478bd9Sstevel@tonic-gate if (kstat_read(kcp, ksp, NULL) == -1) 18397c478bd9Sstevel@tonic-gate goto bail; 18407c478bd9Sstevel@tonic-gate 18417c478bd9Sstevel@tonic-gate if (kstat_value(ksp, "ipackets64", KSTAT_DATA_UINT64, 18427c478bd9Sstevel@tonic-gate &stats->ipackets) < 0) 18437c478bd9Sstevel@tonic-gate goto bail; 18447c478bd9Sstevel@tonic-gate 18457c478bd9Sstevel@tonic-gate if (kstat_value(ksp, "opackets64", KSTAT_DATA_UINT64, 18467c478bd9Sstevel@tonic-gate &stats->opackets) < 0) 18477c478bd9Sstevel@tonic-gate goto bail; 18487c478bd9Sstevel@tonic-gate 18497c478bd9Sstevel@tonic-gate if (kstat_value(ksp, "rbytes64", KSTAT_DATA_UINT64, 18507c478bd9Sstevel@tonic-gate &stats->rbytes) < 0) 18517c478bd9Sstevel@tonic-gate goto bail; 18527c478bd9Sstevel@tonic-gate 18537c478bd9Sstevel@tonic-gate if (kstat_value(ksp, "obytes64", KSTAT_DATA_UINT64, 18547c478bd9Sstevel@tonic-gate &stats->obytes) < 0) 18557c478bd9Sstevel@tonic-gate goto bail; 18567c478bd9Sstevel@tonic-gate 18577c478bd9Sstevel@tonic-gate if (kstat_value(ksp, "ierrors", KSTAT_DATA_UINT32, 18587c478bd9Sstevel@tonic-gate &stats->ierrors) < 0) 18597c478bd9Sstevel@tonic-gate goto bail; 18607c478bd9Sstevel@tonic-gate 18617c478bd9Sstevel@tonic-gate if (kstat_value(ksp, "oerrors", KSTAT_DATA_UINT32, 18627c478bd9Sstevel@tonic-gate &stats->oerrors) < 0) 18637c478bd9Sstevel@tonic-gate goto bail; 18647c478bd9Sstevel@tonic-gate 18657c478bd9Sstevel@tonic-gate (void) kstat_close(kcp); 18667c478bd9Sstevel@tonic-gate return; 18677c478bd9Sstevel@tonic-gate 18687c478bd9Sstevel@tonic-gate bail: 18697c478bd9Sstevel@tonic-gate (void) kstat_close(kcp); 18707c478bd9Sstevel@tonic-gate } 18717c478bd9Sstevel@tonic-gate 18727c478bd9Sstevel@tonic-gate static void 1873ba2e4443Sseb get_mac_stats(const char *dev, pktsum_t *stats) 18747c478bd9Sstevel@tonic-gate { 1875ba2e4443Sseb char module[LIFNAMSIZ]; 1876ba2e4443Sseb int instance; 18777c478bd9Sstevel@tonic-gate 1878ba2e4443Sseb if (dlpi_if_parse(dev, module, &instance) != 0) 1879ba2e4443Sseb return; 18807c478bd9Sstevel@tonic-gate bzero(stats, sizeof (*stats)); 1881ba2e4443Sseb get_stats(module, instance, "mac", stats); 18827c478bd9Sstevel@tonic-gate } 18837c478bd9Sstevel@tonic-gate 18847c478bd9Sstevel@tonic-gate static void 18857c478bd9Sstevel@tonic-gate get_link_stats(const char *link, pktsum_t *stats) 18867c478bd9Sstevel@tonic-gate { 1887ba2e4443Sseb char module[LIFNAMSIZ]; 1888ba2e4443Sseb int instance; 1889ba2e4443Sseb 1890ba2e4443Sseb if (dlpi_if_parse(link, module, &instance) != 0) 1891ba2e4443Sseb return; 18927c478bd9Sstevel@tonic-gate bzero(stats, sizeof (*stats)); 1893ba2e4443Sseb get_stats(module, instance, (char *)link, stats); 18947c478bd9Sstevel@tonic-gate } 18957c478bd9Sstevel@tonic-gate 1896ba2e4443Sseb static int 1897ba2e4443Sseb get_single_mac_stat(const char *dev, const char *name, uint8_t type, 1898ba2e4443Sseb void *val) 18997c478bd9Sstevel@tonic-gate { 1900ba2e4443Sseb char module[LIFNAMSIZ]; 1901ba2e4443Sseb int instance; 19027c478bd9Sstevel@tonic-gate kstat_ctl_t *kcp; 19037c478bd9Sstevel@tonic-gate kstat_t *ksp; 19047c478bd9Sstevel@tonic-gate 19057c478bd9Sstevel@tonic-gate if ((kcp = kstat_open()) == NULL) { 19067c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 19077c478bd9Sstevel@tonic-gate gettext("%s: kstat open operation failed\n"), 19087c478bd9Sstevel@tonic-gate progname); 1909ba2e4443Sseb return (-1); 19107c478bd9Sstevel@tonic-gate } 19117c478bd9Sstevel@tonic-gate 1912ba2e4443Sseb if (dlpi_if_parse(dev, module, &instance) != 0) 1913ba2e4443Sseb return (-1); 1914ba2e4443Sseb if ((ksp = kstat_lookup(kcp, module, instance, "mac")) == NULL && 1915ba2e4443Sseb (ksp = kstat_lookup(kcp, module, instance, NULL)) == NULL) { 19167c478bd9Sstevel@tonic-gate /* 19177c478bd9Sstevel@tonic-gate * The kstat query could fail if the underlying MAC 19187c478bd9Sstevel@tonic-gate * driver was already detached. 19197c478bd9Sstevel@tonic-gate */ 19207c478bd9Sstevel@tonic-gate goto bail; 19217c478bd9Sstevel@tonic-gate } 19227c478bd9Sstevel@tonic-gate 19237c478bd9Sstevel@tonic-gate if (kstat_read(kcp, ksp, NULL) == -1) { 19247c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 19257c478bd9Sstevel@tonic-gate gettext("%s: kstat read failed\n"), 19267c478bd9Sstevel@tonic-gate progname); 19277c478bd9Sstevel@tonic-gate goto bail; 19287c478bd9Sstevel@tonic-gate } 19297c478bd9Sstevel@tonic-gate 1930ba2e4443Sseb if (kstat_value(ksp, name, type, val) < 0) 19317c478bd9Sstevel@tonic-gate goto bail; 1932ba2e4443Sseb 1933ba2e4443Sseb (void) kstat_close(kcp); 1934ba2e4443Sseb return (0); 19357c478bd9Sstevel@tonic-gate 19367c478bd9Sstevel@tonic-gate bail: 19377c478bd9Sstevel@tonic-gate (void) kstat_close(kcp); 1938ba2e4443Sseb return (-1); 1939ba2e4443Sseb } 1940ba2e4443Sseb 1941ba2e4443Sseb static uint64_t 1942ba2e4443Sseb mac_ifspeed(const char *dev) 1943ba2e4443Sseb { 1944ba2e4443Sseb uint64_t ifspeed = 0; 1945ba2e4443Sseb 1946ba2e4443Sseb (void) get_single_mac_stat(dev, "ifspeed", KSTAT_DATA_UINT64, &ifspeed); 19477c478bd9Sstevel@tonic-gate return (ifspeed); 19487c478bd9Sstevel@tonic-gate } 19497c478bd9Sstevel@tonic-gate 19507c478bd9Sstevel@tonic-gate static char * 1951ba2e4443Sseb mac_link_state(const char *dev) 19527c478bd9Sstevel@tonic-gate { 19537c478bd9Sstevel@tonic-gate link_state_t link_state; 19547c478bd9Sstevel@tonic-gate char *state_str = "unknown"; 19557c478bd9Sstevel@tonic-gate 1956ba2e4443Sseb if (get_single_mac_stat(dev, "link_state", KSTAT_DATA_UINT32, 1957ba2e4443Sseb &link_state) != 0) { 19587c478bd9Sstevel@tonic-gate return (state_str); 19597c478bd9Sstevel@tonic-gate } 19607c478bd9Sstevel@tonic-gate 19617c478bd9Sstevel@tonic-gate switch (link_state) { 19627c478bd9Sstevel@tonic-gate case LINK_STATE_UP: 19637c478bd9Sstevel@tonic-gate state_str = "up"; 19647c478bd9Sstevel@tonic-gate break; 19657c478bd9Sstevel@tonic-gate case LINK_STATE_DOWN: 19667c478bd9Sstevel@tonic-gate state_str = "down"; 19677c478bd9Sstevel@tonic-gate break; 19687c478bd9Sstevel@tonic-gate default: 19697c478bd9Sstevel@tonic-gate break; 19707c478bd9Sstevel@tonic-gate } 19717c478bd9Sstevel@tonic-gate 19727c478bd9Sstevel@tonic-gate return (state_str); 19737c478bd9Sstevel@tonic-gate } 19747c478bd9Sstevel@tonic-gate 19757c478bd9Sstevel@tonic-gate 19767c478bd9Sstevel@tonic-gate static char * 1977ba2e4443Sseb mac_link_duplex(const char *dev) 19787c478bd9Sstevel@tonic-gate { 19797c478bd9Sstevel@tonic-gate link_duplex_t link_duplex; 19807c478bd9Sstevel@tonic-gate char *duplex_str = "unknown"; 19817c478bd9Sstevel@tonic-gate 1982ba2e4443Sseb if (get_single_mac_stat(dev, "link_duplex", KSTAT_DATA_UINT32, 1983ba2e4443Sseb &link_duplex) != 0) { 19847c478bd9Sstevel@tonic-gate return (duplex_str); 19857c478bd9Sstevel@tonic-gate } 19867c478bd9Sstevel@tonic-gate 19877c478bd9Sstevel@tonic-gate switch (link_duplex) { 19887c478bd9Sstevel@tonic-gate case LINK_DUPLEX_FULL: 19897c478bd9Sstevel@tonic-gate duplex_str = "full"; 19907c478bd9Sstevel@tonic-gate break; 19917c478bd9Sstevel@tonic-gate case LINK_DUPLEX_HALF: 19927c478bd9Sstevel@tonic-gate duplex_str = "half"; 19937c478bd9Sstevel@tonic-gate break; 19947c478bd9Sstevel@tonic-gate default: 19957c478bd9Sstevel@tonic-gate break; 19967c478bd9Sstevel@tonic-gate } 19977c478bd9Sstevel@tonic-gate 19987c478bd9Sstevel@tonic-gate return (duplex_str); 19997c478bd9Sstevel@tonic-gate } 2000*0ba2cbe9Sxc151355 2001*0ba2cbe9Sxc151355 #define WIFI_CMD_SCAN 0x00000001 2002*0ba2cbe9Sxc151355 #define WIFI_CMD_SHOW 0x00000002 2003*0ba2cbe9Sxc151355 #define WIFI_CMD_ALL (WIFI_CMD_SCAN | WIFI_CMD_SHOW) 2004*0ba2cbe9Sxc151355 typedef struct wifi_field { 2005*0ba2cbe9Sxc151355 const char *wf_name; 2006*0ba2cbe9Sxc151355 const char *wf_header; 2007*0ba2cbe9Sxc151355 uint_t wf_width; 2008*0ba2cbe9Sxc151355 uint_t wf_mask; 2009*0ba2cbe9Sxc151355 uint_t wf_cmdtype; 2010*0ba2cbe9Sxc151355 } wifi_field_t; 2011*0ba2cbe9Sxc151355 2012*0ba2cbe9Sxc151355 static wifi_field_t wifi_fields[] = { 2013*0ba2cbe9Sxc151355 { "link", "LINK", 10, 0, WIFI_CMD_ALL}, 2014*0ba2cbe9Sxc151355 { "essid", "ESSID", 19, WLADM_WLAN_ATTR_ESSID, WIFI_CMD_ALL}, 2015*0ba2cbe9Sxc151355 { "bssid", "BSSID/IBSSID", 17, WLADM_WLAN_ATTR_BSSID, WIFI_CMD_ALL}, 2016*0ba2cbe9Sxc151355 { "ibssid", "BSSID/IBSSID", 17, WLADM_WLAN_ATTR_BSSID, WIFI_CMD_ALL}, 2017*0ba2cbe9Sxc151355 { "mode", "MODE", 6, WLADM_WLAN_ATTR_MODE, WIFI_CMD_ALL}, 2018*0ba2cbe9Sxc151355 { "speed", "SPEED", 6, WLADM_WLAN_ATTR_SPEED, WIFI_CMD_ALL}, 2019*0ba2cbe9Sxc151355 { "auth", "AUTH", 8, WLADM_WLAN_ATTR_AUTH, WIFI_CMD_ALL}, 2020*0ba2cbe9Sxc151355 { "bsstype", "BSSTYPE", 8, WLADM_WLAN_ATTR_BSSTYPE, WIFI_CMD_ALL}, 2021*0ba2cbe9Sxc151355 { "sec", "SEC", 6, WLADM_WLAN_ATTR_SECMODE, WIFI_CMD_ALL}, 2022*0ba2cbe9Sxc151355 { "status", "STATUS", 17, WLADM_LINK_ATTR_STATUS, WIFI_CMD_SHOW}, 2023*0ba2cbe9Sxc151355 { "strength", "STRENGTH", 10, WLADM_WLAN_ATTR_STRENGTH, WIFI_CMD_ALL}} 2024*0ba2cbe9Sxc151355 ; 2025*0ba2cbe9Sxc151355 2026*0ba2cbe9Sxc151355 static char *all_scan_wifi_fields = 2027*0ba2cbe9Sxc151355 "link,essid,bssid,sec,strength,mode,speed,auth,bsstype"; 2028*0ba2cbe9Sxc151355 static char *all_show_wifi_fields = 2029*0ba2cbe9Sxc151355 "link,status,essid,sec,strength,mode,speed,auth,bssid,bsstype"; 2030*0ba2cbe9Sxc151355 static char *def_scan_wifi_fields = 2031*0ba2cbe9Sxc151355 "link,essid,bssid,sec,strength,mode,speed"; 2032*0ba2cbe9Sxc151355 static char *def_show_wifi_fields = 2033*0ba2cbe9Sxc151355 "link,status,essid,sec,strength,mode,speed"; 2034*0ba2cbe9Sxc151355 2035*0ba2cbe9Sxc151355 #define WIFI_MAX_FIELDS (sizeof (wifi_fields) / sizeof (wifi_field_t)) 2036*0ba2cbe9Sxc151355 #define WIFI_MAX_FIELD_LEN 32 2037*0ba2cbe9Sxc151355 2038*0ba2cbe9Sxc151355 typedef struct { 2039*0ba2cbe9Sxc151355 char *s_buf; 2040*0ba2cbe9Sxc151355 char **s_fields; /* array of pointer to the fields in s_buf */ 2041*0ba2cbe9Sxc151355 uint_t s_nfields; /* the number of fields in s_buf */ 2042*0ba2cbe9Sxc151355 } split_t; 2043*0ba2cbe9Sxc151355 2044*0ba2cbe9Sxc151355 /* 2045*0ba2cbe9Sxc151355 * Free the split_t structure pointed to by `sp'. 2046*0ba2cbe9Sxc151355 */ 2047*0ba2cbe9Sxc151355 static void 2048*0ba2cbe9Sxc151355 splitfree(split_t *sp) 2049*0ba2cbe9Sxc151355 { 2050*0ba2cbe9Sxc151355 free(sp->s_buf); 2051*0ba2cbe9Sxc151355 free(sp->s_fields); 2052*0ba2cbe9Sxc151355 free(sp); 2053*0ba2cbe9Sxc151355 } 2054*0ba2cbe9Sxc151355 2055*0ba2cbe9Sxc151355 /* 2056*0ba2cbe9Sxc151355 * Split `str' into at most `maxfields' fields, each field at most `maxlen' in 2057*0ba2cbe9Sxc151355 * length. Return a pointer to a split_t containing the split fields, or NULL 2058*0ba2cbe9Sxc151355 * on failure. 2059*0ba2cbe9Sxc151355 */ 2060*0ba2cbe9Sxc151355 static split_t * 2061*0ba2cbe9Sxc151355 split(const char *str, uint_t maxfields, uint_t maxlen) 2062*0ba2cbe9Sxc151355 { 2063*0ba2cbe9Sxc151355 char *field, *token, *lasts = NULL; 2064*0ba2cbe9Sxc151355 split_t *sp; 2065*0ba2cbe9Sxc151355 2066*0ba2cbe9Sxc151355 if (*str == '\0' || maxfields == 0 || maxlen == 0) 2067*0ba2cbe9Sxc151355 return (NULL); 2068*0ba2cbe9Sxc151355 2069*0ba2cbe9Sxc151355 sp = calloc(sizeof (split_t), 1); 2070*0ba2cbe9Sxc151355 if (sp == NULL) 2071*0ba2cbe9Sxc151355 return (NULL); 2072*0ba2cbe9Sxc151355 2073*0ba2cbe9Sxc151355 sp->s_buf = strdup(str); 2074*0ba2cbe9Sxc151355 sp->s_fields = malloc(sizeof (char *) * maxfields); 2075*0ba2cbe9Sxc151355 if (sp->s_buf == NULL || sp->s_fields == NULL) 2076*0ba2cbe9Sxc151355 goto fail; 2077*0ba2cbe9Sxc151355 2078*0ba2cbe9Sxc151355 token = sp->s_buf; 2079*0ba2cbe9Sxc151355 while ((field = strtok_r(token, ",", &lasts)) != NULL) { 2080*0ba2cbe9Sxc151355 if (sp->s_nfields == maxfields || strlen(field) > maxlen) 2081*0ba2cbe9Sxc151355 goto fail; 2082*0ba2cbe9Sxc151355 token = NULL; 2083*0ba2cbe9Sxc151355 sp->s_fields[sp->s_nfields++] = field; 2084*0ba2cbe9Sxc151355 } 2085*0ba2cbe9Sxc151355 return (sp); 2086*0ba2cbe9Sxc151355 fail: 2087*0ba2cbe9Sxc151355 splitfree(sp); 2088*0ba2cbe9Sxc151355 return (NULL); 2089*0ba2cbe9Sxc151355 } 2090*0ba2cbe9Sxc151355 2091*0ba2cbe9Sxc151355 static int 2092*0ba2cbe9Sxc151355 parse_wifi_fields(char *str, wifi_field_t ***fields, uint_t *countp, 2093*0ba2cbe9Sxc151355 uint_t cmdtype) 2094*0ba2cbe9Sxc151355 { 2095*0ba2cbe9Sxc151355 uint_t i, j; 2096*0ba2cbe9Sxc151355 wifi_field_t **wf = NULL; 2097*0ba2cbe9Sxc151355 split_t *sp; 2098*0ba2cbe9Sxc151355 boolean_t good_match = B_FALSE; 2099*0ba2cbe9Sxc151355 2100*0ba2cbe9Sxc151355 if (cmdtype == WIFI_CMD_SCAN) { 2101*0ba2cbe9Sxc151355 if (str == NULL) 2102*0ba2cbe9Sxc151355 str = def_scan_wifi_fields; 2103*0ba2cbe9Sxc151355 if (strcasecmp(str, "all") == 0) 2104*0ba2cbe9Sxc151355 str = all_scan_wifi_fields; 2105*0ba2cbe9Sxc151355 } else if (cmdtype == WIFI_CMD_SHOW) { 2106*0ba2cbe9Sxc151355 if (str == NULL) 2107*0ba2cbe9Sxc151355 str = def_show_wifi_fields; 2108*0ba2cbe9Sxc151355 if (strcasecmp(str, "all") == 0) 2109*0ba2cbe9Sxc151355 str = all_show_wifi_fields; 2110*0ba2cbe9Sxc151355 } else { 2111*0ba2cbe9Sxc151355 return (-1); 2112*0ba2cbe9Sxc151355 } 2113*0ba2cbe9Sxc151355 2114*0ba2cbe9Sxc151355 sp = split(str, WIFI_MAX_FIELDS, WIFI_MAX_FIELD_LEN); 2115*0ba2cbe9Sxc151355 if (sp == NULL) 2116*0ba2cbe9Sxc151355 return (-1); 2117*0ba2cbe9Sxc151355 2118*0ba2cbe9Sxc151355 wf = malloc(sp->s_nfields * sizeof (wifi_field_t *)); 2119*0ba2cbe9Sxc151355 if (wf == NULL) 2120*0ba2cbe9Sxc151355 goto fail; 2121*0ba2cbe9Sxc151355 2122*0ba2cbe9Sxc151355 for (i = 0; i < sp->s_nfields; i++) { 2123*0ba2cbe9Sxc151355 for (j = 0; j < WIFI_MAX_FIELDS; j++) { 2124*0ba2cbe9Sxc151355 if (strcasecmp(sp->s_fields[i], 2125*0ba2cbe9Sxc151355 wifi_fields[j].wf_name) == 0) { 2126*0ba2cbe9Sxc151355 good_match = wifi_fields[i]. 2127*0ba2cbe9Sxc151355 wf_cmdtype & cmdtype; 2128*0ba2cbe9Sxc151355 break; 2129*0ba2cbe9Sxc151355 } 2130*0ba2cbe9Sxc151355 } 2131*0ba2cbe9Sxc151355 if (!good_match) 2132*0ba2cbe9Sxc151355 goto fail; 2133*0ba2cbe9Sxc151355 2134*0ba2cbe9Sxc151355 good_match = B_FALSE; 2135*0ba2cbe9Sxc151355 wf[i] = &wifi_fields[j]; 2136*0ba2cbe9Sxc151355 } 2137*0ba2cbe9Sxc151355 *countp = i; 2138*0ba2cbe9Sxc151355 *fields = wf; 2139*0ba2cbe9Sxc151355 splitfree(sp); 2140*0ba2cbe9Sxc151355 return (0); 2141*0ba2cbe9Sxc151355 fail: 2142*0ba2cbe9Sxc151355 free(wf); 2143*0ba2cbe9Sxc151355 splitfree(sp); 2144*0ba2cbe9Sxc151355 return (-1); 2145*0ba2cbe9Sxc151355 } 2146*0ba2cbe9Sxc151355 2147*0ba2cbe9Sxc151355 typedef struct print_wifi_state { 2148*0ba2cbe9Sxc151355 const char *ws_link; 2149*0ba2cbe9Sxc151355 boolean_t ws_parseable; 2150*0ba2cbe9Sxc151355 boolean_t ws_header; 2151*0ba2cbe9Sxc151355 wifi_field_t **ws_fields; 2152*0ba2cbe9Sxc151355 uint_t ws_nfields; 2153*0ba2cbe9Sxc151355 boolean_t ws_lastfield; 2154*0ba2cbe9Sxc151355 uint_t ws_overflow; 2155*0ba2cbe9Sxc151355 } print_wifi_state_t; 2156*0ba2cbe9Sxc151355 2157*0ba2cbe9Sxc151355 static void 2158*0ba2cbe9Sxc151355 print_wifi_head(print_wifi_state_t *statep) 2159*0ba2cbe9Sxc151355 { 2160*0ba2cbe9Sxc151355 int i; 2161*0ba2cbe9Sxc151355 wifi_field_t *wfp; 2162*0ba2cbe9Sxc151355 2163*0ba2cbe9Sxc151355 for (i = 0; i < statep->ws_nfields; i++) { 2164*0ba2cbe9Sxc151355 wfp = statep->ws_fields[i]; 2165*0ba2cbe9Sxc151355 if (i + 1 < statep->ws_nfields) 2166*0ba2cbe9Sxc151355 (void) printf("%-*s ", wfp->wf_width, wfp->wf_header); 2167*0ba2cbe9Sxc151355 else 2168*0ba2cbe9Sxc151355 (void) printf("%s", wfp->wf_header); 2169*0ba2cbe9Sxc151355 } 2170*0ba2cbe9Sxc151355 (void) printf("\n"); 2171*0ba2cbe9Sxc151355 } 2172*0ba2cbe9Sxc151355 2173*0ba2cbe9Sxc151355 static void 2174*0ba2cbe9Sxc151355 print_wifi_field(print_wifi_state_t *statep, wifi_field_t *wfp, 2175*0ba2cbe9Sxc151355 const char *value) 2176*0ba2cbe9Sxc151355 { 2177*0ba2cbe9Sxc151355 uint_t width = wfp->wf_width; 2178*0ba2cbe9Sxc151355 uint_t valwidth = strlen(value); 2179*0ba2cbe9Sxc151355 uint_t compress; 2180*0ba2cbe9Sxc151355 2181*0ba2cbe9Sxc151355 if (statep->ws_parseable) { 2182*0ba2cbe9Sxc151355 (void) printf("%s=\"%s\"", wfp->wf_header, value); 2183*0ba2cbe9Sxc151355 } else { 2184*0ba2cbe9Sxc151355 if (value[0] == '\0') 2185*0ba2cbe9Sxc151355 value = "--"; 2186*0ba2cbe9Sxc151355 if (statep->ws_lastfield) { 2187*0ba2cbe9Sxc151355 (void) printf("%s", value); 2188*0ba2cbe9Sxc151355 return; 2189*0ba2cbe9Sxc151355 } 2190*0ba2cbe9Sxc151355 2191*0ba2cbe9Sxc151355 if (valwidth > width) { 2192*0ba2cbe9Sxc151355 statep->ws_overflow += valwidth - width; 2193*0ba2cbe9Sxc151355 } else if (valwidth < width && statep->ws_overflow > 0) { 2194*0ba2cbe9Sxc151355 compress = min(statep->ws_overflow, width - valwidth); 2195*0ba2cbe9Sxc151355 statep->ws_overflow -= compress; 2196*0ba2cbe9Sxc151355 width -= compress; 2197*0ba2cbe9Sxc151355 } 2198*0ba2cbe9Sxc151355 (void) printf("%-*s", width, value); 2199*0ba2cbe9Sxc151355 } 2200*0ba2cbe9Sxc151355 2201*0ba2cbe9Sxc151355 if (!statep->ws_lastfield) 2202*0ba2cbe9Sxc151355 (void) putchar(' '); 2203*0ba2cbe9Sxc151355 } 2204*0ba2cbe9Sxc151355 2205*0ba2cbe9Sxc151355 static void 2206*0ba2cbe9Sxc151355 print_wlan_attr(print_wifi_state_t *statep, wifi_field_t *wfp, 2207*0ba2cbe9Sxc151355 wladm_wlan_attr_t *attrp) 2208*0ba2cbe9Sxc151355 { 2209*0ba2cbe9Sxc151355 char buf[WLADM_STRSIZE]; 2210*0ba2cbe9Sxc151355 const char *str = ""; 2211*0ba2cbe9Sxc151355 2212*0ba2cbe9Sxc151355 if (wfp->wf_mask == 0) { 2213*0ba2cbe9Sxc151355 print_wifi_field(statep, wfp, statep->ws_link); 2214*0ba2cbe9Sxc151355 return; 2215*0ba2cbe9Sxc151355 } 2216*0ba2cbe9Sxc151355 2217*0ba2cbe9Sxc151355 if ((wfp->wf_mask & attrp->wa_valid) == 0) { 2218*0ba2cbe9Sxc151355 print_wifi_field(statep, wfp, ""); 2219*0ba2cbe9Sxc151355 return; 2220*0ba2cbe9Sxc151355 } 2221*0ba2cbe9Sxc151355 2222*0ba2cbe9Sxc151355 switch (wfp->wf_mask) { 2223*0ba2cbe9Sxc151355 case WLADM_WLAN_ATTR_ESSID: 2224*0ba2cbe9Sxc151355 str = wladm_essid2str(&attrp->wa_essid, buf); 2225*0ba2cbe9Sxc151355 break; 2226*0ba2cbe9Sxc151355 case WLADM_WLAN_ATTR_BSSID: 2227*0ba2cbe9Sxc151355 str = wladm_bssid2str(&attrp->wa_bssid, buf); 2228*0ba2cbe9Sxc151355 break; 2229*0ba2cbe9Sxc151355 case WLADM_WLAN_ATTR_SECMODE: 2230*0ba2cbe9Sxc151355 str = wladm_secmode2str(&attrp->wa_secmode, buf); 2231*0ba2cbe9Sxc151355 break; 2232*0ba2cbe9Sxc151355 case WLADM_WLAN_ATTR_STRENGTH: 2233*0ba2cbe9Sxc151355 str = wladm_strength2str(&attrp->wa_strength, buf); 2234*0ba2cbe9Sxc151355 break; 2235*0ba2cbe9Sxc151355 case WLADM_WLAN_ATTR_MODE: 2236*0ba2cbe9Sxc151355 str = wladm_mode2str(&attrp->wa_mode, buf); 2237*0ba2cbe9Sxc151355 break; 2238*0ba2cbe9Sxc151355 case WLADM_WLAN_ATTR_SPEED: 2239*0ba2cbe9Sxc151355 str = wladm_speed2str(&attrp->wa_speed, buf); 2240*0ba2cbe9Sxc151355 (void) strlcat(buf, "Mb", sizeof (buf)); 2241*0ba2cbe9Sxc151355 break; 2242*0ba2cbe9Sxc151355 case WLADM_WLAN_ATTR_AUTH: 2243*0ba2cbe9Sxc151355 str = wladm_auth2str(&attrp->wa_auth, buf); 2244*0ba2cbe9Sxc151355 break; 2245*0ba2cbe9Sxc151355 case WLADM_WLAN_ATTR_BSSTYPE: 2246*0ba2cbe9Sxc151355 str = wladm_bsstype2str(&attrp->wa_bsstype, buf); 2247*0ba2cbe9Sxc151355 break; 2248*0ba2cbe9Sxc151355 } 2249*0ba2cbe9Sxc151355 2250*0ba2cbe9Sxc151355 print_wifi_field(statep, wfp, str); 2251*0ba2cbe9Sxc151355 } 2252*0ba2cbe9Sxc151355 2253*0ba2cbe9Sxc151355 static boolean_t 2254*0ba2cbe9Sxc151355 print_scan_results(void *arg, wladm_wlan_attr_t *attrp) 2255*0ba2cbe9Sxc151355 { 2256*0ba2cbe9Sxc151355 print_wifi_state_t *statep = arg; 2257*0ba2cbe9Sxc151355 int i; 2258*0ba2cbe9Sxc151355 2259*0ba2cbe9Sxc151355 if (statep->ws_header) { 2260*0ba2cbe9Sxc151355 statep->ws_header = B_FALSE; 2261*0ba2cbe9Sxc151355 if (!statep->ws_parseable) 2262*0ba2cbe9Sxc151355 print_wifi_head(statep); 2263*0ba2cbe9Sxc151355 } 2264*0ba2cbe9Sxc151355 2265*0ba2cbe9Sxc151355 statep->ws_overflow = 0; 2266*0ba2cbe9Sxc151355 for (i = 0; i < statep->ws_nfields; i++) { 2267*0ba2cbe9Sxc151355 statep->ws_lastfield = (i + 1 == statep->ws_nfields); 2268*0ba2cbe9Sxc151355 print_wlan_attr(statep, statep->ws_fields[i], attrp); 2269*0ba2cbe9Sxc151355 } 2270*0ba2cbe9Sxc151355 (void) putchar('\n'); 2271*0ba2cbe9Sxc151355 return (B_TRUE); 2272*0ba2cbe9Sxc151355 } 2273*0ba2cbe9Sxc151355 2274*0ba2cbe9Sxc151355 static boolean_t 2275*0ba2cbe9Sxc151355 scan_wifi(void *arg, const char *link) 2276*0ba2cbe9Sxc151355 { 2277*0ba2cbe9Sxc151355 char errmsg[WLADM_STRSIZE]; 2278*0ba2cbe9Sxc151355 print_wifi_state_t *statep = arg; 2279*0ba2cbe9Sxc151355 wladm_status_t status; 2280*0ba2cbe9Sxc151355 2281*0ba2cbe9Sxc151355 statep->ws_link = link; 2282*0ba2cbe9Sxc151355 status = wladm_scan(link, statep, print_scan_results); 2283*0ba2cbe9Sxc151355 if (status != WLADM_STATUS_OK) { 2284*0ba2cbe9Sxc151355 (void) fprintf(stderr, gettext( 2285*0ba2cbe9Sxc151355 "%s: cannot scan link '%s': %s\n"), 2286*0ba2cbe9Sxc151355 progname, link, wladm_status2str(status, errmsg)); 2287*0ba2cbe9Sxc151355 exit(1); 2288*0ba2cbe9Sxc151355 } 2289*0ba2cbe9Sxc151355 return (B_TRUE); 2290*0ba2cbe9Sxc151355 } 2291*0ba2cbe9Sxc151355 2292*0ba2cbe9Sxc151355 static void 2293*0ba2cbe9Sxc151355 print_link_attr(print_wifi_state_t *statep, wifi_field_t *wfp, 2294*0ba2cbe9Sxc151355 wladm_link_attr_t *attrp) 2295*0ba2cbe9Sxc151355 { 2296*0ba2cbe9Sxc151355 char buf[WLADM_STRSIZE]; 2297*0ba2cbe9Sxc151355 const char *str = ""; 2298*0ba2cbe9Sxc151355 2299*0ba2cbe9Sxc151355 if (strcmp(wfp->wf_name, "status") == 0) { 2300*0ba2cbe9Sxc151355 if ((wfp->wf_mask & attrp->la_valid) != 0) 2301*0ba2cbe9Sxc151355 str = wladm_linkstatus2str(&attrp->la_status, buf); 2302*0ba2cbe9Sxc151355 print_wifi_field(statep, wfp, str); 2303*0ba2cbe9Sxc151355 return; 2304*0ba2cbe9Sxc151355 } 2305*0ba2cbe9Sxc151355 print_wlan_attr(statep, wfp, &attrp->la_wlan_attr); 2306*0ba2cbe9Sxc151355 } 2307*0ba2cbe9Sxc151355 2308*0ba2cbe9Sxc151355 static boolean_t 2309*0ba2cbe9Sxc151355 show_wifi(void *arg, const char *link) 2310*0ba2cbe9Sxc151355 { 2311*0ba2cbe9Sxc151355 int i; 2312*0ba2cbe9Sxc151355 char buf[WLADM_STRSIZE]; 2313*0ba2cbe9Sxc151355 print_wifi_state_t *statep = arg; 2314*0ba2cbe9Sxc151355 wladm_link_attr_t attr; 2315*0ba2cbe9Sxc151355 wladm_status_t status; 2316*0ba2cbe9Sxc151355 2317*0ba2cbe9Sxc151355 status = wladm_get_link_attr(link, &attr); 2318*0ba2cbe9Sxc151355 if (status != WLADM_STATUS_OK) { 2319*0ba2cbe9Sxc151355 (void) fprintf(stderr, gettext("%s: cannot get link " 2320*0ba2cbe9Sxc151355 "attributes for '%s': %s\n"), progname, link, 2321*0ba2cbe9Sxc151355 wladm_status2str(status, buf)); 2322*0ba2cbe9Sxc151355 exit(1); 2323*0ba2cbe9Sxc151355 } 2324*0ba2cbe9Sxc151355 2325*0ba2cbe9Sxc151355 if (statep->ws_header) { 2326*0ba2cbe9Sxc151355 statep->ws_header = B_FALSE; 2327*0ba2cbe9Sxc151355 if (!statep->ws_parseable) 2328*0ba2cbe9Sxc151355 print_wifi_head(statep); 2329*0ba2cbe9Sxc151355 } 2330*0ba2cbe9Sxc151355 2331*0ba2cbe9Sxc151355 statep->ws_link = link; 2332*0ba2cbe9Sxc151355 statep->ws_overflow = 0; 2333*0ba2cbe9Sxc151355 for (i = 0; i < statep->ws_nfields; i++) { 2334*0ba2cbe9Sxc151355 statep->ws_lastfield = (i + 1 == statep->ws_nfields); 2335*0ba2cbe9Sxc151355 print_link_attr(statep, statep->ws_fields[i], &attr); 2336*0ba2cbe9Sxc151355 } 2337*0ba2cbe9Sxc151355 (void) putchar('\n'); 2338*0ba2cbe9Sxc151355 return (B_TRUE); 2339*0ba2cbe9Sxc151355 } 2340*0ba2cbe9Sxc151355 2341*0ba2cbe9Sxc151355 static void 2342*0ba2cbe9Sxc151355 do_display_wifi(int argc, char **argv, int cmd) 2343*0ba2cbe9Sxc151355 { 2344*0ba2cbe9Sxc151355 int option; 2345*0ba2cbe9Sxc151355 char errmsg[WLADM_STRSIZE]; 2346*0ba2cbe9Sxc151355 char *fields_str = NULL; 2347*0ba2cbe9Sxc151355 wifi_field_t **fields; 2348*0ba2cbe9Sxc151355 boolean_t (*callback)(void *, const char *); 2349*0ba2cbe9Sxc151355 uint_t nfields; 2350*0ba2cbe9Sxc151355 print_wifi_state_t state; 2351*0ba2cbe9Sxc151355 wladm_status_t status; 2352*0ba2cbe9Sxc151355 2353*0ba2cbe9Sxc151355 if (cmd == WIFI_CMD_SCAN) 2354*0ba2cbe9Sxc151355 callback = scan_wifi; 2355*0ba2cbe9Sxc151355 else if (cmd == WIFI_CMD_SHOW) 2356*0ba2cbe9Sxc151355 callback = show_wifi; 2357*0ba2cbe9Sxc151355 else 2358*0ba2cbe9Sxc151355 return; 2359*0ba2cbe9Sxc151355 2360*0ba2cbe9Sxc151355 state.ws_link = NULL; 2361*0ba2cbe9Sxc151355 state.ws_parseable = B_FALSE; 2362*0ba2cbe9Sxc151355 state.ws_header = B_TRUE; 2363*0ba2cbe9Sxc151355 opterr = 0; 2364*0ba2cbe9Sxc151355 while ((option = getopt_long(argc, argv, ":o:p", 2365*0ba2cbe9Sxc151355 wifi_longopts, NULL)) != -1) { 2366*0ba2cbe9Sxc151355 switch (option) { 2367*0ba2cbe9Sxc151355 case 'o': 2368*0ba2cbe9Sxc151355 fields_str = optarg; 2369*0ba2cbe9Sxc151355 break; 2370*0ba2cbe9Sxc151355 case 'p': 2371*0ba2cbe9Sxc151355 state.ws_parseable = B_TRUE; 2372*0ba2cbe9Sxc151355 if (fields_str == NULL) 2373*0ba2cbe9Sxc151355 fields_str = "all"; 2374*0ba2cbe9Sxc151355 break; 2375*0ba2cbe9Sxc151355 case ':': 2376*0ba2cbe9Sxc151355 (void) fprintf(stderr, 2377*0ba2cbe9Sxc151355 gettext("%s: option requires a value '-%c'\n"), 2378*0ba2cbe9Sxc151355 progname, optopt); 2379*0ba2cbe9Sxc151355 exit(1); 2380*0ba2cbe9Sxc151355 break; 2381*0ba2cbe9Sxc151355 case '?': 2382*0ba2cbe9Sxc151355 default: 2383*0ba2cbe9Sxc151355 (void) fprintf(stderr, 2384*0ba2cbe9Sxc151355 gettext("%s: unrecognized option '-%c'\n"), 2385*0ba2cbe9Sxc151355 progname, optopt); 2386*0ba2cbe9Sxc151355 exit(1); 2387*0ba2cbe9Sxc151355 break; 2388*0ba2cbe9Sxc151355 } 2389*0ba2cbe9Sxc151355 } 2390*0ba2cbe9Sxc151355 2391*0ba2cbe9Sxc151355 if (optind == (argc - 1)) 2392*0ba2cbe9Sxc151355 state.ws_link = argv[optind]; 2393*0ba2cbe9Sxc151355 else if (optind != argc) 2394*0ba2cbe9Sxc151355 usage(); 2395*0ba2cbe9Sxc151355 2396*0ba2cbe9Sxc151355 if (parse_wifi_fields(fields_str, &fields, &nfields, cmd) < 0) { 2397*0ba2cbe9Sxc151355 (void) fprintf(stderr, 2398*0ba2cbe9Sxc151355 gettext("%s: invalid field(s) specified\n"), 2399*0ba2cbe9Sxc151355 progname); 2400*0ba2cbe9Sxc151355 exit(1); 2401*0ba2cbe9Sxc151355 } 2402*0ba2cbe9Sxc151355 state.ws_fields = fields; 2403*0ba2cbe9Sxc151355 state.ws_nfields = nfields; 2404*0ba2cbe9Sxc151355 2405*0ba2cbe9Sxc151355 if (state.ws_link == NULL) { 2406*0ba2cbe9Sxc151355 status = wladm_walk(&state, callback); 2407*0ba2cbe9Sxc151355 if (status != WLADM_STATUS_OK) { 2408*0ba2cbe9Sxc151355 (void) fprintf(stderr, gettext("%s: %s\n"), 2409*0ba2cbe9Sxc151355 progname, wladm_status2str(status, errmsg)); 2410*0ba2cbe9Sxc151355 exit(1); 2411*0ba2cbe9Sxc151355 } 2412*0ba2cbe9Sxc151355 } else { 2413*0ba2cbe9Sxc151355 (void) (*callback)(&state, state.ws_link); 2414*0ba2cbe9Sxc151355 } 2415*0ba2cbe9Sxc151355 free(fields); 2416*0ba2cbe9Sxc151355 } 2417*0ba2cbe9Sxc151355 2418*0ba2cbe9Sxc151355 static void 2419*0ba2cbe9Sxc151355 do_scan_wifi(int argc, char **argv) 2420*0ba2cbe9Sxc151355 { 2421*0ba2cbe9Sxc151355 do_display_wifi(argc, argv, WIFI_CMD_SCAN); 2422*0ba2cbe9Sxc151355 } 2423*0ba2cbe9Sxc151355 2424*0ba2cbe9Sxc151355 static void 2425*0ba2cbe9Sxc151355 do_show_wifi(int argc, char **argv) 2426*0ba2cbe9Sxc151355 { 2427*0ba2cbe9Sxc151355 do_display_wifi(argc, argv, WIFI_CMD_SHOW); 2428*0ba2cbe9Sxc151355 } 2429*0ba2cbe9Sxc151355 2430*0ba2cbe9Sxc151355 typedef struct wlan_count_attr { 2431*0ba2cbe9Sxc151355 uint_t wc_count; 2432*0ba2cbe9Sxc151355 const char *wc_link; 2433*0ba2cbe9Sxc151355 } wlan_count_attr_t; 2434*0ba2cbe9Sxc151355 2435*0ba2cbe9Sxc151355 static boolean_t 2436*0ba2cbe9Sxc151355 do_count_wlan(void *arg, const char *link) 2437*0ba2cbe9Sxc151355 { 2438*0ba2cbe9Sxc151355 wlan_count_attr_t *cp = (wlan_count_attr_t *)arg; 2439*0ba2cbe9Sxc151355 2440*0ba2cbe9Sxc151355 if (cp->wc_count == 0) 2441*0ba2cbe9Sxc151355 cp->wc_link = strdup(link); 2442*0ba2cbe9Sxc151355 cp->wc_count++; 2443*0ba2cbe9Sxc151355 return (B_TRUE); 2444*0ba2cbe9Sxc151355 } 2445*0ba2cbe9Sxc151355 2446*0ba2cbe9Sxc151355 static int 2447*0ba2cbe9Sxc151355 parse_wep_keys(char *str, wladm_wep_key_t **keys, uint_t *key_countp) 2448*0ba2cbe9Sxc151355 { 2449*0ba2cbe9Sxc151355 uint_t i; 2450*0ba2cbe9Sxc151355 split_t *sp; 2451*0ba2cbe9Sxc151355 wladm_wep_key_t *wk; 2452*0ba2cbe9Sxc151355 2453*0ba2cbe9Sxc151355 sp = split(str, WLADM_MAX_WEPKEYS, WLADM_MAX_WEPKEYNAME_LEN); 2454*0ba2cbe9Sxc151355 if (sp == NULL) 2455*0ba2cbe9Sxc151355 return (-1); 2456*0ba2cbe9Sxc151355 2457*0ba2cbe9Sxc151355 wk = malloc(sp->s_nfields * sizeof (wladm_wep_key_t)); 2458*0ba2cbe9Sxc151355 if (wk == NULL) 2459*0ba2cbe9Sxc151355 goto fail; 2460*0ba2cbe9Sxc151355 2461*0ba2cbe9Sxc151355 for (i = 0; i < sp->s_nfields; i++) { 2462*0ba2cbe9Sxc151355 char *s; 2463*0ba2cbe9Sxc151355 dladm_secobj_class_t class; 2464*0ba2cbe9Sxc151355 dladm_status_t status; 2465*0ba2cbe9Sxc151355 2466*0ba2cbe9Sxc151355 (void) strlcpy(wk[i].wk_name, sp->s_fields[i], 2467*0ba2cbe9Sxc151355 WLADM_MAX_WEPKEYNAME_LEN); 2468*0ba2cbe9Sxc151355 2469*0ba2cbe9Sxc151355 wk[i].wk_idx = 1; 2470*0ba2cbe9Sxc151355 if ((s = strrchr(wk[i].wk_name, ':')) != NULL) { 2471*0ba2cbe9Sxc151355 if (s[1] == '\0' || s[2] != '\0' || !isdigit(s[1])) 2472*0ba2cbe9Sxc151355 goto fail; 2473*0ba2cbe9Sxc151355 2474*0ba2cbe9Sxc151355 wk[i].wk_idx = (uint_t)(s[1] - '0'); 2475*0ba2cbe9Sxc151355 *s = '\0'; 2476*0ba2cbe9Sxc151355 } 2477*0ba2cbe9Sxc151355 wk[i].wk_len = WLADM_MAX_WEPKEY_LEN; 2478*0ba2cbe9Sxc151355 2479*0ba2cbe9Sxc151355 status = dladm_get_secobj(wk[i].wk_name, &class, 2480*0ba2cbe9Sxc151355 wk[i].wk_val, &wk[i].wk_len, 0); 2481*0ba2cbe9Sxc151355 if (status != DLADM_STATUS_OK) { 2482*0ba2cbe9Sxc151355 if (status == DLADM_STATUS_NOTFOUND) { 2483*0ba2cbe9Sxc151355 status = dladm_get_secobj(wk[i].wk_name, 2484*0ba2cbe9Sxc151355 &class, wk[i].wk_val, &wk[i].wk_len, 2485*0ba2cbe9Sxc151355 DLADM_OPT_PERSIST); 2486*0ba2cbe9Sxc151355 } 2487*0ba2cbe9Sxc151355 if (status != DLADM_STATUS_OK) 2488*0ba2cbe9Sxc151355 goto fail; 2489*0ba2cbe9Sxc151355 } 2490*0ba2cbe9Sxc151355 } 2491*0ba2cbe9Sxc151355 *keys = wk; 2492*0ba2cbe9Sxc151355 *key_countp = i; 2493*0ba2cbe9Sxc151355 splitfree(sp); 2494*0ba2cbe9Sxc151355 return (0); 2495*0ba2cbe9Sxc151355 fail: 2496*0ba2cbe9Sxc151355 free(wk); 2497*0ba2cbe9Sxc151355 splitfree(sp); 2498*0ba2cbe9Sxc151355 return (-1); 2499*0ba2cbe9Sxc151355 } 2500*0ba2cbe9Sxc151355 2501*0ba2cbe9Sxc151355 static void 2502*0ba2cbe9Sxc151355 do_connect_wifi(int argc, char **argv) 2503*0ba2cbe9Sxc151355 { 2504*0ba2cbe9Sxc151355 int option; 2505*0ba2cbe9Sxc151355 wladm_wlan_attr_t attr, *attrp; 2506*0ba2cbe9Sxc151355 wladm_status_t status = WLADM_STATUS_OK; 2507*0ba2cbe9Sxc151355 int timeout = WLADM_CONNECT_TIMEOUT_DEFAULT; 2508*0ba2cbe9Sxc151355 char errmsg[WLADM_STRSIZE]; 2509*0ba2cbe9Sxc151355 const char *link = NULL; 2510*0ba2cbe9Sxc151355 char *endp = NULL; 2511*0ba2cbe9Sxc151355 wladm_wep_key_t *keys = NULL; 2512*0ba2cbe9Sxc151355 uint_t key_count = 0; 2513*0ba2cbe9Sxc151355 uint_t flags = 0; 2514*0ba2cbe9Sxc151355 wladm_secmode_t keysecmode = WLADM_SECMODE_NONE; 2515*0ba2cbe9Sxc151355 2516*0ba2cbe9Sxc151355 opterr = 0; 2517*0ba2cbe9Sxc151355 (void) memset(&attr, 0, sizeof (attr)); 2518*0ba2cbe9Sxc151355 while ((option = getopt_long(argc, argv, ":e:i:a:m:b:s:k:T:c", 2519*0ba2cbe9Sxc151355 wifi_longopts, NULL)) != -1) { 2520*0ba2cbe9Sxc151355 switch (option) { 2521*0ba2cbe9Sxc151355 case 'e': 2522*0ba2cbe9Sxc151355 status = wladm_str2essid(optarg, &attr.wa_essid); 2523*0ba2cbe9Sxc151355 if (status != WLADM_STATUS_OK) { 2524*0ba2cbe9Sxc151355 (void) fprintf(stderr, 2525*0ba2cbe9Sxc151355 gettext("%s: invalid ESSID '%s'\n"), 2526*0ba2cbe9Sxc151355 progname, optarg); 2527*0ba2cbe9Sxc151355 exit(1); 2528*0ba2cbe9Sxc151355 } 2529*0ba2cbe9Sxc151355 attr.wa_valid |= WLADM_WLAN_ATTR_ESSID; 2530*0ba2cbe9Sxc151355 /* 2531*0ba2cbe9Sxc151355 * Try to connect without doing a scan. 2532*0ba2cbe9Sxc151355 */ 2533*0ba2cbe9Sxc151355 flags |= WLADM_OPT_NOSCAN; 2534*0ba2cbe9Sxc151355 break; 2535*0ba2cbe9Sxc151355 case 'i': 2536*0ba2cbe9Sxc151355 status = wladm_str2bssid(optarg, &attr.wa_bssid); 2537*0ba2cbe9Sxc151355 if (status != WLADM_STATUS_OK) { 2538*0ba2cbe9Sxc151355 (void) fprintf(stderr, 2539*0ba2cbe9Sxc151355 gettext("%s: invalid BSSID %s\n"), 2540*0ba2cbe9Sxc151355 progname, optarg); 2541*0ba2cbe9Sxc151355 exit(1); 2542*0ba2cbe9Sxc151355 } 2543*0ba2cbe9Sxc151355 attr.wa_valid |= WLADM_WLAN_ATTR_BSSID; 2544*0ba2cbe9Sxc151355 break; 2545*0ba2cbe9Sxc151355 case 'a': 2546*0ba2cbe9Sxc151355 status = wladm_str2auth(optarg, &attr.wa_auth); 2547*0ba2cbe9Sxc151355 if (status != WLADM_STATUS_OK) { 2548*0ba2cbe9Sxc151355 (void) fprintf(stderr, 2549*0ba2cbe9Sxc151355 gettext("%s: invalid authentication " 2550*0ba2cbe9Sxc151355 "mode '%s'\n"), progname, optarg); 2551*0ba2cbe9Sxc151355 exit(1); 2552*0ba2cbe9Sxc151355 } 2553*0ba2cbe9Sxc151355 attr.wa_valid |= WLADM_WLAN_ATTR_AUTH; 2554*0ba2cbe9Sxc151355 break; 2555*0ba2cbe9Sxc151355 case 'm': 2556*0ba2cbe9Sxc151355 status = wladm_str2mode(optarg, &attr.wa_mode); 2557*0ba2cbe9Sxc151355 if (status != WLADM_STATUS_OK) { 2558*0ba2cbe9Sxc151355 (void) fprintf(stderr, 2559*0ba2cbe9Sxc151355 gettext("%s: invalid mode '%s'\n"), 2560*0ba2cbe9Sxc151355 progname, optarg); 2561*0ba2cbe9Sxc151355 exit(1); 2562*0ba2cbe9Sxc151355 } 2563*0ba2cbe9Sxc151355 attr.wa_valid |= WLADM_WLAN_ATTR_MODE; 2564*0ba2cbe9Sxc151355 break; 2565*0ba2cbe9Sxc151355 case 'b': 2566*0ba2cbe9Sxc151355 status = wladm_str2bsstype(optarg, &attr.wa_bsstype); 2567*0ba2cbe9Sxc151355 if (status != WLADM_STATUS_OK) { 2568*0ba2cbe9Sxc151355 (void) fprintf(stderr, 2569*0ba2cbe9Sxc151355 gettext("%s: invalid bsstype '%s'\n"), 2570*0ba2cbe9Sxc151355 progname, optarg); 2571*0ba2cbe9Sxc151355 exit(1); 2572*0ba2cbe9Sxc151355 } 2573*0ba2cbe9Sxc151355 attr.wa_valid |= WLADM_WLAN_ATTR_BSSTYPE; 2574*0ba2cbe9Sxc151355 break; 2575*0ba2cbe9Sxc151355 case 's': 2576*0ba2cbe9Sxc151355 status = wladm_str2secmode(optarg, &attr.wa_secmode); 2577*0ba2cbe9Sxc151355 if (status != WLADM_STATUS_OK) { 2578*0ba2cbe9Sxc151355 (void) fprintf(stderr, 2579*0ba2cbe9Sxc151355 gettext("%s: invalid security mode '%s'\n"), 2580*0ba2cbe9Sxc151355 progname, optarg); 2581*0ba2cbe9Sxc151355 exit(1); 2582*0ba2cbe9Sxc151355 } 2583*0ba2cbe9Sxc151355 attr.wa_valid |= WLADM_WLAN_ATTR_SECMODE; 2584*0ba2cbe9Sxc151355 break; 2585*0ba2cbe9Sxc151355 case 'k': 2586*0ba2cbe9Sxc151355 if (parse_wep_keys(optarg, &keys, &key_count) < 0) { 2587*0ba2cbe9Sxc151355 (void) fprintf(stderr, 2588*0ba2cbe9Sxc151355 gettext("%s: invalid key(s) '%s'\n"), 2589*0ba2cbe9Sxc151355 progname, optarg); 2590*0ba2cbe9Sxc151355 exit(1); 2591*0ba2cbe9Sxc151355 } 2592*0ba2cbe9Sxc151355 keysecmode = WLADM_SECMODE_WEP; 2593*0ba2cbe9Sxc151355 break; 2594*0ba2cbe9Sxc151355 case 'T': 2595*0ba2cbe9Sxc151355 if (strcasecmp(optarg, "forever") == 0) { 2596*0ba2cbe9Sxc151355 timeout = -1; 2597*0ba2cbe9Sxc151355 break; 2598*0ba2cbe9Sxc151355 } 2599*0ba2cbe9Sxc151355 errno = 0; 2600*0ba2cbe9Sxc151355 timeout = (int)strtol(optarg, &endp, 10); 2601*0ba2cbe9Sxc151355 if (timeout < 0 || errno != 0 || *endp != '\0') { 2602*0ba2cbe9Sxc151355 (void) fprintf(stderr, 2603*0ba2cbe9Sxc151355 gettext("%s: invalid timeout value '%s'\n"), 2604*0ba2cbe9Sxc151355 progname, optarg); 2605*0ba2cbe9Sxc151355 exit(1); 2606*0ba2cbe9Sxc151355 } 2607*0ba2cbe9Sxc151355 break; 2608*0ba2cbe9Sxc151355 case 'c': 2609*0ba2cbe9Sxc151355 flags |= WLADM_OPT_CREATEIBSS; 2610*0ba2cbe9Sxc151355 break; 2611*0ba2cbe9Sxc151355 case ':': 2612*0ba2cbe9Sxc151355 (void) fprintf(stderr, 2613*0ba2cbe9Sxc151355 gettext("%s: option requires a value '-%c'\n"), 2614*0ba2cbe9Sxc151355 progname, optopt); 2615*0ba2cbe9Sxc151355 exit(1); 2616*0ba2cbe9Sxc151355 break; 2617*0ba2cbe9Sxc151355 case '?': 2618*0ba2cbe9Sxc151355 default: 2619*0ba2cbe9Sxc151355 (void) fprintf(stderr, 2620*0ba2cbe9Sxc151355 gettext("%s: unrecognized option '-%c'\n"), 2621*0ba2cbe9Sxc151355 progname, optopt); 2622*0ba2cbe9Sxc151355 exit(1); 2623*0ba2cbe9Sxc151355 break; 2624*0ba2cbe9Sxc151355 } 2625*0ba2cbe9Sxc151355 } 2626*0ba2cbe9Sxc151355 2627*0ba2cbe9Sxc151355 if (keysecmode == WLADM_SECMODE_NONE) { 2628*0ba2cbe9Sxc151355 if ((attr.wa_valid & WLADM_WLAN_ATTR_SECMODE) != 0 && 2629*0ba2cbe9Sxc151355 attr.wa_secmode == WLADM_SECMODE_WEP) { 2630*0ba2cbe9Sxc151355 (void) fprintf(stderr, 2631*0ba2cbe9Sxc151355 gettext("%s: key required for security mode " 2632*0ba2cbe9Sxc151355 "'wep'\n"), progname); 2633*0ba2cbe9Sxc151355 exit(1); 2634*0ba2cbe9Sxc151355 } 2635*0ba2cbe9Sxc151355 } else { 2636*0ba2cbe9Sxc151355 if ((attr.wa_valid & WLADM_WLAN_ATTR_SECMODE) != 0 && 2637*0ba2cbe9Sxc151355 attr.wa_secmode != keysecmode) { 2638*0ba2cbe9Sxc151355 (void) fprintf(stderr, 2639*0ba2cbe9Sxc151355 gettext("%s: incompatible -s and -k options\n"), 2640*0ba2cbe9Sxc151355 progname); 2641*0ba2cbe9Sxc151355 exit(1); 2642*0ba2cbe9Sxc151355 } 2643*0ba2cbe9Sxc151355 } 2644*0ba2cbe9Sxc151355 attr.wa_secmode = keysecmode; 2645*0ba2cbe9Sxc151355 attr.wa_valid |= WLADM_WLAN_ATTR_SECMODE; 2646*0ba2cbe9Sxc151355 2647*0ba2cbe9Sxc151355 if (optind == (argc - 1)) 2648*0ba2cbe9Sxc151355 link = argv[optind]; 2649*0ba2cbe9Sxc151355 else if (optind != argc) 2650*0ba2cbe9Sxc151355 usage(); 2651*0ba2cbe9Sxc151355 2652*0ba2cbe9Sxc151355 if (link == NULL) { 2653*0ba2cbe9Sxc151355 wlan_count_attr_t wcattr; 2654*0ba2cbe9Sxc151355 2655*0ba2cbe9Sxc151355 wcattr.wc_link = NULL; 2656*0ba2cbe9Sxc151355 wcattr.wc_count = 0; 2657*0ba2cbe9Sxc151355 (void) wladm_walk(&wcattr, do_count_wlan); 2658*0ba2cbe9Sxc151355 if (wcattr.wc_count == 0) { 2659*0ba2cbe9Sxc151355 (void) fprintf(stderr, gettext( 2660*0ba2cbe9Sxc151355 "%s: no wifi links are available\n"), progname); 2661*0ba2cbe9Sxc151355 exit(1); 2662*0ba2cbe9Sxc151355 } else if (wcattr.wc_count > 1) { 2663*0ba2cbe9Sxc151355 (void) fprintf(stderr, gettext( 2664*0ba2cbe9Sxc151355 "%s: link name is required when more than " 2665*0ba2cbe9Sxc151355 "one link is available\n"), progname); 2666*0ba2cbe9Sxc151355 exit(1); 2667*0ba2cbe9Sxc151355 } 2668*0ba2cbe9Sxc151355 link = wcattr.wc_link; 2669*0ba2cbe9Sxc151355 } 2670*0ba2cbe9Sxc151355 attrp = (attr.wa_valid == 0) ? NULL : &attr; 2671*0ba2cbe9Sxc151355 2672*0ba2cbe9Sxc151355 status = wladm_connect(link, attrp, timeout, keys, key_count, flags); 2673*0ba2cbe9Sxc151355 if (status != WLADM_STATUS_OK) { 2674*0ba2cbe9Sxc151355 if ((flags & WLADM_OPT_NOSCAN) != 0) { 2675*0ba2cbe9Sxc151355 /* 2676*0ba2cbe9Sxc151355 * Redo the connect. This time with scanning 2677*0ba2cbe9Sxc151355 * and filtering. 2678*0ba2cbe9Sxc151355 */ 2679*0ba2cbe9Sxc151355 flags &= ~WLADM_OPT_NOSCAN; 2680*0ba2cbe9Sxc151355 status = wladm_connect(link, attrp, timeout, keys, 2681*0ba2cbe9Sxc151355 key_count, flags); 2682*0ba2cbe9Sxc151355 if (status == WLADM_STATUS_OK) { 2683*0ba2cbe9Sxc151355 free(keys); 2684*0ba2cbe9Sxc151355 return; 2685*0ba2cbe9Sxc151355 } 2686*0ba2cbe9Sxc151355 } 2687*0ba2cbe9Sxc151355 if (status == WLADM_STATUS_NOTFOUND) { 2688*0ba2cbe9Sxc151355 if (attr.wa_valid == 0) { 2689*0ba2cbe9Sxc151355 (void) fprintf(stderr, gettext( 2690*0ba2cbe9Sxc151355 "%s: no wifi networks are available\n"), 2691*0ba2cbe9Sxc151355 progname); 2692*0ba2cbe9Sxc151355 } else { 2693*0ba2cbe9Sxc151355 (void) fprintf(stderr, gettext("%s: no wifi " 2694*0ba2cbe9Sxc151355 "networks with the specified criteria " 2695*0ba2cbe9Sxc151355 "are available\n"), progname); 2696*0ba2cbe9Sxc151355 } 2697*0ba2cbe9Sxc151355 } else { 2698*0ba2cbe9Sxc151355 (void) fprintf(stderr, gettext("%s: cannot connect: %s" 2699*0ba2cbe9Sxc151355 "\n"), progname, wladm_status2str(status, errmsg)); 2700*0ba2cbe9Sxc151355 } 2701*0ba2cbe9Sxc151355 exit(1); 2702*0ba2cbe9Sxc151355 } 2703*0ba2cbe9Sxc151355 free(keys); 2704*0ba2cbe9Sxc151355 } 2705*0ba2cbe9Sxc151355 2706*0ba2cbe9Sxc151355 /* ARGSUSED */ 2707*0ba2cbe9Sxc151355 static boolean_t 2708*0ba2cbe9Sxc151355 do_all_disconnect_wifi(void *arg, const char *link) 2709*0ba2cbe9Sxc151355 { 2710*0ba2cbe9Sxc151355 wladm_status_t status; 2711*0ba2cbe9Sxc151355 char errmsg[WLADM_STRSIZE]; 2712*0ba2cbe9Sxc151355 2713*0ba2cbe9Sxc151355 status = wladm_disconnect(link); 2714*0ba2cbe9Sxc151355 if (status != WLADM_STATUS_OK) { 2715*0ba2cbe9Sxc151355 (void) fprintf(stderr, 2716*0ba2cbe9Sxc151355 gettext("%s: cannot disconnect link '%s': %s\n"), 2717*0ba2cbe9Sxc151355 progname, link, wladm_status2str(status, errmsg)); 2718*0ba2cbe9Sxc151355 } 2719*0ba2cbe9Sxc151355 return (B_TRUE); 2720*0ba2cbe9Sxc151355 } 2721*0ba2cbe9Sxc151355 2722*0ba2cbe9Sxc151355 static void 2723*0ba2cbe9Sxc151355 do_disconnect_wifi(int argc, char **argv) 2724*0ba2cbe9Sxc151355 { 2725*0ba2cbe9Sxc151355 int option; 2726*0ba2cbe9Sxc151355 const char *link = NULL; 2727*0ba2cbe9Sxc151355 char errmsg[WLADM_STRSIZE]; 2728*0ba2cbe9Sxc151355 boolean_t all_links = B_FALSE; 2729*0ba2cbe9Sxc151355 wladm_status_t status; 2730*0ba2cbe9Sxc151355 wlan_count_attr_t wcattr; 2731*0ba2cbe9Sxc151355 2732*0ba2cbe9Sxc151355 opterr = 0; 2733*0ba2cbe9Sxc151355 while ((option = getopt_long(argc, argv, ":a", 2734*0ba2cbe9Sxc151355 wifi_longopts, NULL)) != -1) { 2735*0ba2cbe9Sxc151355 switch (option) { 2736*0ba2cbe9Sxc151355 case 'a': 2737*0ba2cbe9Sxc151355 all_links = B_TRUE; 2738*0ba2cbe9Sxc151355 break; 2739*0ba2cbe9Sxc151355 case ':': 2740*0ba2cbe9Sxc151355 (void) fprintf(stderr, 2741*0ba2cbe9Sxc151355 gettext("%s: option requires a value '-%c'\n"), 2742*0ba2cbe9Sxc151355 progname, optopt); 2743*0ba2cbe9Sxc151355 exit(1); 2744*0ba2cbe9Sxc151355 break; 2745*0ba2cbe9Sxc151355 case '?': 2746*0ba2cbe9Sxc151355 default: 2747*0ba2cbe9Sxc151355 (void) fprintf(stderr, 2748*0ba2cbe9Sxc151355 gettext("%s: unrecognized option '-%c'\n"), 2749*0ba2cbe9Sxc151355 progname, optopt); 2750*0ba2cbe9Sxc151355 exit(1); 2751*0ba2cbe9Sxc151355 break; 2752*0ba2cbe9Sxc151355 } 2753*0ba2cbe9Sxc151355 } 2754*0ba2cbe9Sxc151355 2755*0ba2cbe9Sxc151355 if (optind == (argc - 1)) 2756*0ba2cbe9Sxc151355 link = argv[optind]; 2757*0ba2cbe9Sxc151355 else if (optind != argc) 2758*0ba2cbe9Sxc151355 usage(); 2759*0ba2cbe9Sxc151355 2760*0ba2cbe9Sxc151355 if (link == NULL) { 2761*0ba2cbe9Sxc151355 if (!all_links) { 2762*0ba2cbe9Sxc151355 wcattr.wc_link = NULL; 2763*0ba2cbe9Sxc151355 wcattr.wc_count = 0; 2764*0ba2cbe9Sxc151355 (void) wladm_walk(&wcattr, do_count_wlan); 2765*0ba2cbe9Sxc151355 if (wcattr.wc_count == 0) { 2766*0ba2cbe9Sxc151355 (void) fprintf(stderr, gettext( 2767*0ba2cbe9Sxc151355 "%s: no wifi links are available\n"), 2768*0ba2cbe9Sxc151355 progname); 2769*0ba2cbe9Sxc151355 exit(1); 2770*0ba2cbe9Sxc151355 } else if (wcattr.wc_count > 1) { 2771*0ba2cbe9Sxc151355 (void) fprintf(stderr, gettext( 2772*0ba2cbe9Sxc151355 "%s: link name is required when more than " 2773*0ba2cbe9Sxc151355 "one link is available\n"), progname); 2774*0ba2cbe9Sxc151355 exit(1); 2775*0ba2cbe9Sxc151355 } 2776*0ba2cbe9Sxc151355 link = wcattr.wc_link; 2777*0ba2cbe9Sxc151355 } else { 2778*0ba2cbe9Sxc151355 (void) wladm_walk(&all_links, do_all_disconnect_wifi); 2779*0ba2cbe9Sxc151355 return; 2780*0ba2cbe9Sxc151355 } 2781*0ba2cbe9Sxc151355 } 2782*0ba2cbe9Sxc151355 status = wladm_disconnect(link); 2783*0ba2cbe9Sxc151355 if (status != WLADM_STATUS_OK) { 2784*0ba2cbe9Sxc151355 (void) fprintf(stderr, gettext("%s: cannot disconnect: %s\n"), 2785*0ba2cbe9Sxc151355 progname, wladm_status2str(status, errmsg)); 2786*0ba2cbe9Sxc151355 exit(1); 2787*0ba2cbe9Sxc151355 } 2788*0ba2cbe9Sxc151355 } 2789*0ba2cbe9Sxc151355 2790*0ba2cbe9Sxc151355 #define MAX_PROPS 32 2791*0ba2cbe9Sxc151355 #define MAX_PROP_VALS 32 2792*0ba2cbe9Sxc151355 #define MAX_PROP_LINE 512 2793*0ba2cbe9Sxc151355 2794*0ba2cbe9Sxc151355 typedef struct prop_info { 2795*0ba2cbe9Sxc151355 char *pi_name; 2796*0ba2cbe9Sxc151355 char *pi_val[MAX_PROP_VALS]; 2797*0ba2cbe9Sxc151355 uint_t pi_count; 2798*0ba2cbe9Sxc151355 } prop_info_t; 2799*0ba2cbe9Sxc151355 2800*0ba2cbe9Sxc151355 typedef struct prop_list { 2801*0ba2cbe9Sxc151355 prop_info_t pl_info[MAX_PROPS]; 2802*0ba2cbe9Sxc151355 uint_t pl_count; 2803*0ba2cbe9Sxc151355 char *pl_buf; 2804*0ba2cbe9Sxc151355 } prop_list_t; 2805*0ba2cbe9Sxc151355 2806*0ba2cbe9Sxc151355 typedef struct show_linkprop_state { 2807*0ba2cbe9Sxc151355 const char *ls_link; 2808*0ba2cbe9Sxc151355 char *ls_line; 2809*0ba2cbe9Sxc151355 char **ls_propvals; 2810*0ba2cbe9Sxc151355 boolean_t ls_parseable; 2811*0ba2cbe9Sxc151355 boolean_t ls_persist; 2812*0ba2cbe9Sxc151355 boolean_t ls_header; 2813*0ba2cbe9Sxc151355 } show_linkprop_state_t; 2814*0ba2cbe9Sxc151355 2815*0ba2cbe9Sxc151355 static void 2816*0ba2cbe9Sxc151355 free_props(prop_list_t *list) 2817*0ba2cbe9Sxc151355 { 2818*0ba2cbe9Sxc151355 if (list != NULL) { 2819*0ba2cbe9Sxc151355 free(list->pl_buf); 2820*0ba2cbe9Sxc151355 free(list); 2821*0ba2cbe9Sxc151355 } 2822*0ba2cbe9Sxc151355 } 2823*0ba2cbe9Sxc151355 2824*0ba2cbe9Sxc151355 static int 2825*0ba2cbe9Sxc151355 parse_props(char *str, prop_list_t **listp, boolean_t novalues) 2826*0ba2cbe9Sxc151355 { 2827*0ba2cbe9Sxc151355 prop_list_t *list; 2828*0ba2cbe9Sxc151355 prop_info_t *pip; 2829*0ba2cbe9Sxc151355 char *buf, *curr; 2830*0ba2cbe9Sxc151355 int len, i; 2831*0ba2cbe9Sxc151355 2832*0ba2cbe9Sxc151355 list = malloc(sizeof (prop_list_t)); 2833*0ba2cbe9Sxc151355 if (list == NULL) 2834*0ba2cbe9Sxc151355 return (-1); 2835*0ba2cbe9Sxc151355 2836*0ba2cbe9Sxc151355 list->pl_count = 0; 2837*0ba2cbe9Sxc151355 list->pl_buf = buf = strdup(str); 2838*0ba2cbe9Sxc151355 if (buf == NULL) 2839*0ba2cbe9Sxc151355 goto fail; 2840*0ba2cbe9Sxc151355 2841*0ba2cbe9Sxc151355 curr = buf; 2842*0ba2cbe9Sxc151355 len = strlen(buf); 2843*0ba2cbe9Sxc151355 pip = NULL; 2844*0ba2cbe9Sxc151355 for (i = 0; i < len; i++) { 2845*0ba2cbe9Sxc151355 char c = buf[i]; 2846*0ba2cbe9Sxc151355 boolean_t match = (c == '=' || c == ','); 2847*0ba2cbe9Sxc151355 2848*0ba2cbe9Sxc151355 if (!match && i != len - 1) 2849*0ba2cbe9Sxc151355 continue; 2850*0ba2cbe9Sxc151355 2851*0ba2cbe9Sxc151355 if (match) { 2852*0ba2cbe9Sxc151355 buf[i] = '\0'; 2853*0ba2cbe9Sxc151355 if (*curr == '\0') 2854*0ba2cbe9Sxc151355 goto fail; 2855*0ba2cbe9Sxc151355 } 2856*0ba2cbe9Sxc151355 2857*0ba2cbe9Sxc151355 if (pip != NULL && c != '=') { 2858*0ba2cbe9Sxc151355 if (pip->pi_count > MAX_PROP_VALS) 2859*0ba2cbe9Sxc151355 goto fail; 2860*0ba2cbe9Sxc151355 2861*0ba2cbe9Sxc151355 if (novalues) 2862*0ba2cbe9Sxc151355 goto fail; 2863*0ba2cbe9Sxc151355 2864*0ba2cbe9Sxc151355 pip->pi_val[pip->pi_count] = curr; 2865*0ba2cbe9Sxc151355 pip->pi_count++; 2866*0ba2cbe9Sxc151355 } else { 2867*0ba2cbe9Sxc151355 if (list->pl_count > MAX_PROPS) 2868*0ba2cbe9Sxc151355 goto fail; 2869*0ba2cbe9Sxc151355 2870*0ba2cbe9Sxc151355 pip = &list->pl_info[list->pl_count]; 2871*0ba2cbe9Sxc151355 pip->pi_name = curr; 2872*0ba2cbe9Sxc151355 pip->pi_count = 0; 2873*0ba2cbe9Sxc151355 list->pl_count++; 2874*0ba2cbe9Sxc151355 if (c == ',') 2875*0ba2cbe9Sxc151355 pip = NULL; 2876*0ba2cbe9Sxc151355 } 2877*0ba2cbe9Sxc151355 curr = buf + i + 1; 2878*0ba2cbe9Sxc151355 } 2879*0ba2cbe9Sxc151355 *listp = list; 2880*0ba2cbe9Sxc151355 return (0); 2881*0ba2cbe9Sxc151355 2882*0ba2cbe9Sxc151355 fail: 2883*0ba2cbe9Sxc151355 free_props(list); 2884*0ba2cbe9Sxc151355 return (-1); 2885*0ba2cbe9Sxc151355 } 2886*0ba2cbe9Sxc151355 2887*0ba2cbe9Sxc151355 static void 2888*0ba2cbe9Sxc151355 print_linkprop_head(void) 2889*0ba2cbe9Sxc151355 { 2890*0ba2cbe9Sxc151355 (void) printf("%-15s %-14s %-14s %-30s \n", 2891*0ba2cbe9Sxc151355 "PROPERTY", "VALUE", "DEFAULT", "POSSIBLE"); 2892*0ba2cbe9Sxc151355 } 2893*0ba2cbe9Sxc151355 2894*0ba2cbe9Sxc151355 static void 2895*0ba2cbe9Sxc151355 print_linkprop(show_linkprop_state_t *statep, const char *propname, 2896*0ba2cbe9Sxc151355 dladm_prop_type_t type, const char *typename, const char *format, 2897*0ba2cbe9Sxc151355 char **pptr) 2898*0ba2cbe9Sxc151355 { 2899*0ba2cbe9Sxc151355 int i; 2900*0ba2cbe9Sxc151355 char *ptr, *lim; 2901*0ba2cbe9Sxc151355 char buf[DLADM_STRSIZE]; 2902*0ba2cbe9Sxc151355 char *unknown = "?", *notsup = ""; 2903*0ba2cbe9Sxc151355 char **propvals = statep->ls_propvals; 2904*0ba2cbe9Sxc151355 uint_t valcnt = MAX_PROP_VALS; 2905*0ba2cbe9Sxc151355 dladm_status_t status; 2906*0ba2cbe9Sxc151355 2907*0ba2cbe9Sxc151355 status = dladm_get_prop(statep->ls_link, type, propname, 2908*0ba2cbe9Sxc151355 propvals, &valcnt); 2909*0ba2cbe9Sxc151355 if (status != DLADM_STATUS_OK) { 2910*0ba2cbe9Sxc151355 if (status == DLADM_STATUS_NOTSUP || statep->ls_persist) { 2911*0ba2cbe9Sxc151355 valcnt = 1; 2912*0ba2cbe9Sxc151355 if (type == DLADM_PROP_VAL_CURRENT) 2913*0ba2cbe9Sxc151355 propvals = &unknown; 2914*0ba2cbe9Sxc151355 else 2915*0ba2cbe9Sxc151355 propvals = ¬sup; 2916*0ba2cbe9Sxc151355 } else { 2917*0ba2cbe9Sxc151355 (void) fprintf(stderr, gettext( 2918*0ba2cbe9Sxc151355 "%s: cannot get link property '%s': %s\n"), 2919*0ba2cbe9Sxc151355 progname, propname, dladm_status2str(status, buf)); 2920*0ba2cbe9Sxc151355 exit(1); 2921*0ba2cbe9Sxc151355 } 2922*0ba2cbe9Sxc151355 } 2923*0ba2cbe9Sxc151355 2924*0ba2cbe9Sxc151355 ptr = buf; 2925*0ba2cbe9Sxc151355 lim = buf + DLADM_STRSIZE; 2926*0ba2cbe9Sxc151355 for (i = 0; i < valcnt; i++) { 2927*0ba2cbe9Sxc151355 if (propvals[i][0] == '\0' && !statep->ls_parseable) 2928*0ba2cbe9Sxc151355 ptr += snprintf(ptr, lim - ptr, "--,"); 2929*0ba2cbe9Sxc151355 else 2930*0ba2cbe9Sxc151355 ptr += snprintf(ptr, lim - ptr, "%s,", propvals[i]); 2931*0ba2cbe9Sxc151355 if (ptr >= lim) 2932*0ba2cbe9Sxc151355 break; 2933*0ba2cbe9Sxc151355 } 2934*0ba2cbe9Sxc151355 if (valcnt > 0) 2935*0ba2cbe9Sxc151355 buf[strlen(buf) - 1] = '\0'; 2936*0ba2cbe9Sxc151355 2937*0ba2cbe9Sxc151355 lim = statep->ls_line + MAX_PROP_LINE; 2938*0ba2cbe9Sxc151355 if (statep->ls_parseable) { 2939*0ba2cbe9Sxc151355 *pptr += snprintf(*pptr, lim - *pptr, 2940*0ba2cbe9Sxc151355 "%s=\"%s\" ", typename, buf); 2941*0ba2cbe9Sxc151355 } else { 2942*0ba2cbe9Sxc151355 *pptr += snprintf(*pptr, lim - *pptr, format, buf); 2943*0ba2cbe9Sxc151355 } 2944*0ba2cbe9Sxc151355 } 2945*0ba2cbe9Sxc151355 2946*0ba2cbe9Sxc151355 static boolean_t 2947*0ba2cbe9Sxc151355 show_linkprop(void *arg, const char *propname) 2948*0ba2cbe9Sxc151355 { 2949*0ba2cbe9Sxc151355 show_linkprop_state_t *statep = arg; 2950*0ba2cbe9Sxc151355 char *ptr = statep->ls_line; 2951*0ba2cbe9Sxc151355 char *lim = ptr + MAX_PROP_LINE; 2952*0ba2cbe9Sxc151355 2953*0ba2cbe9Sxc151355 if (statep->ls_parseable) 2954*0ba2cbe9Sxc151355 ptr += snprintf(ptr, lim - ptr, "PROPERTY=\"%s\" ", propname); 2955*0ba2cbe9Sxc151355 else 2956*0ba2cbe9Sxc151355 ptr += snprintf(ptr, lim - ptr, "%-15s ", propname); 2957*0ba2cbe9Sxc151355 2958*0ba2cbe9Sxc151355 print_linkprop(statep, propname, 2959*0ba2cbe9Sxc151355 statep->ls_persist ? DLADM_PROP_VAL_PERSISTENT : 2960*0ba2cbe9Sxc151355 DLADM_PROP_VAL_CURRENT, "VALUE", "%-14s ", &ptr); 2961*0ba2cbe9Sxc151355 print_linkprop(statep, propname, DLADM_PROP_VAL_DEFAULT, 2962*0ba2cbe9Sxc151355 "DEFAULT", "%-14s ", &ptr); 2963*0ba2cbe9Sxc151355 print_linkprop(statep, propname, DLADM_PROP_VAL_MODIFIABLE, 2964*0ba2cbe9Sxc151355 "POSSIBLE", "%-30s ", &ptr); 2965*0ba2cbe9Sxc151355 2966*0ba2cbe9Sxc151355 if (statep->ls_header) { 2967*0ba2cbe9Sxc151355 statep->ls_header = B_FALSE; 2968*0ba2cbe9Sxc151355 if (!statep->ls_parseable) 2969*0ba2cbe9Sxc151355 print_linkprop_head(); 2970*0ba2cbe9Sxc151355 } 2971*0ba2cbe9Sxc151355 (void) printf("%s\n", statep->ls_line); 2972*0ba2cbe9Sxc151355 return (B_TRUE); 2973*0ba2cbe9Sxc151355 } 2974*0ba2cbe9Sxc151355 2975*0ba2cbe9Sxc151355 static void 2976*0ba2cbe9Sxc151355 do_show_linkprop(int argc, char **argv) 2977*0ba2cbe9Sxc151355 { 2978*0ba2cbe9Sxc151355 int i, option, fd; 2979*0ba2cbe9Sxc151355 char errmsg[DLADM_STRSIZE]; 2980*0ba2cbe9Sxc151355 char linkname[MAXPATHLEN]; 2981*0ba2cbe9Sxc151355 prop_list_t *proplist = NULL; 2982*0ba2cbe9Sxc151355 char *buf; 2983*0ba2cbe9Sxc151355 dladm_status_t status; 2984*0ba2cbe9Sxc151355 show_linkprop_state_t state; 2985*0ba2cbe9Sxc151355 2986*0ba2cbe9Sxc151355 opterr = 0; 2987*0ba2cbe9Sxc151355 state.ls_link = NULL; 2988*0ba2cbe9Sxc151355 state.ls_propvals = NULL; 2989*0ba2cbe9Sxc151355 state.ls_line = NULL; 2990*0ba2cbe9Sxc151355 state.ls_parseable = B_FALSE; 2991*0ba2cbe9Sxc151355 state.ls_persist = B_FALSE; 2992*0ba2cbe9Sxc151355 state.ls_header = B_TRUE; 2993*0ba2cbe9Sxc151355 while ((option = getopt_long(argc, argv, ":p:cP", 2994*0ba2cbe9Sxc151355 prop_longopts, NULL)) != -1) { 2995*0ba2cbe9Sxc151355 switch (option) { 2996*0ba2cbe9Sxc151355 case 'p': 2997*0ba2cbe9Sxc151355 if (parse_props(optarg, &proplist, B_TRUE) < 0) { 2998*0ba2cbe9Sxc151355 (void) fprintf(stderr, 2999*0ba2cbe9Sxc151355 gettext("%s: invalid field(s) specified\n"), 3000*0ba2cbe9Sxc151355 progname); 3001*0ba2cbe9Sxc151355 exit(1); 3002*0ba2cbe9Sxc151355 } 3003*0ba2cbe9Sxc151355 break; 3004*0ba2cbe9Sxc151355 case 'c': 3005*0ba2cbe9Sxc151355 state.ls_parseable = B_TRUE; 3006*0ba2cbe9Sxc151355 break; 3007*0ba2cbe9Sxc151355 case 'P': 3008*0ba2cbe9Sxc151355 state.ls_persist = B_TRUE; 3009*0ba2cbe9Sxc151355 break; 3010*0ba2cbe9Sxc151355 case ':': 3011*0ba2cbe9Sxc151355 (void) fprintf(stderr, 3012*0ba2cbe9Sxc151355 gettext("%s: option requires a value '-%c'\n"), 3013*0ba2cbe9Sxc151355 progname, optopt); 3014*0ba2cbe9Sxc151355 exit(1); 3015*0ba2cbe9Sxc151355 break; 3016*0ba2cbe9Sxc151355 case '?': 3017*0ba2cbe9Sxc151355 default: 3018*0ba2cbe9Sxc151355 (void) fprintf(stderr, 3019*0ba2cbe9Sxc151355 gettext("%s: unrecognized option '-%c'\n"), 3020*0ba2cbe9Sxc151355 progname, optopt); 3021*0ba2cbe9Sxc151355 exit(1); 3022*0ba2cbe9Sxc151355 break; 3023*0ba2cbe9Sxc151355 } 3024*0ba2cbe9Sxc151355 } 3025*0ba2cbe9Sxc151355 3026*0ba2cbe9Sxc151355 if (optind == (argc - 1)) 3027*0ba2cbe9Sxc151355 state.ls_link = argv[optind]; 3028*0ba2cbe9Sxc151355 else if (optind != argc) 3029*0ba2cbe9Sxc151355 usage(); 3030*0ba2cbe9Sxc151355 3031*0ba2cbe9Sxc151355 if (state.ls_link == NULL) { 3032*0ba2cbe9Sxc151355 (void) fprintf(stderr, 3033*0ba2cbe9Sxc151355 gettext("%s: link name must be specified\n"), progname); 3034*0ba2cbe9Sxc151355 exit(1); 3035*0ba2cbe9Sxc151355 } 3036*0ba2cbe9Sxc151355 3037*0ba2cbe9Sxc151355 /* 3038*0ba2cbe9Sxc151355 * When some WiFi links are opened for the first time, their hardware 3039*0ba2cbe9Sxc151355 * automatically scans for APs and does other slow operations. Thus, 3040*0ba2cbe9Sxc151355 * if there are no open links, the retrieval of link properties 3041*0ba2cbe9Sxc151355 * (below) will proceed slowly unless we hold the link open. 3042*0ba2cbe9Sxc151355 */ 3043*0ba2cbe9Sxc151355 (void) snprintf(linkname, MAXPATHLEN, "/dev/%s", state.ls_link); 3044*0ba2cbe9Sxc151355 if ((fd = open(linkname, O_RDWR)) < 0) { 3045*0ba2cbe9Sxc151355 (void) fprintf(stderr, 3046*0ba2cbe9Sxc151355 gettext("%s: cannot open %s\n"), progname, state.ls_link); 3047*0ba2cbe9Sxc151355 exit(1); 3048*0ba2cbe9Sxc151355 } 3049*0ba2cbe9Sxc151355 3050*0ba2cbe9Sxc151355 buf = malloc((sizeof (char *) + DLADM_PROP_VAL_MAX) * MAX_PROP_VALS + 3051*0ba2cbe9Sxc151355 MAX_PROP_LINE); 3052*0ba2cbe9Sxc151355 if (buf == NULL) { 3053*0ba2cbe9Sxc151355 (void) fprintf(stderr, 3054*0ba2cbe9Sxc151355 gettext("%s: insufficient memory\n"), progname); 3055*0ba2cbe9Sxc151355 exit(1); 3056*0ba2cbe9Sxc151355 } 3057*0ba2cbe9Sxc151355 state.ls_propvals = (char **)(void *)buf; 3058*0ba2cbe9Sxc151355 for (i = 0; i < MAX_PROP_VALS; i++) { 3059*0ba2cbe9Sxc151355 state.ls_propvals[i] = buf + sizeof (char *) * MAX_PROP_VALS + 3060*0ba2cbe9Sxc151355 i * DLADM_PROP_VAL_MAX; 3061*0ba2cbe9Sxc151355 } 3062*0ba2cbe9Sxc151355 state.ls_line = buf + 3063*0ba2cbe9Sxc151355 (sizeof (char *) + DLADM_PROP_VAL_MAX) * MAX_PROP_VALS; 3064*0ba2cbe9Sxc151355 3065*0ba2cbe9Sxc151355 if (proplist != NULL) { 3066*0ba2cbe9Sxc151355 for (i = 0; i < proplist->pl_count; i++) { 3067*0ba2cbe9Sxc151355 if (!show_linkprop(&state, 3068*0ba2cbe9Sxc151355 proplist->pl_info[i].pi_name)) 3069*0ba2cbe9Sxc151355 break; 3070*0ba2cbe9Sxc151355 } 3071*0ba2cbe9Sxc151355 } else { 3072*0ba2cbe9Sxc151355 status = dladm_walk_prop(state.ls_link, &state, show_linkprop); 3073*0ba2cbe9Sxc151355 if (status != DLADM_STATUS_OK) { 3074*0ba2cbe9Sxc151355 (void) fprintf(stderr, 3075*0ba2cbe9Sxc151355 gettext("%s: show-linkprop: %s\n"), progname, 3076*0ba2cbe9Sxc151355 dladm_status2str(status, errmsg)); 3077*0ba2cbe9Sxc151355 exit(1); 3078*0ba2cbe9Sxc151355 } 3079*0ba2cbe9Sxc151355 } 3080*0ba2cbe9Sxc151355 (void) close(fd); 3081*0ba2cbe9Sxc151355 free(buf); 3082*0ba2cbe9Sxc151355 free_props(proplist); 3083*0ba2cbe9Sxc151355 } 3084*0ba2cbe9Sxc151355 3085*0ba2cbe9Sxc151355 static dladm_status_t 3086*0ba2cbe9Sxc151355 set_linkprop_persist(const char *link, const char *prop_name, char **prop_val, 3087*0ba2cbe9Sxc151355 uint_t val_cnt, boolean_t reset) 3088*0ba2cbe9Sxc151355 { 3089*0ba2cbe9Sxc151355 dladm_status_t status; 3090*0ba2cbe9Sxc151355 char errmsg[DLADM_STRSIZE]; 3091*0ba2cbe9Sxc151355 3092*0ba2cbe9Sxc151355 status = dladm_set_prop(link, prop_name, prop_val, val_cnt, 3093*0ba2cbe9Sxc151355 DLADM_OPT_PERSIST); 3094*0ba2cbe9Sxc151355 3095*0ba2cbe9Sxc151355 if (status != DLADM_STATUS_OK) { 3096*0ba2cbe9Sxc151355 if (reset) { 3097*0ba2cbe9Sxc151355 (void) fprintf(stderr, gettext("%s: warning: cannot " 3098*0ba2cbe9Sxc151355 "persistently reset link property '%s' on '%s': " 3099*0ba2cbe9Sxc151355 "%s\n"), progname, prop_name, link, 3100*0ba2cbe9Sxc151355 dladm_status2str(status, errmsg)); 3101*0ba2cbe9Sxc151355 } else { 3102*0ba2cbe9Sxc151355 (void) fprintf(stderr, gettext("%s: warning: cannot " 3103*0ba2cbe9Sxc151355 "persistently set link property '%s' on '%s': " 3104*0ba2cbe9Sxc151355 "%s\n"), progname, prop_name, link, 3105*0ba2cbe9Sxc151355 dladm_status2str(status, errmsg)); 3106*0ba2cbe9Sxc151355 } 3107*0ba2cbe9Sxc151355 } 3108*0ba2cbe9Sxc151355 return (status); 3109*0ba2cbe9Sxc151355 } 3110*0ba2cbe9Sxc151355 3111*0ba2cbe9Sxc151355 static void 3112*0ba2cbe9Sxc151355 set_linkprop(int argc, char **argv, boolean_t reset) 3113*0ba2cbe9Sxc151355 { 3114*0ba2cbe9Sxc151355 int i, option; 3115*0ba2cbe9Sxc151355 char errmsg[DLADM_STRSIZE]; 3116*0ba2cbe9Sxc151355 const char *link = NULL; 3117*0ba2cbe9Sxc151355 prop_list_t *proplist = NULL; 3118*0ba2cbe9Sxc151355 boolean_t temp = B_FALSE; 3119*0ba2cbe9Sxc151355 dladm_status_t status = DLADM_STATUS_OK; 3120*0ba2cbe9Sxc151355 3121*0ba2cbe9Sxc151355 opterr = 0; 3122*0ba2cbe9Sxc151355 while ((option = getopt_long(argc, argv, ":p:R:t", 3123*0ba2cbe9Sxc151355 prop_longopts, NULL)) != -1) { 3124*0ba2cbe9Sxc151355 switch (option) { 3125*0ba2cbe9Sxc151355 case 'p': 3126*0ba2cbe9Sxc151355 if (parse_props(optarg, &proplist, reset) < 0) { 3127*0ba2cbe9Sxc151355 (void) fprintf(stderr, gettext( 3128*0ba2cbe9Sxc151355 "%s: invalid link properties specified\n"), 3129*0ba2cbe9Sxc151355 progname); 3130*0ba2cbe9Sxc151355 exit(1); 3131*0ba2cbe9Sxc151355 } 3132*0ba2cbe9Sxc151355 break; 3133*0ba2cbe9Sxc151355 case 't': 3134*0ba2cbe9Sxc151355 temp = B_TRUE; 3135*0ba2cbe9Sxc151355 break; 3136*0ba2cbe9Sxc151355 case 'R': 3137*0ba2cbe9Sxc151355 status = dladm_set_rootdir(optarg); 3138*0ba2cbe9Sxc151355 if (status != DLADM_STATUS_OK) { 3139*0ba2cbe9Sxc151355 (void) fprintf(stderr, gettext( 3140*0ba2cbe9Sxc151355 "%s: invalid directory specified: %s\n"), 3141*0ba2cbe9Sxc151355 progname, dladm_status2str(status, errmsg)); 3142*0ba2cbe9Sxc151355 exit(1); 3143*0ba2cbe9Sxc151355 } 3144*0ba2cbe9Sxc151355 break; 3145*0ba2cbe9Sxc151355 case ':': 3146*0ba2cbe9Sxc151355 (void) fprintf(stderr, 3147*0ba2cbe9Sxc151355 gettext("%s: option requires a value '-%c'\n"), 3148*0ba2cbe9Sxc151355 progname, optopt); 3149*0ba2cbe9Sxc151355 exit(1); 3150*0ba2cbe9Sxc151355 break; 3151*0ba2cbe9Sxc151355 case '?': 3152*0ba2cbe9Sxc151355 default: 3153*0ba2cbe9Sxc151355 (void) fprintf(stderr, 3154*0ba2cbe9Sxc151355 gettext("%s: unrecognized option '-%c'\n"), 3155*0ba2cbe9Sxc151355 progname, optopt); 3156*0ba2cbe9Sxc151355 exit(1); 3157*0ba2cbe9Sxc151355 break; 3158*0ba2cbe9Sxc151355 } 3159*0ba2cbe9Sxc151355 } 3160*0ba2cbe9Sxc151355 3161*0ba2cbe9Sxc151355 if (optind == (argc - 1)) 3162*0ba2cbe9Sxc151355 link = argv[optind]; 3163*0ba2cbe9Sxc151355 else if (optind != argc) 3164*0ba2cbe9Sxc151355 usage(); 3165*0ba2cbe9Sxc151355 3166*0ba2cbe9Sxc151355 if (link == NULL) { 3167*0ba2cbe9Sxc151355 (void) fprintf(stderr, 3168*0ba2cbe9Sxc151355 gettext("%s: link name must be specified\n"), 3169*0ba2cbe9Sxc151355 progname); 3170*0ba2cbe9Sxc151355 exit(1); 3171*0ba2cbe9Sxc151355 } 3172*0ba2cbe9Sxc151355 3173*0ba2cbe9Sxc151355 if (proplist == NULL) { 3174*0ba2cbe9Sxc151355 if (!reset) { 3175*0ba2cbe9Sxc151355 (void) fprintf(stderr, 3176*0ba2cbe9Sxc151355 gettext("%s: link property must be specified\n"), 3177*0ba2cbe9Sxc151355 progname); 3178*0ba2cbe9Sxc151355 exit(1); 3179*0ba2cbe9Sxc151355 } 3180*0ba2cbe9Sxc151355 status = dladm_set_prop(link, NULL, NULL, 0, DLADM_OPT_TEMP); 3181*0ba2cbe9Sxc151355 if (status != DLADM_STATUS_OK) { 3182*0ba2cbe9Sxc151355 (void) fprintf(stderr, gettext( 3183*0ba2cbe9Sxc151355 "%s: warning: cannot reset link " 3184*0ba2cbe9Sxc151355 "properties on '%s': %s\n"), 3185*0ba2cbe9Sxc151355 progname, link, dladm_status2str(status, errmsg)); 3186*0ba2cbe9Sxc151355 } 3187*0ba2cbe9Sxc151355 if (!temp) { 3188*0ba2cbe9Sxc151355 status = set_linkprop_persist(link, NULL, NULL, 0, 3189*0ba2cbe9Sxc151355 reset); 3190*0ba2cbe9Sxc151355 } 3191*0ba2cbe9Sxc151355 goto done; 3192*0ba2cbe9Sxc151355 } 3193*0ba2cbe9Sxc151355 3194*0ba2cbe9Sxc151355 for (i = 0; i < proplist->pl_count; i++) { 3195*0ba2cbe9Sxc151355 prop_info_t *pip = &proplist->pl_info[i]; 3196*0ba2cbe9Sxc151355 char **val; 3197*0ba2cbe9Sxc151355 uint_t count; 3198*0ba2cbe9Sxc151355 dladm_status_t s; 3199*0ba2cbe9Sxc151355 3200*0ba2cbe9Sxc151355 if (reset) { 3201*0ba2cbe9Sxc151355 val = NULL; 3202*0ba2cbe9Sxc151355 count = 0; 3203*0ba2cbe9Sxc151355 } else { 3204*0ba2cbe9Sxc151355 val = pip->pi_val; 3205*0ba2cbe9Sxc151355 count = pip->pi_count; 3206*0ba2cbe9Sxc151355 if (count == 0) { 3207*0ba2cbe9Sxc151355 (void) fprintf(stderr, gettext( 3208*0ba2cbe9Sxc151355 "%s: value(s) for '%s' not specified\n"), 3209*0ba2cbe9Sxc151355 progname, pip->pi_name); 3210*0ba2cbe9Sxc151355 status = DLADM_STATUS_BADARG; 3211*0ba2cbe9Sxc151355 continue; 3212*0ba2cbe9Sxc151355 } 3213*0ba2cbe9Sxc151355 } 3214*0ba2cbe9Sxc151355 s = dladm_set_prop(link, pip->pi_name, val, count, 3215*0ba2cbe9Sxc151355 DLADM_OPT_TEMP); 3216*0ba2cbe9Sxc151355 if (s == DLADM_STATUS_OK) { 3217*0ba2cbe9Sxc151355 if (!temp) { 3218*0ba2cbe9Sxc151355 s = set_linkprop_persist(link, 3219*0ba2cbe9Sxc151355 pip->pi_name, val, count, reset); 3220*0ba2cbe9Sxc151355 if (s != DLADM_STATUS_OK) 3221*0ba2cbe9Sxc151355 status = s; 3222*0ba2cbe9Sxc151355 } 3223*0ba2cbe9Sxc151355 continue; 3224*0ba2cbe9Sxc151355 } 3225*0ba2cbe9Sxc151355 status = s; 3226*0ba2cbe9Sxc151355 switch (s) { 3227*0ba2cbe9Sxc151355 case DLADM_STATUS_NOTFOUND: 3228*0ba2cbe9Sxc151355 (void) fprintf(stderr, 3229*0ba2cbe9Sxc151355 gettext("%s: invalid link property '%s'\n"), 3230*0ba2cbe9Sxc151355 progname, pip->pi_name); 3231*0ba2cbe9Sxc151355 break; 3232*0ba2cbe9Sxc151355 case DLADM_STATUS_BADVAL: { 3233*0ba2cbe9Sxc151355 int j; 3234*0ba2cbe9Sxc151355 char *ptr, *lim; 3235*0ba2cbe9Sxc151355 char **propvals = NULL; 3236*0ba2cbe9Sxc151355 uint_t valcnt = MAX_PROP_VALS; 3237*0ba2cbe9Sxc151355 3238*0ba2cbe9Sxc151355 ptr = malloc((sizeof (char *) + 3239*0ba2cbe9Sxc151355 DLADM_PROP_VAL_MAX) * MAX_PROP_VALS + 3240*0ba2cbe9Sxc151355 MAX_PROP_LINE); 3241*0ba2cbe9Sxc151355 3242*0ba2cbe9Sxc151355 propvals = (char **)(void *)ptr; 3243*0ba2cbe9Sxc151355 if (propvals == NULL) { 3244*0ba2cbe9Sxc151355 (void) fprintf(stderr, gettext( 3245*0ba2cbe9Sxc151355 "%s: insufficient memory\n"), progname); 3246*0ba2cbe9Sxc151355 exit(1); 3247*0ba2cbe9Sxc151355 } 3248*0ba2cbe9Sxc151355 for (j = 0; j < MAX_PROP_VALS; j++) { 3249*0ba2cbe9Sxc151355 propvals[j] = ptr + sizeof (char *) * 3250*0ba2cbe9Sxc151355 MAX_PROP_VALS + 3251*0ba2cbe9Sxc151355 j * DLADM_PROP_VAL_MAX; 3252*0ba2cbe9Sxc151355 } 3253*0ba2cbe9Sxc151355 s = dladm_get_prop(link, DLADM_PROP_VAL_MODIFIABLE, 3254*0ba2cbe9Sxc151355 pip->pi_name, propvals, &valcnt); 3255*0ba2cbe9Sxc151355 3256*0ba2cbe9Sxc151355 ptr = errmsg; 3257*0ba2cbe9Sxc151355 lim = ptr + DLADM_STRSIZE; 3258*0ba2cbe9Sxc151355 *ptr = '\0'; 3259*0ba2cbe9Sxc151355 for (j = 0; j < valcnt && s == DLADM_STATUS_OK; j++) { 3260*0ba2cbe9Sxc151355 ptr += snprintf(ptr, lim - ptr, "%s,", 3261*0ba2cbe9Sxc151355 propvals[j]); 3262*0ba2cbe9Sxc151355 if (ptr >= lim) 3263*0ba2cbe9Sxc151355 break; 3264*0ba2cbe9Sxc151355 } 3265*0ba2cbe9Sxc151355 if (ptr > errmsg) 3266*0ba2cbe9Sxc151355 *(ptr - 1) = '\0'; 3267*0ba2cbe9Sxc151355 (void) fprintf(stderr, gettext( 3268*0ba2cbe9Sxc151355 "%s: link property '%s' must be one of: %s\n"), 3269*0ba2cbe9Sxc151355 progname, pip->pi_name, errmsg); 3270*0ba2cbe9Sxc151355 free(propvals); 3271*0ba2cbe9Sxc151355 break; 3272*0ba2cbe9Sxc151355 } 3273*0ba2cbe9Sxc151355 default: 3274*0ba2cbe9Sxc151355 if (reset) { 3275*0ba2cbe9Sxc151355 (void) fprintf(stderr, gettext( 3276*0ba2cbe9Sxc151355 "%s: cannot reset link property '%s' on " 3277*0ba2cbe9Sxc151355 "'%s': %s\n"), progname, pip->pi_name, link, 3278*0ba2cbe9Sxc151355 dladm_status2str(s, errmsg)); 3279*0ba2cbe9Sxc151355 } else { 3280*0ba2cbe9Sxc151355 (void) fprintf(stderr, gettext( 3281*0ba2cbe9Sxc151355 "%s: cannot set link property '%s' on " 3282*0ba2cbe9Sxc151355 "'%s': %s\n"), progname, pip->pi_name, link, 3283*0ba2cbe9Sxc151355 dladm_status2str(s, errmsg)); 3284*0ba2cbe9Sxc151355 } 3285*0ba2cbe9Sxc151355 break; 3286*0ba2cbe9Sxc151355 } 3287*0ba2cbe9Sxc151355 } 3288*0ba2cbe9Sxc151355 done: 3289*0ba2cbe9Sxc151355 free_props(proplist); 3290*0ba2cbe9Sxc151355 if (status != DLADM_STATUS_OK) 3291*0ba2cbe9Sxc151355 exit(1); 3292*0ba2cbe9Sxc151355 } 3293*0ba2cbe9Sxc151355 3294*0ba2cbe9Sxc151355 static void 3295*0ba2cbe9Sxc151355 do_set_linkprop(int argc, char **argv) 3296*0ba2cbe9Sxc151355 { 3297*0ba2cbe9Sxc151355 set_linkprop(argc, argv, B_FALSE); 3298*0ba2cbe9Sxc151355 } 3299*0ba2cbe9Sxc151355 3300*0ba2cbe9Sxc151355 static void 3301*0ba2cbe9Sxc151355 do_reset_linkprop(int argc, char **argv) 3302*0ba2cbe9Sxc151355 { 3303*0ba2cbe9Sxc151355 set_linkprop(argc, argv, B_TRUE); 3304*0ba2cbe9Sxc151355 } 3305*0ba2cbe9Sxc151355 3306*0ba2cbe9Sxc151355 static int 3307*0ba2cbe9Sxc151355 convert_secobj(char *buf, uint_t len, uint8_t *obj_val, uint_t *obj_lenp, 3308*0ba2cbe9Sxc151355 dladm_secobj_class_t class) 3309*0ba2cbe9Sxc151355 { 3310*0ba2cbe9Sxc151355 int error = 0; 3311*0ba2cbe9Sxc151355 3312*0ba2cbe9Sxc151355 if (class != DLADM_SECOBJ_CLASS_WEP) 3313*0ba2cbe9Sxc151355 return (ENOENT); 3314*0ba2cbe9Sxc151355 3315*0ba2cbe9Sxc151355 switch (len) { 3316*0ba2cbe9Sxc151355 case 5: /* ASCII key sizes */ 3317*0ba2cbe9Sxc151355 case 13: 3318*0ba2cbe9Sxc151355 (void) memcpy(obj_val, buf, len); 3319*0ba2cbe9Sxc151355 *obj_lenp = len; 3320*0ba2cbe9Sxc151355 break; 3321*0ba2cbe9Sxc151355 case 10: /* Hex key sizes, not preceded by 0x */ 3322*0ba2cbe9Sxc151355 case 26: 3323*0ba2cbe9Sxc151355 error = hexascii_to_octet(buf, len, obj_val, obj_lenp); 3324*0ba2cbe9Sxc151355 break; 3325*0ba2cbe9Sxc151355 case 12: /* Hex key sizes, preceded by 0x */ 3326*0ba2cbe9Sxc151355 case 28: 3327*0ba2cbe9Sxc151355 if (strncmp(buf, "0x", 2) != 0) 3328*0ba2cbe9Sxc151355 return (EINVAL); 3329*0ba2cbe9Sxc151355 error = hexascii_to_octet(buf + 2, len - 2, obj_val, obj_lenp); 3330*0ba2cbe9Sxc151355 break; 3331*0ba2cbe9Sxc151355 default: 3332*0ba2cbe9Sxc151355 return (EINVAL); 3333*0ba2cbe9Sxc151355 } 3334*0ba2cbe9Sxc151355 return (error); 3335*0ba2cbe9Sxc151355 } 3336*0ba2cbe9Sxc151355 3337*0ba2cbe9Sxc151355 /* ARGSUSED */ 3338*0ba2cbe9Sxc151355 static void 3339*0ba2cbe9Sxc151355 defersig(int sig) 3340*0ba2cbe9Sxc151355 { 3341*0ba2cbe9Sxc151355 signalled = sig; 3342*0ba2cbe9Sxc151355 } 3343*0ba2cbe9Sxc151355 3344*0ba2cbe9Sxc151355 static int 3345*0ba2cbe9Sxc151355 get_secobj_from_tty(uint_t try, const char *objname, char *buf) 3346*0ba2cbe9Sxc151355 { 3347*0ba2cbe9Sxc151355 uint_t len = 0; 3348*0ba2cbe9Sxc151355 int c; 3349*0ba2cbe9Sxc151355 struct termios stored, current; 3350*0ba2cbe9Sxc151355 void (*sigfunc)(int); 3351*0ba2cbe9Sxc151355 3352*0ba2cbe9Sxc151355 /* 3353*0ba2cbe9Sxc151355 * Turn off echo -- but before we do so, defer SIGINT handling 3354*0ba2cbe9Sxc151355 * so that a ^C doesn't leave the terminal corrupted. 3355*0ba2cbe9Sxc151355 */ 3356*0ba2cbe9Sxc151355 sigfunc = signal(SIGINT, defersig); 3357*0ba2cbe9Sxc151355 (void) fflush(stdin); 3358*0ba2cbe9Sxc151355 (void) tcgetattr(0, &stored); 3359*0ba2cbe9Sxc151355 current = stored; 3360*0ba2cbe9Sxc151355 current.c_lflag &= ~(ICANON|ECHO); 3361*0ba2cbe9Sxc151355 current.c_cc[VTIME] = 0; 3362*0ba2cbe9Sxc151355 current.c_cc[VMIN] = 1; 3363*0ba2cbe9Sxc151355 (void) tcsetattr(0, TCSANOW, ¤t); 3364*0ba2cbe9Sxc151355 again: 3365*0ba2cbe9Sxc151355 if (try == 1) 3366*0ba2cbe9Sxc151355 (void) printf(gettext("provide value for '%s': "), objname); 3367*0ba2cbe9Sxc151355 else 3368*0ba2cbe9Sxc151355 (void) printf(gettext("confirm value for '%s': "), objname); 3369*0ba2cbe9Sxc151355 3370*0ba2cbe9Sxc151355 (void) fflush(stdout); 3371*0ba2cbe9Sxc151355 while (signalled == 0) { 3372*0ba2cbe9Sxc151355 c = getchar(); 3373*0ba2cbe9Sxc151355 if (c == '\n' || c == '\r') { 3374*0ba2cbe9Sxc151355 if (len != 0) 3375*0ba2cbe9Sxc151355 break; 3376*0ba2cbe9Sxc151355 (void) putchar('\n'); 3377*0ba2cbe9Sxc151355 goto again; 3378*0ba2cbe9Sxc151355 } 3379*0ba2cbe9Sxc151355 3380*0ba2cbe9Sxc151355 buf[len++] = c; 3381*0ba2cbe9Sxc151355 if (len >= DLADM_SECOBJ_VAL_MAX - 1) 3382*0ba2cbe9Sxc151355 break; 3383*0ba2cbe9Sxc151355 (void) putchar('*'); 3384*0ba2cbe9Sxc151355 } 3385*0ba2cbe9Sxc151355 3386*0ba2cbe9Sxc151355 (void) putchar('\n'); 3387*0ba2cbe9Sxc151355 (void) fflush(stdin); 3388*0ba2cbe9Sxc151355 3389*0ba2cbe9Sxc151355 /* 3390*0ba2cbe9Sxc151355 * Restore terminal setting and handle deferred signals. 3391*0ba2cbe9Sxc151355 */ 3392*0ba2cbe9Sxc151355 (void) tcsetattr(0, TCSANOW, &stored); 3393*0ba2cbe9Sxc151355 3394*0ba2cbe9Sxc151355 (void) signal(SIGINT, sigfunc); 3395*0ba2cbe9Sxc151355 if (signalled != 0) 3396*0ba2cbe9Sxc151355 (void) kill(getpid(), signalled); 3397*0ba2cbe9Sxc151355 3398*0ba2cbe9Sxc151355 return (len); 3399*0ba2cbe9Sxc151355 } 3400*0ba2cbe9Sxc151355 3401*0ba2cbe9Sxc151355 static int 3402*0ba2cbe9Sxc151355 get_secobj_val(char *obj_name, uint8_t *obj_val, uint_t *obj_lenp, 3403*0ba2cbe9Sxc151355 dladm_secobj_class_t class, FILE *filep) 3404*0ba2cbe9Sxc151355 { 3405*0ba2cbe9Sxc151355 int rval; 3406*0ba2cbe9Sxc151355 uint_t len, len2; 3407*0ba2cbe9Sxc151355 char buf[DLADM_SECOBJ_VAL_MAX], buf2[DLADM_SECOBJ_VAL_MAX]; 3408*0ba2cbe9Sxc151355 3409*0ba2cbe9Sxc151355 if (filep == NULL) { 3410*0ba2cbe9Sxc151355 len = get_secobj_from_tty(1, obj_name, buf); 3411*0ba2cbe9Sxc151355 rval = convert_secobj(buf, len, obj_val, obj_lenp, class); 3412*0ba2cbe9Sxc151355 if (rval == 0) { 3413*0ba2cbe9Sxc151355 len2 = get_secobj_from_tty(2, obj_name, buf2); 3414*0ba2cbe9Sxc151355 if (len != len2 || memcmp(buf, buf2, len) != 0) 3415*0ba2cbe9Sxc151355 rval = ENOTSUP; 3416*0ba2cbe9Sxc151355 } 3417*0ba2cbe9Sxc151355 return (rval); 3418*0ba2cbe9Sxc151355 } else { 3419*0ba2cbe9Sxc151355 for (;;) { 3420*0ba2cbe9Sxc151355 if (fgets(buf, sizeof (buf), filep) == NULL) 3421*0ba2cbe9Sxc151355 break; 3422*0ba2cbe9Sxc151355 if (isspace(buf[0])) 3423*0ba2cbe9Sxc151355 continue; 3424*0ba2cbe9Sxc151355 3425*0ba2cbe9Sxc151355 len = strlen(buf); 3426*0ba2cbe9Sxc151355 if (buf[len - 1] == '\n') { 3427*0ba2cbe9Sxc151355 buf[len - 1] = '\0'; 3428*0ba2cbe9Sxc151355 len--; 3429*0ba2cbe9Sxc151355 } 3430*0ba2cbe9Sxc151355 break; 3431*0ba2cbe9Sxc151355 } 3432*0ba2cbe9Sxc151355 (void) fclose(filep); 3433*0ba2cbe9Sxc151355 } 3434*0ba2cbe9Sxc151355 return (convert_secobj(buf, len, obj_val, obj_lenp, class)); 3435*0ba2cbe9Sxc151355 } 3436*0ba2cbe9Sxc151355 3437*0ba2cbe9Sxc151355 static boolean_t 3438*0ba2cbe9Sxc151355 check_auth(const char *auth) 3439*0ba2cbe9Sxc151355 { 3440*0ba2cbe9Sxc151355 struct passwd *pw; 3441*0ba2cbe9Sxc151355 3442*0ba2cbe9Sxc151355 if ((pw = getpwuid(getuid())) == NULL) 3443*0ba2cbe9Sxc151355 return (B_FALSE); 3444*0ba2cbe9Sxc151355 3445*0ba2cbe9Sxc151355 return (chkauthattr(auth, pw->pw_name) != 0); 3446*0ba2cbe9Sxc151355 } 3447*0ba2cbe9Sxc151355 3448*0ba2cbe9Sxc151355 static void 3449*0ba2cbe9Sxc151355 audit_secobj(char *auth, char *class, char *obj, 3450*0ba2cbe9Sxc151355 boolean_t success, boolean_t create) 3451*0ba2cbe9Sxc151355 { 3452*0ba2cbe9Sxc151355 adt_session_data_t *ah; 3453*0ba2cbe9Sxc151355 adt_event_data_t *event; 3454*0ba2cbe9Sxc151355 au_event_t flag; 3455*0ba2cbe9Sxc151355 char *errstr; 3456*0ba2cbe9Sxc151355 3457*0ba2cbe9Sxc151355 if (create) { 3458*0ba2cbe9Sxc151355 flag = ADT_dladm_create_secobj; 3459*0ba2cbe9Sxc151355 errstr = "ADT_dladm_create_secobj"; 3460*0ba2cbe9Sxc151355 } else { 3461*0ba2cbe9Sxc151355 flag = ADT_dladm_delete_secobj; 3462*0ba2cbe9Sxc151355 errstr = "ADT_dladm_delete_secobj"; 3463*0ba2cbe9Sxc151355 } 3464*0ba2cbe9Sxc151355 3465*0ba2cbe9Sxc151355 if (adt_start_session(&ah, NULL, ADT_USE_PROC_DATA) != 0) { 3466*0ba2cbe9Sxc151355 (void) fprintf(stderr, "%s: adt_start_session: %s\n", 3467*0ba2cbe9Sxc151355 progname, strerror(errno)); 3468*0ba2cbe9Sxc151355 exit(1); 3469*0ba2cbe9Sxc151355 } 3470*0ba2cbe9Sxc151355 3471*0ba2cbe9Sxc151355 if ((event = adt_alloc_event(ah, flag)) == NULL) { 3472*0ba2cbe9Sxc151355 (void) fprintf(stderr, "%s: adt_alloc_event" 3473*0ba2cbe9Sxc151355 "(%s): %s\n", progname, errstr, 3474*0ba2cbe9Sxc151355 strerror(errno)); 3475*0ba2cbe9Sxc151355 exit(1); 3476*0ba2cbe9Sxc151355 } 3477*0ba2cbe9Sxc151355 3478*0ba2cbe9Sxc151355 /* fill in audit info */ 3479*0ba2cbe9Sxc151355 if (create) { 3480*0ba2cbe9Sxc151355 event->adt_dladm_create_secobj.auth_used = auth; 3481*0ba2cbe9Sxc151355 event->adt_dladm_create_secobj.obj_class = class; 3482*0ba2cbe9Sxc151355 event->adt_dladm_create_secobj.obj_name = obj; 3483*0ba2cbe9Sxc151355 } else { 3484*0ba2cbe9Sxc151355 event->adt_dladm_delete_secobj.auth_used = auth; 3485*0ba2cbe9Sxc151355 event->adt_dladm_delete_secobj.obj_class = class; 3486*0ba2cbe9Sxc151355 event->adt_dladm_delete_secobj.obj_name = obj; 3487*0ba2cbe9Sxc151355 } 3488*0ba2cbe9Sxc151355 3489*0ba2cbe9Sxc151355 if (success) { 3490*0ba2cbe9Sxc151355 if (adt_put_event(event, ADT_SUCCESS, ADT_SUCCESS) != 0) { 3491*0ba2cbe9Sxc151355 (void) fprintf(stderr, "%s: adt_put_event" 3492*0ba2cbe9Sxc151355 "(%s, success): %s\n", 3493*0ba2cbe9Sxc151355 progname, errstr, strerror(errno)); 3494*0ba2cbe9Sxc151355 exit(1); 3495*0ba2cbe9Sxc151355 } 3496*0ba2cbe9Sxc151355 } else { 3497*0ba2cbe9Sxc151355 if (adt_put_event(event, ADT_FAILURE, 3498*0ba2cbe9Sxc151355 ADT_FAIL_VALUE_AUTH) != 0) { 3499*0ba2cbe9Sxc151355 (void) fprintf(stderr, "%s: adt_put_event" 3500*0ba2cbe9Sxc151355 "(%s, failure): %s\n", 3501*0ba2cbe9Sxc151355 progname, errstr, strerror(errno)); 3502*0ba2cbe9Sxc151355 exit(1); 3503*0ba2cbe9Sxc151355 } 3504*0ba2cbe9Sxc151355 } 3505*0ba2cbe9Sxc151355 3506*0ba2cbe9Sxc151355 adt_free_event(event); 3507*0ba2cbe9Sxc151355 (void) adt_end_session(ah); 3508*0ba2cbe9Sxc151355 } 3509*0ba2cbe9Sxc151355 3510*0ba2cbe9Sxc151355 #define MAX_SECOBJS 32 3511*0ba2cbe9Sxc151355 #define MAX_SECOBJ_NAMELEN 32 3512*0ba2cbe9Sxc151355 static void 3513*0ba2cbe9Sxc151355 do_create_secobj(int argc, char **argv) 3514*0ba2cbe9Sxc151355 { 3515*0ba2cbe9Sxc151355 int option, rval; 3516*0ba2cbe9Sxc151355 char errmsg[DLADM_STRSIZE]; 3517*0ba2cbe9Sxc151355 FILE *filep = NULL; 3518*0ba2cbe9Sxc151355 char *obj_name = NULL; 3519*0ba2cbe9Sxc151355 char *class_name = NULL; 3520*0ba2cbe9Sxc151355 uint8_t obj_val[DLADM_SECOBJ_VAL_MAX]; 3521*0ba2cbe9Sxc151355 uint_t obj_len; 3522*0ba2cbe9Sxc151355 boolean_t success, temp = B_FALSE; 3523*0ba2cbe9Sxc151355 dladm_status_t status; 3524*0ba2cbe9Sxc151355 dladm_secobj_class_t class = -1; 3525*0ba2cbe9Sxc151355 uid_t euid; 3526*0ba2cbe9Sxc151355 3527*0ba2cbe9Sxc151355 opterr = 0; 3528*0ba2cbe9Sxc151355 (void) memset(obj_val, 0, DLADM_SECOBJ_VAL_MAX); 3529*0ba2cbe9Sxc151355 while ((option = getopt_long(argc, argv, ":f:c:R:t", 3530*0ba2cbe9Sxc151355 wifi_longopts, NULL)) != -1) { 3531*0ba2cbe9Sxc151355 switch (option) { 3532*0ba2cbe9Sxc151355 case 'f': 3533*0ba2cbe9Sxc151355 euid = geteuid(); 3534*0ba2cbe9Sxc151355 (void) seteuid(getuid()); 3535*0ba2cbe9Sxc151355 filep = fopen(optarg, "r"); 3536*0ba2cbe9Sxc151355 if (filep == NULL) { 3537*0ba2cbe9Sxc151355 (void) fprintf(stderr, 3538*0ba2cbe9Sxc151355 gettext("%s: cannot open %s: %s\n"), 3539*0ba2cbe9Sxc151355 progname, optarg, strerror(errno)); 3540*0ba2cbe9Sxc151355 exit(1); 3541*0ba2cbe9Sxc151355 } 3542*0ba2cbe9Sxc151355 (void) seteuid(euid); 3543*0ba2cbe9Sxc151355 break; 3544*0ba2cbe9Sxc151355 case 'c': 3545*0ba2cbe9Sxc151355 class_name = optarg; 3546*0ba2cbe9Sxc151355 status = dladm_str2secobjclass(optarg, &class); 3547*0ba2cbe9Sxc151355 if (status != DLADM_STATUS_OK) { 3548*0ba2cbe9Sxc151355 (void) fprintf(stderr, gettext( 3549*0ba2cbe9Sxc151355 "%s: invalid secure object class '%s', " 3550*0ba2cbe9Sxc151355 "valid values are: wep\n"), 3551*0ba2cbe9Sxc151355 progname, optarg); 3552*0ba2cbe9Sxc151355 exit(1); 3553*0ba2cbe9Sxc151355 } 3554*0ba2cbe9Sxc151355 break; 3555*0ba2cbe9Sxc151355 case 't': 3556*0ba2cbe9Sxc151355 temp = B_TRUE; 3557*0ba2cbe9Sxc151355 break; 3558*0ba2cbe9Sxc151355 case 'R': 3559*0ba2cbe9Sxc151355 status = dladm_set_rootdir(optarg); 3560*0ba2cbe9Sxc151355 if (status != DLADM_STATUS_OK) { 3561*0ba2cbe9Sxc151355 (void) fprintf(stderr, gettext( 3562*0ba2cbe9Sxc151355 "%s: invalid directory specified: %s\n"), 3563*0ba2cbe9Sxc151355 progname, dladm_status2str(status, errmsg)); 3564*0ba2cbe9Sxc151355 exit(1); 3565*0ba2cbe9Sxc151355 } 3566*0ba2cbe9Sxc151355 break; 3567*0ba2cbe9Sxc151355 case ':': 3568*0ba2cbe9Sxc151355 (void) fprintf(stderr, 3569*0ba2cbe9Sxc151355 gettext("%s: option requires a value '-%c'\n"), 3570*0ba2cbe9Sxc151355 progname, optopt); 3571*0ba2cbe9Sxc151355 exit(1); 3572*0ba2cbe9Sxc151355 break; 3573*0ba2cbe9Sxc151355 case '?': 3574*0ba2cbe9Sxc151355 default: 3575*0ba2cbe9Sxc151355 (void) fprintf(stderr, 3576*0ba2cbe9Sxc151355 gettext("%s: unrecognized option '-%c'\n"), 3577*0ba2cbe9Sxc151355 progname, optopt); 3578*0ba2cbe9Sxc151355 exit(1); 3579*0ba2cbe9Sxc151355 break; 3580*0ba2cbe9Sxc151355 } 3581*0ba2cbe9Sxc151355 } 3582*0ba2cbe9Sxc151355 3583*0ba2cbe9Sxc151355 if (optind == (argc - 1)) 3584*0ba2cbe9Sxc151355 obj_name = argv[optind]; 3585*0ba2cbe9Sxc151355 else if (optind != argc) 3586*0ba2cbe9Sxc151355 usage(); 3587*0ba2cbe9Sxc151355 3588*0ba2cbe9Sxc151355 if (class == -1) { 3589*0ba2cbe9Sxc151355 (void) fprintf(stderr, 3590*0ba2cbe9Sxc151355 gettext("%s: secure object class required\n"), 3591*0ba2cbe9Sxc151355 progname); 3592*0ba2cbe9Sxc151355 exit(1); 3593*0ba2cbe9Sxc151355 } 3594*0ba2cbe9Sxc151355 3595*0ba2cbe9Sxc151355 if (obj_name == NULL) { 3596*0ba2cbe9Sxc151355 (void) fprintf(stderr, 3597*0ba2cbe9Sxc151355 gettext("%s: secure object name required\n"), 3598*0ba2cbe9Sxc151355 progname); 3599*0ba2cbe9Sxc151355 exit(1); 3600*0ba2cbe9Sxc151355 } 3601*0ba2cbe9Sxc151355 3602*0ba2cbe9Sxc151355 success = check_auth(LINK_SEC_AUTH); 3603*0ba2cbe9Sxc151355 audit_secobj(LINK_SEC_AUTH, class_name, obj_name, success, B_TRUE); 3604*0ba2cbe9Sxc151355 if (!success) { 3605*0ba2cbe9Sxc151355 (void) fprintf(stderr, 3606*0ba2cbe9Sxc151355 gettext("%s: authorization '%s' is required\n"), 3607*0ba2cbe9Sxc151355 progname, LINK_SEC_AUTH); 3608*0ba2cbe9Sxc151355 exit(1); 3609*0ba2cbe9Sxc151355 } 3610*0ba2cbe9Sxc151355 3611*0ba2cbe9Sxc151355 if ((rval = get_secobj_val(obj_name, obj_val, &obj_len, 3612*0ba2cbe9Sxc151355 class, filep)) != 0) { 3613*0ba2cbe9Sxc151355 switch (rval) { 3614*0ba2cbe9Sxc151355 case ENOENT: 3615*0ba2cbe9Sxc151355 (void) fprintf(stderr, 3616*0ba2cbe9Sxc151355 gettext("%s: invalid secure object class\n"), 3617*0ba2cbe9Sxc151355 progname); 3618*0ba2cbe9Sxc151355 break; 3619*0ba2cbe9Sxc151355 case EINVAL: 3620*0ba2cbe9Sxc151355 (void) fprintf(stderr, 3621*0ba2cbe9Sxc151355 gettext("%s: invalid secure object value\n"), 3622*0ba2cbe9Sxc151355 progname); 3623*0ba2cbe9Sxc151355 break; 3624*0ba2cbe9Sxc151355 case ENOTSUP: 3625*0ba2cbe9Sxc151355 (void) fprintf(stderr, gettext( 3626*0ba2cbe9Sxc151355 "%s: verification failed\n"), progname); 3627*0ba2cbe9Sxc151355 break; 3628*0ba2cbe9Sxc151355 default: 3629*0ba2cbe9Sxc151355 (void) fprintf(stderr, gettext( 3630*0ba2cbe9Sxc151355 "%s: invalid secure object: %s\n"), 3631*0ba2cbe9Sxc151355 progname, strerror(rval)); 3632*0ba2cbe9Sxc151355 break; 3633*0ba2cbe9Sxc151355 } 3634*0ba2cbe9Sxc151355 exit(1); 3635*0ba2cbe9Sxc151355 } 3636*0ba2cbe9Sxc151355 3637*0ba2cbe9Sxc151355 status = dladm_set_secobj(obj_name, class, obj_val, obj_len, 3638*0ba2cbe9Sxc151355 DLADM_OPT_CREATE | DLADM_OPT_TEMP); 3639*0ba2cbe9Sxc151355 if (status != DLADM_STATUS_OK) { 3640*0ba2cbe9Sxc151355 (void) fprintf(stderr, 3641*0ba2cbe9Sxc151355 gettext("%s: could not create secure object '%s': %s\n"), 3642*0ba2cbe9Sxc151355 progname, obj_name, dladm_status2str(status, errmsg)); 3643*0ba2cbe9Sxc151355 exit(1); 3644*0ba2cbe9Sxc151355 } 3645*0ba2cbe9Sxc151355 if (temp) 3646*0ba2cbe9Sxc151355 return; 3647*0ba2cbe9Sxc151355 3648*0ba2cbe9Sxc151355 status = dladm_set_secobj(obj_name, class, obj_val, obj_len, 3649*0ba2cbe9Sxc151355 DLADM_OPT_PERSIST); 3650*0ba2cbe9Sxc151355 if (status != DLADM_STATUS_OK) { 3651*0ba2cbe9Sxc151355 (void) fprintf(stderr, 3652*0ba2cbe9Sxc151355 gettext("%s: warning: could not persistently create " 3653*0ba2cbe9Sxc151355 "secure object '%s': %s\n"), progname, obj_name, 3654*0ba2cbe9Sxc151355 dladm_status2str(status, errmsg)); 3655*0ba2cbe9Sxc151355 exit(1); 3656*0ba2cbe9Sxc151355 } 3657*0ba2cbe9Sxc151355 } 3658*0ba2cbe9Sxc151355 3659*0ba2cbe9Sxc151355 static void 3660*0ba2cbe9Sxc151355 do_delete_secobj(int argc, char **argv) 3661*0ba2cbe9Sxc151355 { 3662*0ba2cbe9Sxc151355 int i, option; 3663*0ba2cbe9Sxc151355 char errmsg[DLADM_STRSIZE]; 3664*0ba2cbe9Sxc151355 boolean_t temp = B_FALSE; 3665*0ba2cbe9Sxc151355 split_t *sp = NULL; 3666*0ba2cbe9Sxc151355 boolean_t success; 3667*0ba2cbe9Sxc151355 dladm_status_t status, pstatus; 3668*0ba2cbe9Sxc151355 3669*0ba2cbe9Sxc151355 opterr = 0; 3670*0ba2cbe9Sxc151355 status = pstatus = DLADM_STATUS_OK; 3671*0ba2cbe9Sxc151355 while ((option = getopt_long(argc, argv, "R:t", 3672*0ba2cbe9Sxc151355 wifi_longopts, NULL)) != -1) { 3673*0ba2cbe9Sxc151355 switch (option) { 3674*0ba2cbe9Sxc151355 case 't': 3675*0ba2cbe9Sxc151355 temp = B_TRUE; 3676*0ba2cbe9Sxc151355 break; 3677*0ba2cbe9Sxc151355 case 'R': 3678*0ba2cbe9Sxc151355 status = dladm_set_rootdir(optarg); 3679*0ba2cbe9Sxc151355 if (status != DLADM_STATUS_OK) { 3680*0ba2cbe9Sxc151355 (void) fprintf(stderr, gettext( 3681*0ba2cbe9Sxc151355 "%s: invalid directory specified: %s\n"), 3682*0ba2cbe9Sxc151355 progname, dladm_status2str(status, errmsg)); 3683*0ba2cbe9Sxc151355 exit(1); 3684*0ba2cbe9Sxc151355 } 3685*0ba2cbe9Sxc151355 break; 3686*0ba2cbe9Sxc151355 case ':': 3687*0ba2cbe9Sxc151355 (void) fprintf(stderr, 3688*0ba2cbe9Sxc151355 gettext("%s: option requires a value '-%c'\n"), 3689*0ba2cbe9Sxc151355 progname, optopt); 3690*0ba2cbe9Sxc151355 exit(1); 3691*0ba2cbe9Sxc151355 break; 3692*0ba2cbe9Sxc151355 case '?': 3693*0ba2cbe9Sxc151355 default: 3694*0ba2cbe9Sxc151355 (void) fprintf(stderr, 3695*0ba2cbe9Sxc151355 gettext("%s: unrecognized option '-%c'\n"), 3696*0ba2cbe9Sxc151355 progname, optopt); 3697*0ba2cbe9Sxc151355 exit(1); 3698*0ba2cbe9Sxc151355 break; 3699*0ba2cbe9Sxc151355 } 3700*0ba2cbe9Sxc151355 } 3701*0ba2cbe9Sxc151355 3702*0ba2cbe9Sxc151355 if (optind == (argc - 1)) { 3703*0ba2cbe9Sxc151355 sp = split(argv[optind], MAX_SECOBJS, MAX_SECOBJ_NAMELEN); 3704*0ba2cbe9Sxc151355 if (sp == NULL) { 3705*0ba2cbe9Sxc151355 (void) fprintf(stderr, gettext( 3706*0ba2cbe9Sxc151355 "%s: invalid secure object name(s): '%s'\n"), 3707*0ba2cbe9Sxc151355 progname, argv[optind]); 3708*0ba2cbe9Sxc151355 exit(1); 3709*0ba2cbe9Sxc151355 } 3710*0ba2cbe9Sxc151355 } else if (optind != argc) 3711*0ba2cbe9Sxc151355 usage(); 3712*0ba2cbe9Sxc151355 3713*0ba2cbe9Sxc151355 if (sp == NULL || sp->s_nfields < 1) { 3714*0ba2cbe9Sxc151355 (void) fprintf(stderr, 3715*0ba2cbe9Sxc151355 gettext("%s: secure object name required\n"), 3716*0ba2cbe9Sxc151355 progname); 3717*0ba2cbe9Sxc151355 exit(1); 3718*0ba2cbe9Sxc151355 } 3719*0ba2cbe9Sxc151355 3720*0ba2cbe9Sxc151355 success = check_auth(LINK_SEC_AUTH); 3721*0ba2cbe9Sxc151355 audit_secobj(LINK_SEC_AUTH, "wep", argv[optind], success, B_FALSE); 3722*0ba2cbe9Sxc151355 if (!success) { 3723*0ba2cbe9Sxc151355 (void) fprintf(stderr, 3724*0ba2cbe9Sxc151355 gettext("%s: authorization '%s' is required\n"), 3725*0ba2cbe9Sxc151355 progname, LINK_SEC_AUTH); 3726*0ba2cbe9Sxc151355 exit(1); 3727*0ba2cbe9Sxc151355 } 3728*0ba2cbe9Sxc151355 3729*0ba2cbe9Sxc151355 for (i = 0; i < sp->s_nfields; i++) { 3730*0ba2cbe9Sxc151355 status = dladm_unset_secobj(sp->s_fields[i], DLADM_OPT_TEMP); 3731*0ba2cbe9Sxc151355 if (!temp) { 3732*0ba2cbe9Sxc151355 pstatus = dladm_unset_secobj(sp->s_fields[i], 3733*0ba2cbe9Sxc151355 DLADM_OPT_PERSIST); 3734*0ba2cbe9Sxc151355 } else { 3735*0ba2cbe9Sxc151355 pstatus = DLADM_STATUS_OK; 3736*0ba2cbe9Sxc151355 } 3737*0ba2cbe9Sxc151355 3738*0ba2cbe9Sxc151355 if (status != DLADM_STATUS_OK) { 3739*0ba2cbe9Sxc151355 (void) fprintf(stderr, gettext( 3740*0ba2cbe9Sxc151355 "%s: could not delete secure object '%s': %s\n"), 3741*0ba2cbe9Sxc151355 progname, sp->s_fields[i], 3742*0ba2cbe9Sxc151355 dladm_status2str(status, errmsg)); 3743*0ba2cbe9Sxc151355 } 3744*0ba2cbe9Sxc151355 if (pstatus != DLADM_STATUS_OK) { 3745*0ba2cbe9Sxc151355 (void) fprintf(stderr, gettext("%s: warning: could not " 3746*0ba2cbe9Sxc151355 "persistently delete secure object '%s': %s\n"), 3747*0ba2cbe9Sxc151355 progname, sp->s_fields[i], 3748*0ba2cbe9Sxc151355 dladm_status2str(pstatus, errmsg)); 3749*0ba2cbe9Sxc151355 } 3750*0ba2cbe9Sxc151355 } 3751*0ba2cbe9Sxc151355 if (status != DLADM_STATUS_OK || pstatus != DLADM_STATUS_OK) 3752*0ba2cbe9Sxc151355 exit(1); 3753*0ba2cbe9Sxc151355 } 3754*0ba2cbe9Sxc151355 3755*0ba2cbe9Sxc151355 typedef struct show_secobj_state { 3756*0ba2cbe9Sxc151355 boolean_t ss_persist; 3757*0ba2cbe9Sxc151355 boolean_t ss_parseable; 3758*0ba2cbe9Sxc151355 boolean_t ss_debug; 3759*0ba2cbe9Sxc151355 boolean_t ss_header; 3760*0ba2cbe9Sxc151355 } show_secobj_state_t; 3761*0ba2cbe9Sxc151355 3762*0ba2cbe9Sxc151355 static void 3763*0ba2cbe9Sxc151355 print_secobj_head(show_secobj_state_t *statep) 3764*0ba2cbe9Sxc151355 { 3765*0ba2cbe9Sxc151355 (void) printf("%-20s %-20s ", "OBJECT", "CLASS"); 3766*0ba2cbe9Sxc151355 if (statep->ss_debug) 3767*0ba2cbe9Sxc151355 (void) printf("%-30s", "VALUE"); 3768*0ba2cbe9Sxc151355 (void) putchar('\n'); 3769*0ba2cbe9Sxc151355 } 3770*0ba2cbe9Sxc151355 3771*0ba2cbe9Sxc151355 static boolean_t 3772*0ba2cbe9Sxc151355 show_secobj(void *arg, const char *obj_name) 3773*0ba2cbe9Sxc151355 { 3774*0ba2cbe9Sxc151355 uint_t obj_len = DLADM_SECOBJ_VAL_MAX; 3775*0ba2cbe9Sxc151355 uint8_t obj_val[DLADM_SECOBJ_VAL_MAX]; 3776*0ba2cbe9Sxc151355 char buf[DLADM_STRSIZE]; 3777*0ba2cbe9Sxc151355 uint_t flags = 0; 3778*0ba2cbe9Sxc151355 dladm_secobj_class_t class; 3779*0ba2cbe9Sxc151355 show_secobj_state_t *statep = arg; 3780*0ba2cbe9Sxc151355 dladm_status_t status; 3781*0ba2cbe9Sxc151355 3782*0ba2cbe9Sxc151355 if (statep->ss_persist) 3783*0ba2cbe9Sxc151355 flags |= DLADM_OPT_PERSIST; 3784*0ba2cbe9Sxc151355 3785*0ba2cbe9Sxc151355 status = dladm_get_secobj(obj_name, &class, obj_val, &obj_len, flags); 3786*0ba2cbe9Sxc151355 if (status != DLADM_STATUS_OK) { 3787*0ba2cbe9Sxc151355 (void) fprintf(stderr, gettext( 3788*0ba2cbe9Sxc151355 "%s: cannot get secure object '%s': %s\n"), progname, 3789*0ba2cbe9Sxc151355 obj_name, dladm_status2str(status, buf)); 3790*0ba2cbe9Sxc151355 exit(1); 3791*0ba2cbe9Sxc151355 } 3792*0ba2cbe9Sxc151355 3793*0ba2cbe9Sxc151355 if (statep->ss_header) { 3794*0ba2cbe9Sxc151355 statep->ss_header = B_FALSE; 3795*0ba2cbe9Sxc151355 if (!statep->ss_parseable) 3796*0ba2cbe9Sxc151355 print_secobj_head(statep); 3797*0ba2cbe9Sxc151355 } 3798*0ba2cbe9Sxc151355 3799*0ba2cbe9Sxc151355 if (statep->ss_parseable) { 3800*0ba2cbe9Sxc151355 (void) printf("OBJECT=\"%s\" CLASS=\"%s\" ", obj_name, 3801*0ba2cbe9Sxc151355 dladm_secobjclass2str(class, buf)); 3802*0ba2cbe9Sxc151355 } else { 3803*0ba2cbe9Sxc151355 (void) printf("%-20s %-20s ", obj_name, 3804*0ba2cbe9Sxc151355 dladm_secobjclass2str(class, buf)); 3805*0ba2cbe9Sxc151355 } 3806*0ba2cbe9Sxc151355 3807*0ba2cbe9Sxc151355 if (statep->ss_debug) { 3808*0ba2cbe9Sxc151355 char val[DLADM_SECOBJ_VAL_MAX * 2]; 3809*0ba2cbe9Sxc151355 uint_t len = sizeof (val); 3810*0ba2cbe9Sxc151355 3811*0ba2cbe9Sxc151355 if (octet_to_hexascii(obj_val, obj_len, val, &len) == 0) { 3812*0ba2cbe9Sxc151355 if (statep->ss_parseable) 3813*0ba2cbe9Sxc151355 (void) printf("VALUE=\"0x%s\"", val); 3814*0ba2cbe9Sxc151355 else 3815*0ba2cbe9Sxc151355 (void) printf("0x%-30s", val); 3816*0ba2cbe9Sxc151355 } 3817*0ba2cbe9Sxc151355 } 3818*0ba2cbe9Sxc151355 (void) putchar('\n'); 3819*0ba2cbe9Sxc151355 return (B_TRUE); 3820*0ba2cbe9Sxc151355 } 3821*0ba2cbe9Sxc151355 3822*0ba2cbe9Sxc151355 static void 3823*0ba2cbe9Sxc151355 do_show_secobj(int argc, char **argv) 3824*0ba2cbe9Sxc151355 { 3825*0ba2cbe9Sxc151355 int option; 3826*0ba2cbe9Sxc151355 show_secobj_state_t state; 3827*0ba2cbe9Sxc151355 dladm_status_t status; 3828*0ba2cbe9Sxc151355 uint_t i; 3829*0ba2cbe9Sxc151355 char errmsg[DLADM_STRSIZE]; 3830*0ba2cbe9Sxc151355 split_t *sp; 3831*0ba2cbe9Sxc151355 uint_t flags; 3832*0ba2cbe9Sxc151355 3833*0ba2cbe9Sxc151355 opterr = 0; 3834*0ba2cbe9Sxc151355 state.ss_persist = B_FALSE; 3835*0ba2cbe9Sxc151355 state.ss_parseable = B_FALSE; 3836*0ba2cbe9Sxc151355 state.ss_debug = B_FALSE; 3837*0ba2cbe9Sxc151355 state.ss_header = B_TRUE; 3838*0ba2cbe9Sxc151355 while ((option = getopt_long(argc, argv, ":pPd", 3839*0ba2cbe9Sxc151355 wifi_longopts, NULL)) != -1) { 3840*0ba2cbe9Sxc151355 switch (option) { 3841*0ba2cbe9Sxc151355 case 'p': 3842*0ba2cbe9Sxc151355 state.ss_parseable = B_TRUE; 3843*0ba2cbe9Sxc151355 break; 3844*0ba2cbe9Sxc151355 case 'P': 3845*0ba2cbe9Sxc151355 state.ss_persist = B_TRUE; 3846*0ba2cbe9Sxc151355 break; 3847*0ba2cbe9Sxc151355 case 'd': 3848*0ba2cbe9Sxc151355 if (getuid() != 0) { 3849*0ba2cbe9Sxc151355 (void) fprintf(stderr, 3850*0ba2cbe9Sxc151355 gettext("%s: insufficient privileges\n"), 3851*0ba2cbe9Sxc151355 progname); 3852*0ba2cbe9Sxc151355 exit(1); 3853*0ba2cbe9Sxc151355 } 3854*0ba2cbe9Sxc151355 state.ss_debug = B_TRUE; 3855*0ba2cbe9Sxc151355 break; 3856*0ba2cbe9Sxc151355 case ':': 3857*0ba2cbe9Sxc151355 (void) fprintf(stderr, 3858*0ba2cbe9Sxc151355 gettext("%s: option requires a value '-%c'\n"), 3859*0ba2cbe9Sxc151355 progname, optopt); 3860*0ba2cbe9Sxc151355 exit(1); 3861*0ba2cbe9Sxc151355 break; 3862*0ba2cbe9Sxc151355 case '?': 3863*0ba2cbe9Sxc151355 default: 3864*0ba2cbe9Sxc151355 (void) fprintf(stderr, 3865*0ba2cbe9Sxc151355 gettext("%s: unrecognized option '-%c'\n"), 3866*0ba2cbe9Sxc151355 progname, optopt); 3867*0ba2cbe9Sxc151355 exit(1); 3868*0ba2cbe9Sxc151355 break; 3869*0ba2cbe9Sxc151355 } 3870*0ba2cbe9Sxc151355 } 3871*0ba2cbe9Sxc151355 3872*0ba2cbe9Sxc151355 if (optind == (argc - 1)) { 3873*0ba2cbe9Sxc151355 sp = split(argv[optind], MAX_SECOBJS, MAX_SECOBJ_NAMELEN); 3874*0ba2cbe9Sxc151355 if (sp == NULL) { 3875*0ba2cbe9Sxc151355 (void) fprintf(stderr, gettext( 3876*0ba2cbe9Sxc151355 "%s: invalid secure object name(s): '%s'\n"), 3877*0ba2cbe9Sxc151355 progname, argv[optind]); 3878*0ba2cbe9Sxc151355 exit(1); 3879*0ba2cbe9Sxc151355 } 3880*0ba2cbe9Sxc151355 for (i = 0; i < sp->s_nfields; i++) { 3881*0ba2cbe9Sxc151355 if (!show_secobj(&state, sp->s_fields[i])) 3882*0ba2cbe9Sxc151355 break; 3883*0ba2cbe9Sxc151355 } 3884*0ba2cbe9Sxc151355 splitfree(sp); 3885*0ba2cbe9Sxc151355 return; 3886*0ba2cbe9Sxc151355 } else if (optind != argc) 3887*0ba2cbe9Sxc151355 usage(); 3888*0ba2cbe9Sxc151355 3889*0ba2cbe9Sxc151355 flags = state.ss_persist ? DLADM_OPT_PERSIST : 0; 3890*0ba2cbe9Sxc151355 status = dladm_walk_secobj(&state, show_secobj, flags); 3891*0ba2cbe9Sxc151355 if (status != DLADM_STATUS_OK) { 3892*0ba2cbe9Sxc151355 (void) fprintf(stderr, gettext("%s: show-secobj: %s\n"), 3893*0ba2cbe9Sxc151355 progname, dladm_status2str(status, errmsg)); 3894*0ba2cbe9Sxc151355 exit(1); 3895*0ba2cbe9Sxc151355 } 3896*0ba2cbe9Sxc151355 } 3897*0ba2cbe9Sxc151355 3898*0ba2cbe9Sxc151355 /* ARGSUSED */ 3899*0ba2cbe9Sxc151355 static void 3900*0ba2cbe9Sxc151355 do_init_linkprop(int argc, char **argv) 3901*0ba2cbe9Sxc151355 { 3902*0ba2cbe9Sxc151355 char errmsg[DLADM_STRSIZE]; 3903*0ba2cbe9Sxc151355 dladm_status_t status; 3904*0ba2cbe9Sxc151355 3905*0ba2cbe9Sxc151355 status = dladm_init_linkprop(); 3906*0ba2cbe9Sxc151355 if (status != DLADM_STATUS_OK) { 3907*0ba2cbe9Sxc151355 (void) fprintf(stderr, 3908*0ba2cbe9Sxc151355 gettext("%s: link property initialization failed: %s\n"), 3909*0ba2cbe9Sxc151355 progname, dladm_status2str(status, errmsg)); 3910*0ba2cbe9Sxc151355 exit(1); 3911*0ba2cbe9Sxc151355 } 3912*0ba2cbe9Sxc151355 } 3913*0ba2cbe9Sxc151355 3914*0ba2cbe9Sxc151355 /* ARGSUSED */ 3915*0ba2cbe9Sxc151355 static void 3916*0ba2cbe9Sxc151355 do_init_secobj(int argc, char **argv) 3917*0ba2cbe9Sxc151355 { 3918*0ba2cbe9Sxc151355 char errmsg[DLADM_STRSIZE]; 3919*0ba2cbe9Sxc151355 dladm_status_t status; 3920*0ba2cbe9Sxc151355 3921*0ba2cbe9Sxc151355 status = dladm_init_secobj(); 3922*0ba2cbe9Sxc151355 if (status != DLADM_STATUS_OK) { 3923*0ba2cbe9Sxc151355 (void) fprintf(stderr, 3924*0ba2cbe9Sxc151355 gettext("%s: secure object initialization failed: %s\n"), 3925*0ba2cbe9Sxc151355 progname, dladm_status2str(status, errmsg)); 3926*0ba2cbe9Sxc151355 exit(1); 3927*0ba2cbe9Sxc151355 } 3928*0ba2cbe9Sxc151355 } 3929