ipmpstat.c revision ec382c61f99e6dbbdf119dcf5016ce0481d12e04
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem/*
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * CDDL HEADER START
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem *
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * The contents of this file are subject to the terms of the
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * Common Development and Distribution License (the "License").
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * You may not use this file except in compliance with the License.
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem *
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * or http://www.opensolaris.org/os/licensing.
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * See the License for the specific language governing permissions
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * and limitations under the License.
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem *
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * When distributing Covered Code, include this CDDL HEADER in each
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * If applicable, add the following below this CDDL HEADER, with the
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * fields enclosed by brackets "[]" replaced with your own identifying
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * information: Portions Copyright [yyyy] [name of copyright owner]
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem *
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * CDDL HEADER END
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem *
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * Use is subject to license terms.
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem */
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem#include <alloca.h>
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem#include <arpa/inet.h>
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem#include <assert.h>
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem#include <errno.h>
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem#include <ipmp_admin.h>
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem#include <ipmp_query.h>
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem#include <libintl.h>
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem#include <libnvpair.h>
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem#include <libsysevent.h>
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem#include <locale.h>
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem#include <netdb.h>
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem#include <signal.h>
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem#include <stdarg.h>
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem#include <stdio.h>
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem#include <stdlib.h>
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem#include <string.h>
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem#include <unistd.h>
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem#include <sys/sysevent/eventdefs.h>
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem#include <sys/sysevent/ipmp.h>
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem#include <sys/sysmacros.h>
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem#include <sys/termios.h>
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem#include <sys/types.h>
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem/*
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * ipmpstat -- display IPMP subsystem status.
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem *
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * This utility makes extensive use of libipmp and IPMP sysevents to gather
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * and pretty-print the status of the IPMP subsystem. All output formats
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * except for -p (probe) use libipmp to create a point-in-time snapshot of the
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * IPMP subsystem (unless the test-special -L flag is used), and then output
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * the contents of that snapshot in a user-specified manner. Because the
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * output format and requested fields aren't known until run-time, three sets
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * of function pointers and two core data structures are used. Specifically:
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem *
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * * The ipmpstat_walker_t function pointers (walk_*) iterate through
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * all instances of a given IPMP object (group, interface, or address).
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * At most one ipmpstat_walker_t is used per ipmpstat invocation.
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * Since target information is included with the interface information,
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * both -i and -t use the interface walker (walk_if()).
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem *
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * * The ipmpstat_sfunc_t function pointers (sfunc_*) obtain a given
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * value for a given IPMP object. Each ipmpstat_sunc_t is passed a
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * buffer to write its result into, the buffer's size, and an
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * ipmpstat_sfunc_arg_t state structure. The state structure consists
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * of a pointer to the IPMP object to obtain information from
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * (sa_data), and an open libipmp handle (sa_ih) which can be used to
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * do additional libipmp queries, if necessary (e.g., because the
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * object does not have all of the needed information).
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem *
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * * The ipmpstat_field_t structure provides the list of supported fields
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * for a given output format, along with output formatting information
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * (e.g., field width), and a pointer to an ipmpstat_sfunc_t function
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * that can obtain the value for a IPMP given object. For a given
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * ipmpstat output format, there's a corresponding array of
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * ipmpstat_field_t structures. Thus, one ipmpstat_field_t array is
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * used per ipmpstat invocation.
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem *
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * * The ipmpstat_ofmt_t provides an ordered list of the requested
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * ipmpstat_field_t's (e.g., via -o) for a given ipmpstat invocation.
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * It is built at runtime from the command-line arguments. This
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * structure (and a given IPMP object) is used by ofmt_output() to
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * output a single line of information about that IPMP object.
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem *
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * * The ipmpstat_cbfunc_t function pointers (*_cbfunc) are called back
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * by the walkers. They are used both internally to implement nested
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * walks, and by the ipmpstat output logic to provide the glue between
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * the IPMP object walkers and the ofmt_output() logic. Usually, a
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * single line is output for each IPMP object, and thus ofmt_output()
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * can be directly invoked (see info_output_cbfunc()). However, if
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * multiple lines need to be output, then a more complex cbfunc is
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * needed (see targinfo_output_cbfunc()). At most one cbfunc is used
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * per ipmpstat invocation.
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem */
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem/*
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * Data type used by the sfunc callbacks to obtain the requested information
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * from the agreed-upon object.
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem */
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemtypedef struct ipmpstat_sfunc_arg {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ipmp_handle_t sa_ih;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem void *sa_data;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem} ipmpstat_sfunc_arg_t;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemtypedef void ipmpstat_sfunc_t(ipmpstat_sfunc_arg_t *, char *, uint_t);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem/*
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * Data type that describes how to output a field; used by ofmt_output*().
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem */
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemtypedef struct ipmpstat_field {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem const char *f_name; /* field name */
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem uint_t f_width; /* output width */
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ipmpstat_sfunc_t *f_sfunc; /* value->string function */
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem} ipmpstat_field_t;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem/*
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * Data type that specifies the output field order; used by ofmt_output*()
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem */
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemtypedef struct ipmpstat_ofmt {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem const ipmpstat_field_t *o_field; /* current field info */
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem struct ipmpstat_ofmt *o_next; /* next field */
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem} ipmpstat_ofmt_t;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem/*
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * Function pointers used to iterate through IPMP objects.
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem */
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemtypedef void ipmpstat_cbfunc_t(ipmp_handle_t, void *, void *);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemtypedef void ipmpstat_walker_t(ipmp_handle_t, ipmpstat_cbfunc_t *, void *);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem/*
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * Data type used to implement nested walks.
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem */
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemtypedef struct ipmpstat_walkdata {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ipmpstat_cbfunc_t *iw_func; /* caller-specified callback */
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem void *iw_funcarg; /* caller-specified arg */
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem} ipmpstat_walkdata_t;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem/*
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * Data type used by enum2str() to map an enumerated value to a string.
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem */
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemtypedef struct ipmpstat_enum {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem const char *e_name; /* string */
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem int e_val; /* value */
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem} ipmpstat_enum_t;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem/*
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * Data type used to pass state between probe_output() and probe_event().
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem */
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemtypedef struct ipmpstat_probe_state {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ipmp_handle_t ps_ih; /* open IPMP handle */
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ipmpstat_ofmt_t *ps_ofmt; /* requested ofmt string */
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem} ipmpstat_probe_state_t;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem/*
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * Options that modify the output mode; more than one may be lit.
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem */
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemtypedef enum {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem IPMPSTAT_OPT_NUMERIC = 0x1,
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem IPMPSTAT_OPT_PARSABLE = 0x2
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem} ipmpstat_opt_t;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem/*
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * Indices for the FLAGS field of the `-i' output format.
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem */
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemenum {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem IPMPSTAT_IFLAG_INDEX, IPMPSTAT_SFLAG_INDEX, IPMPSTAT_M4FLAG_INDEX,
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem IPMPSTAT_BFLAG_INDEX, IPMPSTAT_M6FLAG_INDEX, IPMPSTAT_DFLAG_INDEX,
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem IPMPSTAT_HFLAG_INDEX, IPMPSTAT_NUM_FLAGS
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem};
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem#define IPMPSTAT_NCOL 80
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem#define NS2FLOATMS(ns) ((float)(ns) / (NANOSEC / MILLISEC))
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem#define MS2FLOATSEC(ms) ((float)(ms) / 1000)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic const char *progname;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic hrtime_t probe_output_start;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic struct winsize winsize;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic ipmpstat_opt_t opt;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic ipmpstat_enum_t addr_state[], group_state[], if_state[], if_link[];
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic ipmpstat_enum_t if_probe[], targ_mode[];
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic ipmpstat_field_t addr_fields[], group_fields[], if_fields[];
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic ipmpstat_field_t probe_fields[], targ_fields[];
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic ipmpstat_cbfunc_t walk_addr_cbfunc, walk_if_cbfunc;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic ipmpstat_cbfunc_t info_output_cbfunc, targinfo_output_cbfunc;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic ipmpstat_walker_t walk_addr, walk_if, walk_group;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic int probe_event(sysevent_t *, void *);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic void probe_output(ipmp_handle_t, ipmpstat_ofmt_t *);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic ipmpstat_field_t *field_find(ipmpstat_field_t *, const char *);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic ipmpstat_ofmt_t *ofmt_create(const char *, ipmpstat_field_t []);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic void ofmt_output(const ipmpstat_ofmt_t *, ipmp_handle_t, void *);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic void ofmt_destroy(ipmpstat_ofmt_t *);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic void enum2str(const ipmpstat_enum_t *, int, char *, uint_t);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic void sockaddr2str(const struct sockaddr_storage *, char *, uint_t);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic void sighandler(int);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic void usage(void);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic void die(const char *, ...);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic void die_ipmperr(int, const char *, ...);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic void warn(const char *, ...);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic void warn_ipmperr(int, const char *, ...);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemint
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemmain(int argc, char **argv)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem{
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem int c;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem int err;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem const char *ofields = NULL;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ipmp_handle_t ih;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ipmp_qcontext_t qcontext = IPMP_QCONTEXT_SNAP;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ipmpstat_ofmt_t *ofmt;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ipmpstat_field_t *fields = NULL;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ipmpstat_cbfunc_t *cbfunc;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ipmpstat_walker_t *walker;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if ((progname = strrchr(argv[0], '/')) == NULL)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem progname = argv[0];
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem else
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem progname++;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem (void) setlocale(LC_ALL, "");
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem (void) textdomain(TEXT_DOMAIN);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem while ((c = getopt(argc, argv, "nLPo:agipt")) != EOF) {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (fields != NULL && strchr("agipt", c) != NULL)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem die("only one output format may be specified\n");
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem switch (c) {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem case 'n':
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem opt |= IPMPSTAT_OPT_NUMERIC;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem break;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem case 'L':
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem /* Undocumented option: for testing use ONLY */
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem qcontext = IPMP_QCONTEXT_LIVE;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem break;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem case 'P':
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem opt |= IPMPSTAT_OPT_PARSABLE;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem break;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem case 'o':
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ofields = optarg;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem break;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem case 'a':
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem walker = walk_addr;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem cbfunc = info_output_cbfunc;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem fields = addr_fields;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem break;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem case 'g':
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem walker = walk_group;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem cbfunc = info_output_cbfunc;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem fields = group_fields;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem break;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem case 'i':
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem walker = walk_if;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem cbfunc = info_output_cbfunc;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem fields = if_fields;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem break;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem case 'p':
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem fields = probe_fields;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem break;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem case 't':
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem walker = walk_if;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem cbfunc = targinfo_output_cbfunc;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem fields = targ_fields;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem break;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem default:
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem usage();
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem break;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem }
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem }
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (argc > optind || fields == NULL)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem usage();
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (opt & IPMPSTAT_OPT_PARSABLE) {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (ofields == NULL) {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem die("output field list (-o) required in parsable "
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem "output mode\n");
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem } else if (strcasecmp(ofields, "all") == 0) {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem die("\"all\" not allowed in parsable output mode\n");
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem }
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem }
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem /*
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * Obtain the window size and monitor changes to the size. This data
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * is used to redisplay the output headers when necessary.
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem */
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem (void) sigset(SIGWINCH, sighandler);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem sighandler(SIGWINCH);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if ((err = ipmp_open(&ih)) != IPMP_SUCCESS)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem die_ipmperr(err, "cannot create IPMP handle");
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (ipmp_ping_daemon(ih) != IPMP_SUCCESS)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem die("cannot contact in.mpathd(1M) -- is IPMP in use?\n");
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem /*
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * Create the ofmt linked list that will eventually be passed to
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * to ofmt_output() to output the fields.
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem */
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ofmt = ofmt_create(ofields, fields);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem /*
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * If we've been asked to display probes, then call the probe output
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * function. Otherwise, snapshot IPMP state (or use live state) and
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * invoke the specified walker with the specified callback function.
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem */
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (fields == probe_fields) {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem probe_output(ih, ofmt);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem } else {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if ((err = ipmp_setqcontext(ih, qcontext)) != IPMP_SUCCESS) {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (qcontext == IPMP_QCONTEXT_SNAP)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem die_ipmperr(err, "cannot snapshot IPMP state");
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem else
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem die_ipmperr(err, "cannot use live IPMP state");
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem }
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem (*walker)(ih, cbfunc, ofmt);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem }
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ofmt_destroy(ofmt);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ipmp_close(ih);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem return (EXIT_SUCCESS);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem}
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem/*
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * Walks all IPMP groups on the system and invokes `cbfunc' on each, passing
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * it `ih', the ipmp_groupinfo_t pointer, and `arg'.
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem */
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic void
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemwalk_group(ipmp_handle_t ih, ipmpstat_cbfunc_t *cbfunc, void *arg)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem{
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem int err;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem uint_t i;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ipmp_groupinfo_t *grinfop;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ipmp_grouplist_t *grlistp;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if ((err = ipmp_getgrouplist(ih, &grlistp)) != IPMP_SUCCESS)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem die_ipmperr(err, "cannot get IPMP group list");
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem for (i = 0; i < grlistp->gl_ngroup; i++) {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem err = ipmp_getgroupinfo(ih, grlistp->gl_groups[i], &grinfop);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (err != IPMP_SUCCESS) {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem warn_ipmperr(err, "cannot get info for group `%s'",
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem grlistp->gl_groups[i]);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem continue;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem }
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem (*cbfunc)(ih, grinfop, arg);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ipmp_freegroupinfo(grinfop);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem }
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ipmp_freegrouplist(grlistp);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem}
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem/*
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * Walks all IPMP interfaces on the system and invokes `cbfunc' on each,
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * passing it `ih', the ipmp_ifinfo_t pointer, and `arg'.
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem */
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic void
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemwalk_if(ipmp_handle_t ih, ipmpstat_cbfunc_t *cbfunc, void *arg)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem{
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ipmpstat_walkdata_t iw = { cbfunc, arg };
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem walk_group(ih, walk_if_cbfunc, &iw);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem}
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem/*
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * Walks all IPMP data addresses on the system and invokes `cbfunc' on each.
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * passing it `ih', the ipmp_addrinfo_t pointer, and `arg'.
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem */
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic void
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemwalk_addr(ipmp_handle_t ih, ipmpstat_cbfunc_t *cbfunc, void *arg)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem{
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ipmpstat_walkdata_t iw = { cbfunc, arg };
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem walk_group(ih, walk_addr_cbfunc, &iw);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem}
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem/*
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * Nested walker callback function for walk_if().
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem */
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic void
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemwalk_if_cbfunc(ipmp_handle_t ih, void *infop, void *arg)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem{
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem int err;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem uint_t i;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ipmp_groupinfo_t *grinfop = infop;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ipmp_ifinfo_t *ifinfop;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ipmp_iflist_t *iflistp = grinfop->gr_iflistp;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ipmpstat_walkdata_t *iwp = arg;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem for (i = 0; i < iflistp->il_nif; i++) {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem err = ipmp_getifinfo(ih, iflistp->il_ifs[i], &ifinfop);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (err != IPMP_SUCCESS) {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem warn_ipmperr(err, "cannot get info for interface `%s'",
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem iflistp->il_ifs[i]);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem continue;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem }
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem (*iwp->iw_func)(ih, ifinfop, iwp->iw_funcarg);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ipmp_freeifinfo(ifinfop);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem }
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem}
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem/*
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * Nested walker callback function for walk_addr().
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem */
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic void
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemwalk_addr_cbfunc(ipmp_handle_t ih, void *infop, void *arg)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem{
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem int err;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem uint_t i;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ipmp_groupinfo_t *grinfop = infop;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ipmp_addrinfo_t *adinfop;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ipmp_addrlist_t *adlistp = grinfop->gr_adlistp;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ipmpstat_walkdata_t *iwp = arg;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem char addr[INET6_ADDRSTRLEN];
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem struct sockaddr_storage *addrp;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem for (i = 0; i < adlistp->al_naddr; i++) {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem addrp = &adlistp->al_addrs[i];
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem err = ipmp_getaddrinfo(ih, grinfop->gr_name, addrp, &adinfop);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (err != IPMP_SUCCESS) {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem sockaddr2str(addrp, addr, sizeof (addr));
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem warn_ipmperr(err, "cannot get info for `%s'", addr);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem continue;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem }
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem (*iwp->iw_func)(ih, adinfop, iwp->iw_funcarg);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ipmp_freeaddrinfo(adinfop);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem }
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem}
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic void
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemsfunc_nvwarn(const char *nvname, char *buf, uint_t bufsize)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem{
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem warn("cannot retrieve %s\n", nvname);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem (void) strlcpy(buf, "?", bufsize);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem}
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic void
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemsfunc_addr_address(ipmpstat_sfunc_arg_t *arg, char *buf, uint_t bufsize)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem{
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ipmp_addrinfo_t *adinfop = arg->sa_data;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem sockaddr2str(&adinfop->ad_addr, buf, bufsize);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem}
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic void
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemsfunc_addr_group(ipmpstat_sfunc_arg_t *arg, char *buf, uint_t bufsize)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem{
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem int err;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ipmp_addrinfo_t *adinfop = arg->sa_data;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ipmp_groupinfo_t *grinfop;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem err = ipmp_getgroupinfo(arg->sa_ih, adinfop->ad_group, &grinfop);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (err != IPMP_SUCCESS) {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem warn_ipmperr(err, "cannot get info for group `%s'",
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem adinfop->ad_group);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem (void) strlcpy(buf, "?", bufsize);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem return;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem }
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem (void) strlcpy(buf, grinfop->gr_ifname, bufsize);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ipmp_freegroupinfo(grinfop);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem}
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic void
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemsfunc_addr_state(ipmpstat_sfunc_arg_t *arg, char *buf, uint_t bufsize)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem{
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ipmp_addrinfo_t *adinfop = arg->sa_data;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem enum2str(addr_state, adinfop->ad_state, buf, bufsize);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem}
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic void
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemsfunc_addr_inbound(ipmpstat_sfunc_arg_t *arg, char *buf, uint_t bufsize)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem{
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ipmp_addrinfo_t *adinfop = arg->sa_data;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem (void) strlcpy(buf, adinfop->ad_binding, bufsize);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem}
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic void
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemsfunc_addr_outbound(ipmpstat_sfunc_arg_t *arg, char *buf, uint_t bufsize)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem{
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem int err;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem uint_t i, nactive = 0;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ipmp_ifinfo_t *ifinfop;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ipmp_iflist_t *iflistp;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ipmp_addrinfo_t *adinfop = arg->sa_data;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ipmp_groupinfo_t *grinfop;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (adinfop->ad_state == IPMP_ADDR_DOWN)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem return;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem /*
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * If there's no inbound interface for this address, there can't
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * be any outbound traffic.
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem */
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (adinfop->ad_binding[0] == '\0')
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem return;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem /*
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * The address can use any active interface in the group, so
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * obtain all of those.
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem */
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem err = ipmp_getgroupinfo(arg->sa_ih, adinfop->ad_group, &grinfop);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (err != IPMP_SUCCESS) {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem warn_ipmperr(err, "cannot get info for group `%s'",
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem adinfop->ad_group);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem (void) strlcpy(buf, "?", bufsize);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem return;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem }
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem iflistp = grinfop->gr_iflistp;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem for (i = 0; i < iflistp->il_nif; i++) {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem err = ipmp_getifinfo(arg->sa_ih, iflistp->il_ifs[i], &ifinfop);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (err != IPMP_SUCCESS) {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem warn_ipmperr(err, "cannot get info for interface `%s'",
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem iflistp->il_ifs[i]);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem continue;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem }
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (ifinfop->if_flags & IPMP_IFFLAG_ACTIVE) {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (nactive++ != 0)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem (void) strlcat(buf, " ", bufsize);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem (void) strlcat(buf, ifinfop->if_name, bufsize);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem }
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ipmp_freeifinfo(ifinfop);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem }
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ipmp_freegroupinfo(grinfop);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem}
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic void
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemsfunc_group_name(ipmpstat_sfunc_arg_t *arg, char *buf, uint_t bufsize)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem{
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ipmp_groupinfo_t *grinfop = arg->sa_data;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem (void) strlcpy(buf, grinfop->gr_name, bufsize);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem}
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic void
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemsfunc_group_ifname(ipmpstat_sfunc_arg_t *arg, char *buf, uint_t bufsize)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem{
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ipmp_groupinfo_t *grinfop = arg->sa_data;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem (void) strlcpy(buf, grinfop->gr_ifname, bufsize);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem}
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic void
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemsfunc_group_state(ipmpstat_sfunc_arg_t *arg, char *buf, uint_t bufsize)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem{
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ipmp_groupinfo_t *grinfop = arg->sa_data;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem enum2str(group_state, grinfop->gr_state, buf, bufsize);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem}
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic void
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemsfunc_group_fdt(ipmpstat_sfunc_arg_t *arg, char *buf, uint_t bufsize)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem{
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ipmp_groupinfo_t *grinfop = arg->sa_data;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (grinfop->gr_fdt == 0)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem return;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem (void) snprintf(buf, bufsize, "%.2fs", MS2FLOATSEC(grinfop->gr_fdt));
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem}
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic void
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemsfunc_group_interfaces(ipmpstat_sfunc_arg_t *arg, char *buf, uint_t bufsize)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem{
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem int err;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem uint_t i;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem char *active, *inactive, *unusable;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem uint_t nactive = 0, ninactive = 0, nunusable = 0;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ipmp_groupinfo_t *grinfop = arg->sa_data;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ipmp_iflist_t *iflistp = grinfop->gr_iflistp;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ipmp_ifinfo_t *ifinfop;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem active = alloca(bufsize);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem active[0] = '\0';
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem inactive = alloca(bufsize);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem inactive[0] = '\0';
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem unusable = alloca(bufsize);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem unusable[0] = '\0';
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem for (i = 0; i < iflistp->il_nif; i++) {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem err = ipmp_getifinfo(arg->sa_ih, iflistp->il_ifs[i], &ifinfop);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (err != IPMP_SUCCESS) {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem warn_ipmperr(err, "cannot get info for interface `%s'",
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem iflistp->il_ifs[i]);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem continue;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem }
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (ifinfop->if_flags & IPMP_IFFLAG_ACTIVE) {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (nactive++ != 0)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem (void) strlcat(active, " ", bufsize);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem (void) strlcat(active, ifinfop->if_name, bufsize);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem } else if (ifinfop->if_flags & IPMP_IFFLAG_INACTIVE) {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (ninactive++ != 0)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem (void) strlcat(inactive, " ", bufsize);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem (void) strlcat(inactive, ifinfop->if_name, bufsize);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem } else {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (nunusable++ != 0)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem (void) strlcat(unusable, " ", bufsize);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem (void) strlcat(unusable, ifinfop->if_name, bufsize);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem }
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ipmp_freeifinfo(ifinfop);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem }
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem (void) strlcpy(buf, active, bufsize);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (ninactive > 0) {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (nactive != 0)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem (void) strlcat(buf, " ", bufsize);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem (void) strlcat(buf, "(", bufsize);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem (void) strlcat(buf, inactive, bufsize);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem (void) strlcat(buf, ")", bufsize);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem }
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (nunusable > 0) {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (nactive + ninactive != 0)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem (void) strlcat(buf, " ", bufsize);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem (void) strlcat(buf, "[", bufsize);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem (void) strlcat(buf, unusable, bufsize);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem (void) strlcat(buf, "]", bufsize);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem }
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem}
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic void
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemsfunc_if_name(ipmpstat_sfunc_arg_t *arg, char *buf, uint_t bufsize)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem{
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ipmp_ifinfo_t *ifinfop = arg->sa_data;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem (void) strlcpy(buf, ifinfop->if_name, bufsize);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem}
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic void
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemsfunc_if_active(ipmpstat_sfunc_arg_t *arg, char *buf, uint_t bufsize)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem{
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ipmp_ifinfo_t *ifinfop = arg->sa_data;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (ifinfop->if_flags & IPMP_IFFLAG_ACTIVE)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem (void) strlcpy(buf, "yes", bufsize);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem else
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem (void) strlcpy(buf, "no", bufsize);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem}
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic void
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemsfunc_if_group(ipmpstat_sfunc_arg_t *arg, char *buf, uint_t bufsize)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem{
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem int err;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ipmp_ifinfo_t *ifinfop = arg->sa_data;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ipmp_groupinfo_t *grinfop;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem err = ipmp_getgroupinfo(arg->sa_ih, ifinfop->if_group, &grinfop);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (err != IPMP_SUCCESS) {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem warn_ipmperr(err, "cannot get info for group `%s'",
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ifinfop->if_group);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem (void) strlcpy(buf, "?", bufsize);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem return;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem }
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem (void) strlcpy(buf, grinfop->gr_ifname, bufsize);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ipmp_freegroupinfo(grinfop);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem}
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic void
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemsfunc_if_flags(ipmpstat_sfunc_arg_t *arg, char *buf, uint_t bufsize)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem{
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem int err;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ipmp_ifinfo_t *ifinfop = arg->sa_data;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ipmp_groupinfo_t *grinfop;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem assert(bufsize > IPMPSTAT_NUM_FLAGS);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem (void) memset(buf, '-', IPMPSTAT_NUM_FLAGS);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem buf[IPMPSTAT_NUM_FLAGS] = '\0';
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (ifinfop->if_type == IPMP_IF_STANDBY)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem buf[IPMPSTAT_SFLAG_INDEX] = 's';
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (ifinfop->if_flags & IPMP_IFFLAG_INACTIVE)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem buf[IPMPSTAT_IFLAG_INDEX] = 'i';
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (ifinfop->if_flags & IPMP_IFFLAG_DOWN)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem buf[IPMPSTAT_DFLAG_INDEX] = 'd';
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (ifinfop->if_flags & IPMP_IFFLAG_HWADDRDUP)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem buf[IPMPSTAT_HFLAG_INDEX] = 'h';
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem err = ipmp_getgroupinfo(arg->sa_ih, ifinfop->if_group, &grinfop);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (err != IPMP_SUCCESS) {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem warn_ipmperr(err, "cannot get broadcast/multicast info for "
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem "group `%s'", ifinfop->if_group);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem return;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem }
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (strcmp(grinfop->gr_m4ifname, ifinfop->if_name) == 0)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem buf[IPMPSTAT_M4FLAG_INDEX] = 'm';
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (strcmp(grinfop->gr_m6ifname, ifinfop->if_name) == 0)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem buf[IPMPSTAT_M6FLAG_INDEX] = 'M';
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (strcmp(grinfop->gr_bcifname, ifinfop->if_name) == 0)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem buf[IPMPSTAT_BFLAG_INDEX] = 'b';
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ipmp_freegroupinfo(grinfop);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem}
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic void
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemsfunc_if_link(ipmpstat_sfunc_arg_t *arg, char *buf, uint_t bufsize)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem{
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ipmp_ifinfo_t *ifinfop = arg->sa_data;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem enum2str(if_link, ifinfop->if_linkstate, buf, bufsize);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem}
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic void
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemsfunc_if_probe(ipmpstat_sfunc_arg_t *arg, char *buf, uint_t bufsize)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem{
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ipmp_ifinfo_t *ifinfop = arg->sa_data;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem enum2str(if_probe, ifinfop->if_probestate, buf, bufsize);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem}
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic void
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemsfunc_if_state(ipmpstat_sfunc_arg_t *arg, char *buf, uint_t bufsize)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem{
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ipmp_ifinfo_t *ifinfop = arg->sa_data;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem enum2str(if_state, ifinfop->if_state, buf, bufsize);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem}
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic void
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemsfunc_probe_id(ipmpstat_sfunc_arg_t *arg, char *buf, uint_t bufsize)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem{
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem uint32_t probe_id;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem nvlist_t *nvl = arg->sa_data;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (nvlist_lookup_uint32(nvl, IPMP_PROBE_ID, &probe_id) != 0) {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem sfunc_nvwarn("IPMP_PROBE_ID", buf, bufsize);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem return;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem }
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem (void) snprintf(buf, bufsize, "%u", probe_id);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem}
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic void
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemsfunc_probe_ifname(ipmpstat_sfunc_arg_t *arg, char *buf, uint_t bufsize)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem{
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem char *ifname;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem nvlist_t *nvl = arg->sa_data;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (nvlist_lookup_string(nvl, IPMP_IF_NAME, &ifname) != 0) {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem sfunc_nvwarn("IPMP_IF_NAME", buf, bufsize);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem return;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem }
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem (void) strlcpy(buf, ifname, bufsize);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem}
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic void
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemsfunc_probe_time(ipmpstat_sfunc_arg_t *arg, char *buf, uint_t bufsize)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem{
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem hrtime_t start;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem nvlist_t *nvl = arg->sa_data;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (nvlist_lookup_hrtime(nvl, IPMP_PROBE_START_TIME, &start) != 0) {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem sfunc_nvwarn("IPMP_PROBE_START_TIME", buf, bufsize);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem return;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem }
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem (void) snprintf(buf, bufsize, "%.2fs",
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem (float)(start - probe_output_start) / NANOSEC);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem}
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic void
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemsfunc_probe_target(ipmpstat_sfunc_arg_t *arg, char *buf, uint_t bufsize)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem{
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem uint_t nelem;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem struct sockaddr_storage *target;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem nvlist_t *nvl = arg->sa_data;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (nvlist_lookup_byte_array(nvl, IPMP_PROBE_TARGET,
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem (uchar_t **)&target, &nelem) != 0) {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem sfunc_nvwarn("IPMP_PROBE_TARGET", buf, bufsize);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem return;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem }
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem sockaddr2str(target, buf, bufsize);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem}
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic void
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemsfunc_probe_rtt(ipmpstat_sfunc_arg_t *arg, char *buf, uint_t bufsize)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem{
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem hrtime_t start, ackproc;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem nvlist_t *nvl = arg->sa_data;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem uint32_t state;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (nvlist_lookup_uint32(nvl, IPMP_PROBE_STATE, &state) != 0) {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem sfunc_nvwarn("IPMP_PROBE_STATE", buf, bufsize);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem return;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem }
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (state != IPMP_PROBE_ACKED)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem return;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (nvlist_lookup_hrtime(nvl, IPMP_PROBE_START_TIME, &start) != 0) {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem sfunc_nvwarn("IPMP_PROBE_START_TIME", buf, bufsize);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem return;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem }
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (nvlist_lookup_hrtime(nvl, IPMP_PROBE_ACKPROC_TIME, &ackproc) != 0) {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem sfunc_nvwarn("IPMP_PROBE_ACKPROC_TIME", buf, bufsize);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem return;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem }
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem (void) snprintf(buf, bufsize, "%.2fms", NS2FLOATMS(ackproc - start));
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem}
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic void
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemsfunc_probe_netrtt(ipmpstat_sfunc_arg_t *arg, char *buf, uint_t bufsize)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem{
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem hrtime_t sent, ackrecv;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem nvlist_t *nvl = arg->sa_data;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem uint32_t state;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (nvlist_lookup_uint32(nvl, IPMP_PROBE_STATE, &state) != 0) {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem sfunc_nvwarn("IPMP_PROBE_STATE", buf, bufsize);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem return;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem }
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (state != IPMP_PROBE_ACKED)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem return;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (nvlist_lookup_hrtime(nvl, IPMP_PROBE_SENT_TIME, &sent) != 0) {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem sfunc_nvwarn("IPMP_PROBE_SENT_TIME", buf, bufsize);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem return;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem }
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (nvlist_lookup_hrtime(nvl, IPMP_PROBE_ACKRECV_TIME, &ackrecv) != 0) {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem sfunc_nvwarn("IPMP_PROBE_ACKRECV_TIME", buf, bufsize);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem return;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem }
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem (void) snprintf(buf, bufsize, "%.2fms", NS2FLOATMS(ackrecv - sent));
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem}
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic void
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemsfunc_probe_rttavg(ipmpstat_sfunc_arg_t *arg, char *buf, uint_t bufsize)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem{
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem int64_t rttavg;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem nvlist_t *nvl = arg->sa_data;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (nvlist_lookup_int64(nvl, IPMP_PROBE_TARGET_RTTAVG, &rttavg) != 0) {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem sfunc_nvwarn("IPMP_PROBE_TARGET_RTTAVG", buf, bufsize);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem return;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem }
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (rttavg != 0)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem (void) snprintf(buf, bufsize, "%.2fms", NS2FLOATMS(rttavg));
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem}
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic void
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemsfunc_probe_rttdev(ipmpstat_sfunc_arg_t *arg, char *buf, uint_t bufsize)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem{
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem int64_t rttdev;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem nvlist_t *nvl = arg->sa_data;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (nvlist_lookup_int64(nvl, IPMP_PROBE_TARGET_RTTDEV, &rttdev) != 0) {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem sfunc_nvwarn("IPMP_PROBE_TARGET_RTTDEV", buf, bufsize);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem return;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem }
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (rttdev != 0)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem (void) snprintf(buf, bufsize, "%.2fms", NS2FLOATMS(rttdev));
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem}
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem/* ARGSUSED */
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic void
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemprobe_enabled_cbfunc(ipmp_handle_t ih, void *infop, void *arg)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem{
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem uint_t *nenabledp = arg;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ipmp_ifinfo_t *ifinfop = infop;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (ifinfop->if_probestate != IPMP_PROBE_DISABLED)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem (*nenabledp)++;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem}
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic void
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemprobe_output(ipmp_handle_t ih, ipmpstat_ofmt_t *ofmt)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem{
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem char sub[MAX_SUBID_LEN];
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem evchan_t *evch;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ipmpstat_probe_state_t ps = { ih, ofmt };
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem uint_t nenabled = 0;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem /*
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * Check if any interfaces are enabled for probe-based failure
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * detection. If not, immediately fail.
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem */
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem walk_if(ih, probe_enabled_cbfunc, &nenabled);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (nenabled == 0)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem die("probe-based failure detection is disabled\n");
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem probe_output_start = gethrtime();
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem /*
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * Unfortunately, until 4791900 is fixed, only privileged processes
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * can bind and thus receive sysevents.
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem */
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem errno = sysevent_evc_bind(IPMP_EVENT_CHAN, &evch, EVCH_CREAT);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (errno != 0) {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (errno == EPERM)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem die("insufficient privileges for -p\n");
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem die("sysevent_evc_bind to channel %s failed", IPMP_EVENT_CHAN);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem }
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem /*
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * The subscriber must be unique in order for sysevent_evc_subscribe()
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * to succeed, so combine our name and pid.
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem */
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem (void) snprintf(sub, sizeof (sub), "%d-%s", getpid(), progname);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem errno = sysevent_evc_subscribe(evch, sub, EC_IPMP, probe_event, &ps, 0);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (errno != 0)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem die("sysevent_evc_subscribe for class %s failed", EC_IPMP);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem for (;;)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem (void) pause();
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem}
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic int
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemprobe_event(sysevent_t *ev, void *arg)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem{
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem nvlist_t *nvl;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem uint32_t state;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem uint32_t version;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ipmpstat_probe_state_t *psp = arg;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (strcmp(sysevent_get_subclass_name(ev), ESC_IPMP_PROBE_STATE) != 0)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem return (0);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (sysevent_get_attr_list(ev, &nvl) != 0) {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem warn("sysevent_get_attr_list failed; dropping event");
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem return (0);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem }
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (nvlist_lookup_uint32(nvl, IPMP_EVENT_VERSION, &version) != 0) {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem warn("dropped event with no IPMP_EVENT_VERSION\n");
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem goto out;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem }
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (version != IPMP_EVENT_CUR_VERSION) {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem warn("dropped event with unsupported IPMP_EVENT_VERSION %d\n",
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem version);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem goto out;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem }
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (nvlist_lookup_uint32(nvl, IPMP_PROBE_STATE, &state) != 0) {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem warn("dropped event with no IPMP_PROBE_STATE\n");
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem goto out;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem }
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (state == IPMP_PROBE_ACKED || state == IPMP_PROBE_LOST)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ofmt_output(psp->ps_ofmt, psp->ps_ih, nvl);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemout:
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem nvlist_free(nvl);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem return (0);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem}
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic void
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemsfunc_targ_ifname(ipmpstat_sfunc_arg_t *arg, char *buf, uint_t bufsize)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem{
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ipmp_targinfo_t *targinfop = arg->sa_data;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem (void) strlcpy(buf, targinfop->it_name, bufsize);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem}
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic void
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemsfunc_targ_mode(ipmpstat_sfunc_arg_t *arg, char *buf, uint_t bufsize)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem{
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ipmp_targinfo_t *targinfop = arg->sa_data;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem enum2str(targ_mode, targinfop->it_targmode, buf, bufsize);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem}
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic void
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemsfunc_targ_testaddr(ipmpstat_sfunc_arg_t *arg, char *buf, uint_t bufsize)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem{
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ipmp_targinfo_t *targinfop = arg->sa_data;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (targinfop->it_targmode != IPMP_TARG_DISABLED)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem sockaddr2str(&targinfop->it_testaddr, buf, bufsize);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem}
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic void
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemsfunc_targ_targets(ipmpstat_sfunc_arg_t *arg, char *buf, uint_t bufsize)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem{
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem uint_t i;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem char *targname = alloca(bufsize);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ipmp_targinfo_t *targinfop = arg->sa_data;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ipmp_addrlist_t *targlistp = targinfop->it_targlistp;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem for (i = 0; i < targlistp->al_naddr; i++) {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem sockaddr2str(&targlistp->al_addrs[i], targname, bufsize);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem (void) strlcat(buf, targname, bufsize);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if ((i + 1) < targlistp->al_naddr)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem (void) strlcat(buf, " ", bufsize);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem }
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem}
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic void
e11c3f44f531fdff80941ce57c065d2ae861cefcmeeminfo_output_cbfunc(ipmp_handle_t ih, void *infop, void *arg)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem{
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ofmt_output(arg, ih, infop);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem}
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic void
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemtarginfo_output_cbfunc(ipmp_handle_t ih, void *infop, void *arg)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem{
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ipmp_ifinfo_t *ifinfop = infop;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ipmp_if_targmode_t targmode4 = ifinfop->if_targinfo4.it_targmode;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ipmp_if_targmode_t targmode6 = ifinfop->if_targinfo6.it_targmode;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem /*
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * Usually, either IPv4 or IPv6 probing will be enabled, but the admin
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * may enable both. If only one is enabled, omit the other one so as
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * to not encourage the admin to enable both. If neither is enabled,
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * we still print one just so the admin can see a MODE of "disabled".
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem */
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (targmode4 != IPMP_TARG_DISABLED || targmode6 == IPMP_TARG_DISABLED)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ofmt_output(arg, ih, &ifinfop->if_targinfo4);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (targmode6 != IPMP_TARG_DISABLED)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ofmt_output(arg, ih, &ifinfop->if_targinfo6);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem}
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem/*
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * Creates an ipmpstat_ofmt_t field list from the comma-separated list of
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * user-specified fields passed via `ofields'. The table of known fields
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * (and their attributes) is passed via `fields'.
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem */
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic ipmpstat_ofmt_t *
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemofmt_create(const char *ofields, ipmpstat_field_t fields[])
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem{
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem char *token, *lasts, *ofields_dup;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem const char *fieldname;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ipmpstat_ofmt_t *ofmt, *ofmt_head = NULL, *ofmt_tail;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ipmpstat_field_t *fieldp;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem uint_t cols = 0;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem /*
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * If "-o" was omitted or "-o all" was specified, build a list of
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * field names. If "-o" was omitted, stop building the list when
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * we run out of columns.
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem */
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (ofields == NULL || strcasecmp(ofields, "all") == 0) {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem for (fieldp = fields; fieldp->f_name != NULL; fieldp++) {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem cols += fieldp->f_width;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (ofields == NULL && cols > IPMPSTAT_NCOL)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem break;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if ((ofmt = calloc(sizeof (*ofmt), 1)) == NULL)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem die("cannot allocate output format list");
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ofmt->o_field = fieldp;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (ofmt_head == NULL) {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ofmt_head = ofmt;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ofmt_tail = ofmt;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem } else {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ofmt_tail->o_next = ofmt;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ofmt_tail = ofmt;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem }
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem }
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem return (ofmt_head);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem }
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if ((ofields_dup = strdup(ofields)) == NULL)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem die("cannot allocate output format list");
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem token = ofields_dup;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem while ((fieldname = strtok_r(token, ",", &lasts)) != NULL) {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem token = NULL;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if ((fieldp = field_find(fields, fieldname)) == NULL) {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem /*
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * Since machine parsers are unlikely to be able to
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * gracefully handle missing fields, die if we're in
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * parsable mode. Otherwise, just print a warning.
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem */
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (opt & IPMPSTAT_OPT_PARSABLE)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem die("unknown output field `%s'\n", fieldname);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem warn("ignoring unknown output field `%s'\n", fieldname);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem continue;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem }
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if ((ofmt = calloc(sizeof (*ofmt), 1)) == NULL)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem die("cannot allocate output format list");
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ofmt->o_field = fieldp;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (ofmt_head == NULL) {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ofmt_head = ofmt;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ofmt_tail = ofmt;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem } else {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ofmt_tail->o_next = ofmt;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ofmt_tail = ofmt;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem }
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem }
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem free(ofields_dup);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (ofmt_head == NULL)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem die("no valid output fields specified\n");
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem return (ofmt_head);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem}
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem/*
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * Destroys the provided `ofmt' field list.
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem */
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic void
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemofmt_destroy(ipmpstat_ofmt_t *ofmt)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem{
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ipmpstat_ofmt_t *ofmt_next;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem for (; ofmt != NULL; ofmt = ofmt_next) {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ofmt_next = ofmt->o_next;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem free(ofmt);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem }
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem}
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem/*
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * Outputs a header for the fields named by `ofmt'.
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem */
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic void
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemofmt_output_header(const ipmpstat_ofmt_t *ofmt)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem{
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem const ipmpstat_field_t *fieldp;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem for (; ofmt != NULL; ofmt = ofmt->o_next) {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem fieldp = ofmt->o_field;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (ofmt->o_next == NULL)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem (void) printf("%s", fieldp->f_name);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem else
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem (void) printf("%-*s", fieldp->f_width, fieldp->f_name);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem }
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem (void) printf("\n");
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem}
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem/*
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * Outputs one row of values for the fields named by `ofmt'. The values to
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * output are obtained through the `ofmt' function pointers, which are
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * indirectly passed the `ih' and `arg' structures for state; see the block
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * comment at the start of this file for details.
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem */
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic void
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemofmt_output(const ipmpstat_ofmt_t *ofmt, ipmp_handle_t ih, void *arg)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem{
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem int i;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem char buf[1024];
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem boolean_t escsep;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem static int nrow;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem const char *value;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem uint_t width, valwidth;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem uint_t compress, overflow = 0;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem const ipmpstat_field_t *fieldp;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ipmpstat_sfunc_arg_t sfunc_arg;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem /*
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * For each screenful of data, display the header.
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem */
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if ((nrow++ % winsize.ws_row) == 0 && !(opt & IPMPSTAT_OPT_PARSABLE)) {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ofmt_output_header(ofmt);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem nrow++;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem }
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem /*
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * Check if we'll be displaying multiple fields per line, and thus
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * need to escape the field separator.
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem */
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem escsep = (ofmt != NULL && ofmt->o_next != NULL);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem for (; ofmt != NULL; ofmt = ofmt->o_next) {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem fieldp = ofmt->o_field;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem sfunc_arg.sa_ih = ih;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem sfunc_arg.sa_data = arg;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem buf[0] = '\0';
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem (*fieldp->f_sfunc)(&sfunc_arg, buf, sizeof (buf));
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (opt & IPMPSTAT_OPT_PARSABLE) {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem for (i = 0; buf[i] != '\0'; i++) {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (escsep && (buf[i] == ':' || buf[i] == '\\'))
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem (void) putchar('\\');
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem (void) putchar(buf[i]);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem }
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (ofmt->o_next != NULL)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem (void) putchar(':');
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem } else {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem value = (buf[0] == '\0') ? "--" : buf;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem /*
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * To avoid needless line-wraps, for the last field,
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * don't include any trailing whitespace.
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem */
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (ofmt->o_next == NULL) {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem (void) printf("%s", value);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem continue;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem }
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem /*
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * For other fields, grow the width as necessary to
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * ensure the value completely fits. However, if
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * there's unused whitespace in subsequent fields,
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * then "compress" that whitespace to attempt to get
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * the columns to line up again.
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem */
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem width = fieldp->f_width;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem valwidth = strlen(value);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (valwidth + overflow >= width) {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem overflow += valwidth - width + 1;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem (void) printf("%s ", value);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem continue;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem }
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (overflow > 0) {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem compress = MIN(overflow, width - valwidth);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem overflow -= compress;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem width -= compress;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem }
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem (void) printf("%-*s", width, value);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem }
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem }
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem (void) printf("\n");
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem /*
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * In case stdout has been redirected to e.g. a pipe, flush stdout so
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * that commands can act on our output immediately.
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem */
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem (void) fflush(stdout);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem}
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem/*
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * Searches the `fields' array for a field matching `fieldname'. Returns
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * a pointer to that field on success, or NULL on failure.
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem */
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic ipmpstat_field_t *
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemfield_find(ipmpstat_field_t *fields, const char *fieldname)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem{
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ipmpstat_field_t *fieldp;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem for (fieldp = fields; fieldp->f_name != NULL; fieldp++) {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (strcasecmp(fieldp->f_name, fieldname) == 0)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem return (fieldp);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem }
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem return (NULL);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem}
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem/*
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * Uses `enums' to map `enumval' to a string, and stores at most `bufsize'
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * bytes of that string into `buf'.
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem */
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic void
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemenum2str(const ipmpstat_enum_t *enums, int enumval, char *buf, uint_t bufsize)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem{
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem const ipmpstat_enum_t *enump;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem for (enump = enums; enump->e_name != NULL; enump++) {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (enump->e_val == enumval) {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem (void) strlcpy(buf, enump->e_name, bufsize);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem return;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem }
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem }
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem (void) snprintf(buf, bufsize, "<%d>", enumval);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem}
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem/*
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * Stores the stringified value of the sockaddr_storage pointed to by `ssp'
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * into at most `bufsize' bytes of `buf'.
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem */
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic void
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemsockaddr2str(const struct sockaddr_storage *ssp, char *buf, uint_t bufsize)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem{
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem int flags = NI_NOFQDN;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem socklen_t socklen;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem struct sockaddr *sp = (struct sockaddr *)ssp;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem /*
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * Sadly, getnameinfo() does not allow the socklen to be oversized for
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * a given family -- so we must determine the exact size to pass to it.
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem */
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem switch (ssp->ss_family) {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem case AF_INET:
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem socklen = sizeof (struct sockaddr_in);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem break;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem case AF_INET6:
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem socklen = sizeof (struct sockaddr_in6);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem break;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem default:
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem (void) strlcpy(buf, "?", bufsize);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem return;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem }
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (opt & IPMPSTAT_OPT_NUMERIC)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem flags |= NI_NUMERICHOST;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem (void) getnameinfo(sp, socklen, buf, bufsize, NULL, 0, flags);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem}
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic void
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemsighandler(int sig)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem{
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem assert(sig == SIGWINCH);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (ioctl(1, TIOCGWINSZ, &winsize) == -1 ||
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem winsize.ws_col == 0 || winsize.ws_row == 0) {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem winsize.ws_col = 80;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem winsize.ws_row = 24;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem }
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem}
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic void
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemusage(void)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem{
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem const char *argstr = gettext("[-n] [-o <field> [-P]] -a|-g|-i|-p|-t");
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem (void) fprintf(stderr, gettext("usage: %s %s\n"), progname, argstr);
ec382c61f99e6dbbdf119dcf5016ce0481d12e04meem (void) fprintf(stderr, gettext("\n"
ec382c61f99e6dbbdf119dcf5016ce0481d12e04meem " output modes:\t -a display IPMP data address information\n"
ec382c61f99e6dbbdf119dcf5016ce0481d12e04meem "\t\t -g display IPMP group information\n"
ec382c61f99e6dbbdf119dcf5016ce0481d12e04meem "\t\t -i display IPMP-related IP interface information\n"
ec382c61f99e6dbbdf119dcf5016ce0481d12e04meem "\t\t -p display IPMP probe information\n"
ec382c61f99e6dbbdf119dcf5016ce0481d12e04meem "\t\t -t display IPMP target information\n\n"
ec382c61f99e6dbbdf119dcf5016ce0481d12e04meem " options:\t -n display IP addresses numerically\n"
ec382c61f99e6dbbdf119dcf5016ce0481d12e04meem "\t\t -o display only the specified fields, in order\n"
ec382c61f99e6dbbdf119dcf5016ce0481d12e04meem "\t\t -P display using parsable output mode\n"));
ec382c61f99e6dbbdf119dcf5016ce0481d12e04meem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem exit(EXIT_FAILURE);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem}
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem/* PRINTFLIKE1 */
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic void
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemwarn(const char *format, ...)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem{
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem va_list alist;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem int error = errno;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem format = gettext(format);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem (void) fprintf(stderr, gettext("%s: warning: "), progname);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem va_start(alist, format);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem (void) vfprintf(stderr, format, alist);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem va_end(alist);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (strchr(format, '\n') == NULL)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem (void) fprintf(stderr, ": %s\n", strerror(error));
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem}
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem/* PRINTFLIKE2 */
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic void
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemwarn_ipmperr(int ipmperr, const char *format, ...)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem{
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem va_list alist;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem format = gettext(format);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem (void) fprintf(stderr, gettext("%s: warning: "), progname);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem va_start(alist, format);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem (void) vfprintf(stderr, format, alist);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem va_end(alist);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem (void) fprintf(stderr, ": %s\n", ipmp_errmsg(ipmperr));
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem}
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem/* PRINTFLIKE1 */
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic void
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemdie(const char *format, ...)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem{
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem va_list alist;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem int error = errno;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem format = gettext(format);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem (void) fprintf(stderr, "%s: ", progname);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem va_start(alist, format);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem (void) vfprintf(stderr, format, alist);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem va_end(alist);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (strchr(format, '\n') == NULL)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem (void) fprintf(stderr, ": %s\n", strerror(error));
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem exit(EXIT_FAILURE);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem}
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem/* PRINTFLIKE2 */
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic void
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemdie_ipmperr(int ipmperr, const char *format, ...)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem{
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem va_list alist;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem format = gettext(format);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem (void) fprintf(stderr, "%s: ", progname);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem va_start(alist, format);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem (void) vfprintf(stderr, format, alist);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem va_end(alist);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem (void) fprintf(stderr, ": %s\n", ipmp_errmsg(ipmperr));
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem exit(EXIT_FAILURE);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem}
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic ipmpstat_field_t addr_fields[] = {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem { "ADDRESS", 26, sfunc_addr_address },
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem { "STATE", 7, sfunc_addr_state },
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem { "GROUP", 12, sfunc_addr_group },
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem { "INBOUND", 12, sfunc_addr_inbound },
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem { "OUTBOUND", 23, sfunc_addr_outbound },
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem { NULL, 0, NULL }
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem};
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic ipmpstat_field_t group_fields[] = {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem { "GROUP", 12, sfunc_group_ifname },
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem { "GROUPNAME", 12, sfunc_group_name },
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem { "STATE", 10, sfunc_group_state },
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem { "FDT", 10, sfunc_group_fdt },
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem { "INTERFACES", 30, sfunc_group_interfaces },
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem { NULL, 0, NULL }
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem};
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic ipmpstat_field_t if_fields[] = {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem { "INTERFACE", 12, sfunc_if_name },
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem { "ACTIVE", 8, sfunc_if_active },
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem { "GROUP", 12, sfunc_if_group },
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem { "FLAGS", 10, sfunc_if_flags },
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem { "LINK", 10, sfunc_if_link },
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem { "PROBE", 10, sfunc_if_probe },
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem { "STATE", 10, sfunc_if_state },
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem { NULL, 0, NULL }
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem};
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic ipmpstat_field_t probe_fields[] = {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem { "TIME", 10, sfunc_probe_time },
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem { "INTERFACE", 12, sfunc_probe_ifname },
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem { "PROBE", 7, sfunc_probe_id },
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem { "NETRTT", 10, sfunc_probe_netrtt },
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem { "RTT", 10, sfunc_probe_rtt },
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem { "RTTAVG", 10, sfunc_probe_rttavg },
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem { "TARGET", 20, sfunc_probe_target },
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem { "RTTDEV", 10, sfunc_probe_rttdev },
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem { NULL, 0, NULL }
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem};
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic ipmpstat_field_t targ_fields[] = {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem { "INTERFACE", 12, sfunc_targ_ifname },
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem { "MODE", 10, sfunc_targ_mode },
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem { "TESTADDR", 20, sfunc_targ_testaddr },
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem { "TARGETS", 38, sfunc_targ_targets },
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem { NULL, 0, NULL }
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem};
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic ipmpstat_enum_t addr_state[] = {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem { "up", IPMP_ADDR_UP },
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem { "down", IPMP_ADDR_DOWN },
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem { NULL, 0 }
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem};
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic ipmpstat_enum_t group_state[] = {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem { "ok", IPMP_GROUP_OK },
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem { "failed", IPMP_GROUP_FAILED },
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem { "degraded", IPMP_GROUP_DEGRADED },
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem { NULL, 0 }
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem};
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic ipmpstat_enum_t if_link[] = {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem { "up", IPMP_LINK_UP },
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem { "down", IPMP_LINK_DOWN },
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem { "unknown", IPMP_LINK_UNKNOWN },
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem { NULL, 0 }
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem};
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic ipmpstat_enum_t if_probe[] = {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem { "ok", IPMP_PROBE_OK },
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem { "failed", IPMP_PROBE_FAILED },
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem { "unknown", IPMP_PROBE_UNKNOWN },
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem { "disabled", IPMP_PROBE_DISABLED },
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem { NULL, 0 }
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem};
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic ipmpstat_enum_t if_state[] = {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem { "ok", IPMP_IF_OK },
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem { "failed", IPMP_IF_FAILED },
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem { "unknown", IPMP_IF_UNKNOWN },
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem { "offline", IPMP_IF_OFFLINE },
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem { NULL, 0 }
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem};
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic ipmpstat_enum_t targ_mode[] = {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem { "disabled", IPMP_TARG_DISABLED },
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem { "routes", IPMP_TARG_ROUTES },
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem { "multicast", IPMP_TARG_MULTICAST },
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem { NULL, 0 }
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem};