/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define STR_UNDEF_VAL "--" #define MAXPORT 256 #define MAXVNIC 256 #define BUFLEN(lim, ptr) (((lim) > (ptr)) ? ((lim) - (ptr)) : 0) #define MAXLINELEN 1024 #define SMF_UPGRADE_FILE "/var/svc/profile/upgrade" #define SMF_UPGRADEDATALINK_FILE "/var/svc/profile/upgrade_datalink" #define SMF_DLADM_UPGRADE_MSG " # added by dladm(1M)" #define CMD_TYPE_ANY 0xffffffff #define WIFI_CMD_SCAN 0x00000001 #define WIFI_CMD_SHOW 0x00000002 #define WIFI_CMD_ALL (WIFI_CMD_SCAN | WIFI_CMD_SHOW) /* * Data structures and routines for printing output. * All non-parseable output is assumed to be in a columnar format. * Multiple fields in parsable output are separated by ':'; single * field output is printed as-is. * * Each sub-command is associated with a global array of pointers, * print_field_t *fields[], where the print_field_t contains information * about the format in which the output is to be printed. * * Sub-commands may be implemented in one of two ways: * (i) the implementation could get all field values into a character * buffer, with pf_offset containing the offset (for pf_name) within * the buffer. The sub-command would make the needed system calls * to obtain all possible column values and then invoke the * dladm_print_field() function to print the specific fields * requested in the command line. See the comments for dladm_print_field * for further details. * (ii) Alternatively, each fields[i] entry could store a pf_index value * that uniquely identifies the column to be printed. The implementation * of the sub-command would then invoke dladm_print_output() with a * callback function whose semantics are described below (see comments * for dladm_print_output()) * * Thus, an implementation of a sub-command must provide the following: * * static print_field_t sub_command_fields[] = { * {,
,, , cmdtype}, * : * {,
,, , cmdtype} * }; * * #define SUB_COMMAND_MAX_FIELDS sizeof \ * (sub_comand_fields) / sizeof (print_field_t)) * * print_state_t sub_command_print_state; * * The function that parses command line arguments (typically * do_sub_command()) should then contain an invocation like: * * fields = parse_output_fields(fields_str, sub_command_fields, * SUB_COMMAND_MAX_FIELDS, CMD_TYPE_ANY, &nfields); * * and store the resulting fields and nfields value in a print_state_t * structure tracked for the command. * * sub_command_print_state.ps_fields = fields; * sub_command_print_state.ps_nfields = nfields; * * To print the column header for the output, the print_header() * function must then be invoked by do_sub_command(). * * Then if method (i) is used for the sub_command, the do_sub_command() * function should make the necessary system calls to fill up the buffer * and then invoke dladm_print_field(). An example of this method is * the implementation of do_show_link() and show_link(); * * If method (ii) is used, do_sub_command should invoke dladm_print_output() * with a callback function that will be called for each field to be printed. * The callback function will be passed a pointer to the print_field_t * for the field, and the pf_index may then be used to identify the * system call required to find the value to be printed. */ typedef struct print_field_s { const char *pf_name; /* name of column to be printed */ const char *pf_header; /* header for this column */ uint_t pf_width; union { uint_t _pf_index; /* private index for sub-command */ size_t _pf_offset; }_pf_un; #define pf_index _pf_un._pf_index #define pf_offset _pf_un._pf_offset; uint_t pf_cmdtype; } print_field_t; /* * The state of the output is tracked in a print_state_t structure. * Each ps_fields[i] entry points at the global print_field_t array for * the sub-command, where ps_nfields is the number of requested fields. */ typedef struct print_state_s { print_field_t **ps_fields; uint_t ps_nfields; boolean_t ps_lastfield; uint_t ps_overflow; } print_state_t; typedef char *(*print_callback_t)(print_field_t *, void *); static print_field_t **parse_output_fields(char *, print_field_t *, int, uint_t, uint_t *); /* * print the header for the output */ static void print_header(print_state_t *); static void print_field(print_state_t *, print_field_t *, const char *, boolean_t); /* * to print output values, call dladm_print_output with a callback * function (*func)() that should parse the args and return an * unformatted character buffer with the value to be printed. * * dladm_print_output() prints the character buffer using the formatting * information provided in the print_field_t for that column. */ static void dladm_print_output(print_state_t *, boolean_t, print_callback_t, void *); /* * helper function that, when invoked as dladm_print_field(pf, buf) * prints string which is offset by pf->pf_offset within buf. */ static char *dladm_print_field(print_field_t *, void *); #define MAX_FIELD_LEN 32 typedef struct show_state { boolean_t ls_firstonly; boolean_t ls_donefirst; pktsum_t ls_prevstats; uint32_t ls_flags; dladm_status_t ls_status; print_state_t ls_print; boolean_t ls_parseable; boolean_t ls_printheader; boolean_t ls_mac; boolean_t ls_hwgrp; } show_state_t; typedef struct show_grp_state { pktsum_t gs_prevstats[MAXPORT]; uint32_t gs_flags; dladm_status_t gs_status; boolean_t gs_parseable; boolean_t gs_lacp; boolean_t gs_extended; boolean_t gs_stats; boolean_t gs_firstonly; boolean_t gs_donefirst; boolean_t gs_printheader; print_state_t gs_print; } show_grp_state_t; typedef struct show_vnic_state { datalink_id_t vs_vnic_id; datalink_id_t vs_link_id; char vs_vnic[MAXLINKNAMELEN]; char vs_link[MAXLINKNAMELEN]; boolean_t vs_parseable; boolean_t vs_printheader; boolean_t vs_found; boolean_t vs_firstonly; boolean_t vs_donefirst; boolean_t vs_stats; boolean_t vs_printstats; pktsum_t vs_totalstats; pktsum_t vs_prevstats[MAXVNIC]; boolean_t vs_etherstub; dladm_status_t vs_status; uint32_t vs_flags; print_state_t vs_print; } show_vnic_state_t; typedef struct show_usage_state_s { boolean_t us_plot; boolean_t us_parseable; boolean_t us_printheader; boolean_t us_first; boolean_t us_showall; print_state_t us_print; } show_usage_state_t; typedef void cmdfunc_t(int, char **, const char *); static cmdfunc_t do_show_link, do_show_wifi, do_show_phys; static cmdfunc_t do_create_aggr, do_delete_aggr, do_add_aggr, do_remove_aggr; static cmdfunc_t do_modify_aggr, do_show_aggr, do_up_aggr; static cmdfunc_t do_scan_wifi, do_connect_wifi, do_disconnect_wifi; static cmdfunc_t do_show_linkprop, do_set_linkprop, do_reset_linkprop; static cmdfunc_t do_create_secobj, do_delete_secobj, do_show_secobj; static cmdfunc_t do_init_linkprop, do_init_secobj; static cmdfunc_t do_create_vlan, do_delete_vlan, do_up_vlan, do_show_vlan; static cmdfunc_t do_rename_link, do_delete_phys, do_init_phys; static cmdfunc_t do_show_linkmap; static cmdfunc_t do_show_ether; static cmdfunc_t do_create_vnic, do_delete_vnic, do_show_vnic; static cmdfunc_t do_up_vnic; static cmdfunc_t do_create_etherstub, do_delete_etherstub, do_show_etherstub; static cmdfunc_t do_show_usage; static void do_up_vnic_common(int, char **, const char *, boolean_t); static void altroot_cmd(char *, int, char **); static int show_linkprop_onelink(dladm_handle_t, datalink_id_t, void *); static void link_stats(datalink_id_t, uint_t, char *, show_state_t *); static void aggr_stats(datalink_id_t, show_grp_state_t *, uint_t); static void vnic_stats(show_vnic_state_t *, uint32_t); static int get_one_kstat(const char *, const char *, uint8_t, void *, boolean_t); static void get_mac_stats(const char *, pktsum_t *); static void get_link_stats(const char *, pktsum_t *); static uint64_t get_ifspeed(const char *, boolean_t); static const char *get_linkstate(const char *, boolean_t, char *); static const char *get_linkduplex(const char *, boolean_t, char *); static int show_etherprop(dladm_handle_t, datalink_id_t, void *); static void show_ether_xprop(void *, dladm_ether_info_t *); static boolean_t link_is_ether(const char *, datalink_id_t *); static boolean_t str2int(const char *, int *); static void die(const char *, ...); static void die_optdup(int); static void die_opterr(int, int, const char *); static void die_dlerr(dladm_status_t, const char *, ...); static void warn(const char *, ...); static void warn_dlerr(dladm_status_t, const char *, ...); typedef struct cmd { char *c_name; cmdfunc_t *c_fn; const char *c_usage; } cmd_t; static cmd_t cmds[] = { { "rename-link", do_rename_link, " rename-link " }, { "show-link", do_show_link, " show-link [-pP] [-o ,..] [-s [-i ]] " "[]\n" }, { "create-aggr", do_create_aggr, " create-aggr [-t] [-P ] [-L ] [-T