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 /* 226f40bf67SRishi Srivatsavai * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate #include <stdio.h> 270ba2cbe9Sxc151355 #include <ctype.h> 284eaa4710SRishi Srivatsavai #include <dlfcn.h> 297c478bd9Sstevel@tonic-gate #include <locale.h> 300ba2cbe9Sxc151355 #include <signal.h> 317c478bd9Sstevel@tonic-gate #include <stdarg.h> 327c478bd9Sstevel@tonic-gate #include <stdlib.h> 337c478bd9Sstevel@tonic-gate #include <fcntl.h> 347c478bd9Sstevel@tonic-gate #include <string.h> 357c478bd9Sstevel@tonic-gate #include <stropts.h> 36d62bc4baSyz147064 #include <sys/stat.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> 432b24ab6bSSebastien Roy #include <limits.h> 440ba2cbe9Sxc151355 #include <termios.h> 450ba2cbe9Sxc151355 #include <pwd.h> 460ba2cbe9Sxc151355 #include <auth_attr.h> 470ba2cbe9Sxc151355 #include <auth_list.h> 487c478bd9Sstevel@tonic-gate #include <libintl.h> 49d62bc4baSyz147064 #include <libdevinfo.h> 507c478bd9Sstevel@tonic-gate #include <libdlpi.h> 51da14cebeSEric Cheng #include <libdladm.h> 52f595a68aSyz147064 #include <libdllink.h> 53da14cebeSEric Cheng #include <libdlstat.h> 54f595a68aSyz147064 #include <libdlaggr.h> 55f595a68aSyz147064 #include <libdlwlan.h> 56d62bc4baSyz147064 #include <libdlvlan.h> 57d62bc4baSyz147064 #include <libdlvnic.h> 584784fcbdSSowmini Varadhan #include <libdlether.h> 592b24ab6bSSebastien Roy #include <libdliptun.h> 60b509e89bSRishi Srivatsavai #include <libdlsim.h> 614eaa4710SRishi Srivatsavai #include <libdlbridge.h> 620ba2cbe9Sxc151355 #include <libinetutil.h> 631cb875aeSCathy Zhou #include <libvrrpadm.h> 640ba2cbe9Sxc151355 #include <bsm/adt.h> 650ba2cbe9Sxc151355 #include <bsm/adt_event.h> 66da14cebeSEric Cheng #include <libdlvnic.h> 67da14cebeSEric Cheng #include <sys/types.h> 68da14cebeSEric Cheng #include <sys/socket.h> 69da14cebeSEric Cheng #include <sys/processor.h> 70da14cebeSEric Cheng #include <netinet/in.h> 71da14cebeSEric Cheng #include <arpa/inet.h> 72da14cebeSEric Cheng #include <net/if_types.h> 73e7801d59Ssowmini #include <stddef.h> 744eaa4710SRishi Srivatsavai #include <stp_in.h> 758002d411SSowmini Varadhan #include <ofmt.h> 767c478bd9Sstevel@tonic-gate 777c478bd9Sstevel@tonic-gate #define MAXPORT 256 78da14cebeSEric Cheng #define MAXVNIC 256 79d62bc4baSyz147064 #define BUFLEN(lim, ptr) (((lim) > (ptr)) ? ((lim) - (ptr)) : 0) 80d62bc4baSyz147064 #define MAXLINELEN 1024 81d62bc4baSyz147064 #define SMF_UPGRADE_FILE "/var/svc/profile/upgrade" 82d62bc4baSyz147064 #define SMF_UPGRADEDATALINK_FILE "/var/svc/profile/upgrade_datalink" 83d62bc4baSyz147064 #define SMF_DLADM_UPGRADE_MSG " # added by dladm(1M)" 848002d411SSowmini Varadhan #define DLADM_DEFAULT_COL 80 857c478bd9Sstevel@tonic-gate 868002d411SSowmini Varadhan /* 878002d411SSowmini Varadhan * used by the wifi show-* commands to set up ofmt_field_t structures. 888002d411SSowmini Varadhan */ 89e7801d59Ssowmini #define WIFI_CMD_SCAN 0x00000001 90e7801d59Ssowmini #define WIFI_CMD_SHOW 0x00000002 91e7801d59Ssowmini #define WIFI_CMD_ALL (WIFI_CMD_SCAN | WIFI_CMD_SHOW) 92e7801d59Ssowmini 934eaa4710SRishi Srivatsavai /* No larger than pktsum_t */ 944eaa4710SRishi Srivatsavai typedef struct brsum_s { 954eaa4710SRishi Srivatsavai uint64_t drops; 964eaa4710SRishi Srivatsavai uint64_t forward_dir; 974eaa4710SRishi Srivatsavai uint64_t forward_mb; 984eaa4710SRishi Srivatsavai uint64_t forward_unk; 994eaa4710SRishi Srivatsavai uint64_t recv; 1004eaa4710SRishi Srivatsavai uint64_t sent; 1014eaa4710SRishi Srivatsavai } brsum_t; 1024eaa4710SRishi Srivatsavai 1034eaa4710SRishi Srivatsavai /* No larger than pktsum_t */ 1044eaa4710SRishi Srivatsavai typedef struct brlsum_s { 1054eaa4710SRishi Srivatsavai uint32_t cfgbpdu; 1064eaa4710SRishi Srivatsavai uint32_t tcnbpdu; 1074eaa4710SRishi Srivatsavai uint32_t rstpbpdu; 1084eaa4710SRishi Srivatsavai uint32_t txbpdu; 1094eaa4710SRishi Srivatsavai uint64_t drops; 1104eaa4710SRishi Srivatsavai uint64_t recv; 1114eaa4710SRishi Srivatsavai uint64_t xmit; 1124eaa4710SRishi Srivatsavai } brlsum_t; 1134eaa4710SRishi Srivatsavai 114d62bc4baSyz147064 typedef struct show_state { 1157c478bd9Sstevel@tonic-gate boolean_t ls_firstonly; 1167c478bd9Sstevel@tonic-gate boolean_t ls_donefirst; 1177c478bd9Sstevel@tonic-gate pktsum_t ls_prevstats; 118d62bc4baSyz147064 uint32_t ls_flags; 119d62bc4baSyz147064 dladm_status_t ls_status; 1208002d411SSowmini Varadhan ofmt_handle_t ls_ofmt; 1218002d411SSowmini Varadhan boolean_t ls_parsable; 122da14cebeSEric Cheng boolean_t ls_mac; 123da14cebeSEric Cheng boolean_t ls_hwgrp; 124d62bc4baSyz147064 } show_state_t; 1257c478bd9Sstevel@tonic-gate 1267c478bd9Sstevel@tonic-gate typedef struct show_grp_state { 127e7801d59Ssowmini pktsum_t gs_prevstats[MAXPORT]; 128e7801d59Ssowmini uint32_t gs_flags; 129e7801d59Ssowmini dladm_status_t gs_status; 1308002d411SSowmini Varadhan boolean_t gs_parsable; 1317c478bd9Sstevel@tonic-gate boolean_t gs_lacp; 132d62bc4baSyz147064 boolean_t gs_extended; 1337c478bd9Sstevel@tonic-gate boolean_t gs_stats; 1347c478bd9Sstevel@tonic-gate boolean_t gs_firstonly; 135d62bc4baSyz147064 boolean_t gs_donefirst; 1368002d411SSowmini Varadhan ofmt_handle_t gs_ofmt; 1377c478bd9Sstevel@tonic-gate } show_grp_state_t; 1387c478bd9Sstevel@tonic-gate 139da14cebeSEric Cheng typedef struct show_vnic_state { 140da14cebeSEric Cheng datalink_id_t vs_vnic_id; 141da14cebeSEric Cheng datalink_id_t vs_link_id; 142da14cebeSEric Cheng char vs_vnic[MAXLINKNAMELEN]; 143da14cebeSEric Cheng char vs_link[MAXLINKNAMELEN]; 1448002d411SSowmini Varadhan boolean_t vs_parsable; 145da14cebeSEric Cheng boolean_t vs_found; 146da14cebeSEric Cheng boolean_t vs_firstonly; 147da14cebeSEric Cheng boolean_t vs_donefirst; 148da14cebeSEric Cheng boolean_t vs_stats; 149da14cebeSEric Cheng boolean_t vs_printstats; 150da14cebeSEric Cheng pktsum_t vs_totalstats; 151da14cebeSEric Cheng pktsum_t vs_prevstats[MAXVNIC]; 152da14cebeSEric Cheng boolean_t vs_etherstub; 153da14cebeSEric Cheng dladm_status_t vs_status; 154da14cebeSEric Cheng uint32_t vs_flags; 1558002d411SSowmini Varadhan ofmt_handle_t vs_ofmt; 156da14cebeSEric Cheng } show_vnic_state_t; 157da14cebeSEric Cheng 158da14cebeSEric Cheng typedef struct show_usage_state_s { 159da14cebeSEric Cheng boolean_t us_plot; 1608002d411SSowmini Varadhan boolean_t us_parsable; 161da14cebeSEric Cheng boolean_t us_printheader; 162da14cebeSEric Cheng boolean_t us_first; 163ae6aa22aSVenugopal Iyer boolean_t us_showall; 1648002d411SSowmini Varadhan ofmt_handle_t us_ofmt; 165da14cebeSEric Cheng } show_usage_state_t; 166da14cebeSEric Cheng 1678002d411SSowmini Varadhan /* 1688002d411SSowmini Varadhan * callback functions for printing output and error diagnostics. 1698002d411SSowmini Varadhan */ 1708002d411SSowmini Varadhan static ofmt_cb_t print_default_cb, print_link_stats_cb, print_linkprop_cb; 1718002d411SSowmini Varadhan static ofmt_cb_t print_lacp_cb, print_phys_one_mac_cb; 1728002d411SSowmini Varadhan static ofmt_cb_t print_xaggr_cb, print_aggr_stats_cb; 1738002d411SSowmini Varadhan static ofmt_cb_t print_phys_one_hwgrp_cb, print_wlan_attr_cb; 1748002d411SSowmini Varadhan static ofmt_cb_t print_wifi_status_cb, print_link_attr_cb; 1758002d411SSowmini Varadhan static void dladm_ofmt_check(ofmt_status_t, boolean_t, ofmt_handle_t); 1768002d411SSowmini Varadhan 1778d5c46e6Sam223141 typedef void cmdfunc_t(int, char **, const char *); 1780ba2cbe9Sxc151355 179da14cebeSEric Cheng static cmdfunc_t do_show_link, do_show_wifi, do_show_phys; 1800ba2cbe9Sxc151355 static cmdfunc_t do_create_aggr, do_delete_aggr, do_add_aggr, do_remove_aggr; 181d62bc4baSyz147064 static cmdfunc_t do_modify_aggr, do_show_aggr, do_up_aggr; 1820ba2cbe9Sxc151355 static cmdfunc_t do_scan_wifi, do_connect_wifi, do_disconnect_wifi; 1830ba2cbe9Sxc151355 static cmdfunc_t do_show_linkprop, do_set_linkprop, do_reset_linkprop; 1840ba2cbe9Sxc151355 static cmdfunc_t do_create_secobj, do_delete_secobj, do_show_secobj; 1850ba2cbe9Sxc151355 static cmdfunc_t do_init_linkprop, do_init_secobj; 186d62bc4baSyz147064 static cmdfunc_t do_create_vlan, do_delete_vlan, do_up_vlan, do_show_vlan; 187d62bc4baSyz147064 static cmdfunc_t do_rename_link, do_delete_phys, do_init_phys; 188d62bc4baSyz147064 static cmdfunc_t do_show_linkmap; 189e7801d59Ssowmini static cmdfunc_t do_show_ether; 190da14cebeSEric Cheng static cmdfunc_t do_create_vnic, do_delete_vnic, do_show_vnic; 191da14cebeSEric Cheng static cmdfunc_t do_up_vnic; 192da14cebeSEric Cheng static cmdfunc_t do_create_etherstub, do_delete_etherstub, do_show_etherstub; 193b509e89bSRishi Srivatsavai static cmdfunc_t do_create_simnet, do_modify_simnet; 194b509e89bSRishi Srivatsavai static cmdfunc_t do_delete_simnet, do_show_simnet, do_up_simnet; 195da14cebeSEric Cheng static cmdfunc_t do_show_usage; 1964eaa4710SRishi Srivatsavai static cmdfunc_t do_create_bridge, do_modify_bridge, do_delete_bridge; 1974eaa4710SRishi Srivatsavai static cmdfunc_t do_add_bridge, do_remove_bridge, do_show_bridge; 1982b24ab6bSSebastien Roy static cmdfunc_t do_create_iptun, do_modify_iptun, do_delete_iptun; 1992b24ab6bSSebastien Roy static cmdfunc_t do_show_iptun, do_up_iptun, do_down_iptun; 200da14cebeSEric Cheng 201da14cebeSEric Cheng static void do_up_vnic_common(int, char **, const char *, boolean_t); 2027c478bd9Sstevel@tonic-gate 203d62bc4baSyz147064 static void altroot_cmd(char *, int, char **); 2044ac67f02SAnurag S. Maskey static int show_linkprop_onelink(dladm_handle_t, datalink_id_t, void *); 205f4b3ec61Sdh155122 2066be03d0bSVasumathi Sundaram - Sun Microsystems static void link_stats(datalink_id_t, uint_t, char *, show_state_t *); 207d62bc4baSyz147064 static void aggr_stats(datalink_id_t, show_grp_state_t *, uint_t); 208da14cebeSEric Cheng static void vnic_stats(show_vnic_state_t *, uint32_t); 2097c478bd9Sstevel@tonic-gate 210d62bc4baSyz147064 static int get_one_kstat(const char *, const char *, uint8_t, 211d62bc4baSyz147064 void *, boolean_t); 212ba2e4443Sseb static void get_mac_stats(const char *, pktsum_t *); 2137c478bd9Sstevel@tonic-gate static void get_link_stats(const char *, pktsum_t *); 214d62bc4baSyz147064 static uint64_t get_ifspeed(const char *, boolean_t); 215d62bc4baSyz147064 static const char *get_linkstate(const char *, boolean_t, char *); 216d62bc4baSyz147064 static const char *get_linkduplex(const char *, boolean_t, char *); 2177c478bd9Sstevel@tonic-gate 2182b24ab6bSSebastien Roy static iptun_type_t iptun_gettypebyname(char *); 2192b24ab6bSSebastien Roy static const char *iptun_gettypebyvalue(iptun_type_t); 2202b24ab6bSSebastien Roy static dladm_status_t print_iptun(dladm_handle_t, datalink_id_t, 2212b24ab6bSSebastien Roy show_state_t *); 2222b24ab6bSSebastien Roy static int print_iptun_walker(dladm_handle_t, datalink_id_t, void *); 2232b24ab6bSSebastien Roy 2244ac67f02SAnurag S. Maskey static int show_etherprop(dladm_handle_t, datalink_id_t, void *); 2254784fcbdSSowmini Varadhan static void show_ether_xprop(void *, dladm_ether_info_t *); 226e7801d59Ssowmini static boolean_t link_is_ether(const char *, datalink_id_t *); 227e7801d59Ssowmini 22833343a97Smeem static boolean_t str2int(const char *, int *); 22933343a97Smeem static void die(const char *, ...); 23033343a97Smeem static void die_optdup(int); 2318d5c46e6Sam223141 static void die_opterr(int, int, const char *); 23233343a97Smeem static void die_dlerr(dladm_status_t, const char *, ...); 23333343a97Smeem static void warn(const char *, ...); 23433343a97Smeem static void warn_dlerr(dladm_status_t, const char *, ...); 23533343a97Smeem 2367c478bd9Sstevel@tonic-gate typedef struct cmd { 2377c478bd9Sstevel@tonic-gate char *c_name; 2380ba2cbe9Sxc151355 cmdfunc_t *c_fn; 2398d5c46e6Sam223141 const char *c_usage; 2407c478bd9Sstevel@tonic-gate } cmd_t; 2417c478bd9Sstevel@tonic-gate 2427c478bd9Sstevel@tonic-gate static cmd_t cmds[] = { 2438d5c46e6Sam223141 { "rename-link", do_rename_link, 2440790b6dcSAnurag S. Maskey " rename-link <oldlink> <newlink>" }, 2450790b6dcSAnurag S. Maskey { "show-link", do_show_link, 2460790b6dcSAnurag S. Maskey " show-link [-pP] [-o <field>,..] [-s [-i <interval>]] " 2470790b6dcSAnurag S. Maskey "[<link>]\n" }, 2488d5c46e6Sam223141 { "create-aggr", do_create_aggr, 2490790b6dcSAnurag S. Maskey " create-aggr [-t] [-P <policy>] [-L <mode>] [-T <time>] " 2500790b6dcSAnurag S. Maskey "[-u <address>]\n" 2510790b6dcSAnurag S. Maskey "\t\t -l <link> [-l <link>...] <link>" }, 2528d5c46e6Sam223141 { "delete-aggr", do_delete_aggr, 2530790b6dcSAnurag S. Maskey " delete-aggr [-t] <link>" }, 2548d5c46e6Sam223141 { "add-aggr", do_add_aggr, 2550790b6dcSAnurag S. Maskey " add-aggr [-t] -l <link> [-l <link>...] <link>" }, 2568d5c46e6Sam223141 { "remove-aggr", do_remove_aggr, 2570790b6dcSAnurag S. Maskey " remove-aggr [-t] -l <link> [-l <link>...] <link>" }, 2588d5c46e6Sam223141 { "modify-aggr", do_modify_aggr, 2590790b6dcSAnurag S. Maskey " modify-aggr [-t] [-P <policy>] [-L <mode>] [-T <time>] " 2600790b6dcSAnurag S. Maskey "[-u <address>]\n" 2610790b6dcSAnurag S. Maskey "\t\t <link>" }, 2628d5c46e6Sam223141 { "show-aggr", do_show_aggr, 2630790b6dcSAnurag S. Maskey " show-aggr [-pPLx] [-o <field>,..] [-s [-i <interval>]] " 2648d5c46e6Sam223141 "[<link>]\n" }, 2658d5c46e6Sam223141 { "up-aggr", do_up_aggr, NULL }, 2668d5c46e6Sam223141 { "scan-wifi", do_scan_wifi, 2670790b6dcSAnurag S. Maskey " scan-wifi [-p] [-o <field>,...] [<link>]" }, 2688d5c46e6Sam223141 { "connect-wifi", do_connect_wifi, 2690790b6dcSAnurag S. Maskey " connect-wifi [-e <essid>] [-i <bssid>] [-k <key>,...] " 2708d5c46e6Sam223141 "[-s wep|wpa]\n" 2710790b6dcSAnurag S. Maskey "\t\t [-a open|shared] [-b bss|ibss] [-c] [-m a|b|g] " 2720790b6dcSAnurag S. Maskey "[-T <time>]\n" 2730790b6dcSAnurag S. Maskey "\t\t [<link>]" }, 2748d5c46e6Sam223141 { "disconnect-wifi", do_disconnect_wifi, 2750790b6dcSAnurag S. Maskey " disconnect-wifi [-a] [<link>]" }, 2768d5c46e6Sam223141 { "show-wifi", do_show_wifi, 2770790b6dcSAnurag S. Maskey " show-wifi [-p] [-o <field>,...] [<link>]\n" }, 2788d5c46e6Sam223141 { "set-linkprop", do_set_linkprop, 2790790b6dcSAnurag S. Maskey " set-linkprop [-t] -p <prop>=<value>[,...] <name>" }, 2808d5c46e6Sam223141 { "reset-linkprop", do_reset_linkprop, 2810790b6dcSAnurag S. Maskey " reset-linkprop [-t] [-p <prop>,...] <name>" }, 2820790b6dcSAnurag S. Maskey { "show-linkprop", do_show_linkprop, 2830790b6dcSAnurag S. Maskey " show-linkprop [-cP] [-o <field>,...] [-p <prop>,...] " 2840790b6dcSAnurag S. Maskey "<name>\n" }, 2858d5c46e6Sam223141 { "show-ether", do_show_ether, 2860790b6dcSAnurag S. Maskey " show-ether [-px][-o <field>,...] <link>\n" }, 2878d5c46e6Sam223141 { "create-secobj", do_create_secobj, 2880790b6dcSAnurag S. Maskey " create-secobj [-t] [-f <file>] -c <class> <secobj>" }, 2898d5c46e6Sam223141 { "delete-secobj", do_delete_secobj, 2900790b6dcSAnurag S. Maskey " delete-secobj [-t] <secobj>[,...]" }, 2918d5c46e6Sam223141 { "show-secobj", do_show_secobj, 2920790b6dcSAnurag S. Maskey " show-secobj [-pP] [-o <field>,...] [<secobj>,...]\n" }, 2938d5c46e6Sam223141 { "init-linkprop", do_init_linkprop, NULL }, 2948d5c46e6Sam223141 { "init-secobj", do_init_secobj, NULL }, 2958d5c46e6Sam223141 { "create-vlan", do_create_vlan, 2960790b6dcSAnurag S. Maskey " create-vlan [-ft] -l <link> -v <vid> [link]" }, 2978d5c46e6Sam223141 { "delete-vlan", do_delete_vlan, 2980790b6dcSAnurag S. Maskey " delete-vlan [-t] <link>" }, 2998d5c46e6Sam223141 { "show-vlan", do_show_vlan, 3000790b6dcSAnurag S. Maskey " show-vlan [-pP] [-o <field>,..] [<link>]\n" }, 3018d5c46e6Sam223141 { "up-vlan", do_up_vlan, NULL }, 3022b24ab6bSSebastien Roy { "create-iptun", do_create_iptun, 3032b24ab6bSSebastien Roy " create-iptun [-t] -T <type> " 3042b24ab6bSSebastien Roy "[-a {local|remote}=<addr>,...] <link>]" }, 3052b24ab6bSSebastien Roy { "delete-iptun", do_delete_iptun, 3062b24ab6bSSebastien Roy " delete-iptun [-t] <link>" }, 3072b24ab6bSSebastien Roy { "modify-iptun", do_modify_iptun, 3082b24ab6bSSebastien Roy " modify-iptun [-t] -a {local|remote}=<addr>,... <link>" }, 3092b24ab6bSSebastien Roy { "show-iptun", do_show_iptun, 3102b24ab6bSSebastien Roy " show-iptun [-pP] [-o <field>,..] [<link>]\n" }, 3112b24ab6bSSebastien Roy { "up-iptun", do_up_iptun, NULL }, 3122b24ab6bSSebastien Roy { "down-iptun", do_down_iptun, NULL }, 3138d5c46e6Sam223141 { "delete-phys", do_delete_phys, 3140790b6dcSAnurag S. Maskey " delete-phys <link>" }, 3158d5c46e6Sam223141 { "show-phys", do_show_phys, 3160790b6dcSAnurag S. Maskey " show-phys [-pP] [-o <field>,..] [-H] [<link>]\n"}, 3178d5c46e6Sam223141 { "init-phys", do_init_phys, NULL }, 318da14cebeSEric Cheng { "show-linkmap", do_show_linkmap, NULL }, 319da14cebeSEric Cheng { "create-vnic", do_create_vnic, 3200790b6dcSAnurag S. Maskey " create-vnic [-t] -l <link> [-m <value> | auto |\n" 3211cb875aeSCathy Zhou "\t\t {factory [-n <slot-id>]} | {random [-r <prefix>]} |\n" 3221cb875aeSCathy Zhou "\t\t {vrrp -V <vrid> -A {inet | inet6}} [-v <vid> [-f]]\n" 323*0dc2366fSVenugopal Iyer "\t\t [-p <prop>=<value>[,...]] <vnic-link>" }, 324da14cebeSEric Cheng { "delete-vnic", do_delete_vnic, 3250790b6dcSAnurag S. Maskey " delete-vnic [-t] <vnic-link>" }, 326da14cebeSEric Cheng { "show-vnic", do_show_vnic, 3270790b6dcSAnurag S. Maskey " show-vnic [-pP] [-l <link>] [-s [-i <interval>]] " 3280790b6dcSAnurag S. Maskey "[<link>]\n" }, 329da14cebeSEric Cheng { "up-vnic", do_up_vnic, NULL }, 330da14cebeSEric Cheng { "create-etherstub", do_create_etherstub, 3310790b6dcSAnurag S. Maskey " create-etherstub [-t] <link>" }, 332da14cebeSEric Cheng { "delete-etherstub", do_delete_etherstub, 3330790b6dcSAnurag S. Maskey " delete-etherstub [-t] <link>" }, 334da14cebeSEric Cheng { "show-etherstub", do_show_etherstub, 3350790b6dcSAnurag S. Maskey " show-etherstub [-t] [<link>]\n" }, 3360f83d385SRishi Srivatsavai { "create-simnet", do_create_simnet, NULL }, 3370f83d385SRishi Srivatsavai { "modify-simnet", do_modify_simnet, NULL }, 3380f83d385SRishi Srivatsavai { "delete-simnet", do_delete_simnet, NULL }, 3390f83d385SRishi Srivatsavai { "show-simnet", do_show_simnet, NULL }, 340b509e89bSRishi Srivatsavai { "up-simnet", do_up_simnet, NULL }, 3414eaa4710SRishi Srivatsavai { "create-bridge", do_create_bridge, 3424eaa4710SRishi Srivatsavai " create-bridge [-R <root-dir>] [-P <protect>] " 3434eaa4710SRishi Srivatsavai "[-p <priority>]\n" 3444eaa4710SRishi Srivatsavai "\t\t [-m <max-age>] [-h <hello-time>] [-d <forward-delay>]\n" 3454eaa4710SRishi Srivatsavai "\t\t [-f <force-protocol>] [-l <link>]... <bridge>" }, 3464eaa4710SRishi Srivatsavai { "modify-bridge", do_modify_bridge, 3474eaa4710SRishi Srivatsavai " modify-bridge [-R <root-dir>] [-P <protect>] " 3484eaa4710SRishi Srivatsavai "[-p <priority>]\n" 3494eaa4710SRishi Srivatsavai "\t\t [-m <max-age>] [-h <hello-time>] [-d <forward-delay>]\n" 3504eaa4710SRishi Srivatsavai "\t\t [-f <force-protocol>] <bridge>" }, 3514eaa4710SRishi Srivatsavai { "delete-bridge", do_delete_bridge, 3524eaa4710SRishi Srivatsavai " delete-bridge [-R <root-dir>] <bridge>" }, 3534eaa4710SRishi Srivatsavai { "add-bridge", do_add_bridge, 3544eaa4710SRishi Srivatsavai " add-bridge [-R <root-dir>] -l <link> [-l <link>]... " 3554eaa4710SRishi Srivatsavai "<bridge>" }, 3564eaa4710SRishi Srivatsavai { "remove-bridge", do_remove_bridge, 3574eaa4710SRishi Srivatsavai " remove-bridge [-R <root-dir>] -l <link> [-l <link>]... " 3584eaa4710SRishi Srivatsavai "<bridge>" }, 3594eaa4710SRishi Srivatsavai { "show-bridge", do_show_bridge, 3604eaa4710SRishi Srivatsavai " show-bridge [-p] [-o <field>,...] [-s [-i <interval>]] " 3614eaa4710SRishi Srivatsavai "[<bridge>]\n" 3624eaa4710SRishi Srivatsavai " show-bridge -l [-p] [-o <field>,...] [-s [-i <interval>]]" 3634eaa4710SRishi Srivatsavai " <bridge>\n" 3644eaa4710SRishi Srivatsavai " show-bridge -f [-p] [-o <field>,...] [-s [-i <interval>]]" 3654eaa4710SRishi Srivatsavai " <bridge>\n" 3664eaa4710SRishi Srivatsavai " show-bridge -t [-p] [-o <field>,...] [-s [-i <interval>]]" 3674eaa4710SRishi Srivatsavai " <bridge>\n" }, 368da14cebeSEric Cheng { "show-usage", do_show_usage, 369ae6aa22aSVenugopal Iyer " show-usage [-a] [-d | -F <format>] " 3700790b6dcSAnurag S. Maskey "[-s <DD/MM/YYYY,HH:MM:SS>]\n" 3710790b6dcSAnurag S. Maskey "\t\t [-e <DD/MM/YYYY,HH:MM:SS>] -f <logfile> [<link>]" } 3727c478bd9Sstevel@tonic-gate }; 3737c478bd9Sstevel@tonic-gate 374d62bc4baSyz147064 static const struct option lopts[] = { 3757c478bd9Sstevel@tonic-gate {"vlan-id", required_argument, 0, 'v'}, 376e7801d59Ssowmini {"output", required_argument, 0, 'o'}, 3777c478bd9Sstevel@tonic-gate {"dev", required_argument, 0, 'd'}, 3787c478bd9Sstevel@tonic-gate {"policy", required_argument, 0, 'P'}, 379d62bc4baSyz147064 {"lacp-mode", required_argument, 0, 'L'}, 3807c478bd9Sstevel@tonic-gate {"lacp-timer", required_argument, 0, 'T'}, 3817c478bd9Sstevel@tonic-gate {"unicast", required_argument, 0, 'u'}, 382d62bc4baSyz147064 {"temporary", no_argument, 0, 't'}, 383d62bc4baSyz147064 {"root-dir", required_argument, 0, 'R'}, 384d62bc4baSyz147064 {"link", required_argument, 0, 'l'}, 385d62bc4baSyz147064 {"forcible", no_argument, 0, 'f'}, 386da14cebeSEric Cheng {"bw-limit", required_argument, 0, 'b'}, 387da14cebeSEric Cheng {"mac-address", required_argument, 0, 'm'}, 388da14cebeSEric Cheng {"slot", required_argument, 0, 'n'}, 389d62bc4baSyz147064 { 0, 0, 0, 0 } 390d62bc4baSyz147064 }; 391d62bc4baSyz147064 392d62bc4baSyz147064 static const struct option show_lopts[] = { 3937c478bd9Sstevel@tonic-gate {"statistics", no_argument, 0, 's'}, 394da14cebeSEric Cheng {"continuous", no_argument, 0, 'S'}, 3957c478bd9Sstevel@tonic-gate {"interval", required_argument, 0, 'i'}, 3968002d411SSowmini Varadhan {"parsable", no_argument, 0, 'p'}, 3977c478bd9Sstevel@tonic-gate {"parseable", no_argument, 0, 'p'}, 398d62bc4baSyz147064 {"extended", no_argument, 0, 'x'}, 399e7801d59Ssowmini {"output", required_argument, 0, 'o'}, 400d62bc4baSyz147064 {"persistent", no_argument, 0, 'P'}, 401d62bc4baSyz147064 {"lacp", no_argument, 0, 'L'}, 4027c478bd9Sstevel@tonic-gate { 0, 0, 0, 0 } 4037c478bd9Sstevel@tonic-gate }; 4047c478bd9Sstevel@tonic-gate 4052b24ab6bSSebastien Roy static const struct option iptun_lopts[] = { 4062b24ab6bSSebastien Roy {"output", required_argument, 0, 'o'}, 4072b24ab6bSSebastien Roy {"tunnel-type", required_argument, 0, 'T'}, 4082b24ab6bSSebastien Roy {"address", required_argument, 0, 'a'}, 4092b24ab6bSSebastien Roy {"root-dir", required_argument, 0, 'R'}, 4102b24ab6bSSebastien Roy {"parsable", no_argument, 0, 'p'}, 4112b24ab6bSSebastien Roy {"parseable", no_argument, 0, 'p'}, 4122b24ab6bSSebastien Roy {"persistent", no_argument, 0, 'P'}, 4132b24ab6bSSebastien Roy { 0, 0, 0, 0 } 4142b24ab6bSSebastien Roy }; 4152b24ab6bSSebastien Roy 4162b24ab6bSSebastien Roy static char * const iptun_addropts[] = { 4172b24ab6bSSebastien Roy #define IPTUN_LOCAL 0 4182b24ab6bSSebastien Roy "local", 4192b24ab6bSSebastien Roy #define IPTUN_REMOTE 1 4202b24ab6bSSebastien Roy "remote", 4212b24ab6bSSebastien Roy NULL}; 4222b24ab6bSSebastien Roy 4232b24ab6bSSebastien Roy static const struct { 4242b24ab6bSSebastien Roy const char *type_name; 4252b24ab6bSSebastien Roy iptun_type_t type_value; 4262b24ab6bSSebastien Roy } iptun_types[] = { 4272b24ab6bSSebastien Roy {"ipv4", IPTUN_TYPE_IPV4}, 4282b24ab6bSSebastien Roy {"ipv6", IPTUN_TYPE_IPV6}, 4292b24ab6bSSebastien Roy {"6to4", IPTUN_TYPE_6TO4}, 4302b24ab6bSSebastien Roy {NULL, 0} 4312b24ab6bSSebastien Roy }; 4322b24ab6bSSebastien Roy 4330ba2cbe9Sxc151355 static const struct option prop_longopts[] = { 4340ba2cbe9Sxc151355 {"temporary", no_argument, 0, 't' }, 435e7801d59Ssowmini {"output", required_argument, 0, 'o' }, 4360ba2cbe9Sxc151355 {"root-dir", required_argument, 0, 'R' }, 4370ba2cbe9Sxc151355 {"prop", required_argument, 0, 'p' }, 4388002d411SSowmini Varadhan {"parsable", no_argument, 0, 'c' }, 4390ba2cbe9Sxc151355 {"parseable", no_argument, 0, 'c' }, 4400ba2cbe9Sxc151355 {"persistent", no_argument, 0, 'P' }, 4410ba2cbe9Sxc151355 { 0, 0, 0, 0 } 4420ba2cbe9Sxc151355 }; 4430ba2cbe9Sxc151355 4440ba2cbe9Sxc151355 static const struct option wifi_longopts[] = { 4458002d411SSowmini Varadhan {"parsable", no_argument, 0, 'p' }, 4460ba2cbe9Sxc151355 {"parseable", no_argument, 0, 'p' }, 4470ba2cbe9Sxc151355 {"output", required_argument, 0, 'o' }, 4480ba2cbe9Sxc151355 {"essid", required_argument, 0, 'e' }, 4490ba2cbe9Sxc151355 {"bsstype", required_argument, 0, 'b' }, 4500ba2cbe9Sxc151355 {"mode", required_argument, 0, 'm' }, 4510ba2cbe9Sxc151355 {"key", required_argument, 0, 'k' }, 4520ba2cbe9Sxc151355 {"sec", required_argument, 0, 's' }, 4530ba2cbe9Sxc151355 {"auth", required_argument, 0, 'a' }, 4540ba2cbe9Sxc151355 {"create-ibss", required_argument, 0, 'c' }, 4550ba2cbe9Sxc151355 {"timeout", required_argument, 0, 'T' }, 4560ba2cbe9Sxc151355 {"all-links", no_argument, 0, 'a' }, 4570ba2cbe9Sxc151355 {"temporary", no_argument, 0, 't' }, 4580ba2cbe9Sxc151355 {"root-dir", required_argument, 0, 'R' }, 4590ba2cbe9Sxc151355 {"persistent", no_argument, 0, 'P' }, 4600ba2cbe9Sxc151355 {"file", required_argument, 0, 'f' }, 4610ba2cbe9Sxc151355 { 0, 0, 0, 0 } 4620ba2cbe9Sxc151355 }; 4632b24ab6bSSebastien Roy 464e7801d59Ssowmini static const struct option showeth_lopts[] = { 4658002d411SSowmini Varadhan {"parsable", no_argument, 0, 'p' }, 466e7801d59Ssowmini {"parseable", no_argument, 0, 'p' }, 467e7801d59Ssowmini {"extended", no_argument, 0, 'x' }, 468e7801d59Ssowmini {"output", required_argument, 0, 'o' }, 469e7801d59Ssowmini { 0, 0, 0, 0 } 470e7801d59Ssowmini }; 471e7801d59Ssowmini 472da14cebeSEric Cheng static const struct option vnic_lopts[] = { 473da14cebeSEric Cheng {"temporary", no_argument, 0, 't' }, 474da14cebeSEric Cheng {"root-dir", required_argument, 0, 'R' }, 475da14cebeSEric Cheng {"dev", required_argument, 0, 'd' }, 476da14cebeSEric Cheng {"mac-address", required_argument, 0, 'm' }, 477da14cebeSEric Cheng {"cpus", required_argument, 0, 'c' }, 478da14cebeSEric Cheng {"bw-limit", required_argument, 0, 'b' }, 479da14cebeSEric Cheng {"slot", required_argument, 0, 'n' }, 480da14cebeSEric Cheng {"mac-prefix", required_argument, 0, 'r' }, 4811cb875aeSCathy Zhou {"vrid", required_argument, 0, 'V' }, 4821cb875aeSCathy Zhou {"address-family", required_argument, 0, 'A' }, 483da14cebeSEric Cheng { 0, 0, 0, 0 } 484da14cebeSEric Cheng }; 485da14cebeSEric Cheng 486da14cebeSEric Cheng static const struct option etherstub_lopts[] = { 487da14cebeSEric Cheng {"temporary", no_argument, 0, 't' }, 488da14cebeSEric Cheng {"root-dir", required_argument, 0, 'R' }, 489da14cebeSEric Cheng { 0, 0, 0, 0 } 490da14cebeSEric Cheng }; 491da14cebeSEric Cheng 492ae6aa22aSVenugopal Iyer static const struct option usage_opts[] = { 493ae6aa22aSVenugopal Iyer {"file", required_argument, 0, 'f' }, 494ae6aa22aSVenugopal Iyer {"format", required_argument, 0, 'F' }, 495ae6aa22aSVenugopal Iyer {"start", required_argument, 0, 's' }, 496ae6aa22aSVenugopal Iyer {"stop", required_argument, 0, 'e' }, 497ae6aa22aSVenugopal Iyer { 0, 0, 0, 0 } 498ae6aa22aSVenugopal Iyer }; 499ae6aa22aSVenugopal Iyer 500b509e89bSRishi Srivatsavai static const struct option simnet_lopts[] = { 501b509e89bSRishi Srivatsavai {"temporary", no_argument, 0, 't' }, 502b509e89bSRishi Srivatsavai {"root-dir", required_argument, 0, 'R' }, 503b509e89bSRishi Srivatsavai {"media", required_argument, 0, 'm' }, 504b509e89bSRishi Srivatsavai {"peer", required_argument, 0, 'p' }, 505b509e89bSRishi Srivatsavai { 0, 0, 0, 0 } 506b509e89bSRishi Srivatsavai }; 507b509e89bSRishi Srivatsavai 5084eaa4710SRishi Srivatsavai static const struct option bridge_lopts[] = { 5094eaa4710SRishi Srivatsavai { "protect", required_argument, 0, 'P' }, 5104eaa4710SRishi Srivatsavai { "root-dir", required_argument, 0, 'R' }, 5114eaa4710SRishi Srivatsavai { "forward-delay", required_argument, 0, 'd' }, 5124eaa4710SRishi Srivatsavai { "force-protocol", required_argument, 0, 'f' }, 5134eaa4710SRishi Srivatsavai { "hello-time", required_argument, 0, 'h' }, 5144eaa4710SRishi Srivatsavai { "link", required_argument, 0, 'l' }, 5154eaa4710SRishi Srivatsavai { "max-age", required_argument, 0, 'm' }, 5164eaa4710SRishi Srivatsavai { "priority", required_argument, 0, 'p' }, 5174eaa4710SRishi Srivatsavai { NULL, NULL, 0, 0 } 5184eaa4710SRishi Srivatsavai }; 5194eaa4710SRishi Srivatsavai 5204eaa4710SRishi Srivatsavai static const struct option bridge_show_lopts[] = { 5214eaa4710SRishi Srivatsavai { "forwarding", no_argument, 0, 'f' }, 5224eaa4710SRishi Srivatsavai { "interval", required_argument, 0, 'i' }, 5234eaa4710SRishi Srivatsavai { "link", no_argument, 0, 'l' }, 5244eaa4710SRishi Srivatsavai { "output", required_argument, 0, 'o' }, 5254eaa4710SRishi Srivatsavai { "parsable", no_argument, 0, 'p' }, 5264eaa4710SRishi Srivatsavai { "parseable", no_argument, 0, 'p' }, 5274eaa4710SRishi Srivatsavai { "statistics", no_argument, 0, 's' }, 5284eaa4710SRishi Srivatsavai { "trill", no_argument, 0, 't' }, 5294eaa4710SRishi Srivatsavai { 0, 0, 0, 0 } 5304eaa4710SRishi Srivatsavai }; 5314eaa4710SRishi Srivatsavai 532e7801d59Ssowmini /* 533e7801d59Ssowmini * structures for 'dladm show-ether' 534e7801d59Ssowmini */ 5354784fcbdSSowmini Varadhan static const char *ptype[] = {LEI_ATTR_NAMES}; 5364784fcbdSSowmini Varadhan 537e7801d59Ssowmini typedef struct ether_fields_buf_s 538e7801d59Ssowmini { 539e7801d59Ssowmini char eth_link[15]; 540e7801d59Ssowmini char eth_ptype[8]; 541e7801d59Ssowmini char eth_state[8]; 542e7801d59Ssowmini char eth_autoneg[5]; 543e7801d59Ssowmini char eth_spdx[31]; 544e7801d59Ssowmini char eth_pause[6]; 545e7801d59Ssowmini char eth_rem_fault[16]; 546e7801d59Ssowmini } ether_fields_buf_t; 547e7801d59Ssowmini 5482b24ab6bSSebastien Roy static const ofmt_field_t ether_fields[] = { 5498002d411SSowmini Varadhan /* name, field width, offset callback */ 5508002d411SSowmini Varadhan { "LINK", 16, 5518002d411SSowmini Varadhan offsetof(ether_fields_buf_t, eth_link), print_default_cb}, 5528002d411SSowmini Varadhan { "PTYPE", 9, 5538002d411SSowmini Varadhan offsetof(ether_fields_buf_t, eth_ptype), print_default_cb}, 5548002d411SSowmini Varadhan { "STATE", 9, 5558002d411SSowmini Varadhan offsetof(ether_fields_buf_t, eth_state), 5568002d411SSowmini Varadhan print_default_cb}, 5578002d411SSowmini Varadhan { "AUTO", 6, 5588002d411SSowmini Varadhan offsetof(ether_fields_buf_t, eth_autoneg), print_default_cb}, 5598002d411SSowmini Varadhan { "SPEED-DUPLEX", 32, 5608002d411SSowmini Varadhan offsetof(ether_fields_buf_t, eth_spdx), print_default_cb}, 5618002d411SSowmini Varadhan { "PAUSE", 7, 5628002d411SSowmini Varadhan offsetof(ether_fields_buf_t, eth_pause), print_default_cb}, 5638002d411SSowmini Varadhan { "REM_FAULT", 17, 5648002d411SSowmini Varadhan offsetof(ether_fields_buf_t, eth_rem_fault), print_default_cb}, 5658002d411SSowmini Varadhan {NULL, 0, 5668002d411SSowmini Varadhan 0, NULL}} 567e7801d59Ssowmini ; 568e7801d59Ssowmini 569e7801d59Ssowmini typedef struct print_ether_state { 570e7801d59Ssowmini const char *es_link; 5718002d411SSowmini Varadhan boolean_t es_parsable; 572e7801d59Ssowmini boolean_t es_header; 573e7801d59Ssowmini boolean_t es_extended; 5748002d411SSowmini Varadhan ofmt_handle_t es_ofmt; 575e7801d59Ssowmini } print_ether_state_t; 576e7801d59Ssowmini 577e7801d59Ssowmini /* 578da14cebeSEric Cheng * structures for 'dladm show-link -s' (print statistics) 579e7801d59Ssowmini */ 580e7801d59Ssowmini typedef enum { 581ae6aa22aSVenugopal Iyer LINK_S_LINK, 582ae6aa22aSVenugopal Iyer LINK_S_IPKTS, 583ae6aa22aSVenugopal Iyer LINK_S_RBYTES, 584ae6aa22aSVenugopal Iyer LINK_S_IERRORS, 585ae6aa22aSVenugopal Iyer LINK_S_OPKTS, 586ae6aa22aSVenugopal Iyer LINK_S_OBYTES, 587ae6aa22aSVenugopal Iyer LINK_S_OERRORS 588ae6aa22aSVenugopal Iyer } link_s_field_index_t; 589e7801d59Ssowmini 5902b24ab6bSSebastien Roy static const ofmt_field_t link_s_fields[] = { 5918002d411SSowmini Varadhan /* name, field width, index, callback */ 5928002d411SSowmini Varadhan { "LINK", 15, LINK_S_LINK, print_link_stats_cb}, 5938002d411SSowmini Varadhan { "IPACKETS", 10, LINK_S_IPKTS, print_link_stats_cb}, 5948002d411SSowmini Varadhan { "RBYTES", 8, LINK_S_RBYTES, print_link_stats_cb}, 5958002d411SSowmini Varadhan { "IERRORS", 10, LINK_S_IERRORS, print_link_stats_cb}, 5968002d411SSowmini Varadhan { "OPACKETS", 12, LINK_S_OPKTS, print_link_stats_cb}, 5978002d411SSowmini Varadhan { "OBYTES", 12, LINK_S_OBYTES, print_link_stats_cb}, 5988002d411SSowmini Varadhan { "OERRORS", 8, LINK_S_OERRORS, print_link_stats_cb}} 599e7801d59Ssowmini ; 600ae6aa22aSVenugopal Iyer 601ae6aa22aSVenugopal Iyer typedef struct link_args_s { 602ae6aa22aSVenugopal Iyer char *link_s_link; 603ae6aa22aSVenugopal Iyer pktsum_t *link_s_psum; 604ae6aa22aSVenugopal Iyer } link_args_t; 605e7801d59Ssowmini 606e7801d59Ssowmini /* 607e7801d59Ssowmini * buffer used by print functions for show-{link,phys,vlan} commands. 608e7801d59Ssowmini */ 609e7801d59Ssowmini typedef struct link_fields_buf_s { 610e7801d59Ssowmini char link_name[MAXLINKNAMELEN]; 611e7801d59Ssowmini char link_class[DLADM_STRSIZE]; 612c08e5e1aSdr146992 char link_mtu[11]; 613e7801d59Ssowmini char link_state[DLADM_STRSIZE]; 6144eaa4710SRishi Srivatsavai char link_bridge[MAXLINKNAMELEN]; 615e7801d59Ssowmini char link_over[MAXLINKNAMELEN]; 6164045d941Ssowmini char link_phys_state[DLADM_STRSIZE]; 617e7801d59Ssowmini char link_phys_media[DLADM_STRSIZE]; 618e7801d59Ssowmini char link_phys_speed[DLADM_STRSIZE]; 619e7801d59Ssowmini char link_phys_duplex[DLPI_LINKNAME_MAX]; 620e7801d59Ssowmini char link_phys_device[DLPI_LINKNAME_MAX]; 621e7801d59Ssowmini char link_flags[6]; 622e7801d59Ssowmini char link_vlan_vid[6]; 623e7801d59Ssowmini } link_fields_buf_t; 624e7801d59Ssowmini 625e7801d59Ssowmini /* 626e7801d59Ssowmini * structures for 'dladm show-link' 627e7801d59Ssowmini */ 6282b24ab6bSSebastien Roy static const ofmt_field_t link_fields[] = { 6298002d411SSowmini Varadhan /* name, field width, index, callback */ 6308002d411SSowmini Varadhan { "LINK", 12, 6318002d411SSowmini Varadhan offsetof(link_fields_buf_t, link_name), print_default_cb}, 6324fd5d067Smeem { "CLASS", 10, 6338002d411SSowmini Varadhan offsetof(link_fields_buf_t, link_class), print_default_cb}, 6348002d411SSowmini Varadhan { "MTU", 7, 6358002d411SSowmini Varadhan offsetof(link_fields_buf_t, link_mtu), print_default_cb}, 6368002d411SSowmini Varadhan { "STATE", 9, 6378002d411SSowmini Varadhan offsetof(link_fields_buf_t, link_state), print_default_cb}, 6384eaa4710SRishi Srivatsavai { "BRIDGE", 11, 6394eaa4710SRishi Srivatsavai offsetof(link_fields_buf_t, link_bridge), print_default_cb}, 6408002d411SSowmini Varadhan { "OVER", DLPI_LINKNAME_MAX, 6418002d411SSowmini Varadhan offsetof(link_fields_buf_t, link_over), print_default_cb}, 6428002d411SSowmini Varadhan { NULL, 0, 0, NULL}} 643e7801d59Ssowmini ; 644e7801d59Ssowmini 645e7801d59Ssowmini /* 646e7801d59Ssowmini * structures for 'dladm show-aggr' 647e7801d59Ssowmini */ 648e7801d59Ssowmini typedef struct laggr_fields_buf_s { 649e7801d59Ssowmini char laggr_name[DLPI_LINKNAME_MAX]; 650e7801d59Ssowmini char laggr_policy[9]; 651e7801d59Ssowmini char laggr_addrpolicy[ETHERADDRL * 3 + 3]; 652e7801d59Ssowmini char laggr_lacpactivity[14]; 653e7801d59Ssowmini char laggr_lacptimer[DLADM_STRSIZE]; 654e7801d59Ssowmini char laggr_flags[7]; 655e7801d59Ssowmini } laggr_fields_buf_t; 656e7801d59Ssowmini 657e7801d59Ssowmini typedef struct laggr_args_s { 658e7801d59Ssowmini int laggr_lport; /* -1 indicates the aggr itself */ 659e7801d59Ssowmini const char *laggr_link; 660e7801d59Ssowmini dladm_aggr_grp_attr_t *laggr_ginfop; 661e7801d59Ssowmini dladm_status_t *laggr_status; 662e7801d59Ssowmini pktsum_t *laggr_pktsumtot; /* -s only */ 6632d40c3b2SPrakash Jalan pktsum_t *laggr_diffstats; /* -s only */ 6648002d411SSowmini Varadhan boolean_t laggr_parsable; 665e7801d59Ssowmini } laggr_args_t; 666e7801d59Ssowmini 6672b24ab6bSSebastien Roy static const ofmt_field_t laggr_fields[] = { 6688002d411SSowmini Varadhan /* name, field width, offset, callback */ 6698002d411SSowmini Varadhan { "LINK", 16, 6708002d411SSowmini Varadhan offsetof(laggr_fields_buf_t, laggr_name), print_default_cb}, 6718002d411SSowmini Varadhan { "POLICY", 9, 6728002d411SSowmini Varadhan offsetof(laggr_fields_buf_t, laggr_policy), print_default_cb}, 6738002d411SSowmini Varadhan { "ADDRPOLICY", ETHERADDRL * 3 + 3, 6748002d411SSowmini Varadhan offsetof(laggr_fields_buf_t, laggr_addrpolicy), print_default_cb}, 6758002d411SSowmini Varadhan { "LACPACTIVITY", 14, 6768002d411SSowmini Varadhan offsetof(laggr_fields_buf_t, laggr_lacpactivity), print_default_cb}, 6778002d411SSowmini Varadhan { "LACPTIMER", 12, 6788002d411SSowmini Varadhan offsetof(laggr_fields_buf_t, laggr_lacptimer), print_default_cb}, 6798002d411SSowmini Varadhan { "FLAGS", 8, 6808002d411SSowmini Varadhan offsetof(laggr_fields_buf_t, laggr_flags), print_default_cb}, 6818002d411SSowmini Varadhan { NULL, 0, 0, NULL}} 682e7801d59Ssowmini ; 683e7801d59Ssowmini 684e7801d59Ssowmini /* 685e7801d59Ssowmini * structures for 'dladm show-aggr -x'. 686e7801d59Ssowmini */ 687e7801d59Ssowmini typedef enum { 688e7801d59Ssowmini AGGR_X_LINK, 689e7801d59Ssowmini AGGR_X_PORT, 690e7801d59Ssowmini AGGR_X_SPEED, 691e7801d59Ssowmini AGGR_X_DUPLEX, 692e7801d59Ssowmini AGGR_X_STATE, 693e7801d59Ssowmini AGGR_X_ADDRESS, 694e7801d59Ssowmini AGGR_X_PORTSTATE 695e7801d59Ssowmini } aggr_x_field_index_t; 696e7801d59Ssowmini 6972b24ab6bSSebastien Roy static const ofmt_field_t aggr_x_fields[] = { 6988002d411SSowmini Varadhan /* name, field width, index callback */ 6998002d411SSowmini Varadhan { "LINK", 12, AGGR_X_LINK, print_xaggr_cb}, 7008002d411SSowmini Varadhan { "PORT", 15, AGGR_X_PORT, print_xaggr_cb}, 7018002d411SSowmini Varadhan { "SPEED", 5, AGGR_X_SPEED, print_xaggr_cb}, 7028002d411SSowmini Varadhan { "DUPLEX", 10, AGGR_X_DUPLEX, print_xaggr_cb}, 7038002d411SSowmini Varadhan { "STATE", 10, AGGR_X_STATE, print_xaggr_cb}, 7048002d411SSowmini Varadhan { "ADDRESS", 19, AGGR_X_ADDRESS, print_xaggr_cb}, 7058002d411SSowmini Varadhan { "PORTSTATE", 16, AGGR_X_PORTSTATE, print_xaggr_cb}, 7068002d411SSowmini Varadhan { NULL, 0, 0, NULL}} 707e7801d59Ssowmini ; 708e7801d59Ssowmini 709e7801d59Ssowmini /* 710e7801d59Ssowmini * structures for 'dladm show-aggr -s'. 711e7801d59Ssowmini */ 712e7801d59Ssowmini typedef enum { 713e7801d59Ssowmini AGGR_S_LINK, 714e7801d59Ssowmini AGGR_S_PORT, 715e7801d59Ssowmini AGGR_S_IPKTS, 716e7801d59Ssowmini AGGR_S_RBYTES, 717e7801d59Ssowmini AGGR_S_OPKTS, 718e7801d59Ssowmini AGGR_S_OBYTES, 719e7801d59Ssowmini AGGR_S_IPKTDIST, 720e7801d59Ssowmini AGGR_S_OPKTDIST 721e7801d59Ssowmini } aggr_s_field_index_t; 722e7801d59Ssowmini 7232b24ab6bSSebastien Roy static const ofmt_field_t aggr_s_fields[] = { 7248002d411SSowmini Varadhan { "LINK", 12, AGGR_S_LINK, print_aggr_stats_cb}, 7258002d411SSowmini Varadhan { "PORT", 10, AGGR_S_PORT, print_aggr_stats_cb}, 7268002d411SSowmini Varadhan { "IPACKETS", 8, AGGR_S_IPKTS, print_aggr_stats_cb}, 7278002d411SSowmini Varadhan { "RBYTES", 8, AGGR_S_RBYTES, print_aggr_stats_cb}, 7288002d411SSowmini Varadhan { "OPACKETS", 8, AGGR_S_OPKTS, print_aggr_stats_cb}, 7298002d411SSowmini Varadhan { "OBYTES", 8, AGGR_S_OBYTES, print_aggr_stats_cb}, 7308002d411SSowmini Varadhan { "IPKTDIST", 9, AGGR_S_IPKTDIST, print_aggr_stats_cb}, 7318002d411SSowmini Varadhan { "OPKTDIST", 15, AGGR_S_OPKTDIST, print_aggr_stats_cb}, 7328002d411SSowmini Varadhan { NULL, 0, 0, NULL}} 733e7801d59Ssowmini ; 734e7801d59Ssowmini 735e7801d59Ssowmini /* 736da14cebeSEric Cheng * structures for 'dladm show-aggr -L'. 737e7801d59Ssowmini */ 738e7801d59Ssowmini typedef enum { 739e7801d59Ssowmini AGGR_L_LINK, 740e7801d59Ssowmini AGGR_L_PORT, 741e7801d59Ssowmini AGGR_L_AGGREGATABLE, 742e7801d59Ssowmini AGGR_L_SYNC, 743e7801d59Ssowmini AGGR_L_COLL, 744e7801d59Ssowmini AGGR_L_DIST, 745e7801d59Ssowmini AGGR_L_DEFAULTED, 746e7801d59Ssowmini AGGR_L_EXPIRED 747e7801d59Ssowmini } aggr_l_field_index_t; 748e7801d59Ssowmini 7492b24ab6bSSebastien Roy static const ofmt_field_t aggr_l_fields[] = { 7508002d411SSowmini Varadhan /* name, field width, index */ 7518002d411SSowmini Varadhan { "LINK", 12, AGGR_L_LINK, print_lacp_cb}, 7528002d411SSowmini Varadhan { "PORT", 13, AGGR_L_PORT, print_lacp_cb}, 7538002d411SSowmini Varadhan { "AGGREGATABLE", 13, AGGR_L_AGGREGATABLE, print_lacp_cb}, 7548002d411SSowmini Varadhan { "SYNC", 5, AGGR_L_SYNC, print_lacp_cb}, 7558002d411SSowmini Varadhan { "COLL", 5, AGGR_L_COLL, print_lacp_cb}, 7568002d411SSowmini Varadhan { "DIST", 5, AGGR_L_DIST, print_lacp_cb}, 7578002d411SSowmini Varadhan { "DEFAULTED", 10, AGGR_L_DEFAULTED, print_lacp_cb}, 7588002d411SSowmini Varadhan { "EXPIRED", 15, AGGR_L_EXPIRED, print_lacp_cb}, 7598002d411SSowmini Varadhan { NULL, 0, 0, NULL}} 760e7801d59Ssowmini ; 761e7801d59Ssowmini 762e7801d59Ssowmini /* 763e7801d59Ssowmini * structures for 'dladm show-phys' 764e7801d59Ssowmini */ 765e7801d59Ssowmini 7662b24ab6bSSebastien Roy static const ofmt_field_t phys_fields[] = { 7678002d411SSowmini Varadhan /* name, field width, offset */ 7688002d411SSowmini Varadhan { "LINK", 13, 7698002d411SSowmini Varadhan offsetof(link_fields_buf_t, link_name), print_default_cb}, 7708002d411SSowmini Varadhan { "MEDIA", 21, 7718002d411SSowmini Varadhan offsetof(link_fields_buf_t, link_phys_media), print_default_cb}, 7728002d411SSowmini Varadhan { "STATE", 11, 7738002d411SSowmini Varadhan offsetof(link_fields_buf_t, link_phys_state), print_default_cb}, 7748002d411SSowmini Varadhan { "SPEED", 7, 7758002d411SSowmini Varadhan offsetof(link_fields_buf_t, link_phys_speed), print_default_cb}, 7768002d411SSowmini Varadhan { "DUPLEX", 10, 7778002d411SSowmini Varadhan offsetof(link_fields_buf_t, link_phys_duplex), print_default_cb}, 7788002d411SSowmini Varadhan { "DEVICE", 13, 7798002d411SSowmini Varadhan offsetof(link_fields_buf_t, link_phys_device), print_default_cb}, 7808002d411SSowmini Varadhan { "FLAGS", 7, 7818002d411SSowmini Varadhan offsetof(link_fields_buf_t, link_flags), print_default_cb}, 7828002d411SSowmini Varadhan { NULL, 0, NULL, 0}} 783e7801d59Ssowmini ; 784e7801d59Ssowmini 785e7801d59Ssowmini /* 786da14cebeSEric Cheng * structures for 'dladm show-phys -m' 787da14cebeSEric Cheng */ 788da14cebeSEric Cheng 789da14cebeSEric Cheng typedef enum { 790da14cebeSEric Cheng PHYS_M_LINK, 791da14cebeSEric Cheng PHYS_M_SLOT, 792da14cebeSEric Cheng PHYS_M_ADDRESS, 793da14cebeSEric Cheng PHYS_M_INUSE, 794da14cebeSEric Cheng PHYS_M_CLIENT 795da14cebeSEric Cheng } phys_m_field_index_t; 796da14cebeSEric Cheng 7972b24ab6bSSebastien Roy static const ofmt_field_t phys_m_fields[] = { 7988002d411SSowmini Varadhan /* name, field width, offset */ 7998002d411SSowmini Varadhan { "LINK", 13, PHYS_M_LINK, print_phys_one_mac_cb}, 8008002d411SSowmini Varadhan { "SLOT", 9, PHYS_M_SLOT, print_phys_one_mac_cb}, 8018002d411SSowmini Varadhan { "ADDRESS", 19, PHYS_M_ADDRESS, print_phys_one_mac_cb}, 8028002d411SSowmini Varadhan { "INUSE", 5, PHYS_M_INUSE, print_phys_one_mac_cb}, 8038002d411SSowmini Varadhan { "CLIENT", 13, PHYS_M_CLIENT, print_phys_one_mac_cb}, 8048002d411SSowmini Varadhan { NULL, 0, 0, NULL}} 805da14cebeSEric Cheng ; 806da14cebeSEric Cheng 807da14cebeSEric Cheng /* 808da14cebeSEric Cheng * structures for 'dladm show-phys -H' 809da14cebeSEric Cheng */ 810da14cebeSEric Cheng 811da14cebeSEric Cheng typedef enum { 812da14cebeSEric Cheng PHYS_H_LINK, 813*0dc2366fSVenugopal Iyer PHYS_H_RINGTYPE, 814da14cebeSEric Cheng PHYS_H_RINGS, 815da14cebeSEric Cheng PHYS_H_CLIENTS 816da14cebeSEric Cheng } phys_h_field_index_t; 817da14cebeSEric Cheng 818*0dc2366fSVenugopal Iyer #define RINGSTRLEN 21 819*0dc2366fSVenugopal Iyer 8202b24ab6bSSebastien Roy static const ofmt_field_t phys_h_fields[] = { 8218002d411SSowmini Varadhan { "LINK", 13, PHYS_H_LINK, print_phys_one_hwgrp_cb}, 822*0dc2366fSVenugopal Iyer { "RINGTYPE", 9, PHYS_H_RINGTYPE, print_phys_one_hwgrp_cb}, 823*0dc2366fSVenugopal Iyer { "RINGS", RINGSTRLEN, PHYS_H_RINGS, print_phys_one_hwgrp_cb}, 824*0dc2366fSVenugopal Iyer { "CLIENTS", 24, PHYS_H_CLIENTS, print_phys_one_hwgrp_cb}, 8258002d411SSowmini Varadhan { NULL, 0, 0, NULL}} 826da14cebeSEric Cheng ; 827da14cebeSEric Cheng 828da14cebeSEric Cheng /* 829e7801d59Ssowmini * structures for 'dladm show-vlan' 830e7801d59Ssowmini */ 8312b24ab6bSSebastien Roy static const ofmt_field_t vlan_fields[] = { 8328002d411SSowmini Varadhan { "LINK", 16, 8338002d411SSowmini Varadhan offsetof(link_fields_buf_t, link_name), print_default_cb}, 8348002d411SSowmini Varadhan { "VID", 9, 8358002d411SSowmini Varadhan offsetof(link_fields_buf_t, link_vlan_vid), print_default_cb}, 8368002d411SSowmini Varadhan { "OVER", 13, 8378002d411SSowmini Varadhan offsetof(link_fields_buf_t, link_over), print_default_cb}, 8388002d411SSowmini Varadhan { "FLAGS", 7, 8398002d411SSowmini Varadhan offsetof(link_fields_buf_t, link_flags), print_default_cb}, 8408002d411SSowmini Varadhan { NULL, 0, 0, NULL}} 841e7801d59Ssowmini ; 842da14cebeSEric Cheng 843e7801d59Ssowmini /* 8448002d411SSowmini Varadhan * structures common to 'dladm scan-wifi' and 'dladm show-wifi' 8458002d411SSowmini Varadhan * callback will be determined in parse_wifi_fields. 846e7801d59Ssowmini */ 8478002d411SSowmini Varadhan static ofmt_field_t wifi_common_fields[] = { 8488002d411SSowmini Varadhan { "LINK", 11, 0, NULL}, 8498002d411SSowmini Varadhan { "ESSID", 20, DLADM_WLAN_ATTR_ESSID, NULL}, 8508002d411SSowmini Varadhan { "BSSID", 18, DLADM_WLAN_ATTR_BSSID, NULL}, 8518002d411SSowmini Varadhan { "IBSSID", 18, DLADM_WLAN_ATTR_BSSID, NULL}, 8528002d411SSowmini Varadhan { "MODE", 7, DLADM_WLAN_ATTR_MODE, NULL}, 8538002d411SSowmini Varadhan { "SPEED", 7, DLADM_WLAN_ATTR_SPEED, NULL}, 8548002d411SSowmini Varadhan { "BSSTYPE", 9, DLADM_WLAN_ATTR_BSSTYPE, NULL}, 8558002d411SSowmini Varadhan { "SEC", 7, DLADM_WLAN_ATTR_SECMODE, NULL}, 8568002d411SSowmini Varadhan { "STRENGTH", 11, DLADM_WLAN_ATTR_STRENGTH, NULL}, 8578002d411SSowmini Varadhan { NULL, 0, 0, NULL}}; 8588002d411SSowmini Varadhan 8598002d411SSowmini Varadhan /* 8608002d411SSowmini Varadhan * the 'show-wifi' command supports all the fields in wifi_common_fields 8618002d411SSowmini Varadhan * plus the AUTH and STATUS fields. 8628002d411SSowmini Varadhan */ 8638002d411SSowmini Varadhan static ofmt_field_t wifi_show_fields[A_CNT(wifi_common_fields) + 2] = { 8648002d411SSowmini Varadhan { "AUTH", 9, DLADM_WLAN_ATTR_AUTH, NULL}, 8658002d411SSowmini Varadhan { "STATUS", 18, DLADM_WLAN_LINKATTR_STATUS, print_wifi_status_cb}, 8668002d411SSowmini Varadhan /* copy wifi_common_fields here */ 8678002d411SSowmini Varadhan }; 868e7801d59Ssowmini 869e7801d59Ssowmini static char *all_scan_wifi_fields = 870e7801d59Ssowmini "link,essid,bssid,sec,strength,mode,speed,bsstype"; 871e7801d59Ssowmini static char *all_show_wifi_fields = 872e7801d59Ssowmini "link,status,essid,sec,strength,mode,speed,auth,bssid,bsstype"; 873e7801d59Ssowmini static char *def_scan_wifi_fields = 874e7801d59Ssowmini "link,essid,bssid,sec,strength,mode,speed"; 875e7801d59Ssowmini static char *def_show_wifi_fields = 876e7801d59Ssowmini "link,status,essid,sec,strength,mode,speed"; 877e7801d59Ssowmini 878e7801d59Ssowmini /* 879e7801d59Ssowmini * structures for 'dladm show-linkprop' 880e7801d59Ssowmini */ 881e7801d59Ssowmini typedef enum { 882e7801d59Ssowmini LINKPROP_LINK, 883e7801d59Ssowmini LINKPROP_PROPERTY, 884afdda45fSVasumathi Sundaram - Sun Microsystems LINKPROP_PERM, 885e7801d59Ssowmini LINKPROP_VALUE, 886e7801d59Ssowmini LINKPROP_DEFAULT, 887e7801d59Ssowmini LINKPROP_POSSIBLE 888e7801d59Ssowmini } linkprop_field_index_t; 889e7801d59Ssowmini 8902b24ab6bSSebastien Roy static const ofmt_field_t linkprop_fields[] = { 8918002d411SSowmini Varadhan /* name, field width, index */ 8928002d411SSowmini Varadhan { "LINK", 13, LINKPROP_LINK, print_linkprop_cb}, 8938002d411SSowmini Varadhan { "PROPERTY", 16, LINKPROP_PROPERTY, print_linkprop_cb}, 8948002d411SSowmini Varadhan { "PERM", 5, LINKPROP_PERM, print_linkprop_cb}, 8958002d411SSowmini Varadhan { "VALUE", 15, LINKPROP_VALUE, print_linkprop_cb}, 8968002d411SSowmini Varadhan { "DEFAULT", 15, LINKPROP_DEFAULT, print_linkprop_cb}, 89725ec3e3dSEric Cheng { "POSSIBLE", 20, LINKPROP_POSSIBLE, print_linkprop_cb}, 8988002d411SSowmini Varadhan { NULL, 0, 0, NULL}} 899e7801d59Ssowmini ; 900e7801d59Ssowmini 901e7801d59Ssowmini #define MAX_PROP_LINE 512 902e7801d59Ssowmini 903e7801d59Ssowmini typedef struct show_linkprop_state { 904e7801d59Ssowmini char ls_link[MAXLINKNAMELEN]; 905e7801d59Ssowmini char *ls_line; 906e7801d59Ssowmini char **ls_propvals; 907da14cebeSEric Cheng dladm_arg_list_t *ls_proplist; 9088002d411SSowmini Varadhan boolean_t ls_parsable; 909e7801d59Ssowmini boolean_t ls_persist; 910e7801d59Ssowmini boolean_t ls_header; 911e7801d59Ssowmini dladm_status_t ls_status; 912e7801d59Ssowmini dladm_status_t ls_retstatus; 9138002d411SSowmini Varadhan ofmt_handle_t ls_ofmt; 914e7801d59Ssowmini } show_linkprop_state_t; 915e7801d59Ssowmini 916da14cebeSEric Cheng typedef struct set_linkprop_state { 917da14cebeSEric Cheng const char *ls_name; 918da14cebeSEric Cheng boolean_t ls_reset; 919da14cebeSEric Cheng boolean_t ls_temp; 920da14cebeSEric Cheng dladm_status_t ls_status; 921da14cebeSEric Cheng } set_linkprop_state_t; 922da14cebeSEric Cheng 923e7801d59Ssowmini typedef struct linkprop_args_s { 924e7801d59Ssowmini show_linkprop_state_t *ls_state; 925e7801d59Ssowmini char *ls_propname; 926e7801d59Ssowmini datalink_id_t ls_linkid; 927e7801d59Ssowmini } linkprop_args_t; 928e7801d59Ssowmini 929e7801d59Ssowmini /* 930e7801d59Ssowmini * structures for 'dladm show-secobj' 931e7801d59Ssowmini */ 932e7801d59Ssowmini typedef struct secobj_fields_buf_s { 933e7801d59Ssowmini char ss_obj_name[DLADM_SECOBJ_VAL_MAX]; 934e7801d59Ssowmini char ss_class[20]; 935e7801d59Ssowmini char ss_val[30]; 936e7801d59Ssowmini } secobj_fields_buf_t; 9378002d411SSowmini Varadhan 9382b24ab6bSSebastien Roy static const ofmt_field_t secobj_fields[] = { 9398002d411SSowmini Varadhan { "OBJECT", 21, 9408002d411SSowmini Varadhan offsetof(secobj_fields_buf_t, ss_obj_name), print_default_cb}, 9418002d411SSowmini Varadhan { "CLASS", 21, 9428002d411SSowmini Varadhan offsetof(secobj_fields_buf_t, ss_class), print_default_cb}, 9438002d411SSowmini Varadhan { "VALUE", 31, 9448002d411SSowmini Varadhan offsetof(secobj_fields_buf_t, ss_val), print_default_cb}, 9458002d411SSowmini Varadhan { NULL, 0, 0, NULL}} 946e7801d59Ssowmini ; 9470ba2cbe9Sxc151355 948da14cebeSEric Cheng /* 949da14cebeSEric Cheng * structures for 'dladm show-vnic' 950da14cebeSEric Cheng */ 951da14cebeSEric Cheng typedef struct vnic_fields_buf_s 952da14cebeSEric Cheng { 953da14cebeSEric Cheng char vnic_link[DLPI_LINKNAME_MAX]; 954da14cebeSEric Cheng char vnic_over[DLPI_LINKNAME_MAX]; 955da14cebeSEric Cheng char vnic_speed[6]; 956b509e89bSRishi Srivatsavai char vnic_macaddr[18]; 957da14cebeSEric Cheng char vnic_macaddrtype[19]; 958da14cebeSEric Cheng char vnic_vid[6]; 959da14cebeSEric Cheng } vnic_fields_buf_t; 960da14cebeSEric Cheng 9612b24ab6bSSebastien Roy static const ofmt_field_t vnic_fields[] = { 9628002d411SSowmini Varadhan { "LINK", 13, 9638002d411SSowmini Varadhan offsetof(vnic_fields_buf_t, vnic_link), print_default_cb}, 9648002d411SSowmini Varadhan { "OVER", 13, 9658002d411SSowmini Varadhan offsetof(vnic_fields_buf_t, vnic_over), print_default_cb}, 9668002d411SSowmini Varadhan { "SPEED", 7, 9678002d411SSowmini Varadhan offsetof(vnic_fields_buf_t, vnic_speed), print_default_cb}, 968b509e89bSRishi Srivatsavai { "MACADDRESS", 18, 9698002d411SSowmini Varadhan offsetof(vnic_fields_buf_t, vnic_macaddr), print_default_cb}, 9708002d411SSowmini Varadhan { "MACADDRTYPE", 20, 9718002d411SSowmini Varadhan offsetof(vnic_fields_buf_t, vnic_macaddrtype), print_default_cb}, 9728002d411SSowmini Varadhan { "VID", 7, 9738002d411SSowmini Varadhan offsetof(vnic_fields_buf_t, vnic_vid), print_default_cb}, 9748002d411SSowmini Varadhan { NULL, 0, 0, NULL}} 975da14cebeSEric Cheng ; 976da14cebeSEric Cheng 977da14cebeSEric Cheng /* 978b509e89bSRishi Srivatsavai * structures for 'dladm show-simnet' 979b509e89bSRishi Srivatsavai */ 980b509e89bSRishi Srivatsavai typedef struct simnet_fields_buf_s 981b509e89bSRishi Srivatsavai { 982b509e89bSRishi Srivatsavai char simnet_name[DLPI_LINKNAME_MAX]; 983b509e89bSRishi Srivatsavai char simnet_media[DLADM_STRSIZE]; 984b509e89bSRishi Srivatsavai char simnet_macaddr[18]; 985b509e89bSRishi Srivatsavai char simnet_otherlink[DLPI_LINKNAME_MAX]; 986b509e89bSRishi Srivatsavai } simnet_fields_buf_t; 987b509e89bSRishi Srivatsavai 9882b24ab6bSSebastien Roy static const ofmt_field_t simnet_fields[] = { 989b509e89bSRishi Srivatsavai { "LINK", 12, 990b509e89bSRishi Srivatsavai offsetof(simnet_fields_buf_t, simnet_name), print_default_cb}, 991b509e89bSRishi Srivatsavai { "MEDIA", 20, 992b509e89bSRishi Srivatsavai offsetof(simnet_fields_buf_t, simnet_media), print_default_cb}, 993b509e89bSRishi Srivatsavai { "MACADDRESS", 18, 994b509e89bSRishi Srivatsavai offsetof(simnet_fields_buf_t, simnet_macaddr), print_default_cb}, 995b509e89bSRishi Srivatsavai { "OTHERLINK", 12, 996b509e89bSRishi Srivatsavai offsetof(simnet_fields_buf_t, simnet_otherlink), print_default_cb}, 997b509e89bSRishi Srivatsavai { NULL, 0, 0, NULL}} 998b509e89bSRishi Srivatsavai ; 999b509e89bSRishi Srivatsavai 1000b509e89bSRishi Srivatsavai /* 1001da14cebeSEric Cheng * structures for 'dladm show-usage' 1002da14cebeSEric Cheng */ 1003da14cebeSEric Cheng 1004da14cebeSEric Cheng typedef struct usage_fields_buf_s { 1005da14cebeSEric Cheng char usage_link[12]; 1006da14cebeSEric Cheng char usage_duration[10]; 1007da14cebeSEric Cheng char usage_ipackets[9]; 1008da14cebeSEric Cheng char usage_rbytes[10]; 1009da14cebeSEric Cheng char usage_opackets[9]; 1010da14cebeSEric Cheng char usage_obytes[10]; 1011da14cebeSEric Cheng char usage_bandwidth[14]; 1012da14cebeSEric Cheng } usage_fields_buf_t; 1013da14cebeSEric Cheng 10142b24ab6bSSebastien Roy static const ofmt_field_t usage_fields[] = { 10158002d411SSowmini Varadhan { "LINK", 13, 10168002d411SSowmini Varadhan offsetof(usage_fields_buf_t, usage_link), print_default_cb}, 10178002d411SSowmini Varadhan { "DURATION", 11, 10188002d411SSowmini Varadhan offsetof(usage_fields_buf_t, usage_duration), print_default_cb}, 10198002d411SSowmini Varadhan { "IPACKETS", 10, 10208002d411SSowmini Varadhan offsetof(usage_fields_buf_t, usage_ipackets), print_default_cb}, 10218002d411SSowmini Varadhan { "RBYTES", 11, 10228002d411SSowmini Varadhan offsetof(usage_fields_buf_t, usage_rbytes), print_default_cb}, 10238002d411SSowmini Varadhan { "OPACKETS", 10, 10248002d411SSowmini Varadhan offsetof(usage_fields_buf_t, usage_opackets), print_default_cb}, 10258002d411SSowmini Varadhan { "OBYTES", 11, 10268002d411SSowmini Varadhan offsetof(usage_fields_buf_t, usage_obytes), print_default_cb}, 10278002d411SSowmini Varadhan { "BANDWIDTH", 15, 10288002d411SSowmini Varadhan offsetof(usage_fields_buf_t, usage_bandwidth), print_default_cb}, 10298002d411SSowmini Varadhan { NULL, 0, 0, NULL}} 1030da14cebeSEric Cheng ; 1031da14cebeSEric Cheng 1032da14cebeSEric Cheng 1033da14cebeSEric Cheng /* 1034da14cebeSEric Cheng * structures for 'dladm show-usage link' 1035da14cebeSEric Cheng */ 1036da14cebeSEric Cheng 1037da14cebeSEric Cheng typedef struct usage_l_fields_buf_s { 1038da14cebeSEric Cheng char usage_l_link[12]; 1039da14cebeSEric Cheng char usage_l_stime[13]; 1040da14cebeSEric Cheng char usage_l_etime[13]; 1041da14cebeSEric Cheng char usage_l_rbytes[8]; 1042da14cebeSEric Cheng char usage_l_obytes[8]; 1043da14cebeSEric Cheng char usage_l_bandwidth[14]; 1044da14cebeSEric Cheng } usage_l_fields_buf_t; 1045da14cebeSEric Cheng 10462b24ab6bSSebastien Roy static const ofmt_field_t usage_l_fields[] = { 10478002d411SSowmini Varadhan /* name, field width, offset */ 10488002d411SSowmini Varadhan { "LINK", 13, 10498002d411SSowmini Varadhan offsetof(usage_l_fields_buf_t, usage_l_link), print_default_cb}, 10508002d411SSowmini Varadhan { "START", 14, 10518002d411SSowmini Varadhan offsetof(usage_l_fields_buf_t, usage_l_stime), print_default_cb}, 10528002d411SSowmini Varadhan { "END", 14, 10538002d411SSowmini Varadhan offsetof(usage_l_fields_buf_t, usage_l_etime), print_default_cb}, 10548002d411SSowmini Varadhan { "RBYTES", 9, 10558002d411SSowmini Varadhan offsetof(usage_l_fields_buf_t, usage_l_rbytes), print_default_cb}, 10568002d411SSowmini Varadhan { "OBYTES", 9, 10578002d411SSowmini Varadhan offsetof(usage_l_fields_buf_t, usage_l_obytes), print_default_cb}, 10588002d411SSowmini Varadhan { "BANDWIDTH", 15, 10598002d411SSowmini Varadhan offsetof(usage_l_fields_buf_t, usage_l_bandwidth), print_default_cb}, 10608002d411SSowmini Varadhan { NULL, 0, 0, NULL}} 1061da14cebeSEric Cheng ; 1062da14cebeSEric Cheng 10632b24ab6bSSebastien Roy /* IPTUN_*FLAG_INDEX values are indices into iptun_flags below. */ 10642b24ab6bSSebastien Roy enum { IPTUN_SFLAG_INDEX, IPTUN_IFLAG_INDEX, IPTUN_NUM_FLAGS }; 10652b24ab6bSSebastien Roy 10662b24ab6bSSebastien Roy /* 10672b24ab6bSSebastien Roy * structures for 'dladm show-iptun' 10682b24ab6bSSebastien Roy */ 10692b24ab6bSSebastien Roy typedef struct iptun_fields_buf_s { 10702b24ab6bSSebastien Roy char iptun_name[MAXLINKNAMELEN]; 10712b24ab6bSSebastien Roy char iptun_type[5]; 10722b24ab6bSSebastien Roy char iptun_laddr[NI_MAXHOST]; 10732b24ab6bSSebastien Roy char iptun_raddr[NI_MAXHOST]; 10742b24ab6bSSebastien Roy char iptun_flags[IPTUN_NUM_FLAGS + 1]; 10752b24ab6bSSebastien Roy } iptun_fields_buf_t; 10762b24ab6bSSebastien Roy 10772b24ab6bSSebastien Roy static const ofmt_field_t iptun_fields[] = { 10782b24ab6bSSebastien Roy { "LINK", 16, 10792b24ab6bSSebastien Roy offsetof(iptun_fields_buf_t, iptun_name), print_default_cb }, 10802b24ab6bSSebastien Roy { "TYPE", 6, 10812b24ab6bSSebastien Roy offsetof(iptun_fields_buf_t, iptun_type), print_default_cb }, 10822b24ab6bSSebastien Roy { "FLAGS", 7, 10832b24ab6bSSebastien Roy offsetof(iptun_fields_buf_t, iptun_flags), print_default_cb }, 10842b24ab6bSSebastien Roy { "LOCAL", 20, 10852b24ab6bSSebastien Roy offsetof(iptun_fields_buf_t, iptun_laddr), print_default_cb }, 10862b24ab6bSSebastien Roy { "REMOTE", 20, 10872b24ab6bSSebastien Roy offsetof(iptun_fields_buf_t, iptun_raddr), print_default_cb }, 10882b24ab6bSSebastien Roy { NULL, 0, 0, NULL} 10892b24ab6bSSebastien Roy }; 10902b24ab6bSSebastien Roy 10914eaa4710SRishi Srivatsavai /* 10924eaa4710SRishi Srivatsavai * structures for 'dladm show-bridge'. These are based on sections 14.8.1.1.3 10934eaa4710SRishi Srivatsavai * and 14.8.1.2.2 of IEEE 802.1D-2004. 10944eaa4710SRishi Srivatsavai */ 10954eaa4710SRishi Srivatsavai typedef struct bridge_fields_buf_s { 10964eaa4710SRishi Srivatsavai char bridge_name[MAXLINKNAMELEN]; /* 14.4.1.2.3(b) */ 10974eaa4710SRishi Srivatsavai char bridge_protect[7]; /* stp or trill */ 10984eaa4710SRishi Srivatsavai char bridge_address[24]; /* 17.18.3, 7.12.5, 14.4.1.2.3(a) */ 10994eaa4710SRishi Srivatsavai char bridge_priority[7]; /* 17.18.3 9.2.5 - only upper 4 bits */ 11004eaa4710SRishi Srivatsavai char bridge_bmaxage[7]; /* 17.18.4 configured */ 11014eaa4710SRishi Srivatsavai char bridge_bhellotime[7]; /* 17.18.4 configured */ 11024eaa4710SRishi Srivatsavai char bridge_bfwddelay[7]; /* 17.18.4 configured */ 11034eaa4710SRishi Srivatsavai char bridge_forceproto[3]; /* 17.13.4 configured */ 11044eaa4710SRishi Srivatsavai char bridge_tctime[12]; /* 14.8.1.1.3(b) */ 11054eaa4710SRishi Srivatsavai char bridge_tccount[12]; /* 17.17.8 */ 11064eaa4710SRishi Srivatsavai char bridge_tchange[12]; /* 17.17.8 */ 11074eaa4710SRishi Srivatsavai char bridge_desroot[24]; /* 17.18.6 priority "/" MAC */ 11084eaa4710SRishi Srivatsavai char bridge_rootcost[12]; /* 17.18.6 */ 11094eaa4710SRishi Srivatsavai char bridge_rootport[12]; /* 17.18.6 */ 11104eaa4710SRishi Srivatsavai char bridge_maxage[7]; /* 17.18.7 for root */ 11114eaa4710SRishi Srivatsavai char bridge_hellotime[7]; /* 17.13.6 for root */ 11124eaa4710SRishi Srivatsavai char bridge_fwddelay[7]; /* 17.13.5 for root */ 11134eaa4710SRishi Srivatsavai char bridge_holdtime[12]; /* 17.13.12 for root */ 11144eaa4710SRishi Srivatsavai } bridge_fields_buf_t; 11154eaa4710SRishi Srivatsavai 11164eaa4710SRishi Srivatsavai static ofmt_field_t bridge_fields[] = { 11174eaa4710SRishi Srivatsavai /* name, field width, offset, callback */ 11184eaa4710SRishi Srivatsavai { "BRIDGE", 12, 11194eaa4710SRishi Srivatsavai offsetof(bridge_fields_buf_t, bridge_name), print_default_cb }, 11204eaa4710SRishi Srivatsavai { "PROTECT", 8, 11214eaa4710SRishi Srivatsavai offsetof(bridge_fields_buf_t, bridge_protect), print_default_cb }, 11224eaa4710SRishi Srivatsavai { "ADDRESS", 19, 11234eaa4710SRishi Srivatsavai offsetof(bridge_fields_buf_t, bridge_address), print_default_cb }, 11244eaa4710SRishi Srivatsavai { "PRIORITY", 9, 11254eaa4710SRishi Srivatsavai offsetof(bridge_fields_buf_t, bridge_priority), print_default_cb }, 11264eaa4710SRishi Srivatsavai { "BMAXAGE", 8, 11274eaa4710SRishi Srivatsavai offsetof(bridge_fields_buf_t, bridge_bmaxage), print_default_cb }, 11284eaa4710SRishi Srivatsavai { "BHELLOTIME", 11, 11294eaa4710SRishi Srivatsavai offsetof(bridge_fields_buf_t, bridge_bhellotime), print_default_cb }, 11304eaa4710SRishi Srivatsavai { "BFWDDELAY", 10, 11314eaa4710SRishi Srivatsavai offsetof(bridge_fields_buf_t, bridge_bfwddelay), print_default_cb }, 11324eaa4710SRishi Srivatsavai { "FORCEPROTO", 11, 11334eaa4710SRishi Srivatsavai offsetof(bridge_fields_buf_t, bridge_forceproto), print_default_cb }, 11344eaa4710SRishi Srivatsavai { "TCTIME", 10, 11354eaa4710SRishi Srivatsavai offsetof(bridge_fields_buf_t, bridge_tctime), print_default_cb }, 11364eaa4710SRishi Srivatsavai { "TCCOUNT", 10, 11374eaa4710SRishi Srivatsavai offsetof(bridge_fields_buf_t, bridge_tccount), print_default_cb }, 11384eaa4710SRishi Srivatsavai { "TCHANGE", 10, 11394eaa4710SRishi Srivatsavai offsetof(bridge_fields_buf_t, bridge_tchange), print_default_cb }, 11404eaa4710SRishi Srivatsavai { "DESROOT", 23, 11414eaa4710SRishi Srivatsavai offsetof(bridge_fields_buf_t, bridge_desroot), print_default_cb }, 11424eaa4710SRishi Srivatsavai { "ROOTCOST", 11, 11434eaa4710SRishi Srivatsavai offsetof(bridge_fields_buf_t, bridge_rootcost), print_default_cb }, 11444eaa4710SRishi Srivatsavai { "ROOTPORT", 11, 11454eaa4710SRishi Srivatsavai offsetof(bridge_fields_buf_t, bridge_rootport), print_default_cb }, 11464eaa4710SRishi Srivatsavai { "MAXAGE", 8, 11474eaa4710SRishi Srivatsavai offsetof(bridge_fields_buf_t, bridge_maxage), print_default_cb }, 11484eaa4710SRishi Srivatsavai { "HELLOTIME", 10, 11494eaa4710SRishi Srivatsavai offsetof(bridge_fields_buf_t, bridge_hellotime), print_default_cb }, 11504eaa4710SRishi Srivatsavai { "FWDDELAY", 9, 11514eaa4710SRishi Srivatsavai offsetof(bridge_fields_buf_t, bridge_fwddelay), print_default_cb }, 11524eaa4710SRishi Srivatsavai { "HOLDTIME", 9, 11534eaa4710SRishi Srivatsavai offsetof(bridge_fields_buf_t, bridge_holdtime), print_default_cb }, 11544eaa4710SRishi Srivatsavai { NULL, 0, 0, NULL}}; 11554eaa4710SRishi Srivatsavai 11564eaa4710SRishi Srivatsavai /* 11574eaa4710SRishi Srivatsavai * structures for 'dladm show-bridge -l'. These are based on 14.4.1.2.3 and 11584eaa4710SRishi Srivatsavai * 14.8.2.1.3 of IEEE 802.1D-2004. 11594eaa4710SRishi Srivatsavai */ 11604eaa4710SRishi Srivatsavai typedef struct bridge_link_fields_buf_s { 11614eaa4710SRishi Srivatsavai char bridgel_link[MAXLINKNAMELEN]; 11624eaa4710SRishi Srivatsavai char bridgel_index[7]; /* 14.4.1.2.3(d1) */ 11634eaa4710SRishi Srivatsavai char bridgel_state[11]; /* 14.8.2.1.3(b) */ 11644eaa4710SRishi Srivatsavai char bridgel_uptime[7]; /* 14.8.2.1.3(a) */ 11654eaa4710SRishi Srivatsavai char bridgel_opercost[7] /* 14.8.2.1.3(d) */; 11664eaa4710SRishi Srivatsavai char bridgel_operp2p[4]; /* 14.8.2.1.3(p) */ 11674eaa4710SRishi Srivatsavai char bridgel_operedge[4]; /* 14.8.2.1.3(k) */ 11684eaa4710SRishi Srivatsavai char bridgel_desroot[23]; /* 14.8.2.1.3(e) */ 11694eaa4710SRishi Srivatsavai char bridgel_descost[12]; /* 14.8.2.1.3(f) */ 11704eaa4710SRishi Srivatsavai char bridgel_desbridge[23]; /* 14.8.2.1.3(g) */ 11714eaa4710SRishi Srivatsavai char bridgel_desport[7]; /* 14.8.2.1.3(h) */ 11724eaa4710SRishi Srivatsavai char bridgel_tcack[4]; /* 14.8.2.1.3(i) */ 11734eaa4710SRishi Srivatsavai } bridge_link_fields_buf_t; 11744eaa4710SRishi Srivatsavai 11754eaa4710SRishi Srivatsavai static ofmt_field_t bridge_link_fields[] = { 11764eaa4710SRishi Srivatsavai /* name, field width, offset, callback */ 11774eaa4710SRishi Srivatsavai { "LINK", 12, 11784eaa4710SRishi Srivatsavai offsetof(bridge_link_fields_buf_t, bridgel_link), print_default_cb }, 11794eaa4710SRishi Srivatsavai { "INDEX", 8, 11804eaa4710SRishi Srivatsavai offsetof(bridge_link_fields_buf_t, bridgel_index), print_default_cb }, 11814eaa4710SRishi Srivatsavai { "STATE", 12, 11824eaa4710SRishi Srivatsavai offsetof(bridge_link_fields_buf_t, bridgel_state), print_default_cb }, 11834eaa4710SRishi Srivatsavai { "UPTIME", 8, 11844eaa4710SRishi Srivatsavai offsetof(bridge_link_fields_buf_t, bridgel_uptime), print_default_cb }, 11854eaa4710SRishi Srivatsavai { "OPERCOST", 9, 11864eaa4710SRishi Srivatsavai offsetof(bridge_link_fields_buf_t, bridgel_opercost), print_default_cb }, 11874eaa4710SRishi Srivatsavai { "OPERP2P", 8, 11884eaa4710SRishi Srivatsavai offsetof(bridge_link_fields_buf_t, bridgel_operp2p), print_default_cb }, 11894eaa4710SRishi Srivatsavai { "OPEREDGE", 9, 11904eaa4710SRishi Srivatsavai offsetof(bridge_link_fields_buf_t, bridgel_operedge), print_default_cb }, 11914eaa4710SRishi Srivatsavai { "DESROOT", 22, 11924eaa4710SRishi Srivatsavai offsetof(bridge_link_fields_buf_t, bridgel_desroot), print_default_cb }, 11934eaa4710SRishi Srivatsavai { "DESCOST", 11, 11944eaa4710SRishi Srivatsavai offsetof(bridge_link_fields_buf_t, bridgel_descost), print_default_cb }, 11954eaa4710SRishi Srivatsavai { "DESBRIDGE", 22, 11964eaa4710SRishi Srivatsavai offsetof(bridge_link_fields_buf_t, bridgel_desbridge), print_default_cb }, 11974eaa4710SRishi Srivatsavai { "DESPORT", 8, 11984eaa4710SRishi Srivatsavai offsetof(bridge_link_fields_buf_t, bridgel_desport), print_default_cb }, 11994eaa4710SRishi Srivatsavai { "TCACK", 6, 12004eaa4710SRishi Srivatsavai offsetof(bridge_link_fields_buf_t, bridgel_tcack), print_default_cb }, 12014eaa4710SRishi Srivatsavai { NULL, 0, 0, NULL}}; 12024eaa4710SRishi Srivatsavai 12034eaa4710SRishi Srivatsavai /* 12044eaa4710SRishi Srivatsavai * structures for 'dladm show-bridge -s'. These are not based on IEEE 12054eaa4710SRishi Srivatsavai * 802.1D-2004. 12064eaa4710SRishi Srivatsavai */ 12074eaa4710SRishi Srivatsavai #define ULONG_DIG (((sizeof (ulong_t) * NBBY) * 3 / 10) + 1) 12084eaa4710SRishi Srivatsavai #define UINT64_DIG (((sizeof (uint64_t) * NBBY) * 3 / 10) + 1) 12094eaa4710SRishi Srivatsavai typedef struct bridge_statfields_buf_s { 12104eaa4710SRishi Srivatsavai char bridges_name[MAXLINKNAMELEN]; 12114eaa4710SRishi Srivatsavai char bridges_drops[UINT64_DIG]; 12124eaa4710SRishi Srivatsavai char bridges_forwards[UINT64_DIG]; 12134eaa4710SRishi Srivatsavai char bridges_mbcast[UINT64_DIG]; 12144eaa4710SRishi Srivatsavai char bridges_unknown[UINT64_DIG]; 12154eaa4710SRishi Srivatsavai char bridges_recv[UINT64_DIG]; 12164eaa4710SRishi Srivatsavai char bridges_sent[UINT64_DIG]; 12174eaa4710SRishi Srivatsavai } bridge_statfields_buf_t; 12184eaa4710SRishi Srivatsavai 12194eaa4710SRishi Srivatsavai static ofmt_field_t bridge_statfields[] = { 12204eaa4710SRishi Srivatsavai /* name, field width, offset, callback */ 12214eaa4710SRishi Srivatsavai { "BRIDGE", 12, 12224eaa4710SRishi Srivatsavai offsetof(bridge_statfields_buf_t, bridges_name), print_default_cb }, 12234eaa4710SRishi Srivatsavai { "DROPS", 12, 12244eaa4710SRishi Srivatsavai offsetof(bridge_statfields_buf_t, bridges_drops), print_default_cb }, 12254eaa4710SRishi Srivatsavai { "FORWARDS", 12, 12264eaa4710SRishi Srivatsavai offsetof(bridge_statfields_buf_t, bridges_forwards), print_default_cb }, 12274eaa4710SRishi Srivatsavai { "MBCAST", 12, 12284eaa4710SRishi Srivatsavai offsetof(bridge_statfields_buf_t, bridges_mbcast), print_default_cb }, 12294eaa4710SRishi Srivatsavai { "UNKNOWN", 12, 12304eaa4710SRishi Srivatsavai offsetof(bridge_statfields_buf_t, bridges_unknown), print_default_cb }, 12314eaa4710SRishi Srivatsavai { "RECV", 12, 12324eaa4710SRishi Srivatsavai offsetof(bridge_statfields_buf_t, bridges_recv), print_default_cb }, 12334eaa4710SRishi Srivatsavai { "SENT", 12, 12344eaa4710SRishi Srivatsavai offsetof(bridge_statfields_buf_t, bridges_sent), print_default_cb }, 12354eaa4710SRishi Srivatsavai { NULL, 0, 0, NULL}}; 12364eaa4710SRishi Srivatsavai 12374eaa4710SRishi Srivatsavai /* 12384eaa4710SRishi Srivatsavai * structures for 'dladm show-bridge -s -l'. These are based in part on 12394eaa4710SRishi Srivatsavai * section 14.6.1.1.3 of IEEE 802.1D-2004. 12404eaa4710SRishi Srivatsavai */ 12414eaa4710SRishi Srivatsavai typedef struct bridge_link_statfields_buf_s { 12424eaa4710SRishi Srivatsavai char bridgels_link[MAXLINKNAMELEN]; 12434eaa4710SRishi Srivatsavai char bridgels_cfgbpdu[ULONG_DIG]; 12444eaa4710SRishi Srivatsavai char bridgels_tcnbpdu[ULONG_DIG]; 12454eaa4710SRishi Srivatsavai char bridgels_rstpbpdu[ULONG_DIG]; 12464eaa4710SRishi Srivatsavai char bridgels_txbpdu[ULONG_DIG]; 12474eaa4710SRishi Srivatsavai char bridgels_drops[UINT64_DIG]; /* 14.6.1.1.3(d) */ 12484eaa4710SRishi Srivatsavai char bridgels_recv[UINT64_DIG]; /* 14.6.1.1.3(a) */ 12494eaa4710SRishi Srivatsavai char bridgels_xmit[UINT64_DIG]; /* 14.6.1.1.3(c) */ 12504eaa4710SRishi Srivatsavai } bridge_link_statfields_buf_t; 12514eaa4710SRishi Srivatsavai 12524eaa4710SRishi Srivatsavai static ofmt_field_t bridge_link_statfields[] = { 12534eaa4710SRishi Srivatsavai /* name, field width, offset, callback */ 12544eaa4710SRishi Srivatsavai { "LINK", 12, 12554eaa4710SRishi Srivatsavai offsetof(bridge_link_statfields_buf_t, bridgels_link), print_default_cb }, 12564eaa4710SRishi Srivatsavai { "CFGBPDU", 9, 12574eaa4710SRishi Srivatsavai offsetof(bridge_link_statfields_buf_t, bridgels_cfgbpdu), 12584eaa4710SRishi Srivatsavai print_default_cb }, 12594eaa4710SRishi Srivatsavai { "TCNBPDU", 9, 12604eaa4710SRishi Srivatsavai offsetof(bridge_link_statfields_buf_t, bridgels_tcnbpdu), 12614eaa4710SRishi Srivatsavai print_default_cb }, 12624eaa4710SRishi Srivatsavai { "RSTPBPDU", 9, 12634eaa4710SRishi Srivatsavai offsetof(bridge_link_statfields_buf_t, bridgels_rstpbpdu), 12644eaa4710SRishi Srivatsavai print_default_cb }, 12654eaa4710SRishi Srivatsavai { "TXBPDU", 9, 12664eaa4710SRishi Srivatsavai offsetof(bridge_link_statfields_buf_t, bridgels_txbpdu), print_default_cb }, 12674eaa4710SRishi Srivatsavai { "DROPS", 9, 12684eaa4710SRishi Srivatsavai offsetof(bridge_link_statfields_buf_t, bridgels_drops), print_default_cb }, 12694eaa4710SRishi Srivatsavai { "RECV", 9, 12704eaa4710SRishi Srivatsavai offsetof(bridge_link_statfields_buf_t, bridgels_recv), print_default_cb }, 12714eaa4710SRishi Srivatsavai { "XMIT", 9, 12724eaa4710SRishi Srivatsavai offsetof(bridge_link_statfields_buf_t, bridgels_xmit), print_default_cb }, 12734eaa4710SRishi Srivatsavai { NULL, 0, 0, NULL}}; 12744eaa4710SRishi Srivatsavai 12754eaa4710SRishi Srivatsavai /* 12764eaa4710SRishi Srivatsavai * structures for 'dladm show-bridge -f'. These are based in part on 12774eaa4710SRishi Srivatsavai * section 14.7.6.3.3 of IEEE 802.1D-2004. 12784eaa4710SRishi Srivatsavai */ 12794eaa4710SRishi Srivatsavai typedef struct bridge_fwd_fields_buf_s { 12804eaa4710SRishi Srivatsavai char bridgef_dest[18]; /* 14.7.6.3.3(a) */ 12814eaa4710SRishi Srivatsavai char bridgef_age[8]; 12824eaa4710SRishi Srivatsavai char bridgef_flags[6]; 12834eaa4710SRishi Srivatsavai char bridgef_output[MAXLINKNAMELEN]; /* 14.7.6.3.3(c) */ 12844eaa4710SRishi Srivatsavai } bridge_fwd_fields_buf_t; 12854eaa4710SRishi Srivatsavai 12864eaa4710SRishi Srivatsavai static ofmt_field_t bridge_fwd_fields[] = { 12874eaa4710SRishi Srivatsavai /* name, field width, offset, callback */ 12884eaa4710SRishi Srivatsavai { "DEST", 17, 12894eaa4710SRishi Srivatsavai offsetof(bridge_fwd_fields_buf_t, bridgef_dest), print_default_cb }, 12904eaa4710SRishi Srivatsavai { "AGE", 7, 12914eaa4710SRishi Srivatsavai offsetof(bridge_fwd_fields_buf_t, bridgef_age), print_default_cb }, 12924eaa4710SRishi Srivatsavai { "FLAGS", 6, 12934eaa4710SRishi Srivatsavai offsetof(bridge_fwd_fields_buf_t, bridgef_flags), print_default_cb }, 12944eaa4710SRishi Srivatsavai { "OUTPUT", 12, 12954eaa4710SRishi Srivatsavai offsetof(bridge_fwd_fields_buf_t, bridgef_output), print_default_cb }, 12964eaa4710SRishi Srivatsavai { NULL, 0, 0, NULL}}; 12974eaa4710SRishi Srivatsavai 12984eaa4710SRishi Srivatsavai /* 12994eaa4710SRishi Srivatsavai * structures for 'dladm show-bridge -t'. 13004eaa4710SRishi Srivatsavai */ 13014eaa4710SRishi Srivatsavai typedef struct bridge_trill_fields_buf_s { 13024eaa4710SRishi Srivatsavai char bridget_nick[6]; 13034eaa4710SRishi Srivatsavai char bridget_flags[6]; 13044eaa4710SRishi Srivatsavai char bridget_link[MAXLINKNAMELEN]; 13054eaa4710SRishi Srivatsavai char bridget_nexthop[18]; 13064eaa4710SRishi Srivatsavai } bridge_trill_fields_buf_t; 13074eaa4710SRishi Srivatsavai 13084eaa4710SRishi Srivatsavai static ofmt_field_t bridge_trill_fields[] = { 13094eaa4710SRishi Srivatsavai /* name, field width, offset, callback */ 13104eaa4710SRishi Srivatsavai { "NICK", 5, 13114eaa4710SRishi Srivatsavai offsetof(bridge_trill_fields_buf_t, bridget_nick), print_default_cb }, 13124eaa4710SRishi Srivatsavai { "FLAGS", 6, 13134eaa4710SRishi Srivatsavai offsetof(bridge_trill_fields_buf_t, bridget_flags), print_default_cb }, 13144eaa4710SRishi Srivatsavai { "LINK", 12, 13154eaa4710SRishi Srivatsavai offsetof(bridge_trill_fields_buf_t, bridget_link), print_default_cb }, 13164eaa4710SRishi Srivatsavai { "NEXTHOP", 17, 13174eaa4710SRishi Srivatsavai offsetof(bridge_trill_fields_buf_t, bridget_nexthop), print_default_cb }, 13184eaa4710SRishi Srivatsavai { NULL, 0, 0, NULL}}; 13194eaa4710SRishi Srivatsavai 13207c478bd9Sstevel@tonic-gate static char *progname; 13210ba2cbe9Sxc151355 static sig_atomic_t signalled; 13227c478bd9Sstevel@tonic-gate 13234ac67f02SAnurag S. Maskey /* 13244ac67f02SAnurag S. Maskey * Handle to libdladm. Opened in main() before the sub-command 13254ac67f02SAnurag S. Maskey * specific function is called. 13264ac67f02SAnurag S. Maskey */ 13274ac67f02SAnurag S. Maskey static dladm_handle_t handle = NULL; 13284ac67f02SAnurag S. Maskey 1329da14cebeSEric Cheng #define DLADM_ETHERSTUB_NAME "etherstub" 1330da14cebeSEric Cheng #define DLADM_IS_ETHERSTUB(id) (id == DATALINK_INVALID_LINKID) 1331da14cebeSEric Cheng 13327c478bd9Sstevel@tonic-gate static void 13337c478bd9Sstevel@tonic-gate usage(void) 13347c478bd9Sstevel@tonic-gate { 13358d5c46e6Sam223141 int i; 13368d5c46e6Sam223141 cmd_t *cmdp; 13378d5c46e6Sam223141 (void) fprintf(stderr, gettext("usage: dladm <subcommand> <args> ..." 13388d5c46e6Sam223141 "\n")); 13398d5c46e6Sam223141 for (i = 0; i < sizeof (cmds) / sizeof (cmds[0]); i++) { 13408d5c46e6Sam223141 cmdp = &cmds[i]; 13418d5c46e6Sam223141 if (cmdp->c_usage != NULL) 13428d5c46e6Sam223141 (void) fprintf(stderr, "%s\n", gettext(cmdp->c_usage)); 13438d5c46e6Sam223141 } 13444ac67f02SAnurag S. Maskey 13454ac67f02SAnurag S. Maskey /* close dladm handle if it was opened */ 13464ac67f02SAnurag S. Maskey if (handle != NULL) 13474ac67f02SAnurag S. Maskey dladm_close(handle); 13484ac67f02SAnurag S. Maskey 13492b24ab6bSSebastien Roy exit(EXIT_FAILURE); 13507c478bd9Sstevel@tonic-gate } 13517c478bd9Sstevel@tonic-gate 13527c478bd9Sstevel@tonic-gate int 13537c478bd9Sstevel@tonic-gate main(int argc, char *argv[]) 13547c478bd9Sstevel@tonic-gate { 13557c478bd9Sstevel@tonic-gate int i; 13567c478bd9Sstevel@tonic-gate cmd_t *cmdp; 13574ac67f02SAnurag S. Maskey dladm_status_t status; 13587c478bd9Sstevel@tonic-gate 13597c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, ""); 13607c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN) 13617c478bd9Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST" 13627c478bd9Sstevel@tonic-gate #endif 13637c478bd9Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN); 13647c478bd9Sstevel@tonic-gate 13657c478bd9Sstevel@tonic-gate progname = argv[0]; 13667c478bd9Sstevel@tonic-gate 13677c478bd9Sstevel@tonic-gate if (argc < 2) 13687c478bd9Sstevel@tonic-gate usage(); 13697c478bd9Sstevel@tonic-gate 13707c478bd9Sstevel@tonic-gate for (i = 0; i < sizeof (cmds) / sizeof (cmds[0]); i++) { 13717c478bd9Sstevel@tonic-gate cmdp = &cmds[i]; 13727c478bd9Sstevel@tonic-gate if (strcmp(argv[1], cmdp->c_name) == 0) { 13734ac67f02SAnurag S. Maskey /* Open the libdladm handle */ 13744ac67f02SAnurag S. Maskey if ((status = dladm_open(&handle)) != DLADM_STATUS_OK) { 13754ac67f02SAnurag S. Maskey die_dlerr(status, 13764ac67f02SAnurag S. Maskey "could not open /dev/dld"); 13774ac67f02SAnurag S. Maskey } 13784ac67f02SAnurag S. Maskey 13798d5c46e6Sam223141 cmdp->c_fn(argc - 1, &argv[1], cmdp->c_usage); 13804ac67f02SAnurag S. Maskey 13814ac67f02SAnurag S. Maskey dladm_close(handle); 13822b24ab6bSSebastien Roy return (EXIT_SUCCESS); 13837c478bd9Sstevel@tonic-gate } 13847c478bd9Sstevel@tonic-gate } 13857c478bd9Sstevel@tonic-gate 13867c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("%s: unknown subcommand '%s'\n"), 13877c478bd9Sstevel@tonic-gate progname, argv[1]); 13887c478bd9Sstevel@tonic-gate usage(); 13892b24ab6bSSebastien Roy return (EXIT_FAILURE); 13907c478bd9Sstevel@tonic-gate } 13917c478bd9Sstevel@tonic-gate 1392da14cebeSEric Cheng /*ARGSUSED*/ 1393da14cebeSEric Cheng static int 1394da14cebeSEric Cheng show_usage_date(dladm_usage_t *usage, void *arg) 1395da14cebeSEric Cheng { 1396ae6aa22aSVenugopal Iyer show_usage_state_t *state = (show_usage_state_t *)arg; 1397da14cebeSEric Cheng time_t stime; 1398da14cebeSEric Cheng char timebuf[20]; 1399ae6aa22aSVenugopal Iyer dladm_status_t status; 1400ae6aa22aSVenugopal Iyer uint32_t flags; 1401ae6aa22aSVenugopal Iyer 1402ae6aa22aSVenugopal Iyer /* 1403ae6aa22aSVenugopal Iyer * Only show usage information for existing links unless '-a' 1404ae6aa22aSVenugopal Iyer * is specified. 1405ae6aa22aSVenugopal Iyer */ 1406ae6aa22aSVenugopal Iyer if (!state->us_showall) { 1407ae6aa22aSVenugopal Iyer if ((status = dladm_name2info(handle, usage->du_name, 1408ae6aa22aSVenugopal Iyer NULL, &flags, NULL, NULL)) != DLADM_STATUS_OK) { 1409ae6aa22aSVenugopal Iyer return (status); 1410ae6aa22aSVenugopal Iyer } 1411ae6aa22aSVenugopal Iyer if ((flags & DLADM_OPT_ACTIVE) == 0) 1412ae6aa22aSVenugopal Iyer return (DLADM_STATUS_LINKINVAL); 1413ae6aa22aSVenugopal Iyer } 1414da14cebeSEric Cheng 1415da14cebeSEric Cheng stime = usage->du_stime; 1416da14cebeSEric Cheng (void) strftime(timebuf, sizeof (timebuf), "%m/%d/%Y", 1417da14cebeSEric Cheng localtime(&stime)); 1418da14cebeSEric Cheng (void) printf("%s\n", timebuf); 1419da14cebeSEric Cheng 1420da14cebeSEric Cheng return (DLADM_STATUS_OK); 1421da14cebeSEric Cheng } 1422da14cebeSEric Cheng 1423da14cebeSEric Cheng static int 1424da14cebeSEric Cheng show_usage_time(dladm_usage_t *usage, void *arg) 1425da14cebeSEric Cheng { 1426da14cebeSEric Cheng show_usage_state_t *state = (show_usage_state_t *)arg; 1427da14cebeSEric Cheng char buf[DLADM_STRSIZE]; 1428da14cebeSEric Cheng usage_l_fields_buf_t ubuf; 1429da14cebeSEric Cheng time_t time; 1430da14cebeSEric Cheng double bw; 1431ae6aa22aSVenugopal Iyer dladm_status_t status; 1432ae6aa22aSVenugopal Iyer uint32_t flags; 1433ae6aa22aSVenugopal Iyer 1434ae6aa22aSVenugopal Iyer /* 1435ae6aa22aSVenugopal Iyer * Only show usage information for existing links unless '-a' 1436ae6aa22aSVenugopal Iyer * is specified. 1437ae6aa22aSVenugopal Iyer */ 1438ae6aa22aSVenugopal Iyer if (!state->us_showall) { 1439ae6aa22aSVenugopal Iyer if ((status = dladm_name2info(handle, usage->du_name, 1440ae6aa22aSVenugopal Iyer NULL, &flags, NULL, NULL)) != DLADM_STATUS_OK) { 1441ae6aa22aSVenugopal Iyer return (status); 1442ae6aa22aSVenugopal Iyer } 1443ae6aa22aSVenugopal Iyer if ((flags & DLADM_OPT_ACTIVE) == 0) 1444ae6aa22aSVenugopal Iyer return (DLADM_STATUS_LINKINVAL); 1445ae6aa22aSVenugopal Iyer } 1446da14cebeSEric Cheng 1447da14cebeSEric Cheng if (state->us_plot) { 1448da14cebeSEric Cheng if (!state->us_printheader) { 1449da14cebeSEric Cheng if (state->us_first) { 1450da14cebeSEric Cheng (void) printf("# Time"); 1451da14cebeSEric Cheng state->us_first = B_FALSE; 1452da14cebeSEric Cheng } 1453da14cebeSEric Cheng (void) printf(" %s", usage->du_name); 1454da14cebeSEric Cheng if (usage->du_last) { 1455da14cebeSEric Cheng (void) printf("\n"); 1456da14cebeSEric Cheng state->us_first = B_TRUE; 1457da14cebeSEric Cheng state->us_printheader = B_TRUE; 1458da14cebeSEric Cheng } 1459da14cebeSEric Cheng } else { 1460da14cebeSEric Cheng if (state->us_first) { 1461da14cebeSEric Cheng time = usage->du_etime; 1462da14cebeSEric Cheng (void) strftime(buf, sizeof (buf), "%T", 1463da14cebeSEric Cheng localtime(&time)); 1464da14cebeSEric Cheng state->us_first = B_FALSE; 1465da14cebeSEric Cheng (void) printf("%s", buf); 1466da14cebeSEric Cheng } 1467da14cebeSEric Cheng bw = (double)usage->du_bandwidth/1000; 1468da14cebeSEric Cheng (void) printf(" %.2f", bw); 1469da14cebeSEric Cheng if (usage->du_last) { 1470da14cebeSEric Cheng (void) printf("\n"); 1471da14cebeSEric Cheng state->us_first = B_TRUE; 1472da14cebeSEric Cheng } 1473da14cebeSEric Cheng } 1474da14cebeSEric Cheng return (DLADM_STATUS_OK); 1475da14cebeSEric Cheng } 1476da14cebeSEric Cheng 1477da14cebeSEric Cheng bzero(&ubuf, sizeof (ubuf)); 1478da14cebeSEric Cheng 1479da14cebeSEric Cheng (void) snprintf(ubuf.usage_l_link, sizeof (ubuf.usage_l_link), "%s", 1480da14cebeSEric Cheng usage->du_name); 1481da14cebeSEric Cheng time = usage->du_stime; 1482da14cebeSEric Cheng (void) strftime(buf, sizeof (buf), "%T", localtime(&time)); 1483da14cebeSEric Cheng (void) snprintf(ubuf.usage_l_stime, sizeof (ubuf.usage_l_stime), "%s", 1484da14cebeSEric Cheng buf); 1485da14cebeSEric Cheng time = usage->du_etime; 1486da14cebeSEric Cheng (void) strftime(buf, sizeof (buf), "%T", localtime(&time)); 1487da14cebeSEric Cheng (void) snprintf(ubuf.usage_l_etime, sizeof (ubuf.usage_l_etime), "%s", 1488da14cebeSEric Cheng buf); 1489da14cebeSEric Cheng (void) snprintf(ubuf.usage_l_rbytes, sizeof (ubuf.usage_l_rbytes), 1490da14cebeSEric Cheng "%llu", usage->du_rbytes); 1491da14cebeSEric Cheng (void) snprintf(ubuf.usage_l_obytes, sizeof (ubuf.usage_l_obytes), 1492da14cebeSEric Cheng "%llu", usage->du_obytes); 1493da14cebeSEric Cheng (void) snprintf(ubuf.usage_l_bandwidth, sizeof (ubuf.usage_l_bandwidth), 1494da14cebeSEric Cheng "%s Mbps", dladm_bw2str(usage->du_bandwidth, buf)); 1495da14cebeSEric Cheng 14968002d411SSowmini Varadhan ofmt_print(state->us_ofmt, &ubuf); 1497da14cebeSEric Cheng return (DLADM_STATUS_OK); 1498da14cebeSEric Cheng } 1499da14cebeSEric Cheng 1500da14cebeSEric Cheng static int 1501da14cebeSEric Cheng show_usage_res(dladm_usage_t *usage, void *arg) 1502da14cebeSEric Cheng { 1503da14cebeSEric Cheng show_usage_state_t *state = (show_usage_state_t *)arg; 1504da14cebeSEric Cheng char buf[DLADM_STRSIZE]; 1505da14cebeSEric Cheng usage_fields_buf_t ubuf; 1506ae6aa22aSVenugopal Iyer dladm_status_t status; 1507ae6aa22aSVenugopal Iyer uint32_t flags; 1508ae6aa22aSVenugopal Iyer 1509ae6aa22aSVenugopal Iyer /* 1510ae6aa22aSVenugopal Iyer * Only show usage information for existing links unless '-a' 1511ae6aa22aSVenugopal Iyer * is specified. 1512ae6aa22aSVenugopal Iyer */ 1513ae6aa22aSVenugopal Iyer if (!state->us_showall) { 1514ae6aa22aSVenugopal Iyer if ((status = dladm_name2info(handle, usage->du_name, 1515ae6aa22aSVenugopal Iyer NULL, &flags, NULL, NULL)) != DLADM_STATUS_OK) { 1516ae6aa22aSVenugopal Iyer return (status); 1517ae6aa22aSVenugopal Iyer } 1518ae6aa22aSVenugopal Iyer if ((flags & DLADM_OPT_ACTIVE) == 0) 1519ae6aa22aSVenugopal Iyer return (DLADM_STATUS_LINKINVAL); 1520ae6aa22aSVenugopal Iyer } 1521da14cebeSEric Cheng 1522da14cebeSEric Cheng bzero(&ubuf, sizeof (ubuf)); 1523da14cebeSEric Cheng 1524da14cebeSEric Cheng (void) snprintf(ubuf.usage_link, sizeof (ubuf.usage_link), "%s", 1525da14cebeSEric Cheng usage->du_name); 1526da14cebeSEric Cheng (void) snprintf(ubuf.usage_duration, sizeof (ubuf.usage_duration), 1527da14cebeSEric Cheng "%llu", usage->du_duration); 1528da14cebeSEric Cheng (void) snprintf(ubuf.usage_ipackets, sizeof (ubuf.usage_ipackets), 1529da14cebeSEric Cheng "%llu", usage->du_ipackets); 1530da14cebeSEric Cheng (void) snprintf(ubuf.usage_rbytes, sizeof (ubuf.usage_rbytes), 1531da14cebeSEric Cheng "%llu", usage->du_rbytes); 1532da14cebeSEric Cheng (void) snprintf(ubuf.usage_opackets, sizeof (ubuf.usage_opackets), 1533da14cebeSEric Cheng "%llu", usage->du_opackets); 1534da14cebeSEric Cheng (void) snprintf(ubuf.usage_obytes, sizeof (ubuf.usage_obytes), 1535da14cebeSEric Cheng "%llu", usage->du_obytes); 1536da14cebeSEric Cheng (void) snprintf(ubuf.usage_bandwidth, sizeof (ubuf.usage_bandwidth), 1537da14cebeSEric Cheng "%s Mbps", dladm_bw2str(usage->du_bandwidth, buf)); 1538da14cebeSEric Cheng 15398002d411SSowmini Varadhan ofmt_print(state->us_ofmt, &ubuf); 1540da14cebeSEric Cheng 1541da14cebeSEric Cheng return (DLADM_STATUS_OK); 1542da14cebeSEric Cheng } 1543da14cebeSEric Cheng 1544da14cebeSEric Cheng static boolean_t 1545da14cebeSEric Cheng valid_formatspec(char *formatspec_str) 1546da14cebeSEric Cheng { 1547da14cebeSEric Cheng if (strcmp(formatspec_str, "gnuplot") == 0) 1548da14cebeSEric Cheng return (B_TRUE); 1549da14cebeSEric Cheng return (B_FALSE); 1550da14cebeSEric Cheng 1551da14cebeSEric Cheng } 1552da14cebeSEric Cheng 1553da14cebeSEric Cheng /*ARGSUSED*/ 1554da14cebeSEric Cheng static void 1555da14cebeSEric Cheng do_show_usage(int argc, char *argv[], const char *use) 1556da14cebeSEric Cheng { 1557da14cebeSEric Cheng char *file = NULL; 1558da14cebeSEric Cheng int opt; 1559da14cebeSEric Cheng dladm_status_t status; 1560da14cebeSEric Cheng boolean_t d_arg = B_FALSE; 1561da14cebeSEric Cheng char *stime = NULL; 1562da14cebeSEric Cheng char *etime = NULL; 1563da14cebeSEric Cheng char *resource = NULL; 1564da14cebeSEric Cheng show_usage_state_t state; 1565da14cebeSEric Cheng boolean_t o_arg = B_FALSE; 1566da14cebeSEric Cheng boolean_t F_arg = B_FALSE; 1567da14cebeSEric Cheng char *fields_str = NULL; 1568da14cebeSEric Cheng char *formatspec_str = NULL; 1569da14cebeSEric Cheng char *all_l_fields = 1570da14cebeSEric Cheng "link,start,end,rbytes,obytes,bandwidth"; 15718002d411SSowmini Varadhan ofmt_handle_t ofmt; 15728002d411SSowmini Varadhan ofmt_status_t oferr; 15738002d411SSowmini Varadhan uint_t ofmtflags = 0; 1574da14cebeSEric Cheng 1575da14cebeSEric Cheng bzero(&state, sizeof (show_usage_state_t)); 15768002d411SSowmini Varadhan state.us_parsable = B_FALSE; 1577da14cebeSEric Cheng state.us_printheader = B_FALSE; 1578da14cebeSEric Cheng state.us_plot = B_FALSE; 1579da14cebeSEric Cheng state.us_first = B_TRUE; 1580da14cebeSEric Cheng 1581ae6aa22aSVenugopal Iyer while ((opt = getopt_long(argc, argv, "das:e:o:f:F:", 1582ae6aa22aSVenugopal Iyer usage_opts, NULL)) != -1) { 1583da14cebeSEric Cheng switch (opt) { 1584da14cebeSEric Cheng case 'd': 1585da14cebeSEric Cheng d_arg = B_TRUE; 1586da14cebeSEric Cheng break; 1587ae6aa22aSVenugopal Iyer case 'a': 1588ae6aa22aSVenugopal Iyer state.us_showall = B_TRUE; 1589da14cebeSEric Cheng break; 1590da14cebeSEric Cheng case 'f': 1591da14cebeSEric Cheng file = optarg; 1592da14cebeSEric Cheng break; 1593da14cebeSEric Cheng case 's': 1594da14cebeSEric Cheng stime = optarg; 1595da14cebeSEric Cheng break; 1596da14cebeSEric Cheng case 'e': 1597da14cebeSEric Cheng etime = optarg; 1598da14cebeSEric Cheng break; 1599da14cebeSEric Cheng case 'o': 1600da14cebeSEric Cheng o_arg = B_TRUE; 1601da14cebeSEric Cheng fields_str = optarg; 1602da14cebeSEric Cheng break; 1603da14cebeSEric Cheng case 'F': 1604ae6aa22aSVenugopal Iyer state.us_plot = F_arg = B_TRUE; 1605da14cebeSEric Cheng formatspec_str = optarg; 1606da14cebeSEric Cheng break; 1607da14cebeSEric Cheng default: 1608da14cebeSEric Cheng die_opterr(optopt, opt, use); 1609da14cebeSEric Cheng break; 1610da14cebeSEric Cheng } 1611da14cebeSEric Cheng } 1612da14cebeSEric Cheng 1613da14cebeSEric Cheng if (file == NULL) 1614da14cebeSEric Cheng die("show-usage requires a file"); 1615da14cebeSEric Cheng 1616da14cebeSEric Cheng if (optind == (argc-1)) { 1617ae6aa22aSVenugopal Iyer uint32_t flags; 1618ae6aa22aSVenugopal Iyer 1619da14cebeSEric Cheng resource = argv[optind]; 1620ae6aa22aSVenugopal Iyer if (!state.us_showall && 1621ae6aa22aSVenugopal Iyer (((status = dladm_name2info(handle, resource, NULL, &flags, 1622ae6aa22aSVenugopal Iyer NULL, NULL)) != DLADM_STATUS_OK) || 1623ae6aa22aSVenugopal Iyer ((flags & DLADM_OPT_ACTIVE) == 0))) { 1624ae6aa22aSVenugopal Iyer die("invalid link: '%s'", resource); 1625ae6aa22aSVenugopal Iyer } 1626da14cebeSEric Cheng } 1627da14cebeSEric Cheng 1628ae6aa22aSVenugopal Iyer if (F_arg && d_arg) 1629ae6aa22aSVenugopal Iyer die("incompatible -d and -F options"); 1630da14cebeSEric Cheng 1631da14cebeSEric Cheng if (F_arg && valid_formatspec(formatspec_str) == B_FALSE) 1632da14cebeSEric Cheng die("Format specifier %s not supported", formatspec_str); 1633da14cebeSEric Cheng 16348002d411SSowmini Varadhan if (state.us_parsable) 16358002d411SSowmini Varadhan ofmtflags |= OFMT_PARSABLE; 16368002d411SSowmini Varadhan 16378002d411SSowmini Varadhan if (resource == NULL && stime == NULL && etime == NULL) { 16388002d411SSowmini Varadhan oferr = ofmt_open(fields_str, usage_fields, ofmtflags, 0, 16398002d411SSowmini Varadhan &ofmt); 16408002d411SSowmini Varadhan } else { 16418002d411SSowmini Varadhan if (!o_arg || (o_arg && strcasecmp(fields_str, "all") == 0)) 16428002d411SSowmini Varadhan fields_str = all_l_fields; 16438002d411SSowmini Varadhan oferr = ofmt_open(fields_str, usage_l_fields, ofmtflags, 0, 16448002d411SSowmini Varadhan &ofmt); 16458002d411SSowmini Varadhan 16468002d411SSowmini Varadhan } 16478002d411SSowmini Varadhan dladm_ofmt_check(oferr, state.us_parsable, ofmt); 16488002d411SSowmini Varadhan state.us_ofmt = ofmt; 16498002d411SSowmini Varadhan 1650da14cebeSEric Cheng if (d_arg) { 1651da14cebeSEric Cheng /* Print log dates */ 1652da14cebeSEric Cheng status = dladm_usage_dates(show_usage_date, 1653da14cebeSEric Cheng DLADM_LOGTYPE_LINK, file, resource, &state); 1654da14cebeSEric Cheng } else if (resource == NULL && stime == NULL && etime == NULL && 1655ae6aa22aSVenugopal Iyer !F_arg) { 1656da14cebeSEric Cheng /* Print summary */ 1657da14cebeSEric Cheng status = dladm_usage_summary(show_usage_res, 1658da14cebeSEric Cheng DLADM_LOGTYPE_LINK, file, &state); 1659da14cebeSEric Cheng } else if (resource != NULL) { 1660da14cebeSEric Cheng /* Print log entries for named resource */ 1661da14cebeSEric Cheng status = dladm_walk_usage_res(show_usage_time, 1662da14cebeSEric Cheng DLADM_LOGTYPE_LINK, file, resource, stime, etime, &state); 1663da14cebeSEric Cheng } else { 1664da14cebeSEric Cheng /* Print time and information for each link */ 1665da14cebeSEric Cheng status = dladm_walk_usage_time(show_usage_time, 1666da14cebeSEric Cheng DLADM_LOGTYPE_LINK, file, stime, etime, &state); 1667da14cebeSEric Cheng } 1668da14cebeSEric Cheng 1669da14cebeSEric Cheng if (status != DLADM_STATUS_OK) 1670da14cebeSEric Cheng die_dlerr(status, "show-usage"); 16718002d411SSowmini Varadhan ofmt_close(ofmt); 1672da14cebeSEric Cheng } 1673da14cebeSEric Cheng 16747c478bd9Sstevel@tonic-gate static void 16758d5c46e6Sam223141 do_create_aggr(int argc, char *argv[], const char *use) 16767c478bd9Sstevel@tonic-gate { 1677b509e89bSRishi Srivatsavai int option; 1678d62bc4baSyz147064 int key = 0; 16797c478bd9Sstevel@tonic-gate uint32_t policy = AGGR_POLICY_L4; 16807c478bd9Sstevel@tonic-gate aggr_lacp_mode_t lacp_mode = AGGR_LACP_OFF; 16817c478bd9Sstevel@tonic-gate aggr_lacp_timer_t lacp_timer = AGGR_LACP_TIMER_SHORT; 1682f595a68aSyz147064 dladm_aggr_port_attr_db_t port[MAXPORT]; 1683d62bc4baSyz147064 uint_t n, ndev, nlink; 16847c478bd9Sstevel@tonic-gate uint8_t mac_addr[ETHERADDRL]; 16857c478bd9Sstevel@tonic-gate boolean_t mac_addr_fixed = B_FALSE; 16867c478bd9Sstevel@tonic-gate boolean_t P_arg = B_FALSE; 16877c478bd9Sstevel@tonic-gate boolean_t l_arg = B_FALSE; 16887c478bd9Sstevel@tonic-gate boolean_t u_arg = B_FALSE; 16897c478bd9Sstevel@tonic-gate boolean_t T_arg = B_FALSE; 1690d62bc4baSyz147064 uint32_t flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST; 16917c478bd9Sstevel@tonic-gate char *altroot = NULL; 1692d62bc4baSyz147064 char name[MAXLINKNAMELEN]; 1693d62bc4baSyz147064 char *devs[MAXPORT]; 1694d62bc4baSyz147064 char *links[MAXPORT]; 1695f595a68aSyz147064 dladm_status_t status; 1696da14cebeSEric Cheng dladm_status_t pstatus; 169763a6526dSMichael Lim char propstr[DLADM_STRSIZE]; 1698da14cebeSEric Cheng dladm_arg_list_t *proplist = NULL; 1699da14cebeSEric Cheng int i; 1700da14cebeSEric Cheng datalink_id_t linkid; 17017c478bd9Sstevel@tonic-gate 1702d62bc4baSyz147064 ndev = nlink = opterr = 0; 170363a6526dSMichael Lim bzero(propstr, DLADM_STRSIZE); 170463a6526dSMichael Lim 1705da14cebeSEric Cheng while ((option = getopt_long(argc, argv, ":d:l:L:P:R:tfu:T:p:", 1706d62bc4baSyz147064 lopts, NULL)) != -1) { 17077c478bd9Sstevel@tonic-gate switch (option) { 17087c478bd9Sstevel@tonic-gate case 'd': 1709d62bc4baSyz147064 if (ndev + nlink >= MAXPORT) 1710d62bc4baSyz147064 die("too many ports specified"); 17117c478bd9Sstevel@tonic-gate 1712d62bc4baSyz147064 devs[ndev++] = optarg; 17137c478bd9Sstevel@tonic-gate break; 17147c478bd9Sstevel@tonic-gate case 'P': 171533343a97Smeem if (P_arg) 171633343a97Smeem die_optdup(option); 17177c478bd9Sstevel@tonic-gate 17187c478bd9Sstevel@tonic-gate P_arg = B_TRUE; 1719f595a68aSyz147064 if (!dladm_aggr_str2policy(optarg, &policy)) 172033343a97Smeem die("invalid policy '%s'", optarg); 17217c478bd9Sstevel@tonic-gate break; 17227c478bd9Sstevel@tonic-gate case 'u': 172333343a97Smeem if (u_arg) 172433343a97Smeem die_optdup(option); 17257c478bd9Sstevel@tonic-gate 17267c478bd9Sstevel@tonic-gate u_arg = B_TRUE; 1727f595a68aSyz147064 if (!dladm_aggr_str2macaddr(optarg, &mac_addr_fixed, 172833343a97Smeem mac_addr)) 172933343a97Smeem die("invalid MAC address '%s'", optarg); 17307c478bd9Sstevel@tonic-gate break; 17317c478bd9Sstevel@tonic-gate case 'l': 1732d62bc4baSyz147064 if (isdigit(optarg[strlen(optarg) - 1])) { 1733d62bc4baSyz147064 1734d62bc4baSyz147064 /* 1735d62bc4baSyz147064 * Ended with digit, possibly a link name. 1736d62bc4baSyz147064 */ 1737d62bc4baSyz147064 if (ndev + nlink >= MAXPORT) 1738d62bc4baSyz147064 die("too many ports specified"); 1739d62bc4baSyz147064 1740d62bc4baSyz147064 links[nlink++] = optarg; 1741d62bc4baSyz147064 break; 1742d62bc4baSyz147064 } 1743d62bc4baSyz147064 /* FALLTHROUGH */ 1744d62bc4baSyz147064 case 'L': 174533343a97Smeem if (l_arg) 174633343a97Smeem die_optdup(option); 17477c478bd9Sstevel@tonic-gate 17487c478bd9Sstevel@tonic-gate l_arg = B_TRUE; 1749f595a68aSyz147064 if (!dladm_aggr_str2lacpmode(optarg, &lacp_mode)) 175033343a97Smeem die("invalid LACP mode '%s'", optarg); 17517c478bd9Sstevel@tonic-gate break; 17527c478bd9Sstevel@tonic-gate case 'T': 175333343a97Smeem if (T_arg) 175433343a97Smeem die_optdup(option); 17557c478bd9Sstevel@tonic-gate 17567c478bd9Sstevel@tonic-gate T_arg = B_TRUE; 1757f595a68aSyz147064 if (!dladm_aggr_str2lacptimer(optarg, &lacp_timer)) 175833343a97Smeem die("invalid LACP timer value '%s'", optarg); 17597c478bd9Sstevel@tonic-gate break; 17607c478bd9Sstevel@tonic-gate case 't': 1761d62bc4baSyz147064 flags &= ~DLADM_OPT_PERSIST; 1762d62bc4baSyz147064 break; 1763d62bc4baSyz147064 case 'f': 1764d62bc4baSyz147064 flags |= DLADM_OPT_FORCE; 17657c478bd9Sstevel@tonic-gate break; 17667c478bd9Sstevel@tonic-gate case 'R': 17677c478bd9Sstevel@tonic-gate altroot = optarg; 17687c478bd9Sstevel@tonic-gate break; 1769da14cebeSEric Cheng case 'p': 177063a6526dSMichael Lim (void) strlcat(propstr, optarg, DLADM_STRSIZE); 177163a6526dSMichael Lim if (strlcat(propstr, ",", DLADM_STRSIZE) >= 177263a6526dSMichael Lim DLADM_STRSIZE) 177363a6526dSMichael Lim die("property list too long '%s'", propstr); 1774da14cebeSEric Cheng break; 177563a6526dSMichael Lim 17767c478bd9Sstevel@tonic-gate default: 17778d5c46e6Sam223141 die_opterr(optopt, option, use); 177833343a97Smeem break; 17797c478bd9Sstevel@tonic-gate } 17807c478bd9Sstevel@tonic-gate } 17817c478bd9Sstevel@tonic-gate 1782d62bc4baSyz147064 if (ndev + nlink == 0) 17837c478bd9Sstevel@tonic-gate usage(); 17847c478bd9Sstevel@tonic-gate 1785d62bc4baSyz147064 /* get key value or the aggregation name (required last argument) */ 17867c478bd9Sstevel@tonic-gate if (optind != (argc-1)) 17877c478bd9Sstevel@tonic-gate usage(); 17887c478bd9Sstevel@tonic-gate 1789d62bc4baSyz147064 if (!str2int(argv[optind], &key)) { 1790d62bc4baSyz147064 if (strlcpy(name, argv[optind], MAXLINKNAMELEN) >= 1791d62bc4baSyz147064 MAXLINKNAMELEN) { 1792d62bc4baSyz147064 die("link name too long '%s'", argv[optind]); 1793d62bc4baSyz147064 } 17947c478bd9Sstevel@tonic-gate 1795d62bc4baSyz147064 if (!dladm_valid_linkname(name)) 1796d62bc4baSyz147064 die("invalid link name '%s'", argv[optind]); 1797d62bc4baSyz147064 } else { 1798d62bc4baSyz147064 (void) snprintf(name, MAXLINKNAMELEN, "aggr%d", key); 1799d62bc4baSyz147064 } 1800d62bc4baSyz147064 1801d62bc4baSyz147064 if (altroot != NULL) 1802d62bc4baSyz147064 altroot_cmd(altroot, argc, argv); 1803d62bc4baSyz147064 1804d62bc4baSyz147064 for (n = 0; n < ndev; n++) { 18054ac67f02SAnurag S. Maskey if ((status = dladm_dev2linkid(handle, devs[n], 18064ac67f02SAnurag S. Maskey &port[n].lp_linkid)) != DLADM_STATUS_OK) { 18074ac67f02SAnurag S. Maskey die_dlerr(status, "invalid dev name '%s'", devs[n]); 1808d62bc4baSyz147064 } 1809d62bc4baSyz147064 } 1810d62bc4baSyz147064 1811d62bc4baSyz147064 for (n = 0; n < nlink; n++) { 18124ac67f02SAnurag S. Maskey if ((status = dladm_name2info(handle, links[n], 18134ac67f02SAnurag S. Maskey &port[ndev + n].lp_linkid, NULL, NULL, NULL)) != 18144ac67f02SAnurag S. Maskey DLADM_STATUS_OK) { 18154ac67f02SAnurag S. Maskey die_dlerr(status, "invalid link name '%s'", links[n]); 1816d62bc4baSyz147064 } 1817d62bc4baSyz147064 } 1818d62bc4baSyz147064 18194ac67f02SAnurag S. Maskey status = dladm_aggr_create(handle, name, key, ndev + nlink, port, 18204ac67f02SAnurag S. Maskey policy, mac_addr_fixed, (const uchar_t *)mac_addr, lacp_mode, 1821d62bc4baSyz147064 lacp_timer, flags); 1822da14cebeSEric Cheng if (status != DLADM_STATUS_OK) 1823da14cebeSEric Cheng goto done; 1824da14cebeSEric Cheng 182563a6526dSMichael Lim if (dladm_parse_link_props(propstr, &proplist, B_FALSE) 182663a6526dSMichael Lim != DLADM_STATUS_OK) 182763a6526dSMichael Lim die("invalid aggregation property"); 182863a6526dSMichael Lim 1829da14cebeSEric Cheng if (proplist == NULL) 1830da14cebeSEric Cheng return; 1831da14cebeSEric Cheng 18324ac67f02SAnurag S. Maskey status = dladm_name2info(handle, name, &linkid, NULL, NULL, NULL); 1833da14cebeSEric Cheng if (status != DLADM_STATUS_OK) 1834da14cebeSEric Cheng goto done; 1835da14cebeSEric Cheng 1836da14cebeSEric Cheng for (i = 0; i < proplist->al_count; i++) { 1837da14cebeSEric Cheng dladm_arg_info_t *aip = &proplist->al_info[i]; 1838da14cebeSEric Cheng 18394ac67f02SAnurag S. Maskey pstatus = dladm_set_linkprop(handle, linkid, aip->ai_name, 1840da14cebeSEric Cheng aip->ai_val, aip->ai_count, flags); 1841da14cebeSEric Cheng 1842da14cebeSEric Cheng if (pstatus != DLADM_STATUS_OK) { 1843da14cebeSEric Cheng die_dlerr(pstatus, 1844da14cebeSEric Cheng "aggr creation succeeded but " 1845da14cebeSEric Cheng "could not set property '%s'", aip->ai_name); 1846da14cebeSEric Cheng } 1847da14cebeSEric Cheng } 1848d62bc4baSyz147064 done: 1849da14cebeSEric Cheng dladm_free_props(proplist); 1850d62bc4baSyz147064 if (status != DLADM_STATUS_OK) { 1851d62bc4baSyz147064 if (status == DLADM_STATUS_NONOTIF) { 18524eaa4710SRishi Srivatsavai die("not all links have link up/down detection; must " 18534eaa4710SRishi Srivatsavai "use -f (see dladm(1M))"); 1854d62bc4baSyz147064 } else { 1855f595a68aSyz147064 die_dlerr(status, "create operation failed"); 18567c478bd9Sstevel@tonic-gate } 1857d62bc4baSyz147064 } 1858d62bc4baSyz147064 } 1859d62bc4baSyz147064 1860d62bc4baSyz147064 /* 1861d62bc4baSyz147064 * arg is either the key or the aggr name. Validate it and convert it to 1862d62bc4baSyz147064 * the linkid if altroot is NULL. 1863d62bc4baSyz147064 */ 1864d62bc4baSyz147064 static dladm_status_t 1865d62bc4baSyz147064 i_dladm_aggr_get_linkid(const char *altroot, const char *arg, 1866d62bc4baSyz147064 datalink_id_t *linkidp, uint32_t flags) 1867d62bc4baSyz147064 { 1868d62bc4baSyz147064 int key = 0; 1869d62bc4baSyz147064 char *aggr = NULL; 1870d62bc4baSyz147064 dladm_status_t status; 1871d62bc4baSyz147064 1872d62bc4baSyz147064 if (!str2int(arg, &key)) 1873d62bc4baSyz147064 aggr = (char *)arg; 1874d62bc4baSyz147064 1875d62bc4baSyz147064 if (aggr == NULL && key == 0) 1876d62bc4baSyz147064 return (DLADM_STATUS_LINKINVAL); 1877d62bc4baSyz147064 1878d62bc4baSyz147064 if (altroot != NULL) 1879d62bc4baSyz147064 return (DLADM_STATUS_OK); 1880d62bc4baSyz147064 1881d62bc4baSyz147064 if (aggr != NULL) { 18824ac67f02SAnurag S. Maskey status = dladm_name2info(handle, aggr, linkidp, NULL, NULL, 18834ac67f02SAnurag S. Maskey NULL); 1884d62bc4baSyz147064 } else { 18854ac67f02SAnurag S. Maskey status = dladm_key2linkid(handle, key, linkidp, flags); 1886d62bc4baSyz147064 } 1887d62bc4baSyz147064 1888d62bc4baSyz147064 return (status); 1889d62bc4baSyz147064 } 18907c478bd9Sstevel@tonic-gate 18917c478bd9Sstevel@tonic-gate static void 18928d5c46e6Sam223141 do_delete_aggr(int argc, char *argv[], const char *use) 18937c478bd9Sstevel@tonic-gate { 1894b509e89bSRishi Srivatsavai int option; 18957c478bd9Sstevel@tonic-gate char *altroot = NULL; 1896d62bc4baSyz147064 uint32_t flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST; 1897f595a68aSyz147064 dladm_status_t status; 1898d62bc4baSyz147064 datalink_id_t linkid; 18997c478bd9Sstevel@tonic-gate 19007c478bd9Sstevel@tonic-gate opterr = 0; 1901d62bc4baSyz147064 while ((option = getopt_long(argc, argv, ":R:t", lopts, NULL)) != -1) { 19027c478bd9Sstevel@tonic-gate switch (option) { 19037c478bd9Sstevel@tonic-gate case 't': 1904d62bc4baSyz147064 flags &= ~DLADM_OPT_PERSIST; 19057c478bd9Sstevel@tonic-gate break; 19067c478bd9Sstevel@tonic-gate case 'R': 19077c478bd9Sstevel@tonic-gate altroot = optarg; 19087c478bd9Sstevel@tonic-gate break; 19097c478bd9Sstevel@tonic-gate default: 19108d5c46e6Sam223141 die_opterr(optopt, option, use); 19117c478bd9Sstevel@tonic-gate break; 19127c478bd9Sstevel@tonic-gate } 19137c478bd9Sstevel@tonic-gate } 19147c478bd9Sstevel@tonic-gate 1915d62bc4baSyz147064 /* get key value or the aggregation name (required last argument) */ 19167c478bd9Sstevel@tonic-gate if (optind != (argc-1)) 19177c478bd9Sstevel@tonic-gate usage(); 19187c478bd9Sstevel@tonic-gate 1919d62bc4baSyz147064 status = i_dladm_aggr_get_linkid(altroot, argv[optind], &linkid, flags); 1920d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 1921d62bc4baSyz147064 goto done; 19227c478bd9Sstevel@tonic-gate 1923d62bc4baSyz147064 if (altroot != NULL) 1924d62bc4baSyz147064 altroot_cmd(altroot, argc, argv); 1925d62bc4baSyz147064 19264ac67f02SAnurag S. Maskey status = dladm_aggr_delete(handle, linkid, flags); 1927d62bc4baSyz147064 done: 1928f595a68aSyz147064 if (status != DLADM_STATUS_OK) 1929f595a68aSyz147064 die_dlerr(status, "delete operation failed"); 19307c478bd9Sstevel@tonic-gate } 19317c478bd9Sstevel@tonic-gate 19327c478bd9Sstevel@tonic-gate static void 19338d5c46e6Sam223141 do_add_aggr(int argc, char *argv[], const char *use) 19347c478bd9Sstevel@tonic-gate { 1935b509e89bSRishi Srivatsavai int option; 1936d62bc4baSyz147064 uint_t n, ndev, nlink; 19377c478bd9Sstevel@tonic-gate char *altroot = NULL; 1938d62bc4baSyz147064 uint32_t flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST; 1939d62bc4baSyz147064 datalink_id_t linkid; 1940f595a68aSyz147064 dladm_status_t status; 1941d62bc4baSyz147064 dladm_aggr_port_attr_db_t port[MAXPORT]; 1942d62bc4baSyz147064 char *devs[MAXPORT]; 1943d62bc4baSyz147064 char *links[MAXPORT]; 19447c478bd9Sstevel@tonic-gate 1945d62bc4baSyz147064 ndev = nlink = opterr = 0; 1946d62bc4baSyz147064 while ((option = getopt_long(argc, argv, ":d:l:R:tf", lopts, 19477c478bd9Sstevel@tonic-gate NULL)) != -1) { 19487c478bd9Sstevel@tonic-gate switch (option) { 19497c478bd9Sstevel@tonic-gate case 'd': 1950d62bc4baSyz147064 if (ndev + nlink >= MAXPORT) 1951d62bc4baSyz147064 die("too many ports specified"); 19527c478bd9Sstevel@tonic-gate 1953d62bc4baSyz147064 devs[ndev++] = optarg; 1954d62bc4baSyz147064 break; 1955d62bc4baSyz147064 case 'l': 1956d62bc4baSyz147064 if (ndev + nlink >= MAXPORT) 1957d62bc4baSyz147064 die("too many ports specified"); 195833343a97Smeem 1959d62bc4baSyz147064 links[nlink++] = optarg; 19607c478bd9Sstevel@tonic-gate break; 19617c478bd9Sstevel@tonic-gate case 't': 1962d62bc4baSyz147064 flags &= ~DLADM_OPT_PERSIST; 1963d62bc4baSyz147064 break; 1964d62bc4baSyz147064 case 'f': 1965d62bc4baSyz147064 flags |= DLADM_OPT_FORCE; 19667c478bd9Sstevel@tonic-gate break; 19677c478bd9Sstevel@tonic-gate case 'R': 19687c478bd9Sstevel@tonic-gate altroot = optarg; 19697c478bd9Sstevel@tonic-gate break; 19707c478bd9Sstevel@tonic-gate default: 19718d5c46e6Sam223141 die_opterr(optopt, option, use); 197233343a97Smeem break; 19737c478bd9Sstevel@tonic-gate } 19747c478bd9Sstevel@tonic-gate } 19757c478bd9Sstevel@tonic-gate 1976d62bc4baSyz147064 if (ndev + nlink == 0) 19777c478bd9Sstevel@tonic-gate usage(); 19787c478bd9Sstevel@tonic-gate 1979d62bc4baSyz147064 /* get key value or the aggregation name (required last argument) */ 19807c478bd9Sstevel@tonic-gate if (optind != (argc-1)) 19817c478bd9Sstevel@tonic-gate usage(); 19827c478bd9Sstevel@tonic-gate 1983d62bc4baSyz147064 if ((status = i_dladm_aggr_get_linkid(altroot, argv[optind], &linkid, 1984d62bc4baSyz147064 flags & (DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST))) != 1985d62bc4baSyz147064 DLADM_STATUS_OK) { 1986d62bc4baSyz147064 goto done; 1987d62bc4baSyz147064 } 19887c478bd9Sstevel@tonic-gate 1989d62bc4baSyz147064 if (altroot != NULL) 1990d62bc4baSyz147064 altroot_cmd(altroot, argc, argv); 1991d62bc4baSyz147064 1992d62bc4baSyz147064 for (n = 0; n < ndev; n++) { 19934ac67f02SAnurag S. Maskey if ((status = dladm_dev2linkid(handle, devs[n], 19944ac67f02SAnurag S. Maskey &(port[n].lp_linkid))) != DLADM_STATUS_OK) { 19954ac67f02SAnurag S. Maskey die_dlerr(status, "invalid <dev> '%s'", devs[n]); 1996d62bc4baSyz147064 } 1997d62bc4baSyz147064 } 1998d62bc4baSyz147064 1999d62bc4baSyz147064 for (n = 0; n < nlink; n++) { 20004ac67f02SAnurag S. Maskey if ((status = dladm_name2info(handle, links[n], 20014ac67f02SAnurag S. Maskey &port[n + ndev].lp_linkid, NULL, NULL, NULL)) != 20024ac67f02SAnurag S. Maskey DLADM_STATUS_OK) { 20034ac67f02SAnurag S. Maskey die_dlerr(status, "invalid <link> '%s'", links[n]); 2004d62bc4baSyz147064 } 2005d62bc4baSyz147064 } 2006d62bc4baSyz147064 20074ac67f02SAnurag S. Maskey status = dladm_aggr_add(handle, linkid, ndev + nlink, port, flags); 2008d62bc4baSyz147064 done: 2009f595a68aSyz147064 if (status != DLADM_STATUS_OK) { 2010219a2a31Shl157128 /* 2011f595a68aSyz147064 * checking DLADM_STATUS_NOTSUP is a temporary workaround 2012219a2a31Shl157128 * and should be removed once 6399681 is fixed. 2013219a2a31Shl157128 */ 2014f595a68aSyz147064 if (status == DLADM_STATUS_NOTSUP) { 20152b24ab6bSSebastien Roy die("add operation failed: link capabilities don't " 20162b24ab6bSSebastien Roy "match"); 2017d62bc4baSyz147064 } else if (status == DLADM_STATUS_NONOTIF) { 20184eaa4710SRishi Srivatsavai die("not all links have link up/down detection; must " 20194eaa4710SRishi Srivatsavai "use -f (see dladm(1M))"); 2020d62bc4baSyz147064 } else { 2021f595a68aSyz147064 die_dlerr(status, "add operation failed"); 20227c478bd9Sstevel@tonic-gate } 20237c478bd9Sstevel@tonic-gate } 2024d62bc4baSyz147064 } 20257c478bd9Sstevel@tonic-gate 20267c478bd9Sstevel@tonic-gate static void 20278d5c46e6Sam223141 do_remove_aggr(int argc, char *argv[], const char *use) 20287c478bd9Sstevel@tonic-gate { 2029b509e89bSRishi Srivatsavai int option; 2030f595a68aSyz147064 dladm_aggr_port_attr_db_t port[MAXPORT]; 2031d62bc4baSyz147064 uint_t n, ndev, nlink; 2032d62bc4baSyz147064 char *devs[MAXPORT]; 2033d62bc4baSyz147064 char *links[MAXPORT]; 20347c478bd9Sstevel@tonic-gate char *altroot = NULL; 2035d62bc4baSyz147064 uint32_t flags; 2036d62bc4baSyz147064 datalink_id_t linkid; 2037f595a68aSyz147064 dladm_status_t status; 20387c478bd9Sstevel@tonic-gate 2039d62bc4baSyz147064 flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST; 2040d62bc4baSyz147064 ndev = nlink = opterr = 0; 2041d62bc4baSyz147064 while ((option = getopt_long(argc, argv, ":d:l:R:t", 2042d62bc4baSyz147064 lopts, NULL)) != -1) { 20437c478bd9Sstevel@tonic-gate switch (option) { 20447c478bd9Sstevel@tonic-gate case 'd': 2045d62bc4baSyz147064 if (ndev + nlink >= MAXPORT) 2046d62bc4baSyz147064 die("too many ports specified"); 20477c478bd9Sstevel@tonic-gate 2048d62bc4baSyz147064 devs[ndev++] = optarg; 2049d62bc4baSyz147064 break; 2050d62bc4baSyz147064 case 'l': 2051d62bc4baSyz147064 if (ndev + nlink >= MAXPORT) 2052d62bc4baSyz147064 die("too many ports specified"); 205333343a97Smeem 2054d62bc4baSyz147064 links[nlink++] = optarg; 20557c478bd9Sstevel@tonic-gate break; 20567c478bd9Sstevel@tonic-gate case 't': 2057d62bc4baSyz147064 flags &= ~DLADM_OPT_PERSIST; 20587c478bd9Sstevel@tonic-gate break; 20597c478bd9Sstevel@tonic-gate case 'R': 20607c478bd9Sstevel@tonic-gate altroot = optarg; 20617c478bd9Sstevel@tonic-gate break; 20627c478bd9Sstevel@tonic-gate default: 20638d5c46e6Sam223141 die_opterr(optopt, option, use); 206433343a97Smeem break; 20657c478bd9Sstevel@tonic-gate } 20667c478bd9Sstevel@tonic-gate } 20677c478bd9Sstevel@tonic-gate 2068d62bc4baSyz147064 if (ndev + nlink == 0) 20697c478bd9Sstevel@tonic-gate usage(); 20707c478bd9Sstevel@tonic-gate 2071d62bc4baSyz147064 /* get key value or the aggregation name (required last argument) */ 20727c478bd9Sstevel@tonic-gate if (optind != (argc-1)) 20737c478bd9Sstevel@tonic-gate usage(); 20747c478bd9Sstevel@tonic-gate 2075d62bc4baSyz147064 status = i_dladm_aggr_get_linkid(altroot, argv[optind], &linkid, flags); 2076d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 2077d62bc4baSyz147064 goto done; 20787c478bd9Sstevel@tonic-gate 2079d62bc4baSyz147064 if (altroot != NULL) 2080d62bc4baSyz147064 altroot_cmd(altroot, argc, argv); 2081d62bc4baSyz147064 2082d62bc4baSyz147064 for (n = 0; n < ndev; n++) { 20834ac67f02SAnurag S. Maskey if ((status = dladm_dev2linkid(handle, devs[n], 20844ac67f02SAnurag S. Maskey &(port[n].lp_linkid))) != DLADM_STATUS_OK) { 20854ac67f02SAnurag S. Maskey die_dlerr(status, "invalid <dev> '%s'", devs[n]); 2086d62bc4baSyz147064 } 2087d62bc4baSyz147064 } 2088d62bc4baSyz147064 2089d62bc4baSyz147064 for (n = 0; n < nlink; n++) { 20904ac67f02SAnurag S. Maskey if ((status = dladm_name2info(handle, links[n], 20914ac67f02SAnurag S. Maskey &port[n + ndev].lp_linkid, NULL, NULL, NULL)) != 20924ac67f02SAnurag S. Maskey DLADM_STATUS_OK) { 20934ac67f02SAnurag S. Maskey die_dlerr(status, "invalid <link> '%s'", links[n]); 2094d62bc4baSyz147064 } 2095d62bc4baSyz147064 } 2096d62bc4baSyz147064 20974ac67f02SAnurag S. Maskey status = dladm_aggr_remove(handle, linkid, ndev + nlink, port, flags); 2098d62bc4baSyz147064 done: 2099f595a68aSyz147064 if (status != DLADM_STATUS_OK) 2100f595a68aSyz147064 die_dlerr(status, "remove operation failed"); 21017c478bd9Sstevel@tonic-gate } 21027c478bd9Sstevel@tonic-gate 21037c478bd9Sstevel@tonic-gate static void 21048d5c46e6Sam223141 do_modify_aggr(int argc, char *argv[], const char *use) 21057c478bd9Sstevel@tonic-gate { 2106b509e89bSRishi Srivatsavai int option; 21077c478bd9Sstevel@tonic-gate uint32_t policy = AGGR_POLICY_L4; 21087c478bd9Sstevel@tonic-gate aggr_lacp_mode_t lacp_mode = AGGR_LACP_OFF; 21097c478bd9Sstevel@tonic-gate aggr_lacp_timer_t lacp_timer = AGGR_LACP_TIMER_SHORT; 21107c478bd9Sstevel@tonic-gate uint8_t mac_addr[ETHERADDRL]; 21117c478bd9Sstevel@tonic-gate boolean_t mac_addr_fixed = B_FALSE; 21127c478bd9Sstevel@tonic-gate uint8_t modify_mask = 0; 21137c478bd9Sstevel@tonic-gate char *altroot = NULL; 2114d62bc4baSyz147064 uint32_t flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST; 2115d62bc4baSyz147064 datalink_id_t linkid; 2116f595a68aSyz147064 dladm_status_t status; 21177c478bd9Sstevel@tonic-gate 21187c478bd9Sstevel@tonic-gate opterr = 0; 2119d62bc4baSyz147064 while ((option = getopt_long(argc, argv, ":L:l:P:R:tu:T:", lopts, 21207c478bd9Sstevel@tonic-gate NULL)) != -1) { 21217c478bd9Sstevel@tonic-gate switch (option) { 21227c478bd9Sstevel@tonic-gate case 'P': 2123f595a68aSyz147064 if (modify_mask & DLADM_AGGR_MODIFY_POLICY) 212433343a97Smeem die_optdup(option); 21257c478bd9Sstevel@tonic-gate 2126f595a68aSyz147064 modify_mask |= DLADM_AGGR_MODIFY_POLICY; 21277c478bd9Sstevel@tonic-gate 2128f595a68aSyz147064 if (!dladm_aggr_str2policy(optarg, &policy)) 212933343a97Smeem die("invalid policy '%s'", optarg); 21307c478bd9Sstevel@tonic-gate break; 21317c478bd9Sstevel@tonic-gate case 'u': 2132f595a68aSyz147064 if (modify_mask & DLADM_AGGR_MODIFY_MAC) 213333343a97Smeem die_optdup(option); 21347c478bd9Sstevel@tonic-gate 2135f595a68aSyz147064 modify_mask |= DLADM_AGGR_MODIFY_MAC; 21367c478bd9Sstevel@tonic-gate 2137f595a68aSyz147064 if (!dladm_aggr_str2macaddr(optarg, &mac_addr_fixed, 213833343a97Smeem mac_addr)) 213933343a97Smeem die("invalid MAC address '%s'", optarg); 21407c478bd9Sstevel@tonic-gate break; 21417c478bd9Sstevel@tonic-gate case 'l': 2142d62bc4baSyz147064 case 'L': 2143f595a68aSyz147064 if (modify_mask & DLADM_AGGR_MODIFY_LACP_MODE) 214433343a97Smeem die_optdup(option); 21457c478bd9Sstevel@tonic-gate 2146f595a68aSyz147064 modify_mask |= DLADM_AGGR_MODIFY_LACP_MODE; 21477c478bd9Sstevel@tonic-gate 2148f595a68aSyz147064 if (!dladm_aggr_str2lacpmode(optarg, &lacp_mode)) 214933343a97Smeem die("invalid LACP mode '%s'", optarg); 21507c478bd9Sstevel@tonic-gate break; 21517c478bd9Sstevel@tonic-gate case 'T': 2152f595a68aSyz147064 if (modify_mask & DLADM_AGGR_MODIFY_LACP_TIMER) 215333343a97Smeem die_optdup(option); 21547c478bd9Sstevel@tonic-gate 2155f595a68aSyz147064 modify_mask |= DLADM_AGGR_MODIFY_LACP_TIMER; 21567c478bd9Sstevel@tonic-gate 2157f595a68aSyz147064 if (!dladm_aggr_str2lacptimer(optarg, &lacp_timer)) 215833343a97Smeem die("invalid LACP timer value '%s'", optarg); 21597c478bd9Sstevel@tonic-gate break; 21607c478bd9Sstevel@tonic-gate case 't': 2161d62bc4baSyz147064 flags &= ~DLADM_OPT_PERSIST; 21627c478bd9Sstevel@tonic-gate break; 21637c478bd9Sstevel@tonic-gate case 'R': 21647c478bd9Sstevel@tonic-gate altroot = optarg; 21657c478bd9Sstevel@tonic-gate break; 21667c478bd9Sstevel@tonic-gate default: 21678d5c46e6Sam223141 die_opterr(optopt, option, use); 216833343a97Smeem break; 21697c478bd9Sstevel@tonic-gate } 21707c478bd9Sstevel@tonic-gate } 21717c478bd9Sstevel@tonic-gate 217233343a97Smeem if (modify_mask == 0) 217333343a97Smeem die("at least one of the -PulT options must be specified"); 21747c478bd9Sstevel@tonic-gate 2175d62bc4baSyz147064 /* get key value or the aggregation name (required last argument) */ 21767c478bd9Sstevel@tonic-gate if (optind != (argc-1)) 21777c478bd9Sstevel@tonic-gate usage(); 21787c478bd9Sstevel@tonic-gate 2179d62bc4baSyz147064 status = i_dladm_aggr_get_linkid(altroot, argv[optind], &linkid, flags); 2180d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 2181d62bc4baSyz147064 goto done; 21827c478bd9Sstevel@tonic-gate 2183d62bc4baSyz147064 if (altroot != NULL) 2184d62bc4baSyz147064 altroot_cmd(altroot, argc, argv); 2185d62bc4baSyz147064 21864ac67f02SAnurag S. Maskey status = dladm_aggr_modify(handle, linkid, modify_mask, policy, 21874ac67f02SAnurag S. Maskey mac_addr_fixed, (const uchar_t *)mac_addr, lacp_mode, lacp_timer, 21884ac67f02SAnurag S. Maskey flags); 2189d62bc4baSyz147064 2190d62bc4baSyz147064 done: 2191f595a68aSyz147064 if (status != DLADM_STATUS_OK) 2192f595a68aSyz147064 die_dlerr(status, "modify operation failed"); 21937c478bd9Sstevel@tonic-gate } 21947c478bd9Sstevel@tonic-gate 21958d5c46e6Sam223141 /*ARGSUSED*/ 21967c478bd9Sstevel@tonic-gate static void 21978d5c46e6Sam223141 do_up_aggr(int argc, char *argv[], const char *use) 21987c478bd9Sstevel@tonic-gate { 2199d62bc4baSyz147064 datalink_id_t linkid = DATALINK_ALL_LINKID; 2200f595a68aSyz147064 dladm_status_t status; 22017c478bd9Sstevel@tonic-gate 2202d62bc4baSyz147064 /* 2203d62bc4baSyz147064 * get the key or the name of the aggregation (optional last argument) 2204d62bc4baSyz147064 */ 22057c478bd9Sstevel@tonic-gate if (argc == 2) { 2206d62bc4baSyz147064 if ((status = i_dladm_aggr_get_linkid(NULL, argv[1], &linkid, 22074ac67f02SAnurag S. Maskey DLADM_OPT_PERSIST)) != DLADM_STATUS_OK) 2208d62bc4baSyz147064 goto done; 22097c478bd9Sstevel@tonic-gate } else if (argc > 2) { 22107c478bd9Sstevel@tonic-gate usage(); 22117c478bd9Sstevel@tonic-gate } 22127c478bd9Sstevel@tonic-gate 22134ac67f02SAnurag S. Maskey status = dladm_aggr_up(handle, linkid); 2214d62bc4baSyz147064 done: 2215d62bc4baSyz147064 if (status != DLADM_STATUS_OK) { 2216d62bc4baSyz147064 if (argc == 2) { 2217d62bc4baSyz147064 die_dlerr(status, 2218d62bc4baSyz147064 "could not bring up aggregation '%s'", argv[1]); 22197c478bd9Sstevel@tonic-gate } else { 2220f595a68aSyz147064 die_dlerr(status, "could not bring aggregations up"); 22217c478bd9Sstevel@tonic-gate } 22227c478bd9Sstevel@tonic-gate } 22237c478bd9Sstevel@tonic-gate } 22247c478bd9Sstevel@tonic-gate 22257c478bd9Sstevel@tonic-gate static void 22268d5c46e6Sam223141 do_create_vlan(int argc, char *argv[], const char *use) 22277c478bd9Sstevel@tonic-gate { 2228d62bc4baSyz147064 char *link = NULL; 2229d62bc4baSyz147064 char drv[DLPI_LINKNAME_MAX]; 2230d62bc4baSyz147064 uint_t ppa; 2231d62bc4baSyz147064 datalink_id_t linkid; 2232da14cebeSEric Cheng datalink_id_t dev_linkid; 2233d62bc4baSyz147064 int vid = 0; 2234b509e89bSRishi Srivatsavai int option; 2235d62bc4baSyz147064 uint32_t flags = (DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST); 2236d62bc4baSyz147064 char *altroot = NULL; 2237d62bc4baSyz147064 char vlan[MAXLINKNAMELEN]; 223863a6526dSMichael Lim char propstr[DLADM_STRSIZE]; 2239da14cebeSEric Cheng dladm_arg_list_t *proplist = NULL; 2240f595a68aSyz147064 dladm_status_t status; 22417c478bd9Sstevel@tonic-gate 2242d62bc4baSyz147064 opterr = 0; 224363a6526dSMichael Lim bzero(propstr, DLADM_STRSIZE); 224463a6526dSMichael Lim 2245da14cebeSEric Cheng while ((option = getopt_long(argc, argv, ":tfR:l:v:p:", 2246d62bc4baSyz147064 lopts, NULL)) != -1) { 2247d62bc4baSyz147064 switch (option) { 2248d62bc4baSyz147064 case 'v': 2249d62bc4baSyz147064 if (vid != 0) 2250d62bc4baSyz147064 die_optdup(option); 2251d62bc4baSyz147064 2252d62bc4baSyz147064 if (!str2int(optarg, &vid) || vid < 1 || vid > 4094) 2253d62bc4baSyz147064 die("invalid VLAN identifier '%s'", optarg); 2254d62bc4baSyz147064 2255d62bc4baSyz147064 break; 2256d62bc4baSyz147064 case 'l': 2257d62bc4baSyz147064 if (link != NULL) 2258d62bc4baSyz147064 die_optdup(option); 2259d62bc4baSyz147064 2260d62bc4baSyz147064 link = optarg; 2261d62bc4baSyz147064 break; 2262d62bc4baSyz147064 case 't': 2263d62bc4baSyz147064 flags &= ~DLADM_OPT_PERSIST; 2264d62bc4baSyz147064 break; 2265d62bc4baSyz147064 case 'R': 2266d62bc4baSyz147064 altroot = optarg; 2267d62bc4baSyz147064 break; 2268da14cebeSEric Cheng case 'p': 226963a6526dSMichael Lim (void) strlcat(propstr, optarg, DLADM_STRSIZE); 227063a6526dSMichael Lim if (strlcat(propstr, ",", DLADM_STRSIZE) >= 227163a6526dSMichael Lim DLADM_STRSIZE) 227263a6526dSMichael Lim die("property list too long '%s'", propstr); 2273da14cebeSEric Cheng break; 2274da14cebeSEric Cheng case 'f': 2275da14cebeSEric Cheng flags |= DLADM_OPT_FORCE; 2276da14cebeSEric Cheng break; 2277d62bc4baSyz147064 default: 22788d5c46e6Sam223141 die_opterr(optopt, option, use); 2279d62bc4baSyz147064 break; 2280d62bc4baSyz147064 } 2281d62bc4baSyz147064 } 2282d62bc4baSyz147064 2283d62bc4baSyz147064 /* get vlan name if there is any */ 2284d62bc4baSyz147064 if ((vid == 0) || (link == NULL) || (argc - optind > 1)) 22857c478bd9Sstevel@tonic-gate usage(); 2286d62bc4baSyz147064 2287d62bc4baSyz147064 if (optind == (argc - 1)) { 2288d62bc4baSyz147064 if (strlcpy(vlan, argv[optind], MAXLINKNAMELEN) >= 2289d62bc4baSyz147064 MAXLINKNAMELEN) { 2290d62bc4baSyz147064 die("vlan name too long '%s'", argv[optind]); 2291d62bc4baSyz147064 } 2292d62bc4baSyz147064 } else { 2293d62bc4baSyz147064 if ((dlpi_parselink(link, drv, &ppa) != DLPI_SUCCESS) || 2294d62bc4baSyz147064 (ppa >= 1000) || 2295d62bc4baSyz147064 (dlpi_makelink(vlan, drv, vid * 1000 + ppa) != 2296d62bc4baSyz147064 DLPI_SUCCESS)) { 2297d62bc4baSyz147064 die("invalid link name '%s'", link); 2298d62bc4baSyz147064 } 22997c478bd9Sstevel@tonic-gate } 23007c478bd9Sstevel@tonic-gate 2301d62bc4baSyz147064 if (altroot != NULL) 2302d62bc4baSyz147064 altroot_cmd(altroot, argc, argv); 2303d62bc4baSyz147064 23044ac67f02SAnurag S. Maskey if (dladm_name2info(handle, link, &dev_linkid, NULL, NULL, NULL) != 2305d62bc4baSyz147064 DLADM_STATUS_OK) { 2306d62bc4baSyz147064 die("invalid link name '%s'", link); 2307d62bc4baSyz147064 } 2308d62bc4baSyz147064 230963a6526dSMichael Lim if (dladm_parse_link_props(propstr, &proplist, B_FALSE) 231063a6526dSMichael Lim != DLADM_STATUS_OK) 231163a6526dSMichael Lim die("invalid vlan property"); 231263a6526dSMichael Lim 23134eaa4710SRishi Srivatsavai status = dladm_vlan_create(handle, vlan, dev_linkid, vid, proplist, 23144eaa4710SRishi Srivatsavai flags, &linkid); 23154eaa4710SRishi Srivatsavai switch (status) { 23164eaa4710SRishi Srivatsavai case DLADM_STATUS_OK: 23174eaa4710SRishi Srivatsavai break; 23184eaa4710SRishi Srivatsavai 23194eaa4710SRishi Srivatsavai case DLADM_STATUS_NOTSUP: 23204eaa4710SRishi Srivatsavai die("VLAN over '%s' may require lowered MTU; must use -f (see " 23214eaa4710SRishi Srivatsavai "dladm(1M))", link); 23224eaa4710SRishi Srivatsavai break; 23234eaa4710SRishi Srivatsavai 23244eaa4710SRishi Srivatsavai case DLADM_STATUS_LINKBUSY: 23256f40bf67SRishi Srivatsavai die("VLAN over '%s' may not use default_tag ID " 23266f40bf67SRishi Srivatsavai "(see dladm(1M))", link); 23274eaa4710SRishi Srivatsavai break; 23284eaa4710SRishi Srivatsavai 23294eaa4710SRishi Srivatsavai default: 23304eaa4710SRishi Srivatsavai die_dlerr(status, "create operation failed"); 2331d62bc4baSyz147064 } 2332d62bc4baSyz147064 } 2333d62bc4baSyz147064 2334d62bc4baSyz147064 static void 23358d5c46e6Sam223141 do_delete_vlan(int argc, char *argv[], const char *use) 2336d62bc4baSyz147064 { 2337b509e89bSRishi Srivatsavai int option; 2338d62bc4baSyz147064 uint32_t flags = (DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST); 2339d62bc4baSyz147064 char *altroot = NULL; 2340d62bc4baSyz147064 datalink_id_t linkid; 2341d62bc4baSyz147064 dladm_status_t status; 2342d62bc4baSyz147064 2343d62bc4baSyz147064 opterr = 0; 2344d62bc4baSyz147064 while ((option = getopt_long(argc, argv, ":R:t", lopts, NULL)) != -1) { 2345d62bc4baSyz147064 switch (option) { 2346d62bc4baSyz147064 case 't': 2347d62bc4baSyz147064 flags &= ~DLADM_OPT_PERSIST; 2348d62bc4baSyz147064 break; 2349d62bc4baSyz147064 case 'R': 2350d62bc4baSyz147064 altroot = optarg; 2351d62bc4baSyz147064 break; 2352d62bc4baSyz147064 default: 23538d5c46e6Sam223141 die_opterr(optopt, option, use); 2354d62bc4baSyz147064 break; 2355d62bc4baSyz147064 } 2356d62bc4baSyz147064 } 2357d62bc4baSyz147064 2358d62bc4baSyz147064 /* get VLAN link name (required last argument) */ 2359d62bc4baSyz147064 if (optind != (argc - 1)) 2360d62bc4baSyz147064 usage(); 2361d62bc4baSyz147064 2362d62bc4baSyz147064 if (altroot != NULL) 2363d62bc4baSyz147064 altroot_cmd(altroot, argc, argv); 2364d62bc4baSyz147064 23654ac67f02SAnurag S. Maskey status = dladm_name2info(handle, argv[optind], &linkid, NULL, NULL, 23664ac67f02SAnurag S. Maskey NULL); 2367d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 2368d62bc4baSyz147064 goto done; 2369d62bc4baSyz147064 23704ac67f02SAnurag S. Maskey status = dladm_vlan_delete(handle, linkid, flags); 2371d62bc4baSyz147064 done: 2372d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 2373d62bc4baSyz147064 die_dlerr(status, "delete operation failed"); 2374d62bc4baSyz147064 } 2375d62bc4baSyz147064 23768d5c46e6Sam223141 /*ARGSUSED*/ 2377d62bc4baSyz147064 static void 23788d5c46e6Sam223141 do_up_vlan(int argc, char *argv[], const char *use) 2379d62bc4baSyz147064 { 2380da14cebeSEric Cheng do_up_vnic_common(argc, argv, use, B_TRUE); 23817c478bd9Sstevel@tonic-gate } 23827c478bd9Sstevel@tonic-gate 2383210db224Sericheng static void 23848d5c46e6Sam223141 do_rename_link(int argc, char *argv[], const char *use) 2385210db224Sericheng { 2386b509e89bSRishi Srivatsavai int option; 2387d62bc4baSyz147064 char *link1, *link2; 2388d62bc4baSyz147064 char *altroot = NULL; 2389d62bc4baSyz147064 dladm_status_t status; 2390210db224Sericheng 2391d62bc4baSyz147064 opterr = 0; 2392d62bc4baSyz147064 while ((option = getopt_long(argc, argv, ":R:", lopts, NULL)) != -1) { 2393d62bc4baSyz147064 switch (option) { 2394d62bc4baSyz147064 case 'R': 2395d62bc4baSyz147064 altroot = optarg; 2396d62bc4baSyz147064 break; 2397d62bc4baSyz147064 default: 23988d5c46e6Sam223141 die_opterr(optopt, option, use); 2399d62bc4baSyz147064 break; 2400210db224Sericheng } 2401210db224Sericheng } 2402210db224Sericheng 2403d62bc4baSyz147064 /* get link1 and link2 name (required the last 2 arguments) */ 2404d62bc4baSyz147064 if (optind != (argc - 2)) 2405d62bc4baSyz147064 usage(); 2406d62bc4baSyz147064 2407d62bc4baSyz147064 if (altroot != NULL) 2408d62bc4baSyz147064 altroot_cmd(altroot, argc, argv); 2409d62bc4baSyz147064 2410d62bc4baSyz147064 link1 = argv[optind++]; 2411d62bc4baSyz147064 link2 = argv[optind]; 24124ac67f02SAnurag S. Maskey if ((status = dladm_rename_link(handle, link1, link2)) != 24134ac67f02SAnurag S. Maskey DLADM_STATUS_OK) 2414d62bc4baSyz147064 die_dlerr(status, "rename operation failed"); 2415d62bc4baSyz147064 } 2416d62bc4baSyz147064 24178d5c46e6Sam223141 /*ARGSUSED*/ 2418d62bc4baSyz147064 static void 24198d5c46e6Sam223141 do_delete_phys(int argc, char *argv[], const char *use) 2420d62bc4baSyz147064 { 2421d62bc4baSyz147064 datalink_id_t linkid = DATALINK_ALL_LINKID; 2422d62bc4baSyz147064 dladm_status_t status; 2423d62bc4baSyz147064 2424d62bc4baSyz147064 /* get link name (required the last argument) */ 2425d62bc4baSyz147064 if (argc > 2) 2426d62bc4baSyz147064 usage(); 2427d62bc4baSyz147064 2428d62bc4baSyz147064 if (argc == 2) { 24294ac67f02SAnurag S. Maskey if ((status = dladm_name2info(handle, argv[1], &linkid, NULL, 24304ac67f02SAnurag S. Maskey NULL, NULL)) != DLADM_STATUS_OK) 2431d62bc4baSyz147064 die_dlerr(status, "cannot delete '%s'", argv[1]); 2432d62bc4baSyz147064 } 2433d62bc4baSyz147064 24344ac67f02SAnurag S. Maskey if ((status = dladm_phys_delete(handle, linkid)) != DLADM_STATUS_OK) { 2435d62bc4baSyz147064 if (argc == 2) 2436d62bc4baSyz147064 die_dlerr(status, "cannot delete '%s'", argv[1]); 2437d62bc4baSyz147064 else 2438d62bc4baSyz147064 die_dlerr(status, "delete operation failed"); 2439d62bc4baSyz147064 } 2440d62bc4baSyz147064 } 2441d62bc4baSyz147064 2442d62bc4baSyz147064 /*ARGSUSED*/ 2443210db224Sericheng static int 24444ac67f02SAnurag S. Maskey i_dladm_walk_linkmap(dladm_handle_t dh, datalink_id_t linkid, void *arg) 2445210db224Sericheng { 2446d62bc4baSyz147064 char name[MAXLINKNAMELEN]; 2447d62bc4baSyz147064 char mediabuf[DLADM_STRSIZE]; 2448d62bc4baSyz147064 char classbuf[DLADM_STRSIZE]; 2449d62bc4baSyz147064 datalink_class_t class; 2450d62bc4baSyz147064 uint32_t media; 2451d62bc4baSyz147064 uint32_t flags; 2452210db224Sericheng 24534ac67f02SAnurag S. Maskey if (dladm_datalink_id2info(dh, linkid, &flags, &class, &media, name, 2454d62bc4baSyz147064 MAXLINKNAMELEN) == DLADM_STATUS_OK) { 2455d62bc4baSyz147064 (void) dladm_class2str(class, classbuf); 2456d62bc4baSyz147064 (void) dladm_media2str(media, mediabuf); 2457d62bc4baSyz147064 (void) printf("%-12s%8d %-12s%-20s %6d\n", name, 2458d62bc4baSyz147064 linkid, classbuf, mediabuf, flags); 2459210db224Sericheng } 2460d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 2461210db224Sericheng } 24627c478bd9Sstevel@tonic-gate 24637c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 24647c478bd9Sstevel@tonic-gate static void 24658d5c46e6Sam223141 do_show_linkmap(int argc, char *argv[], const char *use) 24667c478bd9Sstevel@tonic-gate { 2467d62bc4baSyz147064 if (argc != 1) 2468d62bc4baSyz147064 die("invalid arguments"); 24697c478bd9Sstevel@tonic-gate 2470d62bc4baSyz147064 (void) printf("%-12s%8s %-12s%-20s %6s\n", "NAME", "LINKID", 2471d62bc4baSyz147064 "CLASS", "MEDIA", "FLAGS"); 24724ac67f02SAnurag S. Maskey 24734ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(i_dladm_walk_linkmap, handle, NULL, 2474d62bc4baSyz147064 DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE, 2475d62bc4baSyz147064 DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST); 24767c478bd9Sstevel@tonic-gate } 2477d62bc4baSyz147064 2478d62bc4baSyz147064 /* 2479d62bc4baSyz147064 * Delete inactive physical links. 2480d62bc4baSyz147064 */ 2481d62bc4baSyz147064 /*ARGSUSED*/ 2482d62bc4baSyz147064 static int 24834ac67f02SAnurag S. Maskey purge_phys(dladm_handle_t dh, datalink_id_t linkid, void *arg) 2484d62bc4baSyz147064 { 2485d62bc4baSyz147064 datalink_class_t class; 2486d62bc4baSyz147064 uint32_t flags; 2487d62bc4baSyz147064 24884ac67f02SAnurag S. Maskey if (dladm_datalink_id2info(dh, linkid, &flags, &class, NULL, NULL, 0) 24894ac67f02SAnurag S. Maskey != DLADM_STATUS_OK) { 2490d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 2491d62bc4baSyz147064 } 2492d62bc4baSyz147064 2493d62bc4baSyz147064 if (class == DATALINK_CLASS_PHYS && !(flags & DLADM_OPT_ACTIVE)) 24944ac67f02SAnurag S. Maskey (void) dladm_phys_delete(dh, linkid); 2495d62bc4baSyz147064 2496d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 2497d62bc4baSyz147064 } 2498d62bc4baSyz147064 2499d62bc4baSyz147064 /*ARGSUSED*/ 2500d62bc4baSyz147064 static void 25018d5c46e6Sam223141 do_init_phys(int argc, char *argv[], const char *use) 2502d62bc4baSyz147064 { 2503d62bc4baSyz147064 di_node_t devtree; 2504d62bc4baSyz147064 2505d62bc4baSyz147064 if (argc > 1) 2506d62bc4baSyz147064 usage(); 2507d62bc4baSyz147064 2508d62bc4baSyz147064 /* 2509d62bc4baSyz147064 * Force all the devices to attach, therefore all the network physical 2510d62bc4baSyz147064 * devices can be known to the dlmgmtd daemon. 2511d62bc4baSyz147064 */ 2512d62bc4baSyz147064 if ((devtree = di_init("/", DINFOFORCE | DINFOSUBTREE)) != DI_NODE_NIL) 2513d62bc4baSyz147064 di_fini(devtree); 2514d62bc4baSyz147064 25154ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(purge_phys, handle, NULL, 2516d62bc4baSyz147064 DATALINK_CLASS_PHYS, DATALINK_ANY_MEDIATYPE, DLADM_OPT_PERSIST); 25177c478bd9Sstevel@tonic-gate } 25187c478bd9Sstevel@tonic-gate 2519d62bc4baSyz147064 /* 2520d62bc4baSyz147064 * Print the active topology information. 2521d62bc4baSyz147064 */ 25222b24ab6bSSebastien Roy void 2523d62bc4baSyz147064 print_link_topology(show_state_t *state, datalink_id_t linkid, 2524e7801d59Ssowmini datalink_class_t class, link_fields_buf_t *lbuf) 2525d62bc4baSyz147064 { 2526d62bc4baSyz147064 uint32_t flags = state->ls_flags; 25274eaa4710SRishi Srivatsavai dladm_status_t status; 25286b9e797cSsowmini char tmpbuf[MAXLINKNAMELEN]; 2529d62bc4baSyz147064 2530b509e89bSRishi Srivatsavai lbuf->link_over[0] = '\0'; 25314eaa4710SRishi Srivatsavai lbuf->link_bridge[0] = '\0'; 2532b509e89bSRishi Srivatsavai 2533b509e89bSRishi Srivatsavai switch (class) { 25344eaa4710SRishi Srivatsavai case DATALINK_CLASS_AGGR: 25354eaa4710SRishi Srivatsavai case DATALINK_CLASS_PHYS: 25364eaa4710SRishi Srivatsavai case DATALINK_CLASS_ETHERSTUB: 25374eaa4710SRishi Srivatsavai status = dladm_bridge_getlink(handle, linkid, lbuf->link_bridge, 25384eaa4710SRishi Srivatsavai sizeof (lbuf->link_bridge)); 25392b24ab6bSSebastien Roy if (status != DLADM_STATUS_OK && 25402b24ab6bSSebastien Roy status != DLADM_STATUS_NOTFOUND) 25412b24ab6bSSebastien Roy (void) strcpy(lbuf->link_bridge, "?"); 25424eaa4710SRishi Srivatsavai break; 25434eaa4710SRishi Srivatsavai } 25444eaa4710SRishi Srivatsavai 25454eaa4710SRishi Srivatsavai switch (class) { 2546b509e89bSRishi Srivatsavai case DATALINK_CLASS_VLAN: { 2547d62bc4baSyz147064 dladm_vlan_attr_t vinfo; 2548d62bc4baSyz147064 25492b24ab6bSSebastien Roy if (dladm_vlan_info(handle, linkid, &vinfo, flags) != 25502b24ab6bSSebastien Roy DLADM_STATUS_OK) { 25512b24ab6bSSebastien Roy (void) strcpy(lbuf->link_over, "?"); 2552b509e89bSRishi Srivatsavai break; 2553b509e89bSRishi Srivatsavai } 25542b24ab6bSSebastien Roy if (dladm_datalink_id2info(handle, vinfo.dv_linkid, NULL, NULL, 25552b24ab6bSSebastien Roy NULL, lbuf->link_over, sizeof (lbuf->link_over)) != 25562b24ab6bSSebastien Roy DLADM_STATUS_OK) 25572b24ab6bSSebastien Roy (void) strcpy(lbuf->link_over, "?"); 25582b24ab6bSSebastien Roy break; 25592b24ab6bSSebastien Roy } 2560b509e89bSRishi Srivatsavai case DATALINK_CLASS_AGGR: { 2561d62bc4baSyz147064 dladm_aggr_grp_attr_t ginfo; 2562d62bc4baSyz147064 int i; 2563d62bc4baSyz147064 25642b24ab6bSSebastien Roy if (dladm_aggr_info(handle, linkid, &ginfo, flags) != 25652b24ab6bSSebastien Roy DLADM_STATUS_OK || ginfo.lg_nports == 0) { 25662b24ab6bSSebastien Roy (void) strcpy(lbuf->link_over, "?"); 2567b509e89bSRishi Srivatsavai break; 2568d62bc4baSyz147064 } 2569d62bc4baSyz147064 for (i = 0; i < ginfo.lg_nports; i++) { 25702b24ab6bSSebastien Roy if (dladm_datalink_id2info(handle, 2571e7801d59Ssowmini ginfo.lg_ports[i].lp_linkid, NULL, NULL, NULL, 25722b24ab6bSSebastien Roy tmpbuf, sizeof (tmpbuf)) != DLADM_STATUS_OK) { 25732b24ab6bSSebastien Roy (void) strcpy(lbuf->link_over, "?"); 2574b509e89bSRishi Srivatsavai break; 25752b24ab6bSSebastien Roy } 25766b9e797cSsowmini (void) strlcat(lbuf->link_over, tmpbuf, 25776b9e797cSsowmini sizeof (lbuf->link_over)); 25786b9e797cSsowmini if (i != (ginfo.lg_nports - 1)) { 25796b9e797cSsowmini (void) strlcat(lbuf->link_over, " ", 25806b9e797cSsowmini sizeof (lbuf->link_over)); 25816b9e797cSsowmini } 2582d62bc4baSyz147064 } 2583d62bc4baSyz147064 free(ginfo.lg_ports); 2584b509e89bSRishi Srivatsavai break; 2585b509e89bSRishi Srivatsavai } 2586b509e89bSRishi Srivatsavai case DATALINK_CLASS_VNIC: { 2587da14cebeSEric Cheng dladm_vnic_attr_t vinfo; 2588d62bc4baSyz147064 25892b24ab6bSSebastien Roy if (dladm_vnic_info(handle, linkid, &vinfo, flags) != 25902b24ab6bSSebastien Roy DLADM_STATUS_OK) { 25912b24ab6bSSebastien Roy (void) strcpy(lbuf->link_over, "?"); 2592b509e89bSRishi Srivatsavai break; 2593b509e89bSRishi Srivatsavai } 25942b24ab6bSSebastien Roy if (dladm_datalink_id2info(handle, vinfo.va_link_id, NULL, NULL, 25952b24ab6bSSebastien Roy NULL, lbuf->link_over, sizeof (lbuf->link_over)) != 25962b24ab6bSSebastien Roy DLADM_STATUS_OK) 25972b24ab6bSSebastien Roy (void) strcpy(lbuf->link_over, "?"); 25982b24ab6bSSebastien Roy break; 25992b24ab6bSSebastien Roy } 26004eaa4710SRishi Srivatsavai case DATALINK_CLASS_BRIDGE: { 26014eaa4710SRishi Srivatsavai datalink_id_t *dlp; 26024eaa4710SRishi Srivatsavai uint_t i, nports; 26034eaa4710SRishi Srivatsavai 26042b24ab6bSSebastien Roy if (dladm_datalink_id2info(handle, linkid, NULL, NULL, 26052b24ab6bSSebastien Roy NULL, tmpbuf, sizeof (tmpbuf)) != DLADM_STATUS_OK) { 26062b24ab6bSSebastien Roy (void) strcpy(lbuf->link_over, "?"); 26074eaa4710SRishi Srivatsavai break; 26082b24ab6bSSebastien Roy } 26094eaa4710SRishi Srivatsavai if (tmpbuf[0] != '\0') 26104eaa4710SRishi Srivatsavai tmpbuf[strlen(tmpbuf) - 1] = '\0'; 26114eaa4710SRishi Srivatsavai dlp = dladm_bridge_get_portlist(tmpbuf, &nports); 26124eaa4710SRishi Srivatsavai if (dlp == NULL) { 26132b24ab6bSSebastien Roy (void) strcpy(lbuf->link_over, "?"); 26144eaa4710SRishi Srivatsavai break; 26154eaa4710SRishi Srivatsavai } 26164eaa4710SRishi Srivatsavai for (i = 0; i < nports; i++) { 26172b24ab6bSSebastien Roy if (dladm_datalink_id2info(handle, dlp[i], NULL, 26182b24ab6bSSebastien Roy NULL, NULL, tmpbuf, sizeof (tmpbuf)) != 26192b24ab6bSSebastien Roy DLADM_STATUS_OK) { 26202b24ab6bSSebastien Roy (void) strcpy(lbuf->link_over, "?"); 26214eaa4710SRishi Srivatsavai break; 26222b24ab6bSSebastien Roy } 26234eaa4710SRishi Srivatsavai (void) strlcat(lbuf->link_over, tmpbuf, 26244eaa4710SRishi Srivatsavai sizeof (lbuf->link_over)); 26254eaa4710SRishi Srivatsavai if (i != nports - 1) { 26264eaa4710SRishi Srivatsavai (void) strlcat(lbuf->link_over, " ", 26274eaa4710SRishi Srivatsavai sizeof (lbuf->link_over)); 26284eaa4710SRishi Srivatsavai } 26294eaa4710SRishi Srivatsavai } 26304eaa4710SRishi Srivatsavai dladm_bridge_free_portlist(dlp); 26314eaa4710SRishi Srivatsavai break; 26324eaa4710SRishi Srivatsavai } 26334eaa4710SRishi Srivatsavai 2634b509e89bSRishi Srivatsavai case DATALINK_CLASS_SIMNET: { 2635b509e89bSRishi Srivatsavai dladm_simnet_attr_t slinfo; 2636b509e89bSRishi Srivatsavai 26372b24ab6bSSebastien Roy if (dladm_simnet_info(handle, linkid, &slinfo, flags) != 26382b24ab6bSSebastien Roy DLADM_STATUS_OK) { 26392b24ab6bSSebastien Roy (void) strcpy(lbuf->link_over, "?"); 26402b24ab6bSSebastien Roy break; 26412b24ab6bSSebastien Roy } 26422b24ab6bSSebastien Roy if (slinfo.sna_peer_link_id != DATALINK_INVALID_LINKID) { 26432b24ab6bSSebastien Roy if (dladm_datalink_id2info(handle, 2644b509e89bSRishi Srivatsavai slinfo.sna_peer_link_id, NULL, NULL, NULL, 26452b24ab6bSSebastien Roy lbuf->link_over, sizeof (lbuf->link_over)) != 26462b24ab6bSSebastien Roy DLADM_STATUS_OK) 26472b24ab6bSSebastien Roy (void) strcpy(lbuf->link_over, "?"); 26482b24ab6bSSebastien Roy } 2649b509e89bSRishi Srivatsavai break; 2650d62bc4baSyz147064 } 2651d62bc4baSyz147064 } 2652d62bc4baSyz147064 } 2653d62bc4baSyz147064 2654d62bc4baSyz147064 static dladm_status_t 2655e7801d59Ssowmini print_link(show_state_t *state, datalink_id_t linkid, link_fields_buf_t *lbuf) 2656d62bc4baSyz147064 { 2657d62bc4baSyz147064 char link[MAXLINKNAMELEN]; 2658d62bc4baSyz147064 datalink_class_t class; 2659d62bc4baSyz147064 uint_t mtu; 2660d62bc4baSyz147064 uint32_t flags; 2661d62bc4baSyz147064 dladm_status_t status; 2662d62bc4baSyz147064 26634ac67f02SAnurag S. Maskey if ((status = dladm_datalink_id2info(handle, linkid, &flags, &class, 26644ac67f02SAnurag S. Maskey NULL, link, sizeof (link))) != DLADM_STATUS_OK) { 2665d62bc4baSyz147064 goto done; 2666d62bc4baSyz147064 } 2667d62bc4baSyz147064 2668d62bc4baSyz147064 if (!(state->ls_flags & flags)) { 2669d62bc4baSyz147064 status = DLADM_STATUS_NOTFOUND; 2670d62bc4baSyz147064 goto done; 2671d62bc4baSyz147064 } 2672d62bc4baSyz147064 2673d62bc4baSyz147064 if (state->ls_flags == DLADM_OPT_ACTIVE) { 2674d62bc4baSyz147064 dladm_attr_t dlattr; 2675d62bc4baSyz147064 2676d62bc4baSyz147064 if (class == DATALINK_CLASS_PHYS) { 2677d62bc4baSyz147064 dladm_phys_attr_t dpa; 2678d62bc4baSyz147064 dlpi_handle_t dh; 2679d62bc4baSyz147064 dlpi_info_t dlinfo; 2680d62bc4baSyz147064 26814ac67f02SAnurag S. Maskey if ((status = dladm_phys_info(handle, linkid, &dpa, 2682d62bc4baSyz147064 DLADM_OPT_ACTIVE)) != DLADM_STATUS_OK) { 2683d62bc4baSyz147064 goto done; 2684d62bc4baSyz147064 } 2685d62bc4baSyz147064 2686d62bc4baSyz147064 if (!dpa.dp_novanity) 2687d62bc4baSyz147064 goto link_mtu; 2688d62bc4baSyz147064 2689d62bc4baSyz147064 /* 2690d62bc4baSyz147064 * This is a physical link that does not have 2691d62bc4baSyz147064 * vanity naming support. 2692d62bc4baSyz147064 */ 2693d62bc4baSyz147064 if (dlpi_open(dpa.dp_dev, &dh, DLPI_DEVONLY) != 2694d62bc4baSyz147064 DLPI_SUCCESS) { 2695d62bc4baSyz147064 status = DLADM_STATUS_NOTFOUND; 2696d62bc4baSyz147064 goto done; 2697d62bc4baSyz147064 } 2698d62bc4baSyz147064 2699d62bc4baSyz147064 if (dlpi_info(dh, &dlinfo, 0) != DLPI_SUCCESS) { 2700d62bc4baSyz147064 dlpi_close(dh); 2701d62bc4baSyz147064 status = DLADM_STATUS_BADARG; 2702d62bc4baSyz147064 goto done; 2703d62bc4baSyz147064 } 2704d62bc4baSyz147064 2705d62bc4baSyz147064 dlpi_close(dh); 2706d62bc4baSyz147064 mtu = dlinfo.di_max_sdu; 2707d62bc4baSyz147064 } else { 2708d62bc4baSyz147064 link_mtu: 27094ac67f02SAnurag S. Maskey status = dladm_info(handle, linkid, &dlattr); 2710d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 2711d62bc4baSyz147064 goto done; 2712d62bc4baSyz147064 mtu = dlattr.da_max_sdu; 2713d62bc4baSyz147064 } 2714d62bc4baSyz147064 } 2715d62bc4baSyz147064 2716e7801d59Ssowmini (void) snprintf(lbuf->link_name, sizeof (lbuf->link_name), 2717e7801d59Ssowmini "%s", link); 2718e7801d59Ssowmini (void) dladm_class2str(class, lbuf->link_class); 2719d62bc4baSyz147064 if (state->ls_flags == DLADM_OPT_ACTIVE) { 2720e7801d59Ssowmini (void) snprintf(lbuf->link_mtu, sizeof (lbuf->link_mtu), 2721c08e5e1aSdr146992 "%u", mtu); 2722e7801d59Ssowmini (void) get_linkstate(link, B_TRUE, lbuf->link_state); 2723d62bc4baSyz147064 } 2724d62bc4baSyz147064 27252b24ab6bSSebastien Roy print_link_topology(state, linkid, class, lbuf); 2726d62bc4baSyz147064 done: 2727d62bc4baSyz147064 return (status); 2728d62bc4baSyz147064 } 2729d62bc4baSyz147064 27304ac67f02SAnurag S. Maskey /* ARGSUSED */ 2731d62bc4baSyz147064 static int 27324ac67f02SAnurag S. Maskey show_link(dladm_handle_t dh, datalink_id_t linkid, void *arg) 2733d62bc4baSyz147064 { 2734e7801d59Ssowmini show_state_t *state = (show_state_t *)arg; 2735d62bc4baSyz147064 dladm_status_t status; 2736e7801d59Ssowmini link_fields_buf_t lbuf; 2737d62bc4baSyz147064 2738e7801d59Ssowmini /* 2739e7801d59Ssowmini * first get all the link attributes into lbuf; 2740e7801d59Ssowmini */ 27415f5c9f54SAnurag S. Maskey bzero(&lbuf, sizeof (link_fields_buf_t)); 27422b24ab6bSSebastien Roy if ((status = print_link(state, linkid, &lbuf)) == DLADM_STATUS_OK) 27438002d411SSowmini Varadhan ofmt_print(state->ls_ofmt, &lbuf); 2744d62bc4baSyz147064 state->ls_status = status; 2745d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 2746d62bc4baSyz147064 } 2747d62bc4baSyz147064 27488002d411SSowmini Varadhan static boolean_t 27498002d411SSowmini Varadhan print_link_stats_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize) 2750ae6aa22aSVenugopal Iyer { 27518002d411SSowmini Varadhan link_args_t *largs = ofarg->ofmt_cbarg; 2752ae6aa22aSVenugopal Iyer pktsum_t *diff_stats = largs->link_s_psum; 2753ae6aa22aSVenugopal Iyer 27548002d411SSowmini Varadhan switch (ofarg->ofmt_id) { 2755ae6aa22aSVenugopal Iyer case LINK_S_LINK: 27568002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%s", largs->link_s_link); 2757ae6aa22aSVenugopal Iyer break; 2758ae6aa22aSVenugopal Iyer case LINK_S_IPKTS: 27598002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%llu", diff_stats->ipackets); 2760ae6aa22aSVenugopal Iyer break; 2761ae6aa22aSVenugopal Iyer case LINK_S_RBYTES: 27628002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%llu", diff_stats->rbytes); 2763ae6aa22aSVenugopal Iyer break; 2764ae6aa22aSVenugopal Iyer case LINK_S_IERRORS: 27658002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%u", diff_stats->ierrors); 2766ae6aa22aSVenugopal Iyer break; 2767ae6aa22aSVenugopal Iyer case LINK_S_OPKTS: 27688002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%llu", diff_stats->opackets); 2769ae6aa22aSVenugopal Iyer break; 2770ae6aa22aSVenugopal Iyer case LINK_S_OBYTES: 27718002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%llu", diff_stats->obytes); 2772ae6aa22aSVenugopal Iyer break; 2773ae6aa22aSVenugopal Iyer case LINK_S_OERRORS: 27748002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%u", diff_stats->oerrors); 2775ae6aa22aSVenugopal Iyer break; 2776ae6aa22aSVenugopal Iyer default: 2777ae6aa22aSVenugopal Iyer die("invalid input"); 2778ae6aa22aSVenugopal Iyer break; 2779ae6aa22aSVenugopal Iyer } 27808002d411SSowmini Varadhan return (B_TRUE); 2781ae6aa22aSVenugopal Iyer } 2782ae6aa22aSVenugopal Iyer 2783d62bc4baSyz147064 static int 27844ac67f02SAnurag S. Maskey show_link_stats(dladm_handle_t dh, datalink_id_t linkid, void *arg) 2785d62bc4baSyz147064 { 2786e7801d59Ssowmini char link[DLPI_LINKNAME_MAX]; 2787d62bc4baSyz147064 datalink_class_t class; 27882b24ab6bSSebastien Roy show_state_t *state = arg; 27897c478bd9Sstevel@tonic-gate pktsum_t stats, diff_stats; 2790d62bc4baSyz147064 dladm_phys_attr_t dpa; 2791ae6aa22aSVenugopal Iyer link_args_t largs; 27927c478bd9Sstevel@tonic-gate 27937c478bd9Sstevel@tonic-gate if (state->ls_firstonly) { 27947c478bd9Sstevel@tonic-gate if (state->ls_donefirst) 2795d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 27967c478bd9Sstevel@tonic-gate state->ls_donefirst = B_TRUE; 27977c478bd9Sstevel@tonic-gate } else { 27987c478bd9Sstevel@tonic-gate bzero(&state->ls_prevstats, sizeof (state->ls_prevstats)); 27997c478bd9Sstevel@tonic-gate } 28007c478bd9Sstevel@tonic-gate 28014ac67f02SAnurag S. Maskey if (dladm_datalink_id2info(dh, linkid, NULL, &class, NULL, link, 2802e7801d59Ssowmini DLPI_LINKNAME_MAX) != DLADM_STATUS_OK) { 2803d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 2804d62bc4baSyz147064 } 2805d62bc4baSyz147064 2806d62bc4baSyz147064 if (class == DATALINK_CLASS_PHYS) { 28074ac67f02SAnurag S. Maskey if (dladm_phys_info(dh, linkid, &dpa, DLADM_OPT_ACTIVE) != 2808d62bc4baSyz147064 DLADM_STATUS_OK) { 2809d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 2810d62bc4baSyz147064 } 2811d62bc4baSyz147064 if (dpa.dp_novanity) 2812d62bc4baSyz147064 get_mac_stats(dpa.dp_dev, &stats); 2813d62bc4baSyz147064 else 2814d62bc4baSyz147064 get_link_stats(link, &stats); 2815d62bc4baSyz147064 } else { 2816d62bc4baSyz147064 get_link_stats(link, &stats); 2817d62bc4baSyz147064 } 2818da14cebeSEric Cheng dladm_stats_diff(&diff_stats, &stats, &state->ls_prevstats); 28197c478bd9Sstevel@tonic-gate 2820ae6aa22aSVenugopal Iyer largs.link_s_link = link; 2821ae6aa22aSVenugopal Iyer largs.link_s_psum = &diff_stats; 28228002d411SSowmini Varadhan ofmt_print(state->ls_ofmt, &largs); 28237c478bd9Sstevel@tonic-gate 28247c478bd9Sstevel@tonic-gate state->ls_prevstats = stats; 2825d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 28267c478bd9Sstevel@tonic-gate } 28277c478bd9Sstevel@tonic-gate 2828d62bc4baSyz147064 2829d62bc4baSyz147064 static dladm_status_t 2830d62bc4baSyz147064 print_aggr_info(show_grp_state_t *state, const char *link, 2831e7801d59Ssowmini dladm_aggr_grp_attr_t *ginfop) 2832d62bc4baSyz147064 { 2833d62bc4baSyz147064 char addr_str[ETHERADDRL * 3]; 2834e7801d59Ssowmini laggr_fields_buf_t lbuf; 2835d62bc4baSyz147064 2836e7801d59Ssowmini (void) snprintf(lbuf.laggr_name, sizeof (lbuf.laggr_name), 2837e7801d59Ssowmini "%s", link); 2838e7801d59Ssowmini 2839e7801d59Ssowmini (void) dladm_aggr_policy2str(ginfop->lg_policy, 2840e7801d59Ssowmini lbuf.laggr_policy); 2841d62bc4baSyz147064 2842d62bc4baSyz147064 if (ginfop->lg_mac_fixed) { 2843d62bc4baSyz147064 (void) dladm_aggr_macaddr2str(ginfop->lg_mac, addr_str); 2844e7801d59Ssowmini (void) snprintf(lbuf.laggr_addrpolicy, 2845e7801d59Ssowmini sizeof (lbuf.laggr_addrpolicy), "fixed (%s)", addr_str); 2846d62bc4baSyz147064 } else { 2847e7801d59Ssowmini (void) snprintf(lbuf.laggr_addrpolicy, 2848e7801d59Ssowmini sizeof (lbuf.laggr_addrpolicy), "auto"); 2849d62bc4baSyz147064 } 2850d62bc4baSyz147064 2851e7801d59Ssowmini (void) dladm_aggr_lacpmode2str(ginfop->lg_lacp_mode, 2852e7801d59Ssowmini lbuf.laggr_lacpactivity); 2853e7801d59Ssowmini (void) dladm_aggr_lacptimer2str(ginfop->lg_lacp_timer, 2854e7801d59Ssowmini lbuf.laggr_lacptimer); 2855e7801d59Ssowmini (void) snprintf(lbuf.laggr_flags, sizeof (lbuf.laggr_flags), "%c----", 2856d62bc4baSyz147064 ginfop->lg_force ? 'f' : '-'); 2857e7801d59Ssowmini 28588002d411SSowmini Varadhan ofmt_print(state->gs_ofmt, &lbuf); 2859e7801d59Ssowmini 2860d62bc4baSyz147064 return (DLADM_STATUS_OK); 2861d62bc4baSyz147064 } 2862d62bc4baSyz147064 28638002d411SSowmini Varadhan static boolean_t 28648002d411SSowmini Varadhan print_xaggr_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize) 2865d62bc4baSyz147064 { 28668002d411SSowmini Varadhan const laggr_args_t *l = ofarg->ofmt_cbarg; 2867e7801d59Ssowmini boolean_t is_port = (l->laggr_lport >= 0); 28682b24ab6bSSebastien Roy char tmpbuf[DLADM_STRSIZE]; 28692b24ab6bSSebastien Roy const char *objname; 2870e7801d59Ssowmini dladm_aggr_port_attr_t *portp; 2871d62bc4baSyz147064 dladm_phys_attr_t dpa; 2872d62bc4baSyz147064 2873e7801d59Ssowmini if (is_port) { 28742b24ab6bSSebastien Roy portp = &(l->laggr_ginfop->lg_ports[l->laggr_lport]); 28752b24ab6bSSebastien Roy if (dladm_phys_info(handle, portp->lp_linkid, &dpa, 28762b24ab6bSSebastien Roy DLADM_OPT_ACTIVE) != DLADM_STATUS_OK) 28772b24ab6bSSebastien Roy objname = "?"; 28782b24ab6bSSebastien Roy else 28792b24ab6bSSebastien Roy objname = dpa.dp_dev; 28802b24ab6bSSebastien Roy } else { 28812b24ab6bSSebastien Roy objname = l->laggr_link; 2882d62bc4baSyz147064 } 2883d62bc4baSyz147064 28848002d411SSowmini Varadhan switch (ofarg->ofmt_id) { 2885e7801d59Ssowmini case AGGR_X_LINK: 28868002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%s", 28878002d411SSowmini Varadhan (is_port && !l->laggr_parsable ? " " : l->laggr_link)); 2888e7801d59Ssowmini break; 2889e7801d59Ssowmini case AGGR_X_PORT: 2890e7801d59Ssowmini if (is_port) { 28912b24ab6bSSebastien Roy if (dladm_datalink_id2info(handle, portp->lp_linkid, 28922b24ab6bSSebastien Roy NULL, NULL, NULL, buf, bufsize) != DLADM_STATUS_OK) 28932b24ab6bSSebastien Roy (void) sprintf(buf, "?"); 2894e7801d59Ssowmini } 2895e7801d59Ssowmini break; 2896e7801d59Ssowmini 28972b24ab6bSSebastien Roy case AGGR_X_SPEED: 28982b24ab6bSSebastien Roy (void) snprintf(buf, bufsize, "%uMb", 28992b24ab6bSSebastien Roy (uint_t)((get_ifspeed(objname, !is_port)) / 1000000ull)); 29002b24ab6bSSebastien Roy break; 29012b24ab6bSSebastien Roy 2902e7801d59Ssowmini case AGGR_X_DUPLEX: 29032b24ab6bSSebastien Roy (void) get_linkduplex(objname, !is_port, tmpbuf); 29048002d411SSowmini Varadhan (void) strlcpy(buf, tmpbuf, bufsize); 2905e7801d59Ssowmini break; 2906d62bc4baSyz147064 2907e7801d59Ssowmini case AGGR_X_STATE: 29082b24ab6bSSebastien Roy (void) get_linkstate(objname, !is_port, tmpbuf); 29098002d411SSowmini Varadhan (void) strlcpy(buf, tmpbuf, bufsize); 2910e7801d59Ssowmini break; 2911e7801d59Ssowmini case AGGR_X_ADDRESS: 2912e7801d59Ssowmini (void) dladm_aggr_macaddr2str( 2913e7801d59Ssowmini (is_port ? portp->lp_mac : l->laggr_ginfop->lg_mac), 29148002d411SSowmini Varadhan tmpbuf); 29158002d411SSowmini Varadhan (void) strlcpy(buf, tmpbuf, bufsize); 2916e7801d59Ssowmini break; 2917e7801d59Ssowmini case AGGR_X_PORTSTATE: 29188002d411SSowmini Varadhan if (is_port) { 29198002d411SSowmini Varadhan (void) dladm_aggr_portstate2str(portp->lp_state, 29208002d411SSowmini Varadhan tmpbuf); 29218002d411SSowmini Varadhan (void) strlcpy(buf, tmpbuf, bufsize); 29228002d411SSowmini Varadhan } 2923e7801d59Ssowmini break; 2924e7801d59Ssowmini } 2925e7801d59Ssowmini err: 29262b24ab6bSSebastien Roy *(l->laggr_status) = DLADM_STATUS_OK; 29278002d411SSowmini Varadhan return (B_TRUE); 2928e7801d59Ssowmini } 2929e7801d59Ssowmini 2930e7801d59Ssowmini static dladm_status_t 2931e7801d59Ssowmini print_aggr_extended(show_grp_state_t *state, const char *link, 2932e7801d59Ssowmini dladm_aggr_grp_attr_t *ginfop) 2933e7801d59Ssowmini { 2934e7801d59Ssowmini int i; 2935e7801d59Ssowmini dladm_status_t status; 2936e7801d59Ssowmini laggr_args_t largs; 2937e7801d59Ssowmini 2938e7801d59Ssowmini largs.laggr_lport = -1; 2939e7801d59Ssowmini largs.laggr_link = link; 2940e7801d59Ssowmini largs.laggr_ginfop = ginfop; 2941e7801d59Ssowmini largs.laggr_status = &status; 29428002d411SSowmini Varadhan largs.laggr_parsable = state->gs_parsable; 2943e7801d59Ssowmini 29448002d411SSowmini Varadhan ofmt_print(state->gs_ofmt, &largs); 2945e7801d59Ssowmini 2946e7801d59Ssowmini if (status != DLADM_STATUS_OK) 2947e7801d59Ssowmini goto done; 2948e7801d59Ssowmini 2949e7801d59Ssowmini for (i = 0; i < ginfop->lg_nports; i++) { 2950e7801d59Ssowmini largs.laggr_lport = i; 29518002d411SSowmini Varadhan ofmt_print(state->gs_ofmt, &largs); 2952e7801d59Ssowmini if (status != DLADM_STATUS_OK) 2953e7801d59Ssowmini goto done; 2954d62bc4baSyz147064 } 2955d62bc4baSyz147064 2956d62bc4baSyz147064 status = DLADM_STATUS_OK; 2957d62bc4baSyz147064 done: 2958d62bc4baSyz147064 return (status); 2959d62bc4baSyz147064 } 2960d62bc4baSyz147064 29618002d411SSowmini Varadhan static boolean_t 29628002d411SSowmini Varadhan print_lacp_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize) 2963e7801d59Ssowmini { 29648002d411SSowmini Varadhan const laggr_args_t *l = ofarg->ofmt_cbarg; 2965e7801d59Ssowmini int portnum; 2966e7801d59Ssowmini boolean_t is_port = (l->laggr_lport >= 0); 2967e7801d59Ssowmini dladm_aggr_port_attr_t *portp; 2968e7801d59Ssowmini aggr_lacp_state_t *lstate; 2969e7801d59Ssowmini 29702b24ab6bSSebastien Roy if (!is_port) 29718002d411SSowmini Varadhan return (B_FALSE); /* cannot happen! */ 2972e7801d59Ssowmini 2973e7801d59Ssowmini portnum = l->laggr_lport; 2974e7801d59Ssowmini portp = &(l->laggr_ginfop->lg_ports[portnum]); 2975e7801d59Ssowmini lstate = &(portp->lp_lacp_state); 2976e7801d59Ssowmini 29778002d411SSowmini Varadhan switch (ofarg->ofmt_id) { 2978e7801d59Ssowmini case AGGR_L_LINK: 29798002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%s", 2980e7801d59Ssowmini (portnum > 0 ? "" : l->laggr_link)); 2981e7801d59Ssowmini break; 2982e7801d59Ssowmini 2983e7801d59Ssowmini case AGGR_L_PORT: 29842b24ab6bSSebastien Roy if (dladm_datalink_id2info(handle, portp->lp_linkid, NULL, NULL, 29852b24ab6bSSebastien Roy NULL, buf, bufsize) != DLADM_STATUS_OK) 29862b24ab6bSSebastien Roy (void) sprintf(buf, "?"); 2987e7801d59Ssowmini break; 2988e7801d59Ssowmini 2989e7801d59Ssowmini case AGGR_L_AGGREGATABLE: 29908002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%s", 2991e7801d59Ssowmini (lstate->bit.aggregation ? "yes" : "no")); 2992e7801d59Ssowmini break; 2993e7801d59Ssowmini 2994e7801d59Ssowmini case AGGR_L_SYNC: 29958002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%s", 2996e7801d59Ssowmini (lstate->bit.sync ? "yes" : "no")); 2997e7801d59Ssowmini break; 2998e7801d59Ssowmini 2999e7801d59Ssowmini case AGGR_L_COLL: 30008002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%s", 3001e7801d59Ssowmini (lstate->bit.collecting ? "yes" : "no")); 3002e7801d59Ssowmini break; 3003e7801d59Ssowmini 3004e7801d59Ssowmini case AGGR_L_DIST: 30058002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%s", 3006e7801d59Ssowmini (lstate->bit.distributing ? "yes" : "no")); 3007e7801d59Ssowmini break; 3008e7801d59Ssowmini 3009e7801d59Ssowmini case AGGR_L_DEFAULTED: 30108002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%s", 3011e7801d59Ssowmini (lstate->bit.defaulted ? "yes" : "no")); 3012e7801d59Ssowmini break; 3013e7801d59Ssowmini 3014e7801d59Ssowmini case AGGR_L_EXPIRED: 30158002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%s", 3016e7801d59Ssowmini (lstate->bit.expired ? "yes" : "no")); 3017e7801d59Ssowmini break; 3018e7801d59Ssowmini } 3019e7801d59Ssowmini 30202b24ab6bSSebastien Roy *(l->laggr_status) = DLADM_STATUS_OK; 30218002d411SSowmini Varadhan return (B_TRUE); 3022e7801d59Ssowmini } 3023e7801d59Ssowmini 3024d62bc4baSyz147064 static dladm_status_t 3025d62bc4baSyz147064 print_aggr_lacp(show_grp_state_t *state, const char *link, 3026e7801d59Ssowmini dladm_aggr_grp_attr_t *ginfop) 3027d62bc4baSyz147064 { 3028d62bc4baSyz147064 int i; 3029d62bc4baSyz147064 dladm_status_t status; 3030e7801d59Ssowmini laggr_args_t largs; 3031d62bc4baSyz147064 3032e7801d59Ssowmini largs.laggr_link = link; 3033e7801d59Ssowmini largs.laggr_ginfop = ginfop; 3034e7801d59Ssowmini largs.laggr_status = &status; 3035d62bc4baSyz147064 3036e7801d59Ssowmini for (i = 0; i < ginfop->lg_nports; i++) { 3037e7801d59Ssowmini largs.laggr_lport = i; 30388002d411SSowmini Varadhan ofmt_print(state->gs_ofmt, &largs); 3039d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 3040d62bc4baSyz147064 goto done; 3041d62bc4baSyz147064 } 3042d62bc4baSyz147064 3043d62bc4baSyz147064 status = DLADM_STATUS_OK; 3044d62bc4baSyz147064 done: 3045d62bc4baSyz147064 return (status); 3046d62bc4baSyz147064 } 3047d62bc4baSyz147064 30488002d411SSowmini Varadhan static boolean_t 30498002d411SSowmini Varadhan print_aggr_stats_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize) 3050e7801d59Ssowmini { 30518002d411SSowmini Varadhan const laggr_args_t *l = ofarg->ofmt_cbarg; 3052e7801d59Ssowmini int portnum; 3053e7801d59Ssowmini boolean_t is_port = (l->laggr_lport >= 0); 3054e7801d59Ssowmini dladm_aggr_port_attr_t *portp; 3055e7801d59Ssowmini dladm_status_t *stat, status; 30562d40c3b2SPrakash Jalan pktsum_t *diff_stats; 3057e7801d59Ssowmini 3058e7801d59Ssowmini stat = l->laggr_status; 3059e7801d59Ssowmini *stat = DLADM_STATUS_OK; 3060e7801d59Ssowmini 3061e7801d59Ssowmini if (is_port) { 3062e7801d59Ssowmini portnum = l->laggr_lport; 3063e7801d59Ssowmini portp = &(l->laggr_ginfop->lg_ports[portnum]); 3064e7801d59Ssowmini 30654ac67f02SAnurag S. Maskey if ((status = dladm_datalink_id2info(handle, 30668002d411SSowmini Varadhan portp->lp_linkid, NULL, NULL, NULL, buf, bufsize)) != 30674ac67f02SAnurag S. Maskey DLADM_STATUS_OK) { 3068e7801d59Ssowmini goto err; 3069e7801d59Ssowmini } 30702d40c3b2SPrakash Jalan diff_stats = l->laggr_diffstats; 3071e7801d59Ssowmini } 3072e7801d59Ssowmini 30738002d411SSowmini Varadhan switch (ofarg->ofmt_id) { 3074e7801d59Ssowmini case AGGR_S_LINK: 30758002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%s", 3076e7801d59Ssowmini (is_port ? "" : l->laggr_link)); 3077e7801d59Ssowmini break; 3078e7801d59Ssowmini case AGGR_S_PORT: 30798002d411SSowmini Varadhan /* 30808002d411SSowmini Varadhan * if (is_port), buf has port name. Otherwise we print 30818002d411SSowmini Varadhan * STR_UNDEF_VAL 30828002d411SSowmini Varadhan */ 3083e7801d59Ssowmini break; 3084e7801d59Ssowmini 3085e7801d59Ssowmini case AGGR_S_IPKTS: 3086e7801d59Ssowmini if (is_port) { 30878002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%llu", 30882d40c3b2SPrakash Jalan diff_stats->ipackets); 3089e7801d59Ssowmini } else { 30908002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%llu", 3091e7801d59Ssowmini l->laggr_pktsumtot->ipackets); 3092e7801d59Ssowmini } 3093e7801d59Ssowmini break; 3094e7801d59Ssowmini 3095e7801d59Ssowmini case AGGR_S_RBYTES: 3096e7801d59Ssowmini if (is_port) { 30978002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%llu", 30982d40c3b2SPrakash Jalan diff_stats->rbytes); 3099e7801d59Ssowmini } else { 31008002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%llu", 3101e7801d59Ssowmini l->laggr_pktsumtot->rbytes); 3102e7801d59Ssowmini } 3103e7801d59Ssowmini break; 3104e7801d59Ssowmini 3105e7801d59Ssowmini case AGGR_S_OPKTS: 3106e7801d59Ssowmini if (is_port) { 31078002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%llu", 31082d40c3b2SPrakash Jalan diff_stats->opackets); 3109e7801d59Ssowmini } else { 31108002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%llu", 3111e7801d59Ssowmini l->laggr_pktsumtot->opackets); 3112e7801d59Ssowmini } 3113e7801d59Ssowmini break; 3114e7801d59Ssowmini case AGGR_S_OBYTES: 3115e7801d59Ssowmini if (is_port) { 31168002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%llu", 31172d40c3b2SPrakash Jalan diff_stats->obytes); 3118e7801d59Ssowmini } else { 31198002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%llu", 3120e7801d59Ssowmini l->laggr_pktsumtot->obytes); 3121e7801d59Ssowmini } 3122e7801d59Ssowmini break; 3123e7801d59Ssowmini 3124e7801d59Ssowmini case AGGR_S_IPKTDIST: 3125e7801d59Ssowmini if (is_port) { 31268002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%-6.1f", 31272d40c3b2SPrakash Jalan (double)diff_stats->ipackets/ 3128e7801d59Ssowmini (double)l->laggr_pktsumtot->ipackets * 100); 3129e7801d59Ssowmini } 3130e7801d59Ssowmini break; 3131e7801d59Ssowmini case AGGR_S_OPKTDIST: 3132e7801d59Ssowmini if (is_port) { 31338002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%-6.1f", 31342d40c3b2SPrakash Jalan (double)diff_stats->opackets/ 3135e7801d59Ssowmini (double)l->laggr_pktsumtot->opackets * 100); 3136e7801d59Ssowmini } 3137e7801d59Ssowmini break; 3138e7801d59Ssowmini } 31398002d411SSowmini Varadhan return (B_TRUE); 3140e7801d59Ssowmini 3141e7801d59Ssowmini err: 3142e7801d59Ssowmini *stat = status; 31438002d411SSowmini Varadhan return (B_TRUE); 3144e7801d59Ssowmini } 3145e7801d59Ssowmini 3146d62bc4baSyz147064 static dladm_status_t 3147d62bc4baSyz147064 print_aggr_stats(show_grp_state_t *state, const char *link, 3148e7801d59Ssowmini dladm_aggr_grp_attr_t *ginfop) 3149d62bc4baSyz147064 { 3150d62bc4baSyz147064 dladm_phys_attr_t dpa; 3151d62bc4baSyz147064 dladm_aggr_port_attr_t *portp; 31522d40c3b2SPrakash Jalan pktsum_t pktsumtot, *port_stat; 3153d62bc4baSyz147064 dladm_status_t status; 3154d62bc4baSyz147064 int i; 3155e7801d59Ssowmini laggr_args_t largs; 31567c478bd9Sstevel@tonic-gate 31577c478bd9Sstevel@tonic-gate /* sum the ports statistics */ 31587c478bd9Sstevel@tonic-gate bzero(&pktsumtot, sizeof (pktsumtot)); 3159d62bc4baSyz147064 31602d40c3b2SPrakash Jalan /* Allocate memory to keep stats of each port */ 31612d40c3b2SPrakash Jalan port_stat = malloc(ginfop->lg_nports * sizeof (pktsum_t)); 31622d40c3b2SPrakash Jalan if (port_stat == NULL) { 31632d40c3b2SPrakash Jalan /* Bail out; no memory */ 31642d40c3b2SPrakash Jalan return (DLADM_STATUS_NOMEM); 31652d40c3b2SPrakash Jalan } 31662d40c3b2SPrakash Jalan 31672d40c3b2SPrakash Jalan 3168d62bc4baSyz147064 for (i = 0; i < ginfop->lg_nports; i++) { 3169d62bc4baSyz147064 3170d62bc4baSyz147064 portp = &(ginfop->lg_ports[i]); 31714ac67f02SAnurag S. Maskey if ((status = dladm_phys_info(handle, portp->lp_linkid, &dpa, 3172d62bc4baSyz147064 DLADM_OPT_ACTIVE)) != DLADM_STATUS_OK) { 3173d62bc4baSyz147064 goto done; 31747c478bd9Sstevel@tonic-gate } 31757c478bd9Sstevel@tonic-gate 31762d40c3b2SPrakash Jalan get_mac_stats(dpa.dp_dev, &port_stat[i]); 31772d40c3b2SPrakash Jalan 31782d40c3b2SPrakash Jalan /* 31792d40c3b2SPrakash Jalan * Let's re-use gs_prevstats[] to store the difference of the 31802d40c3b2SPrakash Jalan * counters since last use. We will store the new stats from 31812d40c3b2SPrakash Jalan * port_stat[] once we have the stats displayed. 31822d40c3b2SPrakash Jalan */ 31832d40c3b2SPrakash Jalan 31842d40c3b2SPrakash Jalan dladm_stats_diff(&state->gs_prevstats[i], &port_stat[i], 31852d40c3b2SPrakash Jalan &state->gs_prevstats[i]); 31862d40c3b2SPrakash Jalan dladm_stats_total(&pktsumtot, &pktsumtot, 3187da14cebeSEric Cheng &state->gs_prevstats[i]); 31887c478bd9Sstevel@tonic-gate } 31897c478bd9Sstevel@tonic-gate 3190e7801d59Ssowmini largs.laggr_lport = -1; 3191e7801d59Ssowmini largs.laggr_link = link; 3192e7801d59Ssowmini largs.laggr_ginfop = ginfop; 3193e7801d59Ssowmini largs.laggr_status = &status; 3194e7801d59Ssowmini largs.laggr_pktsumtot = &pktsumtot; 3195e7801d59Ssowmini 31968002d411SSowmini Varadhan ofmt_print(state->gs_ofmt, &largs); 3197e7801d59Ssowmini 3198e7801d59Ssowmini if (status != DLADM_STATUS_OK) 3199e7801d59Ssowmini goto done; 3200d62bc4baSyz147064 3201d62bc4baSyz147064 for (i = 0; i < ginfop->lg_nports; i++) { 3202e7801d59Ssowmini largs.laggr_lport = i; 32032d40c3b2SPrakash Jalan largs.laggr_diffstats = &state->gs_prevstats[i]; 32048002d411SSowmini Varadhan ofmt_print(state->gs_ofmt, &largs); 3205e7801d59Ssowmini if (status != DLADM_STATUS_OK) 3206d62bc4baSyz147064 goto done; 3207d62bc4baSyz147064 } 3208d62bc4baSyz147064 3209d62bc4baSyz147064 status = DLADM_STATUS_OK; 32102d40c3b2SPrakash Jalan for (i = 0; i < ginfop->lg_nports; i++) 32112d40c3b2SPrakash Jalan state->gs_prevstats[i] = port_stat[i]; 32122d40c3b2SPrakash Jalan 3213d62bc4baSyz147064 done: 32142d40c3b2SPrakash Jalan free(port_stat); 3215d62bc4baSyz147064 return (status); 3216d62bc4baSyz147064 } 3217d62bc4baSyz147064 3218d62bc4baSyz147064 static dladm_status_t 3219e7801d59Ssowmini print_aggr(show_grp_state_t *state, datalink_id_t linkid) 3220d62bc4baSyz147064 { 3221d62bc4baSyz147064 char link[MAXLINKNAMELEN]; 3222d62bc4baSyz147064 dladm_aggr_grp_attr_t ginfo; 3223d62bc4baSyz147064 uint32_t flags; 3224d62bc4baSyz147064 dladm_status_t status; 3225d62bc4baSyz147064 32265f5c9f54SAnurag S. Maskey bzero(&ginfo, sizeof (dladm_aggr_grp_attr_t)); 32274ac67f02SAnurag S. Maskey if ((status = dladm_datalink_id2info(handle, linkid, &flags, NULL, 32284ac67f02SAnurag S. Maskey NULL, link, MAXLINKNAMELEN)) != DLADM_STATUS_OK) { 3229d62bc4baSyz147064 return (status); 3230d62bc4baSyz147064 } 3231d62bc4baSyz147064 3232d62bc4baSyz147064 if (!(state->gs_flags & flags)) 3233d62bc4baSyz147064 return (DLADM_STATUS_NOTFOUND); 3234d62bc4baSyz147064 32354ac67f02SAnurag S. Maskey status = dladm_aggr_info(handle, linkid, &ginfo, state->gs_flags); 3236d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 3237d62bc4baSyz147064 return (status); 3238d62bc4baSyz147064 3239d62bc4baSyz147064 if (state->gs_lacp) 3240e7801d59Ssowmini status = print_aggr_lacp(state, link, &ginfo); 3241d62bc4baSyz147064 else if (state->gs_extended) 3242e7801d59Ssowmini status = print_aggr_extended(state, link, &ginfo); 3243d62bc4baSyz147064 else if (state->gs_stats) 3244e7801d59Ssowmini status = print_aggr_stats(state, link, &ginfo); 32454ac67f02SAnurag S. Maskey else 3246e7801d59Ssowmini status = print_aggr_info(state, link, &ginfo); 3247d62bc4baSyz147064 3248d62bc4baSyz147064 done: 3249d62bc4baSyz147064 free(ginfo.lg_ports); 3250d62bc4baSyz147064 return (status); 3251d62bc4baSyz147064 } 3252d62bc4baSyz147064 32534ac67f02SAnurag S. Maskey /* ARGSUSED */ 3254d62bc4baSyz147064 static int 32554ac67f02SAnurag S. Maskey show_aggr(dladm_handle_t dh, datalink_id_t linkid, void *arg) 3256d62bc4baSyz147064 { 3257d62bc4baSyz147064 show_grp_state_t *state = arg; 3258d62bc4baSyz147064 32598002d411SSowmini Varadhan state->gs_status = print_aggr(state, linkid); 3260d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 32617c478bd9Sstevel@tonic-gate } 32627c478bd9Sstevel@tonic-gate 32637c478bd9Sstevel@tonic-gate static void 32648d5c46e6Sam223141 do_show_link(int argc, char *argv[], const char *use) 32657c478bd9Sstevel@tonic-gate { 32667c478bd9Sstevel@tonic-gate int option; 32677c478bd9Sstevel@tonic-gate boolean_t s_arg = B_FALSE; 3268da14cebeSEric Cheng boolean_t S_arg = B_FALSE; 32697c478bd9Sstevel@tonic-gate boolean_t i_arg = B_FALSE; 3270d62bc4baSyz147064 uint32_t flags = DLADM_OPT_ACTIVE; 3271d62bc4baSyz147064 boolean_t p_arg = B_FALSE; 3272d62bc4baSyz147064 datalink_id_t linkid = DATALINK_ALL_LINKID; 3273da14cebeSEric Cheng char linkname[MAXLINKNAMELEN]; 327463a6526dSMichael Lim uint32_t interval = 0; 3275d62bc4baSyz147064 show_state_t state; 3276d62bc4baSyz147064 dladm_status_t status; 3277e7801d59Ssowmini boolean_t o_arg = B_FALSE; 3278e7801d59Ssowmini char *fields_str = NULL; 32794eaa4710SRishi Srivatsavai char *all_active_fields = "link,class,mtu,state,bridge,over"; 32804eaa4710SRishi Srivatsavai char *all_inactive_fields = "link,class,bridge,over"; 32816be03d0bSVasumathi Sundaram - Sun Microsystems char *allstat_fields = 32826be03d0bSVasumathi Sundaram - Sun Microsystems "link,ipackets,rbytes,ierrors,opackets,obytes,oerrors"; 32838002d411SSowmini Varadhan ofmt_handle_t ofmt; 32848002d411SSowmini Varadhan ofmt_status_t oferr; 32858002d411SSowmini Varadhan uint_t ofmtflags = 0; 3286e7801d59Ssowmini 3287e7801d59Ssowmini bzero(&state, sizeof (state)); 32887c478bd9Sstevel@tonic-gate 32897c478bd9Sstevel@tonic-gate opterr = 0; 3290da14cebeSEric Cheng while ((option = getopt_long(argc, argv, ":pPsSi:o:", 3291d62bc4baSyz147064 show_lopts, NULL)) != -1) { 32927c478bd9Sstevel@tonic-gate switch (option) { 32937c478bd9Sstevel@tonic-gate case 'p': 3294d62bc4baSyz147064 if (p_arg) 3295d62bc4baSyz147064 die_optdup(option); 3296d62bc4baSyz147064 3297d62bc4baSyz147064 p_arg = B_TRUE; 32987c478bd9Sstevel@tonic-gate break; 32997c478bd9Sstevel@tonic-gate case 's': 330033343a97Smeem if (s_arg) 330133343a97Smeem die_optdup(option); 33027c478bd9Sstevel@tonic-gate 33037c478bd9Sstevel@tonic-gate s_arg = B_TRUE; 33047c478bd9Sstevel@tonic-gate break; 3305d62bc4baSyz147064 case 'P': 3306d62bc4baSyz147064 if (flags != DLADM_OPT_ACTIVE) 3307d62bc4baSyz147064 die_optdup(option); 3308d62bc4baSyz147064 3309d62bc4baSyz147064 flags = DLADM_OPT_PERSIST; 3310d62bc4baSyz147064 break; 3311da14cebeSEric Cheng case 'S': 3312da14cebeSEric Cheng if (S_arg) 3313da14cebeSEric Cheng die_optdup(option); 3314da14cebeSEric Cheng 3315da14cebeSEric Cheng S_arg = B_TRUE; 3316da14cebeSEric Cheng break; 3317e7801d59Ssowmini case 'o': 3318e7801d59Ssowmini o_arg = B_TRUE; 3319e7801d59Ssowmini fields_str = optarg; 3320e7801d59Ssowmini break; 33217c478bd9Sstevel@tonic-gate case 'i': 332233343a97Smeem if (i_arg) 332333343a97Smeem die_optdup(option); 33247c478bd9Sstevel@tonic-gate 33257c478bd9Sstevel@tonic-gate i_arg = B_TRUE; 332663a6526dSMichael Lim if (!dladm_str2interval(optarg, &interval)) 332733343a97Smeem die("invalid interval value '%s'", optarg); 33287c478bd9Sstevel@tonic-gate break; 33297c478bd9Sstevel@tonic-gate default: 33308d5c46e6Sam223141 die_opterr(optopt, option, use); 333133343a97Smeem break; 33327c478bd9Sstevel@tonic-gate } 33337c478bd9Sstevel@tonic-gate } 33347c478bd9Sstevel@tonic-gate 3335da14cebeSEric Cheng if (i_arg && !(s_arg || S_arg)) 3336da14cebeSEric Cheng die("the option -i can be used only with -s or -S"); 3337da14cebeSEric Cheng 3338da14cebeSEric Cheng if (s_arg && S_arg) 3339da14cebeSEric Cheng die("the -s option cannot be used with -S"); 33407c478bd9Sstevel@tonic-gate 33416be03d0bSVasumathi Sundaram - Sun Microsystems if (s_arg && flags != DLADM_OPT_ACTIVE) 33426be03d0bSVasumathi Sundaram - Sun Microsystems die("the option -P cannot be used with -s"); 3343d62bc4baSyz147064 3344da14cebeSEric Cheng if (S_arg && (p_arg || flags != DLADM_OPT_ACTIVE)) 3345da14cebeSEric Cheng die("the option -%c cannot be used with -S", p_arg ? 'p' : 'P'); 3346da14cebeSEric Cheng 33477c478bd9Sstevel@tonic-gate /* get link name (optional last argument) */ 3348d62bc4baSyz147064 if (optind == (argc-1)) { 3349d62bc4baSyz147064 uint32_t f; 3350d62bc4baSyz147064 33512b24ab6bSSebastien Roy if (strlcpy(linkname, argv[optind], MAXLINKNAMELEN) >= 33522b24ab6bSSebastien Roy MAXLINKNAMELEN) 33532b24ab6bSSebastien Roy die("link name too long"); 33544ac67f02SAnurag S. Maskey if ((status = dladm_name2info(handle, linkname, &linkid, &f, 3355d62bc4baSyz147064 NULL, NULL)) != DLADM_STATUS_OK) { 3356da14cebeSEric Cheng die_dlerr(status, "link %s is not valid", linkname); 3357d62bc4baSyz147064 } 3358d62bc4baSyz147064 3359d62bc4baSyz147064 if (!(f & flags)) { 3360d62bc4baSyz147064 die_dlerr(DLADM_STATUS_BADARG, "link %s is %s", 3361d62bc4baSyz147064 argv[optind], flags == DLADM_OPT_PERSIST ? 3362d62bc4baSyz147064 "a temporary link" : "temporarily removed"); 3363d62bc4baSyz147064 } 3364d62bc4baSyz147064 } else if (optind != argc) { 33657c478bd9Sstevel@tonic-gate usage(); 3366d62bc4baSyz147064 } 33677c478bd9Sstevel@tonic-gate 33680d365605Sschuster if (p_arg && !o_arg) 33690d365605Sschuster die("-p requires -o"); 33700d365605Sschuster 3371da14cebeSEric Cheng if (S_arg) { 33724ac67f02SAnurag S. Maskey dladm_continuous(handle, linkid, NULL, interval, LINK_REPORT); 3373da14cebeSEric Cheng return; 3374da14cebeSEric Cheng } 3375da14cebeSEric Cheng 33760d365605Sschuster if (p_arg && strcasecmp(fields_str, "all") == 0) 33770d365605Sschuster die("\"-o all\" is invalid with -p"); 33780d365605Sschuster 3379e7801d59Ssowmini if (!o_arg || (o_arg && strcasecmp(fields_str, "all") == 0)) { 33806be03d0bSVasumathi Sundaram - Sun Microsystems if (s_arg) 33816be03d0bSVasumathi Sundaram - Sun Microsystems fields_str = allstat_fields; 33826be03d0bSVasumathi Sundaram - Sun Microsystems else if (flags & DLADM_OPT_ACTIVE) 3383e7801d59Ssowmini fields_str = all_active_fields; 3384e7801d59Ssowmini else 3385e7801d59Ssowmini fields_str = all_inactive_fields; 3386e7801d59Ssowmini } 3387e7801d59Ssowmini 33888002d411SSowmini Varadhan state.ls_parsable = p_arg; 33896be03d0bSVasumathi Sundaram - Sun Microsystems state.ls_flags = flags; 33906be03d0bSVasumathi Sundaram - Sun Microsystems state.ls_donefirst = B_FALSE; 33916be03d0bSVasumathi Sundaram - Sun Microsystems 33926be03d0bSVasumathi Sundaram - Sun Microsystems if (s_arg) { 33936be03d0bSVasumathi Sundaram - Sun Microsystems link_stats(linkid, interval, fields_str, &state); 33946be03d0bSVasumathi Sundaram - Sun Microsystems return; 33956be03d0bSVasumathi Sundaram - Sun Microsystems } 33968002d411SSowmini Varadhan if (state.ls_parsable) 33978002d411SSowmini Varadhan ofmtflags |= OFMT_PARSABLE; 33988002d411SSowmini Varadhan oferr = ofmt_open(fields_str, link_fields, ofmtflags, 0, &ofmt); 33998002d411SSowmini Varadhan dladm_ofmt_check(oferr, state.ls_parsable, ofmt); 34008002d411SSowmini Varadhan state.ls_ofmt = ofmt; 3401e7801d59Ssowmini 3402d62bc4baSyz147064 if (linkid == DATALINK_ALL_LINKID) { 34034ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(show_link, handle, &state, 3404d62bc4baSyz147064 DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE, flags); 3405210db224Sericheng } else { 34064ac67f02SAnurag S. Maskey (void) show_link(handle, linkid, &state); 3407d62bc4baSyz147064 if (state.ls_status != DLADM_STATUS_OK) { 3408d62bc4baSyz147064 die_dlerr(state.ls_status, "failed to show link %s", 3409d62bc4baSyz147064 argv[optind]); 3410d62bc4baSyz147064 } 34117c478bd9Sstevel@tonic-gate } 34128002d411SSowmini Varadhan ofmt_close(ofmt); 3413210db224Sericheng } 34147c478bd9Sstevel@tonic-gate 34157c478bd9Sstevel@tonic-gate static void 34168d5c46e6Sam223141 do_show_aggr(int argc, char *argv[], const char *use) 34177c478bd9Sstevel@tonic-gate { 34187c478bd9Sstevel@tonic-gate boolean_t L_arg = B_FALSE; 34197c478bd9Sstevel@tonic-gate boolean_t s_arg = B_FALSE; 34207c478bd9Sstevel@tonic-gate boolean_t i_arg = B_FALSE; 3421d62bc4baSyz147064 boolean_t p_arg = B_FALSE; 3422d62bc4baSyz147064 boolean_t x_arg = B_FALSE; 34237c478bd9Sstevel@tonic-gate show_grp_state_t state; 3424d62bc4baSyz147064 uint32_t flags = DLADM_OPT_ACTIVE; 3425d62bc4baSyz147064 datalink_id_t linkid = DATALINK_ALL_LINKID; 3426d62bc4baSyz147064 int option; 342763a6526dSMichael Lim uint32_t interval = 0; 3428d62bc4baSyz147064 int key; 3429d62bc4baSyz147064 dladm_status_t status; 3430e7801d59Ssowmini boolean_t o_arg = B_FALSE; 3431e7801d59Ssowmini char *fields_str = NULL; 3432e7801d59Ssowmini char *all_fields = 3433e7801d59Ssowmini "link,policy,addrpolicy,lacpactivity,lacptimer,flags"; 3434e7801d59Ssowmini char *all_lacp_fields = 3435e7801d59Ssowmini "link,port,aggregatable,sync,coll,dist,defaulted,expired"; 3436e7801d59Ssowmini char *all_stats_fields = 3437e7801d59Ssowmini "link,port,ipackets,rbytes,opackets,obytes,ipktdist,opktdist"; 3438e7801d59Ssowmini char *all_extended_fields = 3439e7801d59Ssowmini "link,port,speed,duplex,state,address,portstate"; 34402b24ab6bSSebastien Roy const ofmt_field_t *pf; 34418002d411SSowmini Varadhan ofmt_handle_t ofmt; 34428002d411SSowmini Varadhan ofmt_status_t oferr; 34438002d411SSowmini Varadhan uint_t ofmtflags = 0; 3444e7801d59Ssowmini 34457c478bd9Sstevel@tonic-gate opterr = 0; 3446e7801d59Ssowmini while ((option = getopt_long(argc, argv, ":LpPxsi:o:", 3447d62bc4baSyz147064 show_lopts, NULL)) != -1) { 34487c478bd9Sstevel@tonic-gate switch (option) { 34497c478bd9Sstevel@tonic-gate case 'L': 345033343a97Smeem if (L_arg) 345133343a97Smeem die_optdup(option); 34527c478bd9Sstevel@tonic-gate 34537c478bd9Sstevel@tonic-gate L_arg = B_TRUE; 34547c478bd9Sstevel@tonic-gate break; 34557c478bd9Sstevel@tonic-gate case 'p': 3456d62bc4baSyz147064 if (p_arg) 3457d62bc4baSyz147064 die_optdup(option); 3458d62bc4baSyz147064 3459d62bc4baSyz147064 p_arg = B_TRUE; 3460d62bc4baSyz147064 break; 3461d62bc4baSyz147064 case 'x': 3462d62bc4baSyz147064 if (x_arg) 3463d62bc4baSyz147064 die_optdup(option); 3464d62bc4baSyz147064 3465d62bc4baSyz147064 x_arg = B_TRUE; 3466d62bc4baSyz147064 break; 3467d62bc4baSyz147064 case 'P': 3468d62bc4baSyz147064 if (flags != DLADM_OPT_ACTIVE) 3469d62bc4baSyz147064 die_optdup(option); 3470d62bc4baSyz147064 3471d62bc4baSyz147064 flags = DLADM_OPT_PERSIST; 34727c478bd9Sstevel@tonic-gate break; 34737c478bd9Sstevel@tonic-gate case 's': 347433343a97Smeem if (s_arg) 347533343a97Smeem die_optdup(option); 34767c478bd9Sstevel@tonic-gate 34777c478bd9Sstevel@tonic-gate s_arg = B_TRUE; 34787c478bd9Sstevel@tonic-gate break; 3479e7801d59Ssowmini case 'o': 3480e7801d59Ssowmini o_arg = B_TRUE; 3481e7801d59Ssowmini fields_str = optarg; 3482e7801d59Ssowmini break; 34837c478bd9Sstevel@tonic-gate case 'i': 348433343a97Smeem if (i_arg) 348533343a97Smeem die_optdup(option); 34867c478bd9Sstevel@tonic-gate 34877c478bd9Sstevel@tonic-gate i_arg = B_TRUE; 348863a6526dSMichael Lim if (!dladm_str2interval(optarg, &interval)) 348933343a97Smeem die("invalid interval value '%s'", optarg); 34907c478bd9Sstevel@tonic-gate break; 34917c478bd9Sstevel@tonic-gate default: 34928d5c46e6Sam223141 die_opterr(optopt, option, use); 349333343a97Smeem break; 34947c478bd9Sstevel@tonic-gate } 34957c478bd9Sstevel@tonic-gate } 34967c478bd9Sstevel@tonic-gate 34970d365605Sschuster if (p_arg && !o_arg) 34980d365605Sschuster die("-p requires -o"); 34990d365605Sschuster 35000d365605Sschuster if (p_arg && strcasecmp(fields_str, "all") == 0) 35010d365605Sschuster die("\"-o all\" is invalid with -p"); 35020d365605Sschuster 350333343a97Smeem if (i_arg && !s_arg) 350433343a97Smeem die("the option -i can be used only with -s"); 35057c478bd9Sstevel@tonic-gate 3506d62bc4baSyz147064 if (s_arg && (L_arg || p_arg || x_arg || flags != DLADM_OPT_ACTIVE)) { 3507d62bc4baSyz147064 die("the option -%c cannot be used with -s", 3508d62bc4baSyz147064 L_arg ? 'L' : (p_arg ? 'p' : (x_arg ? 'x' : 'P'))); 3509d62bc4baSyz147064 } 3510d62bc4baSyz147064 3511d62bc4baSyz147064 if (L_arg && flags != DLADM_OPT_ACTIVE) 3512d62bc4baSyz147064 die("the option -P cannot be used with -L"); 3513d62bc4baSyz147064 3514d62bc4baSyz147064 if (x_arg && (L_arg || flags != DLADM_OPT_ACTIVE)) 3515d62bc4baSyz147064 die("the option -%c cannot be used with -x", L_arg ? 'L' : 'P'); 3516d62bc4baSyz147064 3517d62bc4baSyz147064 /* get aggregation key or aggrname (optional last argument) */ 35187c478bd9Sstevel@tonic-gate if (optind == (argc-1)) { 3519d62bc4baSyz147064 if (!str2int(argv[optind], &key)) { 35204ac67f02SAnurag S. Maskey status = dladm_name2info(handle, argv[optind], 35214ac67f02SAnurag S. Maskey &linkid, NULL, NULL, NULL); 3522d62bc4baSyz147064 } else { 35234ac67f02SAnurag S. Maskey status = dladm_key2linkid(handle, (uint16_t)key, 3524d62bc4baSyz147064 &linkid, DLADM_OPT_ACTIVE); 3525d62bc4baSyz147064 } 3526d62bc4baSyz147064 3527d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 3528d62bc4baSyz147064 die("non-existent aggregation '%s'", argv[optind]); 3529d62bc4baSyz147064 35307c478bd9Sstevel@tonic-gate } else if (optind != argc) { 35317c478bd9Sstevel@tonic-gate usage(); 35327c478bd9Sstevel@tonic-gate } 35337c478bd9Sstevel@tonic-gate 3534d62bc4baSyz147064 bzero(&state, sizeof (state)); 3535d62bc4baSyz147064 state.gs_lacp = L_arg; 3536d62bc4baSyz147064 state.gs_stats = s_arg; 3537d62bc4baSyz147064 state.gs_flags = flags; 35388002d411SSowmini Varadhan state.gs_parsable = p_arg; 3539d62bc4baSyz147064 state.gs_extended = x_arg; 3540d62bc4baSyz147064 3541e7801d59Ssowmini if (!o_arg || (o_arg && strcasecmp(fields_str, "all") == 0)) { 3542e7801d59Ssowmini if (state.gs_lacp) 3543e7801d59Ssowmini fields_str = all_lacp_fields; 3544e7801d59Ssowmini else if (state.gs_stats) 3545e7801d59Ssowmini fields_str = all_stats_fields; 3546e7801d59Ssowmini else if (state.gs_extended) 3547e7801d59Ssowmini fields_str = all_extended_fields; 3548e7801d59Ssowmini else 3549e7801d59Ssowmini fields_str = all_fields; 3550e7801d59Ssowmini } 3551e7801d59Ssowmini 3552e7801d59Ssowmini if (state.gs_lacp) { 3553e7801d59Ssowmini pf = aggr_l_fields; 3554e7801d59Ssowmini } else if (state.gs_stats) { 3555e7801d59Ssowmini pf = aggr_s_fields; 3556e7801d59Ssowmini } else if (state.gs_extended) { 3557e7801d59Ssowmini pf = aggr_x_fields; 3558e7801d59Ssowmini } else { 3559e7801d59Ssowmini pf = laggr_fields; 3560e7801d59Ssowmini } 3561e7801d59Ssowmini 35628002d411SSowmini Varadhan if (state.gs_parsable) 35638002d411SSowmini Varadhan ofmtflags |= OFMT_PARSABLE; 35648002d411SSowmini Varadhan oferr = ofmt_open(fields_str, pf, ofmtflags, 0, &ofmt); 35658002d411SSowmini Varadhan dladm_ofmt_check(oferr, state.gs_parsable, ofmt); 35668002d411SSowmini Varadhan state.gs_ofmt = ofmt; 3567e7801d59Ssowmini 35687c478bd9Sstevel@tonic-gate if (s_arg) { 3569d62bc4baSyz147064 aggr_stats(linkid, &state, interval); 35708002d411SSowmini Varadhan ofmt_close(ofmt); 35717c478bd9Sstevel@tonic-gate return; 35727c478bd9Sstevel@tonic-gate } 35737c478bd9Sstevel@tonic-gate 3574d62bc4baSyz147064 if (linkid == DATALINK_ALL_LINKID) { 35754ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(show_aggr, handle, &state, 3576d62bc4baSyz147064 DATALINK_CLASS_AGGR, DATALINK_ANY_MEDIATYPE, flags); 3577d62bc4baSyz147064 } else { 35784ac67f02SAnurag S. Maskey (void) show_aggr(handle, linkid, &state); 3579d62bc4baSyz147064 if (state.gs_status != DLADM_STATUS_OK) { 3580d62bc4baSyz147064 die_dlerr(state.gs_status, "failed to show aggr %s", 3581d62bc4baSyz147064 argv[optind]); 3582d62bc4baSyz147064 } 3583d62bc4baSyz147064 } 35848002d411SSowmini Varadhan ofmt_close(ofmt); 35857c478bd9Sstevel@tonic-gate } 35867c478bd9Sstevel@tonic-gate 3587da14cebeSEric Cheng static dladm_status_t 3588da14cebeSEric Cheng print_phys_default(show_state_t *state, datalink_id_t linkid, 3589da14cebeSEric Cheng const char *link, uint32_t flags, uint32_t media) 35907c478bd9Sstevel@tonic-gate { 3591da14cebeSEric Cheng dladm_phys_attr_t dpa; 3592da14cebeSEric Cheng dladm_status_t status; 3593da14cebeSEric Cheng link_fields_buf_t pattr; 3594e7801d59Ssowmini 35954ac67f02SAnurag S. Maskey status = dladm_phys_info(handle, linkid, &dpa, state->ls_flags); 3596da14cebeSEric Cheng if (status != DLADM_STATUS_OK) 3597da14cebeSEric Cheng goto done; 35987c478bd9Sstevel@tonic-gate 3599da14cebeSEric Cheng (void) snprintf(pattr.link_phys_device, 3600da14cebeSEric Cheng sizeof (pattr.link_phys_device), "%s", dpa.dp_dev); 3601da14cebeSEric Cheng (void) dladm_media2str(media, pattr.link_phys_media); 3602da14cebeSEric Cheng if (state->ls_flags == DLADM_OPT_ACTIVE) { 3603da14cebeSEric Cheng boolean_t islink; 3604d62bc4baSyz147064 3605da14cebeSEric Cheng if (!dpa.dp_novanity) { 3606da14cebeSEric Cheng (void) strlcpy(pattr.link_name, link, 3607da14cebeSEric Cheng sizeof (pattr.link_name)); 3608da14cebeSEric Cheng islink = B_TRUE; 3609d62bc4baSyz147064 } else { 3610da14cebeSEric Cheng /* 3611da14cebeSEric Cheng * This is a physical link that does not have 3612da14cebeSEric Cheng * vanity naming support. 3613da14cebeSEric Cheng */ 3614da14cebeSEric Cheng (void) strlcpy(pattr.link_name, dpa.dp_dev, 3615da14cebeSEric Cheng sizeof (pattr.link_name)); 3616da14cebeSEric Cheng islink = B_FALSE; 36177c478bd9Sstevel@tonic-gate } 36187c478bd9Sstevel@tonic-gate 3619da14cebeSEric Cheng (void) get_linkstate(pattr.link_name, islink, 3620da14cebeSEric Cheng pattr.link_phys_state); 3621da14cebeSEric Cheng (void) snprintf(pattr.link_phys_speed, 3622da14cebeSEric Cheng sizeof (pattr.link_phys_speed), "%u", 3623da14cebeSEric Cheng (uint_t)((get_ifspeed(pattr.link_name, 3624da14cebeSEric Cheng islink)) / 1000000ull)); 3625da14cebeSEric Cheng (void) get_linkduplex(pattr.link_name, islink, 3626da14cebeSEric Cheng pattr.link_phys_duplex); 3627da14cebeSEric Cheng } else { 3628da14cebeSEric Cheng (void) snprintf(pattr.link_name, sizeof (pattr.link_name), 3629da14cebeSEric Cheng "%s", link); 3630da14cebeSEric Cheng (void) snprintf(pattr.link_flags, sizeof (pattr.link_flags), 3631da14cebeSEric Cheng "%c----", flags & DLADM_OPT_ACTIVE ? '-' : 'r'); 3632da14cebeSEric Cheng } 3633da14cebeSEric Cheng 36348002d411SSowmini Varadhan ofmt_print(state->ls_ofmt, &pattr); 3635da14cebeSEric Cheng 3636da14cebeSEric Cheng done: 3637da14cebeSEric Cheng return (status); 3638da14cebeSEric Cheng } 3639da14cebeSEric Cheng 3640da14cebeSEric Cheng typedef struct { 3641da14cebeSEric Cheng show_state_t *ms_state; 3642da14cebeSEric Cheng char *ms_link; 3643da14cebeSEric Cheng dladm_macaddr_attr_t *ms_mac_attr; 3644da14cebeSEric Cheng } print_phys_mac_state_t; 3645da14cebeSEric Cheng 36468002d411SSowmini Varadhan /* 36478002d411SSowmini Varadhan * callback for ofmt_print() 36488002d411SSowmini Varadhan */ 36498002d411SSowmini Varadhan static boolean_t 36508002d411SSowmini Varadhan print_phys_one_mac_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize) 3651da14cebeSEric Cheng { 36528002d411SSowmini Varadhan print_phys_mac_state_t *mac_state = ofarg->ofmt_cbarg; 3653da14cebeSEric Cheng dladm_macaddr_attr_t *attr = mac_state->ms_mac_attr; 3654da14cebeSEric Cheng boolean_t is_primary = (attr->ma_slot == 0); 36558002d411SSowmini Varadhan boolean_t is_parsable = mac_state->ms_state->ls_parsable; 3656da14cebeSEric Cheng 36578002d411SSowmini Varadhan switch (ofarg->ofmt_id) { 3658da14cebeSEric Cheng case PHYS_M_LINK: 36598002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%s", 36608002d411SSowmini Varadhan (is_primary || is_parsable) ? mac_state->ms_link : " "); 3661da14cebeSEric Cheng break; 3662da14cebeSEric Cheng case PHYS_M_SLOT: 3663da14cebeSEric Cheng if (is_primary) 36648002d411SSowmini Varadhan (void) snprintf(buf, bufsize, gettext("primary")); 3665da14cebeSEric Cheng else 36668002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%d", attr->ma_slot); 3667da14cebeSEric Cheng break; 3668da14cebeSEric Cheng case PHYS_M_ADDRESS: 3669da14cebeSEric Cheng (void) dladm_aggr_macaddr2str(attr->ma_addr, buf); 3670da14cebeSEric Cheng break; 3671da14cebeSEric Cheng case PHYS_M_INUSE: 36728002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%s", 3673da14cebeSEric Cheng attr->ma_flags & DLADM_MACADDR_USED ? gettext("yes") : 3674da14cebeSEric Cheng gettext("no")); 3675da14cebeSEric Cheng break; 3676da14cebeSEric Cheng case PHYS_M_CLIENT: 3677da14cebeSEric Cheng /* 3678da14cebeSEric Cheng * CR 6678526: resolve link id to actual link name if 3679da14cebeSEric Cheng * it is valid. 3680da14cebeSEric Cheng */ 36818002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%s", attr->ma_client_name); 3682da14cebeSEric Cheng break; 3683da14cebeSEric Cheng } 3684da14cebeSEric Cheng 36858002d411SSowmini Varadhan return (B_TRUE); 3686da14cebeSEric Cheng } 3687da14cebeSEric Cheng 3688da14cebeSEric Cheng typedef struct { 3689da14cebeSEric Cheng show_state_t *hs_state; 3690da14cebeSEric Cheng char *hs_link; 3691da14cebeSEric Cheng dladm_hwgrp_attr_t *hs_grp_attr; 3692da14cebeSEric Cheng } print_phys_hwgrp_state_t; 3693da14cebeSEric Cheng 36948002d411SSowmini Varadhan static boolean_t 36958002d411SSowmini Varadhan print_phys_one_hwgrp_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize) 3696da14cebeSEric Cheng { 3697*0dc2366fSVenugopal Iyer int i; 3698*0dc2366fSVenugopal Iyer boolean_t first = B_TRUE; 3699*0dc2366fSVenugopal Iyer int start = -1; 3700*0dc2366fSVenugopal Iyer int end = -1; 3701*0dc2366fSVenugopal Iyer char ringstr[RINGSTRLEN]; 3702*0dc2366fSVenugopal Iyer char ringsubstr[RINGSTRLEN]; 3703*0dc2366fSVenugopal Iyer 37048002d411SSowmini Varadhan print_phys_hwgrp_state_t *hg_state = ofarg->ofmt_cbarg; 3705da14cebeSEric Cheng dladm_hwgrp_attr_t *attr = hg_state->hs_grp_attr; 3706da14cebeSEric Cheng 37078002d411SSowmini Varadhan switch (ofarg->ofmt_id) { 3708da14cebeSEric Cheng case PHYS_H_LINK: 37098002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%s", attr->hg_link_name); 3710da14cebeSEric Cheng break; 3711*0dc2366fSVenugopal Iyer case PHYS_H_RINGTYPE: 37128002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%s", 3713da14cebeSEric Cheng attr->hg_grp_type == DLADM_HWGRP_TYPE_RX ? "RX" : "TX"); 3714da14cebeSEric Cheng break; 3715da14cebeSEric Cheng case PHYS_H_RINGS: 3716*0dc2366fSVenugopal Iyer ringstr[0] = '\0'; 3717*0dc2366fSVenugopal Iyer for (i = 0; i < attr->hg_n_rings; i++) { 3718*0dc2366fSVenugopal Iyer uint_t index = attr->hg_rings[i]; 3719*0dc2366fSVenugopal Iyer 3720*0dc2366fSVenugopal Iyer if (start == -1) { 3721*0dc2366fSVenugopal Iyer start = index; 3722*0dc2366fSVenugopal Iyer end = index; 3723*0dc2366fSVenugopal Iyer } else if (index == end + 1) { 3724*0dc2366fSVenugopal Iyer end = index; 3725*0dc2366fSVenugopal Iyer } else { 3726*0dc2366fSVenugopal Iyer if (start == end) { 3727*0dc2366fSVenugopal Iyer if (first) { 3728*0dc2366fSVenugopal Iyer (void) snprintf( 3729*0dc2366fSVenugopal Iyer ringsubstr, 3730*0dc2366fSVenugopal Iyer RINGSTRLEN, "%d", 3731*0dc2366fSVenugopal Iyer start); 3732*0dc2366fSVenugopal Iyer first = B_FALSE; 3733*0dc2366fSVenugopal Iyer } else { 3734*0dc2366fSVenugopal Iyer (void) snprintf( 3735*0dc2366fSVenugopal Iyer ringsubstr, 3736*0dc2366fSVenugopal Iyer RINGSTRLEN, ",%d", 3737*0dc2366fSVenugopal Iyer start); 3738*0dc2366fSVenugopal Iyer } 3739*0dc2366fSVenugopal Iyer } else { 3740*0dc2366fSVenugopal Iyer if (first) { 3741*0dc2366fSVenugopal Iyer (void) snprintf( 3742*0dc2366fSVenugopal Iyer ringsubstr, 3743*0dc2366fSVenugopal Iyer RINGSTRLEN, 3744*0dc2366fSVenugopal Iyer "%d-%d", 3745*0dc2366fSVenugopal Iyer start, end); 3746*0dc2366fSVenugopal Iyer first = B_FALSE; 3747*0dc2366fSVenugopal Iyer } else { 3748*0dc2366fSVenugopal Iyer (void) snprintf( 3749*0dc2366fSVenugopal Iyer ringsubstr, 3750*0dc2366fSVenugopal Iyer RINGSTRLEN, 3751*0dc2366fSVenugopal Iyer ",%d-%d", 3752*0dc2366fSVenugopal Iyer start, end); 3753*0dc2366fSVenugopal Iyer } 3754*0dc2366fSVenugopal Iyer } 3755*0dc2366fSVenugopal Iyer (void) strlcat(ringstr, ringsubstr, 3756*0dc2366fSVenugopal Iyer RINGSTRLEN); 3757*0dc2366fSVenugopal Iyer start = index; 3758*0dc2366fSVenugopal Iyer end = index; 3759*0dc2366fSVenugopal Iyer } 3760*0dc2366fSVenugopal Iyer } 3761*0dc2366fSVenugopal Iyer /* The last one */ 3762*0dc2366fSVenugopal Iyer if (start != -1) { 3763*0dc2366fSVenugopal Iyer if (first) { 3764*0dc2366fSVenugopal Iyer if (start == end) { 3765*0dc2366fSVenugopal Iyer (void) snprintf(buf, bufsize, "%d", 3766*0dc2366fSVenugopal Iyer start); 3767*0dc2366fSVenugopal Iyer } else { 3768*0dc2366fSVenugopal Iyer (void) snprintf(buf, bufsize, "%d-%d", 3769*0dc2366fSVenugopal Iyer start, end); 3770*0dc2366fSVenugopal Iyer } 3771*0dc2366fSVenugopal Iyer } else { 3772*0dc2366fSVenugopal Iyer if (start == end) { 3773*0dc2366fSVenugopal Iyer (void) snprintf(ringsubstr, RINGSTRLEN, 3774*0dc2366fSVenugopal Iyer ",%d", start); 3775*0dc2366fSVenugopal Iyer } else { 3776*0dc2366fSVenugopal Iyer (void) snprintf(ringsubstr, RINGSTRLEN, 3777*0dc2366fSVenugopal Iyer ",%d-%d", start, end); 3778*0dc2366fSVenugopal Iyer } 3779*0dc2366fSVenugopal Iyer (void) strlcat(ringstr, ringsubstr, RINGSTRLEN); 3780*0dc2366fSVenugopal Iyer (void) snprintf(buf, bufsize, "%s", ringstr); 3781*0dc2366fSVenugopal Iyer } 3782*0dc2366fSVenugopal Iyer } 3783da14cebeSEric Cheng break; 3784da14cebeSEric Cheng case PHYS_H_CLIENTS: 3785da14cebeSEric Cheng if (attr->hg_client_names[0] == '\0') { 37868002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "--"); 3787da14cebeSEric Cheng } else { 37888002d411SSowmini Varadhan (void) snprintf(buf, bufsize, "%s ", 3789da14cebeSEric Cheng attr->hg_client_names); 3790da14cebeSEric Cheng } 3791da14cebeSEric Cheng break; 3792da14cebeSEric Cheng } 3793da14cebeSEric Cheng 37948002d411SSowmini Varadhan return (B_TRUE); 3795da14cebeSEric Cheng } 3796da14cebeSEric Cheng 37978002d411SSowmini Varadhan /* 37988002d411SSowmini Varadhan * callback for dladm_walk_macaddr, invoked for each MAC address slot 37998002d411SSowmini Varadhan */ 3800da14cebeSEric Cheng static boolean_t 3801da14cebeSEric Cheng print_phys_mac_callback(void *arg, dladm_macaddr_attr_t *attr) 3802da14cebeSEric Cheng { 3803da14cebeSEric Cheng print_phys_mac_state_t *mac_state = arg; 3804da14cebeSEric Cheng show_state_t *state = mac_state->ms_state; 3805da14cebeSEric Cheng 3806da14cebeSEric Cheng mac_state->ms_mac_attr = attr; 38078002d411SSowmini Varadhan ofmt_print(state->ls_ofmt, mac_state); 3808da14cebeSEric Cheng 3809da14cebeSEric Cheng return (B_TRUE); 3810da14cebeSEric Cheng } 3811da14cebeSEric Cheng 38128002d411SSowmini Varadhan /* 38138002d411SSowmini Varadhan * invoked by show-phys -m for each physical data-link 38148002d411SSowmini Varadhan */ 3815da14cebeSEric Cheng static dladm_status_t 3816da14cebeSEric Cheng print_phys_mac(show_state_t *state, datalink_id_t linkid, char *link) 3817da14cebeSEric Cheng { 3818da14cebeSEric Cheng print_phys_mac_state_t mac_state; 3819da14cebeSEric Cheng 3820da14cebeSEric Cheng mac_state.ms_state = state; 3821da14cebeSEric Cheng mac_state.ms_link = link; 3822da14cebeSEric Cheng 38234ac67f02SAnurag S. Maskey return (dladm_walk_macaddr(handle, linkid, &mac_state, 3824da14cebeSEric Cheng print_phys_mac_callback)); 3825da14cebeSEric Cheng } 3826da14cebeSEric Cheng 38278002d411SSowmini Varadhan /* 38288002d411SSowmini Varadhan * callback for dladm_walk_hwgrp, invoked for each MAC hwgrp 38298002d411SSowmini Varadhan */ 3830da14cebeSEric Cheng static boolean_t 3831da14cebeSEric Cheng print_phys_hwgrp_callback(void *arg, dladm_hwgrp_attr_t *attr) 3832da14cebeSEric Cheng { 3833da14cebeSEric Cheng print_phys_hwgrp_state_t *hwgrp_state = arg; 3834da14cebeSEric Cheng show_state_t *state = hwgrp_state->hs_state; 3835da14cebeSEric Cheng 3836da14cebeSEric Cheng hwgrp_state->hs_grp_attr = attr; 38378002d411SSowmini Varadhan ofmt_print(state->ls_ofmt, hwgrp_state); 3838da14cebeSEric Cheng 3839da14cebeSEric Cheng return (B_TRUE); 3840da14cebeSEric Cheng } 3841da14cebeSEric Cheng 3842da14cebeSEric Cheng /* invoked by show-phys -H for each physical data-link */ 3843da14cebeSEric Cheng static dladm_status_t 3844da14cebeSEric Cheng print_phys_hwgrp(show_state_t *state, datalink_id_t linkid, char *link) 3845da14cebeSEric Cheng { 3846da14cebeSEric Cheng print_phys_hwgrp_state_t hwgrp_state; 3847da14cebeSEric Cheng 3848da14cebeSEric Cheng hwgrp_state.hs_state = state; 3849da14cebeSEric Cheng hwgrp_state.hs_link = link; 38504ac67f02SAnurag S. Maskey return (dladm_walk_hwgrp(handle, linkid, &hwgrp_state, 3851da14cebeSEric Cheng print_phys_hwgrp_callback)); 3852da14cebeSEric Cheng } 3853d62bc4baSyz147064 38542b24ab6bSSebastien Roy /* 38552b24ab6bSSebastien Roy * Parse the "local=<laddr>,remote=<raddr>" sub-options for the -a option of 38562b24ab6bSSebastien Roy * *-iptun subcommands. 38572b24ab6bSSebastien Roy */ 38582b24ab6bSSebastien Roy static void 38592b24ab6bSSebastien Roy iptun_process_addrarg(char *addrarg, iptun_params_t *params) 38602b24ab6bSSebastien Roy { 38612b24ab6bSSebastien Roy char *addrval; 38622b24ab6bSSebastien Roy 38632b24ab6bSSebastien Roy while (*addrarg != '\0') { 38642b24ab6bSSebastien Roy switch (getsubopt(&addrarg, iptun_addropts, &addrval)) { 38652b24ab6bSSebastien Roy case IPTUN_LOCAL: 38662b24ab6bSSebastien Roy params->iptun_param_flags |= IPTUN_PARAM_LADDR; 38672b24ab6bSSebastien Roy if (strlcpy(params->iptun_param_laddr, addrval, 38682b24ab6bSSebastien Roy sizeof (params->iptun_param_laddr)) >= 38692b24ab6bSSebastien Roy sizeof (params->iptun_param_laddr)) 38702b24ab6bSSebastien Roy die("tunnel source address is too long"); 38712b24ab6bSSebastien Roy break; 38722b24ab6bSSebastien Roy case IPTUN_REMOTE: 38732b24ab6bSSebastien Roy params->iptun_param_flags |= IPTUN_PARAM_RADDR; 38742b24ab6bSSebastien Roy if (strlcpy(params->iptun_param_raddr, addrval, 38752b24ab6bSSebastien Roy sizeof (params->iptun_param_raddr)) >= 38762b24ab6bSSebastien Roy sizeof (params->iptun_param_raddr)) 38772b24ab6bSSebastien Roy die("tunnel destination address is too long"); 38782b24ab6bSSebastien Roy break; 38792b24ab6bSSebastien Roy default: 38802b24ab6bSSebastien Roy die("invalid address type: %s", addrval); 38812b24ab6bSSebastien Roy break; 38822b24ab6bSSebastien Roy } 38832b24ab6bSSebastien Roy } 38842b24ab6bSSebastien Roy } 38852b24ab6bSSebastien Roy 38862b24ab6bSSebastien Roy /* 38872b24ab6bSSebastien Roy * Convenience routine to process iptun-create/modify/delete subcommand 38882b24ab6bSSebastien Roy * arguments. 38892b24ab6bSSebastien Roy */ 38902b24ab6bSSebastien Roy static void 38912b24ab6bSSebastien Roy iptun_process_args(int argc, char *argv[], const char *opts, 38922b24ab6bSSebastien Roy iptun_params_t *params, uint32_t *flags, char *name, const char *use) 38932b24ab6bSSebastien Roy { 38942b24ab6bSSebastien Roy int option; 38952b24ab6bSSebastien Roy char *altroot = NULL; 38962b24ab6bSSebastien Roy 38972b24ab6bSSebastien Roy if (params != NULL) 38982b24ab6bSSebastien Roy bzero(params, sizeof (*params)); 38992b24ab6bSSebastien Roy *flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST; 39002b24ab6bSSebastien Roy 39012b24ab6bSSebastien Roy opterr = 0; 39022b24ab6bSSebastien Roy while ((option = getopt_long(argc, argv, opts, iptun_lopts, NULL)) != 39032b24ab6bSSebastien Roy -1) { 39042b24ab6bSSebastien Roy switch (option) { 39052b24ab6bSSebastien Roy case 'a': 39062b24ab6bSSebastien Roy iptun_process_addrarg(optarg, params); 39072b24ab6bSSebastien Roy break; 39082b24ab6bSSebastien Roy case 'R': 39092b24ab6bSSebastien Roy altroot = optarg; 39102b24ab6bSSebastien Roy break; 39112b24ab6bSSebastien Roy case 't': 39122b24ab6bSSebastien Roy *flags &= ~DLADM_OPT_PERSIST; 39132b24ab6bSSebastien Roy break; 39142b24ab6bSSebastien Roy case 'T': 39152b24ab6bSSebastien Roy params->iptun_param_type = iptun_gettypebyname(optarg); 39162b24ab6bSSebastien Roy if (params->iptun_param_type == IPTUN_TYPE_UNKNOWN) 39172b24ab6bSSebastien Roy die("unknown tunnel type: %s", optarg); 39182b24ab6bSSebastien Roy params->iptun_param_flags |= IPTUN_PARAM_TYPE; 39192b24ab6bSSebastien Roy break; 39202b24ab6bSSebastien Roy default: 39212b24ab6bSSebastien Roy die_opterr(optopt, option, use); 39222b24ab6bSSebastien Roy break; 39232b24ab6bSSebastien Roy } 39242b24ab6bSSebastien Roy } 39252b24ab6bSSebastien Roy 39262b24ab6bSSebastien Roy /* Get the required tunnel name argument. */ 39272b24ab6bSSebastien Roy if (argc - optind != 1) 39282b24ab6bSSebastien Roy usage(); 39292b24ab6bSSebastien Roy 39302b24ab6bSSebastien Roy if (strlcpy(name, argv[optind], MAXLINKNAMELEN) >= MAXLINKNAMELEN) 39312b24ab6bSSebastien Roy die("tunnel name is too long"); 39322b24ab6bSSebastien Roy 39332b24ab6bSSebastien Roy if (altroot != NULL) 39342b24ab6bSSebastien Roy altroot_cmd(altroot, argc, argv); 39352b24ab6bSSebastien Roy } 39362b24ab6bSSebastien Roy 39372b24ab6bSSebastien Roy static void 39382b24ab6bSSebastien Roy do_create_iptun(int argc, char *argv[], const char *use) 39392b24ab6bSSebastien Roy { 39402b24ab6bSSebastien Roy iptun_params_t params; 39412b24ab6bSSebastien Roy dladm_status_t status; 39422b24ab6bSSebastien Roy uint32_t flags; 39432b24ab6bSSebastien Roy char name[MAXLINKNAMELEN]; 39442b24ab6bSSebastien Roy 39452b24ab6bSSebastien Roy iptun_process_args(argc, argv, ":a:R:tT:", ¶ms, &flags, name, 39462b24ab6bSSebastien Roy use); 39472b24ab6bSSebastien Roy 39482b24ab6bSSebastien Roy status = dladm_iptun_create(handle, name, ¶ms, flags); 39492b24ab6bSSebastien Roy if (status != DLADM_STATUS_OK) 39502b24ab6bSSebastien Roy die_dlerr(status, "could not create tunnel"); 39512b24ab6bSSebastien Roy } 39522b24ab6bSSebastien Roy 39532b24ab6bSSebastien Roy static void 39542b24ab6bSSebastien Roy do_delete_iptun(int argc, char *argv[], const char *use) 39552b24ab6bSSebastien Roy { 39562b24ab6bSSebastien Roy uint32_t flags; 39572b24ab6bSSebastien Roy datalink_id_t linkid; 39582b24ab6bSSebastien Roy dladm_status_t status; 39592b24ab6bSSebastien Roy char name[MAXLINKNAMELEN]; 39602b24ab6bSSebastien Roy 39612b24ab6bSSebastien Roy iptun_process_args(argc, argv, ":R:t", NULL, &flags, name, use); 39622b24ab6bSSebastien Roy 39632b24ab6bSSebastien Roy status = dladm_name2info(handle, name, &linkid, NULL, NULL, NULL); 39642b24ab6bSSebastien Roy if (status != DLADM_STATUS_OK) 39652b24ab6bSSebastien Roy die_dlerr(status, "could not delete tunnel"); 39662b24ab6bSSebastien Roy status = dladm_iptun_delete(handle, linkid, flags); 39672b24ab6bSSebastien Roy if (status != DLADM_STATUS_OK) 39682b24ab6bSSebastien Roy die_dlerr(status, "could not delete tunnel"); 39692b24ab6bSSebastien Roy } 39702b24ab6bSSebastien Roy 39712b24ab6bSSebastien Roy static void 39722b24ab6bSSebastien Roy do_modify_iptun(int argc, char *argv[], const char *use) 39732b24ab6bSSebastien Roy { 39742b24ab6bSSebastien Roy iptun_params_t params; 39752b24ab6bSSebastien Roy uint32_t flags; 39762b24ab6bSSebastien Roy dladm_status_t status; 39772b24ab6bSSebastien Roy char name[MAXLINKNAMELEN]; 39782b24ab6bSSebastien Roy 39792b24ab6bSSebastien Roy iptun_process_args(argc, argv, ":a:R:t", ¶ms, &flags, name, use); 39802b24ab6bSSebastien Roy 39812b24ab6bSSebastien Roy if ((status = dladm_name2info(handle, name, ¶ms.iptun_param_linkid, 39822b24ab6bSSebastien Roy NULL, NULL, NULL)) != DLADM_STATUS_OK) 39832b24ab6bSSebastien Roy die_dlerr(status, "could not modify tunnel"); 39842b24ab6bSSebastien Roy status = dladm_iptun_modify(handle, ¶ms, flags); 39852b24ab6bSSebastien Roy if (status != DLADM_STATUS_OK) 39862b24ab6bSSebastien Roy die_dlerr(status, "could not modify tunnel"); 39872b24ab6bSSebastien Roy } 39882b24ab6bSSebastien Roy 39892b24ab6bSSebastien Roy static void 39902b24ab6bSSebastien Roy do_show_iptun(int argc, char *argv[], const char *use) 39912b24ab6bSSebastien Roy { 39922b24ab6bSSebastien Roy char option; 39932b24ab6bSSebastien Roy datalink_id_t linkid; 39942b24ab6bSSebastien Roy uint32_t flags = DLADM_OPT_ACTIVE; 39952b24ab6bSSebastien Roy char *name = NULL; 39962b24ab6bSSebastien Roy dladm_status_t status; 39972b24ab6bSSebastien Roy const char *fields_str = NULL; 39982b24ab6bSSebastien Roy show_state_t state; 39992b24ab6bSSebastien Roy ofmt_handle_t ofmt; 40002b24ab6bSSebastien Roy ofmt_status_t oferr; 40012b24ab6bSSebastien Roy uint_t ofmtflags = 0; 40022b24ab6bSSebastien Roy 40032b24ab6bSSebastien Roy bzero(&state, sizeof (state)); 40042b24ab6bSSebastien Roy opterr = 0; 40052b24ab6bSSebastien Roy while ((option = getopt_long(argc, argv, ":pPo:", 40062b24ab6bSSebastien Roy iptun_lopts, NULL)) != -1) { 40072b24ab6bSSebastien Roy switch (option) { 40082b24ab6bSSebastien Roy case 'o': 40092b24ab6bSSebastien Roy fields_str = optarg; 40102b24ab6bSSebastien Roy break; 40112b24ab6bSSebastien Roy case 'p': 40122b24ab6bSSebastien Roy state.ls_parsable = B_TRUE; 40132b24ab6bSSebastien Roy ofmtflags = OFMT_PARSABLE; 40142b24ab6bSSebastien Roy break; 40152b24ab6bSSebastien Roy case 'P': 40162b24ab6bSSebastien Roy flags = DLADM_OPT_PERSIST; 40172b24ab6bSSebastien Roy break; 40182b24ab6bSSebastien Roy default: 40192b24ab6bSSebastien Roy die_opterr(optopt, option, use); 40202b24ab6bSSebastien Roy break; 40212b24ab6bSSebastien Roy } 40222b24ab6bSSebastien Roy } 40232b24ab6bSSebastien Roy 40242b24ab6bSSebastien Roy /* 40252b24ab6bSSebastien Roy * Get the optional tunnel name argument. If there is one, it must 40262b24ab6bSSebastien Roy * be the last thing remaining on the command-line. 40272b24ab6bSSebastien Roy */ 40282b24ab6bSSebastien Roy if (argc - optind > 1) 40292b24ab6bSSebastien Roy die(gettext(use)); 40302b24ab6bSSebastien Roy if (argc - optind == 1) 40312b24ab6bSSebastien Roy name = argv[optind]; 40322b24ab6bSSebastien Roy 40332b24ab6bSSebastien Roy oferr = ofmt_open(fields_str, iptun_fields, ofmtflags, 40342b24ab6bSSebastien Roy DLADM_DEFAULT_COL, &ofmt); 40352b24ab6bSSebastien Roy dladm_ofmt_check(oferr, state.ls_parsable, ofmt); 40362b24ab6bSSebastien Roy 40372b24ab6bSSebastien Roy state.ls_ofmt = ofmt; 40382b24ab6bSSebastien Roy state.ls_flags = flags; 40392b24ab6bSSebastien Roy 40402b24ab6bSSebastien Roy if (name == NULL) { 40412b24ab6bSSebastien Roy (void) dladm_walk_datalink_id(print_iptun_walker, handle, 40422b24ab6bSSebastien Roy &state, DATALINK_CLASS_IPTUN, DATALINK_ANY_MEDIATYPE, 40432b24ab6bSSebastien Roy flags); 40442b24ab6bSSebastien Roy status = state.ls_status; 40452b24ab6bSSebastien Roy } else { 40462b24ab6bSSebastien Roy if ((status = dladm_name2info(handle, name, &linkid, NULL, NULL, 40472b24ab6bSSebastien Roy NULL)) == DLADM_STATUS_OK) 40482b24ab6bSSebastien Roy status = print_iptun(handle, linkid, &state); 40492b24ab6bSSebastien Roy } 40502b24ab6bSSebastien Roy 40512b24ab6bSSebastien Roy if (status != DLADM_STATUS_OK) 40522b24ab6bSSebastien Roy die_dlerr(status, "unable to obtain tunnel status"); 40532b24ab6bSSebastien Roy } 40542b24ab6bSSebastien Roy 40552b24ab6bSSebastien Roy /* ARGSUSED */ 40562b24ab6bSSebastien Roy static void 40572b24ab6bSSebastien Roy do_up_iptun(int argc, char *argv[], const char *use) 40582b24ab6bSSebastien Roy { 40592b24ab6bSSebastien Roy datalink_id_t linkid = DATALINK_ALL_LINKID; 40602b24ab6bSSebastien Roy dladm_status_t status = DLADM_STATUS_OK; 40612b24ab6bSSebastien Roy 40622b24ab6bSSebastien Roy /* 40632b24ab6bSSebastien Roy * Get the optional tunnel name argument. If there is one, it must 40642b24ab6bSSebastien Roy * be the last thing remaining on the command-line. 40652b24ab6bSSebastien Roy */ 40662b24ab6bSSebastien Roy if (argc - optind > 1) 40672b24ab6bSSebastien Roy usage(); 40682b24ab6bSSebastien Roy if (argc - optind == 1) { 40692b24ab6bSSebastien Roy status = dladm_name2info(handle, argv[optind], &linkid, NULL, 40702b24ab6bSSebastien Roy NULL, NULL); 40712b24ab6bSSebastien Roy } 40722b24ab6bSSebastien Roy if (status == DLADM_STATUS_OK) 40732b24ab6bSSebastien Roy status = dladm_iptun_up(handle, linkid); 40742b24ab6bSSebastien Roy if (status != DLADM_STATUS_OK) 40752b24ab6bSSebastien Roy die_dlerr(status, "unable to configure IP tunnel links"); 40762b24ab6bSSebastien Roy } 40772b24ab6bSSebastien Roy 40782b24ab6bSSebastien Roy /* ARGSUSED */ 40792b24ab6bSSebastien Roy static void 40802b24ab6bSSebastien Roy do_down_iptun(int argc, char *argv[], const char *use) 40812b24ab6bSSebastien Roy { 40822b24ab6bSSebastien Roy datalink_id_t linkid = DATALINK_ALL_LINKID; 40832b24ab6bSSebastien Roy dladm_status_t status = DLADM_STATUS_OK; 40842b24ab6bSSebastien Roy 40852b24ab6bSSebastien Roy /* 40862b24ab6bSSebastien Roy * Get the optional tunnel name argument. If there is one, it must 40872b24ab6bSSebastien Roy * be the last thing remaining on the command-line. 40882b24ab6bSSebastien Roy */ 40892b24ab6bSSebastien Roy if (argc - optind > 1) 40902b24ab6bSSebastien Roy usage(); 40912b24ab6bSSebastien Roy if (argc - optind == 1) { 40922b24ab6bSSebastien Roy status = dladm_name2info(handle, argv[optind], &linkid, NULL, 40932b24ab6bSSebastien Roy NULL, NULL); 40942b24ab6bSSebastien Roy } 40952b24ab6bSSebastien Roy if (status == DLADM_STATUS_OK) 40962b24ab6bSSebastien Roy status = dladm_iptun_down(handle, linkid); 40972b24ab6bSSebastien Roy if (status != DLADM_STATUS_OK) 40982b24ab6bSSebastien Roy die_dlerr(status, "unable to bring down IP tunnel links"); 40992b24ab6bSSebastien Roy } 41002b24ab6bSSebastien Roy 41012b24ab6bSSebastien Roy static iptun_type_t 41022b24ab6bSSebastien Roy iptun_gettypebyname(char *typestr) 41032b24ab6bSSebastien Roy { 41042b24ab6bSSebastien Roy int i; 41052b24ab6bSSebastien Roy 41062b24ab6bSSebastien Roy for (i = 0; iptun_types[i].type_name != NULL; i++) { 41072b24ab6bSSebastien Roy if (strncmp(iptun_types[i].type_name, typestr, 41082b24ab6bSSebastien Roy strlen(iptun_types[i].type_name)) == 0) { 41092b24ab6bSSebastien Roy return (iptun_types[i].type_value); 41102b24ab6bSSebastien Roy } 41112b24ab6bSSebastien Roy } 41122b24ab6bSSebastien Roy return (IPTUN_TYPE_UNKNOWN); 41132b24ab6bSSebastien Roy } 41142b24ab6bSSebastien Roy 41152b24ab6bSSebastien Roy static const char * 41162b24ab6bSSebastien Roy iptun_gettypebyvalue(iptun_type_t type) 41172b24ab6bSSebastien Roy { 41182b24ab6bSSebastien Roy int i; 41192b24ab6bSSebastien Roy 41202b24ab6bSSebastien Roy for (i = 0; iptun_types[i].type_name != NULL; i++) { 41212b24ab6bSSebastien Roy if (iptun_types[i].type_value == type) 41222b24ab6bSSebastien Roy return (iptun_types[i].type_name); 41232b24ab6bSSebastien Roy } 41242b24ab6bSSebastien Roy return (NULL); 41252b24ab6bSSebastien Roy } 41262b24ab6bSSebastien Roy 41272b24ab6bSSebastien Roy static dladm_status_t 41282b24ab6bSSebastien Roy print_iptun(dladm_handle_t dh, datalink_id_t linkid, show_state_t *state) 41292b24ab6bSSebastien Roy { 41302b24ab6bSSebastien Roy dladm_status_t status; 41312b24ab6bSSebastien Roy iptun_params_t params; 41322b24ab6bSSebastien Roy iptun_fields_buf_t lbuf; 41332b24ab6bSSebastien Roy const char *laddr; 41342b24ab6bSSebastien Roy const char *raddr; 41352b24ab6bSSebastien Roy 41362b24ab6bSSebastien Roy params.iptun_param_linkid = linkid; 41372b24ab6bSSebastien Roy status = dladm_iptun_getparams(dh, ¶ms, state->ls_flags); 41382b24ab6bSSebastien Roy if (status != DLADM_STATUS_OK) 41392b24ab6bSSebastien Roy return (status); 41402b24ab6bSSebastien Roy 41412b24ab6bSSebastien Roy /* LINK */ 41422b24ab6bSSebastien Roy status = dladm_datalink_id2info(dh, linkid, NULL, NULL, NULL, 41432b24ab6bSSebastien Roy lbuf.iptun_name, sizeof (lbuf.iptun_name)); 41442b24ab6bSSebastien Roy if (status != DLADM_STATUS_OK) 41452b24ab6bSSebastien Roy return (status); 41462b24ab6bSSebastien Roy 41472b24ab6bSSebastien Roy /* TYPE */ 41482b24ab6bSSebastien Roy (void) strlcpy(lbuf.iptun_type, 41492b24ab6bSSebastien Roy iptun_gettypebyvalue(params.iptun_param_type), 41502b24ab6bSSebastien Roy sizeof (lbuf.iptun_type)); 41512b24ab6bSSebastien Roy 41522b24ab6bSSebastien Roy /* FLAGS */ 41532b24ab6bSSebastien Roy (void) memset(lbuf.iptun_flags, '-', IPTUN_NUM_FLAGS); 41542b24ab6bSSebastien Roy lbuf.iptun_flags[IPTUN_NUM_FLAGS] = '\0'; 41552b24ab6bSSebastien Roy if (params.iptun_param_flags & IPTUN_PARAM_IPSECPOL) 41562b24ab6bSSebastien Roy lbuf.iptun_flags[IPTUN_SFLAG_INDEX] = 's'; 41572b24ab6bSSebastien Roy if (params.iptun_param_flags & IPTUN_PARAM_IMPLICIT) 41582b24ab6bSSebastien Roy lbuf.iptun_flags[IPTUN_IFLAG_INDEX] = 'i'; 41592b24ab6bSSebastien Roy 41602b24ab6bSSebastien Roy /* LOCAL */ 41612b24ab6bSSebastien Roy if (params.iptun_param_flags & IPTUN_PARAM_LADDR) 41622b24ab6bSSebastien Roy laddr = params.iptun_param_laddr; 41632b24ab6bSSebastien Roy else 41642b24ab6bSSebastien Roy laddr = (state->ls_parsable) ? "" : "--"; 41652b24ab6bSSebastien Roy (void) strlcpy(lbuf.iptun_laddr, laddr, sizeof (lbuf.iptun_laddr)); 41662b24ab6bSSebastien Roy 41672b24ab6bSSebastien Roy /* REMOTE */ 41682b24ab6bSSebastien Roy if (params.iptun_param_flags & IPTUN_PARAM_RADDR) 41692b24ab6bSSebastien Roy raddr = params.iptun_param_raddr; 41702b24ab6bSSebastien Roy else 41712b24ab6bSSebastien Roy raddr = (state->ls_parsable) ? "" : "--"; 41722b24ab6bSSebastien Roy (void) strlcpy(lbuf.iptun_raddr, raddr, sizeof (lbuf.iptun_raddr)); 41732b24ab6bSSebastien Roy 41742b24ab6bSSebastien Roy ofmt_print(state->ls_ofmt, &lbuf); 41752b24ab6bSSebastien Roy 41762b24ab6bSSebastien Roy return (DLADM_STATUS_OK); 41772b24ab6bSSebastien Roy } 41782b24ab6bSSebastien Roy 41792b24ab6bSSebastien Roy static int 41802b24ab6bSSebastien Roy print_iptun_walker(dladm_handle_t dh, datalink_id_t linkid, void *arg) 41812b24ab6bSSebastien Roy { 41822b24ab6bSSebastien Roy ((show_state_t *)arg)->ls_status = print_iptun(dh, linkid, arg); 41832b24ab6bSSebastien Roy return (DLADM_WALK_CONTINUE); 41842b24ab6bSSebastien Roy } 41852b24ab6bSSebastien Roy 4186d62bc4baSyz147064 static dladm_status_t 4187da14cebeSEric Cheng print_phys(show_state_t *state, datalink_id_t linkid) 4188d62bc4baSyz147064 { 4189d62bc4baSyz147064 char link[MAXLINKNAMELEN]; 4190d62bc4baSyz147064 uint32_t flags; 4191da14cebeSEric Cheng dladm_status_t status; 4192d62bc4baSyz147064 datalink_class_t class; 4193d62bc4baSyz147064 uint32_t media; 4194d62bc4baSyz147064 41954ac67f02SAnurag S. Maskey if ((status = dladm_datalink_id2info(handle, linkid, &flags, &class, 41964ac67f02SAnurag S. Maskey &media, link, MAXLINKNAMELEN)) != DLADM_STATUS_OK) { 4197d62bc4baSyz147064 goto done; 4198d62bc4baSyz147064 } 4199d62bc4baSyz147064 4200d62bc4baSyz147064 if (class != DATALINK_CLASS_PHYS) { 4201d62bc4baSyz147064 status = DLADM_STATUS_BADARG; 4202d62bc4baSyz147064 goto done; 4203d62bc4baSyz147064 } 4204d62bc4baSyz147064 4205d62bc4baSyz147064 if (!(state->ls_flags & flags)) { 4206d62bc4baSyz147064 status = DLADM_STATUS_NOTFOUND; 4207d62bc4baSyz147064 goto done; 4208d62bc4baSyz147064 } 4209d62bc4baSyz147064 4210da14cebeSEric Cheng if (state->ls_mac) 4211da14cebeSEric Cheng status = print_phys_mac(state, linkid, link); 4212da14cebeSEric Cheng else if (state->ls_hwgrp) 4213da14cebeSEric Cheng status = print_phys_hwgrp(state, linkid, link); 4214da14cebeSEric Cheng else 4215da14cebeSEric Cheng status = print_phys_default(state, linkid, link, flags, media); 4216d62bc4baSyz147064 4217d62bc4baSyz147064 done: 4218d62bc4baSyz147064 return (status); 4219d62bc4baSyz147064 } 4220d62bc4baSyz147064 42214ac67f02SAnurag S. Maskey /* ARGSUSED */ 4222d62bc4baSyz147064 static int 42234ac67f02SAnurag S. Maskey show_phys(dladm_handle_t dh, datalink_id_t linkid, void *arg) 4224d62bc4baSyz147064 { 4225d62bc4baSyz147064 show_state_t *state = arg; 4226d62bc4baSyz147064 4227da14cebeSEric Cheng state->ls_status = print_phys(state, linkid); 4228d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 4229d62bc4baSyz147064 } 4230d62bc4baSyz147064 4231d62bc4baSyz147064 /* 4232d62bc4baSyz147064 * Print the active topology information. 4233d62bc4baSyz147064 */ 4234d62bc4baSyz147064 static dladm_status_t 4235e7801d59Ssowmini print_vlan(show_state_t *state, datalink_id_t linkid, link_fields_buf_t *l) 4236d62bc4baSyz147064 { 4237d62bc4baSyz147064 dladm_vlan_attr_t vinfo; 4238d62bc4baSyz147064 uint32_t flags; 4239d62bc4baSyz147064 dladm_status_t status; 4240d62bc4baSyz147064 42414ac67f02SAnurag S. Maskey if ((status = dladm_datalink_id2info(handle, linkid, &flags, NULL, NULL, 4242e7801d59Ssowmini l->link_name, sizeof (l->link_name))) != DLADM_STATUS_OK) { 4243d62bc4baSyz147064 goto done; 4244d62bc4baSyz147064 } 4245d62bc4baSyz147064 4246d62bc4baSyz147064 if (!(state->ls_flags & flags)) { 4247d62bc4baSyz147064 status = DLADM_STATUS_NOTFOUND; 4248d62bc4baSyz147064 goto done; 4249d62bc4baSyz147064 } 4250d62bc4baSyz147064 42514ac67f02SAnurag S. Maskey if ((status = dladm_vlan_info(handle, linkid, &vinfo, 42524ac67f02SAnurag S. Maskey state->ls_flags)) != DLADM_STATUS_OK || 42534ac67f02SAnurag S. Maskey (status = dladm_datalink_id2info(handle, vinfo.dv_linkid, NULL, 42544ac67f02SAnurag S. Maskey NULL, NULL, l->link_over, sizeof (l->link_over))) != 42554ac67f02SAnurag S. Maskey DLADM_STATUS_OK) { 4256d62bc4baSyz147064 goto done; 4257d62bc4baSyz147064 } 4258d62bc4baSyz147064 4259e7801d59Ssowmini (void) snprintf(l->link_vlan_vid, sizeof (l->link_vlan_vid), "%d", 4260e7801d59Ssowmini vinfo.dv_vid); 4261da14cebeSEric Cheng (void) snprintf(l->link_flags, sizeof (l->link_flags), "%c----", 4262da14cebeSEric Cheng vinfo.dv_force ? 'f' : '-'); 4263d62bc4baSyz147064 4264d62bc4baSyz147064 done: 4265d62bc4baSyz147064 return (status); 4266d62bc4baSyz147064 } 4267d62bc4baSyz147064 42684ac67f02SAnurag S. Maskey /* ARGSUSED */ 4269d62bc4baSyz147064 static int 42704ac67f02SAnurag S. Maskey show_vlan(dladm_handle_t dh, datalink_id_t linkid, void *arg) 4271d62bc4baSyz147064 { 4272d62bc4baSyz147064 show_state_t *state = arg; 4273d62bc4baSyz147064 dladm_status_t status; 4274e7801d59Ssowmini link_fields_buf_t lbuf; 4275d62bc4baSyz147064 42765f5c9f54SAnurag S. Maskey bzero(&lbuf, sizeof (link_fields_buf_t)); 4277e7801d59Ssowmini status = print_vlan(state, linkid, &lbuf); 4278d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 4279d62bc4baSyz147064 goto done; 4280e7801d59Ssowmini 42818002d411SSowmini Varadhan ofmt_print(state->ls_ofmt, &lbuf); 4282d62bc4baSyz147064 4283d62bc4baSyz147064 done: 4284d62bc4baSyz147064 state->ls_status = status; 4285d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 4286d62bc4baSyz147064 } 4287d62bc4baSyz147064 4288d62bc4baSyz147064 static void 42898d5c46e6Sam223141 do_show_phys(int argc, char *argv[], const char *use) 4290d62bc4baSyz147064 { 4291d62bc4baSyz147064 int option; 4292d62bc4baSyz147064 uint32_t flags = DLADM_OPT_ACTIVE; 4293d62bc4baSyz147064 boolean_t p_arg = B_FALSE; 4294e7801d59Ssowmini boolean_t o_arg = B_FALSE; 4295da14cebeSEric Cheng boolean_t m_arg = B_FALSE; 4296da14cebeSEric Cheng boolean_t H_arg = B_FALSE; 4297d62bc4baSyz147064 datalink_id_t linkid = DATALINK_ALL_LINKID; 4298d62bc4baSyz147064 show_state_t state; 4299d62bc4baSyz147064 dladm_status_t status; 4300e7801d59Ssowmini char *fields_str = NULL; 4301e7801d59Ssowmini char *all_active_fields = 4302e7801d59Ssowmini "link,media,state,speed,duplex,device"; 43035f5c9f54SAnurag S. Maskey char *all_inactive_fields = "link,device,media,flags"; 4304da14cebeSEric Cheng char *all_mac_fields = "link,slot,address,inuse,client"; 4305*0dc2366fSVenugopal Iyer char *all_hwgrp_fields = "link,ringtype,rings,clients"; 43062b24ab6bSSebastien Roy const ofmt_field_t *pf; 43078002d411SSowmini Varadhan ofmt_handle_t ofmt; 43088002d411SSowmini Varadhan ofmt_status_t oferr; 43098002d411SSowmini Varadhan uint_t ofmtflags = 0; 4310d62bc4baSyz147064 4311e7801d59Ssowmini bzero(&state, sizeof (state)); 4312d62bc4baSyz147064 opterr = 0; 4313da14cebeSEric Cheng while ((option = getopt_long(argc, argv, ":pPo:mH", 4314d62bc4baSyz147064 show_lopts, NULL)) != -1) { 4315d62bc4baSyz147064 switch (option) { 4316d62bc4baSyz147064 case 'p': 4317d62bc4baSyz147064 if (p_arg) 4318d62bc4baSyz147064 die_optdup(option); 4319d62bc4baSyz147064 4320d62bc4baSyz147064 p_arg = B_TRUE; 4321d62bc4baSyz147064 break; 4322d62bc4baSyz147064 case 'P': 4323d62bc4baSyz147064 if (flags != DLADM_OPT_ACTIVE) 4324d62bc4baSyz147064 die_optdup(option); 4325d62bc4baSyz147064 4326d62bc4baSyz147064 flags = DLADM_OPT_PERSIST; 4327d62bc4baSyz147064 break; 4328e7801d59Ssowmini case 'o': 4329e7801d59Ssowmini o_arg = B_TRUE; 4330e7801d59Ssowmini fields_str = optarg; 4331e7801d59Ssowmini break; 4332da14cebeSEric Cheng case 'm': 4333da14cebeSEric Cheng m_arg = B_TRUE; 4334da14cebeSEric Cheng break; 4335da14cebeSEric Cheng case 'H': 4336da14cebeSEric Cheng H_arg = B_TRUE; 4337da14cebeSEric Cheng break; 4338d62bc4baSyz147064 default: 43398d5c46e6Sam223141 die_opterr(optopt, option, use); 4340d62bc4baSyz147064 break; 4341d62bc4baSyz147064 } 4342d62bc4baSyz147064 } 4343d62bc4baSyz147064 43440d365605Sschuster if (p_arg && !o_arg) 43450d365605Sschuster die("-p requires -o"); 43460d365605Sschuster 4347da14cebeSEric Cheng if (m_arg && H_arg) 4348da14cebeSEric Cheng die("-m cannot combine with -H"); 4349da14cebeSEric Cheng 43500d365605Sschuster if (p_arg && strcasecmp(fields_str, "all") == 0) 43510d365605Sschuster die("\"-o all\" is invalid with -p"); 43520d365605Sschuster 4353d62bc4baSyz147064 /* get link name (optional last argument) */ 4354d62bc4baSyz147064 if (optind == (argc-1)) { 43554ac67f02SAnurag S. Maskey if ((status = dladm_name2info(handle, argv[optind], &linkid, 43564ac67f02SAnurag S. Maskey NULL, NULL, NULL)) != DLADM_STATUS_OK) { 4357d62bc4baSyz147064 die_dlerr(status, "link %s is not valid", argv[optind]); 4358d62bc4baSyz147064 } 4359d62bc4baSyz147064 } else if (optind != argc) { 4360d62bc4baSyz147064 usage(); 4361d62bc4baSyz147064 } 4362d62bc4baSyz147064 43638002d411SSowmini Varadhan state.ls_parsable = p_arg; 4364d62bc4baSyz147064 state.ls_flags = flags; 4365d62bc4baSyz147064 state.ls_donefirst = B_FALSE; 4366da14cebeSEric Cheng state.ls_mac = m_arg; 4367da14cebeSEric Cheng state.ls_hwgrp = H_arg; 4368d62bc4baSyz147064 4369da14cebeSEric Cheng if (m_arg && !(flags & DLADM_OPT_ACTIVE)) { 4370da14cebeSEric Cheng /* 4371da14cebeSEric Cheng * We can only display the factory MAC addresses of 4372da14cebeSEric Cheng * active data-links. 4373da14cebeSEric Cheng */ 4374da14cebeSEric Cheng die("-m not compatible with -P"); 4375e7801d59Ssowmini } 4376e7801d59Ssowmini 4377da14cebeSEric Cheng if (!o_arg || (o_arg && strcasecmp(fields_str, "all") == 0)) { 4378da14cebeSEric Cheng if (state.ls_mac) 4379da14cebeSEric Cheng fields_str = all_mac_fields; 4380da14cebeSEric Cheng else if (state.ls_hwgrp) 4381da14cebeSEric Cheng fields_str = all_hwgrp_fields; 4382da14cebeSEric Cheng else if (state.ls_flags & DLADM_OPT_ACTIVE) { 4383da14cebeSEric Cheng fields_str = all_active_fields; 4384da14cebeSEric Cheng } else { 4385da14cebeSEric Cheng fields_str = all_inactive_fields; 4386da14cebeSEric Cheng } 4387da14cebeSEric Cheng } 4388da14cebeSEric Cheng 4389da14cebeSEric Cheng if (state.ls_mac) { 4390da14cebeSEric Cheng pf = phys_m_fields; 4391da14cebeSEric Cheng } else if (state.ls_hwgrp) { 4392da14cebeSEric Cheng pf = phys_h_fields; 4393da14cebeSEric Cheng } else { 4394da14cebeSEric Cheng pf = phys_fields; 4395da14cebeSEric Cheng } 4396da14cebeSEric Cheng 43978002d411SSowmini Varadhan if (state.ls_parsable) 43988002d411SSowmini Varadhan ofmtflags |= OFMT_PARSABLE; 43998002d411SSowmini Varadhan oferr = ofmt_open(fields_str, pf, ofmtflags, 0, &ofmt); 44008002d411SSowmini Varadhan dladm_ofmt_check(oferr, state.ls_parsable, ofmt); 44018002d411SSowmini Varadhan state.ls_ofmt = ofmt; 4402e7801d59Ssowmini 4403d62bc4baSyz147064 if (linkid == DATALINK_ALL_LINKID) { 44044ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(show_phys, handle, &state, 4405d62bc4baSyz147064 DATALINK_CLASS_PHYS, DATALINK_ANY_MEDIATYPE, flags); 4406d62bc4baSyz147064 } else { 44074ac67f02SAnurag S. Maskey (void) show_phys(handle, linkid, &state); 4408d62bc4baSyz147064 if (state.ls_status != DLADM_STATUS_OK) { 4409d62bc4baSyz147064 die_dlerr(state.ls_status, 4410d62bc4baSyz147064 "failed to show physical link %s", argv[optind]); 4411d62bc4baSyz147064 } 4412d62bc4baSyz147064 } 44138002d411SSowmini Varadhan ofmt_close(ofmt); 4414d62bc4baSyz147064 } 4415d62bc4baSyz147064 4416d62bc4baSyz147064 static void 44178d5c46e6Sam223141 do_show_vlan(int argc, char *argv[], const char *use) 4418d62bc4baSyz147064 { 4419d62bc4baSyz147064 int option; 4420d62bc4baSyz147064 uint32_t flags = DLADM_OPT_ACTIVE; 4421d62bc4baSyz147064 boolean_t p_arg = B_FALSE; 4422d62bc4baSyz147064 datalink_id_t linkid = DATALINK_ALL_LINKID; 4423d62bc4baSyz147064 show_state_t state; 4424d62bc4baSyz147064 dladm_status_t status; 4425e7801d59Ssowmini boolean_t o_arg = B_FALSE; 4426e7801d59Ssowmini char *fields_str = NULL; 44278002d411SSowmini Varadhan ofmt_handle_t ofmt; 44288002d411SSowmini Varadhan ofmt_status_t oferr; 44298002d411SSowmini Varadhan uint_t ofmtflags = 0; 4430e7801d59Ssowmini 4431e7801d59Ssowmini bzero(&state, sizeof (state)); 4432d62bc4baSyz147064 4433d62bc4baSyz147064 opterr = 0; 4434e7801d59Ssowmini while ((option = getopt_long(argc, argv, ":pPo:", 4435d62bc4baSyz147064 show_lopts, NULL)) != -1) { 4436d62bc4baSyz147064 switch (option) { 4437d62bc4baSyz147064 case 'p': 4438d62bc4baSyz147064 if (p_arg) 4439d62bc4baSyz147064 die_optdup(option); 4440d62bc4baSyz147064 4441d62bc4baSyz147064 p_arg = B_TRUE; 4442d62bc4baSyz147064 break; 4443d62bc4baSyz147064 case 'P': 4444d62bc4baSyz147064 if (flags != DLADM_OPT_ACTIVE) 4445d62bc4baSyz147064 die_optdup(option); 4446d62bc4baSyz147064 4447d62bc4baSyz147064 flags = DLADM_OPT_PERSIST; 4448d62bc4baSyz147064 break; 4449e7801d59Ssowmini case 'o': 4450e7801d59Ssowmini o_arg = B_TRUE; 4451e7801d59Ssowmini fields_str = optarg; 4452e7801d59Ssowmini break; 4453d62bc4baSyz147064 default: 44548d5c46e6Sam223141 die_opterr(optopt, option, use); 4455d62bc4baSyz147064 break; 4456d62bc4baSyz147064 } 4457d62bc4baSyz147064 } 4458d62bc4baSyz147064 4459d62bc4baSyz147064 /* get link name (optional last argument) */ 4460d62bc4baSyz147064 if (optind == (argc-1)) { 44614ac67f02SAnurag S. Maskey if ((status = dladm_name2info(handle, argv[optind], &linkid, 44624ac67f02SAnurag S. Maskey NULL, NULL, NULL)) != DLADM_STATUS_OK) { 4463d62bc4baSyz147064 die_dlerr(status, "link %s is not valid", argv[optind]); 4464d62bc4baSyz147064 } 4465d62bc4baSyz147064 } else if (optind != argc) { 4466d62bc4baSyz147064 usage(); 4467d62bc4baSyz147064 } 4468d62bc4baSyz147064 44698002d411SSowmini Varadhan state.ls_parsable = p_arg; 4470d62bc4baSyz147064 state.ls_flags = flags; 4471d62bc4baSyz147064 state.ls_donefirst = B_FALSE; 4472d62bc4baSyz147064 4473e7801d59Ssowmini if (!o_arg || (o_arg && strcasecmp(fields_str, "all") == 0)) 44748002d411SSowmini Varadhan fields_str = NULL; 4475e7801d59Ssowmini 44768002d411SSowmini Varadhan if (state.ls_parsable) 44778002d411SSowmini Varadhan ofmtflags |= OFMT_PARSABLE; 44788002d411SSowmini Varadhan oferr = ofmt_open(fields_str, vlan_fields, ofmtflags, 0, &ofmt); 44798002d411SSowmini Varadhan dladm_ofmt_check(oferr, state.ls_parsable, ofmt); 44808002d411SSowmini Varadhan state.ls_ofmt = ofmt; 4481e7801d59Ssowmini 4482d62bc4baSyz147064 if (linkid == DATALINK_ALL_LINKID) { 44834ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(show_vlan, handle, &state, 4484d62bc4baSyz147064 DATALINK_CLASS_VLAN, DATALINK_ANY_MEDIATYPE, flags); 4485d62bc4baSyz147064 } else { 44864ac67f02SAnurag S. Maskey (void) show_vlan(handle, linkid, &state); 4487d62bc4baSyz147064 if (state.ls_status != DLADM_STATUS_OK) { 4488d62bc4baSyz147064 die_dlerr(state.ls_status, "failed to show vlan %s", 4489d62bc4baSyz147064 argv[optind]); 4490d62bc4baSyz147064 } 4491d62bc4baSyz147064 } 44928002d411SSowmini Varadhan ofmt_close(ofmt); 4493d62bc4baSyz147064 } 4494d62bc4baSyz147064 4495d62bc4baSyz147064 static void 4496da14cebeSEric Cheng do_create_vnic(int argc, char *argv[], const char *use) 4497da14cebeSEric Cheng { 4498da14cebeSEric Cheng datalink_id_t linkid, dev_linkid; 4499da14cebeSEric Cheng char devname[MAXLINKNAMELEN]; 4500da14cebeSEric Cheng char name[MAXLINKNAMELEN]; 4501da14cebeSEric Cheng boolean_t l_arg = B_FALSE; 4502da14cebeSEric Cheng uint32_t flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST; 4503da14cebeSEric Cheng char *altroot = NULL; 4504b509e89bSRishi Srivatsavai int option; 4505da14cebeSEric Cheng char *endp = NULL; 4506da14cebeSEric Cheng dladm_status_t status; 45071cb875aeSCathy Zhou vnic_mac_addr_type_t mac_addr_type = VNIC_MAC_ADDR_TYPE_UNKNOWN; 45081cb875aeSCathy Zhou uchar_t *mac_addr = NULL; 45091cb875aeSCathy Zhou int mac_slot = -1; 45101cb875aeSCathy Zhou uint_t maclen = 0, mac_prefix_len = 0; 451163a6526dSMichael Lim char propstr[DLADM_STRSIZE]; 4512da14cebeSEric Cheng dladm_arg_list_t *proplist = NULL; 4513285e94f9SMichael Lim int vid = 0; 45141cb875aeSCathy Zhou int af = AF_UNSPEC; 45151cb875aeSCathy Zhou vrid_t vrid = VRRP_VRID_NONE; 4516da14cebeSEric Cheng 4517da14cebeSEric Cheng opterr = 0; 451863a6526dSMichael Lim bzero(propstr, DLADM_STRSIZE); 451963a6526dSMichael Lim 45201cb875aeSCathy Zhou while ((option = getopt_long(argc, argv, ":tfR:l:m:n:p:r:v:V:A:H", 4521da14cebeSEric Cheng vnic_lopts, NULL)) != -1) { 4522da14cebeSEric Cheng switch (option) { 4523da14cebeSEric Cheng case 't': 4524da14cebeSEric Cheng flags &= ~DLADM_OPT_PERSIST; 4525da14cebeSEric Cheng break; 4526da14cebeSEric Cheng case 'R': 4527da14cebeSEric Cheng altroot = optarg; 4528da14cebeSEric Cheng break; 4529da14cebeSEric Cheng case 'l': 4530da14cebeSEric Cheng if (strlcpy(devname, optarg, MAXLINKNAMELEN) >= 4531da14cebeSEric Cheng MAXLINKNAMELEN) 4532da14cebeSEric Cheng die("link name too long"); 4533da14cebeSEric Cheng l_arg = B_TRUE; 4534da14cebeSEric Cheng break; 4535da14cebeSEric Cheng case 'm': 45361cb875aeSCathy Zhou if (mac_addr_type != VNIC_MAC_ADDR_TYPE_UNKNOWN) 45371cb875aeSCathy Zhou die("cannot specify -m option twice"); 45381cb875aeSCathy Zhou 4539da14cebeSEric Cheng if (strcmp(optarg, "fixed") == 0) { 4540da14cebeSEric Cheng /* 4541da14cebeSEric Cheng * A fixed MAC address must be specified 4542da14cebeSEric Cheng * by its value, not by the keyword 'fixed'. 4543da14cebeSEric Cheng */ 4544da14cebeSEric Cheng die("'fixed' is not a valid MAC address"); 4545da14cebeSEric Cheng } 4546da14cebeSEric Cheng if (dladm_vnic_str2macaddrtype(optarg, 4547da14cebeSEric Cheng &mac_addr_type) != DLADM_STATUS_OK) { 4548da14cebeSEric Cheng mac_addr_type = VNIC_MAC_ADDR_TYPE_FIXED; 4549da14cebeSEric Cheng /* MAC address specified by value */ 45501cb875aeSCathy Zhou mac_addr = _link_aton(optarg, (int *)&maclen); 4551da14cebeSEric Cheng if (mac_addr == NULL) { 45521cb875aeSCathy Zhou if (maclen == (uint_t)-1) 4553da14cebeSEric Cheng die("invalid MAC address"); 4554da14cebeSEric Cheng else 4555da14cebeSEric Cheng die("out of memory"); 4556da14cebeSEric Cheng } 4557da14cebeSEric Cheng } 4558da14cebeSEric Cheng break; 4559da14cebeSEric Cheng case 'n': 4560da14cebeSEric Cheng errno = 0; 4561da14cebeSEric Cheng mac_slot = (int)strtol(optarg, &endp, 10); 4562da14cebeSEric Cheng if (errno != 0 || *endp != '\0') 4563da14cebeSEric Cheng die("invalid slot number"); 4564da14cebeSEric Cheng break; 4565da14cebeSEric Cheng case 'p': 456663a6526dSMichael Lim (void) strlcat(propstr, optarg, DLADM_STRSIZE); 456763a6526dSMichael Lim if (strlcat(propstr, ",", DLADM_STRSIZE) >= 456863a6526dSMichael Lim DLADM_STRSIZE) 456963a6526dSMichael Lim die("property list too long '%s'", propstr); 4570da14cebeSEric Cheng break; 4571da14cebeSEric Cheng case 'r': 45721cb875aeSCathy Zhou mac_addr = _link_aton(optarg, (int *)&mac_prefix_len); 4573da14cebeSEric Cheng if (mac_addr == NULL) { 45741cb875aeSCathy Zhou if (mac_prefix_len == (uint_t)-1) 4575da14cebeSEric Cheng die("invalid MAC address"); 4576da14cebeSEric Cheng else 4577da14cebeSEric Cheng die("out of memory"); 4578da14cebeSEric Cheng } 4579da14cebeSEric Cheng break; 45801cb875aeSCathy Zhou case 'V': 45811cb875aeSCathy Zhou if (!str2int(optarg, (int *)&vrid) || 45821cb875aeSCathy Zhou vrid < VRRP_VRID_MIN || vrid > VRRP_VRID_MAX) { 45831cb875aeSCathy Zhou die("invalid VRRP identifier '%s'", optarg); 45841cb875aeSCathy Zhou } 45851cb875aeSCathy Zhou 45861cb875aeSCathy Zhou break; 45871cb875aeSCathy Zhou case 'A': 45881cb875aeSCathy Zhou if (strcmp(optarg, "inet") == 0) 45891cb875aeSCathy Zhou af = AF_INET; 45901cb875aeSCathy Zhou else if (strcmp(optarg, "inet6") == 0) 45911cb875aeSCathy Zhou af = AF_INET6; 45921cb875aeSCathy Zhou else 45931cb875aeSCathy Zhou die("invalid address family '%s'", optarg); 45941cb875aeSCathy Zhou break; 4595da14cebeSEric Cheng case 'v': 4596285e94f9SMichael Lim if (vid != 0) 4597285e94f9SMichael Lim die_optdup(option); 4598285e94f9SMichael Lim 4599285e94f9SMichael Lim if (!str2int(optarg, &vid) || vid < 1 || vid > 4094) 4600285e94f9SMichael Lim die("invalid VLAN identifier '%s'", optarg); 4601285e94f9SMichael Lim 4602da14cebeSEric Cheng break; 4603da14cebeSEric Cheng case 'f': 4604da14cebeSEric Cheng flags |= DLADM_OPT_FORCE; 4605da14cebeSEric Cheng break; 4606da14cebeSEric Cheng default: 4607da14cebeSEric Cheng die_opterr(optopt, option, use); 4608da14cebeSEric Cheng } 4609da14cebeSEric Cheng } 4610da14cebeSEric Cheng 46111cb875aeSCathy Zhou if (mac_addr_type == VNIC_MAC_ADDR_TYPE_UNKNOWN) 46121cb875aeSCathy Zhou mac_addr_type = VNIC_MAC_ADDR_TYPE_AUTO; 46131cb875aeSCathy Zhou 4614da14cebeSEric Cheng /* 4615da14cebeSEric Cheng * 'f' - force, flag can be specified only with 'v' - vlan. 4616da14cebeSEric Cheng */ 4617da14cebeSEric Cheng if ((flags & DLADM_OPT_FORCE) != 0 && vid == 0) 4618da14cebeSEric Cheng die("-f option can only be used with -v"); 4619da14cebeSEric Cheng 4620da14cebeSEric Cheng if (mac_prefix_len != 0 && mac_addr_type != VNIC_MAC_ADDR_TYPE_RANDOM && 4621da14cebeSEric Cheng mac_addr_type != VNIC_MAC_ADDR_TYPE_FIXED) 4622da14cebeSEric Cheng usage(); 4623da14cebeSEric Cheng 46241cb875aeSCathy Zhou if (mac_addr_type == VNIC_MAC_ADDR_TYPE_VRID) { 46251cb875aeSCathy Zhou if (vrid == VRRP_VRID_NONE || af == AF_UNSPEC || 46261cb875aeSCathy Zhou mac_addr != NULL || maclen != 0 || mac_slot != -1 || 46271cb875aeSCathy Zhou mac_prefix_len != 0) { 46281cb875aeSCathy Zhou usage(); 46291cb875aeSCathy Zhou } 46301cb875aeSCathy Zhou } else if ((af != AF_UNSPEC || vrid != VRRP_VRID_NONE)) { 46311cb875aeSCathy Zhou usage(); 46321cb875aeSCathy Zhou } 46331cb875aeSCathy Zhou 4634da14cebeSEric Cheng /* check required options */ 4635da14cebeSEric Cheng if (!l_arg) 4636da14cebeSEric Cheng usage(); 4637da14cebeSEric Cheng 4638da14cebeSEric Cheng if (mac_slot != -1 && mac_addr_type != VNIC_MAC_ADDR_TYPE_FACTORY) 4639da14cebeSEric Cheng usage(); 4640da14cebeSEric Cheng 4641da14cebeSEric Cheng /* the VNIC id is the required operand */ 4642da14cebeSEric Cheng if (optind != (argc - 1)) 4643da14cebeSEric Cheng usage(); 4644da14cebeSEric Cheng 4645da14cebeSEric Cheng if (strlcpy(name, argv[optind], MAXLINKNAMELEN) >= MAXLINKNAMELEN) 4646da14cebeSEric Cheng die("link name too long '%s'", argv[optind]); 4647da14cebeSEric Cheng 4648da14cebeSEric Cheng if (!dladm_valid_linkname(name)) 4649da14cebeSEric Cheng die("invalid link name '%s'", argv[optind]); 4650da14cebeSEric Cheng 4651da14cebeSEric Cheng if (altroot != NULL) 4652da14cebeSEric Cheng altroot_cmd(altroot, argc, argv); 4653da14cebeSEric Cheng 46544ac67f02SAnurag S. Maskey if (dladm_name2info(handle, devname, &dev_linkid, NULL, NULL, NULL) != 4655da14cebeSEric Cheng DLADM_STATUS_OK) 4656da14cebeSEric Cheng die("invalid link name '%s'", devname); 4657da14cebeSEric Cheng 465863a6526dSMichael Lim if (dladm_parse_link_props(propstr, &proplist, B_FALSE) 465963a6526dSMichael Lim != DLADM_STATUS_OK) 466063a6526dSMichael Lim die("invalid vnic property"); 466163a6526dSMichael Lim 46624ac67f02SAnurag S. Maskey status = dladm_vnic_create(handle, name, dev_linkid, mac_addr_type, 46631cb875aeSCathy Zhou mac_addr, maclen, &mac_slot, mac_prefix_len, vid, vrid, af, 46641cb875aeSCathy Zhou &linkid, proplist, flags); 46656f40bf67SRishi Srivatsavai switch (status) { 46666f40bf67SRishi Srivatsavai case DLADM_STATUS_OK: 46676f40bf67SRishi Srivatsavai break; 46686f40bf67SRishi Srivatsavai 46696f40bf67SRishi Srivatsavai case DLADM_STATUS_LINKBUSY: 46706f40bf67SRishi Srivatsavai die("VLAN over '%s' may not use default_tag ID " 46716f40bf67SRishi Srivatsavai "(see dladm(1M))", devname); 46726f40bf67SRishi Srivatsavai break; 46736f40bf67SRishi Srivatsavai 46746f40bf67SRishi Srivatsavai default: 4675da14cebeSEric Cheng die_dlerr(status, "vnic creation over %s failed", devname); 46766f40bf67SRishi Srivatsavai } 4677da14cebeSEric Cheng 4678da14cebeSEric Cheng dladm_free_props(proplist); 46791cb875aeSCathy Zhou free(mac_addr); 4680da14cebeSEric Cheng } 4681da14cebeSEric Cheng 4682da14cebeSEric Cheng static void 4683da14cebeSEric Cheng do_etherstub_check(const char *name, datalink_id_t linkid, boolean_t etherstub, 4684da14cebeSEric Cheng uint32_t flags) 4685da14cebeSEric Cheng { 4686da14cebeSEric Cheng boolean_t is_etherstub; 4687da14cebeSEric Cheng dladm_vnic_attr_t attr; 4688da14cebeSEric Cheng 46894ac67f02SAnurag S. Maskey if (dladm_vnic_info(handle, linkid, &attr, flags) != DLADM_STATUS_OK) { 4690da14cebeSEric Cheng /* 4691da14cebeSEric Cheng * Let the delete continue anyway. 4692da14cebeSEric Cheng */ 4693da14cebeSEric Cheng return; 4694da14cebeSEric Cheng } 4695da14cebeSEric Cheng is_etherstub = (attr.va_link_id == DATALINK_INVALID_LINKID); 4696da14cebeSEric Cheng if (is_etherstub != etherstub) { 4697da14cebeSEric Cheng die("'%s' is not %s", name, 4698da14cebeSEric Cheng (is_etherstub ? "a vnic" : "an etherstub")); 4699da14cebeSEric Cheng } 4700da14cebeSEric Cheng } 4701da14cebeSEric Cheng 4702da14cebeSEric Cheng static void 4703da14cebeSEric Cheng do_delete_vnic_common(int argc, char *argv[], const char *use, 4704da14cebeSEric Cheng boolean_t etherstub) 4705da14cebeSEric Cheng { 4706b509e89bSRishi Srivatsavai int option; 4707da14cebeSEric Cheng uint32_t flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST; 4708da14cebeSEric Cheng datalink_id_t linkid; 4709da14cebeSEric Cheng char *altroot = NULL; 4710da14cebeSEric Cheng dladm_status_t status; 4711da14cebeSEric Cheng 4712da14cebeSEric Cheng opterr = 0; 4713da14cebeSEric Cheng while ((option = getopt_long(argc, argv, ":R:t", lopts, 4714da14cebeSEric Cheng NULL)) != -1) { 4715da14cebeSEric Cheng switch (option) { 4716da14cebeSEric Cheng case 't': 4717da14cebeSEric Cheng flags &= ~DLADM_OPT_PERSIST; 4718da14cebeSEric Cheng break; 4719da14cebeSEric Cheng case 'R': 4720da14cebeSEric Cheng altroot = optarg; 4721da14cebeSEric Cheng break; 4722da14cebeSEric Cheng default: 4723da14cebeSEric Cheng die_opterr(optopt, option, use); 4724da14cebeSEric Cheng } 4725da14cebeSEric Cheng } 4726da14cebeSEric Cheng 4727da14cebeSEric Cheng /* get vnic name (required last argument) */ 4728da14cebeSEric Cheng if (optind != (argc - 1)) 4729da14cebeSEric Cheng usage(); 4730da14cebeSEric Cheng 4731da14cebeSEric Cheng if (altroot != NULL) 4732da14cebeSEric Cheng altroot_cmd(altroot, argc, argv); 4733da14cebeSEric Cheng 47344ac67f02SAnurag S. Maskey status = dladm_name2info(handle, argv[optind], &linkid, NULL, NULL, 47354ac67f02SAnurag S. Maskey NULL); 4736da14cebeSEric Cheng if (status != DLADM_STATUS_OK) 4737da14cebeSEric Cheng die("invalid link name '%s'", argv[optind]); 4738da14cebeSEric Cheng 4739da14cebeSEric Cheng if ((flags & DLADM_OPT_ACTIVE) != 0) { 4740da14cebeSEric Cheng do_etherstub_check(argv[optind], linkid, etherstub, 4741da14cebeSEric Cheng DLADM_OPT_ACTIVE); 4742da14cebeSEric Cheng } 4743da14cebeSEric Cheng if ((flags & DLADM_OPT_PERSIST) != 0) { 4744da14cebeSEric Cheng do_etherstub_check(argv[optind], linkid, etherstub, 4745da14cebeSEric Cheng DLADM_OPT_PERSIST); 4746da14cebeSEric Cheng } 4747da14cebeSEric Cheng 47484ac67f02SAnurag S. Maskey status = dladm_vnic_delete(handle, linkid, flags); 4749da14cebeSEric Cheng if (status != DLADM_STATUS_OK) 4750da14cebeSEric Cheng die_dlerr(status, "vnic deletion failed"); 4751da14cebeSEric Cheng } 4752da14cebeSEric Cheng 4753da14cebeSEric Cheng static void 4754da14cebeSEric Cheng do_delete_vnic(int argc, char *argv[], const char *use) 4755da14cebeSEric Cheng { 4756da14cebeSEric Cheng do_delete_vnic_common(argc, argv, use, B_FALSE); 4757da14cebeSEric Cheng } 4758da14cebeSEric Cheng 4759da14cebeSEric Cheng /* ARGSUSED */ 4760da14cebeSEric Cheng static void 4761da14cebeSEric Cheng do_up_vnic_common(int argc, char *argv[], const char *use, boolean_t vlan) 4762da14cebeSEric Cheng { 4763da14cebeSEric Cheng datalink_id_t linkid = DATALINK_ALL_LINKID; 4764da14cebeSEric Cheng dladm_status_t status; 4765da14cebeSEric Cheng char *type; 4766da14cebeSEric Cheng 4767da14cebeSEric Cheng type = vlan ? "vlan" : "vnic"; 4768da14cebeSEric Cheng 4769da14cebeSEric Cheng /* 4770da14cebeSEric Cheng * get the id or the name of the vnic/vlan (optional last argument) 4771da14cebeSEric Cheng */ 4772da14cebeSEric Cheng if (argc == 2) { 47734ac67f02SAnurag S. Maskey status = dladm_name2info(handle, argv[1], &linkid, NULL, NULL, 47744ac67f02SAnurag S. Maskey NULL); 4775da14cebeSEric Cheng if (status != DLADM_STATUS_OK) 4776da14cebeSEric Cheng goto done; 4777da14cebeSEric Cheng 4778da14cebeSEric Cheng } else if (argc > 2) { 4779da14cebeSEric Cheng usage(); 4780da14cebeSEric Cheng } 4781da14cebeSEric Cheng 4782da14cebeSEric Cheng if (vlan) 47834ac67f02SAnurag S. Maskey status = dladm_vlan_up(handle, linkid); 4784da14cebeSEric Cheng else 47854ac67f02SAnurag S. Maskey status = dladm_vnic_up(handle, linkid, 0); 4786da14cebeSEric Cheng 4787da14cebeSEric Cheng done: 4788da14cebeSEric Cheng if (status != DLADM_STATUS_OK) { 4789da14cebeSEric Cheng if (argc == 2) { 4790da14cebeSEric Cheng die_dlerr(status, 4791da14cebeSEric Cheng "could not bring up %s '%s'", type, argv[1]); 4792da14cebeSEric Cheng } else { 4793da14cebeSEric Cheng die_dlerr(status, "could not bring %ss up", type); 4794da14cebeSEric Cheng } 4795da14cebeSEric Cheng } 4796da14cebeSEric Cheng } 4797da14cebeSEric Cheng 4798da14cebeSEric Cheng static void 4799da14cebeSEric Cheng do_up_vnic(int argc, char *argv[], const char *use) 4800da14cebeSEric Cheng { 4801da14cebeSEric Cheng do_up_vnic_common(argc, argv, use, B_FALSE); 4802da14cebeSEric Cheng } 4803da14cebeSEric Cheng 4804da14cebeSEric Cheng static void 4805da14cebeSEric Cheng dump_vnics_head(const char *dev) 4806da14cebeSEric Cheng { 4807da14cebeSEric Cheng if (strlen(dev)) 4808da14cebeSEric Cheng (void) printf("%s", dev); 4809da14cebeSEric Cheng 4810da14cebeSEric Cheng (void) printf("\tipackets rbytes opackets obytes "); 4811da14cebeSEric Cheng 4812da14cebeSEric Cheng if (strlen(dev)) 4813da14cebeSEric Cheng (void) printf("%%ipkts %%opkts\n"); 4814da14cebeSEric Cheng else 4815da14cebeSEric Cheng (void) printf("\n"); 4816da14cebeSEric Cheng } 4817da14cebeSEric Cheng 4818da14cebeSEric Cheng static void 4819da14cebeSEric Cheng dump_vnic_stat(const char *name, datalink_id_t vnic_id, 4820da14cebeSEric Cheng show_vnic_state_t *state, pktsum_t *vnic_stats, pktsum_t *tot_stats) 4821da14cebeSEric Cheng { 4822da14cebeSEric Cheng pktsum_t diff_stats; 4823da14cebeSEric Cheng pktsum_t *old_stats = &state->vs_prevstats[vnic_id]; 4824da14cebeSEric Cheng 4825da14cebeSEric Cheng dladm_stats_diff(&diff_stats, vnic_stats, old_stats); 4826da14cebeSEric Cheng 4827da14cebeSEric Cheng (void) printf("%s", name); 4828da14cebeSEric Cheng 4829da14cebeSEric Cheng (void) printf("\t%-10llu", diff_stats.ipackets); 4830da14cebeSEric Cheng (void) printf("%-12llu", diff_stats.rbytes); 4831da14cebeSEric Cheng (void) printf("%-10llu", diff_stats.opackets); 4832da14cebeSEric Cheng (void) printf("%-12llu", diff_stats.obytes); 4833da14cebeSEric Cheng 4834da14cebeSEric Cheng if (tot_stats) { 4835da14cebeSEric Cheng if (tot_stats->ipackets == 0) { 4836da14cebeSEric Cheng (void) printf("\t-"); 4837da14cebeSEric Cheng } else { 4838da14cebeSEric Cheng (void) printf("\t%-6.1f", (double)diff_stats.ipackets/ 4839da14cebeSEric Cheng (double)tot_stats->ipackets * 100); 4840da14cebeSEric Cheng } 4841da14cebeSEric Cheng if (tot_stats->opackets == 0) { 4842da14cebeSEric Cheng (void) printf("\t-"); 4843da14cebeSEric Cheng } else { 4844da14cebeSEric Cheng (void) printf("\t%-6.1f", (double)diff_stats.opackets/ 4845da14cebeSEric Cheng (double)tot_stats->opackets * 100); 4846da14cebeSEric Cheng } 4847da14cebeSEric Cheng } 4848da14cebeSEric Cheng (void) printf("\n"); 4849da14cebeSEric Cheng 4850da14cebeSEric Cheng *old_stats = *vnic_stats; 4851da14cebeSEric Cheng } 4852da14cebeSEric Cheng 4853da14cebeSEric Cheng /* 4854da14cebeSEric Cheng * Called from the walker dladm_vnic_walk_sys() for each vnic to display 4855da14cebeSEric Cheng * vnic information or statistics. 4856da14cebeSEric Cheng */ 4857da14cebeSEric Cheng static dladm_status_t 4858da14cebeSEric Cheng print_vnic(show_vnic_state_t *state, datalink_id_t linkid) 4859da14cebeSEric Cheng { 4860da14cebeSEric Cheng dladm_vnic_attr_t attr, *vnic = &attr; 4861da14cebeSEric Cheng dladm_status_t status; 4862da14cebeSEric Cheng boolean_t is_etherstub; 4863da14cebeSEric Cheng char devname[MAXLINKNAMELEN]; 4864da14cebeSEric Cheng char vnic_name[MAXLINKNAMELEN]; 4865da14cebeSEric Cheng char mstr[MAXMACADDRLEN * 3]; 4866da14cebeSEric Cheng vnic_fields_buf_t vbuf; 4867da14cebeSEric Cheng 48684ac67f02SAnurag S. Maskey if ((status = dladm_vnic_info(handle, linkid, vnic, state->vs_flags)) != 4869da14cebeSEric Cheng DLADM_STATUS_OK) 4870da14cebeSEric Cheng return (status); 4871da14cebeSEric Cheng 4872da14cebeSEric Cheng is_etherstub = (vnic->va_link_id == DATALINK_INVALID_LINKID); 4873da14cebeSEric Cheng if (state->vs_etherstub != is_etherstub) { 4874da14cebeSEric Cheng /* 4875da14cebeSEric Cheng * Want all etherstub but it's not one, or want 4876da14cebeSEric Cheng * non-etherstub and it's one. 4877da14cebeSEric Cheng */ 4878da14cebeSEric Cheng return (DLADM_STATUS_OK); 4879da14cebeSEric Cheng } 4880da14cebeSEric Cheng 4881da14cebeSEric Cheng if (state->vs_link_id != DATALINK_ALL_LINKID) { 4882da14cebeSEric Cheng if (state->vs_link_id != vnic->va_link_id) 4883da14cebeSEric Cheng return (DLADM_STATUS_OK); 4884da14cebeSEric Cheng } 4885da14cebeSEric Cheng 48864ac67f02SAnurag S. Maskey if (dladm_datalink_id2info(handle, linkid, NULL, NULL, 4887da14cebeSEric Cheng NULL, vnic_name, sizeof (vnic_name)) != DLADM_STATUS_OK) 4888da14cebeSEric Cheng return (DLADM_STATUS_BADARG); 4889da14cebeSEric Cheng 4890da14cebeSEric Cheng bzero(devname, sizeof (devname)); 4891da14cebeSEric Cheng if (!is_etherstub && 48924ac67f02SAnurag S. Maskey dladm_datalink_id2info(handle, vnic->va_link_id, NULL, NULL, 4893da14cebeSEric Cheng NULL, devname, sizeof (devname)) != DLADM_STATUS_OK) 48942b24ab6bSSebastien Roy (void) sprintf(devname, "?"); 4895da14cebeSEric Cheng 4896da14cebeSEric Cheng state->vs_found = B_TRUE; 4897da14cebeSEric Cheng if (state->vs_stats) { 4898da14cebeSEric Cheng /* print vnic statistics */ 4899da14cebeSEric Cheng pktsum_t vnic_stats; 4900da14cebeSEric Cheng 4901da14cebeSEric Cheng if (state->vs_firstonly) { 4902da14cebeSEric Cheng if (state->vs_donefirst) 4903da14cebeSEric Cheng return (0); 4904da14cebeSEric Cheng state->vs_donefirst = B_TRUE; 4905da14cebeSEric Cheng } 4906da14cebeSEric Cheng 4907da14cebeSEric Cheng if (!state->vs_printstats) { 4908da14cebeSEric Cheng /* 4909da14cebeSEric Cheng * get vnic statistics and add to the sum for the 4910da14cebeSEric Cheng * named device. 4911da14cebeSEric Cheng */ 4912da14cebeSEric Cheng get_link_stats(vnic_name, &vnic_stats); 4913da14cebeSEric Cheng dladm_stats_total(&state->vs_totalstats, &vnic_stats, 4914da14cebeSEric Cheng &state->vs_prevstats[vnic->va_vnic_id]); 4915da14cebeSEric Cheng } else { 4916da14cebeSEric Cheng /* get and print vnic statistics */ 4917da14cebeSEric Cheng get_link_stats(vnic_name, &vnic_stats); 4918da14cebeSEric Cheng dump_vnic_stat(vnic_name, linkid, state, &vnic_stats, 4919da14cebeSEric Cheng &state->vs_totalstats); 4920da14cebeSEric Cheng } 4921da14cebeSEric Cheng return (DLADM_STATUS_OK); 4922da14cebeSEric Cheng } else { 4923da14cebeSEric Cheng (void) snprintf(vbuf.vnic_link, sizeof (vbuf.vnic_link), 4924da14cebeSEric Cheng "%s", vnic_name); 4925da14cebeSEric Cheng 4926da14cebeSEric Cheng if (!is_etherstub) { 4927da14cebeSEric Cheng 4928da14cebeSEric Cheng (void) snprintf(vbuf.vnic_over, sizeof (vbuf.vnic_over), 4929da14cebeSEric Cheng "%s", devname); 4930da14cebeSEric Cheng (void) snprintf(vbuf.vnic_speed, 4931da14cebeSEric Cheng sizeof (vbuf.vnic_speed), "%u", 4932da14cebeSEric Cheng (uint_t)((get_ifspeed(vnic_name, B_TRUE)) 4933da14cebeSEric Cheng / 1000000ull)); 4934da14cebeSEric Cheng 4935da14cebeSEric Cheng switch (vnic->va_mac_addr_type) { 4936da14cebeSEric Cheng case VNIC_MAC_ADDR_TYPE_FIXED: 4937da14cebeSEric Cheng case VNIC_MAC_ADDR_TYPE_PRIMARY: 4938da14cebeSEric Cheng (void) snprintf(vbuf.vnic_macaddrtype, 4939da14cebeSEric Cheng sizeof (vbuf.vnic_macaddrtype), 4940da14cebeSEric Cheng gettext("fixed")); 4941da14cebeSEric Cheng break; 4942da14cebeSEric Cheng case VNIC_MAC_ADDR_TYPE_RANDOM: 4943da14cebeSEric Cheng (void) snprintf(vbuf.vnic_macaddrtype, 4944da14cebeSEric Cheng sizeof (vbuf.vnic_macaddrtype), 4945da14cebeSEric Cheng gettext("random")); 4946da14cebeSEric Cheng break; 4947da14cebeSEric Cheng case VNIC_MAC_ADDR_TYPE_FACTORY: 4948da14cebeSEric Cheng (void) snprintf(vbuf.vnic_macaddrtype, 4949da14cebeSEric Cheng sizeof (vbuf.vnic_macaddrtype), 4950da14cebeSEric Cheng gettext("factory, slot %d"), 4951da14cebeSEric Cheng vnic->va_mac_slot); 4952da14cebeSEric Cheng break; 49531cb875aeSCathy Zhou case VNIC_MAC_ADDR_TYPE_VRID: 49541cb875aeSCathy Zhou (void) snprintf(vbuf.vnic_macaddrtype, 49551cb875aeSCathy Zhou sizeof (vbuf.vnic_macaddrtype), 49561cb875aeSCathy Zhou gettext("vrrp, %d/%s"), 49571cb875aeSCathy Zhou vnic->va_vrid, vnic->va_af == AF_INET ? 49581cb875aeSCathy Zhou "inet" : "inet6"); 49591cb875aeSCathy Zhou break; 4960da14cebeSEric Cheng } 4961da14cebeSEric Cheng 4962da14cebeSEric Cheng if (strlen(vbuf.vnic_macaddrtype) > 0) { 4963da14cebeSEric Cheng (void) snprintf(vbuf.vnic_macaddr, 4964da14cebeSEric Cheng sizeof (vbuf.vnic_macaddr), "%s", 4965da14cebeSEric Cheng dladm_aggr_macaddr2str(vnic->va_mac_addr, 4966da14cebeSEric Cheng mstr)); 4967da14cebeSEric Cheng } 4968da14cebeSEric Cheng 4969da14cebeSEric Cheng (void) snprintf(vbuf.vnic_vid, sizeof (vbuf.vnic_vid), 4970da14cebeSEric Cheng "%d", vnic->va_vid); 4971da14cebeSEric Cheng } 4972da14cebeSEric Cheng 49738002d411SSowmini Varadhan ofmt_print(state->vs_ofmt, &vbuf); 4974da14cebeSEric Cheng 4975da14cebeSEric Cheng return (DLADM_STATUS_OK); 4976da14cebeSEric Cheng } 4977da14cebeSEric Cheng } 4978da14cebeSEric Cheng 49794ac67f02SAnurag S. Maskey /* ARGSUSED */ 4980da14cebeSEric Cheng static int 49814ac67f02SAnurag S. Maskey show_vnic(dladm_handle_t dh, datalink_id_t linkid, void *arg) 4982da14cebeSEric Cheng { 4983da14cebeSEric Cheng show_vnic_state_t *state = arg; 4984da14cebeSEric Cheng 4985da14cebeSEric Cheng state->vs_status = print_vnic(state, linkid); 4986da14cebeSEric Cheng return (DLADM_WALK_CONTINUE); 4987da14cebeSEric Cheng } 4988da14cebeSEric Cheng 4989da14cebeSEric Cheng static void 4990da14cebeSEric Cheng do_show_vnic_common(int argc, char *argv[], const char *use, 4991da14cebeSEric Cheng boolean_t etherstub) 4992da14cebeSEric Cheng { 4993da14cebeSEric Cheng int option; 4994da14cebeSEric Cheng boolean_t s_arg = B_FALSE; 4995da14cebeSEric Cheng boolean_t i_arg = B_FALSE; 4996da14cebeSEric Cheng boolean_t l_arg = B_FALSE; 4997da14cebeSEric Cheng uint32_t interval = 0, flags = DLADM_OPT_ACTIVE; 4998da14cebeSEric Cheng datalink_id_t linkid = DATALINK_ALL_LINKID; 4999da14cebeSEric Cheng datalink_id_t dev_linkid = DATALINK_ALL_LINKID; 5000da14cebeSEric Cheng show_vnic_state_t state; 5001da14cebeSEric Cheng dladm_status_t status; 5002da14cebeSEric Cheng boolean_t o_arg = B_FALSE; 5003da14cebeSEric Cheng char *fields_str = NULL; 50042b24ab6bSSebastien Roy const ofmt_field_t *pf; 50058002d411SSowmini Varadhan char *all_e_fields = "link"; 50068002d411SSowmini Varadhan ofmt_handle_t ofmt; 50078002d411SSowmini Varadhan ofmt_status_t oferr; 50088002d411SSowmini Varadhan uint_t ofmtflags = 0; 5009da14cebeSEric Cheng 5010da14cebeSEric Cheng bzero(&state, sizeof (state)); 5011da14cebeSEric Cheng opterr = 0; 5012da14cebeSEric Cheng while ((option = getopt_long(argc, argv, ":pPl:si:o:", lopts, 5013da14cebeSEric Cheng NULL)) != -1) { 5014da14cebeSEric Cheng switch (option) { 5015da14cebeSEric Cheng case 'p': 50168002d411SSowmini Varadhan state.vs_parsable = B_TRUE; 5017da14cebeSEric Cheng break; 5018da14cebeSEric Cheng case 'P': 5019da14cebeSEric Cheng flags = DLADM_OPT_PERSIST; 5020da14cebeSEric Cheng break; 5021da14cebeSEric Cheng case 'l': 5022da14cebeSEric Cheng if (etherstub) 5023da14cebeSEric Cheng die("option not supported for this command"); 5024da14cebeSEric Cheng 5025da14cebeSEric Cheng if (strlcpy(state.vs_link, optarg, MAXLINKNAMELEN) >= 5026da14cebeSEric Cheng MAXLINKNAMELEN) 5027da14cebeSEric Cheng die("link name too long"); 5028da14cebeSEric Cheng 5029da14cebeSEric Cheng l_arg = B_TRUE; 5030da14cebeSEric Cheng break; 5031da14cebeSEric Cheng case 's': 5032da14cebeSEric Cheng if (s_arg) { 5033da14cebeSEric Cheng die("the option -s cannot be specified " 5034da14cebeSEric Cheng "more than once"); 5035da14cebeSEric Cheng } 5036da14cebeSEric Cheng s_arg = B_TRUE; 5037da14cebeSEric Cheng break; 5038da14cebeSEric Cheng case 'i': 5039da14cebeSEric Cheng if (i_arg) { 5040da14cebeSEric Cheng die("the option -i cannot be specified " 5041da14cebeSEric Cheng "more than once"); 5042da14cebeSEric Cheng } 5043da14cebeSEric Cheng i_arg = B_TRUE; 504463a6526dSMichael Lim if (!dladm_str2interval(optarg, &interval)) 5045da14cebeSEric Cheng die("invalid interval value '%s'", optarg); 5046da14cebeSEric Cheng break; 5047da14cebeSEric Cheng case 'o': 5048da14cebeSEric Cheng o_arg = B_TRUE; 5049da14cebeSEric Cheng fields_str = optarg; 5050da14cebeSEric Cheng break; 5051da14cebeSEric Cheng default: 5052da14cebeSEric Cheng die_opterr(optopt, option, use); 5053da14cebeSEric Cheng } 5054da14cebeSEric Cheng } 5055da14cebeSEric Cheng 5056da14cebeSEric Cheng if (i_arg && !s_arg) 5057da14cebeSEric Cheng die("the option -i can be used only with -s"); 5058da14cebeSEric Cheng 5059da14cebeSEric Cheng /* get vnic ID (optional last argument) */ 5060da14cebeSEric Cheng if (optind == (argc - 1)) { 50614ac67f02SAnurag S. Maskey status = dladm_name2info(handle, argv[optind], &linkid, NULL, 5062da14cebeSEric Cheng NULL, NULL); 5063da14cebeSEric Cheng if (status != DLADM_STATUS_OK) { 5064da14cebeSEric Cheng die_dlerr(status, "invalid vnic name '%s'", 5065da14cebeSEric Cheng argv[optind]); 5066da14cebeSEric Cheng } 5067da14cebeSEric Cheng (void) strlcpy(state.vs_vnic, argv[optind], MAXLINKNAMELEN); 5068da14cebeSEric Cheng } else if (optind != argc) { 5069da14cebeSEric Cheng usage(); 5070da14cebeSEric Cheng } 5071da14cebeSEric Cheng 5072da14cebeSEric Cheng if (l_arg) { 50734ac67f02SAnurag S. Maskey status = dladm_name2info(handle, state.vs_link, &dev_linkid, 50744ac67f02SAnurag S. Maskey NULL, NULL, NULL); 5075da14cebeSEric Cheng if (status != DLADM_STATUS_OK) { 5076da14cebeSEric Cheng die_dlerr(status, "invalid link name '%s'", 5077da14cebeSEric Cheng state.vs_link); 5078da14cebeSEric Cheng } 5079da14cebeSEric Cheng } 5080da14cebeSEric Cheng 5081da14cebeSEric Cheng state.vs_vnic_id = linkid; 5082da14cebeSEric Cheng state.vs_link_id = dev_linkid; 5083da14cebeSEric Cheng state.vs_etherstub = etherstub; 5084da14cebeSEric Cheng state.vs_found = B_FALSE; 5085da14cebeSEric Cheng state.vs_flags = flags; 5086da14cebeSEric Cheng 5087da14cebeSEric Cheng if (!o_arg || (o_arg && strcasecmp(fields_str, "all") == 0)) { 5088da14cebeSEric Cheng if (etherstub) 5089da14cebeSEric Cheng fields_str = all_e_fields; 5090da14cebeSEric Cheng } 5091da14cebeSEric Cheng pf = vnic_fields; 5092da14cebeSEric Cheng 50938002d411SSowmini Varadhan if (state.vs_parsable) 50948002d411SSowmini Varadhan ofmtflags |= OFMT_PARSABLE; 50958002d411SSowmini Varadhan oferr = ofmt_open(fields_str, pf, ofmtflags, 0, &ofmt); 50968002d411SSowmini Varadhan dladm_ofmt_check(oferr, state.vs_parsable, ofmt); 50978002d411SSowmini Varadhan state.vs_ofmt = ofmt; 5098da14cebeSEric Cheng 5099da14cebeSEric Cheng if (s_arg) { 5100da14cebeSEric Cheng /* Display vnic statistics */ 5101da14cebeSEric Cheng vnic_stats(&state, interval); 51028002d411SSowmini Varadhan ofmt_close(ofmt); 5103da14cebeSEric Cheng return; 5104da14cebeSEric Cheng } 5105da14cebeSEric Cheng 5106da14cebeSEric Cheng /* Display vnic information */ 5107da14cebeSEric Cheng state.vs_donefirst = B_FALSE; 5108da14cebeSEric Cheng 5109da14cebeSEric Cheng if (linkid == DATALINK_ALL_LINKID) { 51104ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(show_vnic, handle, &state, 5111da14cebeSEric Cheng DATALINK_CLASS_VNIC | DATALINK_CLASS_ETHERSTUB, 5112c3affd82SMichael Lim DATALINK_ANY_MEDIATYPE, flags); 5113da14cebeSEric Cheng } else { 51144ac67f02SAnurag S. Maskey (void) show_vnic(handle, linkid, &state); 5115da14cebeSEric Cheng if (state.vs_status != DLADM_STATUS_OK) { 51168002d411SSowmini Varadhan ofmt_close(ofmt); 5117da14cebeSEric Cheng die_dlerr(state.vs_status, "failed to show vnic '%s'", 5118da14cebeSEric Cheng state.vs_vnic); 5119da14cebeSEric Cheng } 5120da14cebeSEric Cheng } 51218002d411SSowmini Varadhan ofmt_close(ofmt); 5122da14cebeSEric Cheng } 5123da14cebeSEric Cheng 5124da14cebeSEric Cheng static void 5125da14cebeSEric Cheng do_show_vnic(int argc, char *argv[], const char *use) 5126da14cebeSEric Cheng { 5127da14cebeSEric Cheng do_show_vnic_common(argc, argv, use, B_FALSE); 5128da14cebeSEric Cheng } 5129da14cebeSEric Cheng 5130da14cebeSEric Cheng static void 5131da14cebeSEric Cheng do_create_etherstub(int argc, char *argv[], const char *use) 5132da14cebeSEric Cheng { 5133da14cebeSEric Cheng uint32_t flags; 5134da14cebeSEric Cheng char *altroot = NULL; 5135b509e89bSRishi Srivatsavai int option; 5136da14cebeSEric Cheng dladm_status_t status; 5137da14cebeSEric Cheng char name[MAXLINKNAMELEN]; 5138da14cebeSEric Cheng uchar_t mac_addr[ETHERADDRL]; 5139da14cebeSEric Cheng 5140da14cebeSEric Cheng name[0] = '\0'; 5141da14cebeSEric Cheng bzero(mac_addr, sizeof (mac_addr)); 5142da14cebeSEric Cheng flags = DLADM_OPT_ANCHOR | DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST; 5143da14cebeSEric Cheng 5144da14cebeSEric Cheng opterr = 0; 5145da14cebeSEric Cheng while ((option = getopt_long(argc, argv, "tR:", 5146da14cebeSEric Cheng etherstub_lopts, NULL)) != -1) { 5147da14cebeSEric Cheng switch (option) { 5148da14cebeSEric Cheng case 't': 5149da14cebeSEric Cheng flags &= ~DLADM_OPT_PERSIST; 5150da14cebeSEric Cheng break; 5151da14cebeSEric Cheng case 'R': 5152da14cebeSEric Cheng altroot = optarg; 5153da14cebeSEric Cheng break; 5154da14cebeSEric Cheng default: 5155da14cebeSEric Cheng die_opterr(optopt, option, use); 5156da14cebeSEric Cheng } 5157da14cebeSEric Cheng } 5158da14cebeSEric Cheng 5159da14cebeSEric Cheng /* the etherstub id is the required operand */ 5160da14cebeSEric Cheng if (optind != (argc - 1)) 5161da14cebeSEric Cheng usage(); 5162da14cebeSEric Cheng 5163da14cebeSEric Cheng if (strlcpy(name, argv[optind], MAXLINKNAMELEN) >= MAXLINKNAMELEN) 5164da14cebeSEric Cheng die("link name too long '%s'", argv[optind]); 5165da14cebeSEric Cheng 5166da14cebeSEric Cheng if (!dladm_valid_linkname(name)) 5167da14cebeSEric Cheng die("invalid link name '%s'", argv[optind]); 5168da14cebeSEric Cheng 5169da14cebeSEric Cheng if (altroot != NULL) 5170da14cebeSEric Cheng altroot_cmd(altroot, argc, argv); 5171da14cebeSEric Cheng 51724ac67f02SAnurag S. Maskey status = dladm_vnic_create(handle, name, DATALINK_INVALID_LINKID, 51731cb875aeSCathy Zhou VNIC_MAC_ADDR_TYPE_AUTO, mac_addr, ETHERADDRL, NULL, 0, 0, 51741cb875aeSCathy Zhou VRRP_VRID_NONE, AF_UNSPEC, NULL, NULL, flags); 5175da14cebeSEric Cheng if (status != DLADM_STATUS_OK) 5176da14cebeSEric Cheng die_dlerr(status, "etherstub creation failed"); 5177da14cebeSEric Cheng } 5178da14cebeSEric Cheng 5179da14cebeSEric Cheng static void 5180da14cebeSEric Cheng do_delete_etherstub(int argc, char *argv[], const char *use) 5181da14cebeSEric Cheng { 5182da14cebeSEric Cheng do_delete_vnic_common(argc, argv, use, B_TRUE); 5183da14cebeSEric Cheng } 5184da14cebeSEric Cheng 5185da14cebeSEric Cheng /* ARGSUSED */ 5186da14cebeSEric Cheng static void 5187da14cebeSEric Cheng do_show_etherstub(int argc, char *argv[], const char *use) 5188da14cebeSEric Cheng { 5189da14cebeSEric Cheng do_show_vnic_common(argc, argv, use, B_TRUE); 5190da14cebeSEric Cheng } 5191da14cebeSEric Cheng 5192b509e89bSRishi Srivatsavai /* ARGSUSED */ 5193b509e89bSRishi Srivatsavai static void 5194b509e89bSRishi Srivatsavai do_up_simnet(int argc, char *argv[], const char *use) 5195b509e89bSRishi Srivatsavai { 5196b509e89bSRishi Srivatsavai (void) dladm_simnet_up(handle, DATALINK_ALL_LINKID, 0); 5197b509e89bSRishi Srivatsavai } 5198b509e89bSRishi Srivatsavai 5199b509e89bSRishi Srivatsavai static void 5200b509e89bSRishi Srivatsavai do_create_simnet(int argc, char *argv[], const char *use) 5201b509e89bSRishi Srivatsavai { 5202b509e89bSRishi Srivatsavai uint32_t flags; 5203b509e89bSRishi Srivatsavai char *altroot = NULL; 5204b509e89bSRishi Srivatsavai char *media = NULL; 5205b509e89bSRishi Srivatsavai uint32_t mtype = DL_ETHER; 5206b509e89bSRishi Srivatsavai int option; 5207b509e89bSRishi Srivatsavai dladm_status_t status; 5208b509e89bSRishi Srivatsavai char name[MAXLINKNAMELEN]; 5209b509e89bSRishi Srivatsavai 5210b509e89bSRishi Srivatsavai name[0] = '\0'; 5211b509e89bSRishi Srivatsavai flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST; 5212b509e89bSRishi Srivatsavai 5213b509e89bSRishi Srivatsavai opterr = 0; 5214b509e89bSRishi Srivatsavai while ((option = getopt_long(argc, argv, ":tR:m:", 5215b509e89bSRishi Srivatsavai simnet_lopts, NULL)) != -1) { 5216b509e89bSRishi Srivatsavai switch (option) { 5217b509e89bSRishi Srivatsavai case 't': 5218b509e89bSRishi Srivatsavai flags &= ~DLADM_OPT_PERSIST; 5219b509e89bSRishi Srivatsavai break; 5220b509e89bSRishi Srivatsavai case 'R': 5221b509e89bSRishi Srivatsavai altroot = optarg; 5222b509e89bSRishi Srivatsavai break; 5223b509e89bSRishi Srivatsavai case 'm': 5224b509e89bSRishi Srivatsavai media = optarg; 5225b509e89bSRishi Srivatsavai break; 5226b509e89bSRishi Srivatsavai default: 5227b509e89bSRishi Srivatsavai die_opterr(optopt, option, use); 5228b509e89bSRishi Srivatsavai } 5229b509e89bSRishi Srivatsavai } 5230b509e89bSRishi Srivatsavai 5231b509e89bSRishi Srivatsavai /* the simnet id is the required operand */ 5232b509e89bSRishi Srivatsavai if (optind != (argc - 1)) 5233b509e89bSRishi Srivatsavai usage(); 5234b509e89bSRishi Srivatsavai 5235b509e89bSRishi Srivatsavai if (strlcpy(name, argv[optind], MAXLINKNAMELEN) >= MAXLINKNAMELEN) 5236b509e89bSRishi Srivatsavai die("link name too long '%s'", argv[optind]); 5237b509e89bSRishi Srivatsavai 5238b509e89bSRishi Srivatsavai if (!dladm_valid_linkname(name)) 5239b509e89bSRishi Srivatsavai die("invalid link name '%s'", name); 5240b509e89bSRishi Srivatsavai 5241b509e89bSRishi Srivatsavai if (media != NULL) { 5242b509e89bSRishi Srivatsavai mtype = dladm_str2media(media); 5243b509e89bSRishi Srivatsavai if (mtype != DL_ETHER && mtype != DL_WIFI) 5244b509e89bSRishi Srivatsavai die("media type '%s' is not supported", media); 5245b509e89bSRishi Srivatsavai } 5246b509e89bSRishi Srivatsavai 5247b509e89bSRishi Srivatsavai if (altroot != NULL) 5248b509e89bSRishi Srivatsavai altroot_cmd(altroot, argc, argv); 5249b509e89bSRishi Srivatsavai 5250b509e89bSRishi Srivatsavai status = dladm_simnet_create(handle, name, mtype, flags); 5251b509e89bSRishi Srivatsavai if (status != DLADM_STATUS_OK) 5252b509e89bSRishi Srivatsavai die_dlerr(status, "simnet creation failed"); 5253b509e89bSRishi Srivatsavai } 5254b509e89bSRishi Srivatsavai 5255b509e89bSRishi Srivatsavai static void 5256b509e89bSRishi Srivatsavai do_delete_simnet(int argc, char *argv[], const char *use) 5257b509e89bSRishi Srivatsavai { 5258b509e89bSRishi Srivatsavai int option; 5259b509e89bSRishi Srivatsavai uint32_t flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST; 5260b509e89bSRishi Srivatsavai datalink_id_t linkid; 5261b509e89bSRishi Srivatsavai char *altroot = NULL; 5262b509e89bSRishi Srivatsavai dladm_status_t status; 5263b509e89bSRishi Srivatsavai dladm_simnet_attr_t slinfo; 5264b509e89bSRishi Srivatsavai 5265b509e89bSRishi Srivatsavai opterr = 0; 5266b509e89bSRishi Srivatsavai while ((option = getopt_long(argc, argv, ":tR:", simnet_lopts, 5267b509e89bSRishi Srivatsavai NULL)) != -1) { 5268b509e89bSRishi Srivatsavai switch (option) { 5269b509e89bSRishi Srivatsavai case 't': 5270b509e89bSRishi Srivatsavai flags &= ~DLADM_OPT_PERSIST; 5271b509e89bSRishi Srivatsavai break; 5272b509e89bSRishi Srivatsavai case 'R': 5273b509e89bSRishi Srivatsavai altroot = optarg; 5274b509e89bSRishi Srivatsavai break; 5275b509e89bSRishi Srivatsavai default: 5276b509e89bSRishi Srivatsavai die_opterr(optopt, option, use); 5277b509e89bSRishi Srivatsavai } 5278b509e89bSRishi Srivatsavai } 5279b509e89bSRishi Srivatsavai 5280b509e89bSRishi Srivatsavai /* get simnet name (required last argument) */ 5281b509e89bSRishi Srivatsavai if (optind != (argc - 1)) 5282b509e89bSRishi Srivatsavai usage(); 5283b509e89bSRishi Srivatsavai 5284b509e89bSRishi Srivatsavai if (!dladm_valid_linkname(argv[optind])) 5285b509e89bSRishi Srivatsavai die("invalid link name '%s'", argv[optind]); 5286b509e89bSRishi Srivatsavai 5287b509e89bSRishi Srivatsavai if (altroot != NULL) 5288b509e89bSRishi Srivatsavai altroot_cmd(altroot, argc, argv); 5289b509e89bSRishi Srivatsavai 5290b509e89bSRishi Srivatsavai status = dladm_name2info(handle, argv[optind], &linkid, NULL, NULL, 5291b509e89bSRishi Srivatsavai NULL); 5292b509e89bSRishi Srivatsavai if (status != DLADM_STATUS_OK) 5293b509e89bSRishi Srivatsavai die("simnet '%s' not found", argv[optind]); 5294b509e89bSRishi Srivatsavai 5295b509e89bSRishi Srivatsavai if ((status = dladm_simnet_info(handle, linkid, &slinfo, 5296b509e89bSRishi Srivatsavai flags)) != DLADM_STATUS_OK) 5297b509e89bSRishi Srivatsavai die_dlerr(status, "failed to retrieve simnet information"); 5298b509e89bSRishi Srivatsavai 5299b509e89bSRishi Srivatsavai status = dladm_simnet_delete(handle, linkid, flags); 5300b509e89bSRishi Srivatsavai if (status != DLADM_STATUS_OK) 5301b509e89bSRishi Srivatsavai die_dlerr(status, "simnet deletion failed"); 5302b509e89bSRishi Srivatsavai } 5303b509e89bSRishi Srivatsavai 5304b509e89bSRishi Srivatsavai static void 5305b509e89bSRishi Srivatsavai do_modify_simnet(int argc, char *argv[], const char *use) 5306b509e89bSRishi Srivatsavai { 5307b509e89bSRishi Srivatsavai int option; 5308b509e89bSRishi Srivatsavai uint32_t flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST; 5309b509e89bSRishi Srivatsavai datalink_id_t linkid; 5310b509e89bSRishi Srivatsavai datalink_id_t peer_linkid; 5311b509e89bSRishi Srivatsavai char *altroot = NULL; 5312b509e89bSRishi Srivatsavai dladm_status_t status; 5313b509e89bSRishi Srivatsavai boolean_t p_arg = B_FALSE; 5314b509e89bSRishi Srivatsavai 5315b509e89bSRishi Srivatsavai opterr = 0; 5316b509e89bSRishi Srivatsavai while ((option = getopt_long(argc, argv, ":tR:p:", simnet_lopts, 5317b509e89bSRishi Srivatsavai NULL)) != -1) { 5318b509e89bSRishi Srivatsavai switch (option) { 5319b509e89bSRishi Srivatsavai case 't': 5320b509e89bSRishi Srivatsavai flags &= ~DLADM_OPT_PERSIST; 5321b509e89bSRishi Srivatsavai break; 5322b509e89bSRishi Srivatsavai case 'R': 5323b509e89bSRishi Srivatsavai altroot = optarg; 5324b509e89bSRishi Srivatsavai break; 5325b509e89bSRishi Srivatsavai case 'p': 5326b509e89bSRishi Srivatsavai if (p_arg) 5327b509e89bSRishi Srivatsavai die_optdup(option); 5328b509e89bSRishi Srivatsavai p_arg = B_TRUE; 5329b509e89bSRishi Srivatsavai if (strcasecmp(optarg, "none") == 0) 5330b509e89bSRishi Srivatsavai peer_linkid = DATALINK_INVALID_LINKID; 5331b509e89bSRishi Srivatsavai else if (dladm_name2info(handle, optarg, &peer_linkid, 5332b509e89bSRishi Srivatsavai NULL, NULL, NULL) != DLADM_STATUS_OK) 5333b509e89bSRishi Srivatsavai die("invalid peer link name '%s'", optarg); 5334b509e89bSRishi Srivatsavai break; 5335b509e89bSRishi Srivatsavai default: 5336b509e89bSRishi Srivatsavai die_opterr(optopt, option, use); 5337b509e89bSRishi Srivatsavai } 5338b509e89bSRishi Srivatsavai } 5339b509e89bSRishi Srivatsavai 5340b509e89bSRishi Srivatsavai /* get simnet name (required last argument) */ 5341b509e89bSRishi Srivatsavai if (optind != (argc - 1)) 5342b509e89bSRishi Srivatsavai usage(); 5343b509e89bSRishi Srivatsavai 5344b509e89bSRishi Srivatsavai /* Nothing to do if no peer link argument */ 5345b509e89bSRishi Srivatsavai if (!p_arg) 5346b509e89bSRishi Srivatsavai return; 5347b509e89bSRishi Srivatsavai 5348b509e89bSRishi Srivatsavai if (altroot != NULL) 5349b509e89bSRishi Srivatsavai altroot_cmd(altroot, argc, argv); 5350b509e89bSRishi Srivatsavai 5351b509e89bSRishi Srivatsavai status = dladm_name2info(handle, argv[optind], &linkid, NULL, NULL, 5352b509e89bSRishi Srivatsavai NULL); 5353b509e89bSRishi Srivatsavai if (status != DLADM_STATUS_OK) 5354b509e89bSRishi Srivatsavai die("invalid link name '%s'", argv[optind]); 5355b509e89bSRishi Srivatsavai 5356b509e89bSRishi Srivatsavai status = dladm_simnet_modify(handle, linkid, peer_linkid, flags); 5357b509e89bSRishi Srivatsavai if (status != DLADM_STATUS_OK) 5358b509e89bSRishi Srivatsavai die_dlerr(status, "simnet modification failed"); 5359b509e89bSRishi Srivatsavai } 5360b509e89bSRishi Srivatsavai 5361b509e89bSRishi Srivatsavai static dladm_status_t 5362b509e89bSRishi Srivatsavai print_simnet(show_state_t *state, datalink_id_t linkid) 5363b509e89bSRishi Srivatsavai { 5364b509e89bSRishi Srivatsavai dladm_simnet_attr_t slinfo; 5365b509e89bSRishi Srivatsavai uint32_t flags; 5366b509e89bSRishi Srivatsavai dladm_status_t status; 5367b509e89bSRishi Srivatsavai simnet_fields_buf_t slbuf; 5368b509e89bSRishi Srivatsavai char mstr[ETHERADDRL * 3]; 5369b509e89bSRishi Srivatsavai 5370b509e89bSRishi Srivatsavai bzero(&slbuf, sizeof (slbuf)); 5371b509e89bSRishi Srivatsavai if ((status = dladm_datalink_id2info(handle, linkid, &flags, NULL, NULL, 5372b509e89bSRishi Srivatsavai slbuf.simnet_name, sizeof (slbuf.simnet_name))) 5373b509e89bSRishi Srivatsavai != DLADM_STATUS_OK) 5374b509e89bSRishi Srivatsavai return (status); 5375b509e89bSRishi Srivatsavai 5376b509e89bSRishi Srivatsavai if (!(state->ls_flags & flags)) 5377b509e89bSRishi Srivatsavai return (DLADM_STATUS_NOTFOUND); 5378b509e89bSRishi Srivatsavai 5379b509e89bSRishi Srivatsavai if ((status = dladm_simnet_info(handle, linkid, &slinfo, 5380b509e89bSRishi Srivatsavai state->ls_flags)) != DLADM_STATUS_OK) 5381b509e89bSRishi Srivatsavai return (status); 5382b509e89bSRishi Srivatsavai 5383b509e89bSRishi Srivatsavai if (slinfo.sna_peer_link_id != DATALINK_INVALID_LINKID && 5384b509e89bSRishi Srivatsavai (status = dladm_datalink_id2info(handle, slinfo.sna_peer_link_id, 5385b509e89bSRishi Srivatsavai NULL, NULL, NULL, slbuf.simnet_otherlink, 5386b509e89bSRishi Srivatsavai sizeof (slbuf.simnet_otherlink))) != 5387b509e89bSRishi Srivatsavai DLADM_STATUS_OK) 5388b509e89bSRishi Srivatsavai return (status); 5389b509e89bSRishi Srivatsavai 5390b509e89bSRishi Srivatsavai if (slinfo.sna_mac_len > sizeof (slbuf.simnet_macaddr)) 5391b509e89bSRishi Srivatsavai return (DLADM_STATUS_BADVAL); 5392b509e89bSRishi Srivatsavai 5393b509e89bSRishi Srivatsavai (void) strlcpy(slbuf.simnet_macaddr, 5394b509e89bSRishi Srivatsavai dladm_aggr_macaddr2str(slinfo.sna_mac_addr, mstr), 5395b509e89bSRishi Srivatsavai sizeof (slbuf.simnet_macaddr)); 5396b509e89bSRishi Srivatsavai (void) dladm_media2str(slinfo.sna_type, slbuf.simnet_media); 5397b509e89bSRishi Srivatsavai 5398b509e89bSRishi Srivatsavai ofmt_print(state->ls_ofmt, &slbuf); 5399b509e89bSRishi Srivatsavai return (status); 5400b509e89bSRishi Srivatsavai } 5401b509e89bSRishi Srivatsavai 5402b509e89bSRishi Srivatsavai /* ARGSUSED */ 5403b509e89bSRishi Srivatsavai static int 5404b509e89bSRishi Srivatsavai show_simnet(dladm_handle_t dh, datalink_id_t linkid, void *arg) 5405b509e89bSRishi Srivatsavai { 5406b509e89bSRishi Srivatsavai show_state_t *state = arg; 5407b509e89bSRishi Srivatsavai 5408b509e89bSRishi Srivatsavai state->ls_status = print_simnet(state, linkid); 5409b509e89bSRishi Srivatsavai return (DLADM_WALK_CONTINUE); 5410b509e89bSRishi Srivatsavai } 5411b509e89bSRishi Srivatsavai 5412b509e89bSRishi Srivatsavai static void 5413b509e89bSRishi Srivatsavai do_show_simnet(int argc, char *argv[], const char *use) 5414b509e89bSRishi Srivatsavai { 5415b509e89bSRishi Srivatsavai int option; 5416b509e89bSRishi Srivatsavai uint32_t flags = DLADM_OPT_ACTIVE; 5417b509e89bSRishi Srivatsavai boolean_t p_arg = B_FALSE; 5418b509e89bSRishi Srivatsavai datalink_id_t linkid = DATALINK_ALL_LINKID; 5419b509e89bSRishi Srivatsavai show_state_t state; 5420b509e89bSRishi Srivatsavai dladm_status_t status; 5421b509e89bSRishi Srivatsavai boolean_t o_arg = B_FALSE; 5422b509e89bSRishi Srivatsavai ofmt_handle_t ofmt; 5423b509e89bSRishi Srivatsavai ofmt_status_t oferr; 5424b509e89bSRishi Srivatsavai char *all_fields = "link,media,macaddress,otherlink"; 5425b509e89bSRishi Srivatsavai char *fields_str = all_fields; 5426b509e89bSRishi Srivatsavai uint_t ofmtflags = 0; 5427b509e89bSRishi Srivatsavai 5428b509e89bSRishi Srivatsavai bzero(&state, sizeof (state)); 5429b509e89bSRishi Srivatsavai 5430b509e89bSRishi Srivatsavai opterr = 0; 5431b509e89bSRishi Srivatsavai while ((option = getopt_long(argc, argv, ":pPo:", 5432b509e89bSRishi Srivatsavai show_lopts, NULL)) != -1) { 5433b509e89bSRishi Srivatsavai switch (option) { 5434b509e89bSRishi Srivatsavai case 'p': 5435b509e89bSRishi Srivatsavai if (p_arg) 5436b509e89bSRishi Srivatsavai die_optdup(option); 5437b509e89bSRishi Srivatsavai 5438b509e89bSRishi Srivatsavai p_arg = B_TRUE; 5439b509e89bSRishi Srivatsavai state.ls_parsable = p_arg; 5440b509e89bSRishi Srivatsavai break; 5441b509e89bSRishi Srivatsavai case 'P': 5442b509e89bSRishi Srivatsavai if (flags != DLADM_OPT_ACTIVE) 5443b509e89bSRishi Srivatsavai die_optdup(option); 5444b509e89bSRishi Srivatsavai 5445b509e89bSRishi Srivatsavai flags = DLADM_OPT_PERSIST; 5446b509e89bSRishi Srivatsavai break; 5447b509e89bSRishi Srivatsavai case 'o': 5448b509e89bSRishi Srivatsavai o_arg = B_TRUE; 5449b509e89bSRishi Srivatsavai fields_str = optarg; 5450b509e89bSRishi Srivatsavai break; 5451b509e89bSRishi Srivatsavai default: 5452b509e89bSRishi Srivatsavai die_opterr(optopt, option, use); 5453b509e89bSRishi Srivatsavai break; 5454b509e89bSRishi Srivatsavai } 5455b509e89bSRishi Srivatsavai } 5456b509e89bSRishi Srivatsavai 5457b509e89bSRishi Srivatsavai if (p_arg && !o_arg) 5458b509e89bSRishi Srivatsavai die("-p requires -o"); 5459b509e89bSRishi Srivatsavai 5460b509e89bSRishi Srivatsavai if (strcasecmp(fields_str, "all") == 0) { 5461b509e89bSRishi Srivatsavai if (p_arg) 5462b509e89bSRishi Srivatsavai die("\"-o all\" is invalid with -p"); 5463b509e89bSRishi Srivatsavai fields_str = all_fields; 5464b509e89bSRishi Srivatsavai } 5465b509e89bSRishi Srivatsavai 5466b509e89bSRishi Srivatsavai /* get link name (optional last argument) */ 5467b509e89bSRishi Srivatsavai if (optind == (argc-1)) { 5468b509e89bSRishi Srivatsavai if ((status = dladm_name2info(handle, argv[optind], &linkid, 5469b509e89bSRishi Srivatsavai NULL, NULL, NULL)) != DLADM_STATUS_OK) { 5470b509e89bSRishi Srivatsavai die_dlerr(status, "link %s is not valid", argv[optind]); 5471b509e89bSRishi Srivatsavai } 5472b509e89bSRishi Srivatsavai } else if (optind != argc) { 5473b509e89bSRishi Srivatsavai usage(); 5474b509e89bSRishi Srivatsavai } 5475b509e89bSRishi Srivatsavai 5476b509e89bSRishi Srivatsavai state.ls_flags = flags; 5477b509e89bSRishi Srivatsavai state.ls_donefirst = B_FALSE; 5478b509e89bSRishi Srivatsavai if (state.ls_parsable) 5479b509e89bSRishi Srivatsavai ofmtflags |= OFMT_PARSABLE; 5480b509e89bSRishi Srivatsavai oferr = ofmt_open(fields_str, simnet_fields, ofmtflags, 0, &ofmt); 5481b509e89bSRishi Srivatsavai dladm_ofmt_check(oferr, state.ls_parsable, ofmt); 5482b509e89bSRishi Srivatsavai state.ls_ofmt = ofmt; 5483b509e89bSRishi Srivatsavai 5484b509e89bSRishi Srivatsavai if (linkid == DATALINK_ALL_LINKID) { 5485b509e89bSRishi Srivatsavai (void) dladm_walk_datalink_id(show_simnet, handle, &state, 5486b509e89bSRishi Srivatsavai DATALINK_CLASS_SIMNET, DATALINK_ANY_MEDIATYPE, flags); 5487b509e89bSRishi Srivatsavai } else { 5488b509e89bSRishi Srivatsavai (void) show_simnet(handle, linkid, &state); 5489b509e89bSRishi Srivatsavai if (state.ls_status != DLADM_STATUS_OK) { 5490b509e89bSRishi Srivatsavai ofmt_close(ofmt); 5491b509e89bSRishi Srivatsavai die_dlerr(state.ls_status, "failed to show simnet %s", 5492b509e89bSRishi Srivatsavai argv[optind]); 5493b509e89bSRishi Srivatsavai } 5494b509e89bSRishi Srivatsavai } 5495b509e89bSRishi Srivatsavai ofmt_close(ofmt); 5496b509e89bSRishi Srivatsavai } 5497b509e89bSRishi Srivatsavai 5498da14cebeSEric Cheng static void 54996be03d0bSVasumathi Sundaram - Sun Microsystems link_stats(datalink_id_t linkid, uint_t interval, char *fields_str, 55006be03d0bSVasumathi Sundaram - Sun Microsystems show_state_t *state) 5501d62bc4baSyz147064 { 55028002d411SSowmini Varadhan ofmt_handle_t ofmt; 55038002d411SSowmini Varadhan ofmt_status_t oferr; 55048002d411SSowmini Varadhan uint_t ofmtflags = 0; 550533343a97Smeem 55068002d411SSowmini Varadhan if (state->ls_parsable) 55078002d411SSowmini Varadhan ofmtflags |= OFMT_PARSABLE; 55088002d411SSowmini Varadhan oferr = ofmt_open(fields_str, link_s_fields, ofmtflags, 0, &ofmt); 55098002d411SSowmini Varadhan dladm_ofmt_check(oferr, state->ls_parsable, ofmt); 55108002d411SSowmini Varadhan state->ls_ofmt = ofmt; 55117c478bd9Sstevel@tonic-gate 55127c478bd9Sstevel@tonic-gate /* 55137c478bd9Sstevel@tonic-gate * If an interval is specified, continuously show the stats 55147c478bd9Sstevel@tonic-gate * only for the first MAC port. 55157c478bd9Sstevel@tonic-gate */ 55166be03d0bSVasumathi Sundaram - Sun Microsystems state->ls_firstonly = (interval != 0); 55177c478bd9Sstevel@tonic-gate 55187c478bd9Sstevel@tonic-gate for (;;) { 55196be03d0bSVasumathi Sundaram - Sun Microsystems state->ls_donefirst = B_FALSE; 5520d62bc4baSyz147064 if (linkid == DATALINK_ALL_LINKID) { 55214ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(show_link_stats, handle, 55224ac67f02SAnurag S. Maskey state, DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE, 5523d62bc4baSyz147064 DLADM_OPT_ACTIVE); 5524d62bc4baSyz147064 } else { 55254ac67f02SAnurag S. Maskey (void) show_link_stats(handle, linkid, state); 5526d62bc4baSyz147064 } 55277c478bd9Sstevel@tonic-gate 55287c478bd9Sstevel@tonic-gate if (interval == 0) 55297c478bd9Sstevel@tonic-gate break; 55307c478bd9Sstevel@tonic-gate 5531c3affd82SMichael Lim (void) fflush(stdout); 55327c478bd9Sstevel@tonic-gate (void) sleep(interval); 55337c478bd9Sstevel@tonic-gate } 55348002d411SSowmini Varadhan ofmt_close(ofmt); 55357c478bd9Sstevel@tonic-gate } 55367c478bd9Sstevel@tonic-gate 55377c478bd9Sstevel@tonic-gate static void 5538d62bc4baSyz147064 aggr_stats(datalink_id_t linkid, show_grp_state_t *state, uint_t interval) 55397c478bd9Sstevel@tonic-gate { 55407c478bd9Sstevel@tonic-gate /* 55417c478bd9Sstevel@tonic-gate * If an interval is specified, continuously show the stats 55427c478bd9Sstevel@tonic-gate * only for the first group. 55437c478bd9Sstevel@tonic-gate */ 5544d62bc4baSyz147064 state->gs_firstonly = (interval != 0); 55457c478bd9Sstevel@tonic-gate 55467c478bd9Sstevel@tonic-gate for (;;) { 5547d62bc4baSyz147064 state->gs_donefirst = B_FALSE; 5548d62bc4baSyz147064 if (linkid == DATALINK_ALL_LINKID) 55494ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(show_aggr, handle, state, 5550d62bc4baSyz147064 DATALINK_CLASS_AGGR, DATALINK_ANY_MEDIATYPE, 5551d62bc4baSyz147064 DLADM_OPT_ACTIVE); 5552d62bc4baSyz147064 else 55534ac67f02SAnurag S. Maskey (void) show_aggr(handle, linkid, state); 55547c478bd9Sstevel@tonic-gate 55557c478bd9Sstevel@tonic-gate if (interval == 0) 55567c478bd9Sstevel@tonic-gate break; 55577c478bd9Sstevel@tonic-gate 5558c3affd82SMichael Lim (void) fflush(stdout); 55597c478bd9Sstevel@tonic-gate (void) sleep(interval); 55607c478bd9Sstevel@tonic-gate } 55617c478bd9Sstevel@tonic-gate } 55627c478bd9Sstevel@tonic-gate 5563da14cebeSEric Cheng /* ARGSUSED */ 55647c478bd9Sstevel@tonic-gate static void 5565da14cebeSEric Cheng vnic_stats(show_vnic_state_t *sp, uint32_t interval) 55667c478bd9Sstevel@tonic-gate { 5567da14cebeSEric Cheng show_vnic_state_t state; 5568da14cebeSEric Cheng boolean_t specific_link, specific_dev; 55697c478bd9Sstevel@tonic-gate 5570da14cebeSEric Cheng /* Display vnic statistics */ 5571da14cebeSEric Cheng dump_vnics_head(sp->vs_link); 5572e7801d59Ssowmini 5573da14cebeSEric Cheng bzero(&state, sizeof (state)); 5574da14cebeSEric Cheng state.vs_stats = B_TRUE; 5575da14cebeSEric Cheng state.vs_vnic_id = sp->vs_vnic_id; 5576da14cebeSEric Cheng state.vs_link_id = sp->vs_link_id; 55777c478bd9Sstevel@tonic-gate 55787c478bd9Sstevel@tonic-gate /* 5579da14cebeSEric Cheng * If an interval is specified, and a vnic ID is not specified, 5580da14cebeSEric Cheng * continuously show the stats only for the first vnic. 55817c478bd9Sstevel@tonic-gate */ 5582da14cebeSEric Cheng specific_link = (sp->vs_vnic_id != DATALINK_ALL_LINKID); 5583da14cebeSEric Cheng specific_dev = (sp->vs_link_id != DATALINK_ALL_LINKID); 55847c478bd9Sstevel@tonic-gate 55857c478bd9Sstevel@tonic-gate for (;;) { 5586da14cebeSEric Cheng /* Get stats for each vnic */ 5587da14cebeSEric Cheng state.vs_found = B_FALSE; 5588da14cebeSEric Cheng state.vs_donefirst = B_FALSE; 5589da14cebeSEric Cheng state.vs_printstats = B_FALSE; 5590da14cebeSEric Cheng state.vs_flags = DLADM_OPT_ACTIVE; 55917c478bd9Sstevel@tonic-gate 5592da14cebeSEric Cheng if (!specific_link) { 55934ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(show_vnic, handle, &state, 5594da14cebeSEric Cheng DATALINK_CLASS_VNIC, DATALINK_ANY_MEDIATYPE, 5595da14cebeSEric Cheng DLADM_OPT_ACTIVE); 5596da14cebeSEric Cheng } else { 55974ac67f02SAnurag S. Maskey (void) show_vnic(handle, sp->vs_vnic_id, &state); 5598da14cebeSEric Cheng if (state.vs_status != DLADM_STATUS_OK) { 5599da14cebeSEric Cheng die_dlerr(state.vs_status, 5600da14cebeSEric Cheng "failed to show vnic '%s'", sp->vs_vnic); 5601da14cebeSEric Cheng } 5602da14cebeSEric Cheng } 56037c478bd9Sstevel@tonic-gate 5604da14cebeSEric Cheng if (specific_link && !state.vs_found) 5605da14cebeSEric Cheng die("non-existent vnic '%s'", sp->vs_vnic); 5606da14cebeSEric Cheng if (specific_dev && !state.vs_found) 5607da14cebeSEric Cheng die("device %s has no vnics", sp->vs_link); 5608da14cebeSEric Cheng 5609da14cebeSEric Cheng /* Show totals */ 5610da14cebeSEric Cheng if ((specific_link | specific_dev) && !interval) { 5611da14cebeSEric Cheng (void) printf("Total"); 5612da14cebeSEric Cheng (void) printf("\t%-10llu", 5613da14cebeSEric Cheng state.vs_totalstats.ipackets); 5614da14cebeSEric Cheng (void) printf("%-12llu", 5615da14cebeSEric Cheng state.vs_totalstats.rbytes); 5616da14cebeSEric Cheng (void) printf("%-10llu", 5617da14cebeSEric Cheng state.vs_totalstats.opackets); 5618da14cebeSEric Cheng (void) printf("%-12llu\n", 5619da14cebeSEric Cheng state.vs_totalstats.obytes); 5620da14cebeSEric Cheng } 5621da14cebeSEric Cheng 5622da14cebeSEric Cheng /* Show stats for each vnic */ 5623da14cebeSEric Cheng state.vs_donefirst = B_FALSE; 5624da14cebeSEric Cheng state.vs_printstats = B_TRUE; 5625da14cebeSEric Cheng 5626da14cebeSEric Cheng if (!specific_link) { 56274ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(show_vnic, handle, &state, 5628da14cebeSEric Cheng DATALINK_CLASS_VNIC, DATALINK_ANY_MEDIATYPE, 5629da14cebeSEric Cheng DLADM_OPT_ACTIVE); 5630da14cebeSEric Cheng } else { 56314ac67f02SAnurag S. Maskey (void) show_vnic(handle, sp->vs_vnic_id, &state); 5632da14cebeSEric Cheng if (state.vs_status != DLADM_STATUS_OK) { 5633da14cebeSEric Cheng die_dlerr(state.vs_status, 5634da14cebeSEric Cheng "failed to show vnic '%s'", sp->vs_vnic); 5635da14cebeSEric Cheng } 5636da14cebeSEric Cheng } 56377c478bd9Sstevel@tonic-gate 56387c478bd9Sstevel@tonic-gate if (interval == 0) 56397c478bd9Sstevel@tonic-gate break; 56407c478bd9Sstevel@tonic-gate 5641c3affd82SMichael Lim (void) fflush(stdout); 56427c478bd9Sstevel@tonic-gate (void) sleep(interval); 56437c478bd9Sstevel@tonic-gate } 56447c478bd9Sstevel@tonic-gate } 56457c478bd9Sstevel@tonic-gate 56467c478bd9Sstevel@tonic-gate static void 5647da14cebeSEric Cheng get_mac_stats(const char *dev, pktsum_t *stats) 56487c478bd9Sstevel@tonic-gate { 56497c478bd9Sstevel@tonic-gate kstat_ctl_t *kcp; 56507c478bd9Sstevel@tonic-gate kstat_t *ksp; 5651da14cebeSEric Cheng char module[DLPI_LINKNAME_MAX]; 5652da14cebeSEric Cheng uint_t instance; 5653da14cebeSEric Cheng 5654da14cebeSEric Cheng 5655da14cebeSEric Cheng bzero(stats, sizeof (*stats)); 5656da14cebeSEric Cheng 5657da14cebeSEric Cheng if (dlpi_parselink(dev, module, &instance) != DLPI_SUCCESS) 5658da14cebeSEric Cheng return; 56597c478bd9Sstevel@tonic-gate 56607c478bd9Sstevel@tonic-gate if ((kcp = kstat_open()) == NULL) { 566133343a97Smeem warn("kstat open operation failed"); 56627c478bd9Sstevel@tonic-gate return; 56637c478bd9Sstevel@tonic-gate } 56647c478bd9Sstevel@tonic-gate 5665da14cebeSEric Cheng ksp = dladm_kstat_lookup(kcp, module, instance, "mac", NULL); 5666da14cebeSEric Cheng if (ksp != NULL) 5667da14cebeSEric Cheng dladm_get_stats(kcp, ksp, stats); 5668da14cebeSEric Cheng 56697c478bd9Sstevel@tonic-gate (void) kstat_close(kcp); 56707c478bd9Sstevel@tonic-gate 56717c478bd9Sstevel@tonic-gate } 56727c478bd9Sstevel@tonic-gate 56737c478bd9Sstevel@tonic-gate static void 56747c478bd9Sstevel@tonic-gate get_link_stats(const char *link, pktsum_t *stats) 56757c478bd9Sstevel@tonic-gate { 5676da14cebeSEric Cheng kstat_ctl_t *kcp; 5677da14cebeSEric Cheng kstat_t *ksp; 5678da14cebeSEric Cheng 56797c478bd9Sstevel@tonic-gate bzero(stats, sizeof (*stats)); 5680da14cebeSEric Cheng 5681da14cebeSEric Cheng if ((kcp = kstat_open()) == NULL) { 5682da14cebeSEric Cheng warn("kstat_open operation failed"); 5683da14cebeSEric Cheng return; 5684da14cebeSEric Cheng } 5685da14cebeSEric Cheng 5686da14cebeSEric Cheng ksp = dladm_kstat_lookup(kcp, "link", 0, link, NULL); 5687da14cebeSEric Cheng 5688da14cebeSEric Cheng if (ksp != NULL) 5689da14cebeSEric Cheng dladm_get_stats(kcp, ksp, stats); 5690da14cebeSEric Cheng 5691da14cebeSEric Cheng (void) kstat_close(kcp); 56927c478bd9Sstevel@tonic-gate } 56937c478bd9Sstevel@tonic-gate 5694ba2e4443Sseb static int 5695d62bc4baSyz147064 query_kstat(char *module, int instance, const char *name, const char *stat, 5696d62bc4baSyz147064 uint8_t type, void *val) 56977c478bd9Sstevel@tonic-gate { 56987c478bd9Sstevel@tonic-gate kstat_ctl_t *kcp; 56997c478bd9Sstevel@tonic-gate kstat_t *ksp; 57007c478bd9Sstevel@tonic-gate 57017c478bd9Sstevel@tonic-gate if ((kcp = kstat_open()) == NULL) { 570233343a97Smeem warn("kstat open operation failed"); 5703ba2e4443Sseb return (-1); 57047c478bd9Sstevel@tonic-gate } 57057c478bd9Sstevel@tonic-gate 5706d62bc4baSyz147064 if ((ksp = kstat_lookup(kcp, module, instance, (char *)name)) == NULL) { 57077c478bd9Sstevel@tonic-gate /* 57087c478bd9Sstevel@tonic-gate * The kstat query could fail if the underlying MAC 57097c478bd9Sstevel@tonic-gate * driver was already detached. 57107c478bd9Sstevel@tonic-gate */ 57117c478bd9Sstevel@tonic-gate goto bail; 57127c478bd9Sstevel@tonic-gate } 57137c478bd9Sstevel@tonic-gate 57147c478bd9Sstevel@tonic-gate if (kstat_read(kcp, ksp, NULL) == -1) { 571533343a97Smeem warn("kstat read failed"); 57167c478bd9Sstevel@tonic-gate goto bail; 57177c478bd9Sstevel@tonic-gate } 57187c478bd9Sstevel@tonic-gate 5719e7801d59Ssowmini if (dladm_kstat_value(ksp, stat, type, val) < 0) 57207c478bd9Sstevel@tonic-gate goto bail; 5721ba2e4443Sseb 5722ba2e4443Sseb (void) kstat_close(kcp); 5723ba2e4443Sseb return (0); 57247c478bd9Sstevel@tonic-gate 57257c478bd9Sstevel@tonic-gate bail: 57267c478bd9Sstevel@tonic-gate (void) kstat_close(kcp); 5727ba2e4443Sseb return (-1); 5728ba2e4443Sseb } 5729ba2e4443Sseb 5730d62bc4baSyz147064 static int 5731d62bc4baSyz147064 get_one_kstat(const char *name, const char *stat, uint8_t type, 5732d62bc4baSyz147064 void *val, boolean_t islink) 5733d62bc4baSyz147064 { 5734d62bc4baSyz147064 char module[DLPI_LINKNAME_MAX]; 5735d62bc4baSyz147064 uint_t instance; 5736d62bc4baSyz147064 5737d62bc4baSyz147064 if (islink) { 5738d62bc4baSyz147064 return (query_kstat("link", 0, name, stat, type, val)); 5739d62bc4baSyz147064 } else { 5740d62bc4baSyz147064 if (dlpi_parselink(name, module, &instance) != DLPI_SUCCESS) 5741d62bc4baSyz147064 return (-1); 5742d62bc4baSyz147064 5743d62bc4baSyz147064 return (query_kstat(module, instance, "mac", stat, type, val)); 5744d62bc4baSyz147064 } 5745d62bc4baSyz147064 } 5746d62bc4baSyz147064 5747ba2e4443Sseb static uint64_t 5748d62bc4baSyz147064 get_ifspeed(const char *name, boolean_t islink) 5749ba2e4443Sseb { 5750ba2e4443Sseb uint64_t ifspeed = 0; 5751ba2e4443Sseb 5752d62bc4baSyz147064 (void) get_one_kstat(name, "ifspeed", KSTAT_DATA_UINT64, 5753d62bc4baSyz147064 &ifspeed, islink); 5754d62bc4baSyz147064 57557c478bd9Sstevel@tonic-gate return (ifspeed); 57567c478bd9Sstevel@tonic-gate } 57577c478bd9Sstevel@tonic-gate 5758f595a68aSyz147064 static const char * 5759d62bc4baSyz147064 get_linkstate(const char *name, boolean_t islink, char *buf) 57607c478bd9Sstevel@tonic-gate { 5761d62bc4baSyz147064 link_state_t linkstate; 57627c478bd9Sstevel@tonic-gate 5763d62bc4baSyz147064 if (get_one_kstat(name, "link_state", KSTAT_DATA_UINT32, 5764d62bc4baSyz147064 &linkstate, islink) != 0) { 5765da14cebeSEric Cheng (void) strlcpy(buf, "?", DLADM_STRSIZE); 57663a62633bSyz147064 return (buf); 57677c478bd9Sstevel@tonic-gate } 5768d62bc4baSyz147064 return (dladm_linkstate2str(linkstate, buf)); 57697c478bd9Sstevel@tonic-gate } 57707c478bd9Sstevel@tonic-gate 5771f595a68aSyz147064 static const char * 5772d62bc4baSyz147064 get_linkduplex(const char *name, boolean_t islink, char *buf) 57737c478bd9Sstevel@tonic-gate { 5774d62bc4baSyz147064 link_duplex_t linkduplex; 57757c478bd9Sstevel@tonic-gate 5776d62bc4baSyz147064 if (get_one_kstat(name, "link_duplex", KSTAT_DATA_UINT32, 5777d62bc4baSyz147064 &linkduplex, islink) != 0) { 57783a62633bSyz147064 (void) strlcpy(buf, "unknown", DLADM_STRSIZE); 57793a62633bSyz147064 return (buf); 57807c478bd9Sstevel@tonic-gate } 57817c478bd9Sstevel@tonic-gate 5782d62bc4baSyz147064 return (dladm_linkduplex2str(linkduplex, buf)); 57837c478bd9Sstevel@tonic-gate } 57840ba2cbe9Sxc151355 57850ba2cbe9Sxc151355 static int 57868002d411SSowmini Varadhan parse_wifi_fields(char *str, ofmt_handle_t *ofmt, uint_t cmdtype, 57878002d411SSowmini Varadhan boolean_t parsable) 57880ba2cbe9Sxc151355 { 57898002d411SSowmini Varadhan ofmt_field_t *template, *of; 57908002d411SSowmini Varadhan ofmt_cb_t *fn; 57918002d411SSowmini Varadhan ofmt_status_t oferr; 57920ba2cbe9Sxc151355 57930ba2cbe9Sxc151355 if (cmdtype == WIFI_CMD_SCAN) { 57948002d411SSowmini Varadhan template = wifi_common_fields; 57950ba2cbe9Sxc151355 if (str == NULL) 57960ba2cbe9Sxc151355 str = def_scan_wifi_fields; 57970ba2cbe9Sxc151355 if (strcasecmp(str, "all") == 0) 57980ba2cbe9Sxc151355 str = all_scan_wifi_fields; 57998002d411SSowmini Varadhan fn = print_wlan_attr_cb; 58000ba2cbe9Sxc151355 } else if (cmdtype == WIFI_CMD_SHOW) { 58018002d411SSowmini Varadhan bcopy(wifi_common_fields, &wifi_show_fields[2], 58028002d411SSowmini Varadhan sizeof (wifi_common_fields)); 58038002d411SSowmini Varadhan template = wifi_show_fields; 58040ba2cbe9Sxc151355 if (str == NULL) 58050ba2cbe9Sxc151355 str = def_show_wifi_fields; 58060ba2cbe9Sxc151355 if (strcasecmp(str, "all") == 0) 58070ba2cbe9Sxc151355 str = all_show_wifi_fields; 58088002d411SSowmini Varadhan fn = print_link_attr_cb; 58090ba2cbe9Sxc151355 } else { 58100ba2cbe9Sxc151355 return (-1); 58110ba2cbe9Sxc151355 } 58128002d411SSowmini Varadhan 58138002d411SSowmini Varadhan for (of = template; of->of_name != NULL; of++) { 58148002d411SSowmini Varadhan if (of->of_cb == NULL) 58158002d411SSowmini Varadhan of->of_cb = fn; 58168002d411SSowmini Varadhan } 58178002d411SSowmini Varadhan 58188002d411SSowmini Varadhan oferr = ofmt_open(str, template, (parsable ? OFMT_PARSABLE : 0), 58198002d411SSowmini Varadhan 0, ofmt); 58208002d411SSowmini Varadhan dladm_ofmt_check(oferr, parsable, *ofmt); 5821e7801d59Ssowmini return (0); 58220ba2cbe9Sxc151355 } 58230ba2cbe9Sxc151355 58240ba2cbe9Sxc151355 typedef struct print_wifi_state { 5825d62bc4baSyz147064 char *ws_link; 58268002d411SSowmini Varadhan boolean_t ws_parsable; 58270ba2cbe9Sxc151355 boolean_t ws_header; 58288002d411SSowmini Varadhan ofmt_handle_t ws_ofmt; 58290ba2cbe9Sxc151355 } print_wifi_state_t; 58300ba2cbe9Sxc151355 5831e7801d59Ssowmini typedef struct wlan_scan_args_s { 5832e7801d59Ssowmini print_wifi_state_t *ws_state; 5833e7801d59Ssowmini void *ws_attr; 5834e7801d59Ssowmini } wlan_scan_args_t; 58350ba2cbe9Sxc151355 58368002d411SSowmini Varadhan static boolean_t 58378002d411SSowmini Varadhan print_wlan_attr_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize) 58380ba2cbe9Sxc151355 { 58398002d411SSowmini Varadhan wlan_scan_args_t *w = ofarg->ofmt_cbarg; 5840e7801d59Ssowmini print_wifi_state_t *statep = w->ws_state; 5841e7801d59Ssowmini dladm_wlan_attr_t *attrp = w->ws_attr; 58428002d411SSowmini Varadhan char tmpbuf[DLADM_STRSIZE]; 58430ba2cbe9Sxc151355 58448002d411SSowmini Varadhan if (ofarg->ofmt_id == 0) { 58458002d411SSowmini Varadhan (void) strlcpy(buf, (char *)statep->ws_link, bufsize); 58468002d411SSowmini Varadhan return (B_TRUE); 58470ba2cbe9Sxc151355 } 58480ba2cbe9Sxc151355 58498002d411SSowmini Varadhan if ((ofarg->ofmt_id & attrp->wa_valid) == 0) 58508002d411SSowmini Varadhan return (B_TRUE); 58510ba2cbe9Sxc151355 58528002d411SSowmini Varadhan switch (ofarg->ofmt_id) { 5853f595a68aSyz147064 case DLADM_WLAN_ATTR_ESSID: 58548002d411SSowmini Varadhan (void) dladm_wlan_essid2str(&attrp->wa_essid, tmpbuf); 58550ba2cbe9Sxc151355 break; 5856f595a68aSyz147064 case DLADM_WLAN_ATTR_BSSID: 58578002d411SSowmini Varadhan (void) dladm_wlan_bssid2str(&attrp->wa_bssid, tmpbuf); 58580ba2cbe9Sxc151355 break; 5859f595a68aSyz147064 case DLADM_WLAN_ATTR_SECMODE: 58608002d411SSowmini Varadhan (void) dladm_wlan_secmode2str(&attrp->wa_secmode, tmpbuf); 58610ba2cbe9Sxc151355 break; 5862f595a68aSyz147064 case DLADM_WLAN_ATTR_STRENGTH: 58638002d411SSowmini Varadhan (void) dladm_wlan_strength2str(&attrp->wa_strength, tmpbuf); 58640ba2cbe9Sxc151355 break; 5865f595a68aSyz147064 case DLADM_WLAN_ATTR_MODE: 58668002d411SSowmini Varadhan (void) dladm_wlan_mode2str(&attrp->wa_mode, tmpbuf); 58670ba2cbe9Sxc151355 break; 5868f595a68aSyz147064 case DLADM_WLAN_ATTR_SPEED: 58698002d411SSowmini Varadhan (void) dladm_wlan_speed2str(&attrp->wa_speed, tmpbuf); 58708002d411SSowmini Varadhan (void) strlcat(tmpbuf, "Mb", sizeof (tmpbuf)); 58710ba2cbe9Sxc151355 break; 5872f595a68aSyz147064 case DLADM_WLAN_ATTR_AUTH: 58738002d411SSowmini Varadhan (void) dladm_wlan_auth2str(&attrp->wa_auth, tmpbuf); 58740ba2cbe9Sxc151355 break; 5875f595a68aSyz147064 case DLADM_WLAN_ATTR_BSSTYPE: 58768002d411SSowmini Varadhan (void) dladm_wlan_bsstype2str(&attrp->wa_bsstype, tmpbuf); 58770ba2cbe9Sxc151355 break; 58780ba2cbe9Sxc151355 } 58798002d411SSowmini Varadhan (void) strlcpy(buf, tmpbuf, bufsize); 58800ba2cbe9Sxc151355 58818002d411SSowmini Varadhan return (B_TRUE); 58820ba2cbe9Sxc151355 } 58830ba2cbe9Sxc151355 58840ba2cbe9Sxc151355 static boolean_t 5885f595a68aSyz147064 print_scan_results(void *arg, dladm_wlan_attr_t *attrp) 58860ba2cbe9Sxc151355 { 58870ba2cbe9Sxc151355 print_wifi_state_t *statep = arg; 5888e7801d59Ssowmini wlan_scan_args_t warg; 58890ba2cbe9Sxc151355 5890e7801d59Ssowmini bzero(&warg, sizeof (warg)); 5891e7801d59Ssowmini warg.ws_state = statep; 5892e7801d59Ssowmini warg.ws_attr = attrp; 58938002d411SSowmini Varadhan ofmt_print(statep->ws_ofmt, &warg); 58940ba2cbe9Sxc151355 return (B_TRUE); 58950ba2cbe9Sxc151355 } 58960ba2cbe9Sxc151355 5897d62bc4baSyz147064 static int 58984ac67f02SAnurag S. Maskey scan_wifi(dladm_handle_t dh, datalink_id_t linkid, void *arg) 58990ba2cbe9Sxc151355 { 59000ba2cbe9Sxc151355 print_wifi_state_t *statep = arg; 5901f595a68aSyz147064 dladm_status_t status; 5902d62bc4baSyz147064 char link[MAXLINKNAMELEN]; 5903d62bc4baSyz147064 59044ac67f02SAnurag S. Maskey if ((status = dladm_datalink_id2info(dh, linkid, NULL, NULL, NULL, link, 5905e7801d59Ssowmini sizeof (link))) != DLADM_STATUS_OK) { 5906d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 5907d62bc4baSyz147064 } 59080ba2cbe9Sxc151355 59090ba2cbe9Sxc151355 statep->ws_link = link; 59104ac67f02SAnurag S. Maskey status = dladm_wlan_scan(dh, linkid, statep, print_scan_results); 5911f595a68aSyz147064 if (status != DLADM_STATUS_OK) 5912d62bc4baSyz147064 die_dlerr(status, "cannot scan link '%s'", statep->ws_link); 591333343a97Smeem 5914d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 59150ba2cbe9Sxc151355 } 59160ba2cbe9Sxc151355 59178002d411SSowmini Varadhan static boolean_t 59188002d411SSowmini Varadhan print_wifi_status_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize) 59190ba2cbe9Sxc151355 { 59208002d411SSowmini Varadhan static char tmpbuf[DLADM_STRSIZE]; 59218002d411SSowmini Varadhan wlan_scan_args_t *w = ofarg->ofmt_cbarg; 59228002d411SSowmini Varadhan dladm_wlan_linkattr_t *attrp = w->ws_attr; 59238002d411SSowmini Varadhan 59248002d411SSowmini Varadhan if ((ofarg->ofmt_id & attrp->la_valid) != 0) { 59258002d411SSowmini Varadhan (void) dladm_wlan_linkstatus2str(&attrp->la_status, tmpbuf); 59268002d411SSowmini Varadhan (void) strlcpy(buf, tmpbuf, bufsize); 59278002d411SSowmini Varadhan } 59288002d411SSowmini Varadhan return (B_TRUE); 59298002d411SSowmini Varadhan } 59308002d411SSowmini Varadhan 59318002d411SSowmini Varadhan static boolean_t 59328002d411SSowmini Varadhan print_link_attr_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize) 59338002d411SSowmini Varadhan { 59348002d411SSowmini Varadhan wlan_scan_args_t *w = ofarg->ofmt_cbarg, w1; 5935e7801d59Ssowmini print_wifi_state_t *statep = w->ws_state; 5936e7801d59Ssowmini dladm_wlan_linkattr_t *attrp = w->ws_attr; 59370ba2cbe9Sxc151355 5938e7801d59Ssowmini bzero(&w1, sizeof (w1)); 5939e7801d59Ssowmini w1.ws_state = statep; 5940e7801d59Ssowmini w1.ws_attr = &attrp->la_wlan_attr; 59418002d411SSowmini Varadhan ofarg->ofmt_cbarg = &w1; 59428002d411SSowmini Varadhan return (print_wlan_attr_cb(ofarg, buf, bufsize)); 59430ba2cbe9Sxc151355 } 59440ba2cbe9Sxc151355 5945d62bc4baSyz147064 static int 59464ac67f02SAnurag S. Maskey show_wifi(dladm_handle_t dh, datalink_id_t linkid, void *arg) 59470ba2cbe9Sxc151355 { 59480ba2cbe9Sxc151355 print_wifi_state_t *statep = arg; 5949f595a68aSyz147064 dladm_wlan_linkattr_t attr; 5950f595a68aSyz147064 dladm_status_t status; 5951d62bc4baSyz147064 char link[MAXLINKNAMELEN]; 5952e7801d59Ssowmini wlan_scan_args_t warg; 59530ba2cbe9Sxc151355 59544ac67f02SAnurag S. Maskey if ((status = dladm_datalink_id2info(dh, linkid, NULL, NULL, NULL, link, 5955e7801d59Ssowmini sizeof (link))) != DLADM_STATUS_OK) { 5956d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 5957d62bc4baSyz147064 } 5958d62bc4baSyz147064 59595f5c9f54SAnurag S. Maskey /* dladm_wlan_get_linkattr() memsets attr with 0 */ 59604ac67f02SAnurag S. Maskey status = dladm_wlan_get_linkattr(dh, linkid, &attr); 5961f595a68aSyz147064 if (status != DLADM_STATUS_OK) 5962d62bc4baSyz147064 die_dlerr(status, "cannot get link attributes for %s", link); 5963d62bc4baSyz147064 5964d62bc4baSyz147064 statep->ws_link = link; 59650ba2cbe9Sxc151355 5966e7801d59Ssowmini bzero(&warg, sizeof (warg)); 5967e7801d59Ssowmini warg.ws_state = statep; 5968e7801d59Ssowmini warg.ws_attr = &attr; 59698002d411SSowmini Varadhan ofmt_print(statep->ws_ofmt, &warg); 5970d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 59710ba2cbe9Sxc151355 } 59720ba2cbe9Sxc151355 59730ba2cbe9Sxc151355 static void 59748d5c46e6Sam223141 do_display_wifi(int argc, char **argv, int cmd, const char *use) 59750ba2cbe9Sxc151355 { 59760ba2cbe9Sxc151355 int option; 59770ba2cbe9Sxc151355 char *fields_str = NULL; 59784ac67f02SAnurag S. Maskey int (*callback)(dladm_handle_t, datalink_id_t, void *); 59790ba2cbe9Sxc151355 print_wifi_state_t state; 5980d62bc4baSyz147064 datalink_id_t linkid = DATALINK_ALL_LINKID; 5981f595a68aSyz147064 dladm_status_t status; 59820ba2cbe9Sxc151355 59830ba2cbe9Sxc151355 if (cmd == WIFI_CMD_SCAN) 59840ba2cbe9Sxc151355 callback = scan_wifi; 59850ba2cbe9Sxc151355 else if (cmd == WIFI_CMD_SHOW) 59860ba2cbe9Sxc151355 callback = show_wifi; 59870ba2cbe9Sxc151355 else 59880ba2cbe9Sxc151355 return; 59890ba2cbe9Sxc151355 59908002d411SSowmini Varadhan state.ws_parsable = B_FALSE; 59910ba2cbe9Sxc151355 state.ws_header = B_TRUE; 59920ba2cbe9Sxc151355 opterr = 0; 59930ba2cbe9Sxc151355 while ((option = getopt_long(argc, argv, ":o:p", 59940ba2cbe9Sxc151355 wifi_longopts, NULL)) != -1) { 59950ba2cbe9Sxc151355 switch (option) { 59960ba2cbe9Sxc151355 case 'o': 59970ba2cbe9Sxc151355 fields_str = optarg; 59980ba2cbe9Sxc151355 break; 59990ba2cbe9Sxc151355 case 'p': 60008002d411SSowmini Varadhan state.ws_parsable = B_TRUE; 60010ba2cbe9Sxc151355 break; 60020ba2cbe9Sxc151355 default: 60038d5c46e6Sam223141 die_opterr(optopt, option, use); 60040ba2cbe9Sxc151355 } 60050ba2cbe9Sxc151355 } 60060ba2cbe9Sxc151355 60078002d411SSowmini Varadhan if (state.ws_parsable && fields_str == NULL) 60080d365605Sschuster die("-p requires -o"); 60090d365605Sschuster 60108002d411SSowmini Varadhan if (state.ws_parsable && strcasecmp(fields_str, "all") == 0) 60110d365605Sschuster die("\"-o all\" is invalid with -p"); 60120d365605Sschuster 6013d62bc4baSyz147064 if (optind == (argc - 1)) { 60144ac67f02SAnurag S. Maskey if ((status = dladm_name2info(handle, argv[optind], &linkid, 60154ac67f02SAnurag S. Maskey NULL, NULL, NULL)) != DLADM_STATUS_OK) { 6016d62bc4baSyz147064 die_dlerr(status, "link %s is not valid", argv[optind]); 6017d62bc4baSyz147064 } 6018d62bc4baSyz147064 } else if (optind != argc) { 60190ba2cbe9Sxc151355 usage(); 6020d62bc4baSyz147064 } 60210ba2cbe9Sxc151355 60228002d411SSowmini Varadhan if (parse_wifi_fields(fields_str, &state.ws_ofmt, cmd, 60238002d411SSowmini Varadhan state.ws_parsable) < 0) 602433343a97Smeem die("invalid field(s) specified"); 602533343a97Smeem 6026d62bc4baSyz147064 if (linkid == DATALINK_ALL_LINKID) { 60274ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(callback, handle, &state, 6028b509e89bSRishi Srivatsavai DATALINK_CLASS_PHYS | DATALINK_CLASS_SIMNET, 6029b509e89bSRishi Srivatsavai DL_WIFI, DLADM_OPT_ACTIVE); 60300ba2cbe9Sxc151355 } else { 60314ac67f02SAnurag S. Maskey (void) (*callback)(handle, linkid, &state); 60320ba2cbe9Sxc151355 } 60338002d411SSowmini Varadhan ofmt_close(state.ws_ofmt); 60340ba2cbe9Sxc151355 } 60350ba2cbe9Sxc151355 60360ba2cbe9Sxc151355 static void 60378d5c46e6Sam223141 do_scan_wifi(int argc, char **argv, const char *use) 60380ba2cbe9Sxc151355 { 60398d5c46e6Sam223141 do_display_wifi(argc, argv, WIFI_CMD_SCAN, use); 60400ba2cbe9Sxc151355 } 60410ba2cbe9Sxc151355 60420ba2cbe9Sxc151355 static void 60438d5c46e6Sam223141 do_show_wifi(int argc, char **argv, const char *use) 60440ba2cbe9Sxc151355 { 60458d5c46e6Sam223141 do_display_wifi(argc, argv, WIFI_CMD_SHOW, use); 60460ba2cbe9Sxc151355 } 60470ba2cbe9Sxc151355 60480ba2cbe9Sxc151355 typedef struct wlan_count_attr { 60490ba2cbe9Sxc151355 uint_t wc_count; 6050d62bc4baSyz147064 datalink_id_t wc_linkid; 60510ba2cbe9Sxc151355 } wlan_count_attr_t; 60520ba2cbe9Sxc151355 60534ac67f02SAnurag S. Maskey /* ARGSUSED */ 6054d62bc4baSyz147064 static int 60554ac67f02SAnurag S. Maskey do_count_wlan(dladm_handle_t dh, datalink_id_t linkid, void *arg) 60560ba2cbe9Sxc151355 { 605733343a97Smeem wlan_count_attr_t *cp = arg; 60580ba2cbe9Sxc151355 60590ba2cbe9Sxc151355 if (cp->wc_count == 0) 6060d62bc4baSyz147064 cp->wc_linkid = linkid; 60610ba2cbe9Sxc151355 cp->wc_count++; 6062d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 60630ba2cbe9Sxc151355 } 60640ba2cbe9Sxc151355 60650ba2cbe9Sxc151355 static int 6066a399b765Szf162725 parse_wlan_keys(char *str, dladm_wlan_key_t **keys, uint_t *key_countp) 60670ba2cbe9Sxc151355 { 60680ba2cbe9Sxc151355 uint_t i; 6069a399b765Szf162725 dladm_wlan_key_t *wk; 60708002d411SSowmini Varadhan int nfields = 1; 60718002d411SSowmini Varadhan char *field, *token, *lasts = NULL, c; 60720ba2cbe9Sxc151355 60738002d411SSowmini Varadhan token = str; 60748002d411SSowmini Varadhan while ((c = *token++) != NULL) { 60758002d411SSowmini Varadhan if (c == ',') 60768002d411SSowmini Varadhan nfields++; 60778002d411SSowmini Varadhan } 60788002d411SSowmini Varadhan token = strdup(str); 60798002d411SSowmini Varadhan if (token == NULL) 60800ba2cbe9Sxc151355 return (-1); 60810ba2cbe9Sxc151355 60828002d411SSowmini Varadhan wk = malloc(nfields * sizeof (dladm_wlan_key_t)); 60830ba2cbe9Sxc151355 if (wk == NULL) 60840ba2cbe9Sxc151355 goto fail; 60850ba2cbe9Sxc151355 60868002d411SSowmini Varadhan token = str; 60878002d411SSowmini Varadhan for (i = 0; i < nfields; i++) { 60880ba2cbe9Sxc151355 char *s; 60890ba2cbe9Sxc151355 dladm_secobj_class_t class; 60900ba2cbe9Sxc151355 dladm_status_t status; 60910ba2cbe9Sxc151355 60928002d411SSowmini Varadhan field = strtok_r(token, ",", &lasts); 60938002d411SSowmini Varadhan token = NULL; 60948002d411SSowmini Varadhan 60958002d411SSowmini Varadhan (void) strlcpy(wk[i].wk_name, field, 6096a399b765Szf162725 DLADM_WLAN_MAX_KEYNAME_LEN); 60970ba2cbe9Sxc151355 60980ba2cbe9Sxc151355 wk[i].wk_idx = 1; 60990ba2cbe9Sxc151355 if ((s = strrchr(wk[i].wk_name, ':')) != NULL) { 61000ba2cbe9Sxc151355 if (s[1] == '\0' || s[2] != '\0' || !isdigit(s[1])) 61010ba2cbe9Sxc151355 goto fail; 61020ba2cbe9Sxc151355 61030ba2cbe9Sxc151355 wk[i].wk_idx = (uint_t)(s[1] - '0'); 61040ba2cbe9Sxc151355 *s = '\0'; 61050ba2cbe9Sxc151355 } 6106a399b765Szf162725 wk[i].wk_len = DLADM_WLAN_MAX_KEY_LEN; 61070ba2cbe9Sxc151355 61084ac67f02SAnurag S. Maskey status = dladm_get_secobj(handle, wk[i].wk_name, &class, 61090ba2cbe9Sxc151355 wk[i].wk_val, &wk[i].wk_len, 0); 61100ba2cbe9Sxc151355 if (status != DLADM_STATUS_OK) { 61110ba2cbe9Sxc151355 if (status == DLADM_STATUS_NOTFOUND) { 61124ac67f02SAnurag S. Maskey status = dladm_get_secobj(handle, wk[i].wk_name, 61130ba2cbe9Sxc151355 &class, wk[i].wk_val, &wk[i].wk_len, 61140ba2cbe9Sxc151355 DLADM_OPT_PERSIST); 61150ba2cbe9Sxc151355 } 61160ba2cbe9Sxc151355 if (status != DLADM_STATUS_OK) 61170ba2cbe9Sxc151355 goto fail; 61180ba2cbe9Sxc151355 } 6119a399b765Szf162725 wk[i].wk_class = class; 61200ba2cbe9Sxc151355 } 61210ba2cbe9Sxc151355 *keys = wk; 61220ba2cbe9Sxc151355 *key_countp = i; 61238002d411SSowmini Varadhan free(token); 61240ba2cbe9Sxc151355 return (0); 61250ba2cbe9Sxc151355 fail: 61260ba2cbe9Sxc151355 free(wk); 61278002d411SSowmini Varadhan free(token); 61280ba2cbe9Sxc151355 return (-1); 61290ba2cbe9Sxc151355 } 61300ba2cbe9Sxc151355 61310ba2cbe9Sxc151355 static void 61328d5c46e6Sam223141 do_connect_wifi(int argc, char **argv, const char *use) 61330ba2cbe9Sxc151355 { 61340ba2cbe9Sxc151355 int option; 6135f595a68aSyz147064 dladm_wlan_attr_t attr, *attrp; 6136f595a68aSyz147064 dladm_status_t status = DLADM_STATUS_OK; 6137f595a68aSyz147064 int timeout = DLADM_WLAN_CONNECT_TIMEOUT_DEFAULT; 6138d62bc4baSyz147064 datalink_id_t linkid = DATALINK_ALL_LINKID; 6139a399b765Szf162725 dladm_wlan_key_t *keys = NULL; 61400ba2cbe9Sxc151355 uint_t key_count = 0; 61410ba2cbe9Sxc151355 uint_t flags = 0; 6142f595a68aSyz147064 dladm_wlan_secmode_t keysecmode = DLADM_WLAN_SECMODE_NONE; 6143a399b765Szf162725 char buf[DLADM_STRSIZE]; 61440ba2cbe9Sxc151355 61450ba2cbe9Sxc151355 opterr = 0; 61460ba2cbe9Sxc151355 (void) memset(&attr, 0, sizeof (attr)); 61470ba2cbe9Sxc151355 while ((option = getopt_long(argc, argv, ":e:i:a:m:b:s:k:T:c", 61480ba2cbe9Sxc151355 wifi_longopts, NULL)) != -1) { 61490ba2cbe9Sxc151355 switch (option) { 61500ba2cbe9Sxc151355 case 'e': 6151f595a68aSyz147064 status = dladm_wlan_str2essid(optarg, &attr.wa_essid); 6152f595a68aSyz147064 if (status != DLADM_STATUS_OK) 615333343a97Smeem die("invalid ESSID '%s'", optarg); 615433343a97Smeem 6155f595a68aSyz147064 attr.wa_valid |= DLADM_WLAN_ATTR_ESSID; 61560ba2cbe9Sxc151355 /* 61570ba2cbe9Sxc151355 * Try to connect without doing a scan. 61580ba2cbe9Sxc151355 */ 6159f595a68aSyz147064 flags |= DLADM_WLAN_CONNECT_NOSCAN; 61600ba2cbe9Sxc151355 break; 61610ba2cbe9Sxc151355 case 'i': 6162f595a68aSyz147064 status = dladm_wlan_str2bssid(optarg, &attr.wa_bssid); 6163f595a68aSyz147064 if (status != DLADM_STATUS_OK) 616433343a97Smeem die("invalid BSSID %s", optarg); 616533343a97Smeem 6166f595a68aSyz147064 attr.wa_valid |= DLADM_WLAN_ATTR_BSSID; 61670ba2cbe9Sxc151355 break; 61680ba2cbe9Sxc151355 case 'a': 6169f595a68aSyz147064 status = dladm_wlan_str2auth(optarg, &attr.wa_auth); 6170f595a68aSyz147064 if (status != DLADM_STATUS_OK) 617133343a97Smeem die("invalid authentication mode '%s'", optarg); 617233343a97Smeem 6173f595a68aSyz147064 attr.wa_valid |= DLADM_WLAN_ATTR_AUTH; 61740ba2cbe9Sxc151355 break; 61750ba2cbe9Sxc151355 case 'm': 6176f595a68aSyz147064 status = dladm_wlan_str2mode(optarg, &attr.wa_mode); 6177f595a68aSyz147064 if (status != DLADM_STATUS_OK) 617833343a97Smeem die("invalid mode '%s'", optarg); 617933343a97Smeem 6180f595a68aSyz147064 attr.wa_valid |= DLADM_WLAN_ATTR_MODE; 61810ba2cbe9Sxc151355 break; 61820ba2cbe9Sxc151355 case 'b': 6183f595a68aSyz147064 if ((status = dladm_wlan_str2bsstype(optarg, 6184f595a68aSyz147064 &attr.wa_bsstype)) != DLADM_STATUS_OK) { 618533343a97Smeem die("invalid bsstype '%s'", optarg); 6186f595a68aSyz147064 } 618733343a97Smeem 6188f595a68aSyz147064 attr.wa_valid |= DLADM_WLAN_ATTR_BSSTYPE; 61890ba2cbe9Sxc151355 break; 61900ba2cbe9Sxc151355 case 's': 6191f595a68aSyz147064 if ((status = dladm_wlan_str2secmode(optarg, 6192f595a68aSyz147064 &attr.wa_secmode)) != DLADM_STATUS_OK) { 619333343a97Smeem die("invalid security mode '%s'", optarg); 6194f595a68aSyz147064 } 619533343a97Smeem 6196f595a68aSyz147064 attr.wa_valid |= DLADM_WLAN_ATTR_SECMODE; 61970ba2cbe9Sxc151355 break; 61980ba2cbe9Sxc151355 case 'k': 6199a399b765Szf162725 if (parse_wlan_keys(optarg, &keys, &key_count) < 0) 620033343a97Smeem die("invalid key(s) '%s'", optarg); 620133343a97Smeem 6202a399b765Szf162725 if (keys[0].wk_class == DLADM_SECOBJ_CLASS_WEP) 6203f595a68aSyz147064 keysecmode = DLADM_WLAN_SECMODE_WEP; 6204a399b765Szf162725 else 6205a399b765Szf162725 keysecmode = DLADM_WLAN_SECMODE_WPA; 62060ba2cbe9Sxc151355 break; 62070ba2cbe9Sxc151355 case 'T': 62080ba2cbe9Sxc151355 if (strcasecmp(optarg, "forever") == 0) { 62090ba2cbe9Sxc151355 timeout = -1; 62100ba2cbe9Sxc151355 break; 62110ba2cbe9Sxc151355 } 621233343a97Smeem if (!str2int(optarg, &timeout) || timeout < 0) 621333343a97Smeem die("invalid timeout value '%s'", optarg); 62140ba2cbe9Sxc151355 break; 62150ba2cbe9Sxc151355 case 'c': 6216f595a68aSyz147064 flags |= DLADM_WLAN_CONNECT_CREATEIBSS; 6217a399b765Szf162725 flags |= DLADM_WLAN_CONNECT_CREATEIBSS; 62180ba2cbe9Sxc151355 break; 62190ba2cbe9Sxc151355 default: 62208d5c46e6Sam223141 die_opterr(optopt, option, use); 62210ba2cbe9Sxc151355 break; 62220ba2cbe9Sxc151355 } 62230ba2cbe9Sxc151355 } 62240ba2cbe9Sxc151355 6225f595a68aSyz147064 if (keysecmode == DLADM_WLAN_SECMODE_NONE) { 6226a399b765Szf162725 if ((attr.wa_valid & DLADM_WLAN_ATTR_SECMODE) != 0) { 6227a399b765Szf162725 die("key required for security mode '%s'", 6228a399b765Szf162725 dladm_wlan_secmode2str(&attr.wa_secmode, buf)); 6229a399b765Szf162725 } 62300ba2cbe9Sxc151355 } else { 6231f595a68aSyz147064 if ((attr.wa_valid & DLADM_WLAN_ATTR_SECMODE) != 0 && 623233343a97Smeem attr.wa_secmode != keysecmode) 623333343a97Smeem die("incompatible -s and -k options"); 6234f595a68aSyz147064 attr.wa_valid |= DLADM_WLAN_ATTR_SECMODE; 6235a399b765Szf162725 attr.wa_secmode = keysecmode; 6236a399b765Szf162725 } 62370ba2cbe9Sxc151355 6238d62bc4baSyz147064 if (optind == (argc - 1)) { 62394ac67f02SAnurag S. Maskey if ((status = dladm_name2info(handle, argv[optind], &linkid, 62404ac67f02SAnurag S. Maskey NULL, NULL, NULL)) != DLADM_STATUS_OK) { 6241d62bc4baSyz147064 die_dlerr(status, "link %s is not valid", argv[optind]); 6242d62bc4baSyz147064 } 6243d62bc4baSyz147064 } else if (optind != argc) { 62440ba2cbe9Sxc151355 usage(); 6245d62bc4baSyz147064 } 62460ba2cbe9Sxc151355 6247d62bc4baSyz147064 if (linkid == DATALINK_ALL_LINKID) { 62480ba2cbe9Sxc151355 wlan_count_attr_t wcattr; 62490ba2cbe9Sxc151355 6250d62bc4baSyz147064 wcattr.wc_linkid = DATALINK_INVALID_LINKID; 62510ba2cbe9Sxc151355 wcattr.wc_count = 0; 62524ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(do_count_wlan, handle, &wcattr, 6253b509e89bSRishi Srivatsavai DATALINK_CLASS_PHYS | DATALINK_CLASS_SIMNET, 6254b509e89bSRishi Srivatsavai DL_WIFI, DLADM_OPT_ACTIVE); 62550ba2cbe9Sxc151355 if (wcattr.wc_count == 0) { 625633343a97Smeem die("no wifi links are available"); 62570ba2cbe9Sxc151355 } else if (wcattr.wc_count > 1) { 625833343a97Smeem die("link name is required when more than one wifi " 625933343a97Smeem "link is available"); 62600ba2cbe9Sxc151355 } 6261d62bc4baSyz147064 linkid = wcattr.wc_linkid; 62620ba2cbe9Sxc151355 } 62630ba2cbe9Sxc151355 attrp = (attr.wa_valid == 0) ? NULL : &attr; 626433343a97Smeem again: 62654ac67f02SAnurag S. Maskey if ((status = dladm_wlan_connect(handle, linkid, attrp, timeout, keys, 6266f595a68aSyz147064 key_count, flags)) != DLADM_STATUS_OK) { 6267f595a68aSyz147064 if ((flags & DLADM_WLAN_CONNECT_NOSCAN) != 0) { 62680ba2cbe9Sxc151355 /* 626933343a97Smeem * Try again with scanning and filtering. 62700ba2cbe9Sxc151355 */ 6271f595a68aSyz147064 flags &= ~DLADM_WLAN_CONNECT_NOSCAN; 627233343a97Smeem goto again; 62730ba2cbe9Sxc151355 } 627433343a97Smeem 6275f595a68aSyz147064 if (status == DLADM_STATUS_NOTFOUND) { 62760ba2cbe9Sxc151355 if (attr.wa_valid == 0) { 627733343a97Smeem die("no wifi networks are available"); 62780ba2cbe9Sxc151355 } else { 627933343a97Smeem die("no wifi networks with the specified " 628033343a97Smeem "criteria are available"); 62810ba2cbe9Sxc151355 } 62820ba2cbe9Sxc151355 } 6283d62bc4baSyz147064 die_dlerr(status, "cannot connect"); 62840ba2cbe9Sxc151355 } 62850ba2cbe9Sxc151355 free(keys); 62860ba2cbe9Sxc151355 } 62870ba2cbe9Sxc151355 62880ba2cbe9Sxc151355 /* ARGSUSED */ 6289d62bc4baSyz147064 static int 62904ac67f02SAnurag S. Maskey do_all_disconnect_wifi(dladm_handle_t dh, datalink_id_t linkid, void *arg) 62910ba2cbe9Sxc151355 { 6292f595a68aSyz147064 dladm_status_t status; 62930ba2cbe9Sxc151355 62944ac67f02SAnurag S. Maskey status = dladm_wlan_disconnect(dh, linkid); 6295f595a68aSyz147064 if (status != DLADM_STATUS_OK) 6296d62bc4baSyz147064 warn_dlerr(status, "cannot disconnect link"); 629733343a97Smeem 6298d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 62990ba2cbe9Sxc151355 } 63000ba2cbe9Sxc151355 63010ba2cbe9Sxc151355 static void 63028d5c46e6Sam223141 do_disconnect_wifi(int argc, char **argv, const char *use) 63030ba2cbe9Sxc151355 { 63040ba2cbe9Sxc151355 int option; 6305d62bc4baSyz147064 datalink_id_t linkid = DATALINK_ALL_LINKID; 63060ba2cbe9Sxc151355 boolean_t all_links = B_FALSE; 6307f595a68aSyz147064 dladm_status_t status; 63080ba2cbe9Sxc151355 wlan_count_attr_t wcattr; 63090ba2cbe9Sxc151355 63100ba2cbe9Sxc151355 opterr = 0; 63110ba2cbe9Sxc151355 while ((option = getopt_long(argc, argv, ":a", 63120ba2cbe9Sxc151355 wifi_longopts, NULL)) != -1) { 63130ba2cbe9Sxc151355 switch (option) { 63140ba2cbe9Sxc151355 case 'a': 63150ba2cbe9Sxc151355 all_links = B_TRUE; 63160ba2cbe9Sxc151355 break; 63170ba2cbe9Sxc151355 default: 63188d5c46e6Sam223141 die_opterr(optopt, option, use); 63190ba2cbe9Sxc151355 break; 63200ba2cbe9Sxc151355 } 63210ba2cbe9Sxc151355 } 63220ba2cbe9Sxc151355 6323d62bc4baSyz147064 if (optind == (argc - 1)) { 63244ac67f02SAnurag S. Maskey if ((status = dladm_name2info(handle, argv[optind], &linkid, 63254ac67f02SAnurag S. Maskey NULL, NULL, NULL)) != DLADM_STATUS_OK) { 6326d62bc4baSyz147064 die_dlerr(status, "link %s is not valid", argv[optind]); 6327d62bc4baSyz147064 } 6328d62bc4baSyz147064 } else if (optind != argc) { 63290ba2cbe9Sxc151355 usage(); 6330d62bc4baSyz147064 } 63310ba2cbe9Sxc151355 6332d62bc4baSyz147064 if (linkid == DATALINK_ALL_LINKID) { 63330ba2cbe9Sxc151355 if (!all_links) { 6334d62bc4baSyz147064 wcattr.wc_linkid = linkid; 63350ba2cbe9Sxc151355 wcattr.wc_count = 0; 63364ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(do_count_wlan, handle, 6337b509e89bSRishi Srivatsavai &wcattr, 6338b509e89bSRishi Srivatsavai DATALINK_CLASS_PHYS | DATALINK_CLASS_SIMNET, 6339b509e89bSRishi Srivatsavai DL_WIFI, DLADM_OPT_ACTIVE); 63400ba2cbe9Sxc151355 if (wcattr.wc_count == 0) { 634133343a97Smeem die("no wifi links are available"); 63420ba2cbe9Sxc151355 } else if (wcattr.wc_count > 1) { 634333343a97Smeem die("link name is required when more than " 634433343a97Smeem "one wifi link is available"); 63450ba2cbe9Sxc151355 } 6346d62bc4baSyz147064 linkid = wcattr.wc_linkid; 63470ba2cbe9Sxc151355 } else { 6348d62bc4baSyz147064 (void) dladm_walk_datalink_id(do_all_disconnect_wifi, 6349b509e89bSRishi Srivatsavai handle, NULL, 6350b509e89bSRishi Srivatsavai DATALINK_CLASS_PHYS | DATALINK_CLASS_SIMNET, 6351b509e89bSRishi Srivatsavai DL_WIFI, DLADM_OPT_ACTIVE); 63520ba2cbe9Sxc151355 return; 63530ba2cbe9Sxc151355 } 63540ba2cbe9Sxc151355 } 63554ac67f02SAnurag S. Maskey status = dladm_wlan_disconnect(handle, linkid); 6356f595a68aSyz147064 if (status != DLADM_STATUS_OK) 6357d62bc4baSyz147064 die_dlerr(status, "cannot disconnect"); 63580ba2cbe9Sxc151355 } 63590ba2cbe9Sxc151355 63600ba2cbe9Sxc151355 static void 6361d62bc4baSyz147064 print_linkprop(datalink_id_t linkid, show_linkprop_state_t *statep, 63624ac67f02SAnurag S. Maskey const char *propname, dladm_prop_type_t type, const char *format, 63634ac67f02SAnurag S. Maskey char **pptr) 63640ba2cbe9Sxc151355 { 63650ba2cbe9Sxc151355 int i; 63660ba2cbe9Sxc151355 char *ptr, *lim; 63670ba2cbe9Sxc151355 char buf[DLADM_STRSIZE]; 6368da14cebeSEric Cheng char *unknown = "--", *notsup = ""; 63690ba2cbe9Sxc151355 char **propvals = statep->ls_propvals; 6370d62bc4baSyz147064 uint_t valcnt = DLADM_MAX_PROP_VALCNT; 63710ba2cbe9Sxc151355 dladm_status_t status; 63720ba2cbe9Sxc151355 63734ac67f02SAnurag S. Maskey status = dladm_get_linkprop(handle, linkid, type, propname, propvals, 63744ac67f02SAnurag S. Maskey &valcnt); 63750ba2cbe9Sxc151355 if (status != DLADM_STATUS_OK) { 6376f595a68aSyz147064 if (status == DLADM_STATUS_TEMPONLY) { 6377d62bc4baSyz147064 if (type == DLADM_PROP_VAL_MODIFIABLE && 6378d62bc4baSyz147064 statep->ls_persist) { 6379d62bc4baSyz147064 valcnt = 1; 6380d62bc4baSyz147064 propvals = &unknown; 6381d62bc4baSyz147064 } else { 6382f595a68aSyz147064 statep->ls_status = status; 6383e7801d59Ssowmini statep->ls_retstatus = status; 6384f595a68aSyz147064 return; 6385d62bc4baSyz147064 } 6386f595a68aSyz147064 } else if (status == DLADM_STATUS_NOTSUP || 6387f595a68aSyz147064 statep->ls_persist) { 63880ba2cbe9Sxc151355 valcnt = 1; 6389afdda45fSVasumathi Sundaram - Sun Microsystems if (type == DLADM_PROP_VAL_CURRENT || 6390afdda45fSVasumathi Sundaram - Sun Microsystems type == DLADM_PROP_VAL_PERM) 63910ba2cbe9Sxc151355 propvals = &unknown; 63920ba2cbe9Sxc151355 else 63930ba2cbe9Sxc151355 propvals = ¬sup; 6394149b7eb2SSowmini Varadhan } else if (status == DLADM_STATUS_NOTDEFINED) { 6395149b7eb2SSowmini Varadhan propvals = ¬sup; /* STR_UNDEF_VAL */ 63960ba2cbe9Sxc151355 } else { 6397e7801d59Ssowmini if (statep->ls_proplist && 6398e7801d59Ssowmini statep->ls_status == DLADM_STATUS_OK) { 6399f595a68aSyz147064 warn_dlerr(status, 6400f595a68aSyz147064 "cannot get link property '%s' for %s", 6401f595a68aSyz147064 propname, statep->ls_link); 6402d62bc4baSyz147064 } 6403e7801d59Ssowmini statep->ls_status = status; 6404e7801d59Ssowmini statep->ls_retstatus = status; 6405f595a68aSyz147064 return; 64060ba2cbe9Sxc151355 } 64070ba2cbe9Sxc151355 } 64080ba2cbe9Sxc151355 6409e7801d59Ssowmini statep->ls_status = DLADM_STATUS_OK; 6410e7801d59Ssowmini 641125ec3e3dSEric Cheng buf[0] = '\0'; 64120ba2cbe9Sxc151355 ptr = buf; 64130ba2cbe9Sxc151355 lim = buf + DLADM_STRSIZE; 64140ba2cbe9Sxc151355 for (i = 0; i < valcnt; i++) { 64158002d411SSowmini Varadhan if (propvals[i][0] == '\0' && !statep->ls_parsable) 64168002d411SSowmini Varadhan ptr += snprintf(ptr, lim - ptr, "--,"); 64170ba2cbe9Sxc151355 else 64180ba2cbe9Sxc151355 ptr += snprintf(ptr, lim - ptr, "%s,", propvals[i]); 64190ba2cbe9Sxc151355 if (ptr >= lim) 64200ba2cbe9Sxc151355 break; 64210ba2cbe9Sxc151355 } 64220ba2cbe9Sxc151355 if (valcnt > 0) 64230ba2cbe9Sxc151355 buf[strlen(buf) - 1] = '\0'; 64240ba2cbe9Sxc151355 64250ba2cbe9Sxc151355 lim = statep->ls_line + MAX_PROP_LINE; 64268002d411SSowmini Varadhan if (statep->ls_parsable) { 64270ba2cbe9Sxc151355 *pptr += snprintf(*pptr, lim - *pptr, 6428e7801d59Ssowmini "%s", buf); 64290ba2cbe9Sxc151355 } else { 64300ba2cbe9Sxc151355 *pptr += snprintf(*pptr, lim - *pptr, format, buf); 64310ba2cbe9Sxc151355 } 64320ba2cbe9Sxc151355 } 64330ba2cbe9Sxc151355 64348002d411SSowmini Varadhan static boolean_t 64358002d411SSowmini Varadhan print_linkprop_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize) 6436e7801d59Ssowmini { 64378002d411SSowmini Varadhan linkprop_args_t *arg = ofarg->ofmt_cbarg; 6438e7801d59Ssowmini char *propname = arg->ls_propname; 6439e7801d59Ssowmini show_linkprop_state_t *statep = arg->ls_state; 6440e7801d59Ssowmini char *ptr = statep->ls_line; 6441e7801d59Ssowmini char *lim = ptr + MAX_PROP_LINE; 6442e7801d59Ssowmini datalink_id_t linkid = arg->ls_linkid; 6443e7801d59Ssowmini 64448002d411SSowmini Varadhan switch (ofarg->ofmt_id) { 6445e7801d59Ssowmini case LINKPROP_LINK: 6446e7801d59Ssowmini (void) snprintf(ptr, lim - ptr, "%s", statep->ls_link); 6447e7801d59Ssowmini break; 6448e7801d59Ssowmini case LINKPROP_PROPERTY: 6449e7801d59Ssowmini (void) snprintf(ptr, lim - ptr, "%s", propname); 6450e7801d59Ssowmini break; 6451e7801d59Ssowmini case LINKPROP_VALUE: 6452e7801d59Ssowmini print_linkprop(linkid, statep, propname, 6453e7801d59Ssowmini statep->ls_persist ? DLADM_PROP_VAL_PERSISTENT : 6454e7801d59Ssowmini DLADM_PROP_VAL_CURRENT, "%s", &ptr); 6455e7801d59Ssowmini /* 6456e7801d59Ssowmini * If we failed to query the link property, for example, query 6457e7801d59Ssowmini * the persistent value of a non-persistable link property, 6458e7801d59Ssowmini * simply skip the output. 6459e7801d59Ssowmini */ 6460e7801d59Ssowmini if (statep->ls_status != DLADM_STATUS_OK) 6461e7801d59Ssowmini goto skip; 6462e7801d59Ssowmini ptr = statep->ls_line; 6463e7801d59Ssowmini break; 6464afdda45fSVasumathi Sundaram - Sun Microsystems case LINKPROP_PERM: 6465afdda45fSVasumathi Sundaram - Sun Microsystems print_linkprop(linkid, statep, propname, 6466afdda45fSVasumathi Sundaram - Sun Microsystems DLADM_PROP_VAL_PERM, "%s", &ptr); 6467afdda45fSVasumathi Sundaram - Sun Microsystems if (statep->ls_status != DLADM_STATUS_OK) 6468afdda45fSVasumathi Sundaram - Sun Microsystems goto skip; 6469afdda45fSVasumathi Sundaram - Sun Microsystems ptr = statep->ls_line; 6470afdda45fSVasumathi Sundaram - Sun Microsystems break; 6471e7801d59Ssowmini case LINKPROP_DEFAULT: 6472e7801d59Ssowmini print_linkprop(linkid, statep, propname, 6473e7801d59Ssowmini DLADM_PROP_VAL_DEFAULT, "%s", &ptr); 6474e7801d59Ssowmini if (statep->ls_status != DLADM_STATUS_OK) 6475e7801d59Ssowmini goto skip; 6476e7801d59Ssowmini ptr = statep->ls_line; 6477e7801d59Ssowmini break; 6478e7801d59Ssowmini case LINKPROP_POSSIBLE: 6479e7801d59Ssowmini print_linkprop(linkid, statep, propname, 6480e7801d59Ssowmini DLADM_PROP_VAL_MODIFIABLE, "%s ", &ptr); 6481e7801d59Ssowmini if (statep->ls_status != DLADM_STATUS_OK) 6482e7801d59Ssowmini goto skip; 6483e7801d59Ssowmini ptr = statep->ls_line; 6484e7801d59Ssowmini break; 6485e7801d59Ssowmini default: 6486e7801d59Ssowmini die("invalid input"); 6487e7801d59Ssowmini break; 6488e7801d59Ssowmini } 64898002d411SSowmini Varadhan (void) strlcpy(buf, ptr, bufsize); 64908002d411SSowmini Varadhan return (B_TRUE); 6491e7801d59Ssowmini skip: 64928002d411SSowmini Varadhan return ((statep->ls_status == DLADM_STATUS_OK) ? 64938002d411SSowmini Varadhan B_TRUE : B_FALSE); 6494e7801d59Ssowmini } 6495e7801d59Ssowmini 6496bcb5c89dSSowmini Varadhan static boolean_t 6497bcb5c89dSSowmini Varadhan linkprop_is_supported(datalink_id_t linkid, const char *propname, 6498bcb5c89dSSowmini Varadhan show_linkprop_state_t *statep) 6499bcb5c89dSSowmini Varadhan { 6500bcb5c89dSSowmini Varadhan dladm_status_t status; 6501bcb5c89dSSowmini Varadhan uint_t valcnt = DLADM_MAX_PROP_VALCNT; 6502bcb5c89dSSowmini Varadhan 65034784fcbdSSowmini Varadhan /* if used with -p flag, always print output */ 65044784fcbdSSowmini Varadhan if (statep->ls_proplist != NULL) 65054784fcbdSSowmini Varadhan return (B_TRUE); 65064784fcbdSSowmini Varadhan 65074ac67f02SAnurag S. Maskey status = dladm_get_linkprop(handle, linkid, DLADM_PROP_VAL_DEFAULT, 6508bcb5c89dSSowmini Varadhan propname, statep->ls_propvals, &valcnt); 6509bcb5c89dSSowmini Varadhan 6510149b7eb2SSowmini Varadhan if (status == DLADM_STATUS_OK) 6511149b7eb2SSowmini Varadhan return (B_TRUE); 6512149b7eb2SSowmini Varadhan 6513149b7eb2SSowmini Varadhan /* 6514149b7eb2SSowmini Varadhan * A system wide default value is not available for the 6515149b7eb2SSowmini Varadhan * property. Check if current value can be retrieved. 6516149b7eb2SSowmini Varadhan */ 65174ac67f02SAnurag S. Maskey status = dladm_get_linkprop(handle, linkid, DLADM_PROP_VAL_CURRENT, 6518149b7eb2SSowmini Varadhan propname, statep->ls_propvals, &valcnt); 6519149b7eb2SSowmini Varadhan 6520149b7eb2SSowmini Varadhan return (status == DLADM_STATUS_OK); 6521bcb5c89dSSowmini Varadhan } 6522bcb5c89dSSowmini Varadhan 65234ac67f02SAnurag S. Maskey /* ARGSUSED */ 6524d62bc4baSyz147064 static int 65254ac67f02SAnurag S. Maskey show_linkprop(dladm_handle_t dh, datalink_id_t linkid, const char *propname, 65264ac67f02SAnurag S. Maskey void *arg) 65270ba2cbe9Sxc151355 { 65280ba2cbe9Sxc151355 show_linkprop_state_t *statep = arg; 6529e7801d59Ssowmini linkprop_args_t ls_arg; 65300ba2cbe9Sxc151355 6531e7801d59Ssowmini bzero(&ls_arg, sizeof (ls_arg)); 6532e7801d59Ssowmini ls_arg.ls_state = statep; 6533e7801d59Ssowmini ls_arg.ls_propname = (char *)propname; 6534e7801d59Ssowmini ls_arg.ls_linkid = linkid; 65350ba2cbe9Sxc151355 653662ee1d25SArtem Kachitchkine /* 653762ee1d25SArtem Kachitchkine * This will need to be fixed when kernel interfaces are added 653862ee1d25SArtem Kachitchkine * to enable walking of all known private properties. For now, 653962ee1d25SArtem Kachitchkine * we are limited to walking persistent private properties only. 654062ee1d25SArtem Kachitchkine */ 654162ee1d25SArtem Kachitchkine if ((propname[0] == '_') && !statep->ls_persist && 654262ee1d25SArtem Kachitchkine (statep->ls_proplist == NULL)) 654362ee1d25SArtem Kachitchkine return (DLADM_WALK_CONTINUE); 65448002d411SSowmini Varadhan if (!statep->ls_parsable && 6545149b7eb2SSowmini Varadhan !linkprop_is_supported(linkid, propname, statep)) 6546bcb5c89dSSowmini Varadhan return (DLADM_WALK_CONTINUE); 6547bcb5c89dSSowmini Varadhan 65488002d411SSowmini Varadhan ofmt_print(statep->ls_ofmt, &ls_arg); 6549e7801d59Ssowmini 6550d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 65510ba2cbe9Sxc151355 } 65520ba2cbe9Sxc151355 65530ba2cbe9Sxc151355 static void 65548d5c46e6Sam223141 do_show_linkprop(int argc, char **argv, const char *use) 65550ba2cbe9Sxc151355 { 6556f4b3ec61Sdh155122 int option; 655763a6526dSMichael Lim char propstr[DLADM_STRSIZE]; 6558da14cebeSEric Cheng dladm_arg_list_t *proplist = NULL; 6559d62bc4baSyz147064 datalink_id_t linkid = DATALINK_ALL_LINKID; 65600ba2cbe9Sxc151355 show_linkprop_state_t state; 6561d62bc4baSyz147064 uint32_t flags = DLADM_OPT_ACTIVE; 6562d62bc4baSyz147064 dladm_status_t status; 6563e7801d59Ssowmini char *fields_str = NULL; 65648002d411SSowmini Varadhan ofmt_handle_t ofmt; 65658002d411SSowmini Varadhan ofmt_status_t oferr; 65668002d411SSowmini Varadhan uint_t ofmtflags = 0; 65670ba2cbe9Sxc151355 656863a6526dSMichael Lim bzero(propstr, DLADM_STRSIZE); 65690ba2cbe9Sxc151355 opterr = 0; 65700ba2cbe9Sxc151355 state.ls_propvals = NULL; 65710ba2cbe9Sxc151355 state.ls_line = NULL; 65728002d411SSowmini Varadhan state.ls_parsable = B_FALSE; 65730ba2cbe9Sxc151355 state.ls_persist = B_FALSE; 65740ba2cbe9Sxc151355 state.ls_header = B_TRUE; 6575e7801d59Ssowmini state.ls_retstatus = DLADM_STATUS_OK; 657663a6526dSMichael Lim 6577e7801d59Ssowmini while ((option = getopt_long(argc, argv, ":p:cPo:", 65780ba2cbe9Sxc151355 prop_longopts, NULL)) != -1) { 65790ba2cbe9Sxc151355 switch (option) { 65800ba2cbe9Sxc151355 case 'p': 658163a6526dSMichael Lim (void) strlcat(propstr, optarg, DLADM_STRSIZE); 658263a6526dSMichael Lim if (strlcat(propstr, ",", DLADM_STRSIZE) >= 658363a6526dSMichael Lim DLADM_STRSIZE) 658463a6526dSMichael Lim die("property list too long '%s'", propstr); 65850ba2cbe9Sxc151355 break; 65860ba2cbe9Sxc151355 case 'c': 65878002d411SSowmini Varadhan state.ls_parsable = B_TRUE; 65880ba2cbe9Sxc151355 break; 65890ba2cbe9Sxc151355 case 'P': 65900ba2cbe9Sxc151355 state.ls_persist = B_TRUE; 6591d62bc4baSyz147064 flags = DLADM_OPT_PERSIST; 65920ba2cbe9Sxc151355 break; 6593e7801d59Ssowmini case 'o': 6594e7801d59Ssowmini fields_str = optarg; 6595e7801d59Ssowmini break; 65960ba2cbe9Sxc151355 default: 65978d5c46e6Sam223141 die_opterr(optopt, option, use); 65980ba2cbe9Sxc151355 break; 65990ba2cbe9Sxc151355 } 66000ba2cbe9Sxc151355 } 66010ba2cbe9Sxc151355 6602d62bc4baSyz147064 if (optind == (argc - 1)) { 66034ac67f02SAnurag S. Maskey if ((status = dladm_name2info(handle, argv[optind], &linkid, 66044ac67f02SAnurag S. Maskey NULL, NULL, NULL)) != DLADM_STATUS_OK) { 6605d62bc4baSyz147064 die_dlerr(status, "link %s is not valid", argv[optind]); 6606d62bc4baSyz147064 } 6607d62bc4baSyz147064 } else if (optind != argc) { 66080ba2cbe9Sxc151355 usage(); 6609d62bc4baSyz147064 } 66100ba2cbe9Sxc151355 661163a6526dSMichael Lim if (dladm_parse_link_props(propstr, &proplist, B_TRUE) 661263a6526dSMichael Lim != DLADM_STATUS_OK) 661363a6526dSMichael Lim die("invalid link properties specified"); 6614f4b3ec61Sdh155122 state.ls_proplist = proplist; 6615f595a68aSyz147064 state.ls_status = DLADM_STATUS_OK; 6616f4b3ec61Sdh155122 66178002d411SSowmini Varadhan if (state.ls_parsable) 66188002d411SSowmini Varadhan ofmtflags |= OFMT_PARSABLE; 661925ec3e3dSEric Cheng else 662025ec3e3dSEric Cheng ofmtflags |= OFMT_WRAP; 662125ec3e3dSEric Cheng 66228002d411SSowmini Varadhan oferr = ofmt_open(fields_str, linkprop_fields, ofmtflags, 0, &ofmt); 66238002d411SSowmini Varadhan dladm_ofmt_check(oferr, state.ls_parsable, ofmt); 66248002d411SSowmini Varadhan state.ls_ofmt = ofmt; 6625e7801d59Ssowmini 6626d62bc4baSyz147064 if (linkid == DATALINK_ALL_LINKID) { 66274ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(show_linkprop_onelink, handle, 66284ac67f02SAnurag S. Maskey &state, DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE, flags); 6629f4b3ec61Sdh155122 } else { 66304ac67f02SAnurag S. Maskey (void) show_linkprop_onelink(handle, linkid, &state); 6631f4b3ec61Sdh155122 } 66328002d411SSowmini Varadhan ofmt_close(ofmt); 6633da14cebeSEric Cheng dladm_free_props(proplist); 6634f595a68aSyz147064 66354ac67f02SAnurag S. Maskey if (state.ls_retstatus != DLADM_STATUS_OK) { 66364ac67f02SAnurag S. Maskey dladm_close(handle); 6637f595a68aSyz147064 exit(EXIT_FAILURE); 6638f4b3ec61Sdh155122 } 66394ac67f02SAnurag S. Maskey } 6640f4b3ec61Sdh155122 6641d62bc4baSyz147064 static int 66424ac67f02SAnurag S. Maskey show_linkprop_onelink(dladm_handle_t hdl, datalink_id_t linkid, void *arg) 6643f4b3ec61Sdh155122 { 6644948f2876Sss150715 int i; 6645f4b3ec61Sdh155122 char *buf; 6646d62bc4baSyz147064 uint32_t flags; 6647da14cebeSEric Cheng dladm_arg_list_t *proplist = NULL; 6648d62bc4baSyz147064 show_linkprop_state_t *statep = arg; 6649d62bc4baSyz147064 dlpi_handle_t dh = NULL; 6650f4b3ec61Sdh155122 6651d62bc4baSyz147064 statep->ls_status = DLADM_STATUS_OK; 6652d62bc4baSyz147064 66534ac67f02SAnurag S. Maskey if (dladm_datalink_id2info(hdl, linkid, &flags, NULL, NULL, 66544ac67f02SAnurag S. Maskey statep->ls_link, MAXLINKNAMELEN) != DLADM_STATUS_OK) { 6655d62bc4baSyz147064 statep->ls_status = DLADM_STATUS_NOTFOUND; 6656d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 6657d62bc4baSyz147064 } 6658d62bc4baSyz147064 6659d62bc4baSyz147064 if ((statep->ls_persist && !(flags & DLADM_OPT_PERSIST)) || 6660d62bc4baSyz147064 (!statep->ls_persist && !(flags & DLADM_OPT_ACTIVE))) { 6661d62bc4baSyz147064 statep->ls_status = DLADM_STATUS_BADARG; 6662d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 6663d62bc4baSyz147064 } 6664d62bc4baSyz147064 6665f4b3ec61Sdh155122 proplist = statep->ls_proplist; 66660ba2cbe9Sxc151355 66670ba2cbe9Sxc151355 /* 66680ba2cbe9Sxc151355 * When some WiFi links are opened for the first time, their hardware 66690ba2cbe9Sxc151355 * automatically scans for APs and does other slow operations. Thus, 66700ba2cbe9Sxc151355 * if there are no open links, the retrieval of link properties 66710ba2cbe9Sxc151355 * (below) will proceed slowly unless we hold the link open. 6672d62bc4baSyz147064 * 6673d62bc4baSyz147064 * Note that failure of dlpi_open() does not necessarily mean invalid 6674d62bc4baSyz147064 * link properties, because dlpi_open() may fail because of incorrect 6675d62bc4baSyz147064 * autopush configuration. Therefore, we ingore the return value of 6676d62bc4baSyz147064 * dlpi_open(). 66770ba2cbe9Sxc151355 */ 6678d62bc4baSyz147064 if (!statep->ls_persist) 6679d62bc4baSyz147064 (void) dlpi_open(statep->ls_link, &dh, 0); 66800ba2cbe9Sxc151355 6681d62bc4baSyz147064 buf = malloc((sizeof (char *) + DLADM_PROP_VAL_MAX) * 6682d62bc4baSyz147064 DLADM_MAX_PROP_VALCNT + MAX_PROP_LINE); 668333343a97Smeem if (buf == NULL) 668433343a97Smeem die("insufficient memory"); 668533343a97Smeem 6686f4b3ec61Sdh155122 statep->ls_propvals = (char **)(void *)buf; 6687d62bc4baSyz147064 for (i = 0; i < DLADM_MAX_PROP_VALCNT; i++) { 6688d62bc4baSyz147064 statep->ls_propvals[i] = buf + 6689d62bc4baSyz147064 sizeof (char *) * DLADM_MAX_PROP_VALCNT + 66900ba2cbe9Sxc151355 i * DLADM_PROP_VAL_MAX; 66910ba2cbe9Sxc151355 } 6692f4b3ec61Sdh155122 statep->ls_line = buf + 6693d62bc4baSyz147064 (sizeof (char *) + DLADM_PROP_VAL_MAX) * DLADM_MAX_PROP_VALCNT; 66940ba2cbe9Sxc151355 66950ba2cbe9Sxc151355 if (proplist != NULL) { 6696da14cebeSEric Cheng for (i = 0; i < proplist->al_count; i++) { 66974ac67f02SAnurag S. Maskey (void) show_linkprop(hdl, linkid, 6698da14cebeSEric Cheng proplist->al_info[i].ai_name, statep); 66990ba2cbe9Sxc151355 } 6700d62bc4baSyz147064 } else { 67014ac67f02SAnurag S. Maskey (void) dladm_walk_linkprop(hdl, linkid, statep, 67024ac67f02SAnurag S. Maskey show_linkprop); 6703d62bc4baSyz147064 } 6704d62bc4baSyz147064 if (dh != NULL) 6705948f2876Sss150715 dlpi_close(dh); 67060ba2cbe9Sxc151355 free(buf); 6707d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 67080ba2cbe9Sxc151355 } 67090ba2cbe9Sxc151355 6710da14cebeSEric Cheng static int 67114ac67f02SAnurag S. Maskey reset_one_linkprop(dladm_handle_t dh, datalink_id_t linkid, 67124ac67f02SAnurag S. Maskey const char *propname, void *arg) 6713da14cebeSEric Cheng { 6714da14cebeSEric Cheng set_linkprop_state_t *statep = arg; 6715da14cebeSEric Cheng dladm_status_t status; 6716da14cebeSEric Cheng 67174ac67f02SAnurag S. Maskey status = dladm_set_linkprop(dh, linkid, propname, NULL, 0, 67184eaa4710SRishi Srivatsavai DLADM_OPT_ACTIVE | (statep->ls_temp ? 0 : DLADM_OPT_PERSIST)); 67190b8f0546SSowmini Varadhan if (status != DLADM_STATUS_OK && 67200b8f0546SSowmini Varadhan status != DLADM_STATUS_PROPRDONLY && 67210b8f0546SSowmini Varadhan status != DLADM_STATUS_NOTSUP) { 6722da14cebeSEric Cheng warn_dlerr(status, "cannot reset link property '%s' on '%s'", 6723da14cebeSEric Cheng propname, statep->ls_name); 6724da14cebeSEric Cheng statep->ls_status = status; 67254eaa4710SRishi Srivatsavai } 6726da14cebeSEric Cheng 6727da14cebeSEric Cheng return (DLADM_WALK_CONTINUE); 6728da14cebeSEric Cheng } 6729da14cebeSEric Cheng 67300ba2cbe9Sxc151355 static void 67318d5c46e6Sam223141 set_linkprop(int argc, char **argv, boolean_t reset, const char *use) 67320ba2cbe9Sxc151355 { 67330ba2cbe9Sxc151355 int i, option; 67340ba2cbe9Sxc151355 char errmsg[DLADM_STRSIZE]; 6735d62bc4baSyz147064 char *altroot = NULL; 6736d62bc4baSyz147064 datalink_id_t linkid; 67370ba2cbe9Sxc151355 boolean_t temp = B_FALSE; 67380ba2cbe9Sxc151355 dladm_status_t status = DLADM_STATUS_OK; 673963a6526dSMichael Lim char propstr[DLADM_STRSIZE]; 6740da14cebeSEric Cheng dladm_arg_list_t *proplist = NULL; 67410ba2cbe9Sxc151355 67420ba2cbe9Sxc151355 opterr = 0; 674363a6526dSMichael Lim bzero(propstr, DLADM_STRSIZE); 674463a6526dSMichael Lim 67450ba2cbe9Sxc151355 while ((option = getopt_long(argc, argv, ":p:R:t", 67460ba2cbe9Sxc151355 prop_longopts, NULL)) != -1) { 67470ba2cbe9Sxc151355 switch (option) { 67480ba2cbe9Sxc151355 case 'p': 674963a6526dSMichael Lim (void) strlcat(propstr, optarg, DLADM_STRSIZE); 675063a6526dSMichael Lim if (strlcat(propstr, ",", DLADM_STRSIZE) >= 675163a6526dSMichael Lim DLADM_STRSIZE) 675263a6526dSMichael Lim die("property list too long '%s'", propstr); 67530ba2cbe9Sxc151355 break; 67540ba2cbe9Sxc151355 case 't': 67550ba2cbe9Sxc151355 temp = B_TRUE; 67560ba2cbe9Sxc151355 break; 67570ba2cbe9Sxc151355 case 'R': 6758d62bc4baSyz147064 altroot = optarg; 67590ba2cbe9Sxc151355 break; 67600ba2cbe9Sxc151355 default: 67618d5c46e6Sam223141 die_opterr(optopt, option, use); 67628d5c46e6Sam223141 67630ba2cbe9Sxc151355 } 67640ba2cbe9Sxc151355 } 67650ba2cbe9Sxc151355 6766d62bc4baSyz147064 /* get link name (required last argument) */ 6767d62bc4baSyz147064 if (optind != (argc - 1)) 67680ba2cbe9Sxc151355 usage(); 67690ba2cbe9Sxc151355 677063a6526dSMichael Lim if (dladm_parse_link_props(propstr, &proplist, reset) != 677163a6526dSMichael Lim DLADM_STATUS_OK) 677263a6526dSMichael Lim die("invalid link properties specified"); 677363a6526dSMichael Lim 6774d62bc4baSyz147064 if (proplist == NULL && !reset) 677533343a97Smeem die("link property must be specified"); 677633343a97Smeem 6777d62bc4baSyz147064 if (altroot != NULL) { 6778da14cebeSEric Cheng dladm_free_props(proplist); 6779d62bc4baSyz147064 altroot_cmd(altroot, argc, argv); 6780d62bc4baSyz147064 } 6781d62bc4baSyz147064 67824ac67f02SAnurag S. Maskey status = dladm_name2info(handle, argv[optind], &linkid, NULL, NULL, 67834ac67f02SAnurag S. Maskey NULL); 6784d62bc4baSyz147064 if (status != DLADM_STATUS_OK) 6785d62bc4baSyz147064 die_dlerr(status, "link %s is not valid", argv[optind]); 6786d62bc4baSyz147064 6787d62bc4baSyz147064 if (proplist == NULL) { 6788da14cebeSEric Cheng set_linkprop_state_t state; 678913994ee8Sxz162242 6790da14cebeSEric Cheng state.ls_name = argv[optind]; 6791da14cebeSEric Cheng state.ls_reset = reset; 6792da14cebeSEric Cheng state.ls_temp = temp; 6793da14cebeSEric Cheng state.ls_status = DLADM_STATUS_OK; 6794da14cebeSEric Cheng 67954ac67f02SAnurag S. Maskey (void) dladm_walk_linkprop(handle, linkid, &state, 67964ac67f02SAnurag S. Maskey reset_one_linkprop); 6797da14cebeSEric Cheng 6798da14cebeSEric Cheng status = state.ls_status; 67990ba2cbe9Sxc151355 goto done; 68000ba2cbe9Sxc151355 } 68010ba2cbe9Sxc151355 6802da14cebeSEric Cheng for (i = 0; i < proplist->al_count; i++) { 6803da14cebeSEric Cheng dladm_arg_info_t *aip = &proplist->al_info[i]; 68040ba2cbe9Sxc151355 char **val; 68050ba2cbe9Sxc151355 uint_t count; 68060ba2cbe9Sxc151355 68070ba2cbe9Sxc151355 if (reset) { 68080ba2cbe9Sxc151355 val = NULL; 68090ba2cbe9Sxc151355 count = 0; 68100ba2cbe9Sxc151355 } else { 6811da14cebeSEric Cheng val = aip->ai_val; 6812da14cebeSEric Cheng count = aip->ai_count; 68130ba2cbe9Sxc151355 if (count == 0) { 681433343a97Smeem warn("no value specified for '%s'", 6815da14cebeSEric Cheng aip->ai_name); 68160ba2cbe9Sxc151355 status = DLADM_STATUS_BADARG; 68170ba2cbe9Sxc151355 continue; 68180ba2cbe9Sxc151355 } 68190ba2cbe9Sxc151355 } 68204eaa4710SRishi Srivatsavai status = dladm_set_linkprop(handle, linkid, aip->ai_name, val, 68214eaa4710SRishi Srivatsavai count, DLADM_OPT_ACTIVE | (temp ? 0 : DLADM_OPT_PERSIST)); 68224eaa4710SRishi Srivatsavai switch (status) { 68234eaa4710SRishi Srivatsavai case DLADM_STATUS_OK: 68244eaa4710SRishi Srivatsavai break; 68250ba2cbe9Sxc151355 case DLADM_STATUS_NOTFOUND: 6826da14cebeSEric Cheng warn("invalid link property '%s'", aip->ai_name); 68270ba2cbe9Sxc151355 break; 68280ba2cbe9Sxc151355 case DLADM_STATUS_BADVAL: { 68290ba2cbe9Sxc151355 int j; 68300ba2cbe9Sxc151355 char *ptr, *lim; 68310ba2cbe9Sxc151355 char **propvals = NULL; 6832d62bc4baSyz147064 uint_t valcnt = DLADM_MAX_PROP_VALCNT; 68334eaa4710SRishi Srivatsavai dladm_status_t s; 68340ba2cbe9Sxc151355 68350ba2cbe9Sxc151355 ptr = malloc((sizeof (char *) + 6836d62bc4baSyz147064 DLADM_PROP_VAL_MAX) * DLADM_MAX_PROP_VALCNT + 68370ba2cbe9Sxc151355 MAX_PROP_LINE); 68380ba2cbe9Sxc151355 68390ba2cbe9Sxc151355 propvals = (char **)(void *)ptr; 684033343a97Smeem if (propvals == NULL) 684133343a97Smeem die("insufficient memory"); 684233343a97Smeem 6843d62bc4baSyz147064 for (j = 0; j < DLADM_MAX_PROP_VALCNT; j++) { 68440ba2cbe9Sxc151355 propvals[j] = ptr + sizeof (char *) * 6845d62bc4baSyz147064 DLADM_MAX_PROP_VALCNT + 68460ba2cbe9Sxc151355 j * DLADM_PROP_VAL_MAX; 68470ba2cbe9Sxc151355 } 68484ac67f02SAnurag S. Maskey s = dladm_get_linkprop(handle, linkid, 6849da14cebeSEric Cheng DLADM_PROP_VAL_MODIFIABLE, aip->ai_name, propvals, 6850d62bc4baSyz147064 &valcnt); 6851d62bc4baSyz147064 6852d62bc4baSyz147064 if (s != DLADM_STATUS_OK) { 6853d62bc4baSyz147064 warn_dlerr(status, "cannot set link property " 6854da14cebeSEric Cheng "'%s' on '%s'", aip->ai_name, argv[optind]); 6855d62bc4baSyz147064 free(propvals); 6856d62bc4baSyz147064 break; 6857d62bc4baSyz147064 } 68580ba2cbe9Sxc151355 68590ba2cbe9Sxc151355 ptr = errmsg; 68600ba2cbe9Sxc151355 lim = ptr + DLADM_STRSIZE; 68610ba2cbe9Sxc151355 *ptr = '\0'; 6862d62bc4baSyz147064 for (j = 0; j < valcnt; j++) { 68630ba2cbe9Sxc151355 ptr += snprintf(ptr, lim - ptr, "%s,", 68640ba2cbe9Sxc151355 propvals[j]); 68650ba2cbe9Sxc151355 if (ptr >= lim) 68660ba2cbe9Sxc151355 break; 68670ba2cbe9Sxc151355 } 6868f4b3ec61Sdh155122 if (ptr > errmsg) { 68690ba2cbe9Sxc151355 *(ptr - 1) = '\0'; 687033343a97Smeem warn("link property '%s' must be one of: %s", 6871da14cebeSEric Cheng aip->ai_name, errmsg); 6872f4b3ec61Sdh155122 } else 6873f4b3ec61Sdh155122 warn("invalid link property '%s'", *val); 68740ba2cbe9Sxc151355 free(propvals); 68750ba2cbe9Sxc151355 break; 68760ba2cbe9Sxc151355 } 68770ba2cbe9Sxc151355 default: 68780ba2cbe9Sxc151355 if (reset) { 687933343a97Smeem warn_dlerr(status, "cannot reset link property " 6880da14cebeSEric Cheng "'%s' on '%s'", aip->ai_name, argv[optind]); 68810ba2cbe9Sxc151355 } else { 688233343a97Smeem warn_dlerr(status, "cannot set link property " 6883da14cebeSEric Cheng "'%s' on '%s'", aip->ai_name, argv[optind]); 68840ba2cbe9Sxc151355 } 68850ba2cbe9Sxc151355 break; 68860ba2cbe9Sxc151355 } 68870ba2cbe9Sxc151355 } 68880ba2cbe9Sxc151355 done: 6889da14cebeSEric Cheng dladm_free_props(proplist); 68904ac67f02SAnurag S. Maskey if (status != DLADM_STATUS_OK) { 68914ac67f02SAnurag S. Maskey dladm_close(handle); 68922b24ab6bSSebastien Roy exit(EXIT_FAILURE); 68930ba2cbe9Sxc151355 } 68944ac67f02SAnurag S. Maskey } 68950ba2cbe9Sxc151355 68960ba2cbe9Sxc151355 static void 68978d5c46e6Sam223141 do_set_linkprop(int argc, char **argv, const char *use) 68980ba2cbe9Sxc151355 { 68998d5c46e6Sam223141 set_linkprop(argc, argv, B_FALSE, use); 69000ba2cbe9Sxc151355 } 69010ba2cbe9Sxc151355 69020ba2cbe9Sxc151355 static void 69038d5c46e6Sam223141 do_reset_linkprop(int argc, char **argv, const char *use) 69040ba2cbe9Sxc151355 { 69058d5c46e6Sam223141 set_linkprop(argc, argv, B_TRUE, use); 69060ba2cbe9Sxc151355 } 69070ba2cbe9Sxc151355 69080ba2cbe9Sxc151355 static int 69090ba2cbe9Sxc151355 convert_secobj(char *buf, uint_t len, uint8_t *obj_val, uint_t *obj_lenp, 69100ba2cbe9Sxc151355 dladm_secobj_class_t class) 69110ba2cbe9Sxc151355 { 69120ba2cbe9Sxc151355 int error = 0; 69130ba2cbe9Sxc151355 6914a399b765Szf162725 if (class == DLADM_SECOBJ_CLASS_WPA) { 6915a399b765Szf162725 if (len < 8 || len > 63) 6916a399b765Szf162725 return (EINVAL); 6917a399b765Szf162725 (void) memcpy(obj_val, buf, len); 6918a399b765Szf162725 *obj_lenp = len; 6919a399b765Szf162725 return (error); 6920a399b765Szf162725 } 69210ba2cbe9Sxc151355 6922a399b765Szf162725 if (class == DLADM_SECOBJ_CLASS_WEP) { 69230ba2cbe9Sxc151355 switch (len) { 69240ba2cbe9Sxc151355 case 5: /* ASCII key sizes */ 69250ba2cbe9Sxc151355 case 13: 69260ba2cbe9Sxc151355 (void) memcpy(obj_val, buf, len); 69270ba2cbe9Sxc151355 *obj_lenp = len; 69280ba2cbe9Sxc151355 break; 69290ba2cbe9Sxc151355 case 10: /* Hex key sizes, not preceded by 0x */ 69300ba2cbe9Sxc151355 case 26: 69310ba2cbe9Sxc151355 error = hexascii_to_octet(buf, len, obj_val, obj_lenp); 69320ba2cbe9Sxc151355 break; 69330ba2cbe9Sxc151355 case 12: /* Hex key sizes, preceded by 0x */ 69340ba2cbe9Sxc151355 case 28: 69350ba2cbe9Sxc151355 if (strncmp(buf, "0x", 2) != 0) 69360ba2cbe9Sxc151355 return (EINVAL); 6937a399b765Szf162725 error = hexascii_to_octet(buf + 2, len - 2, 6938a399b765Szf162725 obj_val, obj_lenp); 69390ba2cbe9Sxc151355 break; 69400ba2cbe9Sxc151355 default: 69410ba2cbe9Sxc151355 return (EINVAL); 69420ba2cbe9Sxc151355 } 69430ba2cbe9Sxc151355 return (error); 69440ba2cbe9Sxc151355 } 69450ba2cbe9Sxc151355 6946a399b765Szf162725 return (ENOENT); 6947a399b765Szf162725 } 6948a399b765Szf162725 69490ba2cbe9Sxc151355 static void 69500ba2cbe9Sxc151355 defersig(int sig) 69510ba2cbe9Sxc151355 { 69520ba2cbe9Sxc151355 signalled = sig; 69530ba2cbe9Sxc151355 } 69540ba2cbe9Sxc151355 69550ba2cbe9Sxc151355 static int 69560ba2cbe9Sxc151355 get_secobj_from_tty(uint_t try, const char *objname, char *buf) 69570ba2cbe9Sxc151355 { 69580ba2cbe9Sxc151355 uint_t len = 0; 69590ba2cbe9Sxc151355 int c; 69600ba2cbe9Sxc151355 struct termios stored, current; 69610ba2cbe9Sxc151355 void (*sigfunc)(int); 69620ba2cbe9Sxc151355 69630ba2cbe9Sxc151355 /* 69640ba2cbe9Sxc151355 * Turn off echo -- but before we do so, defer SIGINT handling 69650ba2cbe9Sxc151355 * so that a ^C doesn't leave the terminal corrupted. 69660ba2cbe9Sxc151355 */ 69670ba2cbe9Sxc151355 sigfunc = signal(SIGINT, defersig); 69680ba2cbe9Sxc151355 (void) fflush(stdin); 69690ba2cbe9Sxc151355 (void) tcgetattr(0, &stored); 69700ba2cbe9Sxc151355 current = stored; 69710ba2cbe9Sxc151355 current.c_lflag &= ~(ICANON|ECHO); 69720ba2cbe9Sxc151355 current.c_cc[VTIME] = 0; 69730ba2cbe9Sxc151355 current.c_cc[VMIN] = 1; 69740ba2cbe9Sxc151355 (void) tcsetattr(0, TCSANOW, ¤t); 69750ba2cbe9Sxc151355 again: 69760ba2cbe9Sxc151355 if (try == 1) 69770ba2cbe9Sxc151355 (void) printf(gettext("provide value for '%s': "), objname); 69780ba2cbe9Sxc151355 else 69790ba2cbe9Sxc151355 (void) printf(gettext("confirm value for '%s': "), objname); 69800ba2cbe9Sxc151355 69810ba2cbe9Sxc151355 (void) fflush(stdout); 69820ba2cbe9Sxc151355 while (signalled == 0) { 69830ba2cbe9Sxc151355 c = getchar(); 69840ba2cbe9Sxc151355 if (c == '\n' || c == '\r') { 69850ba2cbe9Sxc151355 if (len != 0) 69860ba2cbe9Sxc151355 break; 69870ba2cbe9Sxc151355 (void) putchar('\n'); 69880ba2cbe9Sxc151355 goto again; 69890ba2cbe9Sxc151355 } 69900ba2cbe9Sxc151355 69910ba2cbe9Sxc151355 buf[len++] = c; 69920ba2cbe9Sxc151355 if (len >= DLADM_SECOBJ_VAL_MAX - 1) 69930ba2cbe9Sxc151355 break; 69940ba2cbe9Sxc151355 (void) putchar('*'); 69950ba2cbe9Sxc151355 } 69960ba2cbe9Sxc151355 69970ba2cbe9Sxc151355 (void) putchar('\n'); 69980ba2cbe9Sxc151355 (void) fflush(stdin); 69990ba2cbe9Sxc151355 70000ba2cbe9Sxc151355 /* 70010ba2cbe9Sxc151355 * Restore terminal setting and handle deferred signals. 70020ba2cbe9Sxc151355 */ 70030ba2cbe9Sxc151355 (void) tcsetattr(0, TCSANOW, &stored); 70040ba2cbe9Sxc151355 70050ba2cbe9Sxc151355 (void) signal(SIGINT, sigfunc); 70060ba2cbe9Sxc151355 if (signalled != 0) 70070ba2cbe9Sxc151355 (void) kill(getpid(), signalled); 70080ba2cbe9Sxc151355 70090ba2cbe9Sxc151355 return (len); 70100ba2cbe9Sxc151355 } 70110ba2cbe9Sxc151355 70120ba2cbe9Sxc151355 static int 70130ba2cbe9Sxc151355 get_secobj_val(char *obj_name, uint8_t *obj_val, uint_t *obj_lenp, 70140ba2cbe9Sxc151355 dladm_secobj_class_t class, FILE *filep) 70150ba2cbe9Sxc151355 { 70160ba2cbe9Sxc151355 int rval; 70170ba2cbe9Sxc151355 uint_t len, len2; 70180ba2cbe9Sxc151355 char buf[DLADM_SECOBJ_VAL_MAX], buf2[DLADM_SECOBJ_VAL_MAX]; 70190ba2cbe9Sxc151355 70200ba2cbe9Sxc151355 if (filep == NULL) { 70210ba2cbe9Sxc151355 len = get_secobj_from_tty(1, obj_name, buf); 70220ba2cbe9Sxc151355 rval = convert_secobj(buf, len, obj_val, obj_lenp, class); 70230ba2cbe9Sxc151355 if (rval == 0) { 70240ba2cbe9Sxc151355 len2 = get_secobj_from_tty(2, obj_name, buf2); 70250ba2cbe9Sxc151355 if (len != len2 || memcmp(buf, buf2, len) != 0) 70260ba2cbe9Sxc151355 rval = ENOTSUP; 70270ba2cbe9Sxc151355 } 70280ba2cbe9Sxc151355 return (rval); 70290ba2cbe9Sxc151355 } else { 70300ba2cbe9Sxc151355 for (;;) { 70310ba2cbe9Sxc151355 if (fgets(buf, sizeof (buf), filep) == NULL) 70320ba2cbe9Sxc151355 break; 70330ba2cbe9Sxc151355 if (isspace(buf[0])) 70340ba2cbe9Sxc151355 continue; 70350ba2cbe9Sxc151355 70360ba2cbe9Sxc151355 len = strlen(buf); 70370ba2cbe9Sxc151355 if (buf[len - 1] == '\n') { 70380ba2cbe9Sxc151355 buf[len - 1] = '\0'; 70390ba2cbe9Sxc151355 len--; 70400ba2cbe9Sxc151355 } 70410ba2cbe9Sxc151355 break; 70420ba2cbe9Sxc151355 } 70430ba2cbe9Sxc151355 (void) fclose(filep); 70440ba2cbe9Sxc151355 } 70450ba2cbe9Sxc151355 return (convert_secobj(buf, len, obj_val, obj_lenp, class)); 70460ba2cbe9Sxc151355 } 70470ba2cbe9Sxc151355 70480ba2cbe9Sxc151355 static boolean_t 70490ba2cbe9Sxc151355 check_auth(const char *auth) 70500ba2cbe9Sxc151355 { 70510ba2cbe9Sxc151355 struct passwd *pw; 70520ba2cbe9Sxc151355 70530ba2cbe9Sxc151355 if ((pw = getpwuid(getuid())) == NULL) 70540ba2cbe9Sxc151355 return (B_FALSE); 70550ba2cbe9Sxc151355 70560ba2cbe9Sxc151355 return (chkauthattr(auth, pw->pw_name) != 0); 70570ba2cbe9Sxc151355 } 70580ba2cbe9Sxc151355 70590ba2cbe9Sxc151355 static void 70600ba2cbe9Sxc151355 audit_secobj(char *auth, char *class, char *obj, 70610ba2cbe9Sxc151355 boolean_t success, boolean_t create) 70620ba2cbe9Sxc151355 { 70630ba2cbe9Sxc151355 adt_session_data_t *ah; 70640ba2cbe9Sxc151355 adt_event_data_t *event; 70650ba2cbe9Sxc151355 au_event_t flag; 70660ba2cbe9Sxc151355 char *errstr; 70670ba2cbe9Sxc151355 70680ba2cbe9Sxc151355 if (create) { 70690ba2cbe9Sxc151355 flag = ADT_dladm_create_secobj; 70700ba2cbe9Sxc151355 errstr = "ADT_dladm_create_secobj"; 70710ba2cbe9Sxc151355 } else { 70720ba2cbe9Sxc151355 flag = ADT_dladm_delete_secobj; 70730ba2cbe9Sxc151355 errstr = "ADT_dladm_delete_secobj"; 70740ba2cbe9Sxc151355 } 70750ba2cbe9Sxc151355 707633343a97Smeem if (adt_start_session(&ah, NULL, ADT_USE_PROC_DATA) != 0) 707733343a97Smeem die("adt_start_session: %s", strerror(errno)); 70780ba2cbe9Sxc151355 707933343a97Smeem if ((event = adt_alloc_event(ah, flag)) == NULL) 708033343a97Smeem die("adt_alloc_event (%s): %s", errstr, strerror(errno)); 70810ba2cbe9Sxc151355 70820ba2cbe9Sxc151355 /* fill in audit info */ 70830ba2cbe9Sxc151355 if (create) { 70840ba2cbe9Sxc151355 event->adt_dladm_create_secobj.auth_used = auth; 70850ba2cbe9Sxc151355 event->adt_dladm_create_secobj.obj_class = class; 70860ba2cbe9Sxc151355 event->adt_dladm_create_secobj.obj_name = obj; 70870ba2cbe9Sxc151355 } else { 70880ba2cbe9Sxc151355 event->adt_dladm_delete_secobj.auth_used = auth; 70890ba2cbe9Sxc151355 event->adt_dladm_delete_secobj.obj_class = class; 70900ba2cbe9Sxc151355 event->adt_dladm_delete_secobj.obj_name = obj; 70910ba2cbe9Sxc151355 } 70920ba2cbe9Sxc151355 70930ba2cbe9Sxc151355 if (success) { 70940ba2cbe9Sxc151355 if (adt_put_event(event, ADT_SUCCESS, ADT_SUCCESS) != 0) { 709533343a97Smeem die("adt_put_event (%s, success): %s", errstr, 709633343a97Smeem strerror(errno)); 70970ba2cbe9Sxc151355 } 70980ba2cbe9Sxc151355 } else { 70990ba2cbe9Sxc151355 if (adt_put_event(event, ADT_FAILURE, 71000ba2cbe9Sxc151355 ADT_FAIL_VALUE_AUTH) != 0) { 710133343a97Smeem die("adt_put_event: (%s, failure): %s", errstr, 710233343a97Smeem strerror(errno)); 71030ba2cbe9Sxc151355 } 71040ba2cbe9Sxc151355 } 71050ba2cbe9Sxc151355 71060ba2cbe9Sxc151355 adt_free_event(event); 71070ba2cbe9Sxc151355 (void) adt_end_session(ah); 71080ba2cbe9Sxc151355 } 71090ba2cbe9Sxc151355 71100ba2cbe9Sxc151355 #define MAX_SECOBJS 32 71110ba2cbe9Sxc151355 #define MAX_SECOBJ_NAMELEN 32 71120ba2cbe9Sxc151355 static void 71138d5c46e6Sam223141 do_create_secobj(int argc, char **argv, const char *use) 71140ba2cbe9Sxc151355 { 71150ba2cbe9Sxc151355 int option, rval; 71160ba2cbe9Sxc151355 FILE *filep = NULL; 71170ba2cbe9Sxc151355 char *obj_name = NULL; 71180ba2cbe9Sxc151355 char *class_name = NULL; 71190ba2cbe9Sxc151355 uint8_t obj_val[DLADM_SECOBJ_VAL_MAX]; 71200ba2cbe9Sxc151355 uint_t obj_len; 71210ba2cbe9Sxc151355 boolean_t success, temp = B_FALSE; 71220ba2cbe9Sxc151355 dladm_status_t status; 71230ba2cbe9Sxc151355 dladm_secobj_class_t class = -1; 71240ba2cbe9Sxc151355 uid_t euid; 71250ba2cbe9Sxc151355 71260ba2cbe9Sxc151355 opterr = 0; 71270ba2cbe9Sxc151355 (void) memset(obj_val, 0, DLADM_SECOBJ_VAL_MAX); 71280ba2cbe9Sxc151355 while ((option = getopt_long(argc, argv, ":f:c:R:t", 71290ba2cbe9Sxc151355 wifi_longopts, NULL)) != -1) { 71300ba2cbe9Sxc151355 switch (option) { 71310ba2cbe9Sxc151355 case 'f': 71320ba2cbe9Sxc151355 euid = geteuid(); 71330ba2cbe9Sxc151355 (void) seteuid(getuid()); 71340ba2cbe9Sxc151355 filep = fopen(optarg, "r"); 71350ba2cbe9Sxc151355 if (filep == NULL) { 713633343a97Smeem die("cannot open %s: %s", optarg, 713733343a97Smeem strerror(errno)); 71380ba2cbe9Sxc151355 } 71390ba2cbe9Sxc151355 (void) seteuid(euid); 71400ba2cbe9Sxc151355 break; 71410ba2cbe9Sxc151355 case 'c': 71420ba2cbe9Sxc151355 class_name = optarg; 71430ba2cbe9Sxc151355 status = dladm_str2secobjclass(optarg, &class); 71440ba2cbe9Sxc151355 if (status != DLADM_STATUS_OK) { 714533343a97Smeem die("invalid secure object class '%s', " 7146a399b765Szf162725 "valid values are: wep, wpa", optarg); 71470ba2cbe9Sxc151355 } 71480ba2cbe9Sxc151355 break; 71490ba2cbe9Sxc151355 case 't': 71500ba2cbe9Sxc151355 temp = B_TRUE; 71510ba2cbe9Sxc151355 break; 71520ba2cbe9Sxc151355 case 'R': 71530ba2cbe9Sxc151355 status = dladm_set_rootdir(optarg); 71540ba2cbe9Sxc151355 if (status != DLADM_STATUS_OK) { 715533343a97Smeem die_dlerr(status, "invalid directory " 715633343a97Smeem "specified"); 71570ba2cbe9Sxc151355 } 71580ba2cbe9Sxc151355 break; 71590ba2cbe9Sxc151355 default: 71608d5c46e6Sam223141 die_opterr(optopt, option, use); 71610ba2cbe9Sxc151355 break; 71620ba2cbe9Sxc151355 } 71630ba2cbe9Sxc151355 } 71640ba2cbe9Sxc151355 71650ba2cbe9Sxc151355 if (optind == (argc - 1)) 71660ba2cbe9Sxc151355 obj_name = argv[optind]; 71670ba2cbe9Sxc151355 else if (optind != argc) 71680ba2cbe9Sxc151355 usage(); 71690ba2cbe9Sxc151355 717033343a97Smeem if (class == -1) 717133343a97Smeem die("secure object class required"); 71720ba2cbe9Sxc151355 717333343a97Smeem if (obj_name == NULL) 717433343a97Smeem die("secure object name required"); 71750ba2cbe9Sxc151355 7176a9489f61SAnurag S. Maskey if (!dladm_valid_secobj_name(obj_name)) 7177a9489f61SAnurag S. Maskey die("invalid secure object name '%s'", obj_name); 7178a9489f61SAnurag S. Maskey 71790ba2cbe9Sxc151355 success = check_auth(LINK_SEC_AUTH); 71800ba2cbe9Sxc151355 audit_secobj(LINK_SEC_AUTH, class_name, obj_name, success, B_TRUE); 718133343a97Smeem if (!success) 718233343a97Smeem die("authorization '%s' is required", LINK_SEC_AUTH); 71830ba2cbe9Sxc151355 718433343a97Smeem rval = get_secobj_val(obj_name, obj_val, &obj_len, class, filep); 718533343a97Smeem if (rval != 0) { 71860ba2cbe9Sxc151355 switch (rval) { 71870ba2cbe9Sxc151355 case ENOENT: 718833343a97Smeem die("invalid secure object class"); 71890ba2cbe9Sxc151355 break; 71900ba2cbe9Sxc151355 case EINVAL: 719133343a97Smeem die("invalid secure object value"); 71920ba2cbe9Sxc151355 break; 71930ba2cbe9Sxc151355 case ENOTSUP: 719433343a97Smeem die("verification failed"); 71950ba2cbe9Sxc151355 break; 71960ba2cbe9Sxc151355 default: 719733343a97Smeem die("invalid secure object: %s", strerror(rval)); 71980ba2cbe9Sxc151355 break; 71990ba2cbe9Sxc151355 } 72000ba2cbe9Sxc151355 } 72010ba2cbe9Sxc151355 72024ac67f02SAnurag S. Maskey status = dladm_set_secobj(handle, obj_name, class, obj_val, obj_len, 7203d62bc4baSyz147064 DLADM_OPT_CREATE | DLADM_OPT_ACTIVE); 72040ba2cbe9Sxc151355 if (status != DLADM_STATUS_OK) { 720533343a97Smeem die_dlerr(status, "could not create secure object '%s'", 720633343a97Smeem obj_name); 72070ba2cbe9Sxc151355 } 72080ba2cbe9Sxc151355 if (temp) 72090ba2cbe9Sxc151355 return; 72100ba2cbe9Sxc151355 72114ac67f02SAnurag S. Maskey status = dladm_set_secobj(handle, obj_name, class, obj_val, obj_len, 72120ba2cbe9Sxc151355 DLADM_OPT_PERSIST); 72130ba2cbe9Sxc151355 if (status != DLADM_STATUS_OK) { 721433343a97Smeem warn_dlerr(status, "could not persistently create secure " 721533343a97Smeem "object '%s'", obj_name); 72160ba2cbe9Sxc151355 } 72170ba2cbe9Sxc151355 } 72180ba2cbe9Sxc151355 72190ba2cbe9Sxc151355 static void 72208d5c46e6Sam223141 do_delete_secobj(int argc, char **argv, const char *use) 72210ba2cbe9Sxc151355 { 72220ba2cbe9Sxc151355 int i, option; 72230ba2cbe9Sxc151355 boolean_t temp = B_FALSE; 72240ba2cbe9Sxc151355 boolean_t success; 72250ba2cbe9Sxc151355 dladm_status_t status, pstatus; 72268002d411SSowmini Varadhan int nfields = 1; 72278002d411SSowmini Varadhan char *field, *token, *lasts = NULL, c; 72280ba2cbe9Sxc151355 72290ba2cbe9Sxc151355 opterr = 0; 72300ba2cbe9Sxc151355 status = pstatus = DLADM_STATUS_OK; 723133343a97Smeem while ((option = getopt_long(argc, argv, ":R:t", 72320ba2cbe9Sxc151355 wifi_longopts, NULL)) != -1) { 72330ba2cbe9Sxc151355 switch (option) { 72340ba2cbe9Sxc151355 case 't': 72350ba2cbe9Sxc151355 temp = B_TRUE; 72360ba2cbe9Sxc151355 break; 72370ba2cbe9Sxc151355 case 'R': 72380ba2cbe9Sxc151355 status = dladm_set_rootdir(optarg); 72390ba2cbe9Sxc151355 if (status != DLADM_STATUS_OK) { 724033343a97Smeem die_dlerr(status, "invalid directory " 724133343a97Smeem "specified"); 72420ba2cbe9Sxc151355 } 72430ba2cbe9Sxc151355 break; 72440ba2cbe9Sxc151355 default: 72458d5c46e6Sam223141 die_opterr(optopt, option, use); 72460ba2cbe9Sxc151355 break; 72470ba2cbe9Sxc151355 } 72480ba2cbe9Sxc151355 } 72490ba2cbe9Sxc151355 72500ba2cbe9Sxc151355 if (optind == (argc - 1)) { 72518002d411SSowmini Varadhan token = argv[optind]; 72528002d411SSowmini Varadhan if (token == NULL) 72538002d411SSowmini Varadhan die("secure object name required"); 72548002d411SSowmini Varadhan while ((c = *token++) != NULL) { 72558002d411SSowmini Varadhan if (c == ',') 72568002d411SSowmini Varadhan nfields++; 72570ba2cbe9Sxc151355 } 72588002d411SSowmini Varadhan token = strdup(argv[optind]); 72598002d411SSowmini Varadhan if (token == NULL) 72608002d411SSowmini Varadhan die("no memory"); 72610ba2cbe9Sxc151355 } else if (optind != argc) 72620ba2cbe9Sxc151355 usage(); 72630ba2cbe9Sxc151355 72640ba2cbe9Sxc151355 success = check_auth(LINK_SEC_AUTH); 7265a399b765Szf162725 audit_secobj(LINK_SEC_AUTH, "unknown", argv[optind], success, B_FALSE); 726633343a97Smeem if (!success) 726733343a97Smeem die("authorization '%s' is required", LINK_SEC_AUTH); 72680ba2cbe9Sxc151355 72698002d411SSowmini Varadhan for (i = 0; i < nfields; i++) { 72708002d411SSowmini Varadhan 72718002d411SSowmini Varadhan field = strtok_r(token, ",", &lasts); 72728002d411SSowmini Varadhan token = NULL; 72738002d411SSowmini Varadhan status = dladm_unset_secobj(handle, field, DLADM_OPT_ACTIVE); 72740ba2cbe9Sxc151355 if (!temp) { 72758002d411SSowmini Varadhan pstatus = dladm_unset_secobj(handle, field, 72760ba2cbe9Sxc151355 DLADM_OPT_PERSIST); 72770ba2cbe9Sxc151355 } else { 72780ba2cbe9Sxc151355 pstatus = DLADM_STATUS_OK; 72790ba2cbe9Sxc151355 } 72800ba2cbe9Sxc151355 72810ba2cbe9Sxc151355 if (status != DLADM_STATUS_OK) { 728233343a97Smeem warn_dlerr(status, "could not delete secure object " 72838002d411SSowmini Varadhan "'%s'", field); 72840ba2cbe9Sxc151355 } 72850ba2cbe9Sxc151355 if (pstatus != DLADM_STATUS_OK) { 728633343a97Smeem warn_dlerr(pstatus, "could not persistently delete " 72878002d411SSowmini Varadhan "secure object '%s'", field); 72880ba2cbe9Sxc151355 } 72890ba2cbe9Sxc151355 } 72908002d411SSowmini Varadhan free(token); 72914ac67f02SAnurag S. Maskey 72924ac67f02SAnurag S. Maskey if (status != DLADM_STATUS_OK || pstatus != DLADM_STATUS_OK) { 72934ac67f02SAnurag S. Maskey dladm_close(handle); 72942b24ab6bSSebastien Roy exit(EXIT_FAILURE); 72950ba2cbe9Sxc151355 } 72964ac67f02SAnurag S. Maskey } 72970ba2cbe9Sxc151355 72980ba2cbe9Sxc151355 typedef struct show_secobj_state { 72990ba2cbe9Sxc151355 boolean_t ss_persist; 73008002d411SSowmini Varadhan boolean_t ss_parsable; 73010ba2cbe9Sxc151355 boolean_t ss_header; 73028002d411SSowmini Varadhan ofmt_handle_t ss_ofmt; 73030ba2cbe9Sxc151355 } show_secobj_state_t; 73040ba2cbe9Sxc151355 73050ba2cbe9Sxc151355 73060ba2cbe9Sxc151355 static boolean_t 73074ac67f02SAnurag S. Maskey show_secobj(dladm_handle_t dh, void *arg, const char *obj_name) 73080ba2cbe9Sxc151355 { 73090ba2cbe9Sxc151355 uint_t obj_len = DLADM_SECOBJ_VAL_MAX; 73100ba2cbe9Sxc151355 uint8_t obj_val[DLADM_SECOBJ_VAL_MAX]; 73110ba2cbe9Sxc151355 char buf[DLADM_STRSIZE]; 73120ba2cbe9Sxc151355 uint_t flags = 0; 73130ba2cbe9Sxc151355 dladm_secobj_class_t class; 73140ba2cbe9Sxc151355 show_secobj_state_t *statep = arg; 73150ba2cbe9Sxc151355 dladm_status_t status; 7316e7801d59Ssowmini secobj_fields_buf_t sbuf; 73170ba2cbe9Sxc151355 73185f5c9f54SAnurag S. Maskey bzero(&sbuf, sizeof (secobj_fields_buf_t)); 73190ba2cbe9Sxc151355 if (statep->ss_persist) 73200ba2cbe9Sxc151355 flags |= DLADM_OPT_PERSIST; 73210ba2cbe9Sxc151355 73224ac67f02SAnurag S. Maskey status = dladm_get_secobj(dh, obj_name, &class, obj_val, &obj_len, 73234ac67f02SAnurag S. Maskey flags); 732433343a97Smeem if (status != DLADM_STATUS_OK) 732533343a97Smeem die_dlerr(status, "cannot get secure object '%s'", obj_name); 73260ba2cbe9Sxc151355 7327e7801d59Ssowmini (void) snprintf(sbuf.ss_obj_name, sizeof (sbuf.ss_obj_name), 7328e7801d59Ssowmini obj_name); 7329e7801d59Ssowmini (void) dladm_secobjclass2str(class, buf); 7330e7801d59Ssowmini (void) snprintf(sbuf.ss_class, sizeof (sbuf.ss_class), "%s", buf); 7331e7801d59Ssowmini if (getuid() == 0) { 73320ba2cbe9Sxc151355 char val[DLADM_SECOBJ_VAL_MAX * 2]; 73330ba2cbe9Sxc151355 uint_t len = sizeof (val); 73340ba2cbe9Sxc151355 7335e7801d59Ssowmini if (octet_to_hexascii(obj_val, obj_len, val, &len) == 0) 7336e7801d59Ssowmini (void) snprintf(sbuf.ss_val, 7337e7801d59Ssowmini sizeof (sbuf.ss_val), "%s", val); 73380ba2cbe9Sxc151355 } 73398002d411SSowmini Varadhan ofmt_print(statep->ss_ofmt, &sbuf); 73400ba2cbe9Sxc151355 return (B_TRUE); 73410ba2cbe9Sxc151355 } 73420ba2cbe9Sxc151355 73430ba2cbe9Sxc151355 static void 73448d5c46e6Sam223141 do_show_secobj(int argc, char **argv, const char *use) 73450ba2cbe9Sxc151355 { 73460ba2cbe9Sxc151355 int option; 73470ba2cbe9Sxc151355 show_secobj_state_t state; 73480ba2cbe9Sxc151355 dladm_status_t status; 73490d365605Sschuster boolean_t o_arg = B_FALSE; 73500ba2cbe9Sxc151355 uint_t i; 73510ba2cbe9Sxc151355 uint_t flags; 7352e7801d59Ssowmini char *fields_str = NULL; 7353e7801d59Ssowmini char *def_fields = "object,class"; 7354e7801d59Ssowmini char *all_fields = "object,class,value"; 73558002d411SSowmini Varadhan char *field, *token, *lasts = NULL, c; 73568002d411SSowmini Varadhan ofmt_handle_t ofmt; 73578002d411SSowmini Varadhan ofmt_status_t oferr; 73588002d411SSowmini Varadhan uint_t ofmtflags = 0; 73590ba2cbe9Sxc151355 73600ba2cbe9Sxc151355 opterr = 0; 7361e7801d59Ssowmini bzero(&state, sizeof (state)); 73628002d411SSowmini Varadhan state.ss_parsable = B_FALSE; 7363e7801d59Ssowmini fields_str = def_fields; 73640ba2cbe9Sxc151355 state.ss_persist = B_FALSE; 73658002d411SSowmini Varadhan state.ss_parsable = B_FALSE; 73660ba2cbe9Sxc151355 state.ss_header = B_TRUE; 7367e7801d59Ssowmini while ((option = getopt_long(argc, argv, ":pPo:", 73680ba2cbe9Sxc151355 wifi_longopts, NULL)) != -1) { 73690ba2cbe9Sxc151355 switch (option) { 73700ba2cbe9Sxc151355 case 'p': 73718002d411SSowmini Varadhan state.ss_parsable = B_TRUE; 73720ba2cbe9Sxc151355 break; 73730ba2cbe9Sxc151355 case 'P': 73740ba2cbe9Sxc151355 state.ss_persist = B_TRUE; 73750ba2cbe9Sxc151355 break; 7376e7801d59Ssowmini case 'o': 73770d365605Sschuster o_arg = B_TRUE; 7378e7801d59Ssowmini if (strcasecmp(optarg, "all") == 0) 7379e7801d59Ssowmini fields_str = all_fields; 7380e7801d59Ssowmini else 7381e7801d59Ssowmini fields_str = optarg; 73820ba2cbe9Sxc151355 break; 73830ba2cbe9Sxc151355 default: 73848d5c46e6Sam223141 die_opterr(optopt, option, use); 73850ba2cbe9Sxc151355 break; 73860ba2cbe9Sxc151355 } 73870ba2cbe9Sxc151355 } 73880ba2cbe9Sxc151355 73898002d411SSowmini Varadhan if (state.ss_parsable && !o_arg) 73900d365605Sschuster die("option -c requires -o"); 73910d365605Sschuster 73928002d411SSowmini Varadhan if (state.ss_parsable && fields_str == all_fields) 73930d365605Sschuster die("\"-o all\" is invalid with -p"); 73940d365605Sschuster 73958002d411SSowmini Varadhan if (state.ss_parsable) 73968002d411SSowmini Varadhan ofmtflags |= OFMT_PARSABLE; 73978002d411SSowmini Varadhan oferr = ofmt_open(fields_str, secobj_fields, ofmtflags, 0, &ofmt); 73988002d411SSowmini Varadhan dladm_ofmt_check(oferr, state.ss_parsable, ofmt); 73998002d411SSowmini Varadhan state.ss_ofmt = ofmt; 7400e7801d59Ssowmini 7401e7801d59Ssowmini flags = state.ss_persist ? DLADM_OPT_PERSIST : 0; 74024ac67f02SAnurag S. Maskey 74030ba2cbe9Sxc151355 if (optind == (argc - 1)) { 74048002d411SSowmini Varadhan uint_t obj_fields = 1; 74058002d411SSowmini Varadhan 74068002d411SSowmini Varadhan token = argv[optind]; 74078002d411SSowmini Varadhan if (token == NULL) 74088002d411SSowmini Varadhan die("secure object name required"); 74098002d411SSowmini Varadhan while ((c = *token++) != NULL) { 74108002d411SSowmini Varadhan if (c == ',') 74118002d411SSowmini Varadhan obj_fields++; 74120ba2cbe9Sxc151355 } 74138002d411SSowmini Varadhan token = strdup(argv[optind]); 74148002d411SSowmini Varadhan if (token == NULL) 74158002d411SSowmini Varadhan die("no memory"); 74168002d411SSowmini Varadhan for (i = 0; i < obj_fields; i++) { 74178002d411SSowmini Varadhan field = strtok_r(token, ",", &lasts); 74188002d411SSowmini Varadhan token = NULL; 74198002d411SSowmini Varadhan if (!show_secobj(handle, &state, field)) 74200ba2cbe9Sxc151355 break; 74210ba2cbe9Sxc151355 } 74228002d411SSowmini Varadhan free(token); 74238002d411SSowmini Varadhan ofmt_close(ofmt); 74240ba2cbe9Sxc151355 return; 74250ba2cbe9Sxc151355 } else if (optind != argc) 74260ba2cbe9Sxc151355 usage(); 74270ba2cbe9Sxc151355 74284ac67f02SAnurag S. Maskey status = dladm_walk_secobj(handle, &state, show_secobj, flags); 74294ac67f02SAnurag S. Maskey 743033343a97Smeem if (status != DLADM_STATUS_OK) 743133343a97Smeem die_dlerr(status, "show-secobj"); 74328002d411SSowmini Varadhan ofmt_close(ofmt); 74330ba2cbe9Sxc151355 } 74340ba2cbe9Sxc151355 74350ba2cbe9Sxc151355 /*ARGSUSED*/ 7436d62bc4baSyz147064 static int 74374ac67f02SAnurag S. Maskey i_dladm_init_linkprop(dladm_handle_t dh, datalink_id_t linkid, void *arg) 7438d62bc4baSyz147064 { 74394ac67f02SAnurag S. Maskey (void) dladm_init_linkprop(dh, linkid, B_TRUE); 7440d62bc4baSyz147064 return (DLADM_WALK_CONTINUE); 7441d62bc4baSyz147064 } 7442d62bc4baSyz147064 74438d5c46e6Sam223141 /*ARGSUSED*/ 7444da14cebeSEric Cheng void 74458d5c46e6Sam223141 do_init_linkprop(int argc, char **argv, const char *use) 74460ba2cbe9Sxc151355 { 744730890389Sartem int option; 744830890389Sartem dladm_status_t status; 744930890389Sartem datalink_id_t linkid = DATALINK_ALL_LINKID; 745030890389Sartem datalink_media_t media = DATALINK_ANY_MEDIATYPE; 745130890389Sartem uint_t any_media = B_TRUE; 745230890389Sartem 745330890389Sartem opterr = 0; 745430890389Sartem while ((option = getopt(argc, argv, ":w")) != -1) { 745530890389Sartem switch (option) { 745630890389Sartem case 'w': 745730890389Sartem media = DL_WIFI; 745830890389Sartem any_media = B_FALSE; 745930890389Sartem break; 746030890389Sartem default: 74618d5c46e6Sam223141 /* 74628d5c46e6Sam223141 * Because init-linkprop is not a public command, 74638d5c46e6Sam223141 * print the usage instead. 74648d5c46e6Sam223141 */ 74658d5c46e6Sam223141 usage(); 746630890389Sartem break; 746730890389Sartem } 746830890389Sartem } 746930890389Sartem 747030890389Sartem if (optind == (argc - 1)) { 74714ac67f02SAnurag S. Maskey if ((status = dladm_name2info(handle, argv[optind], &linkid, 74724ac67f02SAnurag S. Maskey NULL, NULL, NULL)) != DLADM_STATUS_OK) 747330890389Sartem die_dlerr(status, "link %s is not valid", argv[optind]); 747430890389Sartem } else if (optind != argc) { 747530890389Sartem usage(); 747630890389Sartem } 747730890389Sartem 747830890389Sartem if (linkid == DATALINK_ALL_LINKID) { 7479d62bc4baSyz147064 /* 748030890389Sartem * linkprops of links of other classes have been initialized as 7481d62bc4baSyz147064 * part of the dladm up-xxx operation. 7482d62bc4baSyz147064 */ 74834ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(i_dladm_init_linkprop, handle, 74844ac67f02SAnurag S. Maskey NULL, DATALINK_CLASS_PHYS, media, DLADM_OPT_PERSIST); 748530890389Sartem } else { 74864ac67f02SAnurag S. Maskey (void) dladm_init_linkprop(handle, linkid, any_media); 748730890389Sartem } 74880ba2cbe9Sxc151355 } 74890ba2cbe9Sxc151355 74900ba2cbe9Sxc151355 static void 74918d5c46e6Sam223141 do_show_ether(int argc, char **argv, const char *use) 7492e7801d59Ssowmini { 7493e7801d59Ssowmini int option; 7494e7801d59Ssowmini datalink_id_t linkid; 7495e7801d59Ssowmini print_ether_state_t state; 74968002d411SSowmini Varadhan char *fields_str = NULL; 74978002d411SSowmini Varadhan ofmt_handle_t ofmt; 74988002d411SSowmini Varadhan ofmt_status_t oferr; 74998002d411SSowmini Varadhan uint_t ofmtflags = 0; 7500e7801d59Ssowmini 7501e7801d59Ssowmini bzero(&state, sizeof (state)); 7502e7801d59Ssowmini state.es_link = NULL; 75038002d411SSowmini Varadhan state.es_parsable = B_FALSE; 7504e7801d59Ssowmini 7505e7801d59Ssowmini while ((option = getopt_long(argc, argv, "o:px", 7506e7801d59Ssowmini showeth_lopts, NULL)) != -1) { 7507e7801d59Ssowmini switch (option) { 7508e7801d59Ssowmini case 'x': 7509e7801d59Ssowmini state.es_extended = B_TRUE; 7510e7801d59Ssowmini break; 7511e7801d59Ssowmini case 'p': 75128002d411SSowmini Varadhan state.es_parsable = B_TRUE; 7513e7801d59Ssowmini break; 7514e7801d59Ssowmini case 'o': 7515e7801d59Ssowmini fields_str = optarg; 7516e7801d59Ssowmini break; 7517e7801d59Ssowmini default: 75188d5c46e6Sam223141 die_opterr(optopt, option, use); 7519e7801d59Ssowmini break; 7520e7801d59Ssowmini } 7521e7801d59Ssowmini } 7522e7801d59Ssowmini 7523e7801d59Ssowmini if (optind == (argc - 1)) 7524e7801d59Ssowmini state.es_link = argv[optind]; 7525e7801d59Ssowmini 75268002d411SSowmini Varadhan if (state.es_parsable) 75278002d411SSowmini Varadhan ofmtflags |= OFMT_PARSABLE; 75288002d411SSowmini Varadhan oferr = ofmt_open(fields_str, ether_fields, ofmtflags, 75298002d411SSowmini Varadhan DLADM_DEFAULT_COL, &ofmt); 75308002d411SSowmini Varadhan dladm_ofmt_check(oferr, state.es_parsable, ofmt); 75318002d411SSowmini Varadhan state.es_ofmt = ofmt; 75324ac67f02SAnurag S. Maskey 7533e7801d59Ssowmini if (state.es_link == NULL) { 75344ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(show_etherprop, handle, &state, 75353361618bSRishi Srivatsavai DATALINK_CLASS_PHYS, DL_ETHER, DLADM_OPT_ACTIVE); 7536e7801d59Ssowmini } else { 75374ac67f02SAnurag S. Maskey if (!link_is_ether(state.es_link, &linkid)) 7538e7801d59Ssowmini die("invalid link specified"); 75394ac67f02SAnurag S. Maskey (void) show_etherprop(handle, linkid, &state); 7540e7801d59Ssowmini } 75418002d411SSowmini Varadhan ofmt_close(ofmt); 7542e7801d59Ssowmini } 7543e7801d59Ssowmini 7544e7801d59Ssowmini static int 75454ac67f02SAnurag S. Maskey show_etherprop(dladm_handle_t dh, datalink_id_t linkid, void *arg) 7546e7801d59Ssowmini { 7547e7801d59Ssowmini print_ether_state_t *statep = arg; 7548e7801d59Ssowmini ether_fields_buf_t ebuf; 75494784fcbdSSowmini Varadhan dladm_ether_info_t eattr; 75504784fcbdSSowmini Varadhan dladm_status_t status; 7551e7801d59Ssowmini 75525f5c9f54SAnurag S. Maskey bzero(&ebuf, sizeof (ether_fields_buf_t)); 75534ac67f02SAnurag S. Maskey if (dladm_datalink_id2info(dh, linkid, NULL, NULL, NULL, 7554e7801d59Ssowmini ebuf.eth_link, sizeof (ebuf.eth_link)) != DLADM_STATUS_OK) { 7555e7801d59Ssowmini return (DLADM_WALK_CONTINUE); 7556e7801d59Ssowmini } 7557e7801d59Ssowmini 75584ac67f02SAnurag S. Maskey status = dladm_ether_info(dh, linkid, &eattr); 75594784fcbdSSowmini Varadhan if (status != DLADM_STATUS_OK) 75604784fcbdSSowmini Varadhan goto cleanup; 7561e7801d59Ssowmini 75624784fcbdSSowmini Varadhan (void) strlcpy(ebuf.eth_ptype, "current", sizeof (ebuf.eth_ptype)); 7563e7801d59Ssowmini 75644784fcbdSSowmini Varadhan (void) dladm_ether_autoneg2str(ebuf.eth_autoneg, 75654784fcbdSSowmini Varadhan sizeof (ebuf.eth_autoneg), &eattr, CURRENT); 75664784fcbdSSowmini Varadhan (void) dladm_ether_pause2str(ebuf.eth_pause, 75674784fcbdSSowmini Varadhan sizeof (ebuf.eth_pause), &eattr, CURRENT); 75684784fcbdSSowmini Varadhan (void) dladm_ether_spdx2str(ebuf.eth_spdx, 75694784fcbdSSowmini Varadhan sizeof (ebuf.eth_spdx), &eattr, CURRENT); 75704784fcbdSSowmini Varadhan (void) strlcpy(ebuf.eth_state, 75714784fcbdSSowmini Varadhan dladm_linkstate2str(eattr.lei_state, ebuf.eth_state), 75724784fcbdSSowmini Varadhan sizeof (ebuf.eth_state)); 75734784fcbdSSowmini Varadhan (void) strlcpy(ebuf.eth_rem_fault, 75744784fcbdSSowmini Varadhan (eattr.lei_attr[CURRENT].le_fault ? "fault" : "none"), 75754784fcbdSSowmini Varadhan sizeof (ebuf.eth_rem_fault)); 7576e7801d59Ssowmini 75778002d411SSowmini Varadhan ofmt_print(statep->es_ofmt, &ebuf); 7578e7801d59Ssowmini 7579e7801d59Ssowmini if (statep->es_extended) 75804784fcbdSSowmini Varadhan show_ether_xprop(arg, &eattr); 7581e7801d59Ssowmini 75824784fcbdSSowmini Varadhan cleanup: 75834784fcbdSSowmini Varadhan dladm_ether_info_done(&eattr); 7584e7801d59Ssowmini return (DLADM_WALK_CONTINUE); 7585e7801d59Ssowmini } 7586e7801d59Ssowmini 7587e7801d59Ssowmini /* ARGSUSED */ 7588e7801d59Ssowmini static void 75898d5c46e6Sam223141 do_init_secobj(int argc, char **argv, const char *use) 75900ba2cbe9Sxc151355 { 75910ba2cbe9Sxc151355 dladm_status_t status; 75920ba2cbe9Sxc151355 75934ac67f02SAnurag S. Maskey status = dladm_init_secobj(handle); 759433343a97Smeem if (status != DLADM_STATUS_OK) 759533343a97Smeem die_dlerr(status, "secure object initialization failed"); 759633343a97Smeem } 759733343a97Smeem 75984eaa4710SRishi Srivatsavai enum bridge_func { 75994eaa4710SRishi Srivatsavai brCreate, brAdd, brModify 76004eaa4710SRishi Srivatsavai }; 76014eaa4710SRishi Srivatsavai 76024eaa4710SRishi Srivatsavai static void 76034eaa4710SRishi Srivatsavai create_modify_add_bridge(int argc, char **argv, const char *use, 76044eaa4710SRishi Srivatsavai enum bridge_func func) 76054eaa4710SRishi Srivatsavai { 76064eaa4710SRishi Srivatsavai int option; 76074eaa4710SRishi Srivatsavai uint_t n, i, nlink; 76084eaa4710SRishi Srivatsavai uint32_t flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST; 76094eaa4710SRishi Srivatsavai char *altroot = NULL; 76104eaa4710SRishi Srivatsavai char *links[MAXPORT]; 76114eaa4710SRishi Srivatsavai datalink_id_t linkids[MAXPORT]; 76124eaa4710SRishi Srivatsavai dladm_status_t status; 76134eaa4710SRishi Srivatsavai const char *bridge; 76144eaa4710SRishi Srivatsavai UID_STP_CFG_T cfg, cfg_old; 76154eaa4710SRishi Srivatsavai dladm_bridge_prot_t brprot = DLADM_BRIDGE_PROT_UNKNOWN; 76164eaa4710SRishi Srivatsavai dladm_bridge_prot_t brprot_old; 76174eaa4710SRishi Srivatsavai 76184eaa4710SRishi Srivatsavai /* Set up the default configuration values */ 76194eaa4710SRishi Srivatsavai cfg.field_mask = 0; 76204eaa4710SRishi Srivatsavai cfg.bridge_priority = DEF_BR_PRIO; 76214eaa4710SRishi Srivatsavai cfg.max_age = DEF_BR_MAXAGE; 76224eaa4710SRishi Srivatsavai cfg.hello_time = DEF_BR_HELLOT; 76234eaa4710SRishi Srivatsavai cfg.forward_delay = DEF_BR_FWDELAY; 76244eaa4710SRishi Srivatsavai cfg.force_version = DEF_FORCE_VERS; 76254eaa4710SRishi Srivatsavai 76264eaa4710SRishi Srivatsavai nlink = opterr = 0; 76274eaa4710SRishi Srivatsavai while ((option = getopt_long(argc, argv, ":P:R:d:f:h:l:m:p:", 76284eaa4710SRishi Srivatsavai bridge_lopts, NULL)) != -1) { 76294eaa4710SRishi Srivatsavai switch (option) { 76304eaa4710SRishi Srivatsavai case 'P': 76314eaa4710SRishi Srivatsavai if (func == brAdd) 76324eaa4710SRishi Srivatsavai die_opterr(optopt, option, use); 76334eaa4710SRishi Srivatsavai status = dladm_bridge_str2prot(optarg, &brprot); 76344eaa4710SRishi Srivatsavai if (status != DLADM_STATUS_OK) 76354eaa4710SRishi Srivatsavai die_dlerr(status, "protection %s", optarg); 76364eaa4710SRishi Srivatsavai break; 76374eaa4710SRishi Srivatsavai case 'R': 76384eaa4710SRishi Srivatsavai altroot = optarg; 76394eaa4710SRishi Srivatsavai break; 76404eaa4710SRishi Srivatsavai case 'd': 76414eaa4710SRishi Srivatsavai if (func == brAdd) 76424eaa4710SRishi Srivatsavai die_opterr(optopt, option, use); 76434eaa4710SRishi Srivatsavai if (cfg.field_mask & BR_CFG_DELAY) 76444eaa4710SRishi Srivatsavai die("forwarding delay set more than once"); 76454eaa4710SRishi Srivatsavai if (!str2int(optarg, &cfg.forward_delay) || 76464eaa4710SRishi Srivatsavai cfg.forward_delay < MIN_BR_FWDELAY || 76474eaa4710SRishi Srivatsavai cfg.forward_delay > MAX_BR_FWDELAY) 76484eaa4710SRishi Srivatsavai die("incorrect forwarding delay"); 76494eaa4710SRishi Srivatsavai cfg.field_mask |= BR_CFG_DELAY; 76504eaa4710SRishi Srivatsavai break; 76514eaa4710SRishi Srivatsavai case 'f': 76524eaa4710SRishi Srivatsavai if (func == brAdd) 76534eaa4710SRishi Srivatsavai die_opterr(optopt, option, use); 76544eaa4710SRishi Srivatsavai if (cfg.field_mask & BR_CFG_FORCE_VER) 76554eaa4710SRishi Srivatsavai die("force protocol set more than once"); 76564eaa4710SRishi Srivatsavai if (!str2int(optarg, &cfg.force_version) || 76574eaa4710SRishi Srivatsavai cfg.force_version < 0) 76584eaa4710SRishi Srivatsavai die("incorrect force protocol"); 76594eaa4710SRishi Srivatsavai cfg.field_mask |= BR_CFG_FORCE_VER; 76604eaa4710SRishi Srivatsavai break; 76614eaa4710SRishi Srivatsavai case 'h': 76624eaa4710SRishi Srivatsavai if (func == brAdd) 76634eaa4710SRishi Srivatsavai die_opterr(optopt, option, use); 76644eaa4710SRishi Srivatsavai if (cfg.field_mask & BR_CFG_HELLO) 76654eaa4710SRishi Srivatsavai die("hello time set more than once"); 76664eaa4710SRishi Srivatsavai if (!str2int(optarg, &cfg.hello_time) || 76674eaa4710SRishi Srivatsavai cfg.hello_time < MIN_BR_HELLOT || 76684eaa4710SRishi Srivatsavai cfg.hello_time > MAX_BR_HELLOT) 76694eaa4710SRishi Srivatsavai die("incorrect hello time"); 76704eaa4710SRishi Srivatsavai cfg.field_mask |= BR_CFG_HELLO; 76714eaa4710SRishi Srivatsavai break; 76724eaa4710SRishi Srivatsavai case 'l': 76734eaa4710SRishi Srivatsavai if (func == brModify) 76744eaa4710SRishi Srivatsavai die_opterr(optopt, option, use); 76754eaa4710SRishi Srivatsavai if (nlink >= MAXPORT) 76764eaa4710SRishi Srivatsavai die("too many links specified"); 76774eaa4710SRishi Srivatsavai links[nlink++] = optarg; 76784eaa4710SRishi Srivatsavai break; 76794eaa4710SRishi Srivatsavai case 'm': 76804eaa4710SRishi Srivatsavai if (func == brAdd) 76814eaa4710SRishi Srivatsavai die_opterr(optopt, option, use); 76824eaa4710SRishi Srivatsavai if (cfg.field_mask & BR_CFG_AGE) 76834eaa4710SRishi Srivatsavai die("max age set more than once"); 76844eaa4710SRishi Srivatsavai if (!str2int(optarg, &cfg.max_age) || 76854eaa4710SRishi Srivatsavai cfg.max_age < MIN_BR_MAXAGE || 76864eaa4710SRishi Srivatsavai cfg.max_age > MAX_BR_MAXAGE) 76874eaa4710SRishi Srivatsavai die("incorrect max age"); 76884eaa4710SRishi Srivatsavai cfg.field_mask |= BR_CFG_AGE; 76894eaa4710SRishi Srivatsavai break; 76904eaa4710SRishi Srivatsavai case 'p': 76914eaa4710SRishi Srivatsavai if (func == brAdd) 76924eaa4710SRishi Srivatsavai die_opterr(optopt, option, use); 76934eaa4710SRishi Srivatsavai if (cfg.field_mask & BR_CFG_PRIO) 76944eaa4710SRishi Srivatsavai die("priority set more than once"); 76954eaa4710SRishi Srivatsavai if (!str2int(optarg, &cfg.bridge_priority) || 76964eaa4710SRishi Srivatsavai cfg.bridge_priority < MIN_BR_PRIO || 76974eaa4710SRishi Srivatsavai cfg.bridge_priority > MAX_BR_PRIO) 76984eaa4710SRishi Srivatsavai die("incorrect priority"); 76994eaa4710SRishi Srivatsavai cfg.bridge_priority &= 0xF000; 77004eaa4710SRishi Srivatsavai cfg.field_mask |= BR_CFG_PRIO; 77014eaa4710SRishi Srivatsavai break; 77024eaa4710SRishi Srivatsavai default: 77034eaa4710SRishi Srivatsavai die_opterr(optopt, option, use); 77044eaa4710SRishi Srivatsavai break; 77054eaa4710SRishi Srivatsavai } 77064eaa4710SRishi Srivatsavai } 77074eaa4710SRishi Srivatsavai 77084eaa4710SRishi Srivatsavai /* get the bridge name (required last argument) */ 77094eaa4710SRishi Srivatsavai if (optind != (argc-1)) 77104eaa4710SRishi Srivatsavai usage(); 77114eaa4710SRishi Srivatsavai 77124eaa4710SRishi Srivatsavai bridge = argv[optind]; 77134eaa4710SRishi Srivatsavai if (!dladm_valid_bridgename(bridge)) 77144eaa4710SRishi Srivatsavai die("invalid bridge name '%s'", bridge); 77154eaa4710SRishi Srivatsavai 77164eaa4710SRishi Srivatsavai /* 77174eaa4710SRishi Srivatsavai * Get the current properties, if any, and merge in with changes. This 77184eaa4710SRishi Srivatsavai * is necessary (even with the field_mask feature) so that the 77194eaa4710SRishi Srivatsavai * value-checking macros will produce the right results with proposed 77204eaa4710SRishi Srivatsavai * changes to existing configuration. We only need it for those 77214eaa4710SRishi Srivatsavai * parameters, though. 77224eaa4710SRishi Srivatsavai */ 77234eaa4710SRishi Srivatsavai (void) dladm_bridge_get_properties(bridge, &cfg_old, &brprot_old); 77244eaa4710SRishi Srivatsavai if (brprot == DLADM_BRIDGE_PROT_UNKNOWN) 77254eaa4710SRishi Srivatsavai brprot = brprot_old; 77264eaa4710SRishi Srivatsavai if (!(cfg.field_mask & BR_CFG_AGE)) 77274eaa4710SRishi Srivatsavai cfg.max_age = cfg_old.max_age; 77284eaa4710SRishi Srivatsavai if (!(cfg.field_mask & BR_CFG_HELLO)) 77294eaa4710SRishi Srivatsavai cfg.hello_time = cfg_old.hello_time; 77304eaa4710SRishi Srivatsavai if (!(cfg.field_mask & BR_CFG_DELAY)) 77314eaa4710SRishi Srivatsavai cfg.forward_delay = cfg_old.forward_delay; 77324eaa4710SRishi Srivatsavai 77334eaa4710SRishi Srivatsavai if (!CHECK_BRIDGE_CONFIG(cfg)) { 77344eaa4710SRishi Srivatsavai warn("illegal forward delay / max age / hello time " 77354eaa4710SRishi Srivatsavai "combination"); 77364eaa4710SRishi Srivatsavai if (NO_MAXAGE(cfg)) { 77374eaa4710SRishi Srivatsavai die("no max age possible: need forward delay >= %d or " 77384eaa4710SRishi Srivatsavai "hello time <= %d", MIN_FWDELAY_NOM(cfg), 77394eaa4710SRishi Srivatsavai MAX_HELLOTIME_NOM(cfg)); 77404eaa4710SRishi Srivatsavai } else if (SMALL_MAXAGE(cfg)) { 77414eaa4710SRishi Srivatsavai if (CAPPED_MAXAGE(cfg)) 77424eaa4710SRishi Srivatsavai die("max age too small: need age >= %d and " 77434eaa4710SRishi Srivatsavai "<= %d or hello time <= %d", 77444eaa4710SRishi Srivatsavai MIN_MAXAGE(cfg), MAX_MAXAGE(cfg), 77454eaa4710SRishi Srivatsavai MAX_HELLOTIME(cfg)); 77464eaa4710SRishi Srivatsavai else 77474eaa4710SRishi Srivatsavai die("max age too small: need age >= %d or " 77484eaa4710SRishi Srivatsavai "hello time <= %d", 77494eaa4710SRishi Srivatsavai MIN_MAXAGE(cfg), MAX_HELLOTIME(cfg)); 77504eaa4710SRishi Srivatsavai } else if (FLOORED_MAXAGE(cfg)) { 77514eaa4710SRishi Srivatsavai die("max age too large: need age >= %d and <= %d or " 77524eaa4710SRishi Srivatsavai "forward delay >= %d", 77534eaa4710SRishi Srivatsavai MIN_MAXAGE(cfg), MAX_MAXAGE(cfg), 77544eaa4710SRishi Srivatsavai MIN_FWDELAY(cfg)); 77554eaa4710SRishi Srivatsavai } else { 77564eaa4710SRishi Srivatsavai die("max age too large: need age <= %d or forward " 77574eaa4710SRishi Srivatsavai "delay >= %d", 77584eaa4710SRishi Srivatsavai MAX_MAXAGE(cfg), MIN_FWDELAY(cfg)); 77594eaa4710SRishi Srivatsavai } 77604eaa4710SRishi Srivatsavai } 77614eaa4710SRishi Srivatsavai 77624eaa4710SRishi Srivatsavai if (altroot != NULL) 77634eaa4710SRishi Srivatsavai altroot_cmd(altroot, argc, argv); 77644eaa4710SRishi Srivatsavai 77654eaa4710SRishi Srivatsavai for (n = 0; n < nlink; n++) { 77664eaa4710SRishi Srivatsavai datalink_class_t class; 77674eaa4710SRishi Srivatsavai uint32_t media; 77684eaa4710SRishi Srivatsavai char pointless[DLADM_STRSIZE]; 77694eaa4710SRishi Srivatsavai 77704eaa4710SRishi Srivatsavai if (dladm_name2info(handle, links[n], &linkids[n], NULL, &class, 77714eaa4710SRishi Srivatsavai &media) != DLADM_STATUS_OK) 77724eaa4710SRishi Srivatsavai die("invalid link name '%s'", links[n]); 77734eaa4710SRishi Srivatsavai if (class & ~(DATALINK_CLASS_PHYS | DATALINK_CLASS_AGGR | 77744eaa4710SRishi Srivatsavai DATALINK_CLASS_ETHERSTUB | DATALINK_CLASS_SIMNET)) 77754eaa4710SRishi Srivatsavai die("%s %s cannot be bridged", 77764eaa4710SRishi Srivatsavai dladm_class2str(class, pointless), links[n]); 77774eaa4710SRishi Srivatsavai if (media != DL_ETHER && media != DL_100VG && 77784eaa4710SRishi Srivatsavai media != DL_ETH_CSMA && media != DL_100BT) 77794eaa4710SRishi Srivatsavai die("%s interface %s cannot be bridged", 77804eaa4710SRishi Srivatsavai dladm_media2str(media, pointless), links[n]); 77814eaa4710SRishi Srivatsavai } 77824eaa4710SRishi Srivatsavai 77834eaa4710SRishi Srivatsavai if (func == brCreate) 77844eaa4710SRishi Srivatsavai flags |= DLADM_OPT_CREATE; 77854eaa4710SRishi Srivatsavai 77864eaa4710SRishi Srivatsavai if (func != brAdd) { 77874eaa4710SRishi Srivatsavai status = dladm_bridge_configure(handle, bridge, &cfg, brprot, 77884eaa4710SRishi Srivatsavai flags); 77894eaa4710SRishi Srivatsavai if (status != DLADM_STATUS_OK) 77904eaa4710SRishi Srivatsavai die_dlerr(status, "create operation failed"); 77914eaa4710SRishi Srivatsavai } 77924eaa4710SRishi Srivatsavai 77934eaa4710SRishi Srivatsavai status = DLADM_STATUS_OK; 77944eaa4710SRishi Srivatsavai for (n = 0; n < nlink; n++) { 77954eaa4710SRishi Srivatsavai status = dladm_bridge_setlink(handle, linkids[n], bridge); 77964eaa4710SRishi Srivatsavai if (status != DLADM_STATUS_OK) 77974eaa4710SRishi Srivatsavai break; 77984eaa4710SRishi Srivatsavai } 77994eaa4710SRishi Srivatsavai 78004eaa4710SRishi Srivatsavai if (n >= nlink) { 78014eaa4710SRishi Srivatsavai /* 78024eaa4710SRishi Srivatsavai * We were successful. If we're creating a new bridge, then 78034eaa4710SRishi Srivatsavai * there's just one more step: enabling. If we're modifying or 78044eaa4710SRishi Srivatsavai * just adding links, then we're done. 78054eaa4710SRishi Srivatsavai */ 78064eaa4710SRishi Srivatsavai if (func != brCreate || 78074eaa4710SRishi Srivatsavai (status = dladm_bridge_enable(bridge)) == DLADM_STATUS_OK) 78084eaa4710SRishi Srivatsavai return; 78094eaa4710SRishi Srivatsavai } 78104eaa4710SRishi Srivatsavai 78114eaa4710SRishi Srivatsavai /* clean up the partial configuration */ 78124eaa4710SRishi Srivatsavai for (i = 0; i < n; i++) 78134eaa4710SRishi Srivatsavai (void) dladm_bridge_setlink(handle, linkids[i], ""); 78144eaa4710SRishi Srivatsavai 78154eaa4710SRishi Srivatsavai /* if failure for brCreate, then delete the bridge */ 78164eaa4710SRishi Srivatsavai if (func == brCreate) 78174eaa4710SRishi Srivatsavai (void) dladm_bridge_delete(handle, bridge, flags); 78184eaa4710SRishi Srivatsavai 78194eaa4710SRishi Srivatsavai if (n < nlink) 78204eaa4710SRishi Srivatsavai die_dlerr(status, "unable to add link %s to bridge %s", 78214eaa4710SRishi Srivatsavai links[n], bridge); 78224eaa4710SRishi Srivatsavai else 78234eaa4710SRishi Srivatsavai die_dlerr(status, "unable to enable bridge %s", bridge); 78244eaa4710SRishi Srivatsavai } 78254eaa4710SRishi Srivatsavai 78264eaa4710SRishi Srivatsavai static void 78274eaa4710SRishi Srivatsavai do_create_bridge(int argc, char **argv, const char *use) 78284eaa4710SRishi Srivatsavai { 78294eaa4710SRishi Srivatsavai create_modify_add_bridge(argc, argv, use, brCreate); 78304eaa4710SRishi Srivatsavai } 78314eaa4710SRishi Srivatsavai 78324eaa4710SRishi Srivatsavai static void 78334eaa4710SRishi Srivatsavai do_modify_bridge(int argc, char **argv, const char *use) 78344eaa4710SRishi Srivatsavai { 78354eaa4710SRishi Srivatsavai create_modify_add_bridge(argc, argv, use, brModify); 78364eaa4710SRishi Srivatsavai } 78374eaa4710SRishi Srivatsavai 78384eaa4710SRishi Srivatsavai static void 78394eaa4710SRishi Srivatsavai do_add_bridge(int argc, char **argv, const char *use) 78404eaa4710SRishi Srivatsavai { 78414eaa4710SRishi Srivatsavai create_modify_add_bridge(argc, argv, use, brAdd); 78424eaa4710SRishi Srivatsavai } 78434eaa4710SRishi Srivatsavai 78444eaa4710SRishi Srivatsavai static void 78454eaa4710SRishi Srivatsavai do_delete_bridge(int argc, char **argv, const char *use) 78464eaa4710SRishi Srivatsavai { 78474eaa4710SRishi Srivatsavai char option; 78484eaa4710SRishi Srivatsavai char *altroot = NULL; 78494eaa4710SRishi Srivatsavai uint32_t flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST; 78504eaa4710SRishi Srivatsavai dladm_status_t status; 78514eaa4710SRishi Srivatsavai 78524eaa4710SRishi Srivatsavai opterr = 0; 78534eaa4710SRishi Srivatsavai while ((option = getopt_long(argc, argv, ":R:", bridge_lopts, NULL)) != 78544eaa4710SRishi Srivatsavai -1) { 78554eaa4710SRishi Srivatsavai switch (option) { 78564eaa4710SRishi Srivatsavai case 'R': 78574eaa4710SRishi Srivatsavai altroot = optarg; 78584eaa4710SRishi Srivatsavai break; 78594eaa4710SRishi Srivatsavai default: 78604eaa4710SRishi Srivatsavai die_opterr(optopt, option, use); 78614eaa4710SRishi Srivatsavai break; 78624eaa4710SRishi Srivatsavai } 78634eaa4710SRishi Srivatsavai } 78644eaa4710SRishi Srivatsavai 78654eaa4710SRishi Srivatsavai /* get the bridge name (required last argument) */ 78664eaa4710SRishi Srivatsavai if (optind != (argc-1)) 78674eaa4710SRishi Srivatsavai usage(); 78684eaa4710SRishi Srivatsavai 78694eaa4710SRishi Srivatsavai if (altroot != NULL) 78704eaa4710SRishi Srivatsavai altroot_cmd(altroot, argc, argv); 78714eaa4710SRishi Srivatsavai 78724eaa4710SRishi Srivatsavai status = dladm_bridge_delete(handle, argv[optind], flags); 78734eaa4710SRishi Srivatsavai if (status != DLADM_STATUS_OK) 78744eaa4710SRishi Srivatsavai die_dlerr(status, "delete operation failed"); 78754eaa4710SRishi Srivatsavai } 78764eaa4710SRishi Srivatsavai 78774eaa4710SRishi Srivatsavai static void 78784eaa4710SRishi Srivatsavai do_remove_bridge(int argc, char **argv, const char *use) 78794eaa4710SRishi Srivatsavai { 78804eaa4710SRishi Srivatsavai char option; 78814eaa4710SRishi Srivatsavai uint_t n, nlink; 78824eaa4710SRishi Srivatsavai char *links[MAXPORT]; 78834eaa4710SRishi Srivatsavai datalink_id_t linkids[MAXPORT]; 78844eaa4710SRishi Srivatsavai char *altroot = NULL; 78854eaa4710SRishi Srivatsavai dladm_status_t status; 78864eaa4710SRishi Srivatsavai boolean_t removed_one; 78874eaa4710SRishi Srivatsavai 78884eaa4710SRishi Srivatsavai nlink = opterr = 0; 78894eaa4710SRishi Srivatsavai while ((option = getopt_long(argc, argv, ":R:l:", bridge_lopts, 78904eaa4710SRishi Srivatsavai NULL)) != -1) { 78914eaa4710SRishi Srivatsavai switch (option) { 78924eaa4710SRishi Srivatsavai case 'R': 78934eaa4710SRishi Srivatsavai altroot = optarg; 78944eaa4710SRishi Srivatsavai break; 78954eaa4710SRishi Srivatsavai case 'l': 78964eaa4710SRishi Srivatsavai if (nlink >= MAXPORT) 78974eaa4710SRishi Srivatsavai die("too many links specified"); 78984eaa4710SRishi Srivatsavai links[nlink++] = optarg; 78994eaa4710SRishi Srivatsavai break; 79004eaa4710SRishi Srivatsavai default: 79014eaa4710SRishi Srivatsavai die_opterr(optopt, option, use); 79024eaa4710SRishi Srivatsavai break; 79034eaa4710SRishi Srivatsavai } 79044eaa4710SRishi Srivatsavai } 79054eaa4710SRishi Srivatsavai 79064eaa4710SRishi Srivatsavai if (nlink == 0) 79074eaa4710SRishi Srivatsavai usage(); 79084eaa4710SRishi Srivatsavai 79094eaa4710SRishi Srivatsavai /* get the bridge name (required last argument) */ 79104eaa4710SRishi Srivatsavai if (optind != (argc-1)) 79114eaa4710SRishi Srivatsavai usage(); 79124eaa4710SRishi Srivatsavai 79134eaa4710SRishi Srivatsavai if (altroot != NULL) 79144eaa4710SRishi Srivatsavai altroot_cmd(altroot, argc, argv); 79154eaa4710SRishi Srivatsavai 79164eaa4710SRishi Srivatsavai for (n = 0; n < nlink; n++) { 79174eaa4710SRishi Srivatsavai char bridge[MAXLINKNAMELEN]; 79184eaa4710SRishi Srivatsavai 79194eaa4710SRishi Srivatsavai if (dladm_name2info(handle, links[n], &linkids[n], NULL, NULL, 79204eaa4710SRishi Srivatsavai NULL) != DLADM_STATUS_OK) 79214eaa4710SRishi Srivatsavai die("invalid link name '%s'", links[n]); 79224eaa4710SRishi Srivatsavai status = dladm_bridge_getlink(handle, linkids[n], bridge, 79234eaa4710SRishi Srivatsavai sizeof (bridge)); 79244eaa4710SRishi Srivatsavai if (status != DLADM_STATUS_OK && 79254eaa4710SRishi Srivatsavai status != DLADM_STATUS_NOTFOUND) { 79264eaa4710SRishi Srivatsavai die_dlerr(status, "cannot get bridge status on %s", 79274eaa4710SRishi Srivatsavai links[n]); 79284eaa4710SRishi Srivatsavai } 79294eaa4710SRishi Srivatsavai if (status == DLADM_STATUS_NOTFOUND || 79304eaa4710SRishi Srivatsavai strcmp(bridge, argv[optind]) != 0) 79314eaa4710SRishi Srivatsavai die("link %s is not on bridge %s", links[n], 79324eaa4710SRishi Srivatsavai argv[optind]); 79334eaa4710SRishi Srivatsavai } 79344eaa4710SRishi Srivatsavai 79354eaa4710SRishi Srivatsavai removed_one = B_FALSE; 79364eaa4710SRishi Srivatsavai for (n = 0; n < nlink; n++) { 79374eaa4710SRishi Srivatsavai status = dladm_bridge_setlink(handle, linkids[n], ""); 79384eaa4710SRishi Srivatsavai if (status == DLADM_STATUS_OK) { 79394eaa4710SRishi Srivatsavai removed_one = B_TRUE; 79404eaa4710SRishi Srivatsavai } else { 79414eaa4710SRishi Srivatsavai warn_dlerr(status, 79424eaa4710SRishi Srivatsavai "cannot remove link %s from bridge %s", 79434eaa4710SRishi Srivatsavai links[n], argv[optind]); 79444eaa4710SRishi Srivatsavai } 79454eaa4710SRishi Srivatsavai } 79464eaa4710SRishi Srivatsavai if (!removed_one) 79474eaa4710SRishi Srivatsavai die("unable to remove any links from bridge %s", argv[optind]); 79484eaa4710SRishi Srivatsavai } 79494eaa4710SRishi Srivatsavai 79504eaa4710SRishi Srivatsavai static void 79514eaa4710SRishi Srivatsavai fmt_int(char *buf, size_t buflen, int value, int runvalue, 79524eaa4710SRishi Srivatsavai boolean_t printstar) 79534eaa4710SRishi Srivatsavai { 79544eaa4710SRishi Srivatsavai (void) snprintf(buf, buflen, "%d", value); 79554eaa4710SRishi Srivatsavai if (value != runvalue && printstar) 79564eaa4710SRishi Srivatsavai (void) strlcat(buf, "*", buflen); 79574eaa4710SRishi Srivatsavai } 79584eaa4710SRishi Srivatsavai 79594eaa4710SRishi Srivatsavai static void 79604eaa4710SRishi Srivatsavai fmt_bridge_id(char *buf, size_t buflen, UID_BRIDGE_ID_T *bid) 79614eaa4710SRishi Srivatsavai { 79624eaa4710SRishi Srivatsavai (void) snprintf(buf, buflen, "%u/%x:%x:%x:%x:%x:%x", bid->prio, 79634eaa4710SRishi Srivatsavai bid->addr[0], bid->addr[1], bid->addr[2], bid->addr[3], 79644eaa4710SRishi Srivatsavai bid->addr[4], bid->addr[5]); 79654eaa4710SRishi Srivatsavai } 79664eaa4710SRishi Srivatsavai 79674eaa4710SRishi Srivatsavai static dladm_status_t 79684eaa4710SRishi Srivatsavai print_bridge(show_state_t *state, datalink_id_t linkid, 79694eaa4710SRishi Srivatsavai bridge_fields_buf_t *bbuf) 79704eaa4710SRishi Srivatsavai { 79714eaa4710SRishi Srivatsavai char link[MAXLINKNAMELEN]; 79724eaa4710SRishi Srivatsavai datalink_class_t class; 79734eaa4710SRishi Srivatsavai uint32_t flags; 79744eaa4710SRishi Srivatsavai dladm_status_t status; 79754eaa4710SRishi Srivatsavai UID_STP_CFG_T smfcfg, runcfg; 79764eaa4710SRishi Srivatsavai UID_STP_STATE_T stpstate; 79774eaa4710SRishi Srivatsavai dladm_bridge_prot_t smfprot, runprot; 79784eaa4710SRishi Srivatsavai 79794eaa4710SRishi Srivatsavai if ((status = dladm_datalink_id2info(handle, linkid, &flags, &class, 79804eaa4710SRishi Srivatsavai NULL, link, sizeof (link))) != DLADM_STATUS_OK) 79814eaa4710SRishi Srivatsavai return (status); 79824eaa4710SRishi Srivatsavai 79834eaa4710SRishi Srivatsavai if (!(state->ls_flags & flags)) 79844eaa4710SRishi Srivatsavai return (DLADM_STATUS_NOTFOUND); 79854eaa4710SRishi Srivatsavai 79864eaa4710SRishi Srivatsavai /* Convert observability node name back to bridge name */ 79874eaa4710SRishi Srivatsavai if (!dladm_observe_to_bridge(link)) 79884eaa4710SRishi Srivatsavai return (DLADM_STATUS_NOTFOUND); 79894eaa4710SRishi Srivatsavai (void) strlcpy(bbuf->bridge_name, link, sizeof (bbuf->bridge_name)); 79904eaa4710SRishi Srivatsavai 79914eaa4710SRishi Srivatsavai /* 79924eaa4710SRishi Srivatsavai * If the running value differs from the one in SMF, and parsable 79934eaa4710SRishi Srivatsavai * output is not requested, then we show the running value with an 79944eaa4710SRishi Srivatsavai * asterisk. 79954eaa4710SRishi Srivatsavai */ 79964eaa4710SRishi Srivatsavai (void) dladm_bridge_get_properties(bbuf->bridge_name, &smfcfg, 79974eaa4710SRishi Srivatsavai &smfprot); 79984eaa4710SRishi Srivatsavai (void) dladm_bridge_run_properties(bbuf->bridge_name, &runcfg, 79994eaa4710SRishi Srivatsavai &runprot); 80004eaa4710SRishi Srivatsavai (void) snprintf(bbuf->bridge_protect, sizeof (bbuf->bridge_protect), 80014eaa4710SRishi Srivatsavai "%s%s", state->ls_parsable || smfprot == runprot ? "" : "*", 80024eaa4710SRishi Srivatsavai dladm_bridge_prot2str(runprot)); 80034eaa4710SRishi Srivatsavai fmt_int(bbuf->bridge_priority, sizeof (bbuf->bridge_priority), 80044eaa4710SRishi Srivatsavai smfcfg.bridge_priority, runcfg.bridge_priority, 80054eaa4710SRishi Srivatsavai !state->ls_parsable && (runcfg.field_mask & BR_CFG_AGE)); 80064eaa4710SRishi Srivatsavai fmt_int(bbuf->bridge_bmaxage, sizeof (bbuf->bridge_bmaxage), 80074eaa4710SRishi Srivatsavai smfcfg.max_age, runcfg.max_age, 80084eaa4710SRishi Srivatsavai !state->ls_parsable && (runcfg.field_mask & BR_CFG_AGE)); 80094eaa4710SRishi Srivatsavai fmt_int(bbuf->bridge_bhellotime, 80104eaa4710SRishi Srivatsavai sizeof (bbuf->bridge_bhellotime), smfcfg.hello_time, 80114eaa4710SRishi Srivatsavai runcfg.hello_time, 80124eaa4710SRishi Srivatsavai !state->ls_parsable && (runcfg.field_mask & BR_CFG_HELLO)); 80134eaa4710SRishi Srivatsavai fmt_int(bbuf->bridge_bfwddelay, sizeof (bbuf->bridge_bfwddelay), 80144eaa4710SRishi Srivatsavai smfcfg.forward_delay, runcfg.forward_delay, 80154eaa4710SRishi Srivatsavai !state->ls_parsable && (runcfg.field_mask & BR_CFG_DELAY)); 80164eaa4710SRishi Srivatsavai fmt_int(bbuf->bridge_forceproto, sizeof (bbuf->bridge_forceproto), 80174eaa4710SRishi Srivatsavai smfcfg.force_version, runcfg.force_version, 80184eaa4710SRishi Srivatsavai !state->ls_parsable && (runcfg.field_mask & BR_CFG_FORCE_VER)); 80194eaa4710SRishi Srivatsavai fmt_int(bbuf->bridge_holdtime, sizeof (bbuf->bridge_holdtime), 80204eaa4710SRishi Srivatsavai smfcfg.hold_time, runcfg.hold_time, 80214eaa4710SRishi Srivatsavai !state->ls_parsable && (runcfg.field_mask & BR_CFG_HOLD_TIME)); 80224eaa4710SRishi Srivatsavai 80234eaa4710SRishi Srivatsavai if (dladm_bridge_state(bbuf->bridge_name, &stpstate) == 80244eaa4710SRishi Srivatsavai DLADM_STATUS_OK) { 80254eaa4710SRishi Srivatsavai fmt_bridge_id(bbuf->bridge_address, 80264eaa4710SRishi Srivatsavai sizeof (bbuf->bridge_address), &stpstate.bridge_id); 80274eaa4710SRishi Srivatsavai (void) snprintf(bbuf->bridge_tctime, 80284eaa4710SRishi Srivatsavai sizeof (bbuf->bridge_tctime), "%lu", 80294eaa4710SRishi Srivatsavai stpstate.timeSince_Topo_Change); 80304eaa4710SRishi Srivatsavai (void) snprintf(bbuf->bridge_tccount, 80314eaa4710SRishi Srivatsavai sizeof (bbuf->bridge_tccount), "%lu", 80324eaa4710SRishi Srivatsavai stpstate.Topo_Change_Count); 80334eaa4710SRishi Srivatsavai (void) snprintf(bbuf->bridge_tchange, 80344eaa4710SRishi Srivatsavai sizeof (bbuf->bridge_tchange), "%u", stpstate.Topo_Change); 80354eaa4710SRishi Srivatsavai fmt_bridge_id(bbuf->bridge_desroot, 80364eaa4710SRishi Srivatsavai sizeof (bbuf->bridge_desroot), &stpstate.designated_root); 80374eaa4710SRishi Srivatsavai (void) snprintf(bbuf->bridge_rootcost, 80384eaa4710SRishi Srivatsavai sizeof (bbuf->bridge_rootcost), "%lu", 80394eaa4710SRishi Srivatsavai stpstate.root_path_cost); 80404eaa4710SRishi Srivatsavai (void) snprintf(bbuf->bridge_rootport, 80414eaa4710SRishi Srivatsavai sizeof (bbuf->bridge_rootport), "%u", stpstate.root_port); 80424eaa4710SRishi Srivatsavai (void) snprintf(bbuf->bridge_maxage, 80434eaa4710SRishi Srivatsavai sizeof (bbuf->bridge_maxage), "%d", stpstate.max_age); 80444eaa4710SRishi Srivatsavai (void) snprintf(bbuf->bridge_hellotime, 80454eaa4710SRishi Srivatsavai sizeof (bbuf->bridge_hellotime), "%d", stpstate.hello_time); 80464eaa4710SRishi Srivatsavai (void) snprintf(bbuf->bridge_fwddelay, 80474eaa4710SRishi Srivatsavai sizeof (bbuf->bridge_fwddelay), "%d", 80484eaa4710SRishi Srivatsavai stpstate.forward_delay); 80494eaa4710SRishi Srivatsavai } 80504eaa4710SRishi Srivatsavai return (DLADM_STATUS_OK); 80514eaa4710SRishi Srivatsavai } 80524eaa4710SRishi Srivatsavai 80534eaa4710SRishi Srivatsavai static dladm_status_t 80544eaa4710SRishi Srivatsavai print_bridge_stats(show_state_t *state, datalink_id_t linkid, 80554eaa4710SRishi Srivatsavai bridge_statfields_buf_t *bbuf) 80564eaa4710SRishi Srivatsavai { 80574eaa4710SRishi Srivatsavai char link[MAXLINKNAMELEN]; 80584eaa4710SRishi Srivatsavai datalink_class_t class; 80594eaa4710SRishi Srivatsavai uint32_t flags; 80604eaa4710SRishi Srivatsavai dladm_status_t status; 80614eaa4710SRishi Srivatsavai kstat_ctl_t *kcp; 80624eaa4710SRishi Srivatsavai kstat_t *ksp; 80634eaa4710SRishi Srivatsavai brsum_t *brsum = (brsum_t *)&state->ls_prevstats; 80644eaa4710SRishi Srivatsavai brsum_t newval; 80654eaa4710SRishi Srivatsavai 80664eaa4710SRishi Srivatsavai #ifndef lint 80674eaa4710SRishi Srivatsavai /* This is a compile-time assertion; optimizer normally fixes this */ 80684eaa4710SRishi Srivatsavai extern void brsum_t_is_too_large(void); 80694eaa4710SRishi Srivatsavai 80704eaa4710SRishi Srivatsavai if (sizeof (*brsum) > sizeof (state->ls_prevstats)) 80714eaa4710SRishi Srivatsavai brsum_t_is_too_large(); 80724eaa4710SRishi Srivatsavai #endif 80734eaa4710SRishi Srivatsavai 80744eaa4710SRishi Srivatsavai if (state->ls_firstonly) { 80754eaa4710SRishi Srivatsavai if (state->ls_donefirst) 80764eaa4710SRishi Srivatsavai return (DLADM_WALK_CONTINUE); 80774eaa4710SRishi Srivatsavai state->ls_donefirst = B_TRUE; 80784eaa4710SRishi Srivatsavai } else { 80794eaa4710SRishi Srivatsavai bzero(brsum, sizeof (*brsum)); 80804eaa4710SRishi Srivatsavai } 80814eaa4710SRishi Srivatsavai bzero(&newval, sizeof (newval)); 80824eaa4710SRishi Srivatsavai 80834eaa4710SRishi Srivatsavai if ((status = dladm_datalink_id2info(handle, linkid, &flags, &class, 80844eaa4710SRishi Srivatsavai NULL, link, sizeof (link))) != DLADM_STATUS_OK) 80854eaa4710SRishi Srivatsavai return (status); 80864eaa4710SRishi Srivatsavai 80874eaa4710SRishi Srivatsavai if (!(state->ls_flags & flags)) 80884eaa4710SRishi Srivatsavai return (DLADM_STATUS_NOTFOUND); 80894eaa4710SRishi Srivatsavai 80904eaa4710SRishi Srivatsavai if ((kcp = kstat_open()) == NULL) { 80914eaa4710SRishi Srivatsavai warn("kstat open operation failed"); 80924eaa4710SRishi Srivatsavai return (DLADM_STATUS_OK); 80934eaa4710SRishi Srivatsavai } 80944eaa4710SRishi Srivatsavai if ((ksp = kstat_lookup(kcp, "bridge", 0, link)) != NULL && 80954eaa4710SRishi Srivatsavai kstat_read(kcp, ksp, NULL) != -1) { 80964eaa4710SRishi Srivatsavai if (dladm_kstat_value(ksp, "drops", KSTAT_DATA_UINT64, 80974eaa4710SRishi Srivatsavai &newval.drops) == DLADM_STATUS_OK) { 80984eaa4710SRishi Srivatsavai (void) snprintf(bbuf->bridges_drops, 80994eaa4710SRishi Srivatsavai sizeof (bbuf->bridges_drops), "%llu", 81004eaa4710SRishi Srivatsavai newval.drops - brsum->drops); 81014eaa4710SRishi Srivatsavai } 81024eaa4710SRishi Srivatsavai if (dladm_kstat_value(ksp, "forward_direct", KSTAT_DATA_UINT64, 81034eaa4710SRishi Srivatsavai &newval.forward_dir) == DLADM_STATUS_OK) { 81044eaa4710SRishi Srivatsavai (void) snprintf(bbuf->bridges_forwards, 81054eaa4710SRishi Srivatsavai sizeof (bbuf->bridges_forwards), "%llu", 81064eaa4710SRishi Srivatsavai newval.forward_dir - brsum->forward_dir); 81074eaa4710SRishi Srivatsavai } 81084eaa4710SRishi Srivatsavai if (dladm_kstat_value(ksp, "forward_mbcast", KSTAT_DATA_UINT64, 81094eaa4710SRishi Srivatsavai &newval.forward_mb) == DLADM_STATUS_OK) { 81104eaa4710SRishi Srivatsavai (void) snprintf(bbuf->bridges_mbcast, 81114eaa4710SRishi Srivatsavai sizeof (bbuf->bridges_mbcast), "%llu", 81124eaa4710SRishi Srivatsavai newval.forward_mb - brsum->forward_mb); 81134eaa4710SRishi Srivatsavai } 81144eaa4710SRishi Srivatsavai if (dladm_kstat_value(ksp, "forward_unknown", KSTAT_DATA_UINT64, 81154eaa4710SRishi Srivatsavai &newval.forward_unk) == DLADM_STATUS_OK) { 81164eaa4710SRishi Srivatsavai (void) snprintf(bbuf->bridges_unknown, 81174eaa4710SRishi Srivatsavai sizeof (bbuf->bridges_unknown), "%llu", 81184eaa4710SRishi Srivatsavai newval.forward_unk - brsum->forward_unk); 81194eaa4710SRishi Srivatsavai } 81204eaa4710SRishi Srivatsavai if (dladm_kstat_value(ksp, "recv", KSTAT_DATA_UINT64, 81214eaa4710SRishi Srivatsavai &newval.recv) == DLADM_STATUS_OK) { 81224eaa4710SRishi Srivatsavai (void) snprintf(bbuf->bridges_recv, 81234eaa4710SRishi Srivatsavai sizeof (bbuf->bridges_recv), "%llu", 81244eaa4710SRishi Srivatsavai newval.recv - brsum->recv); 81254eaa4710SRishi Srivatsavai } 81264eaa4710SRishi Srivatsavai if (dladm_kstat_value(ksp, "sent", KSTAT_DATA_UINT64, 81274eaa4710SRishi Srivatsavai &newval.sent) == DLADM_STATUS_OK) { 81284eaa4710SRishi Srivatsavai (void) snprintf(bbuf->bridges_sent, 81294eaa4710SRishi Srivatsavai sizeof (bbuf->bridges_sent), "%llu", 81304eaa4710SRishi Srivatsavai newval.sent - brsum->sent); 81314eaa4710SRishi Srivatsavai } 81324eaa4710SRishi Srivatsavai } 81334eaa4710SRishi Srivatsavai (void) kstat_close(kcp); 81344eaa4710SRishi Srivatsavai 81354eaa4710SRishi Srivatsavai /* Convert observability node name back to bridge name */ 81364eaa4710SRishi Srivatsavai if (!dladm_observe_to_bridge(link)) 81374eaa4710SRishi Srivatsavai return (DLADM_STATUS_NOTFOUND); 81384eaa4710SRishi Srivatsavai (void) strlcpy(bbuf->bridges_name, link, sizeof (bbuf->bridges_name)); 81394eaa4710SRishi Srivatsavai 81404eaa4710SRishi Srivatsavai *brsum = newval; 81414eaa4710SRishi Srivatsavai 81424eaa4710SRishi Srivatsavai return (DLADM_STATUS_OK); 81434eaa4710SRishi Srivatsavai } 81444eaa4710SRishi Srivatsavai 81454eaa4710SRishi Srivatsavai /* 81464eaa4710SRishi Srivatsavai * This structure carries around extra state information for the show-bridge 81474eaa4710SRishi Srivatsavai * command and allows us to use common support functions. 81484eaa4710SRishi Srivatsavai */ 81494eaa4710SRishi Srivatsavai typedef struct { 81504eaa4710SRishi Srivatsavai show_state_t state; 81514eaa4710SRishi Srivatsavai boolean_t show_stats; 81524eaa4710SRishi Srivatsavai const char *bridge; 81534eaa4710SRishi Srivatsavai } show_brstate_t; 81544eaa4710SRishi Srivatsavai 81554eaa4710SRishi Srivatsavai /* ARGSUSED */ 81564eaa4710SRishi Srivatsavai static int 81574eaa4710SRishi Srivatsavai show_bridge(dladm_handle_t handle, datalink_id_t linkid, void *arg) 81584eaa4710SRishi Srivatsavai { 81594eaa4710SRishi Srivatsavai show_brstate_t *brstate = arg; 81604eaa4710SRishi Srivatsavai void *buf; 81614eaa4710SRishi Srivatsavai 81624eaa4710SRishi Srivatsavai if (brstate->show_stats) { 81634eaa4710SRishi Srivatsavai bridge_statfields_buf_t bbuf; 81644eaa4710SRishi Srivatsavai 81654eaa4710SRishi Srivatsavai bzero(&bbuf, sizeof (bbuf)); 81664eaa4710SRishi Srivatsavai brstate->state.ls_status = print_bridge_stats(&brstate->state, 81674eaa4710SRishi Srivatsavai linkid, &bbuf); 81684eaa4710SRishi Srivatsavai buf = &bbuf; 81694eaa4710SRishi Srivatsavai } else { 81704eaa4710SRishi Srivatsavai bridge_fields_buf_t bbuf; 81714eaa4710SRishi Srivatsavai 81724eaa4710SRishi Srivatsavai bzero(&bbuf, sizeof (bbuf)); 81734eaa4710SRishi Srivatsavai brstate->state.ls_status = print_bridge(&brstate->state, linkid, 81744eaa4710SRishi Srivatsavai &bbuf); 81754eaa4710SRishi Srivatsavai buf = &bbuf; 81764eaa4710SRishi Srivatsavai } 81774eaa4710SRishi Srivatsavai if (brstate->state.ls_status == DLADM_STATUS_OK) 81784eaa4710SRishi Srivatsavai ofmt_print(brstate->state.ls_ofmt, buf); 81794eaa4710SRishi Srivatsavai return (DLADM_WALK_CONTINUE); 81804eaa4710SRishi Srivatsavai } 81814eaa4710SRishi Srivatsavai 81824eaa4710SRishi Srivatsavai static void 81834eaa4710SRishi Srivatsavai fmt_bool(char *buf, size_t buflen, int val) 81844eaa4710SRishi Srivatsavai { 81854eaa4710SRishi Srivatsavai (void) strlcpy(buf, val ? "yes" : "no", buflen); 81864eaa4710SRishi Srivatsavai } 81874eaa4710SRishi Srivatsavai 81884eaa4710SRishi Srivatsavai static dladm_status_t 81894eaa4710SRishi Srivatsavai print_bridge_link(show_state_t *state, datalink_id_t linkid, 81904eaa4710SRishi Srivatsavai bridge_link_fields_buf_t *bbuf) 81914eaa4710SRishi Srivatsavai { 81924eaa4710SRishi Srivatsavai datalink_class_t class; 81934eaa4710SRishi Srivatsavai uint32_t flags; 81944eaa4710SRishi Srivatsavai dladm_status_t status; 81954eaa4710SRishi Srivatsavai UID_STP_PORT_STATE_T stpstate; 81964eaa4710SRishi Srivatsavai 81974eaa4710SRishi Srivatsavai status = dladm_datalink_id2info(handle, linkid, &flags, &class, NULL, 81984eaa4710SRishi Srivatsavai bbuf->bridgel_link, sizeof (bbuf->bridgel_link)); 81994eaa4710SRishi Srivatsavai if (status != DLADM_STATUS_OK) 82004eaa4710SRishi Srivatsavai return (status); 82014eaa4710SRishi Srivatsavai 82024eaa4710SRishi Srivatsavai if (!(state->ls_flags & flags)) 82034eaa4710SRishi Srivatsavai return (DLADM_STATUS_NOTFOUND); 82044eaa4710SRishi Srivatsavai 82054eaa4710SRishi Srivatsavai if (dladm_bridge_link_state(handle, linkid, &stpstate) == 82064eaa4710SRishi Srivatsavai DLADM_STATUS_OK) { 82074eaa4710SRishi Srivatsavai (void) snprintf(bbuf->bridgel_index, 82084eaa4710SRishi Srivatsavai sizeof (bbuf->bridgel_index), "%u", stpstate.port_no); 82094eaa4710SRishi Srivatsavai if (dlsym(RTLD_PROBE, "STP_IN_state2str")) { 82104eaa4710SRishi Srivatsavai (void) strlcpy(bbuf->bridgel_state, 82114eaa4710SRishi Srivatsavai STP_IN_state2str(stpstate.state), 82124eaa4710SRishi Srivatsavai sizeof (bbuf->bridgel_state)); 82134eaa4710SRishi Srivatsavai } else { 82144eaa4710SRishi Srivatsavai (void) snprintf(bbuf->bridgel_state, 82154eaa4710SRishi Srivatsavai sizeof (bbuf->bridgel_state), "%u", 82164eaa4710SRishi Srivatsavai stpstate.state); 82174eaa4710SRishi Srivatsavai } 82184eaa4710SRishi Srivatsavai (void) snprintf(bbuf->bridgel_uptime, 82194eaa4710SRishi Srivatsavai sizeof (bbuf->bridgel_uptime), "%lu", stpstate.uptime); 82204eaa4710SRishi Srivatsavai (void) snprintf(bbuf->bridgel_opercost, 82214eaa4710SRishi Srivatsavai sizeof (bbuf->bridgel_opercost), "%lu", 82224eaa4710SRishi Srivatsavai stpstate.oper_port_path_cost); 82234eaa4710SRishi Srivatsavai fmt_bool(bbuf->bridgel_operp2p, sizeof (bbuf->bridgel_operp2p), 82244eaa4710SRishi Srivatsavai stpstate.oper_point2point); 82254eaa4710SRishi Srivatsavai fmt_bool(bbuf->bridgel_operedge, 82264eaa4710SRishi Srivatsavai sizeof (bbuf->bridgel_operedge), stpstate.oper_edge); 82274eaa4710SRishi Srivatsavai fmt_bridge_id(bbuf->bridgel_desroot, 82284eaa4710SRishi Srivatsavai sizeof (bbuf->bridgel_desroot), &stpstate.designated_root); 82294eaa4710SRishi Srivatsavai (void) snprintf(bbuf->bridgel_descost, 82304eaa4710SRishi Srivatsavai sizeof (bbuf->bridgel_descost), "%lu", 82314eaa4710SRishi Srivatsavai stpstate.designated_cost); 82324eaa4710SRishi Srivatsavai fmt_bridge_id(bbuf->bridgel_desbridge, 82334eaa4710SRishi Srivatsavai sizeof (bbuf->bridgel_desbridge), 82344eaa4710SRishi Srivatsavai &stpstate.designated_bridge); 82354eaa4710SRishi Srivatsavai (void) snprintf(bbuf->bridgel_desport, 82364eaa4710SRishi Srivatsavai sizeof (bbuf->bridgel_desport), "%u", 82374eaa4710SRishi Srivatsavai stpstate.designated_port); 82384eaa4710SRishi Srivatsavai fmt_bool(bbuf->bridgel_tcack, sizeof (bbuf->bridgel_tcack), 82394eaa4710SRishi Srivatsavai stpstate.top_change_ack); 82404eaa4710SRishi Srivatsavai } 82414eaa4710SRishi Srivatsavai return (DLADM_STATUS_OK); 82424eaa4710SRishi Srivatsavai } 82434eaa4710SRishi Srivatsavai 82444eaa4710SRishi Srivatsavai static dladm_status_t 82454eaa4710SRishi Srivatsavai print_bridge_link_stats(show_state_t *state, datalink_id_t linkid, 82464eaa4710SRishi Srivatsavai bridge_link_statfields_buf_t *bbuf) 82474eaa4710SRishi Srivatsavai { 82484eaa4710SRishi Srivatsavai datalink_class_t class; 82494eaa4710SRishi Srivatsavai uint32_t flags; 82504eaa4710SRishi Srivatsavai dladm_status_t status; 82514eaa4710SRishi Srivatsavai UID_STP_PORT_STATE_T stpstate; 82524eaa4710SRishi Srivatsavai kstat_ctl_t *kcp; 82534eaa4710SRishi Srivatsavai kstat_t *ksp; 82544eaa4710SRishi Srivatsavai char bridge[MAXLINKNAMELEN]; 82554eaa4710SRishi Srivatsavai char kstatname[MAXLINKNAMELEN*2 + 1]; 82564eaa4710SRishi Srivatsavai brlsum_t *brlsum = (brlsum_t *)&state->ls_prevstats; 82574eaa4710SRishi Srivatsavai brlsum_t newval; 82584eaa4710SRishi Srivatsavai 82594eaa4710SRishi Srivatsavai #ifndef lint 82604eaa4710SRishi Srivatsavai /* This is a compile-time assertion; optimizer normally fixes this */ 82614eaa4710SRishi Srivatsavai extern void brlsum_t_is_too_large(void); 82624eaa4710SRishi Srivatsavai 82634eaa4710SRishi Srivatsavai if (sizeof (*brlsum) > sizeof (state->ls_prevstats)) 82644eaa4710SRishi Srivatsavai brlsum_t_is_too_large(); 82654eaa4710SRishi Srivatsavai #endif 82664eaa4710SRishi Srivatsavai 82674eaa4710SRishi Srivatsavai if (state->ls_firstonly) { 82684eaa4710SRishi Srivatsavai if (state->ls_donefirst) 82694eaa4710SRishi Srivatsavai return (DLADM_WALK_CONTINUE); 82704eaa4710SRishi Srivatsavai state->ls_donefirst = B_TRUE; 82714eaa4710SRishi Srivatsavai } else { 82724eaa4710SRishi Srivatsavai bzero(brlsum, sizeof (*brlsum)); 82734eaa4710SRishi Srivatsavai } 82744eaa4710SRishi Srivatsavai bzero(&newval, sizeof (newval)); 82754eaa4710SRishi Srivatsavai 82764eaa4710SRishi Srivatsavai status = dladm_datalink_id2info(handle, linkid, &flags, &class, NULL, 82774eaa4710SRishi Srivatsavai bbuf->bridgels_link, sizeof (bbuf->bridgels_link)); 82784eaa4710SRishi Srivatsavai if (status != DLADM_STATUS_OK) 82794eaa4710SRishi Srivatsavai return (status); 82804eaa4710SRishi Srivatsavai 82814eaa4710SRishi Srivatsavai if (!(state->ls_flags & flags)) 82824eaa4710SRishi Srivatsavai return (DLADM_STATUS_NOTFOUND); 82834eaa4710SRishi Srivatsavai 82844eaa4710SRishi Srivatsavai if (dladm_bridge_link_state(handle, linkid, &stpstate) == 82854eaa4710SRishi Srivatsavai DLADM_STATUS_OK) { 82864eaa4710SRishi Srivatsavai newval.cfgbpdu = stpstate.rx_cfg_bpdu_cnt; 82874eaa4710SRishi Srivatsavai newval.tcnbpdu = stpstate.rx_tcn_bpdu_cnt; 82884eaa4710SRishi Srivatsavai newval.rstpbpdu = stpstate.rx_rstp_bpdu_cnt; 82894eaa4710SRishi Srivatsavai newval.txbpdu = stpstate.txCount; 82904eaa4710SRishi Srivatsavai 82914eaa4710SRishi Srivatsavai (void) snprintf(bbuf->bridgels_cfgbpdu, 82924eaa4710SRishi Srivatsavai sizeof (bbuf->bridgels_cfgbpdu), "%lu", 82934eaa4710SRishi Srivatsavai newval.cfgbpdu - brlsum->cfgbpdu); 82944eaa4710SRishi Srivatsavai (void) snprintf(bbuf->bridgels_tcnbpdu, 82954eaa4710SRishi Srivatsavai sizeof (bbuf->bridgels_tcnbpdu), "%lu", 82964eaa4710SRishi Srivatsavai newval.tcnbpdu - brlsum->tcnbpdu); 82974eaa4710SRishi Srivatsavai (void) snprintf(bbuf->bridgels_rstpbpdu, 82984eaa4710SRishi Srivatsavai sizeof (bbuf->bridgels_rstpbpdu), "%lu", 82994eaa4710SRishi Srivatsavai newval.rstpbpdu - brlsum->rstpbpdu); 83004eaa4710SRishi Srivatsavai (void) snprintf(bbuf->bridgels_txbpdu, 83014eaa4710SRishi Srivatsavai sizeof (bbuf->bridgels_txbpdu), "%lu", 83024eaa4710SRishi Srivatsavai newval.txbpdu - brlsum->txbpdu); 83034eaa4710SRishi Srivatsavai } 83044eaa4710SRishi Srivatsavai 83054eaa4710SRishi Srivatsavai if ((status = dladm_bridge_getlink(handle, linkid, bridge, 83064eaa4710SRishi Srivatsavai sizeof (bridge))) != DLADM_STATUS_OK) 83074eaa4710SRishi Srivatsavai goto bls_out; 83084eaa4710SRishi Srivatsavai (void) snprintf(kstatname, sizeof (kstatname), "%s0-%s", bridge, 83094eaa4710SRishi Srivatsavai bbuf->bridgels_link); 83104eaa4710SRishi Srivatsavai if ((kcp = kstat_open()) == NULL) { 83114eaa4710SRishi Srivatsavai warn("kstat open operation failed"); 83124eaa4710SRishi Srivatsavai goto bls_out; 83134eaa4710SRishi Srivatsavai } 83144eaa4710SRishi Srivatsavai if ((ksp = kstat_lookup(kcp, "bridge", 0, kstatname)) != NULL && 83154eaa4710SRishi Srivatsavai kstat_read(kcp, ksp, NULL) != -1) { 83164eaa4710SRishi Srivatsavai if (dladm_kstat_value(ksp, "drops", KSTAT_DATA_UINT64, 83174eaa4710SRishi Srivatsavai &newval.drops) != -1) { 83184eaa4710SRishi Srivatsavai (void) snprintf(bbuf->bridgels_drops, 83194eaa4710SRishi Srivatsavai sizeof (bbuf->bridgels_drops), "%llu", 83204eaa4710SRishi Srivatsavai newval.drops - brlsum->drops); 83214eaa4710SRishi Srivatsavai } 83224eaa4710SRishi Srivatsavai if (dladm_kstat_value(ksp, "recv", KSTAT_DATA_UINT64, 83234eaa4710SRishi Srivatsavai &newval.recv) != -1) { 83244eaa4710SRishi Srivatsavai (void) snprintf(bbuf->bridgels_recv, 83254eaa4710SRishi Srivatsavai sizeof (bbuf->bridgels_recv), "%llu", 83264eaa4710SRishi Srivatsavai newval.recv - brlsum->recv); 83274eaa4710SRishi Srivatsavai } 83284eaa4710SRishi Srivatsavai if (dladm_kstat_value(ksp, "xmit", KSTAT_DATA_UINT64, 83294eaa4710SRishi Srivatsavai &newval.xmit) != -1) { 83304eaa4710SRishi Srivatsavai (void) snprintf(bbuf->bridgels_xmit, 83314eaa4710SRishi Srivatsavai sizeof (bbuf->bridgels_xmit), "%llu", 83324eaa4710SRishi Srivatsavai newval.xmit - brlsum->xmit); 83334eaa4710SRishi Srivatsavai } 83344eaa4710SRishi Srivatsavai } 83354eaa4710SRishi Srivatsavai (void) kstat_close(kcp); 83364eaa4710SRishi Srivatsavai bls_out: 83374eaa4710SRishi Srivatsavai *brlsum = newval; 83384eaa4710SRishi Srivatsavai 83394eaa4710SRishi Srivatsavai return (status); 83404eaa4710SRishi Srivatsavai } 83414eaa4710SRishi Srivatsavai 83424eaa4710SRishi Srivatsavai static void 83434eaa4710SRishi Srivatsavai show_bridge_link(datalink_id_t linkid, show_brstate_t *brstate) 83444eaa4710SRishi Srivatsavai { 83454eaa4710SRishi Srivatsavai void *buf; 83464eaa4710SRishi Srivatsavai 83474eaa4710SRishi Srivatsavai if (brstate->show_stats) { 83484eaa4710SRishi Srivatsavai bridge_link_statfields_buf_t bbuf; 83494eaa4710SRishi Srivatsavai 83504eaa4710SRishi Srivatsavai bzero(&bbuf, sizeof (bbuf)); 83514eaa4710SRishi Srivatsavai brstate->state.ls_status = print_bridge_link_stats( 83524eaa4710SRishi Srivatsavai &brstate->state, linkid, &bbuf); 83534eaa4710SRishi Srivatsavai buf = &bbuf; 83544eaa4710SRishi Srivatsavai } else { 83554eaa4710SRishi Srivatsavai bridge_link_fields_buf_t bbuf; 83564eaa4710SRishi Srivatsavai 83574eaa4710SRishi Srivatsavai bzero(&bbuf, sizeof (bbuf)); 83584eaa4710SRishi Srivatsavai brstate->state.ls_status = print_bridge_link(&brstate->state, 83594eaa4710SRishi Srivatsavai linkid, &bbuf); 83604eaa4710SRishi Srivatsavai buf = &bbuf; 83614eaa4710SRishi Srivatsavai } 83624eaa4710SRishi Srivatsavai if (brstate->state.ls_status == DLADM_STATUS_OK) 83634eaa4710SRishi Srivatsavai ofmt_print(brstate->state.ls_ofmt, buf); 83644eaa4710SRishi Srivatsavai } 83654eaa4710SRishi Srivatsavai 83664eaa4710SRishi Srivatsavai /* ARGSUSED */ 83674eaa4710SRishi Srivatsavai static int 83684eaa4710SRishi Srivatsavai show_bridge_link_walk(dladm_handle_t handle, datalink_id_t linkid, void *arg) 83694eaa4710SRishi Srivatsavai { 83704eaa4710SRishi Srivatsavai show_brstate_t *brstate = arg; 83714eaa4710SRishi Srivatsavai char bridge[MAXLINKNAMELEN]; 83724eaa4710SRishi Srivatsavai 83734eaa4710SRishi Srivatsavai if (dladm_bridge_getlink(handle, linkid, bridge, sizeof (bridge)) == 83744eaa4710SRishi Srivatsavai DLADM_STATUS_OK && strcmp(bridge, brstate->bridge) == 0) { 83754eaa4710SRishi Srivatsavai show_bridge_link(linkid, brstate); 83764eaa4710SRishi Srivatsavai } 83774eaa4710SRishi Srivatsavai return (DLADM_WALK_CONTINUE); 83784eaa4710SRishi Srivatsavai } 83794eaa4710SRishi Srivatsavai 83804eaa4710SRishi Srivatsavai static void 83814eaa4710SRishi Srivatsavai show_bridge_fwd(dladm_handle_t handle, bridge_listfwd_t *blf, 83824eaa4710SRishi Srivatsavai show_state_t *state) 83834eaa4710SRishi Srivatsavai { 83844eaa4710SRishi Srivatsavai bridge_fwd_fields_buf_t bbuf; 83854eaa4710SRishi Srivatsavai 83864eaa4710SRishi Srivatsavai bzero(&bbuf, sizeof (bbuf)); 83874eaa4710SRishi Srivatsavai (void) snprintf(bbuf.bridgef_dest, sizeof (bbuf.bridgef_dest), 83884eaa4710SRishi Srivatsavai "%s", ether_ntoa((struct ether_addr *)blf->blf_dest)); 83894eaa4710SRishi Srivatsavai if (blf->blf_is_local) { 83904eaa4710SRishi Srivatsavai (void) strlcpy(bbuf.bridgef_flags, "L", 83914eaa4710SRishi Srivatsavai sizeof (bbuf.bridgef_flags)); 83924eaa4710SRishi Srivatsavai } else { 83934eaa4710SRishi Srivatsavai (void) snprintf(bbuf.bridgef_age, sizeof (bbuf.bridgef_age), 83944eaa4710SRishi Srivatsavai "%2d.%03d", blf->blf_ms_age / 1000, blf->blf_ms_age % 1000); 83954eaa4710SRishi Srivatsavai if (blf->blf_trill_nick != 0) { 83964eaa4710SRishi Srivatsavai (void) snprintf(bbuf.bridgef_output, 83974eaa4710SRishi Srivatsavai sizeof (bbuf.bridgef_output), "%u", 83984eaa4710SRishi Srivatsavai blf->blf_trill_nick); 83994eaa4710SRishi Srivatsavai } 84004eaa4710SRishi Srivatsavai } 84014eaa4710SRishi Srivatsavai if (blf->blf_linkid != DATALINK_INVALID_LINKID && 84024eaa4710SRishi Srivatsavai blf->blf_trill_nick == 0) { 84034eaa4710SRishi Srivatsavai state->ls_status = dladm_datalink_id2info(handle, 84044eaa4710SRishi Srivatsavai blf->blf_linkid, NULL, NULL, NULL, bbuf.bridgef_output, 84054eaa4710SRishi Srivatsavai sizeof (bbuf.bridgef_output)); 84064eaa4710SRishi Srivatsavai } 84074eaa4710SRishi Srivatsavai if (state->ls_status == DLADM_STATUS_OK) 84084eaa4710SRishi Srivatsavai ofmt_print(state->ls_ofmt, &bbuf); 84094eaa4710SRishi Srivatsavai } 84104eaa4710SRishi Srivatsavai 84114eaa4710SRishi Srivatsavai static void 84124eaa4710SRishi Srivatsavai show_bridge_trillnick(trill_listnick_t *tln, show_state_t *state) 84134eaa4710SRishi Srivatsavai { 84144eaa4710SRishi Srivatsavai bridge_trill_fields_buf_t bbuf; 84154eaa4710SRishi Srivatsavai 84164eaa4710SRishi Srivatsavai bzero(&bbuf, sizeof (bbuf)); 84174eaa4710SRishi Srivatsavai (void) snprintf(bbuf.bridget_nick, sizeof (bbuf.bridget_nick), 84184eaa4710SRishi Srivatsavai "%u", tln->tln_nick); 84194eaa4710SRishi Srivatsavai if (tln->tln_ours) { 84204eaa4710SRishi Srivatsavai (void) strlcpy(bbuf.bridget_flags, "L", 84214eaa4710SRishi Srivatsavai sizeof (bbuf.bridget_flags)); 84224eaa4710SRishi Srivatsavai } else { 84234eaa4710SRishi Srivatsavai state->ls_status = dladm_datalink_id2info(handle, 84244eaa4710SRishi Srivatsavai tln->tln_linkid, NULL, NULL, NULL, bbuf.bridget_link, 84254eaa4710SRishi Srivatsavai sizeof (bbuf.bridget_link)); 84264eaa4710SRishi Srivatsavai (void) snprintf(bbuf.bridget_nexthop, 84274eaa4710SRishi Srivatsavai sizeof (bbuf.bridget_nexthop), "%s", 84284eaa4710SRishi Srivatsavai ether_ntoa((struct ether_addr *)tln->tln_nexthop)); 84294eaa4710SRishi Srivatsavai } 84304eaa4710SRishi Srivatsavai if (state->ls_status == DLADM_STATUS_OK) 84314eaa4710SRishi Srivatsavai ofmt_print(state->ls_ofmt, &bbuf); 84324eaa4710SRishi Srivatsavai } 84334eaa4710SRishi Srivatsavai 84344eaa4710SRishi Srivatsavai static void 84354eaa4710SRishi Srivatsavai do_show_bridge(int argc, char **argv, const char *use) 84364eaa4710SRishi Srivatsavai { 84374eaa4710SRishi Srivatsavai int option; 84384eaa4710SRishi Srivatsavai enum { 84394eaa4710SRishi Srivatsavai bridgeMode, linkMode, fwdMode, trillMode 84404eaa4710SRishi Srivatsavai } op_mode = bridgeMode; 84414eaa4710SRishi Srivatsavai uint32_t flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST; 84424eaa4710SRishi Srivatsavai boolean_t parsable = B_FALSE; 84434eaa4710SRishi Srivatsavai datalink_id_t linkid = DATALINK_ALL_LINKID; 84444eaa4710SRishi Srivatsavai int interval = 0; 84454eaa4710SRishi Srivatsavai show_brstate_t brstate; 84464eaa4710SRishi Srivatsavai dladm_status_t status; 84474eaa4710SRishi Srivatsavai char *fields_str = NULL; 84484eaa4710SRishi Srivatsavai /* default: bridge-related data */ 84494eaa4710SRishi Srivatsavai char *all_fields = "bridge,protect,address,priority,bmaxage," 84504eaa4710SRishi Srivatsavai "bhellotime,bfwddelay,forceproto,tctime,tccount,tchange," 84514eaa4710SRishi Srivatsavai "desroot,rootcost,rootport,maxage,hellotime,fwddelay,holdtime"; 84524eaa4710SRishi Srivatsavai char *default_fields = "bridge,protect,address,priority," 84534eaa4710SRishi Srivatsavai "desroot"; 84544eaa4710SRishi Srivatsavai char *all_statfields = "bridge,drops,forwards,mbcast," 84554eaa4710SRishi Srivatsavai "unknown,recv,sent"; 84564eaa4710SRishi Srivatsavai char *default_statfields = "bridge,drops,forwards,mbcast," 84574eaa4710SRishi Srivatsavai "unknown"; 84584eaa4710SRishi Srivatsavai /* -l: link-related data */ 84594eaa4710SRishi Srivatsavai char *all_link_fields = "link,index,state,uptime,opercost," 84604eaa4710SRishi Srivatsavai "operp2p,operedge,desroot,descost,desbridge,desport,tcack"; 84614eaa4710SRishi Srivatsavai char *default_link_fields = "link,state,uptime,desroot"; 84624eaa4710SRishi Srivatsavai char *all_link_statfields = "link,cfgbpdu,tcnbpdu,rstpbpdu," 84634eaa4710SRishi Srivatsavai "txbpdu,drops,recv,xmit"; 84644eaa4710SRishi Srivatsavai char *default_link_statfields = "link,drops,recv,xmit"; 84654eaa4710SRishi Srivatsavai /* -f: bridge forwarding table related data */ 84664eaa4710SRishi Srivatsavai char *default_fwd_fields = "dest,age,flags,output"; 84674eaa4710SRishi Srivatsavai /* -t: TRILL nickname table related data */ 84684eaa4710SRishi Srivatsavai char *default_trill_fields = "nick,flags,link,nexthop"; 84694eaa4710SRishi Srivatsavai char *default_str; 84704eaa4710SRishi Srivatsavai char *all_str; 84714eaa4710SRishi Srivatsavai ofmt_field_t *field_arr; 84724eaa4710SRishi Srivatsavai ofmt_handle_t ofmt; 84734eaa4710SRishi Srivatsavai ofmt_status_t oferr; 84744eaa4710SRishi Srivatsavai uint_t ofmtflags = 0; 84754eaa4710SRishi Srivatsavai 84764eaa4710SRishi Srivatsavai bzero(&brstate, sizeof (brstate)); 84774eaa4710SRishi Srivatsavai 84784eaa4710SRishi Srivatsavai opterr = 0; 84794eaa4710SRishi Srivatsavai while ((option = getopt_long(argc, argv, ":fi:lo:pst", 84804eaa4710SRishi Srivatsavai bridge_show_lopts, NULL)) != -1) { 84814eaa4710SRishi Srivatsavai switch (option) { 84824eaa4710SRishi Srivatsavai case 'f': 84834eaa4710SRishi Srivatsavai if (op_mode != bridgeMode && op_mode != fwdMode) 84844eaa4710SRishi Srivatsavai die("-f is incompatible with -l or -t"); 84854eaa4710SRishi Srivatsavai op_mode = fwdMode; 84864eaa4710SRishi Srivatsavai break; 84874eaa4710SRishi Srivatsavai case 'i': 84884eaa4710SRishi Srivatsavai if (interval != 0) 84894eaa4710SRishi Srivatsavai die_optdup(option); 84904eaa4710SRishi Srivatsavai if (!str2int(optarg, &interval) || interval == 0) 84914eaa4710SRishi Srivatsavai die("invalid interval value '%s'", optarg); 84924eaa4710SRishi Srivatsavai break; 84934eaa4710SRishi Srivatsavai case 'l': 84944eaa4710SRishi Srivatsavai if (op_mode != bridgeMode && op_mode != linkMode) 84954eaa4710SRishi Srivatsavai die("-l is incompatible with -f or -t"); 84964eaa4710SRishi Srivatsavai op_mode = linkMode; 84974eaa4710SRishi Srivatsavai break; 84984eaa4710SRishi Srivatsavai case 'o': 84994eaa4710SRishi Srivatsavai fields_str = optarg; 85004eaa4710SRishi Srivatsavai break; 85014eaa4710SRishi Srivatsavai case 'p': 85024eaa4710SRishi Srivatsavai if (parsable) 85034eaa4710SRishi Srivatsavai die_optdup(option); 85044eaa4710SRishi Srivatsavai parsable = B_TRUE; 85054eaa4710SRishi Srivatsavai break; 85064eaa4710SRishi Srivatsavai case 's': 85074eaa4710SRishi Srivatsavai if (brstate.show_stats) 85084eaa4710SRishi Srivatsavai die_optdup(option); 85094eaa4710SRishi Srivatsavai brstate.show_stats = B_TRUE; 85104eaa4710SRishi Srivatsavai break; 85114eaa4710SRishi Srivatsavai case 't': 85124eaa4710SRishi Srivatsavai if (op_mode != bridgeMode && op_mode != trillMode) 85134eaa4710SRishi Srivatsavai die("-t is incompatible with -f or -l"); 85144eaa4710SRishi Srivatsavai op_mode = trillMode; 85154eaa4710SRishi Srivatsavai break; 85164eaa4710SRishi Srivatsavai default: 85174eaa4710SRishi Srivatsavai die_opterr(optopt, option, use); 85184eaa4710SRishi Srivatsavai break; 85194eaa4710SRishi Srivatsavai } 85204eaa4710SRishi Srivatsavai } 85214eaa4710SRishi Srivatsavai 85224eaa4710SRishi Srivatsavai if (interval != 0 && !brstate.show_stats) 85234eaa4710SRishi Srivatsavai die("the -i option can be used only with -s"); 85244eaa4710SRishi Srivatsavai 85254eaa4710SRishi Srivatsavai if ((op_mode == fwdMode || op_mode == trillMode) && brstate.show_stats) 85264eaa4710SRishi Srivatsavai die("the -f/-t and -s options cannot be used together"); 85274eaa4710SRishi Srivatsavai 85284eaa4710SRishi Srivatsavai /* get the bridge name (optional last argument) */ 85294eaa4710SRishi Srivatsavai if (optind == (argc-1)) { 85304eaa4710SRishi Srivatsavai char lname[MAXLINKNAMELEN]; 85314eaa4710SRishi Srivatsavai uint32_t lnkflg; 85324eaa4710SRishi Srivatsavai datalink_class_t class; 85334eaa4710SRishi Srivatsavai 85344eaa4710SRishi Srivatsavai brstate.bridge = argv[optind]; 85354eaa4710SRishi Srivatsavai (void) snprintf(lname, sizeof (lname), "%s0", brstate.bridge); 85364eaa4710SRishi Srivatsavai if ((status = dladm_name2info(handle, lname, &linkid, &lnkflg, 85374eaa4710SRishi Srivatsavai &class, NULL)) != DLADM_STATUS_OK) { 85384eaa4710SRishi Srivatsavai die_dlerr(status, "bridge %s is not valid", 85394eaa4710SRishi Srivatsavai brstate.bridge); 85404eaa4710SRishi Srivatsavai } 85414eaa4710SRishi Srivatsavai 85424eaa4710SRishi Srivatsavai if (class != DATALINK_CLASS_BRIDGE) 85434eaa4710SRishi Srivatsavai die("%s is not a bridge", brstate.bridge); 85444eaa4710SRishi Srivatsavai 85454eaa4710SRishi Srivatsavai if (!(lnkflg & flags)) { 85464eaa4710SRishi Srivatsavai die_dlerr(DLADM_STATUS_BADARG, 85474eaa4710SRishi Srivatsavai "bridge %s is temporarily removed", brstate.bridge); 85484eaa4710SRishi Srivatsavai } 85494eaa4710SRishi Srivatsavai } else if (optind != argc) { 85504eaa4710SRishi Srivatsavai usage(); 85514eaa4710SRishi Srivatsavai } else if (op_mode != bridgeMode) { 85524eaa4710SRishi Srivatsavai die("bridge name required for -l, -f, or -t"); 85534eaa4710SRishi Srivatsavai return; 85544eaa4710SRishi Srivatsavai } 85554eaa4710SRishi Srivatsavai 85564eaa4710SRishi Srivatsavai brstate.state.ls_parsable = parsable; 85574eaa4710SRishi Srivatsavai brstate.state.ls_flags = flags; 85584eaa4710SRishi Srivatsavai brstate.state.ls_firstonly = (interval != 0); 85594eaa4710SRishi Srivatsavai 85604eaa4710SRishi Srivatsavai switch (op_mode) { 85614eaa4710SRishi Srivatsavai case bridgeMode: 85624eaa4710SRishi Srivatsavai if (brstate.show_stats) { 85634eaa4710SRishi Srivatsavai default_str = default_statfields; 85644eaa4710SRishi Srivatsavai all_str = all_statfields; 85654eaa4710SRishi Srivatsavai field_arr = bridge_statfields; 85664eaa4710SRishi Srivatsavai } else { 85674eaa4710SRishi Srivatsavai default_str = default_fields; 85684eaa4710SRishi Srivatsavai all_str = all_fields; 85694eaa4710SRishi Srivatsavai field_arr = bridge_fields; 85704eaa4710SRishi Srivatsavai } 85714eaa4710SRishi Srivatsavai break; 85724eaa4710SRishi Srivatsavai 85734eaa4710SRishi Srivatsavai case linkMode: 85744eaa4710SRishi Srivatsavai if (brstate.show_stats) { 85754eaa4710SRishi Srivatsavai default_str = default_link_statfields; 85764eaa4710SRishi Srivatsavai all_str = all_link_statfields; 85774eaa4710SRishi Srivatsavai field_arr = bridge_link_statfields; 85784eaa4710SRishi Srivatsavai } else { 85794eaa4710SRishi Srivatsavai default_str = default_link_fields; 85804eaa4710SRishi Srivatsavai all_str = all_link_fields; 85814eaa4710SRishi Srivatsavai field_arr = bridge_link_fields; 85824eaa4710SRishi Srivatsavai } 85834eaa4710SRishi Srivatsavai break; 85844eaa4710SRishi Srivatsavai 85854eaa4710SRishi Srivatsavai case fwdMode: 85864eaa4710SRishi Srivatsavai default_str = all_str = default_fwd_fields; 85874eaa4710SRishi Srivatsavai field_arr = bridge_fwd_fields; 85884eaa4710SRishi Srivatsavai break; 85894eaa4710SRishi Srivatsavai 85904eaa4710SRishi Srivatsavai case trillMode: 85914eaa4710SRishi Srivatsavai default_str = all_str = default_trill_fields; 85924eaa4710SRishi Srivatsavai field_arr = bridge_trill_fields; 85934eaa4710SRishi Srivatsavai break; 85944eaa4710SRishi Srivatsavai } 85954eaa4710SRishi Srivatsavai 85964eaa4710SRishi Srivatsavai if (fields_str == NULL) 85974eaa4710SRishi Srivatsavai fields_str = default_str; 85984eaa4710SRishi Srivatsavai else if (strcasecmp(fields_str, "all") == 0) 85994eaa4710SRishi Srivatsavai fields_str = all_str; 86004eaa4710SRishi Srivatsavai 86014eaa4710SRishi Srivatsavai if (parsable) 86024eaa4710SRishi Srivatsavai ofmtflags |= OFMT_PARSABLE; 86034eaa4710SRishi Srivatsavai oferr = ofmt_open(fields_str, field_arr, ofmtflags, 0, &ofmt); 86044eaa4710SRishi Srivatsavai dladm_ofmt_check(oferr, brstate.state.ls_parsable, ofmt); 86054eaa4710SRishi Srivatsavai brstate.state.ls_ofmt = ofmt; 86064eaa4710SRishi Srivatsavai 86074eaa4710SRishi Srivatsavai for (;;) { 86084eaa4710SRishi Srivatsavai brstate.state.ls_donefirst = B_FALSE; 86094eaa4710SRishi Srivatsavai switch (op_mode) { 86104eaa4710SRishi Srivatsavai case bridgeMode: 86114eaa4710SRishi Srivatsavai if (linkid == DATALINK_ALL_LINKID) { 86124eaa4710SRishi Srivatsavai (void) dladm_walk_datalink_id(show_bridge, 86134eaa4710SRishi Srivatsavai handle, &brstate, DATALINK_CLASS_BRIDGE, 86144eaa4710SRishi Srivatsavai DATALINK_ANY_MEDIATYPE, flags); 86154eaa4710SRishi Srivatsavai } else { 86164eaa4710SRishi Srivatsavai (void) show_bridge(handle, linkid, &brstate); 86174eaa4710SRishi Srivatsavai if (brstate.state.ls_status != 86184eaa4710SRishi Srivatsavai DLADM_STATUS_OK) { 86194eaa4710SRishi Srivatsavai die_dlerr(brstate.state.ls_status, 86204eaa4710SRishi Srivatsavai "failed to show bridge %s", 86214eaa4710SRishi Srivatsavai brstate.bridge); 86224eaa4710SRishi Srivatsavai } 86234eaa4710SRishi Srivatsavai } 86244eaa4710SRishi Srivatsavai break; 86254eaa4710SRishi Srivatsavai 86264eaa4710SRishi Srivatsavai case linkMode: { 86274eaa4710SRishi Srivatsavai datalink_id_t *dlp; 86284eaa4710SRishi Srivatsavai uint_t i, nlinks; 86294eaa4710SRishi Srivatsavai 86304eaa4710SRishi Srivatsavai dlp = dladm_bridge_get_portlist(brstate.bridge, 86314eaa4710SRishi Srivatsavai &nlinks); 86324eaa4710SRishi Srivatsavai if (dlp != NULL) { 86334eaa4710SRishi Srivatsavai for (i = 0; i < nlinks; i++) 86344eaa4710SRishi Srivatsavai show_bridge_link(dlp[i], &brstate); 86354eaa4710SRishi Srivatsavai dladm_bridge_free_portlist(dlp); 86364eaa4710SRishi Srivatsavai } else if (errno == ENOENT) { 86374eaa4710SRishi Srivatsavai /* bridge not running; iterate on libdladm */ 86384eaa4710SRishi Srivatsavai (void) dladm_walk_datalink_id( 86394eaa4710SRishi Srivatsavai show_bridge_link_walk, handle, 86404eaa4710SRishi Srivatsavai &brstate, DATALINK_CLASS_PHYS | 86414eaa4710SRishi Srivatsavai DATALINK_CLASS_AGGR | 86424eaa4710SRishi Srivatsavai DATALINK_CLASS_ETHERSTUB, 86434eaa4710SRishi Srivatsavai DATALINK_ANY_MEDIATYPE, flags); 86444eaa4710SRishi Srivatsavai } else { 86454eaa4710SRishi Srivatsavai die("unable to get port list for bridge %s: %s", 86464eaa4710SRishi Srivatsavai brstate.bridge, strerror(errno)); 86474eaa4710SRishi Srivatsavai } 86484eaa4710SRishi Srivatsavai break; 86494eaa4710SRishi Srivatsavai } 86504eaa4710SRishi Srivatsavai 86514eaa4710SRishi Srivatsavai case fwdMode: { 86524eaa4710SRishi Srivatsavai bridge_listfwd_t *blf; 86534eaa4710SRishi Srivatsavai uint_t i, nfwd; 86544eaa4710SRishi Srivatsavai 86554eaa4710SRishi Srivatsavai blf = dladm_bridge_get_fwdtable(handle, brstate.bridge, 86564eaa4710SRishi Srivatsavai &nfwd); 86574eaa4710SRishi Srivatsavai if (blf == NULL) { 86584eaa4710SRishi Srivatsavai die("unable to get forwarding entries for " 86594eaa4710SRishi Srivatsavai "bridge %s", brstate.bridge); 86604eaa4710SRishi Srivatsavai } else { 86614eaa4710SRishi Srivatsavai for (i = 0; i < nfwd; i++) 86624eaa4710SRishi Srivatsavai show_bridge_fwd(handle, blf + i, 86634eaa4710SRishi Srivatsavai &brstate.state); 86644eaa4710SRishi Srivatsavai dladm_bridge_free_fwdtable(blf); 86654eaa4710SRishi Srivatsavai } 86664eaa4710SRishi Srivatsavai break; 86674eaa4710SRishi Srivatsavai } 86684eaa4710SRishi Srivatsavai 86694eaa4710SRishi Srivatsavai case trillMode: { 86704eaa4710SRishi Srivatsavai trill_listnick_t *tln; 86714eaa4710SRishi Srivatsavai uint_t i, nnick; 86724eaa4710SRishi Srivatsavai 86734eaa4710SRishi Srivatsavai tln = dladm_bridge_get_trillnick(brstate.bridge, 86744eaa4710SRishi Srivatsavai &nnick); 86754eaa4710SRishi Srivatsavai if (tln == NULL) { 86764eaa4710SRishi Srivatsavai if (errno == ENOENT) 86774eaa4710SRishi Srivatsavai die("bridge %s is not running TRILL", 86784eaa4710SRishi Srivatsavai brstate.bridge); 86794eaa4710SRishi Srivatsavai else 86804eaa4710SRishi Srivatsavai die("unable to get TRILL nickname " 86814eaa4710SRishi Srivatsavai "entries for bridge %s", 86824eaa4710SRishi Srivatsavai brstate.bridge); 86834eaa4710SRishi Srivatsavai } else { 86844eaa4710SRishi Srivatsavai for (i = 0; i < nnick; i++) 86854eaa4710SRishi Srivatsavai show_bridge_trillnick(tln + i, 86864eaa4710SRishi Srivatsavai &brstate.state); 86874eaa4710SRishi Srivatsavai dladm_bridge_free_trillnick(tln); 86884eaa4710SRishi Srivatsavai } 86894eaa4710SRishi Srivatsavai break; 86904eaa4710SRishi Srivatsavai } 86914eaa4710SRishi Srivatsavai } 86924eaa4710SRishi Srivatsavai if (interval == 0) 86934eaa4710SRishi Srivatsavai break; 86944eaa4710SRishi Srivatsavai (void) sleep(interval); 86954eaa4710SRishi Srivatsavai } 86964eaa4710SRishi Srivatsavai } 86974eaa4710SRishi Srivatsavai 8698d62bc4baSyz147064 /* 8699d62bc4baSyz147064 * "-R" option support. It is used for live upgrading. Append dladm commands 8700d62bc4baSyz147064 * to a upgrade script which will be run when the alternative root boots up: 8701d62bc4baSyz147064 * 8702b9e076dcSyz147064 * - If the /etc/dladm/datalink.conf file exists on the alternative root, 8703b9e076dcSyz147064 * append dladm commands to the <altroot>/var/svc/profile/upgrade_datalink 8704b9e076dcSyz147064 * script. This script will be run as part of the network/physical service. 8705b9e076dcSyz147064 * We cannot defer this to /var/svc/profile/upgrade because then the 8706b9e076dcSyz147064 * configuration will not be able to take effect before network/physical 8707b9e076dcSyz147064 * plumbs various interfaces. 8708d62bc4baSyz147064 * 8709b9e076dcSyz147064 * - If the /etc/dladm/datalink.conf file does not exist on the alternative 8710b9e076dcSyz147064 * root, append dladm commands to the <altroot>/var/svc/profile/upgrade script, 8711b9e076dcSyz147064 * which will be run in the manifest-import service. 8712d62bc4baSyz147064 * 8713d62bc4baSyz147064 * Note that the SMF team is considering to move the manifest-import service 8714d62bc4baSyz147064 * to be run at the very begining of boot. Once that is done, the need for 8715d62bc4baSyz147064 * the /var/svc/profile/upgrade_datalink script will not exist any more. 8716d62bc4baSyz147064 */ 8717d62bc4baSyz147064 static void 8718d62bc4baSyz147064 altroot_cmd(char *altroot, int argc, char *argv[]) 8719d62bc4baSyz147064 { 8720d62bc4baSyz147064 char path[MAXPATHLEN]; 8721d62bc4baSyz147064 struct stat stbuf; 8722d62bc4baSyz147064 FILE *fp; 8723d62bc4baSyz147064 int i; 8724d62bc4baSyz147064 8725d62bc4baSyz147064 /* 8726b9e076dcSyz147064 * Check for the existence of the /etc/dladm/datalink.conf 8727b9e076dcSyz147064 * configuration file, and determine the name of script file. 8728d62bc4baSyz147064 */ 8729b9e076dcSyz147064 (void) snprintf(path, MAXPATHLEN, "/%s/etc/dladm/datalink.conf", 8730b9e076dcSyz147064 altroot); 8731d62bc4baSyz147064 if (stat(path, &stbuf) < 0) { 8732d62bc4baSyz147064 (void) snprintf(path, MAXPATHLEN, "/%s/%s", altroot, 8733d62bc4baSyz147064 SMF_UPGRADE_FILE); 8734d62bc4baSyz147064 } else { 8735d62bc4baSyz147064 (void) snprintf(path, MAXPATHLEN, "/%s/%s", altroot, 8736d62bc4baSyz147064 SMF_UPGRADEDATALINK_FILE); 8737d62bc4baSyz147064 } 8738d62bc4baSyz147064 8739d62bc4baSyz147064 if ((fp = fopen(path, "a+")) == NULL) 8740d62bc4baSyz147064 die("operation not supported on %s", altroot); 8741d62bc4baSyz147064 8742d62bc4baSyz147064 (void) fprintf(fp, "/sbin/dladm "); 8743d62bc4baSyz147064 for (i = 0; i < argc; i++) { 8744d62bc4baSyz147064 /* 8745d62bc4baSyz147064 * Directly write to the file if it is not the "-R <altroot>" 8746d62bc4baSyz147064 * option. In which case, skip it. 8747d62bc4baSyz147064 */ 8748d62bc4baSyz147064 if (strcmp(argv[i], "-R") != 0) 8749d62bc4baSyz147064 (void) fprintf(fp, "%s ", argv[i]); 8750d62bc4baSyz147064 else 8751d62bc4baSyz147064 i ++; 8752d62bc4baSyz147064 } 8753d62bc4baSyz147064 (void) fprintf(fp, "%s\n", SMF_DLADM_UPGRADE_MSG); 8754d62bc4baSyz147064 (void) fclose(fp); 87554ac67f02SAnurag S. Maskey dladm_close(handle); 87562b24ab6bSSebastien Roy exit(EXIT_SUCCESS); 8757d62bc4baSyz147064 } 8758d62bc4baSyz147064 8759d62bc4baSyz147064 /* 8760d62bc4baSyz147064 * Convert the string to an integer. Note that the string must not have any 8761d62bc4baSyz147064 * trailing non-integer characters. 8762d62bc4baSyz147064 */ 876333343a97Smeem static boolean_t 876433343a97Smeem str2int(const char *str, int *valp) 876533343a97Smeem { 876633343a97Smeem int val; 876733343a97Smeem char *endp = NULL; 876833343a97Smeem 876933343a97Smeem errno = 0; 877033343a97Smeem val = strtol(str, &endp, 10); 877133343a97Smeem if (errno != 0 || *endp != '\0') 877233343a97Smeem return (B_FALSE); 877333343a97Smeem 877433343a97Smeem *valp = val; 877533343a97Smeem return (B_TRUE); 877633343a97Smeem } 877733343a97Smeem 877833343a97Smeem /* PRINTFLIKE1 */ 877933343a97Smeem static void 878033343a97Smeem warn(const char *format, ...) 878133343a97Smeem { 878233343a97Smeem va_list alist; 878333343a97Smeem 878433343a97Smeem format = gettext(format); 878533343a97Smeem (void) fprintf(stderr, "%s: warning: ", progname); 878633343a97Smeem 878733343a97Smeem va_start(alist, format); 878833343a97Smeem (void) vfprintf(stderr, format, alist); 878933343a97Smeem va_end(alist); 879033343a97Smeem 8791*0dc2366fSVenugopal Iyer (void) putc('\n', stderr); 879233343a97Smeem } 879333343a97Smeem 879433343a97Smeem /* PRINTFLIKE2 */ 879533343a97Smeem static void 879633343a97Smeem warn_dlerr(dladm_status_t err, const char *format, ...) 879733343a97Smeem { 879833343a97Smeem va_list alist; 879933343a97Smeem char errmsg[DLADM_STRSIZE]; 880033343a97Smeem 880133343a97Smeem format = gettext(format); 880233343a97Smeem (void) fprintf(stderr, gettext("%s: warning: "), progname); 880333343a97Smeem 880433343a97Smeem va_start(alist, format); 880533343a97Smeem (void) vfprintf(stderr, format, alist); 880633343a97Smeem va_end(alist); 880733343a97Smeem (void) fprintf(stderr, ": %s\n", dladm_status2str(err, errmsg)); 880833343a97Smeem } 880933343a97Smeem 88104ac67f02SAnurag S. Maskey /* 88114ac67f02SAnurag S. Maskey * Also closes the dladm handle if it is not NULL. 88124ac67f02SAnurag S. Maskey */ 881333343a97Smeem /* PRINTFLIKE2 */ 881433343a97Smeem static void 881533343a97Smeem die_dlerr(dladm_status_t err, const char *format, ...) 881633343a97Smeem { 881733343a97Smeem va_list alist; 881833343a97Smeem char errmsg[DLADM_STRSIZE]; 881933343a97Smeem 882033343a97Smeem format = gettext(format); 882133343a97Smeem (void) fprintf(stderr, "%s: ", progname); 882233343a97Smeem 882333343a97Smeem va_start(alist, format); 882433343a97Smeem (void) vfprintf(stderr, format, alist); 882533343a97Smeem va_end(alist); 882633343a97Smeem (void) fprintf(stderr, ": %s\n", dladm_status2str(err, errmsg)); 882733343a97Smeem 88284ac67f02SAnurag S. Maskey /* close dladm handle if it was opened */ 88294ac67f02SAnurag S. Maskey if (handle != NULL) 88304ac67f02SAnurag S. Maskey dladm_close(handle); 88314ac67f02SAnurag S. Maskey 883233343a97Smeem exit(EXIT_FAILURE); 883333343a97Smeem } 883433343a97Smeem 883533343a97Smeem /* PRINTFLIKE1 */ 883633343a97Smeem static void 883733343a97Smeem die(const char *format, ...) 883833343a97Smeem { 883933343a97Smeem va_list alist; 884033343a97Smeem 884133343a97Smeem format = gettext(format); 884233343a97Smeem (void) fprintf(stderr, "%s: ", progname); 884333343a97Smeem 884433343a97Smeem va_start(alist, format); 884533343a97Smeem (void) vfprintf(stderr, format, alist); 884633343a97Smeem va_end(alist); 884733343a97Smeem 8848*0dc2366fSVenugopal Iyer (void) putc('\n', stderr); 88494ac67f02SAnurag S. Maskey 88504ac67f02SAnurag S. Maskey /* close dladm handle if it was opened */ 88514ac67f02SAnurag S. Maskey if (handle != NULL) 88524ac67f02SAnurag S. Maskey dladm_close(handle); 88534ac67f02SAnurag S. Maskey 885433343a97Smeem exit(EXIT_FAILURE); 885533343a97Smeem } 885633343a97Smeem 885733343a97Smeem static void 885833343a97Smeem die_optdup(int opt) 885933343a97Smeem { 886033343a97Smeem die("the option -%c cannot be specified more than once", opt); 886133343a97Smeem } 886233343a97Smeem 886333343a97Smeem static void 88648d5c46e6Sam223141 die_opterr(int opt, int opterr, const char *usage) 886533343a97Smeem { 886633343a97Smeem switch (opterr) { 886733343a97Smeem case ':': 88688d5c46e6Sam223141 die("option '-%c' requires a value\nusage: %s", opt, 88698d5c46e6Sam223141 gettext(usage)); 887033343a97Smeem break; 887133343a97Smeem case '?': 887233343a97Smeem default: 88738d5c46e6Sam223141 die("unrecognized option '-%c'\nusage: %s", opt, 88748d5c46e6Sam223141 gettext(usage)); 887533343a97Smeem break; 88760ba2cbe9Sxc151355 } 88770ba2cbe9Sxc151355 } 8878e7801d59Ssowmini 8879e7801d59Ssowmini static void 88804784fcbdSSowmini Varadhan show_ether_xprop(void *arg, dladm_ether_info_t *eattr) 8881e7801d59Ssowmini { 8882e7801d59Ssowmini print_ether_state_t *statep = arg; 8883e7801d59Ssowmini ether_fields_buf_t ebuf; 88844784fcbdSSowmini Varadhan int i; 8885e7801d59Ssowmini 88864784fcbdSSowmini Varadhan for (i = CAPABLE; i <= PEERADV; i++) { 8887e7801d59Ssowmini bzero(&ebuf, sizeof (ebuf)); 88884784fcbdSSowmini Varadhan (void) strlcpy(ebuf.eth_ptype, ptype[i], 88894784fcbdSSowmini Varadhan sizeof (ebuf.eth_ptype)); 88904784fcbdSSowmini Varadhan (void) dladm_ether_autoneg2str(ebuf.eth_autoneg, 88914784fcbdSSowmini Varadhan sizeof (ebuf.eth_autoneg), eattr, i); 88924784fcbdSSowmini Varadhan (void) dladm_ether_spdx2str(ebuf.eth_spdx, 88934784fcbdSSowmini Varadhan sizeof (ebuf.eth_spdx), eattr, i); 88944784fcbdSSowmini Varadhan (void) dladm_ether_pause2str(ebuf.eth_pause, 88954784fcbdSSowmini Varadhan sizeof (ebuf.eth_pause), eattr, i); 88964784fcbdSSowmini Varadhan (void) strlcpy(ebuf.eth_rem_fault, 88974784fcbdSSowmini Varadhan (eattr->lei_attr[i].le_fault ? "fault" : "none"), 88984784fcbdSSowmini Varadhan sizeof (ebuf.eth_rem_fault)); 88998002d411SSowmini Varadhan ofmt_print(statep->es_ofmt, &ebuf); 8900e7801d59Ssowmini } 8901e7801d59Ssowmini 8902e7801d59Ssowmini } 8903e7801d59Ssowmini 8904e7801d59Ssowmini static boolean_t 8905e7801d59Ssowmini link_is_ether(const char *link, datalink_id_t *linkid) 8906e7801d59Ssowmini { 8907e7801d59Ssowmini uint32_t media; 8908e7801d59Ssowmini datalink_class_t class; 8909e7801d59Ssowmini 89104ac67f02SAnurag S. Maskey if (dladm_name2info(handle, link, linkid, NULL, &class, &media) == 8911e7801d59Ssowmini DLADM_STATUS_OK) { 8912e7801d59Ssowmini if (class == DATALINK_CLASS_PHYS && media == DL_ETHER) 8913e7801d59Ssowmini return (B_TRUE); 8914e7801d59Ssowmini } 8915e7801d59Ssowmini return (B_FALSE); 8916e7801d59Ssowmini } 89178002d411SSowmini Varadhan 89188002d411SSowmini Varadhan /* 89198002d411SSowmini Varadhan * default output callback function that, when invoked, 89208002d411SSowmini Varadhan * prints string which is offset by ofmt_arg->ofmt_id within buf. 89218002d411SSowmini Varadhan */ 89228002d411SSowmini Varadhan static boolean_t 89238002d411SSowmini Varadhan print_default_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize) 89248002d411SSowmini Varadhan { 89258002d411SSowmini Varadhan char *value; 89268002d411SSowmini Varadhan 89278002d411SSowmini Varadhan value = (char *)ofarg->ofmt_cbarg + ofarg->ofmt_id; 89288002d411SSowmini Varadhan (void) strlcpy(buf, value, bufsize); 89298002d411SSowmini Varadhan return (B_TRUE); 89308002d411SSowmini Varadhan } 89318002d411SSowmini Varadhan 89328002d411SSowmini Varadhan static void 89338002d411SSowmini Varadhan dladm_ofmt_check(ofmt_status_t oferr, boolean_t parsable, 89348002d411SSowmini Varadhan ofmt_handle_t ofmt) 89358002d411SSowmini Varadhan { 89368002d411SSowmini Varadhan char buf[OFMT_BUFSIZE]; 89378002d411SSowmini Varadhan 89388002d411SSowmini Varadhan if (oferr == OFMT_SUCCESS) 89398002d411SSowmini Varadhan return; 89408002d411SSowmini Varadhan (void) ofmt_strerror(ofmt, oferr, buf, sizeof (buf)); 89418002d411SSowmini Varadhan /* 89428002d411SSowmini Varadhan * All errors are considered fatal in parsable mode. 89438002d411SSowmini Varadhan * NOMEM errors are always fatal, regardless of mode. 89448002d411SSowmini Varadhan * For other errors, we print diagnostics in human-readable 89458002d411SSowmini Varadhan * mode and processs what we can. 89468002d411SSowmini Varadhan */ 89478002d411SSowmini Varadhan if (parsable || oferr == OFMT_ENOFIELDS) { 89488002d411SSowmini Varadhan ofmt_close(ofmt); 89498002d411SSowmini Varadhan die(buf); 89508002d411SSowmini Varadhan } else { 89518002d411SSowmini Varadhan warn(buf); 89528002d411SSowmini Varadhan } 89538002d411SSowmini Varadhan } 8954