18485SPeter.Memishian@Sun.COM /*
28485SPeter.Memishian@Sun.COM * CDDL HEADER START
38485SPeter.Memishian@Sun.COM *
48485SPeter.Memishian@Sun.COM * The contents of this file are subject to the terms of the
58485SPeter.Memishian@Sun.COM * Common Development and Distribution License (the "License").
68485SPeter.Memishian@Sun.COM * You may not use this file except in compliance with the License.
78485SPeter.Memishian@Sun.COM *
88485SPeter.Memishian@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
98485SPeter.Memishian@Sun.COM * or http://www.opensolaris.org/os/licensing.
108485SPeter.Memishian@Sun.COM * See the License for the specific language governing permissions
118485SPeter.Memishian@Sun.COM * and limitations under the License.
128485SPeter.Memishian@Sun.COM *
138485SPeter.Memishian@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each
148485SPeter.Memishian@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
158485SPeter.Memishian@Sun.COM * If applicable, add the following below this CDDL HEADER, with the
168485SPeter.Memishian@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying
178485SPeter.Memishian@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner]
188485SPeter.Memishian@Sun.COM *
198485SPeter.Memishian@Sun.COM * CDDL HEADER END
208485SPeter.Memishian@Sun.COM *
218485SPeter.Memishian@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
228485SPeter.Memishian@Sun.COM * Use is subject to license terms.
238485SPeter.Memishian@Sun.COM */
248485SPeter.Memishian@Sun.COM
258485SPeter.Memishian@Sun.COM #include <alloca.h>
268485SPeter.Memishian@Sun.COM #include <arpa/inet.h>
278485SPeter.Memishian@Sun.COM #include <assert.h>
288485SPeter.Memishian@Sun.COM #include <errno.h>
298485SPeter.Memishian@Sun.COM #include <ipmp_admin.h>
308485SPeter.Memishian@Sun.COM #include <ipmp_query.h>
318485SPeter.Memishian@Sun.COM #include <libintl.h>
328485SPeter.Memishian@Sun.COM #include <libnvpair.h>
338485SPeter.Memishian@Sun.COM #include <libsysevent.h>
348485SPeter.Memishian@Sun.COM #include <locale.h>
358485SPeter.Memishian@Sun.COM #include <netdb.h>
36*9071SSowmini.Varadhan@Sun.COM #include <ofmt.h>
378485SPeter.Memishian@Sun.COM #include <signal.h>
388485SPeter.Memishian@Sun.COM #include <stdarg.h>
398485SPeter.Memishian@Sun.COM #include <stdio.h>
408485SPeter.Memishian@Sun.COM #include <stdlib.h>
418485SPeter.Memishian@Sun.COM #include <string.h>
428485SPeter.Memishian@Sun.COM #include <unistd.h>
438485SPeter.Memishian@Sun.COM #include <sys/sysevent/eventdefs.h>
448485SPeter.Memishian@Sun.COM #include <sys/sysevent/ipmp.h>
458485SPeter.Memishian@Sun.COM #include <sys/sysmacros.h>
468485SPeter.Memishian@Sun.COM #include <sys/termios.h>
478485SPeter.Memishian@Sun.COM #include <sys/types.h>
488485SPeter.Memishian@Sun.COM
498485SPeter.Memishian@Sun.COM /*
508485SPeter.Memishian@Sun.COM * ipmpstat -- display IPMP subsystem status.
518485SPeter.Memishian@Sun.COM *
528485SPeter.Memishian@Sun.COM * This utility makes extensive use of libipmp and IPMP sysevents to gather
538485SPeter.Memishian@Sun.COM * and pretty-print the status of the IPMP subsystem. All output formats
548485SPeter.Memishian@Sun.COM * except for -p (probe) use libipmp to create a point-in-time snapshot of the
558485SPeter.Memishian@Sun.COM * IPMP subsystem (unless the test-special -L flag is used), and then output
568485SPeter.Memishian@Sun.COM * the contents of that snapshot in a user-specified manner. Because the
578485SPeter.Memishian@Sun.COM * output format and requested fields aren't known until run-time, three sets
588485SPeter.Memishian@Sun.COM * of function pointers and two core data structures are used. Specifically:
598485SPeter.Memishian@Sun.COM *
608485SPeter.Memishian@Sun.COM * * The ipmpstat_walker_t function pointers (walk_*) iterate through
618485SPeter.Memishian@Sun.COM * all instances of a given IPMP object (group, interface, or address).
628485SPeter.Memishian@Sun.COM * At most one ipmpstat_walker_t is used per ipmpstat invocation.
638485SPeter.Memishian@Sun.COM * Since target information is included with the interface information,
648485SPeter.Memishian@Sun.COM * both -i and -t use the interface walker (walk_if()).
658485SPeter.Memishian@Sun.COM *
66*9071SSowmini.Varadhan@Sun.COM * * The ofmt_sfunc_t function pointers (sfunc_*) obtain a given value
67*9071SSowmini.Varadhan@Sun.COM * for a given IPMP object. Each ofmt_sfunc_t is passed a buffer to
68*9071SSowmini.Varadhan@Sun.COM * write its result into, the buffer's size, and an ipmpstat_sfunc_arg_t
69*9071SSowmini.Varadhan@Sun.COM * state structure. The state structure consists of a pointer to the
70*9071SSowmini.Varadhan@Sun.COM * IPMP object to obtain information from (sa_data), and an open libipmp
71*9071SSowmini.Varadhan@Sun.COM * handle (sa_ih) which can be used to do additional libipmp queries, if
72*9071SSowmini.Varadhan@Sun.COM * necessary (e.g., because the object does not have all of the needed
73*9071SSowmini.Varadhan@Sun.COM * information).
748485SPeter.Memishian@Sun.COM *
75*9071SSowmini.Varadhan@Sun.COM * * The ofmt_field_t arrays (*_fields[]) provide the supported fields for
76*9071SSowmini.Varadhan@Sun.COM * a given output format, along with output formatting information
77*9071SSowmini.Varadhan@Sun.COM * (e.g., field width) and a pointer to an ofmt_sfunc_t function that
78*9071SSowmini.Varadhan@Sun.COM * can obtain the value for a given IPMP object. One ofmt_field_t array
79*9071SSowmini.Varadhan@Sun.COM * is used per ipmpstat invocation, and is passed to ofmt_open() (along
80*9071SSowmini.Varadhan@Sun.COM * with the output fields and modes requested by the user) to create an
81*9071SSowmini.Varadhan@Sun.COM * ofmt_t.
828485SPeter.Memishian@Sun.COM *
83*9071SSowmini.Varadhan@Sun.COM * * The ofmt_t structure is a handle that tracks all information
84*9071SSowmini.Varadhan@Sun.COM * related to output formatting and is used by libinetutil`ofmt_print()
85*9071SSowmini.Varadhan@Sun.COM * (indirectly through our local ofmt_output() utility routine) to
86*9071SSowmini.Varadhan@Sun.COM * output a single line of information about the provided IPMP object.
878485SPeter.Memishian@Sun.COM *
888485SPeter.Memishian@Sun.COM * * The ipmpstat_cbfunc_t function pointers (*_cbfunc) are called back
898485SPeter.Memishian@Sun.COM * by the walkers. They are used both internally to implement nested
908485SPeter.Memishian@Sun.COM * walks, and by the ipmpstat output logic to provide the glue between
918485SPeter.Memishian@Sun.COM * the IPMP object walkers and the ofmt_output() logic. Usually, a
928485SPeter.Memishian@Sun.COM * single line is output for each IPMP object, and thus ofmt_output()
938485SPeter.Memishian@Sun.COM * can be directly invoked (see info_output_cbfunc()). However, if
948485SPeter.Memishian@Sun.COM * multiple lines need to be output, then a more complex cbfunc is
958485SPeter.Memishian@Sun.COM * needed (see targinfo_output_cbfunc()). At most one cbfunc is used
968485SPeter.Memishian@Sun.COM * per ipmpstat invocation.
978485SPeter.Memishian@Sun.COM */
988485SPeter.Memishian@Sun.COM
998485SPeter.Memishian@Sun.COM /*
1008485SPeter.Memishian@Sun.COM * Data type used by the sfunc callbacks to obtain the requested information
1018485SPeter.Memishian@Sun.COM * from the agreed-upon object.
1028485SPeter.Memishian@Sun.COM */
1038485SPeter.Memishian@Sun.COM typedef struct ipmpstat_sfunc_arg {
1048485SPeter.Memishian@Sun.COM ipmp_handle_t sa_ih;
1058485SPeter.Memishian@Sun.COM void *sa_data;
1068485SPeter.Memishian@Sun.COM } ipmpstat_sfunc_arg_t;
1078485SPeter.Memishian@Sun.COM
1088485SPeter.Memishian@Sun.COM /*
1098485SPeter.Memishian@Sun.COM * Function pointers used to iterate through IPMP objects.
1108485SPeter.Memishian@Sun.COM */
1118485SPeter.Memishian@Sun.COM typedef void ipmpstat_cbfunc_t(ipmp_handle_t, void *, void *);
1128485SPeter.Memishian@Sun.COM typedef void ipmpstat_walker_t(ipmp_handle_t, ipmpstat_cbfunc_t *, void *);
1138485SPeter.Memishian@Sun.COM
1148485SPeter.Memishian@Sun.COM /*
1158485SPeter.Memishian@Sun.COM * Data type used to implement nested walks.
1168485SPeter.Memishian@Sun.COM */
1178485SPeter.Memishian@Sun.COM typedef struct ipmpstat_walkdata {
1188485SPeter.Memishian@Sun.COM ipmpstat_cbfunc_t *iw_func; /* caller-specified callback */
1198485SPeter.Memishian@Sun.COM void *iw_funcarg; /* caller-specified arg */
1208485SPeter.Memishian@Sun.COM } ipmpstat_walkdata_t;
1218485SPeter.Memishian@Sun.COM
1228485SPeter.Memishian@Sun.COM /*
1238485SPeter.Memishian@Sun.COM * Data type used by enum2str() to map an enumerated value to a string.
1248485SPeter.Memishian@Sun.COM */
1258485SPeter.Memishian@Sun.COM typedef struct ipmpstat_enum {
1268485SPeter.Memishian@Sun.COM const char *e_name; /* string */
1278485SPeter.Memishian@Sun.COM int e_val; /* value */
1288485SPeter.Memishian@Sun.COM } ipmpstat_enum_t;
1298485SPeter.Memishian@Sun.COM
1308485SPeter.Memishian@Sun.COM /*
1318485SPeter.Memishian@Sun.COM * Data type used to pass state between probe_output() and probe_event().
1328485SPeter.Memishian@Sun.COM */
1338485SPeter.Memishian@Sun.COM typedef struct ipmpstat_probe_state {
134*9071SSowmini.Varadhan@Sun.COM ipmp_handle_t ps_ih; /* open IPMP handle */
135*9071SSowmini.Varadhan@Sun.COM ofmt_handle_t ps_ofmt; /* open formatted-output handle */
1368485SPeter.Memishian@Sun.COM } ipmpstat_probe_state_t;
1378485SPeter.Memishian@Sun.COM
1388485SPeter.Memishian@Sun.COM /*
1398485SPeter.Memishian@Sun.COM * Options that modify the output mode; more than one may be lit.
1408485SPeter.Memishian@Sun.COM */
1418485SPeter.Memishian@Sun.COM typedef enum {
1428485SPeter.Memishian@Sun.COM IPMPSTAT_OPT_NUMERIC = 0x1,
1438485SPeter.Memishian@Sun.COM IPMPSTAT_OPT_PARSABLE = 0x2
1448485SPeter.Memishian@Sun.COM } ipmpstat_opt_t;
1458485SPeter.Memishian@Sun.COM
1468485SPeter.Memishian@Sun.COM /*
1478485SPeter.Memishian@Sun.COM * Indices for the FLAGS field of the `-i' output format.
1488485SPeter.Memishian@Sun.COM */
1498485SPeter.Memishian@Sun.COM enum {
1508485SPeter.Memishian@Sun.COM IPMPSTAT_IFLAG_INDEX, IPMPSTAT_SFLAG_INDEX, IPMPSTAT_M4FLAG_INDEX,
1518485SPeter.Memishian@Sun.COM IPMPSTAT_BFLAG_INDEX, IPMPSTAT_M6FLAG_INDEX, IPMPSTAT_DFLAG_INDEX,
1528485SPeter.Memishian@Sun.COM IPMPSTAT_HFLAG_INDEX, IPMPSTAT_NUM_FLAGS
1538485SPeter.Memishian@Sun.COM };
1548485SPeter.Memishian@Sun.COM
1558485SPeter.Memishian@Sun.COM #define IPMPSTAT_NCOL 80
1568485SPeter.Memishian@Sun.COM #define NS2FLOATMS(ns) ((float)(ns) / (NANOSEC / MILLISEC))
1578485SPeter.Memishian@Sun.COM #define MS2FLOATSEC(ms) ((float)(ms) / 1000)
1588485SPeter.Memishian@Sun.COM
1598485SPeter.Memishian@Sun.COM static const char *progname;
1608485SPeter.Memishian@Sun.COM static hrtime_t probe_output_start;
1618485SPeter.Memishian@Sun.COM static ipmpstat_opt_t opt;
162*9071SSowmini.Varadhan@Sun.COM static ofmt_handle_t ofmt;
1638485SPeter.Memishian@Sun.COM static ipmpstat_enum_t addr_state[], group_state[], if_state[], if_link[];
1648485SPeter.Memishian@Sun.COM static ipmpstat_enum_t if_probe[], targ_mode[];
165*9071SSowmini.Varadhan@Sun.COM static ofmt_field_t addr_fields[], group_fields[], if_fields[];
166*9071SSowmini.Varadhan@Sun.COM static ofmt_field_t probe_fields[], targ_fields[];
1678485SPeter.Memishian@Sun.COM static ipmpstat_cbfunc_t walk_addr_cbfunc, walk_if_cbfunc;
1688485SPeter.Memishian@Sun.COM static ipmpstat_cbfunc_t info_output_cbfunc, targinfo_output_cbfunc;
1698485SPeter.Memishian@Sun.COM static ipmpstat_walker_t walk_addr, walk_if, walk_group;
1708485SPeter.Memishian@Sun.COM
1718485SPeter.Memishian@Sun.COM static int probe_event(sysevent_t *, void *);
172*9071SSowmini.Varadhan@Sun.COM static void probe_output(ipmp_handle_t, ofmt_handle_t);
173*9071SSowmini.Varadhan@Sun.COM static void ofmt_output(ofmt_handle_t, ipmp_handle_t, void *);
1748485SPeter.Memishian@Sun.COM static void enum2str(const ipmpstat_enum_t *, int, char *, uint_t);
1758485SPeter.Memishian@Sun.COM static void sockaddr2str(const struct sockaddr_storage *, char *, uint_t);
1768485SPeter.Memishian@Sun.COM static void sighandler(int);
1778485SPeter.Memishian@Sun.COM static void usage(void);
1788485SPeter.Memishian@Sun.COM static void die(const char *, ...);
1798485SPeter.Memishian@Sun.COM static void die_ipmperr(int, const char *, ...);
1808485SPeter.Memishian@Sun.COM static void warn(const char *, ...);
1818485SPeter.Memishian@Sun.COM static void warn_ipmperr(int, const char *, ...);
1828485SPeter.Memishian@Sun.COM
1838485SPeter.Memishian@Sun.COM int
main(int argc,char ** argv)1848485SPeter.Memishian@Sun.COM main(int argc, char **argv)
1858485SPeter.Memishian@Sun.COM {
1868485SPeter.Memishian@Sun.COM int c;
1878485SPeter.Memishian@Sun.COM int err;
1888485SPeter.Memishian@Sun.COM const char *ofields = NULL;
189*9071SSowmini.Varadhan@Sun.COM ofmt_status_t ofmterr;
190*9071SSowmini.Varadhan@Sun.COM ofmt_field_t *fields = NULL;
191*9071SSowmini.Varadhan@Sun.COM uint_t ofmtflags = 0;
1928485SPeter.Memishian@Sun.COM ipmp_handle_t ih;
1938485SPeter.Memishian@Sun.COM ipmp_qcontext_t qcontext = IPMP_QCONTEXT_SNAP;
1948485SPeter.Memishian@Sun.COM ipmpstat_cbfunc_t *cbfunc;
1958485SPeter.Memishian@Sun.COM ipmpstat_walker_t *walker;
196*9071SSowmini.Varadhan@Sun.COM char errbuf[OFMT_BUFSIZE];
1978485SPeter.Memishian@Sun.COM
1988485SPeter.Memishian@Sun.COM if ((progname = strrchr(argv[0], '/')) == NULL)
1998485SPeter.Memishian@Sun.COM progname = argv[0];
2008485SPeter.Memishian@Sun.COM else
2018485SPeter.Memishian@Sun.COM progname++;
2028485SPeter.Memishian@Sun.COM
2038485SPeter.Memishian@Sun.COM (void) setlocale(LC_ALL, "");
2048485SPeter.Memishian@Sun.COM (void) textdomain(TEXT_DOMAIN);
2058485SPeter.Memishian@Sun.COM
2068485SPeter.Memishian@Sun.COM while ((c = getopt(argc, argv, "nLPo:agipt")) != EOF) {
2078485SPeter.Memishian@Sun.COM if (fields != NULL && strchr("agipt", c) != NULL)
2088485SPeter.Memishian@Sun.COM die("only one output format may be specified\n");
2098485SPeter.Memishian@Sun.COM
2108485SPeter.Memishian@Sun.COM switch (c) {
2118485SPeter.Memishian@Sun.COM case 'n':
2128485SPeter.Memishian@Sun.COM opt |= IPMPSTAT_OPT_NUMERIC;
2138485SPeter.Memishian@Sun.COM break;
2148485SPeter.Memishian@Sun.COM case 'L':
2158485SPeter.Memishian@Sun.COM /* Undocumented option: for testing use ONLY */
2168485SPeter.Memishian@Sun.COM qcontext = IPMP_QCONTEXT_LIVE;
2178485SPeter.Memishian@Sun.COM break;
2188485SPeter.Memishian@Sun.COM case 'P':
2198485SPeter.Memishian@Sun.COM opt |= IPMPSTAT_OPT_PARSABLE;
220*9071SSowmini.Varadhan@Sun.COM ofmtflags |= OFMT_PARSABLE;
2218485SPeter.Memishian@Sun.COM break;
2228485SPeter.Memishian@Sun.COM case 'o':
2238485SPeter.Memishian@Sun.COM ofields = optarg;
2248485SPeter.Memishian@Sun.COM break;
2258485SPeter.Memishian@Sun.COM case 'a':
2268485SPeter.Memishian@Sun.COM walker = walk_addr;
2278485SPeter.Memishian@Sun.COM cbfunc = info_output_cbfunc;
2288485SPeter.Memishian@Sun.COM fields = addr_fields;
2298485SPeter.Memishian@Sun.COM break;
2308485SPeter.Memishian@Sun.COM case 'g':
2318485SPeter.Memishian@Sun.COM walker = walk_group;
2328485SPeter.Memishian@Sun.COM cbfunc = info_output_cbfunc;
2338485SPeter.Memishian@Sun.COM fields = group_fields;
2348485SPeter.Memishian@Sun.COM break;
2358485SPeter.Memishian@Sun.COM case 'i':
2368485SPeter.Memishian@Sun.COM walker = walk_if;
2378485SPeter.Memishian@Sun.COM cbfunc = info_output_cbfunc;
2388485SPeter.Memishian@Sun.COM fields = if_fields;
2398485SPeter.Memishian@Sun.COM break;
2408485SPeter.Memishian@Sun.COM case 'p':
2418485SPeter.Memishian@Sun.COM fields = probe_fields;
2428485SPeter.Memishian@Sun.COM break;
2438485SPeter.Memishian@Sun.COM case 't':
2448485SPeter.Memishian@Sun.COM walker = walk_if;
2458485SPeter.Memishian@Sun.COM cbfunc = targinfo_output_cbfunc;
2468485SPeter.Memishian@Sun.COM fields = targ_fields;
2478485SPeter.Memishian@Sun.COM break;
2488485SPeter.Memishian@Sun.COM default:
2498485SPeter.Memishian@Sun.COM usage();
2508485SPeter.Memishian@Sun.COM break;
2518485SPeter.Memishian@Sun.COM }
2528485SPeter.Memishian@Sun.COM }
2538485SPeter.Memishian@Sun.COM
2548485SPeter.Memishian@Sun.COM if (argc > optind || fields == NULL)
2558485SPeter.Memishian@Sun.COM usage();
2568485SPeter.Memishian@Sun.COM
257*9071SSowmini.Varadhan@Sun.COM /*
258*9071SSowmini.Varadhan@Sun.COM * Open a handle to the formatted output engine.
259*9071SSowmini.Varadhan@Sun.COM */
260*9071SSowmini.Varadhan@Sun.COM ofmterr = ofmt_open(ofields, fields, ofmtflags, IPMPSTAT_NCOL, &ofmt);
261*9071SSowmini.Varadhan@Sun.COM if (ofmterr != OFMT_SUCCESS) {
262*9071SSowmini.Varadhan@Sun.COM /*
263*9071SSowmini.Varadhan@Sun.COM * If some fields were badly formed in human-friendly mode, we
264*9071SSowmini.Varadhan@Sun.COM * emit a warning and continue. Otherwise exit immediately.
265*9071SSowmini.Varadhan@Sun.COM */
266*9071SSowmini.Varadhan@Sun.COM (void) ofmt_strerror(ofmt, ofmterr, errbuf, sizeof (errbuf));
267*9071SSowmini.Varadhan@Sun.COM if (ofmterr != OFMT_EBADFIELDS || (opt & IPMPSTAT_OPT_PARSABLE))
268*9071SSowmini.Varadhan@Sun.COM die("%s\n", errbuf);
269*9071SSowmini.Varadhan@Sun.COM else
270*9071SSowmini.Varadhan@Sun.COM warn("%s\n", errbuf);
2718485SPeter.Memishian@Sun.COM }
2728485SPeter.Memishian@Sun.COM
2738485SPeter.Memishian@Sun.COM /*
2748485SPeter.Memishian@Sun.COM * Obtain the window size and monitor changes to the size. This data
2758485SPeter.Memishian@Sun.COM * is used to redisplay the output headers when necessary.
2768485SPeter.Memishian@Sun.COM */
2778485SPeter.Memishian@Sun.COM (void) sigset(SIGWINCH, sighandler);
2788485SPeter.Memishian@Sun.COM
2798485SPeter.Memishian@Sun.COM if ((err = ipmp_open(&ih)) != IPMP_SUCCESS)
2808485SPeter.Memishian@Sun.COM die_ipmperr(err, "cannot create IPMP handle");
2818485SPeter.Memishian@Sun.COM
2828485SPeter.Memishian@Sun.COM if (ipmp_ping_daemon(ih) != IPMP_SUCCESS)
2838485SPeter.Memishian@Sun.COM die("cannot contact in.mpathd(1M) -- is IPMP in use?\n");
2848485SPeter.Memishian@Sun.COM
2858485SPeter.Memishian@Sun.COM /*
2868485SPeter.Memishian@Sun.COM * If we've been asked to display probes, then call the probe output
2878485SPeter.Memishian@Sun.COM * function. Otherwise, snapshot IPMP state (or use live state) and
2888485SPeter.Memishian@Sun.COM * invoke the specified walker with the specified callback function.
2898485SPeter.Memishian@Sun.COM */
2908485SPeter.Memishian@Sun.COM if (fields == probe_fields) {
2918485SPeter.Memishian@Sun.COM probe_output(ih, ofmt);
2928485SPeter.Memishian@Sun.COM } else {
2938485SPeter.Memishian@Sun.COM if ((err = ipmp_setqcontext(ih, qcontext)) != IPMP_SUCCESS) {
2948485SPeter.Memishian@Sun.COM if (qcontext == IPMP_QCONTEXT_SNAP)
2958485SPeter.Memishian@Sun.COM die_ipmperr(err, "cannot snapshot IPMP state");
2968485SPeter.Memishian@Sun.COM else
2978485SPeter.Memishian@Sun.COM die_ipmperr(err, "cannot use live IPMP state");
2988485SPeter.Memishian@Sun.COM }
2998485SPeter.Memishian@Sun.COM (*walker)(ih, cbfunc, ofmt);
3008485SPeter.Memishian@Sun.COM }
3018485SPeter.Memishian@Sun.COM
302*9071SSowmini.Varadhan@Sun.COM ofmt_close(ofmt);
3038485SPeter.Memishian@Sun.COM ipmp_close(ih);
3048485SPeter.Memishian@Sun.COM
3058485SPeter.Memishian@Sun.COM return (EXIT_SUCCESS);
3068485SPeter.Memishian@Sun.COM }
3078485SPeter.Memishian@Sun.COM
3088485SPeter.Memishian@Sun.COM /*
3098485SPeter.Memishian@Sun.COM * Walks all IPMP groups on the system and invokes `cbfunc' on each, passing
3108485SPeter.Memishian@Sun.COM * it `ih', the ipmp_groupinfo_t pointer, and `arg'.
3118485SPeter.Memishian@Sun.COM */
3128485SPeter.Memishian@Sun.COM static void
walk_group(ipmp_handle_t ih,ipmpstat_cbfunc_t * cbfunc,void * arg)3138485SPeter.Memishian@Sun.COM walk_group(ipmp_handle_t ih, ipmpstat_cbfunc_t *cbfunc, void *arg)
3148485SPeter.Memishian@Sun.COM {
3158485SPeter.Memishian@Sun.COM int err;
3168485SPeter.Memishian@Sun.COM uint_t i;
3178485SPeter.Memishian@Sun.COM ipmp_groupinfo_t *grinfop;
3188485SPeter.Memishian@Sun.COM ipmp_grouplist_t *grlistp;
3198485SPeter.Memishian@Sun.COM
3208485SPeter.Memishian@Sun.COM if ((err = ipmp_getgrouplist(ih, &grlistp)) != IPMP_SUCCESS)
3218485SPeter.Memishian@Sun.COM die_ipmperr(err, "cannot get IPMP group list");
3228485SPeter.Memishian@Sun.COM
3238485SPeter.Memishian@Sun.COM for (i = 0; i < grlistp->gl_ngroup; i++) {
3248485SPeter.Memishian@Sun.COM err = ipmp_getgroupinfo(ih, grlistp->gl_groups[i], &grinfop);
3258485SPeter.Memishian@Sun.COM if (err != IPMP_SUCCESS) {
3268485SPeter.Memishian@Sun.COM warn_ipmperr(err, "cannot get info for group `%s'",
3278485SPeter.Memishian@Sun.COM grlistp->gl_groups[i]);
3288485SPeter.Memishian@Sun.COM continue;
3298485SPeter.Memishian@Sun.COM }
3308485SPeter.Memishian@Sun.COM (*cbfunc)(ih, grinfop, arg);
3318485SPeter.Memishian@Sun.COM ipmp_freegroupinfo(grinfop);
3328485SPeter.Memishian@Sun.COM }
3338485SPeter.Memishian@Sun.COM
3348485SPeter.Memishian@Sun.COM ipmp_freegrouplist(grlistp);
3358485SPeter.Memishian@Sun.COM }
3368485SPeter.Memishian@Sun.COM
3378485SPeter.Memishian@Sun.COM /*
3388485SPeter.Memishian@Sun.COM * Walks all IPMP interfaces on the system and invokes `cbfunc' on each,
3398485SPeter.Memishian@Sun.COM * passing it `ih', the ipmp_ifinfo_t pointer, and `arg'.
3408485SPeter.Memishian@Sun.COM */
3418485SPeter.Memishian@Sun.COM static void
walk_if(ipmp_handle_t ih,ipmpstat_cbfunc_t * cbfunc,void * arg)3428485SPeter.Memishian@Sun.COM walk_if(ipmp_handle_t ih, ipmpstat_cbfunc_t *cbfunc, void *arg)
3438485SPeter.Memishian@Sun.COM {
3448485SPeter.Memishian@Sun.COM ipmpstat_walkdata_t iw = { cbfunc, arg };
3458485SPeter.Memishian@Sun.COM
3468485SPeter.Memishian@Sun.COM walk_group(ih, walk_if_cbfunc, &iw);
3478485SPeter.Memishian@Sun.COM }
3488485SPeter.Memishian@Sun.COM
3498485SPeter.Memishian@Sun.COM /*
3508485SPeter.Memishian@Sun.COM * Walks all IPMP data addresses on the system and invokes `cbfunc' on each.
3518485SPeter.Memishian@Sun.COM * passing it `ih', the ipmp_addrinfo_t pointer, and `arg'.
3528485SPeter.Memishian@Sun.COM */
3538485SPeter.Memishian@Sun.COM static void
walk_addr(ipmp_handle_t ih,ipmpstat_cbfunc_t * cbfunc,void * arg)3548485SPeter.Memishian@Sun.COM walk_addr(ipmp_handle_t ih, ipmpstat_cbfunc_t *cbfunc, void *arg)
3558485SPeter.Memishian@Sun.COM {
3568485SPeter.Memishian@Sun.COM ipmpstat_walkdata_t iw = { cbfunc, arg };
3578485SPeter.Memishian@Sun.COM
3588485SPeter.Memishian@Sun.COM walk_group(ih, walk_addr_cbfunc, &iw);
3598485SPeter.Memishian@Sun.COM }
3608485SPeter.Memishian@Sun.COM
3618485SPeter.Memishian@Sun.COM /*
3628485SPeter.Memishian@Sun.COM * Nested walker callback function for walk_if().
3638485SPeter.Memishian@Sun.COM */
3648485SPeter.Memishian@Sun.COM static void
walk_if_cbfunc(ipmp_handle_t ih,void * infop,void * arg)3658485SPeter.Memishian@Sun.COM walk_if_cbfunc(ipmp_handle_t ih, void *infop, void *arg)
3668485SPeter.Memishian@Sun.COM {
3678485SPeter.Memishian@Sun.COM int err;
3688485SPeter.Memishian@Sun.COM uint_t i;
3698485SPeter.Memishian@Sun.COM ipmp_groupinfo_t *grinfop = infop;
3708485SPeter.Memishian@Sun.COM ipmp_ifinfo_t *ifinfop;
3718485SPeter.Memishian@Sun.COM ipmp_iflist_t *iflistp = grinfop->gr_iflistp;
3728485SPeter.Memishian@Sun.COM ipmpstat_walkdata_t *iwp = arg;
3738485SPeter.Memishian@Sun.COM
3748485SPeter.Memishian@Sun.COM for (i = 0; i < iflistp->il_nif; i++) {
3758485SPeter.Memishian@Sun.COM err = ipmp_getifinfo(ih, iflistp->il_ifs[i], &ifinfop);
3768485SPeter.Memishian@Sun.COM if (err != IPMP_SUCCESS) {
3778485SPeter.Memishian@Sun.COM warn_ipmperr(err, "cannot get info for interface `%s'",
3788485SPeter.Memishian@Sun.COM iflistp->il_ifs[i]);
3798485SPeter.Memishian@Sun.COM continue;
3808485SPeter.Memishian@Sun.COM }
3818485SPeter.Memishian@Sun.COM (*iwp->iw_func)(ih, ifinfop, iwp->iw_funcarg);
3828485SPeter.Memishian@Sun.COM ipmp_freeifinfo(ifinfop);
3838485SPeter.Memishian@Sun.COM }
3848485SPeter.Memishian@Sun.COM }
3858485SPeter.Memishian@Sun.COM
3868485SPeter.Memishian@Sun.COM /*
3878485SPeter.Memishian@Sun.COM * Nested walker callback function for walk_addr().
3888485SPeter.Memishian@Sun.COM */
3898485SPeter.Memishian@Sun.COM static void
walk_addr_cbfunc(ipmp_handle_t ih,void * infop,void * arg)3908485SPeter.Memishian@Sun.COM walk_addr_cbfunc(ipmp_handle_t ih, void *infop, void *arg)
3918485SPeter.Memishian@Sun.COM {
3928485SPeter.Memishian@Sun.COM int err;
3938485SPeter.Memishian@Sun.COM uint_t i;
3948485SPeter.Memishian@Sun.COM ipmp_groupinfo_t *grinfop = infop;
3958485SPeter.Memishian@Sun.COM ipmp_addrinfo_t *adinfop;
3968485SPeter.Memishian@Sun.COM ipmp_addrlist_t *adlistp = grinfop->gr_adlistp;
3978485SPeter.Memishian@Sun.COM ipmpstat_walkdata_t *iwp = arg;
3988485SPeter.Memishian@Sun.COM char addr[INET6_ADDRSTRLEN];
3998485SPeter.Memishian@Sun.COM struct sockaddr_storage *addrp;
4008485SPeter.Memishian@Sun.COM
4018485SPeter.Memishian@Sun.COM for (i = 0; i < adlistp->al_naddr; i++) {
4028485SPeter.Memishian@Sun.COM addrp = &adlistp->al_addrs[i];
4038485SPeter.Memishian@Sun.COM err = ipmp_getaddrinfo(ih, grinfop->gr_name, addrp, &adinfop);
4048485SPeter.Memishian@Sun.COM if (err != IPMP_SUCCESS) {
4058485SPeter.Memishian@Sun.COM sockaddr2str(addrp, addr, sizeof (addr));
4068485SPeter.Memishian@Sun.COM warn_ipmperr(err, "cannot get info for `%s'", addr);
4078485SPeter.Memishian@Sun.COM continue;
4088485SPeter.Memishian@Sun.COM }
4098485SPeter.Memishian@Sun.COM (*iwp->iw_func)(ih, adinfop, iwp->iw_funcarg);
4108485SPeter.Memishian@Sun.COM ipmp_freeaddrinfo(adinfop);
4118485SPeter.Memishian@Sun.COM }
4128485SPeter.Memishian@Sun.COM }
4138485SPeter.Memishian@Sun.COM
414*9071SSowmini.Varadhan@Sun.COM static boolean_t
sfunc_nvwarn(const char * nvname)415*9071SSowmini.Varadhan@Sun.COM sfunc_nvwarn(const char *nvname)
4168485SPeter.Memishian@Sun.COM {
4178485SPeter.Memishian@Sun.COM warn("cannot retrieve %s\n", nvname);
418*9071SSowmini.Varadhan@Sun.COM return (B_FALSE);
4198485SPeter.Memishian@Sun.COM }
4208485SPeter.Memishian@Sun.COM
421*9071SSowmini.Varadhan@Sun.COM static boolean_t
sfunc_addr_address(ofmt_arg_t * ofmtarg,char * buf,uint_t bufsize)422*9071SSowmini.Varadhan@Sun.COM sfunc_addr_address(ofmt_arg_t *ofmtarg, char *buf, uint_t bufsize)
4238485SPeter.Memishian@Sun.COM {
424*9071SSowmini.Varadhan@Sun.COM ipmpstat_sfunc_arg_t *arg = ofmtarg->ofmt_cbarg;
4258485SPeter.Memishian@Sun.COM ipmp_addrinfo_t *adinfop = arg->sa_data;
4268485SPeter.Memishian@Sun.COM
4278485SPeter.Memishian@Sun.COM sockaddr2str(&adinfop->ad_addr, buf, bufsize);
428*9071SSowmini.Varadhan@Sun.COM return (B_TRUE);
4298485SPeter.Memishian@Sun.COM }
4308485SPeter.Memishian@Sun.COM
431*9071SSowmini.Varadhan@Sun.COM static boolean_t
sfunc_addr_group(ofmt_arg_t * ofmtarg,char * buf,uint_t bufsize)432*9071SSowmini.Varadhan@Sun.COM sfunc_addr_group(ofmt_arg_t *ofmtarg, char *buf, uint_t bufsize)
4338485SPeter.Memishian@Sun.COM {
434*9071SSowmini.Varadhan@Sun.COM ipmpstat_sfunc_arg_t *arg = ofmtarg->ofmt_cbarg;
4358485SPeter.Memishian@Sun.COM int err;
4368485SPeter.Memishian@Sun.COM ipmp_addrinfo_t *adinfop = arg->sa_data;
4378485SPeter.Memishian@Sun.COM ipmp_groupinfo_t *grinfop;
4388485SPeter.Memishian@Sun.COM
4398485SPeter.Memishian@Sun.COM err = ipmp_getgroupinfo(arg->sa_ih, adinfop->ad_group, &grinfop);
4408485SPeter.Memishian@Sun.COM if (err != IPMP_SUCCESS) {
4418485SPeter.Memishian@Sun.COM warn_ipmperr(err, "cannot get info for group `%s'",
4428485SPeter.Memishian@Sun.COM adinfop->ad_group);
443*9071SSowmini.Varadhan@Sun.COM return (B_FALSE);
4448485SPeter.Memishian@Sun.COM }
4458485SPeter.Memishian@Sun.COM (void) strlcpy(buf, grinfop->gr_ifname, bufsize);
4468485SPeter.Memishian@Sun.COM ipmp_freegroupinfo(grinfop);
447*9071SSowmini.Varadhan@Sun.COM return (B_TRUE);
4488485SPeter.Memishian@Sun.COM }
4498485SPeter.Memishian@Sun.COM
450*9071SSowmini.Varadhan@Sun.COM static boolean_t
sfunc_addr_state(ofmt_arg_t * ofmtarg,char * buf,uint_t bufsize)451*9071SSowmini.Varadhan@Sun.COM sfunc_addr_state(ofmt_arg_t *ofmtarg, char *buf, uint_t bufsize)
4528485SPeter.Memishian@Sun.COM {
453*9071SSowmini.Varadhan@Sun.COM ipmpstat_sfunc_arg_t *arg = ofmtarg->ofmt_cbarg;
4548485SPeter.Memishian@Sun.COM ipmp_addrinfo_t *adinfop = arg->sa_data;
4558485SPeter.Memishian@Sun.COM
4568485SPeter.Memishian@Sun.COM enum2str(addr_state, adinfop->ad_state, buf, bufsize);
457*9071SSowmini.Varadhan@Sun.COM return (B_TRUE);
4588485SPeter.Memishian@Sun.COM }
4598485SPeter.Memishian@Sun.COM
460*9071SSowmini.Varadhan@Sun.COM static boolean_t
sfunc_addr_inbound(ofmt_arg_t * ofmtarg,char * buf,uint_t bufsize)461*9071SSowmini.Varadhan@Sun.COM sfunc_addr_inbound(ofmt_arg_t *ofmtarg, char *buf, uint_t bufsize)
4628485SPeter.Memishian@Sun.COM {
463*9071SSowmini.Varadhan@Sun.COM ipmpstat_sfunc_arg_t *arg = ofmtarg->ofmt_cbarg;
4648485SPeter.Memishian@Sun.COM ipmp_addrinfo_t *adinfop = arg->sa_data;
4658485SPeter.Memishian@Sun.COM
4668485SPeter.Memishian@Sun.COM (void) strlcpy(buf, adinfop->ad_binding, bufsize);
467*9071SSowmini.Varadhan@Sun.COM return (B_TRUE);
4688485SPeter.Memishian@Sun.COM }
4698485SPeter.Memishian@Sun.COM
470*9071SSowmini.Varadhan@Sun.COM static boolean_t
sfunc_addr_outbound(ofmt_arg_t * ofmtarg,char * buf,uint_t bufsize)471*9071SSowmini.Varadhan@Sun.COM sfunc_addr_outbound(ofmt_arg_t *ofmtarg, char *buf, uint_t bufsize)
4728485SPeter.Memishian@Sun.COM {
473*9071SSowmini.Varadhan@Sun.COM ipmpstat_sfunc_arg_t *arg = ofmtarg->ofmt_cbarg;
4748485SPeter.Memishian@Sun.COM int err;
4758485SPeter.Memishian@Sun.COM uint_t i, nactive = 0;
4768485SPeter.Memishian@Sun.COM ipmp_ifinfo_t *ifinfop;
4778485SPeter.Memishian@Sun.COM ipmp_iflist_t *iflistp;
4788485SPeter.Memishian@Sun.COM ipmp_addrinfo_t *adinfop = arg->sa_data;
4798485SPeter.Memishian@Sun.COM ipmp_groupinfo_t *grinfop;
4808485SPeter.Memishian@Sun.COM
4818485SPeter.Memishian@Sun.COM if (adinfop->ad_state == IPMP_ADDR_DOWN)
482*9071SSowmini.Varadhan@Sun.COM return (B_TRUE);
4838485SPeter.Memishian@Sun.COM
4848485SPeter.Memishian@Sun.COM /*
4858485SPeter.Memishian@Sun.COM * If there's no inbound interface for this address, there can't
4868485SPeter.Memishian@Sun.COM * be any outbound traffic.
4878485SPeter.Memishian@Sun.COM */
4888485SPeter.Memishian@Sun.COM if (adinfop->ad_binding[0] == '\0')
489*9071SSowmini.Varadhan@Sun.COM return (B_TRUE);
4908485SPeter.Memishian@Sun.COM
4918485SPeter.Memishian@Sun.COM /*
4928485SPeter.Memishian@Sun.COM * The address can use any active interface in the group, so
4938485SPeter.Memishian@Sun.COM * obtain all of those.
4948485SPeter.Memishian@Sun.COM */
4958485SPeter.Memishian@Sun.COM err = ipmp_getgroupinfo(arg->sa_ih, adinfop->ad_group, &grinfop);
4968485SPeter.Memishian@Sun.COM if (err != IPMP_SUCCESS) {
4978485SPeter.Memishian@Sun.COM warn_ipmperr(err, "cannot get info for group `%s'",
4988485SPeter.Memishian@Sun.COM adinfop->ad_group);
499*9071SSowmini.Varadhan@Sun.COM return (B_FALSE);
5008485SPeter.Memishian@Sun.COM }
5018485SPeter.Memishian@Sun.COM
5028485SPeter.Memishian@Sun.COM iflistp = grinfop->gr_iflistp;
5038485SPeter.Memishian@Sun.COM for (i = 0; i < iflistp->il_nif; i++) {
5048485SPeter.Memishian@Sun.COM err = ipmp_getifinfo(arg->sa_ih, iflistp->il_ifs[i], &ifinfop);
5058485SPeter.Memishian@Sun.COM if (err != IPMP_SUCCESS) {
5068485SPeter.Memishian@Sun.COM warn_ipmperr(err, "cannot get info for interface `%s'",
5078485SPeter.Memishian@Sun.COM iflistp->il_ifs[i]);
5088485SPeter.Memishian@Sun.COM continue;
5098485SPeter.Memishian@Sun.COM }
5108485SPeter.Memishian@Sun.COM
5118485SPeter.Memishian@Sun.COM if (ifinfop->if_flags & IPMP_IFFLAG_ACTIVE) {
5128485SPeter.Memishian@Sun.COM if (nactive++ != 0)
5138485SPeter.Memishian@Sun.COM (void) strlcat(buf, " ", bufsize);
5148485SPeter.Memishian@Sun.COM (void) strlcat(buf, ifinfop->if_name, bufsize);
5158485SPeter.Memishian@Sun.COM }
5168485SPeter.Memishian@Sun.COM ipmp_freeifinfo(ifinfop);
5178485SPeter.Memishian@Sun.COM }
5188485SPeter.Memishian@Sun.COM ipmp_freegroupinfo(grinfop);
519*9071SSowmini.Varadhan@Sun.COM return (B_TRUE);
5208485SPeter.Memishian@Sun.COM }
5218485SPeter.Memishian@Sun.COM
522*9071SSowmini.Varadhan@Sun.COM static boolean_t
sfunc_group_name(ofmt_arg_t * ofmtarg,char * buf,uint_t bufsize)523*9071SSowmini.Varadhan@Sun.COM sfunc_group_name(ofmt_arg_t *ofmtarg, char *buf, uint_t bufsize)
5248485SPeter.Memishian@Sun.COM {
525*9071SSowmini.Varadhan@Sun.COM ipmpstat_sfunc_arg_t *arg = ofmtarg->ofmt_cbarg;
5268485SPeter.Memishian@Sun.COM ipmp_groupinfo_t *grinfop = arg->sa_data;
5278485SPeter.Memishian@Sun.COM
5288485SPeter.Memishian@Sun.COM (void) strlcpy(buf, grinfop->gr_name, bufsize);
529*9071SSowmini.Varadhan@Sun.COM return (B_TRUE);
5308485SPeter.Memishian@Sun.COM }
5318485SPeter.Memishian@Sun.COM
532*9071SSowmini.Varadhan@Sun.COM static boolean_t
sfunc_group_ifname(ofmt_arg_t * ofmtarg,char * buf,uint_t bufsize)533*9071SSowmini.Varadhan@Sun.COM sfunc_group_ifname(ofmt_arg_t *ofmtarg, char *buf, uint_t bufsize)
5348485SPeter.Memishian@Sun.COM {
535*9071SSowmini.Varadhan@Sun.COM ipmpstat_sfunc_arg_t *arg = ofmtarg->ofmt_cbarg;
5368485SPeter.Memishian@Sun.COM ipmp_groupinfo_t *grinfop = arg->sa_data;
5378485SPeter.Memishian@Sun.COM
5388485SPeter.Memishian@Sun.COM (void) strlcpy(buf, grinfop->gr_ifname, bufsize);
539*9071SSowmini.Varadhan@Sun.COM return (B_TRUE);
5408485SPeter.Memishian@Sun.COM }
5418485SPeter.Memishian@Sun.COM
542*9071SSowmini.Varadhan@Sun.COM static boolean_t
sfunc_group_state(ofmt_arg_t * ofmtarg,char * buf,uint_t bufsize)543*9071SSowmini.Varadhan@Sun.COM sfunc_group_state(ofmt_arg_t *ofmtarg, char *buf, uint_t bufsize)
5448485SPeter.Memishian@Sun.COM {
545*9071SSowmini.Varadhan@Sun.COM ipmpstat_sfunc_arg_t *arg = ofmtarg->ofmt_cbarg;
5468485SPeter.Memishian@Sun.COM ipmp_groupinfo_t *grinfop = arg->sa_data;
5478485SPeter.Memishian@Sun.COM
5488485SPeter.Memishian@Sun.COM enum2str(group_state, grinfop->gr_state, buf, bufsize);
549*9071SSowmini.Varadhan@Sun.COM return (B_TRUE);
5508485SPeter.Memishian@Sun.COM }
5518485SPeter.Memishian@Sun.COM
552*9071SSowmini.Varadhan@Sun.COM static boolean_t
sfunc_group_fdt(ofmt_arg_t * ofmtarg,char * buf,uint_t bufsize)553*9071SSowmini.Varadhan@Sun.COM sfunc_group_fdt(ofmt_arg_t *ofmtarg, char *buf, uint_t bufsize)
5548485SPeter.Memishian@Sun.COM {
555*9071SSowmini.Varadhan@Sun.COM ipmpstat_sfunc_arg_t *arg = ofmtarg->ofmt_cbarg;
5568485SPeter.Memishian@Sun.COM ipmp_groupinfo_t *grinfop = arg->sa_data;
5578485SPeter.Memishian@Sun.COM
5588485SPeter.Memishian@Sun.COM if (grinfop->gr_fdt == 0)
559*9071SSowmini.Varadhan@Sun.COM return (B_TRUE);
5608485SPeter.Memishian@Sun.COM
5618485SPeter.Memishian@Sun.COM (void) snprintf(buf, bufsize, "%.2fs", MS2FLOATSEC(grinfop->gr_fdt));
562*9071SSowmini.Varadhan@Sun.COM return (B_TRUE);
5638485SPeter.Memishian@Sun.COM }
5648485SPeter.Memishian@Sun.COM
565*9071SSowmini.Varadhan@Sun.COM static boolean_t
sfunc_group_interfaces(ofmt_arg_t * ofmtarg,char * buf,uint_t bufsize)566*9071SSowmini.Varadhan@Sun.COM sfunc_group_interfaces(ofmt_arg_t *ofmtarg, char *buf, uint_t bufsize)
5678485SPeter.Memishian@Sun.COM {
568*9071SSowmini.Varadhan@Sun.COM ipmpstat_sfunc_arg_t *arg = ofmtarg->ofmt_cbarg;
5698485SPeter.Memishian@Sun.COM int err;
5708485SPeter.Memishian@Sun.COM uint_t i;
5718485SPeter.Memishian@Sun.COM char *active, *inactive, *unusable;
5728485SPeter.Memishian@Sun.COM uint_t nactive = 0, ninactive = 0, nunusable = 0;
5738485SPeter.Memishian@Sun.COM ipmp_groupinfo_t *grinfop = arg->sa_data;
5748485SPeter.Memishian@Sun.COM ipmp_iflist_t *iflistp = grinfop->gr_iflistp;
5758485SPeter.Memishian@Sun.COM ipmp_ifinfo_t *ifinfop;
5768485SPeter.Memishian@Sun.COM
5778485SPeter.Memishian@Sun.COM active = alloca(bufsize);
5788485SPeter.Memishian@Sun.COM active[0] = '\0';
5798485SPeter.Memishian@Sun.COM inactive = alloca(bufsize);
5808485SPeter.Memishian@Sun.COM inactive[0] = '\0';
5818485SPeter.Memishian@Sun.COM unusable = alloca(bufsize);
5828485SPeter.Memishian@Sun.COM unusable[0] = '\0';
5838485SPeter.Memishian@Sun.COM
5848485SPeter.Memishian@Sun.COM for (i = 0; i < iflistp->il_nif; i++) {
5858485SPeter.Memishian@Sun.COM err = ipmp_getifinfo(arg->sa_ih, iflistp->il_ifs[i], &ifinfop);
5868485SPeter.Memishian@Sun.COM if (err != IPMP_SUCCESS) {
5878485SPeter.Memishian@Sun.COM warn_ipmperr(err, "cannot get info for interface `%s'",
5888485SPeter.Memishian@Sun.COM iflistp->il_ifs[i]);
5898485SPeter.Memishian@Sun.COM continue;
5908485SPeter.Memishian@Sun.COM }
5918485SPeter.Memishian@Sun.COM
5928485SPeter.Memishian@Sun.COM if (ifinfop->if_flags & IPMP_IFFLAG_ACTIVE) {
5938485SPeter.Memishian@Sun.COM if (nactive++ != 0)
5948485SPeter.Memishian@Sun.COM (void) strlcat(active, " ", bufsize);
5958485SPeter.Memishian@Sun.COM (void) strlcat(active, ifinfop->if_name, bufsize);
5968485SPeter.Memishian@Sun.COM } else if (ifinfop->if_flags & IPMP_IFFLAG_INACTIVE) {
5978485SPeter.Memishian@Sun.COM if (ninactive++ != 0)
5988485SPeter.Memishian@Sun.COM (void) strlcat(inactive, " ", bufsize);
5998485SPeter.Memishian@Sun.COM (void) strlcat(inactive, ifinfop->if_name, bufsize);
6008485SPeter.Memishian@Sun.COM } else {
6018485SPeter.Memishian@Sun.COM if (nunusable++ != 0)
6028485SPeter.Memishian@Sun.COM (void) strlcat(unusable, " ", bufsize);
6038485SPeter.Memishian@Sun.COM (void) strlcat(unusable, ifinfop->if_name, bufsize);
6048485SPeter.Memishian@Sun.COM }
6058485SPeter.Memishian@Sun.COM
6068485SPeter.Memishian@Sun.COM ipmp_freeifinfo(ifinfop);
6078485SPeter.Memishian@Sun.COM }
6088485SPeter.Memishian@Sun.COM
6098485SPeter.Memishian@Sun.COM (void) strlcpy(buf, active, bufsize);
6108485SPeter.Memishian@Sun.COM
6118485SPeter.Memishian@Sun.COM if (ninactive > 0) {
6128485SPeter.Memishian@Sun.COM if (nactive != 0)
6138485SPeter.Memishian@Sun.COM (void) strlcat(buf, " ", bufsize);
6148485SPeter.Memishian@Sun.COM
6158485SPeter.Memishian@Sun.COM (void) strlcat(buf, "(", bufsize);
6168485SPeter.Memishian@Sun.COM (void) strlcat(buf, inactive, bufsize);
6178485SPeter.Memishian@Sun.COM (void) strlcat(buf, ")", bufsize);
6188485SPeter.Memishian@Sun.COM }
6198485SPeter.Memishian@Sun.COM
6208485SPeter.Memishian@Sun.COM if (nunusable > 0) {
6218485SPeter.Memishian@Sun.COM if (nactive + ninactive != 0)
6228485SPeter.Memishian@Sun.COM (void) strlcat(buf, " ", bufsize);
6238485SPeter.Memishian@Sun.COM
6248485SPeter.Memishian@Sun.COM (void) strlcat(buf, "[", bufsize);
6258485SPeter.Memishian@Sun.COM (void) strlcat(buf, unusable, bufsize);
6268485SPeter.Memishian@Sun.COM (void) strlcat(buf, "]", bufsize);
6278485SPeter.Memishian@Sun.COM }
628*9071SSowmini.Varadhan@Sun.COM return (B_TRUE);
6298485SPeter.Memishian@Sun.COM }
6308485SPeter.Memishian@Sun.COM
631*9071SSowmini.Varadhan@Sun.COM static boolean_t
sfunc_if_name(ofmt_arg_t * ofmtarg,char * buf,uint_t bufsize)632*9071SSowmini.Varadhan@Sun.COM sfunc_if_name(ofmt_arg_t *ofmtarg, char *buf, uint_t bufsize)
6338485SPeter.Memishian@Sun.COM {
634*9071SSowmini.Varadhan@Sun.COM ipmpstat_sfunc_arg_t *arg = ofmtarg->ofmt_cbarg;
6358485SPeter.Memishian@Sun.COM ipmp_ifinfo_t *ifinfop = arg->sa_data;
6368485SPeter.Memishian@Sun.COM
6378485SPeter.Memishian@Sun.COM (void) strlcpy(buf, ifinfop->if_name, bufsize);
638*9071SSowmini.Varadhan@Sun.COM return (B_TRUE);
6398485SPeter.Memishian@Sun.COM }
6408485SPeter.Memishian@Sun.COM
641*9071SSowmini.Varadhan@Sun.COM static boolean_t
sfunc_if_active(ofmt_arg_t * ofmtarg,char * buf,uint_t bufsize)642*9071SSowmini.Varadhan@Sun.COM sfunc_if_active(ofmt_arg_t *ofmtarg, char *buf, uint_t bufsize)
6438485SPeter.Memishian@Sun.COM {
644*9071SSowmini.Varadhan@Sun.COM ipmpstat_sfunc_arg_t *arg = ofmtarg->ofmt_cbarg;
6458485SPeter.Memishian@Sun.COM ipmp_ifinfo_t *ifinfop = arg->sa_data;
6468485SPeter.Memishian@Sun.COM
6478485SPeter.Memishian@Sun.COM if (ifinfop->if_flags & IPMP_IFFLAG_ACTIVE)
6488485SPeter.Memishian@Sun.COM (void) strlcpy(buf, "yes", bufsize);
6498485SPeter.Memishian@Sun.COM else
6508485SPeter.Memishian@Sun.COM (void) strlcpy(buf, "no", bufsize);
651*9071SSowmini.Varadhan@Sun.COM return (B_TRUE);
6528485SPeter.Memishian@Sun.COM }
6538485SPeter.Memishian@Sun.COM
654*9071SSowmini.Varadhan@Sun.COM static boolean_t
sfunc_if_group(ofmt_arg_t * ofmtarg,char * buf,uint_t bufsize)655*9071SSowmini.Varadhan@Sun.COM sfunc_if_group(ofmt_arg_t *ofmtarg, char *buf, uint_t bufsize)
6568485SPeter.Memishian@Sun.COM {
657*9071SSowmini.Varadhan@Sun.COM ipmpstat_sfunc_arg_t *arg = ofmtarg->ofmt_cbarg;
6588485SPeter.Memishian@Sun.COM int err;
6598485SPeter.Memishian@Sun.COM ipmp_ifinfo_t *ifinfop = arg->sa_data;
6608485SPeter.Memishian@Sun.COM ipmp_groupinfo_t *grinfop;
6618485SPeter.Memishian@Sun.COM
6628485SPeter.Memishian@Sun.COM err = ipmp_getgroupinfo(arg->sa_ih, ifinfop->if_group, &grinfop);
6638485SPeter.Memishian@Sun.COM if (err != IPMP_SUCCESS) {
6648485SPeter.Memishian@Sun.COM warn_ipmperr(err, "cannot get info for group `%s'",
6658485SPeter.Memishian@Sun.COM ifinfop->if_group);
666*9071SSowmini.Varadhan@Sun.COM return (B_TRUE);
6678485SPeter.Memishian@Sun.COM }
6688485SPeter.Memishian@Sun.COM
6698485SPeter.Memishian@Sun.COM (void) strlcpy(buf, grinfop->gr_ifname, bufsize);
6708485SPeter.Memishian@Sun.COM ipmp_freegroupinfo(grinfop);
671*9071SSowmini.Varadhan@Sun.COM return (B_TRUE);
6728485SPeter.Memishian@Sun.COM }
6738485SPeter.Memishian@Sun.COM
674*9071SSowmini.Varadhan@Sun.COM static boolean_t
sfunc_if_flags(ofmt_arg_t * ofmtarg,char * buf,uint_t bufsize)675*9071SSowmini.Varadhan@Sun.COM sfunc_if_flags(ofmt_arg_t *ofmtarg, char *buf, uint_t bufsize)
6768485SPeter.Memishian@Sun.COM {
677*9071SSowmini.Varadhan@Sun.COM ipmpstat_sfunc_arg_t *arg = ofmtarg->ofmt_cbarg;
6788485SPeter.Memishian@Sun.COM int err;
6798485SPeter.Memishian@Sun.COM ipmp_ifinfo_t *ifinfop = arg->sa_data;
6808485SPeter.Memishian@Sun.COM ipmp_groupinfo_t *grinfop;
6818485SPeter.Memishian@Sun.COM
6828485SPeter.Memishian@Sun.COM assert(bufsize > IPMPSTAT_NUM_FLAGS);
6838485SPeter.Memishian@Sun.COM
6848485SPeter.Memishian@Sun.COM (void) memset(buf, '-', IPMPSTAT_NUM_FLAGS);
6858485SPeter.Memishian@Sun.COM buf[IPMPSTAT_NUM_FLAGS] = '\0';
6868485SPeter.Memishian@Sun.COM
6878485SPeter.Memishian@Sun.COM if (ifinfop->if_type == IPMP_IF_STANDBY)
6888485SPeter.Memishian@Sun.COM buf[IPMPSTAT_SFLAG_INDEX] = 's';
6898485SPeter.Memishian@Sun.COM
6908485SPeter.Memishian@Sun.COM if (ifinfop->if_flags & IPMP_IFFLAG_INACTIVE)
6918485SPeter.Memishian@Sun.COM buf[IPMPSTAT_IFLAG_INDEX] = 'i';
6928485SPeter.Memishian@Sun.COM
6938485SPeter.Memishian@Sun.COM if (ifinfop->if_flags & IPMP_IFFLAG_DOWN)
6948485SPeter.Memishian@Sun.COM buf[IPMPSTAT_DFLAG_INDEX] = 'd';
6958485SPeter.Memishian@Sun.COM
6968485SPeter.Memishian@Sun.COM if (ifinfop->if_flags & IPMP_IFFLAG_HWADDRDUP)
6978485SPeter.Memishian@Sun.COM buf[IPMPSTAT_HFLAG_INDEX] = 'h';
6988485SPeter.Memishian@Sun.COM
6998485SPeter.Memishian@Sun.COM err = ipmp_getgroupinfo(arg->sa_ih, ifinfop->if_group, &grinfop);
7008485SPeter.Memishian@Sun.COM if (err != IPMP_SUCCESS) {
7018485SPeter.Memishian@Sun.COM warn_ipmperr(err, "cannot get broadcast/multicast info for "
7028485SPeter.Memishian@Sun.COM "group `%s'", ifinfop->if_group);
703*9071SSowmini.Varadhan@Sun.COM return (B_TRUE);
7048485SPeter.Memishian@Sun.COM }
7058485SPeter.Memishian@Sun.COM
7068485SPeter.Memishian@Sun.COM if (strcmp(grinfop->gr_m4ifname, ifinfop->if_name) == 0)
7078485SPeter.Memishian@Sun.COM buf[IPMPSTAT_M4FLAG_INDEX] = 'm';
7088485SPeter.Memishian@Sun.COM
7098485SPeter.Memishian@Sun.COM if (strcmp(grinfop->gr_m6ifname, ifinfop->if_name) == 0)
7108485SPeter.Memishian@Sun.COM buf[IPMPSTAT_M6FLAG_INDEX] = 'M';
7118485SPeter.Memishian@Sun.COM
7128485SPeter.Memishian@Sun.COM if (strcmp(grinfop->gr_bcifname, ifinfop->if_name) == 0)
7138485SPeter.Memishian@Sun.COM buf[IPMPSTAT_BFLAG_INDEX] = 'b';
7148485SPeter.Memishian@Sun.COM
7158485SPeter.Memishian@Sun.COM ipmp_freegroupinfo(grinfop);
716*9071SSowmini.Varadhan@Sun.COM return (B_TRUE);
7178485SPeter.Memishian@Sun.COM }
7188485SPeter.Memishian@Sun.COM
719*9071SSowmini.Varadhan@Sun.COM static boolean_t
sfunc_if_link(ofmt_arg_t * ofmtarg,char * buf,uint_t bufsize)720*9071SSowmini.Varadhan@Sun.COM sfunc_if_link(ofmt_arg_t *ofmtarg, char *buf, uint_t bufsize)
7218485SPeter.Memishian@Sun.COM {
722*9071SSowmini.Varadhan@Sun.COM ipmpstat_sfunc_arg_t *arg = ofmtarg->ofmt_cbarg;
7238485SPeter.Memishian@Sun.COM ipmp_ifinfo_t *ifinfop = arg->sa_data;
7248485SPeter.Memishian@Sun.COM
7258485SPeter.Memishian@Sun.COM enum2str(if_link, ifinfop->if_linkstate, buf, bufsize);
726*9071SSowmini.Varadhan@Sun.COM return (B_TRUE);
7278485SPeter.Memishian@Sun.COM }
7288485SPeter.Memishian@Sun.COM
729*9071SSowmini.Varadhan@Sun.COM static boolean_t
sfunc_if_probe(ofmt_arg_t * ofmtarg,char * buf,uint_t bufsize)730*9071SSowmini.Varadhan@Sun.COM sfunc_if_probe(ofmt_arg_t *ofmtarg, char *buf, uint_t bufsize)
7318485SPeter.Memishian@Sun.COM {
732*9071SSowmini.Varadhan@Sun.COM ipmpstat_sfunc_arg_t *arg = ofmtarg->ofmt_cbarg;
7338485SPeter.Memishian@Sun.COM ipmp_ifinfo_t *ifinfop = arg->sa_data;
7348485SPeter.Memishian@Sun.COM
7358485SPeter.Memishian@Sun.COM enum2str(if_probe, ifinfop->if_probestate, buf, bufsize);
736*9071SSowmini.Varadhan@Sun.COM return (B_TRUE);
7378485SPeter.Memishian@Sun.COM }
7388485SPeter.Memishian@Sun.COM
739*9071SSowmini.Varadhan@Sun.COM static boolean_t
sfunc_if_state(ofmt_arg_t * ofmtarg,char * buf,uint_t bufsize)740*9071SSowmini.Varadhan@Sun.COM sfunc_if_state(ofmt_arg_t *ofmtarg, char *buf, uint_t bufsize)
7418485SPeter.Memishian@Sun.COM {
742*9071SSowmini.Varadhan@Sun.COM ipmpstat_sfunc_arg_t *arg = ofmtarg->ofmt_cbarg;
7438485SPeter.Memishian@Sun.COM ipmp_ifinfo_t *ifinfop = arg->sa_data;
7448485SPeter.Memishian@Sun.COM
7458485SPeter.Memishian@Sun.COM enum2str(if_state, ifinfop->if_state, buf, bufsize);
746*9071SSowmini.Varadhan@Sun.COM return (B_TRUE);
7478485SPeter.Memishian@Sun.COM }
7488485SPeter.Memishian@Sun.COM
749*9071SSowmini.Varadhan@Sun.COM static boolean_t
sfunc_probe_id(ofmt_arg_t * ofmtarg,char * buf,uint_t bufsize)750*9071SSowmini.Varadhan@Sun.COM sfunc_probe_id(ofmt_arg_t *ofmtarg, char *buf, uint_t bufsize)
7518485SPeter.Memishian@Sun.COM {
752*9071SSowmini.Varadhan@Sun.COM ipmpstat_sfunc_arg_t *arg = ofmtarg->ofmt_cbarg;
7538485SPeter.Memishian@Sun.COM uint32_t probe_id;
7548485SPeter.Memishian@Sun.COM nvlist_t *nvl = arg->sa_data;
7558485SPeter.Memishian@Sun.COM
756*9071SSowmini.Varadhan@Sun.COM if (nvlist_lookup_uint32(nvl, IPMP_PROBE_ID, &probe_id) != 0)
757*9071SSowmini.Varadhan@Sun.COM return (sfunc_nvwarn("IPMP_PROBE_ID"));
7588485SPeter.Memishian@Sun.COM
7598485SPeter.Memishian@Sun.COM (void) snprintf(buf, bufsize, "%u", probe_id);
760*9071SSowmini.Varadhan@Sun.COM return (B_TRUE);
7618485SPeter.Memishian@Sun.COM }
7628485SPeter.Memishian@Sun.COM
763*9071SSowmini.Varadhan@Sun.COM static boolean_t
sfunc_probe_ifname(ofmt_arg_t * ofmtarg,char * buf,uint_t bufsize)764*9071SSowmini.Varadhan@Sun.COM sfunc_probe_ifname(ofmt_arg_t *ofmtarg, char *buf, uint_t bufsize)
7658485SPeter.Memishian@Sun.COM {
766*9071SSowmini.Varadhan@Sun.COM ipmpstat_sfunc_arg_t *arg = ofmtarg->ofmt_cbarg;
7678485SPeter.Memishian@Sun.COM char *ifname;
7688485SPeter.Memishian@Sun.COM nvlist_t *nvl = arg->sa_data;
7698485SPeter.Memishian@Sun.COM
770*9071SSowmini.Varadhan@Sun.COM if (nvlist_lookup_string(nvl, IPMP_IF_NAME, &ifname) != 0)
771*9071SSowmini.Varadhan@Sun.COM return (sfunc_nvwarn("IPMP_IF_NAME"));
7728485SPeter.Memishian@Sun.COM
7738485SPeter.Memishian@Sun.COM (void) strlcpy(buf, ifname, bufsize);
774*9071SSowmini.Varadhan@Sun.COM return (B_TRUE);
7758485SPeter.Memishian@Sun.COM }
7768485SPeter.Memishian@Sun.COM
777*9071SSowmini.Varadhan@Sun.COM static boolean_t
sfunc_probe_time(ofmt_arg_t * ofmtarg,char * buf,uint_t bufsize)778*9071SSowmini.Varadhan@Sun.COM sfunc_probe_time(ofmt_arg_t *ofmtarg, char *buf, uint_t bufsize)
7798485SPeter.Memishian@Sun.COM {
780*9071SSowmini.Varadhan@Sun.COM ipmpstat_sfunc_arg_t *arg = ofmtarg->ofmt_cbarg;
7818485SPeter.Memishian@Sun.COM hrtime_t start;
7828485SPeter.Memishian@Sun.COM nvlist_t *nvl = arg->sa_data;
7838485SPeter.Memishian@Sun.COM
784*9071SSowmini.Varadhan@Sun.COM if (nvlist_lookup_hrtime(nvl, IPMP_PROBE_START_TIME, &start) != 0)
785*9071SSowmini.Varadhan@Sun.COM return (sfunc_nvwarn("IPMP_PROBE_START_TIME"));
7868485SPeter.Memishian@Sun.COM
7878485SPeter.Memishian@Sun.COM (void) snprintf(buf, bufsize, "%.2fs",
7888485SPeter.Memishian@Sun.COM (float)(start - probe_output_start) / NANOSEC);
789*9071SSowmini.Varadhan@Sun.COM return (B_TRUE);
7908485SPeter.Memishian@Sun.COM }
7918485SPeter.Memishian@Sun.COM
792*9071SSowmini.Varadhan@Sun.COM static boolean_t
sfunc_probe_target(ofmt_arg_t * ofmtarg,char * buf,uint_t bufsize)793*9071SSowmini.Varadhan@Sun.COM sfunc_probe_target(ofmt_arg_t *ofmtarg, char *buf, uint_t bufsize)
7948485SPeter.Memishian@Sun.COM {
795*9071SSowmini.Varadhan@Sun.COM ipmpstat_sfunc_arg_t *arg = ofmtarg->ofmt_cbarg;
7968485SPeter.Memishian@Sun.COM uint_t nelem;
7978485SPeter.Memishian@Sun.COM struct sockaddr_storage *target;
7988485SPeter.Memishian@Sun.COM nvlist_t *nvl = arg->sa_data;
7998485SPeter.Memishian@Sun.COM
8008485SPeter.Memishian@Sun.COM if (nvlist_lookup_byte_array(nvl, IPMP_PROBE_TARGET,
801*9071SSowmini.Varadhan@Sun.COM (uchar_t **)&target, &nelem) != 0)
802*9071SSowmini.Varadhan@Sun.COM return (sfunc_nvwarn("IPMP_PROBE_TARGET"));
8038485SPeter.Memishian@Sun.COM
8048485SPeter.Memishian@Sun.COM sockaddr2str(target, buf, bufsize);
805*9071SSowmini.Varadhan@Sun.COM return (B_TRUE);
8068485SPeter.Memishian@Sun.COM }
8078485SPeter.Memishian@Sun.COM
808*9071SSowmini.Varadhan@Sun.COM static boolean_t
sfunc_probe_rtt(ofmt_arg_t * ofmtarg,char * buf,uint_t bufsize)809*9071SSowmini.Varadhan@Sun.COM sfunc_probe_rtt(ofmt_arg_t *ofmtarg, char *buf, uint_t bufsize)
8108485SPeter.Memishian@Sun.COM {
811*9071SSowmini.Varadhan@Sun.COM ipmpstat_sfunc_arg_t *arg = ofmtarg->ofmt_cbarg;
8128485SPeter.Memishian@Sun.COM hrtime_t start, ackproc;
8138485SPeter.Memishian@Sun.COM nvlist_t *nvl = arg->sa_data;
8148485SPeter.Memishian@Sun.COM uint32_t state;
8158485SPeter.Memishian@Sun.COM
816*9071SSowmini.Varadhan@Sun.COM if (nvlist_lookup_uint32(nvl, IPMP_PROBE_STATE, &state) != 0)
817*9071SSowmini.Varadhan@Sun.COM return (sfunc_nvwarn("IPMP_PROBE_STATE"));
8188485SPeter.Memishian@Sun.COM
8198485SPeter.Memishian@Sun.COM if (state != IPMP_PROBE_ACKED)
820*9071SSowmini.Varadhan@Sun.COM return (B_TRUE);
8218485SPeter.Memishian@Sun.COM
822*9071SSowmini.Varadhan@Sun.COM if (nvlist_lookup_hrtime(nvl, IPMP_PROBE_START_TIME, &start) != 0)
823*9071SSowmini.Varadhan@Sun.COM return (sfunc_nvwarn("IPMP_PROBE_START_TIME"));
8248485SPeter.Memishian@Sun.COM
825*9071SSowmini.Varadhan@Sun.COM if (nvlist_lookup_hrtime(nvl, IPMP_PROBE_ACKPROC_TIME, &ackproc) != 0)
826*9071SSowmini.Varadhan@Sun.COM return (sfunc_nvwarn("IPMP_PROBE_ACKPROC_TIME"));
8278485SPeter.Memishian@Sun.COM
8288485SPeter.Memishian@Sun.COM (void) snprintf(buf, bufsize, "%.2fms", NS2FLOATMS(ackproc - start));
829*9071SSowmini.Varadhan@Sun.COM return (B_TRUE);
8308485SPeter.Memishian@Sun.COM }
8318485SPeter.Memishian@Sun.COM
832*9071SSowmini.Varadhan@Sun.COM static boolean_t
sfunc_probe_netrtt(ofmt_arg_t * ofmtarg,char * buf,uint_t bufsize)833*9071SSowmini.Varadhan@Sun.COM sfunc_probe_netrtt(ofmt_arg_t *ofmtarg, char *buf, uint_t bufsize)
8348485SPeter.Memishian@Sun.COM {
835*9071SSowmini.Varadhan@Sun.COM ipmpstat_sfunc_arg_t *arg = ofmtarg->ofmt_cbarg;
8368485SPeter.Memishian@Sun.COM hrtime_t sent, ackrecv;
8378485SPeter.Memishian@Sun.COM nvlist_t *nvl = arg->sa_data;
8388485SPeter.Memishian@Sun.COM uint32_t state;
8398485SPeter.Memishian@Sun.COM
840*9071SSowmini.Varadhan@Sun.COM if (nvlist_lookup_uint32(nvl, IPMP_PROBE_STATE, &state) != 0)
841*9071SSowmini.Varadhan@Sun.COM return (sfunc_nvwarn("IPMP_PROBE_STATE"));
8428485SPeter.Memishian@Sun.COM
8438485SPeter.Memishian@Sun.COM if (state != IPMP_PROBE_ACKED)
844*9071SSowmini.Varadhan@Sun.COM return (B_TRUE);
8458485SPeter.Memishian@Sun.COM
846*9071SSowmini.Varadhan@Sun.COM if (nvlist_lookup_hrtime(nvl, IPMP_PROBE_SENT_TIME, &sent) != 0)
847*9071SSowmini.Varadhan@Sun.COM return (sfunc_nvwarn("IPMP_PROBE_SENT_TIME"));
8488485SPeter.Memishian@Sun.COM
849*9071SSowmini.Varadhan@Sun.COM if (nvlist_lookup_hrtime(nvl, IPMP_PROBE_ACKRECV_TIME, &ackrecv) != 0)
850*9071SSowmini.Varadhan@Sun.COM return (sfunc_nvwarn("IPMP_PROBE_ACKRECV_TIME"));
8518485SPeter.Memishian@Sun.COM
8528485SPeter.Memishian@Sun.COM (void) snprintf(buf, bufsize, "%.2fms", NS2FLOATMS(ackrecv - sent));
853*9071SSowmini.Varadhan@Sun.COM return (B_TRUE);
8548485SPeter.Memishian@Sun.COM }
8558485SPeter.Memishian@Sun.COM
856*9071SSowmini.Varadhan@Sun.COM static boolean_t
sfunc_probe_rttavg(ofmt_arg_t * ofmtarg,char * buf,uint_t bufsize)857*9071SSowmini.Varadhan@Sun.COM sfunc_probe_rttavg(ofmt_arg_t *ofmtarg, char *buf, uint_t bufsize)
8588485SPeter.Memishian@Sun.COM {
859*9071SSowmini.Varadhan@Sun.COM ipmpstat_sfunc_arg_t *arg = ofmtarg->ofmt_cbarg;
8608485SPeter.Memishian@Sun.COM int64_t rttavg;
8618485SPeter.Memishian@Sun.COM nvlist_t *nvl = arg->sa_data;
8628485SPeter.Memishian@Sun.COM
863*9071SSowmini.Varadhan@Sun.COM if (nvlist_lookup_int64(nvl, IPMP_PROBE_TARGET_RTTAVG, &rttavg) != 0)
864*9071SSowmini.Varadhan@Sun.COM return (sfunc_nvwarn("IPMP_PROBE_TARGET_RTTAVG"));
8658485SPeter.Memishian@Sun.COM
8668485SPeter.Memishian@Sun.COM if (rttavg != 0)
8678485SPeter.Memishian@Sun.COM (void) snprintf(buf, bufsize, "%.2fms", NS2FLOATMS(rttavg));
868*9071SSowmini.Varadhan@Sun.COM return (B_TRUE);
8698485SPeter.Memishian@Sun.COM }
8708485SPeter.Memishian@Sun.COM
871*9071SSowmini.Varadhan@Sun.COM static boolean_t
sfunc_probe_rttdev(ofmt_arg_t * ofmtarg,char * buf,uint_t bufsize)872*9071SSowmini.Varadhan@Sun.COM sfunc_probe_rttdev(ofmt_arg_t *ofmtarg, char *buf, uint_t bufsize)
8738485SPeter.Memishian@Sun.COM {
874*9071SSowmini.Varadhan@Sun.COM ipmpstat_sfunc_arg_t *arg = ofmtarg->ofmt_cbarg;
8758485SPeter.Memishian@Sun.COM int64_t rttdev;
8768485SPeter.Memishian@Sun.COM nvlist_t *nvl = arg->sa_data;
8778485SPeter.Memishian@Sun.COM
878*9071SSowmini.Varadhan@Sun.COM if (nvlist_lookup_int64(nvl, IPMP_PROBE_TARGET_RTTDEV, &rttdev) != 0)
879*9071SSowmini.Varadhan@Sun.COM return (sfunc_nvwarn("IPMP_PROBE_TARGET_RTTDEV"));
8808485SPeter.Memishian@Sun.COM
8818485SPeter.Memishian@Sun.COM if (rttdev != 0)
8828485SPeter.Memishian@Sun.COM (void) snprintf(buf, bufsize, "%.2fms", NS2FLOATMS(rttdev));
883*9071SSowmini.Varadhan@Sun.COM return (B_TRUE);
8848485SPeter.Memishian@Sun.COM }
8858485SPeter.Memishian@Sun.COM
8868485SPeter.Memishian@Sun.COM /* ARGSUSED */
8878485SPeter.Memishian@Sun.COM static void
probe_enabled_cbfunc(ipmp_handle_t ih,void * infop,void * arg)8888485SPeter.Memishian@Sun.COM probe_enabled_cbfunc(ipmp_handle_t ih, void *infop, void *arg)
8898485SPeter.Memishian@Sun.COM {
8908485SPeter.Memishian@Sun.COM uint_t *nenabledp = arg;
8918485SPeter.Memishian@Sun.COM ipmp_ifinfo_t *ifinfop = infop;
8928485SPeter.Memishian@Sun.COM
8938485SPeter.Memishian@Sun.COM if (ifinfop->if_probestate != IPMP_PROBE_DISABLED)
8948485SPeter.Memishian@Sun.COM (*nenabledp)++;
8958485SPeter.Memishian@Sun.COM }
8968485SPeter.Memishian@Sun.COM
8978485SPeter.Memishian@Sun.COM static void
probe_output(ipmp_handle_t ih,ofmt_handle_t ofmt)898*9071SSowmini.Varadhan@Sun.COM probe_output(ipmp_handle_t ih, ofmt_handle_t ofmt)
8998485SPeter.Memishian@Sun.COM {
9008485SPeter.Memishian@Sun.COM char sub[MAX_SUBID_LEN];
9018485SPeter.Memishian@Sun.COM evchan_t *evch;
9028485SPeter.Memishian@Sun.COM ipmpstat_probe_state_t ps = { ih, ofmt };
9038485SPeter.Memishian@Sun.COM uint_t nenabled = 0;
9048485SPeter.Memishian@Sun.COM
9058485SPeter.Memishian@Sun.COM /*
9068485SPeter.Memishian@Sun.COM * Check if any interfaces are enabled for probe-based failure
9078485SPeter.Memishian@Sun.COM * detection. If not, immediately fail.
9088485SPeter.Memishian@Sun.COM */
9098485SPeter.Memishian@Sun.COM walk_if(ih, probe_enabled_cbfunc, &nenabled);
9108485SPeter.Memishian@Sun.COM if (nenabled == 0)
9118485SPeter.Memishian@Sun.COM die("probe-based failure detection is disabled\n");
9128485SPeter.Memishian@Sun.COM
9138485SPeter.Memishian@Sun.COM probe_output_start = gethrtime();
9148485SPeter.Memishian@Sun.COM
9158485SPeter.Memishian@Sun.COM /*
9168485SPeter.Memishian@Sun.COM * Unfortunately, until 4791900 is fixed, only privileged processes
9178485SPeter.Memishian@Sun.COM * can bind and thus receive sysevents.
9188485SPeter.Memishian@Sun.COM */
9198485SPeter.Memishian@Sun.COM errno = sysevent_evc_bind(IPMP_EVENT_CHAN, &evch, EVCH_CREAT);
9208485SPeter.Memishian@Sun.COM if (errno != 0) {
9218485SPeter.Memishian@Sun.COM if (errno == EPERM)
9228485SPeter.Memishian@Sun.COM die("insufficient privileges for -p\n");
9238485SPeter.Memishian@Sun.COM die("sysevent_evc_bind to channel %s failed", IPMP_EVENT_CHAN);
9248485SPeter.Memishian@Sun.COM }
9258485SPeter.Memishian@Sun.COM
9268485SPeter.Memishian@Sun.COM /*
9278485SPeter.Memishian@Sun.COM * The subscriber must be unique in order for sysevent_evc_subscribe()
9288485SPeter.Memishian@Sun.COM * to succeed, so combine our name and pid.
9298485SPeter.Memishian@Sun.COM */
9308485SPeter.Memishian@Sun.COM (void) snprintf(sub, sizeof (sub), "%d-%s", getpid(), progname);
9318485SPeter.Memishian@Sun.COM
9328485SPeter.Memishian@Sun.COM errno = sysevent_evc_subscribe(evch, sub, EC_IPMP, probe_event, &ps, 0);
9338485SPeter.Memishian@Sun.COM if (errno != 0)
9348485SPeter.Memishian@Sun.COM die("sysevent_evc_subscribe for class %s failed", EC_IPMP);
9358485SPeter.Memishian@Sun.COM
9368485SPeter.Memishian@Sun.COM for (;;)
9378485SPeter.Memishian@Sun.COM (void) pause();
9388485SPeter.Memishian@Sun.COM }
9398485SPeter.Memishian@Sun.COM
9408485SPeter.Memishian@Sun.COM static int
probe_event(sysevent_t * ev,void * arg)9418485SPeter.Memishian@Sun.COM probe_event(sysevent_t *ev, void *arg)
9428485SPeter.Memishian@Sun.COM {
9438485SPeter.Memishian@Sun.COM nvlist_t *nvl;
9448485SPeter.Memishian@Sun.COM uint32_t state;
9458485SPeter.Memishian@Sun.COM uint32_t version;
9468485SPeter.Memishian@Sun.COM ipmpstat_probe_state_t *psp = arg;
9478485SPeter.Memishian@Sun.COM
9488485SPeter.Memishian@Sun.COM if (strcmp(sysevent_get_subclass_name(ev), ESC_IPMP_PROBE_STATE) != 0)
9498485SPeter.Memishian@Sun.COM return (0);
9508485SPeter.Memishian@Sun.COM
9518485SPeter.Memishian@Sun.COM if (sysevent_get_attr_list(ev, &nvl) != 0) {
9528485SPeter.Memishian@Sun.COM warn("sysevent_get_attr_list failed; dropping event");
9538485SPeter.Memishian@Sun.COM return (0);
9548485SPeter.Memishian@Sun.COM }
9558485SPeter.Memishian@Sun.COM
9568485SPeter.Memishian@Sun.COM if (nvlist_lookup_uint32(nvl, IPMP_EVENT_VERSION, &version) != 0) {
9578485SPeter.Memishian@Sun.COM warn("dropped event with no IPMP_EVENT_VERSION\n");
9588485SPeter.Memishian@Sun.COM goto out;
9598485SPeter.Memishian@Sun.COM }
9608485SPeter.Memishian@Sun.COM
9618485SPeter.Memishian@Sun.COM if (version != IPMP_EVENT_CUR_VERSION) {
9628485SPeter.Memishian@Sun.COM warn("dropped event with unsupported IPMP_EVENT_VERSION %d\n",
9638485SPeter.Memishian@Sun.COM version);
9648485SPeter.Memishian@Sun.COM goto out;
9658485SPeter.Memishian@Sun.COM }
9668485SPeter.Memishian@Sun.COM
9678485SPeter.Memishian@Sun.COM if (nvlist_lookup_uint32(nvl, IPMP_PROBE_STATE, &state) != 0) {
9688485SPeter.Memishian@Sun.COM warn("dropped event with no IPMP_PROBE_STATE\n");
9698485SPeter.Memishian@Sun.COM goto out;
9708485SPeter.Memishian@Sun.COM }
9718485SPeter.Memishian@Sun.COM
9728485SPeter.Memishian@Sun.COM if (state == IPMP_PROBE_ACKED || state == IPMP_PROBE_LOST)
9738485SPeter.Memishian@Sun.COM ofmt_output(psp->ps_ofmt, psp->ps_ih, nvl);
9748485SPeter.Memishian@Sun.COM out:
9758485SPeter.Memishian@Sun.COM nvlist_free(nvl);
9768485SPeter.Memishian@Sun.COM return (0);
9778485SPeter.Memishian@Sun.COM }
9788485SPeter.Memishian@Sun.COM
979*9071SSowmini.Varadhan@Sun.COM static boolean_t
sfunc_targ_ifname(ofmt_arg_t * ofmtarg,char * buf,uint_t bufsize)980*9071SSowmini.Varadhan@Sun.COM sfunc_targ_ifname(ofmt_arg_t *ofmtarg, char *buf, uint_t bufsize)
9818485SPeter.Memishian@Sun.COM {
982*9071SSowmini.Varadhan@Sun.COM ipmpstat_sfunc_arg_t *arg = ofmtarg->ofmt_cbarg;
9838485SPeter.Memishian@Sun.COM ipmp_targinfo_t *targinfop = arg->sa_data;
9848485SPeter.Memishian@Sun.COM
9858485SPeter.Memishian@Sun.COM (void) strlcpy(buf, targinfop->it_name, bufsize);
986*9071SSowmini.Varadhan@Sun.COM return (B_TRUE);
9878485SPeter.Memishian@Sun.COM }
9888485SPeter.Memishian@Sun.COM
989*9071SSowmini.Varadhan@Sun.COM static boolean_t
sfunc_targ_mode(ofmt_arg_t * ofmtarg,char * buf,uint_t bufsize)990*9071SSowmini.Varadhan@Sun.COM sfunc_targ_mode(ofmt_arg_t *ofmtarg, char *buf, uint_t bufsize)
9918485SPeter.Memishian@Sun.COM {
992*9071SSowmini.Varadhan@Sun.COM ipmpstat_sfunc_arg_t *arg = ofmtarg->ofmt_cbarg;
9938485SPeter.Memishian@Sun.COM ipmp_targinfo_t *targinfop = arg->sa_data;
9948485SPeter.Memishian@Sun.COM
9958485SPeter.Memishian@Sun.COM enum2str(targ_mode, targinfop->it_targmode, buf, bufsize);
996*9071SSowmini.Varadhan@Sun.COM return (B_TRUE);
9978485SPeter.Memishian@Sun.COM }
9988485SPeter.Memishian@Sun.COM
999*9071SSowmini.Varadhan@Sun.COM static boolean_t
sfunc_targ_testaddr(ofmt_arg_t * ofmtarg,char * buf,uint_t bufsize)1000*9071SSowmini.Varadhan@Sun.COM sfunc_targ_testaddr(ofmt_arg_t *ofmtarg, char *buf, uint_t bufsize)
10018485SPeter.Memishian@Sun.COM {
1002*9071SSowmini.Varadhan@Sun.COM ipmpstat_sfunc_arg_t *arg = ofmtarg->ofmt_cbarg;
10038485SPeter.Memishian@Sun.COM ipmp_targinfo_t *targinfop = arg->sa_data;
10048485SPeter.Memishian@Sun.COM
10058485SPeter.Memishian@Sun.COM if (targinfop->it_targmode != IPMP_TARG_DISABLED)
10068485SPeter.Memishian@Sun.COM sockaddr2str(&targinfop->it_testaddr, buf, bufsize);
1007*9071SSowmini.Varadhan@Sun.COM return (B_TRUE);
10088485SPeter.Memishian@Sun.COM }
10098485SPeter.Memishian@Sun.COM
1010*9071SSowmini.Varadhan@Sun.COM static boolean_t
sfunc_targ_targets(ofmt_arg_t * ofmtarg,char * buf,uint_t bufsize)1011*9071SSowmini.Varadhan@Sun.COM sfunc_targ_targets(ofmt_arg_t *ofmtarg, char *buf, uint_t bufsize)
10128485SPeter.Memishian@Sun.COM {
1013*9071SSowmini.Varadhan@Sun.COM ipmpstat_sfunc_arg_t *arg = ofmtarg->ofmt_cbarg;
10148485SPeter.Memishian@Sun.COM uint_t i;
10158485SPeter.Memishian@Sun.COM char *targname = alloca(bufsize);
10168485SPeter.Memishian@Sun.COM ipmp_targinfo_t *targinfop = arg->sa_data;
10178485SPeter.Memishian@Sun.COM ipmp_addrlist_t *targlistp = targinfop->it_targlistp;
10188485SPeter.Memishian@Sun.COM
10198485SPeter.Memishian@Sun.COM for (i = 0; i < targlistp->al_naddr; i++) {
10208485SPeter.Memishian@Sun.COM sockaddr2str(&targlistp->al_addrs[i], targname, bufsize);
10218485SPeter.Memishian@Sun.COM (void) strlcat(buf, targname, bufsize);
10228485SPeter.Memishian@Sun.COM if ((i + 1) < targlistp->al_naddr)
10238485SPeter.Memishian@Sun.COM (void) strlcat(buf, " ", bufsize);
10248485SPeter.Memishian@Sun.COM }
1025*9071SSowmini.Varadhan@Sun.COM return (B_TRUE);
10268485SPeter.Memishian@Sun.COM }
10278485SPeter.Memishian@Sun.COM
10288485SPeter.Memishian@Sun.COM static void
info_output_cbfunc(ipmp_handle_t ih,void * infop,void * arg)10298485SPeter.Memishian@Sun.COM info_output_cbfunc(ipmp_handle_t ih, void *infop, void *arg)
10308485SPeter.Memishian@Sun.COM {
10318485SPeter.Memishian@Sun.COM ofmt_output(arg, ih, infop);
10328485SPeter.Memishian@Sun.COM }
10338485SPeter.Memishian@Sun.COM
10348485SPeter.Memishian@Sun.COM static void
targinfo_output_cbfunc(ipmp_handle_t ih,void * infop,void * arg)10358485SPeter.Memishian@Sun.COM targinfo_output_cbfunc(ipmp_handle_t ih, void *infop, void *arg)
10368485SPeter.Memishian@Sun.COM {
10378485SPeter.Memishian@Sun.COM ipmp_ifinfo_t *ifinfop = infop;
10388485SPeter.Memishian@Sun.COM ipmp_if_targmode_t targmode4 = ifinfop->if_targinfo4.it_targmode;
10398485SPeter.Memishian@Sun.COM ipmp_if_targmode_t targmode6 = ifinfop->if_targinfo6.it_targmode;
10408485SPeter.Memishian@Sun.COM
10418485SPeter.Memishian@Sun.COM /*
10428485SPeter.Memishian@Sun.COM * Usually, either IPv4 or IPv6 probing will be enabled, but the admin
10438485SPeter.Memishian@Sun.COM * may enable both. If only one is enabled, omit the other one so as
10448485SPeter.Memishian@Sun.COM * to not encourage the admin to enable both. If neither is enabled,
10458485SPeter.Memishian@Sun.COM * we still print one just so the admin can see a MODE of "disabled".
10468485SPeter.Memishian@Sun.COM */
10478485SPeter.Memishian@Sun.COM if (targmode4 != IPMP_TARG_DISABLED || targmode6 == IPMP_TARG_DISABLED)
10488485SPeter.Memishian@Sun.COM ofmt_output(arg, ih, &ifinfop->if_targinfo4);
10498485SPeter.Memishian@Sun.COM if (targmode6 != IPMP_TARG_DISABLED)
10508485SPeter.Memishian@Sun.COM ofmt_output(arg, ih, &ifinfop->if_targinfo6);
10518485SPeter.Memishian@Sun.COM }
10528485SPeter.Memishian@Sun.COM
10538485SPeter.Memishian@Sun.COM /*
1054*9071SSowmini.Varadhan@Sun.COM * Outputs one row of values. The values to output are obtained through the
1055*9071SSowmini.Varadhan@Sun.COM * callback function pointers. The actual values are computed from the `ih'
1056*9071SSowmini.Varadhan@Sun.COM * and `arg' structures passed to the callback function.
10578485SPeter.Memishian@Sun.COM */
10588485SPeter.Memishian@Sun.COM static void
ofmt_output(const ofmt_handle_t ofmt,ipmp_handle_t ih,void * arg)1059*9071SSowmini.Varadhan@Sun.COM ofmt_output(const ofmt_handle_t ofmt, ipmp_handle_t ih, void *arg)
10608485SPeter.Memishian@Sun.COM {
1061*9071SSowmini.Varadhan@Sun.COM ipmpstat_sfunc_arg_t sfunc_arg;
10628485SPeter.Memishian@Sun.COM
1063*9071SSowmini.Varadhan@Sun.COM sfunc_arg.sa_ih = ih;
1064*9071SSowmini.Varadhan@Sun.COM sfunc_arg.sa_data = arg;
1065*9071SSowmini.Varadhan@Sun.COM ofmt_print(ofmt, &sfunc_arg);
10668485SPeter.Memishian@Sun.COM }
10678485SPeter.Memishian@Sun.COM
10688485SPeter.Memishian@Sun.COM /*
10698485SPeter.Memishian@Sun.COM * Uses `enums' to map `enumval' to a string, and stores at most `bufsize'
10708485SPeter.Memishian@Sun.COM * bytes of that string into `buf'.
10718485SPeter.Memishian@Sun.COM */
10728485SPeter.Memishian@Sun.COM static void
enum2str(const ipmpstat_enum_t * enums,int enumval,char * buf,uint_t bufsize)10738485SPeter.Memishian@Sun.COM enum2str(const ipmpstat_enum_t *enums, int enumval, char *buf, uint_t bufsize)
10748485SPeter.Memishian@Sun.COM {
10758485SPeter.Memishian@Sun.COM const ipmpstat_enum_t *enump;
10768485SPeter.Memishian@Sun.COM
10778485SPeter.Memishian@Sun.COM for (enump = enums; enump->e_name != NULL; enump++) {
10788485SPeter.Memishian@Sun.COM if (enump->e_val == enumval) {
10798485SPeter.Memishian@Sun.COM (void) strlcpy(buf, enump->e_name, bufsize);
10808485SPeter.Memishian@Sun.COM return;
10818485SPeter.Memishian@Sun.COM }
10828485SPeter.Memishian@Sun.COM }
10838485SPeter.Memishian@Sun.COM (void) snprintf(buf, bufsize, "<%d>", enumval);
10848485SPeter.Memishian@Sun.COM }
10858485SPeter.Memishian@Sun.COM
10868485SPeter.Memishian@Sun.COM /*
10878485SPeter.Memishian@Sun.COM * Stores the stringified value of the sockaddr_storage pointed to by `ssp'
10888485SPeter.Memishian@Sun.COM * into at most `bufsize' bytes of `buf'.
10898485SPeter.Memishian@Sun.COM */
10908485SPeter.Memishian@Sun.COM static void
sockaddr2str(const struct sockaddr_storage * ssp,char * buf,uint_t bufsize)10918485SPeter.Memishian@Sun.COM sockaddr2str(const struct sockaddr_storage *ssp, char *buf, uint_t bufsize)
10928485SPeter.Memishian@Sun.COM {
10938485SPeter.Memishian@Sun.COM int flags = NI_NOFQDN;
10948485SPeter.Memishian@Sun.COM socklen_t socklen;
10958485SPeter.Memishian@Sun.COM struct sockaddr *sp = (struct sockaddr *)ssp;
10968485SPeter.Memishian@Sun.COM
10978485SPeter.Memishian@Sun.COM /*
10988485SPeter.Memishian@Sun.COM * Sadly, getnameinfo() does not allow the socklen to be oversized for
10998485SPeter.Memishian@Sun.COM * a given family -- so we must determine the exact size to pass to it.
11008485SPeter.Memishian@Sun.COM */
11018485SPeter.Memishian@Sun.COM switch (ssp->ss_family) {
11028485SPeter.Memishian@Sun.COM case AF_INET:
11038485SPeter.Memishian@Sun.COM socklen = sizeof (struct sockaddr_in);
11048485SPeter.Memishian@Sun.COM break;
11058485SPeter.Memishian@Sun.COM case AF_INET6:
11068485SPeter.Memishian@Sun.COM socklen = sizeof (struct sockaddr_in6);
11078485SPeter.Memishian@Sun.COM break;
11088485SPeter.Memishian@Sun.COM default:
11098485SPeter.Memishian@Sun.COM (void) strlcpy(buf, "?", bufsize);
11108485SPeter.Memishian@Sun.COM return;
11118485SPeter.Memishian@Sun.COM }
11128485SPeter.Memishian@Sun.COM
11138485SPeter.Memishian@Sun.COM if (opt & IPMPSTAT_OPT_NUMERIC)
11148485SPeter.Memishian@Sun.COM flags |= NI_NUMERICHOST;
11158485SPeter.Memishian@Sun.COM
11168485SPeter.Memishian@Sun.COM (void) getnameinfo(sp, socklen, buf, bufsize, NULL, 0, flags);
11178485SPeter.Memishian@Sun.COM }
11188485SPeter.Memishian@Sun.COM
11198485SPeter.Memishian@Sun.COM static void
sighandler(int sig)11208485SPeter.Memishian@Sun.COM sighandler(int sig)
11218485SPeter.Memishian@Sun.COM {
11228485SPeter.Memishian@Sun.COM assert(sig == SIGWINCH);
11238485SPeter.Memishian@Sun.COM
1124*9071SSowmini.Varadhan@Sun.COM ofmt_update_winsize(ofmt);
11258485SPeter.Memishian@Sun.COM }
11268485SPeter.Memishian@Sun.COM
11278485SPeter.Memishian@Sun.COM static void
usage(void)11288485SPeter.Memishian@Sun.COM usage(void)
11298485SPeter.Memishian@Sun.COM {
11308485SPeter.Memishian@Sun.COM const char *argstr = gettext("[-n] [-o <field> [-P]] -a|-g|-i|-p|-t");
11318485SPeter.Memishian@Sun.COM
11328485SPeter.Memishian@Sun.COM (void) fprintf(stderr, gettext("usage: %s %s\n"), progname, argstr);
11338755SPeter.Memishian@Sun.COM (void) fprintf(stderr, gettext("\n"
11348755SPeter.Memishian@Sun.COM " output modes:\t -a display IPMP data address information\n"
11358755SPeter.Memishian@Sun.COM "\t\t -g display IPMP group information\n"
11368755SPeter.Memishian@Sun.COM "\t\t -i display IPMP-related IP interface information\n"
11378755SPeter.Memishian@Sun.COM "\t\t -p display IPMP probe information\n"
11388755SPeter.Memishian@Sun.COM "\t\t -t display IPMP target information\n\n"
11398755SPeter.Memishian@Sun.COM " options:\t -n display IP addresses numerically\n"
11408755SPeter.Memishian@Sun.COM "\t\t -o display only the specified fields, in order\n"
11418755SPeter.Memishian@Sun.COM "\t\t -P display using parsable output mode\n"));
11428755SPeter.Memishian@Sun.COM
11438485SPeter.Memishian@Sun.COM exit(EXIT_FAILURE);
11448485SPeter.Memishian@Sun.COM }
11458485SPeter.Memishian@Sun.COM
11468485SPeter.Memishian@Sun.COM /* PRINTFLIKE1 */
11478485SPeter.Memishian@Sun.COM static void
warn(const char * format,...)11488485SPeter.Memishian@Sun.COM warn(const char *format, ...)
11498485SPeter.Memishian@Sun.COM {
11508485SPeter.Memishian@Sun.COM va_list alist;
11518485SPeter.Memishian@Sun.COM int error = errno;
11528485SPeter.Memishian@Sun.COM
11538485SPeter.Memishian@Sun.COM format = gettext(format);
11548485SPeter.Memishian@Sun.COM (void) fprintf(stderr, gettext("%s: warning: "), progname);
11558485SPeter.Memishian@Sun.COM
11568485SPeter.Memishian@Sun.COM va_start(alist, format);
11578485SPeter.Memishian@Sun.COM (void) vfprintf(stderr, format, alist);
11588485SPeter.Memishian@Sun.COM va_end(alist);
11598485SPeter.Memishian@Sun.COM
11608485SPeter.Memishian@Sun.COM if (strchr(format, '\n') == NULL)
11618485SPeter.Memishian@Sun.COM (void) fprintf(stderr, ": %s\n", strerror(error));
11628485SPeter.Memishian@Sun.COM }
11638485SPeter.Memishian@Sun.COM
11648485SPeter.Memishian@Sun.COM /* PRINTFLIKE2 */
11658485SPeter.Memishian@Sun.COM static void
warn_ipmperr(int ipmperr,const char * format,...)11668485SPeter.Memishian@Sun.COM warn_ipmperr(int ipmperr, const char *format, ...)
11678485SPeter.Memishian@Sun.COM {
11688485SPeter.Memishian@Sun.COM va_list alist;
11698485SPeter.Memishian@Sun.COM
11708485SPeter.Memishian@Sun.COM format = gettext(format);
11718485SPeter.Memishian@Sun.COM (void) fprintf(stderr, gettext("%s: warning: "), progname);
11728485SPeter.Memishian@Sun.COM
11738485SPeter.Memishian@Sun.COM va_start(alist, format);
11748485SPeter.Memishian@Sun.COM (void) vfprintf(stderr, format, alist);
11758485SPeter.Memishian@Sun.COM va_end(alist);
11768485SPeter.Memishian@Sun.COM
11778485SPeter.Memishian@Sun.COM (void) fprintf(stderr, ": %s\n", ipmp_errmsg(ipmperr));
11788485SPeter.Memishian@Sun.COM }
11798485SPeter.Memishian@Sun.COM
11808485SPeter.Memishian@Sun.COM /* PRINTFLIKE1 */
11818485SPeter.Memishian@Sun.COM static void
die(const char * format,...)11828485SPeter.Memishian@Sun.COM die(const char *format, ...)
11838485SPeter.Memishian@Sun.COM {
11848485SPeter.Memishian@Sun.COM va_list alist;
11858485SPeter.Memishian@Sun.COM int error = errno;
11868485SPeter.Memishian@Sun.COM
11878485SPeter.Memishian@Sun.COM format = gettext(format);
11888485SPeter.Memishian@Sun.COM (void) fprintf(stderr, "%s: ", progname);
11898485SPeter.Memishian@Sun.COM
11908485SPeter.Memishian@Sun.COM va_start(alist, format);
11918485SPeter.Memishian@Sun.COM (void) vfprintf(stderr, format, alist);
11928485SPeter.Memishian@Sun.COM va_end(alist);
11938485SPeter.Memishian@Sun.COM
11948485SPeter.Memishian@Sun.COM if (strchr(format, '\n') == NULL)
11958485SPeter.Memishian@Sun.COM (void) fprintf(stderr, ": %s\n", strerror(error));
11968485SPeter.Memishian@Sun.COM
11978485SPeter.Memishian@Sun.COM exit(EXIT_FAILURE);
11988485SPeter.Memishian@Sun.COM }
11998485SPeter.Memishian@Sun.COM
12008485SPeter.Memishian@Sun.COM /* PRINTFLIKE2 */
12018485SPeter.Memishian@Sun.COM static void
die_ipmperr(int ipmperr,const char * format,...)12028485SPeter.Memishian@Sun.COM die_ipmperr(int ipmperr, const char *format, ...)
12038485SPeter.Memishian@Sun.COM {
12048485SPeter.Memishian@Sun.COM va_list alist;
12058485SPeter.Memishian@Sun.COM
12068485SPeter.Memishian@Sun.COM format = gettext(format);
12078485SPeter.Memishian@Sun.COM (void) fprintf(stderr, "%s: ", progname);
12088485SPeter.Memishian@Sun.COM
12098485SPeter.Memishian@Sun.COM va_start(alist, format);
12108485SPeter.Memishian@Sun.COM (void) vfprintf(stderr, format, alist);
12118485SPeter.Memishian@Sun.COM va_end(alist);
12128485SPeter.Memishian@Sun.COM (void) fprintf(stderr, ": %s\n", ipmp_errmsg(ipmperr));
12138485SPeter.Memishian@Sun.COM
12148485SPeter.Memishian@Sun.COM exit(EXIT_FAILURE);
12158485SPeter.Memishian@Sun.COM }
12168485SPeter.Memishian@Sun.COM
1217*9071SSowmini.Varadhan@Sun.COM static ofmt_field_t addr_fields[] = {
1218*9071SSowmini.Varadhan@Sun.COM { "ADDRESS", 26, 0, sfunc_addr_address },
1219*9071SSowmini.Varadhan@Sun.COM { "STATE", 7, 0, sfunc_addr_state },
1220*9071SSowmini.Varadhan@Sun.COM { "GROUP", 12, 0, sfunc_addr_group },
1221*9071SSowmini.Varadhan@Sun.COM { "INBOUND", 12, 0, sfunc_addr_inbound },
1222*9071SSowmini.Varadhan@Sun.COM { "OUTBOUND", 23, 0, sfunc_addr_outbound },
1223*9071SSowmini.Varadhan@Sun.COM { NULL, 0, 0, NULL }
12248485SPeter.Memishian@Sun.COM };
12258485SPeter.Memishian@Sun.COM
1226*9071SSowmini.Varadhan@Sun.COM static ofmt_field_t group_fields[] = {
1227*9071SSowmini.Varadhan@Sun.COM { "GROUP", 12, 0, sfunc_group_ifname },
1228*9071SSowmini.Varadhan@Sun.COM { "GROUPNAME", 12, 0, sfunc_group_name },
1229*9071SSowmini.Varadhan@Sun.COM { "STATE", 10, 0, sfunc_group_state },
1230*9071SSowmini.Varadhan@Sun.COM { "FDT", 10, 0, sfunc_group_fdt },
1231*9071SSowmini.Varadhan@Sun.COM { "INTERFACES", 30, 0, sfunc_group_interfaces },
1232*9071SSowmini.Varadhan@Sun.COM { NULL, 0, 0, NULL }
12338485SPeter.Memishian@Sun.COM };
12348485SPeter.Memishian@Sun.COM
1235*9071SSowmini.Varadhan@Sun.COM static ofmt_field_t if_fields[] = {
1236*9071SSowmini.Varadhan@Sun.COM { "INTERFACE", 12, 0, sfunc_if_name },
1237*9071SSowmini.Varadhan@Sun.COM { "ACTIVE", 8, 0, sfunc_if_active },
1238*9071SSowmini.Varadhan@Sun.COM { "GROUP", 12, 0, sfunc_if_group },
1239*9071SSowmini.Varadhan@Sun.COM { "FLAGS", 10, 0, sfunc_if_flags },
1240*9071SSowmini.Varadhan@Sun.COM { "LINK", 10, 0, sfunc_if_link },
1241*9071SSowmini.Varadhan@Sun.COM { "PROBE", 10, 0, sfunc_if_probe },
1242*9071SSowmini.Varadhan@Sun.COM { "STATE", 10, 0, sfunc_if_state },
1243*9071SSowmini.Varadhan@Sun.COM { NULL, 0, 0, NULL }
12448485SPeter.Memishian@Sun.COM };
12458485SPeter.Memishian@Sun.COM
1246*9071SSowmini.Varadhan@Sun.COM static ofmt_field_t probe_fields[] = {
1247*9071SSowmini.Varadhan@Sun.COM { "TIME", 10, 0, sfunc_probe_time },
1248*9071SSowmini.Varadhan@Sun.COM { "INTERFACE", 12, 0, sfunc_probe_ifname },
1249*9071SSowmini.Varadhan@Sun.COM { "PROBE", 7, 0, sfunc_probe_id },
1250*9071SSowmini.Varadhan@Sun.COM { "NETRTT", 10, 0, sfunc_probe_netrtt },
1251*9071SSowmini.Varadhan@Sun.COM { "RTT", 10, 0, sfunc_probe_rtt },
1252*9071SSowmini.Varadhan@Sun.COM { "RTTAVG", 10, 0, sfunc_probe_rttavg },
1253*9071SSowmini.Varadhan@Sun.COM { "TARGET", 20, 0, sfunc_probe_target },
1254*9071SSowmini.Varadhan@Sun.COM { "RTTDEV", 10, 0, sfunc_probe_rttdev },
1255*9071SSowmini.Varadhan@Sun.COM { NULL, 0, 0, NULL }
12568485SPeter.Memishian@Sun.COM };
12578485SPeter.Memishian@Sun.COM
1258*9071SSowmini.Varadhan@Sun.COM static ofmt_field_t targ_fields[] = {
1259*9071SSowmini.Varadhan@Sun.COM { "INTERFACE", 12, 0, sfunc_targ_ifname },
1260*9071SSowmini.Varadhan@Sun.COM { "MODE", 10, 0, sfunc_targ_mode },
1261*9071SSowmini.Varadhan@Sun.COM { "TESTADDR", 20, 0, sfunc_targ_testaddr },
1262*9071SSowmini.Varadhan@Sun.COM { "TARGETS", 38, 0, sfunc_targ_targets },
1263*9071SSowmini.Varadhan@Sun.COM { NULL, 0, 0, NULL }
12648485SPeter.Memishian@Sun.COM };
12658485SPeter.Memishian@Sun.COM
12668485SPeter.Memishian@Sun.COM static ipmpstat_enum_t addr_state[] = {
1267*9071SSowmini.Varadhan@Sun.COM { "up", IPMP_ADDR_UP },
1268*9071SSowmini.Varadhan@Sun.COM { "down", IPMP_ADDR_DOWN },
1269*9071SSowmini.Varadhan@Sun.COM { NULL, 0 }
12708485SPeter.Memishian@Sun.COM };
12718485SPeter.Memishian@Sun.COM
12728485SPeter.Memishian@Sun.COM static ipmpstat_enum_t group_state[] = {
1273*9071SSowmini.Varadhan@Sun.COM { "ok", IPMP_GROUP_OK },
1274*9071SSowmini.Varadhan@Sun.COM { "failed", IPMP_GROUP_FAILED },
1275*9071SSowmini.Varadhan@Sun.COM { "degraded", IPMP_GROUP_DEGRADED },
1276*9071SSowmini.Varadhan@Sun.COM { NULL, 0 }
12778485SPeter.Memishian@Sun.COM };
12788485SPeter.Memishian@Sun.COM
12798485SPeter.Memishian@Sun.COM static ipmpstat_enum_t if_link[] = {
1280*9071SSowmini.Varadhan@Sun.COM { "up", IPMP_LINK_UP },
1281*9071SSowmini.Varadhan@Sun.COM { "down", IPMP_LINK_DOWN },
1282*9071SSowmini.Varadhan@Sun.COM { "unknown", IPMP_LINK_UNKNOWN },
1283*9071SSowmini.Varadhan@Sun.COM { NULL, 0 }
12848485SPeter.Memishian@Sun.COM };
12858485SPeter.Memishian@Sun.COM
12868485SPeter.Memishian@Sun.COM static ipmpstat_enum_t if_probe[] = {
1287*9071SSowmini.Varadhan@Sun.COM { "ok", IPMP_PROBE_OK },
1288*9071SSowmini.Varadhan@Sun.COM { "failed", IPMP_PROBE_FAILED },
1289*9071SSowmini.Varadhan@Sun.COM { "unknown", IPMP_PROBE_UNKNOWN },
1290*9071SSowmini.Varadhan@Sun.COM { "disabled", IPMP_PROBE_DISABLED },
1291*9071SSowmini.Varadhan@Sun.COM { NULL, 0 }
12928485SPeter.Memishian@Sun.COM };
12938485SPeter.Memishian@Sun.COM
12948485SPeter.Memishian@Sun.COM static ipmpstat_enum_t if_state[] = {
1295*9071SSowmini.Varadhan@Sun.COM { "ok", IPMP_IF_OK },
1296*9071SSowmini.Varadhan@Sun.COM { "failed", IPMP_IF_FAILED },
1297*9071SSowmini.Varadhan@Sun.COM { "unknown", IPMP_IF_UNKNOWN },
1298*9071SSowmini.Varadhan@Sun.COM { "offline", IPMP_IF_OFFLINE },
1299*9071SSowmini.Varadhan@Sun.COM { NULL, 0 }
13008485SPeter.Memishian@Sun.COM };
13018485SPeter.Memishian@Sun.COM
13028485SPeter.Memishian@Sun.COM static ipmpstat_enum_t targ_mode[] = {
1303*9071SSowmini.Varadhan@Sun.COM { "disabled", IPMP_TARG_DISABLED },
1304*9071SSowmini.Varadhan@Sun.COM { "routes", IPMP_TARG_ROUTES },
1305*9071SSowmini.Varadhan@Sun.COM { "multicast", IPMP_TARG_MULTICAST },
1306*9071SSowmini.Varadhan@Sun.COM { NULL, 0 }
13078485SPeter.Memishian@Sun.COM };
1308