ipmpstat.c revision 19449258028e6813f0b7a606b554b2fa37a390ec
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * CDDL HEADER START
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 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * See the License for the specific language governing permissions
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * and limitations under the License.
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 * CDDL HEADER END
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * Use is subject to license terms.
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * ipmpstat -- display IPMP subsystem status.
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 * * 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()).
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhan * * The ofmt_sfunc_t function pointers (sfunc_*) obtain a given value
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhan * for a given IPMP object. Each ofmt_sfunc_t is passed a buffer to
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhan * write its result into, the buffer's size, and an ipmpstat_sfunc_arg_t
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhan * state structure. The state structure consists of a pointer to the
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhan * IPMP object to obtain information from (sa_data), and an open libipmp
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhan * handle (sa_ih) which can be used to do additional libipmp queries, if
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhan * necessary (e.g., because the object does not have all of the needed
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhan * information).
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhan * * The ofmt_field_t arrays (*_fields[]) provide the supported fields for
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhan * a given output format, along with output formatting information
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhan * (e.g., field width) and a pointer to an ofmt_sfunc_t function that
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhan * can obtain the value for a given IPMP object. One ofmt_field_t array
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhan * is used per ipmpstat invocation, and is passed to ofmt_open() (along
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhan * with the output fields and modes requested by the user) to create an
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhan * * The ofmt_t structure is a handle that tracks all information
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhan * related to output formatting and is used by libinetutil`ofmt_print()
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhan * (indirectly through our local ofmt_output() utility routine) to
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhan * output a single line of information about the provided IPMP object.
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 * Data type used by the sfunc callbacks to obtain the requested information
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * from the agreed-upon object.
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemtypedef struct ipmpstat_sfunc_arg {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * Function pointers used to iterate through IPMP objects.
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemtypedef void ipmpstat_cbfunc_t(ipmp_handle_t, void *, void *);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemtypedef void ipmpstat_walker_t(ipmp_handle_t, ipmpstat_cbfunc_t *, void *);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * Data type used to implement nested walks.
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemtypedef struct ipmpstat_walkdata {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ipmpstat_cbfunc_t *iw_func; /* caller-specified callback */
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * Data type used by enum2str() to map an enumerated value to a string.
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemtypedef struct ipmpstat_enum {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * Data type used to pass state between probe_output() and probe_event().
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemtypedef struct ipmpstat_probe_state {
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhan ipmp_handle_t ps_ih; /* open IPMP handle */
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhan ofmt_handle_t ps_ofmt; /* open formatted-output handle */
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * Options that modify the output mode; more than one may be lit.
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemtypedef enum {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * Indices for the FLAGS field of the `-i' output format.
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem IPMPSTAT_IFLAG_INDEX, IPMPSTAT_SFLAG_INDEX, IPMPSTAT_M4FLAG_INDEX,
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem IPMPSTAT_BFLAG_INDEX, IPMPSTAT_M6FLAG_INDEX, IPMPSTAT_DFLAG_INDEX,
19449258028e6813f0b7a606b554b2fa37a390ecJosef 'Jeff' Sipek#define NS2FLOATMS(ns) (NSEC2MSEC((float)(ns)))
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic const char *progname;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic ipmpstat_enum_t addr_state[], group_state[], if_state[], if_link[];
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhanstatic ofmt_field_t addr_fields[], group_fields[], if_fields[];
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhanstatic ofmt_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;
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhanstatic void probe_output(ipmp_handle_t, ofmt_handle_t);
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhanstatic void ofmt_output(ofmt_handle_t, ipmp_handle_t, void *);
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 while ((c = getopt(argc, argv, "nLPo:agipt")) != EOF) {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem switch (c) {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem /* Undocumented option: for testing use ONLY */
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhan * Open a handle to the formatted output engine.
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhan ofmterr = ofmt_open(ofields, fields, ofmtflags, IPMPSTAT_NCOL, &ofmt);
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhan * If some fields were badly formed in human-friendly mode, we
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhan * emit a warning and continue. Otherwise exit immediately.
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhan (void) ofmt_strerror(ofmt, ofmterr, errbuf, sizeof (errbuf));
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhan if (ofmterr != OFMT_EBADFIELDS || (opt & IPMPSTAT_OPT_PARSABLE))
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * Obtain the window size and monitor changes to the size. This data
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * is used to redisplay the output headers when necessary.
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem die("cannot contact in.mpathd(1M) -- is IPMP in use?\n");
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 if ((err = ipmp_setqcontext(ih, qcontext)) != IPMP_SUCCESS) {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * Walks all IPMP groups on the system and invokes `cbfunc' on each, passing
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * it `ih', the ipmp_groupinfo_t pointer, and `arg'.
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic void
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemwalk_group(ipmp_handle_t ih, ipmpstat_cbfunc_t *cbfunc, void *arg)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if ((err = ipmp_getgrouplist(ih, &grlistp)) != IPMP_SUCCESS)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem err = ipmp_getgroupinfo(ih, grlistp->gl_groups[i], &grinfop);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * Walks all IPMP interfaces on the system and invokes `cbfunc' on each,
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * passing it `ih', the ipmp_ifinfo_t pointer, and `arg'.
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic void
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemwalk_if(ipmp_handle_t ih, ipmpstat_cbfunc_t *cbfunc, void *arg)
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'.
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic void
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemwalk_addr(ipmp_handle_t ih, ipmpstat_cbfunc_t *cbfunc, void *arg)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * Nested walker callback function for walk_if().
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic void
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemwalk_if_cbfunc(ipmp_handle_t ih, void *infop, void *arg)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem err = ipmp_getifinfo(ih, iflistp->il_ifs[i], &ifinfop);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem warn_ipmperr(err, "cannot get info for interface `%s'",
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * Nested walker callback function for walk_addr().
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic void
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemwalk_addr_cbfunc(ipmp_handle_t ih, void *infop, void *arg)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem err = ipmp_getaddrinfo(ih, grinfop->gr_name, addrp, &adinfop);
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhansfunc_addr_address(ofmt_arg_t *ofmtarg, char *buf, uint_t bufsize)
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhan ipmpstat_sfunc_arg_t *arg = ofmtarg->ofmt_cbarg;
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhansfunc_addr_group(ofmt_arg_t *ofmtarg, char *buf, uint_t bufsize)
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhan ipmpstat_sfunc_arg_t *arg = ofmtarg->ofmt_cbarg;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem err = ipmp_getgroupinfo(arg->sa_ih, adinfop->ad_group, &grinfop);
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhansfunc_addr_state(ofmt_arg_t *ofmtarg, char *buf, uint_t bufsize)
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhan ipmpstat_sfunc_arg_t *arg = ofmtarg->ofmt_cbarg;
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhansfunc_addr_inbound(ofmt_arg_t *ofmtarg, char *buf, uint_t bufsize)
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhan ipmpstat_sfunc_arg_t *arg = ofmtarg->ofmt_cbarg;
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhansfunc_addr_outbound(ofmt_arg_t *ofmtarg, char *buf, uint_t bufsize)
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhan ipmpstat_sfunc_arg_t *arg = ofmtarg->ofmt_cbarg;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * If there's no inbound interface for this address, there can't
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * be any outbound traffic.
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * The address can use any active interface in the group, so
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * obtain all of those.
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem err = ipmp_getgroupinfo(arg->sa_ih, adinfop->ad_group, &grinfop);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem err = ipmp_getifinfo(arg->sa_ih, iflistp->il_ifs[i], &ifinfop);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem warn_ipmperr(err, "cannot get info for interface `%s'",
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (nactive++ != 0)
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhansfunc_group_name(ofmt_arg_t *ofmtarg, char *buf, uint_t bufsize)
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhan ipmpstat_sfunc_arg_t *arg = ofmtarg->ofmt_cbarg;
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhansfunc_group_ifname(ofmt_arg_t *ofmtarg, char *buf, uint_t bufsize)
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhan ipmpstat_sfunc_arg_t *arg = ofmtarg->ofmt_cbarg;
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhansfunc_group_state(ofmt_arg_t *ofmtarg, char *buf, uint_t bufsize)
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhan ipmpstat_sfunc_arg_t *arg = ofmtarg->ofmt_cbarg;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem enum2str(group_state, grinfop->gr_state, buf, bufsize);
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhansfunc_group_fdt(ofmt_arg_t *ofmtarg, char *buf, uint_t bufsize)
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhan ipmpstat_sfunc_arg_t *arg = ofmtarg->ofmt_cbarg;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem (void) snprintf(buf, bufsize, "%.2fs", MS2FLOATSEC(grinfop->gr_fdt));
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhansfunc_group_interfaces(ofmt_arg_t *ofmtarg, char *buf, uint_t bufsize)
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhan ipmpstat_sfunc_arg_t *arg = ofmtarg->ofmt_cbarg;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem err = ipmp_getifinfo(arg->sa_ih, iflistp->il_ifs[i], &ifinfop);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem warn_ipmperr(err, "cannot get info for interface `%s'",
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (nactive++ != 0)
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhansfunc_if_name(ofmt_arg_t *ofmtarg, char *buf, uint_t bufsize)
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhan ipmpstat_sfunc_arg_t *arg = ofmtarg->ofmt_cbarg;
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhansfunc_if_active(ofmt_arg_t *ofmtarg, char *buf, uint_t bufsize)
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhan ipmpstat_sfunc_arg_t *arg = ofmtarg->ofmt_cbarg;
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhansfunc_if_group(ofmt_arg_t *ofmtarg, char *buf, uint_t bufsize)
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhan ipmpstat_sfunc_arg_t *arg = ofmtarg->ofmt_cbarg;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem err = ipmp_getgroupinfo(arg->sa_ih, ifinfop->if_group, &grinfop);
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhansfunc_if_flags(ofmt_arg_t *ofmtarg, char *buf, uint_t bufsize)
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhan ipmpstat_sfunc_arg_t *arg = ofmtarg->ofmt_cbarg;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem err = ipmp_getgroupinfo(arg->sa_ih, ifinfop->if_group, &grinfop);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem warn_ipmperr(err, "cannot get broadcast/multicast info for "
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (strcmp(grinfop->gr_m4ifname, ifinfop->if_name) == 0)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (strcmp(grinfop->gr_m6ifname, ifinfop->if_name) == 0)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (strcmp(grinfop->gr_bcifname, ifinfop->if_name) == 0)
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhansfunc_if_link(ofmt_arg_t *ofmtarg, char *buf, uint_t bufsize)
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhan ipmpstat_sfunc_arg_t *arg = ofmtarg->ofmt_cbarg;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem enum2str(if_link, ifinfop->if_linkstate, buf, bufsize);
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhansfunc_if_probe(ofmt_arg_t *ofmtarg, char *buf, uint_t bufsize)
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhan ipmpstat_sfunc_arg_t *arg = ofmtarg->ofmt_cbarg;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem enum2str(if_probe, ifinfop->if_probestate, buf, bufsize);
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhansfunc_if_state(ofmt_arg_t *ofmtarg, char *buf, uint_t bufsize)
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhan ipmpstat_sfunc_arg_t *arg = ofmtarg->ofmt_cbarg;
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhansfunc_probe_id(ofmt_arg_t *ofmtarg, char *buf, uint_t bufsize)
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhan ipmpstat_sfunc_arg_t *arg = ofmtarg->ofmt_cbarg;
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhan if (nvlist_lookup_uint32(nvl, IPMP_PROBE_ID, &probe_id) != 0)
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhansfunc_probe_ifname(ofmt_arg_t *ofmtarg, char *buf, uint_t bufsize)
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhan ipmpstat_sfunc_arg_t *arg = ofmtarg->ofmt_cbarg;
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhan if (nvlist_lookup_string(nvl, IPMP_IF_NAME, &ifname) != 0)
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhansfunc_probe_time(ofmt_arg_t *ofmtarg, char *buf, uint_t bufsize)
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhan ipmpstat_sfunc_arg_t *arg = ofmtarg->ofmt_cbarg;
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhan if (nvlist_lookup_hrtime(nvl, IPMP_PROBE_START_TIME, &start) != 0)
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhan return (sfunc_nvwarn("IPMP_PROBE_START_TIME"));
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhansfunc_probe_target(ofmt_arg_t *ofmtarg, char *buf, uint_t bufsize)
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhan ipmpstat_sfunc_arg_t *arg = ofmtarg->ofmt_cbarg;
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhan return (sfunc_nvwarn("IPMP_PROBE_TARGET"));
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhansfunc_probe_rtt(ofmt_arg_t *ofmtarg, char *buf, uint_t bufsize)
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhan ipmpstat_sfunc_arg_t *arg = ofmtarg->ofmt_cbarg;
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhan if (nvlist_lookup_uint32(nvl, IPMP_PROBE_STATE, &state) != 0)
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhan if (nvlist_lookup_hrtime(nvl, IPMP_PROBE_START_TIME, &start) != 0)
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhan return (sfunc_nvwarn("IPMP_PROBE_START_TIME"));
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhan if (nvlist_lookup_hrtime(nvl, IPMP_PROBE_ACKPROC_TIME, &ackproc) != 0)
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhan return (sfunc_nvwarn("IPMP_PROBE_ACKPROC_TIME"));
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem (void) snprintf(buf, bufsize, "%.2fms", NS2FLOATMS(ackproc - start));
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhansfunc_probe_netrtt(ofmt_arg_t *ofmtarg, char *buf, uint_t bufsize)
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhan ipmpstat_sfunc_arg_t *arg = ofmtarg->ofmt_cbarg;
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhan if (nvlist_lookup_uint32(nvl, IPMP_PROBE_STATE, &state) != 0)
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhan if (nvlist_lookup_hrtime(nvl, IPMP_PROBE_SENT_TIME, &sent) != 0)
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhan return (sfunc_nvwarn("IPMP_PROBE_SENT_TIME"));
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhan if (nvlist_lookup_hrtime(nvl, IPMP_PROBE_ACKRECV_TIME, &ackrecv) != 0)
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhan return (sfunc_nvwarn("IPMP_PROBE_ACKRECV_TIME"));
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem (void) snprintf(buf, bufsize, "%.2fms", NS2FLOATMS(ackrecv - sent));
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhansfunc_probe_rttavg(ofmt_arg_t *ofmtarg, char *buf, uint_t bufsize)
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhan ipmpstat_sfunc_arg_t *arg = ofmtarg->ofmt_cbarg;
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhan if (nvlist_lookup_int64(nvl, IPMP_PROBE_TARGET_RTTAVG, &rttavg) != 0)
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhan return (sfunc_nvwarn("IPMP_PROBE_TARGET_RTTAVG"));
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem (void) snprintf(buf, bufsize, "%.2fms", NS2FLOATMS(rttavg));
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhansfunc_probe_rttdev(ofmt_arg_t *ofmtarg, char *buf, uint_t bufsize)
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhan ipmpstat_sfunc_arg_t *arg = ofmtarg->ofmt_cbarg;
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhan if (nvlist_lookup_int64(nvl, IPMP_PROBE_TARGET_RTTDEV, &rttdev) != 0)
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhan return (sfunc_nvwarn("IPMP_PROBE_TARGET_RTTDEV"));
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem (void) snprintf(buf, bufsize, "%.2fms", NS2FLOATMS(rttdev));
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem/* ARGSUSED */
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic void
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemprobe_enabled_cbfunc(ipmp_handle_t ih, void *infop, void *arg)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic void
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhanprobe_output(ipmp_handle_t ih, ofmt_handle_t ofmt)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * Check if any interfaces are enabled for probe-based failure
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * detection. If not, immediately fail.
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * Unfortunately, until 4791900 is fixed, only privileged processes
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * can bind and thus receive sysevents.
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem errno = sysevent_evc_bind(IPMP_EVENT_CHAN, &evch, EVCH_CREAT);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (errno != 0) {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem die("sysevent_evc_bind to channel %s failed", IPMP_EVENT_CHAN);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * The subscriber must be unique in order for sysevent_evc_subscribe()
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * to succeed, so combine our name and pid.
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem (void) snprintf(sub, sizeof (sub), "%d-%s", getpid(), progname);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem errno = sysevent_evc_subscribe(evch, sub, EC_IPMP, probe_event, &ps, 0);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem die("sysevent_evc_subscribe for class %s failed", EC_IPMP);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (strcmp(sysevent_get_subclass_name(ev), ESC_IPMP_PROBE_STATE) != 0)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem return (0);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem return (0);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (nvlist_lookup_uint32(nvl, IPMP_EVENT_VERSION, &version) != 0) {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem warn("dropped event with unsupported IPMP_EVENT_VERSION %d\n",
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (nvlist_lookup_uint32(nvl, IPMP_PROBE_STATE, &state) != 0) {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (state == IPMP_PROBE_ACKED || state == IPMP_PROBE_LOST)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem return (0);
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhansfunc_targ_ifname(ofmt_arg_t *ofmtarg, char *buf, uint_t bufsize)
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhan ipmpstat_sfunc_arg_t *arg = ofmtarg->ofmt_cbarg;
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhansfunc_targ_mode(ofmt_arg_t *ofmtarg, char *buf, uint_t bufsize)
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhan ipmpstat_sfunc_arg_t *arg = ofmtarg->ofmt_cbarg;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem enum2str(targ_mode, targinfop->it_targmode, buf, bufsize);
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhansfunc_targ_testaddr(ofmt_arg_t *ofmtarg, char *buf, uint_t bufsize)
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhan ipmpstat_sfunc_arg_t *arg = ofmtarg->ofmt_cbarg;
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhansfunc_targ_targets(ofmt_arg_t *ofmtarg, char *buf, uint_t bufsize)
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhan ipmpstat_sfunc_arg_t *arg = ofmtarg->ofmt_cbarg;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem sockaddr2str(&targlistp->al_addrs[i], targname, bufsize);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic void
e11c3f44f531fdff80941ce57c065d2ae861cefcmeeminfo_output_cbfunc(ipmp_handle_t ih, void *infop, void *arg)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic void
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemtarginfo_output_cbfunc(ipmp_handle_t ih, void *infop, void *arg)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ipmp_if_targmode_t targmode4 = ifinfop->if_targinfo4.it_targmode;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ipmp_if_targmode_t targmode6 = ifinfop->if_targinfo6.it_targmode;
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 if (targmode4 != IPMP_TARG_DISABLED || targmode6 == IPMP_TARG_DISABLED)
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhan * Outputs one row of values. The values to output are obtained through the
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhan * callback function pointers. The actual values are computed from the `ih'
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhan * and `arg' structures passed to the callback function.
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic void
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhanofmt_output(const ofmt_handle_t ofmt, ipmp_handle_t ih, void *arg)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * Uses `enums' to map `enumval' to a string, and stores at most `bufsize'
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * bytes of that string into `buf'.
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic void
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemenum2str(const ipmpstat_enum_t *enums, int enumval, char *buf, uint_t bufsize)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * Stores the stringified value of the sockaddr_storage pointed to by `ssp'
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * into at most `bufsize' bytes of `buf'.
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic void
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemsockaddr2str(const struct sockaddr_storage *ssp, char *buf, uint_t bufsize)
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 (void) getnameinfo(sp, socklen, buf, bufsize, NULL, 0, flags);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic void
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic void
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem const char *argstr = gettext("[-n] [-o <field> [-P]] -a|-g|-i|-p|-t");
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem (void) fprintf(stderr, gettext("usage: %s %s\n"), progname, argstr);
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"));
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem/* PRINTFLIKE1 */
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic void
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem (void) fprintf(stderr, gettext("%s: warning: "), progname);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem/* PRINTFLIKE2 */
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic void
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem (void) fprintf(stderr, gettext("%s: warning: "), progname);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem (void) fprintf(stderr, ": %s\n", ipmp_errmsg(ipmperr));
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem/* PRINTFLIKE1 */
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic void
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem/* PRINTFLIKE2 */
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic void
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem (void) fprintf(stderr, ": %s\n", ipmp_errmsg(ipmperr));
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhan { "OUTBOUND", 23, 0, sfunc_addr_outbound },
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhan { "INTERFACES", 30, 0, sfunc_group_interfaces },
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhan { "INTERFACE", 12, 0, sfunc_probe_ifname },
8002d4117c1ea26aff1f16f584ae97bdbd5b21d5Sowmini Varadhan { "TESTADDR", 20, 0, sfunc_targ_testaddr },