17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5*d62bc4baSyz147064 * Common Development and Distribution License (the "License").
6*d62bc4baSyz147064 * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
217c478bd9Sstevel@tonic-gate /*
22*d62bc4baSyz147064 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
237c478bd9Sstevel@tonic-gate * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate */
257c478bd9Sstevel@tonic-gate
267c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
277c478bd9Sstevel@tonic-gate
287c478bd9Sstevel@tonic-gate /*
297c478bd9Sstevel@tonic-gate * rstat service: built with rstat.x
307c478bd9Sstevel@tonic-gate */
317c478bd9Sstevel@tonic-gate
327c478bd9Sstevel@tonic-gate #include <stdio.h>
337c478bd9Sstevel@tonic-gate #include <stdlib.h>
347c478bd9Sstevel@tonic-gate #include <stdarg.h>
357c478bd9Sstevel@tonic-gate #include <string.h>
367c478bd9Sstevel@tonic-gate #include <signal.h>
377c478bd9Sstevel@tonic-gate #include <utmpx.h>
387c478bd9Sstevel@tonic-gate #include <nlist.h>
397c478bd9Sstevel@tonic-gate #include <fcntl.h>
407c478bd9Sstevel@tonic-gate #include <syslog.h>
417c478bd9Sstevel@tonic-gate #include <kstat.h>
427c478bd9Sstevel@tonic-gate
437c478bd9Sstevel@tonic-gate #include <rpc/rpc.h>
447c478bd9Sstevel@tonic-gate
457c478bd9Sstevel@tonic-gate #include <sys/socket.h>
467c478bd9Sstevel@tonic-gate #include <sys/cpuvar.h>
477c478bd9Sstevel@tonic-gate #include <sys/sysinfo.h>
487c478bd9Sstevel@tonic-gate #include <sys/systm.h>
497c478bd9Sstevel@tonic-gate #include <errno.h>
507c478bd9Sstevel@tonic-gate #include <sys/stropts.h>
517c478bd9Sstevel@tonic-gate #include <sys/tihdr.h>
527c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h>
537c478bd9Sstevel@tonic-gate
547c478bd9Sstevel@tonic-gate #include <net/if.h>
557c478bd9Sstevel@tonic-gate #include <inet/mib2.h>
567c478bd9Sstevel@tonic-gate
577c478bd9Sstevel@tonic-gate #include "rstat.h"
587c478bd9Sstevel@tonic-gate #include "rstat_v2.h"
597c478bd9Sstevel@tonic-gate
607c478bd9Sstevel@tonic-gate typedef struct {
617c478bd9Sstevel@tonic-gate kstat_t sys;
627c478bd9Sstevel@tonic-gate kstat_t vm;
637c478bd9Sstevel@tonic-gate } _cpu_stats_t;
647c478bd9Sstevel@tonic-gate
657c478bd9Sstevel@tonic-gate /*
667c478bd9Sstevel@tonic-gate * system and cpu stats
677c478bd9Sstevel@tonic-gate */
687c478bd9Sstevel@tonic-gate static kstat_ctl_t *kc; /* libkstat cookie */
697c478bd9Sstevel@tonic-gate static int ncpus;
707c478bd9Sstevel@tonic-gate static _cpu_stats_t *cpu_stats_list = NULL;
717c478bd9Sstevel@tonic-gate static kstat_t *system_misc_ksp;
727c478bd9Sstevel@tonic-gate static kstat_named_t *boot_time_knp;
737c478bd9Sstevel@tonic-gate static kstat_named_t *avenrun_1min_knp, *avenrun_5min_knp, *avenrun_15min_knp;
747c478bd9Sstevel@tonic-gate static int hz;
757c478bd9Sstevel@tonic-gate static struct timeval btm; /* boottime */
767c478bd9Sstevel@tonic-gate
777c478bd9Sstevel@tonic-gate /*
787c478bd9Sstevel@tonic-gate * network interface stats
797c478bd9Sstevel@tonic-gate */
807c478bd9Sstevel@tonic-gate
817c478bd9Sstevel@tonic-gate typedef struct mib_item_s {
827c478bd9Sstevel@tonic-gate struct mib_item_s *next_item;
837c478bd9Sstevel@tonic-gate long group;
847c478bd9Sstevel@tonic-gate long mib_id;
857c478bd9Sstevel@tonic-gate long length;
867c478bd9Sstevel@tonic-gate char *valp;
877c478bd9Sstevel@tonic-gate } mib_item_t;
887c478bd9Sstevel@tonic-gate
897c478bd9Sstevel@tonic-gate mib_item_t *netstat_item;
907c478bd9Sstevel@tonic-gate
917c478bd9Sstevel@tonic-gate /*
927c478bd9Sstevel@tonic-gate * disk stats
937c478bd9Sstevel@tonic-gate */
947c478bd9Sstevel@tonic-gate
957c478bd9Sstevel@tonic-gate struct diskinfo {
967c478bd9Sstevel@tonic-gate struct diskinfo *next;
977c478bd9Sstevel@tonic-gate kstat_t *ks;
987c478bd9Sstevel@tonic-gate kstat_io_t kios;
997c478bd9Sstevel@tonic-gate };
1007c478bd9Sstevel@tonic-gate
1017c478bd9Sstevel@tonic-gate #define NULLDISK (struct diskinfo *)0
1027c478bd9Sstevel@tonic-gate static struct diskinfo zerodisk = { NULL, NULL };
1037c478bd9Sstevel@tonic-gate static struct diskinfo *firstdisk = NULLDISK;
1047c478bd9Sstevel@tonic-gate static struct diskinfo *lastdisk = NULLDISK;
1057c478bd9Sstevel@tonic-gate static struct diskinfo *snip = NULLDISK;
1067c478bd9Sstevel@tonic-gate static int ndisks;
1077c478bd9Sstevel@tonic-gate
1087c478bd9Sstevel@tonic-gate /*
1097c478bd9Sstevel@tonic-gate * net stats
1107c478bd9Sstevel@tonic-gate */
1117c478bd9Sstevel@tonic-gate
1127c478bd9Sstevel@tonic-gate struct netinfo {
1137c478bd9Sstevel@tonic-gate struct netinfo *next;
1147c478bd9Sstevel@tonic-gate kstat_t *ks;
1157c478bd9Sstevel@tonic-gate kstat_named_t *ipackets;
1167c478bd9Sstevel@tonic-gate kstat_named_t *opackets;
1177c478bd9Sstevel@tonic-gate kstat_named_t *ierrors;
1187c478bd9Sstevel@tonic-gate kstat_named_t *oerrors;
1197c478bd9Sstevel@tonic-gate kstat_named_t *collisions;
1207c478bd9Sstevel@tonic-gate };
1217c478bd9Sstevel@tonic-gate
1227c478bd9Sstevel@tonic-gate #define NULLNET (struct netinfo *)0
1237c478bd9Sstevel@tonic-gate static struct netinfo zeronet = { NULL, NULL, NULL, NULL, NULL, NULL, NULL };
1247c478bd9Sstevel@tonic-gate static struct netinfo *firstnet = NULLNET;
1257c478bd9Sstevel@tonic-gate static struct netinfo *lastnet = NULLNET;
1267c478bd9Sstevel@tonic-gate static struct netinfo *netsnip = NULLNET;
1277c478bd9Sstevel@tonic-gate static int nnets;
1287c478bd9Sstevel@tonic-gate
1297c478bd9Sstevel@tonic-gate /*
1307c478bd9Sstevel@tonic-gate * Define EXIT_WHEN_IDLE if you are able to have this program invoked
1317c478bd9Sstevel@tonic-gate * automatically on demand (as from inetd). When defined, the service
1327c478bd9Sstevel@tonic-gate * will terminated after being idle for 120 seconds.
1337c478bd9Sstevel@tonic-gate */
1347c478bd9Sstevel@tonic-gate
1357c478bd9Sstevel@tonic-gate #define EXIT_WHEN_IDLE 1
1367c478bd9Sstevel@tonic-gate
1377c478bd9Sstevel@tonic-gate int sincelastreq = 0; /* number of alarms since last request */
1387c478bd9Sstevel@tonic-gate #ifdef EXIT_WHEN_IDLE
1397c478bd9Sstevel@tonic-gate #define CLOSEDOWN 120 /* how long to wait before exiting */
1407c478bd9Sstevel@tonic-gate #endif /* def EXIT_WHEN_IDLE */
1417c478bd9Sstevel@tonic-gate
1427c478bd9Sstevel@tonic-gate statstime stats_s3;
1437c478bd9Sstevel@tonic-gate statsvar stats_s4;
1447c478bd9Sstevel@tonic-gate /* V2 support for backwards compatibility to pre-5.0 systems */
1457c478bd9Sstevel@tonic-gate statsswtch stats_s2;
1467c478bd9Sstevel@tonic-gate
14749e7ca49Speteh static int stat_is_init = 0;
1487c478bd9Sstevel@tonic-gate
1497c478bd9Sstevel@tonic-gate static void fail(int, char *, ...);
1507c478bd9Sstevel@tonic-gate static void safe_zalloc(void **, int, int);
1517c478bd9Sstevel@tonic-gate static kid_t safe_kstat_read(kstat_ctl_t *, kstat_t *, void *);
1527c478bd9Sstevel@tonic-gate static kstat_t *safe_kstat_lookup(kstat_ctl_t *, char *, int, char *);
1537c478bd9Sstevel@tonic-gate static void *safe_kstat_data_lookup(kstat_t *, char *);
1547c478bd9Sstevel@tonic-gate static void system_stat_init(void);
1557c478bd9Sstevel@tonic-gate static int system_stat_load(void);
1567c478bd9Sstevel@tonic-gate static void init_disks(void);
1577c478bd9Sstevel@tonic-gate static int diskinfo_load(void);
1587c478bd9Sstevel@tonic-gate static void init_net(void);
1597c478bd9Sstevel@tonic-gate static int netinfo_load(void);
1607c478bd9Sstevel@tonic-gate
1617c478bd9Sstevel@tonic-gate static void updatestat(int);
1627c478bd9Sstevel@tonic-gate
1637c478bd9Sstevel@tonic-gate static mib_item_t *mibget(int sd);
1647c478bd9Sstevel@tonic-gate static int mibopen(void);
1657c478bd9Sstevel@tonic-gate static char *octetstr(char *buf, Octet_t *op, int code);
1667c478bd9Sstevel@tonic-gate
1677c478bd9Sstevel@tonic-gate static void kstat_copy(kstat_t *, kstat_t *, int);
1687c478bd9Sstevel@tonic-gate
1697c478bd9Sstevel@tonic-gate static char *cmdname = "rpc.rstatd";
1707c478bd9Sstevel@tonic-gate
1717c478bd9Sstevel@tonic-gate #define CPU_STAT(ksp, name) (((kstat_named_t *)safe_kstat_data_lookup( \
1727c478bd9Sstevel@tonic-gate (ksp), (name)))->value.ui64)
1737c478bd9Sstevel@tonic-gate static _cpu_stats_t cpu_stats_all = { 0 };
1747c478bd9Sstevel@tonic-gate
1757c478bd9Sstevel@tonic-gate static void
stat_init(void)1767c478bd9Sstevel@tonic-gate stat_init(void)
1777c478bd9Sstevel@tonic-gate {
1787c478bd9Sstevel@tonic-gate struct utmpx *utmpx, utmpx_id;
1797c478bd9Sstevel@tonic-gate
1807c478bd9Sstevel@tonic-gate stat_is_init = 1;
1817c478bd9Sstevel@tonic-gate
1827c478bd9Sstevel@tonic-gate if ((kc = kstat_open()) == NULL)
1837c478bd9Sstevel@tonic-gate fail(1, "kstat_open(): can't open /dev/kstat");
1847c478bd9Sstevel@tonic-gate
1857c478bd9Sstevel@tonic-gate /*
1867c478bd9Sstevel@tonic-gate * Preallocate minimal set of drive entries.
1877c478bd9Sstevel@tonic-gate */
1887c478bd9Sstevel@tonic-gate
1897c478bd9Sstevel@tonic-gate if (stats_s4.dk_xfer.dk_xfer_val == NULL) {
1907c478bd9Sstevel@tonic-gate stats_s4.dk_xfer.dk_xfer_len = RSTAT_DK_NDRIVE;
1917c478bd9Sstevel@tonic-gate stats_s4.dk_xfer.dk_xfer_val =
1927c478bd9Sstevel@tonic-gate (int *)calloc(RSTAT_DK_NDRIVE, sizeof (int));
1937c478bd9Sstevel@tonic-gate }
1947c478bd9Sstevel@tonic-gate
1957c478bd9Sstevel@tonic-gate system_stat_init();
1967c478bd9Sstevel@tonic-gate init_disks();
1977c478bd9Sstevel@tonic-gate init_net();
1987c478bd9Sstevel@tonic-gate
1997c478bd9Sstevel@tonic-gate /*
2007c478bd9Sstevel@tonic-gate * To get the boot time, use utmpx, which is per-zone, but fall back
2017c478bd9Sstevel@tonic-gate * to the system-wide kstat if utmpx is hosed for any reason.
2027c478bd9Sstevel@tonic-gate */
2037c478bd9Sstevel@tonic-gate utmpx_id.ut_type = BOOT_TIME;
2047c478bd9Sstevel@tonic-gate if ((utmpx = getutxid(&utmpx_id)) != NULL)
2057c478bd9Sstevel@tonic-gate btm = utmpx->ut_tv;
2067c478bd9Sstevel@tonic-gate else {
2077c478bd9Sstevel@tonic-gate btm.tv_sec = boot_time_knp->value.ul;
2087c478bd9Sstevel@tonic-gate btm.tv_usec = 0; /* don't bother with usecs for boot time */
2097c478bd9Sstevel@tonic-gate }
2107c478bd9Sstevel@tonic-gate endutxent();
2117c478bd9Sstevel@tonic-gate stats_s4.boottime.tv_sec =
2127c478bd9Sstevel@tonic-gate stats_s2.boottime.tv_sec =
2137c478bd9Sstevel@tonic-gate stats_s3.boottime.tv_sec = btm.tv_sec;
2147c478bd9Sstevel@tonic-gate stats_s4.boottime.tv_usec =
2157c478bd9Sstevel@tonic-gate stats_s2.boottime.tv_usec =
2167c478bd9Sstevel@tonic-gate stats_s3.boottime.tv_usec = btm.tv_usec;
2177c478bd9Sstevel@tonic-gate
2187c478bd9Sstevel@tonic-gate updatestat(0);
2197c478bd9Sstevel@tonic-gate alarm(1);
2207c478bd9Sstevel@tonic-gate signal(SIGALRM, updatestat);
2217c478bd9Sstevel@tonic-gate sleep(2); /* allow for one wake-up */
2227c478bd9Sstevel@tonic-gate }
2237c478bd9Sstevel@tonic-gate
2247c478bd9Sstevel@tonic-gate statsvar *
rstatproc_stats_4_svc(argp,svcrq)2257c478bd9Sstevel@tonic-gate rstatproc_stats_4_svc(argp, svcrq)
2267c478bd9Sstevel@tonic-gate void *argp;
2277c478bd9Sstevel@tonic-gate struct svc_req *svcrq;
2287c478bd9Sstevel@tonic-gate {
2297c478bd9Sstevel@tonic-gate if (! stat_is_init)
2307c478bd9Sstevel@tonic-gate stat_init();
2317c478bd9Sstevel@tonic-gate #ifdef EXIT_WHEN_IDLE
2327c478bd9Sstevel@tonic-gate sincelastreq = 0;
2337c478bd9Sstevel@tonic-gate #endif
2347c478bd9Sstevel@tonic-gate return (&stats_s4);
2357c478bd9Sstevel@tonic-gate }
2367c478bd9Sstevel@tonic-gate
2377c478bd9Sstevel@tonic-gate statstime *
rstatproc_stats_3_svc(argp,svcrq)2387c478bd9Sstevel@tonic-gate rstatproc_stats_3_svc(argp, svcrq)
2397c478bd9Sstevel@tonic-gate void *argp;
2407c478bd9Sstevel@tonic-gate struct svc_req *svcrq;
2417c478bd9Sstevel@tonic-gate {
2427c478bd9Sstevel@tonic-gate if (! stat_is_init)
2437c478bd9Sstevel@tonic-gate stat_init();
2447c478bd9Sstevel@tonic-gate #ifdef EXIT_WHEN_IDLE
2457c478bd9Sstevel@tonic-gate sincelastreq = 0;
2467c478bd9Sstevel@tonic-gate #endif
2477c478bd9Sstevel@tonic-gate return (&stats_s3);
2487c478bd9Sstevel@tonic-gate }
2497c478bd9Sstevel@tonic-gate
2507c478bd9Sstevel@tonic-gate statsswtch *
rstatproc_stats_2_svc(argp,svcrq)2517c478bd9Sstevel@tonic-gate rstatproc_stats_2_svc(argp, svcrq)
2527c478bd9Sstevel@tonic-gate void *argp;
2537c478bd9Sstevel@tonic-gate struct svc_req *svcrq;
2547c478bd9Sstevel@tonic-gate {
2557c478bd9Sstevel@tonic-gate if (! stat_is_init)
2567c478bd9Sstevel@tonic-gate stat_init();
2577c478bd9Sstevel@tonic-gate #ifdef EXIT_WHEN_IDLE
2587c478bd9Sstevel@tonic-gate sincelastreq = 0;
2597c478bd9Sstevel@tonic-gate #endif
2607c478bd9Sstevel@tonic-gate return (&stats_s2);
2617c478bd9Sstevel@tonic-gate }
2627c478bd9Sstevel@tonic-gate
2637c478bd9Sstevel@tonic-gate
2647c478bd9Sstevel@tonic-gate uint_t *
rstatproc_havedisk_4_svc(argp,svcrq)2657c478bd9Sstevel@tonic-gate rstatproc_havedisk_4_svc(argp, svcrq)
2667c478bd9Sstevel@tonic-gate void *argp;
2677c478bd9Sstevel@tonic-gate struct svc_req *svcrq;
2687c478bd9Sstevel@tonic-gate {
2697c478bd9Sstevel@tonic-gate return (rstatproc_havedisk_3_svc(argp, svcrq));
2707c478bd9Sstevel@tonic-gate }
2717c478bd9Sstevel@tonic-gate
2727c478bd9Sstevel@tonic-gate uint_t *
rstatproc_havedisk_3_svc(argp,svcrq)2737c478bd9Sstevel@tonic-gate rstatproc_havedisk_3_svc(argp, svcrq)
2747c478bd9Sstevel@tonic-gate void *argp;
2757c478bd9Sstevel@tonic-gate struct svc_req *svcrq;
2767c478bd9Sstevel@tonic-gate {
2777c478bd9Sstevel@tonic-gate static uint_t have;
2787c478bd9Sstevel@tonic-gate
2797c478bd9Sstevel@tonic-gate if (! stat_is_init)
2807c478bd9Sstevel@tonic-gate stat_init();
2817c478bd9Sstevel@tonic-gate #ifdef EXIT_WHEN_IDLE
2827c478bd9Sstevel@tonic-gate sincelastreq = 0;
2837c478bd9Sstevel@tonic-gate #endif
2847c478bd9Sstevel@tonic-gate have = (ndisks != 0);
2857c478bd9Sstevel@tonic-gate return (&have);
2867c478bd9Sstevel@tonic-gate }
2877c478bd9Sstevel@tonic-gate
2887c478bd9Sstevel@tonic-gate uint_t *
rstatproc_havedisk_2_svc(argp,svcrq)2897c478bd9Sstevel@tonic-gate rstatproc_havedisk_2_svc(argp, svcrq)
2907c478bd9Sstevel@tonic-gate void *argp;
2917c478bd9Sstevel@tonic-gate struct svc_req *svcrq;
2927c478bd9Sstevel@tonic-gate {
2937c478bd9Sstevel@tonic-gate return (rstatproc_havedisk_3_svc(argp, svcrq));
2947c478bd9Sstevel@tonic-gate }
2957c478bd9Sstevel@tonic-gate
2967c478bd9Sstevel@tonic-gate void
updatestat(int ignored)2977c478bd9Sstevel@tonic-gate updatestat(int ignored)
2987c478bd9Sstevel@tonic-gate {
2997c478bd9Sstevel@tonic-gate extern int _rpcpmstart; /* Started by a port monitor ? */
3007c478bd9Sstevel@tonic-gate extern int _rpcsvcdirty; /* Still serving ? */
3017c478bd9Sstevel@tonic-gate
3027c478bd9Sstevel@tonic-gate #ifdef DEBUG
3037c478bd9Sstevel@tonic-gate fprintf(stderr, "entering updatestat\n");
3047c478bd9Sstevel@tonic-gate #endif
3057c478bd9Sstevel@tonic-gate #ifdef EXIT_WHEN_IDLE
3067c478bd9Sstevel@tonic-gate if (_rpcpmstart && sincelastreq >= CLOSEDOWN && !_rpcsvcdirty) {
3077c478bd9Sstevel@tonic-gate #ifdef DEBUG
3087c478bd9Sstevel@tonic-gate fprintf(stderr, "about to closedown\n");
3097c478bd9Sstevel@tonic-gate #endif
3107c478bd9Sstevel@tonic-gate exit(0);
3117c478bd9Sstevel@tonic-gate }
3127c478bd9Sstevel@tonic-gate sincelastreq++;
3137c478bd9Sstevel@tonic-gate #endif /* def EXIT_WHEN_IDLE */
3147c478bd9Sstevel@tonic-gate
3157c478bd9Sstevel@tonic-gate (void) alarm(0);
3167c478bd9Sstevel@tonic-gate #ifdef DEBUG
3177c478bd9Sstevel@tonic-gate fprintf(stderr, "boottime: %d %d\n", stats_s3.boottime.tv_sec,
3187c478bd9Sstevel@tonic-gate stats_s3.boottime.tv_usec);
3197c478bd9Sstevel@tonic-gate #endif
3207c478bd9Sstevel@tonic-gate while (system_stat_load() || diskinfo_load() || netinfo_load()) {
3217c478bd9Sstevel@tonic-gate (void) kstat_chain_update(kc);
3227c478bd9Sstevel@tonic-gate system_stat_init();
3237c478bd9Sstevel@tonic-gate init_disks();
3247c478bd9Sstevel@tonic-gate init_net();
3257c478bd9Sstevel@tonic-gate }
3267c478bd9Sstevel@tonic-gate stats_s4.cp_time.cp_time_len = CPU_STATES;
3277c478bd9Sstevel@tonic-gate if (stats_s4.cp_time.cp_time_val == NULL)
3287c478bd9Sstevel@tonic-gate stats_s4.cp_time.cp_time_val =
3297c478bd9Sstevel@tonic-gate malloc(stats_s4.cp_time.cp_time_len * sizeof (int));
3307c478bd9Sstevel@tonic-gate stats_s2.cp_time[RSTAT_CPU_USER] =
3317c478bd9Sstevel@tonic-gate stats_s3.cp_time[RSTAT_CPU_USER] =
3327c478bd9Sstevel@tonic-gate stats_s4.cp_time.cp_time_val[RSTAT_CPU_USER] =
3337c478bd9Sstevel@tonic-gate CPU_STAT(&cpu_stats_all.sys, "cpu_ticks_user");
3347c478bd9Sstevel@tonic-gate stats_s2.cp_time[RSTAT_CPU_NICE] =
3357c478bd9Sstevel@tonic-gate stats_s3.cp_time[RSTAT_CPU_NICE] =
3367c478bd9Sstevel@tonic-gate stats_s4.cp_time.cp_time_val[RSTAT_CPU_NICE] =
3377c478bd9Sstevel@tonic-gate CPU_STAT(&cpu_stats_all.sys, "cpu_ticks_wait");
3387c478bd9Sstevel@tonic-gate stats_s2.cp_time[RSTAT_CPU_SYS] =
3397c478bd9Sstevel@tonic-gate stats_s3.cp_time[RSTAT_CPU_SYS] =
3407c478bd9Sstevel@tonic-gate stats_s4.cp_time.cp_time_val[RSTAT_CPU_SYS] =
3417c478bd9Sstevel@tonic-gate CPU_STAT(&cpu_stats_all.sys, "cpu_ticks_kernel");
3427c478bd9Sstevel@tonic-gate stats_s2.cp_time[RSTAT_CPU_IDLE] =
3437c478bd9Sstevel@tonic-gate stats_s3.cp_time[RSTAT_CPU_IDLE] =
3447c478bd9Sstevel@tonic-gate stats_s4.cp_time.cp_time_val[RSTAT_CPU_IDLE] =
3457c478bd9Sstevel@tonic-gate CPU_STAT(&cpu_stats_all.sys, "cpu_ticks_idle");
3467c478bd9Sstevel@tonic-gate
3477c478bd9Sstevel@tonic-gate #ifdef DEBUG
3487c478bd9Sstevel@tonic-gate fprintf(stderr, "cpu: %d %d %d %d\n",
3497c478bd9Sstevel@tonic-gate CPU_STAT(&cpu_stats_all.sys, "cpu_ticks_user"),
3507c478bd9Sstevel@tonic-gate CPU_STAT(&cpu_stats_all.sys, "cpu_ticks_wait"),
3517c478bd9Sstevel@tonic-gate CPU_STAT(&cpu_stats_all.sys, "cpu_ticks_kernel"),
3527c478bd9Sstevel@tonic-gate CPU_STAT(&cpu_stats_all.sys, "cpu_ticks_idle"));
3537c478bd9Sstevel@tonic-gate fprintf(stderr, "cp_time: %d %d %d %d\n",
3547c478bd9Sstevel@tonic-gate stats_s3.cp_time[RSTAT_CPU_USER],
3557c478bd9Sstevel@tonic-gate stats_s3.cp_time[RSTAT_CPU_NICE],
3567c478bd9Sstevel@tonic-gate stats_s3.cp_time[RSTAT_CPU_SYS],
3577c478bd9Sstevel@tonic-gate stats_s3.cp_time[RSTAT_CPU_IDLE]);
3587c478bd9Sstevel@tonic-gate #endif
3597c478bd9Sstevel@tonic-gate
3607c478bd9Sstevel@tonic-gate /* current time */
3617c478bd9Sstevel@tonic-gate gettimeofday((struct timeval *)&stats_s3.curtime, NULL);
3627c478bd9Sstevel@tonic-gate stats_s4.curtime = stats_s3.curtime;
3637c478bd9Sstevel@tonic-gate
3647c478bd9Sstevel@tonic-gate stats_s2.v_pgpgin =
3657c478bd9Sstevel@tonic-gate stats_s3.v_pgpgin =
3667c478bd9Sstevel@tonic-gate stats_s4.v_pgpgin = CPU_STAT(&cpu_stats_all.vm, "pgpgin");
3677c478bd9Sstevel@tonic-gate stats_s2.v_pgpgout =
3687c478bd9Sstevel@tonic-gate stats_s3.v_pgpgout =
3697c478bd9Sstevel@tonic-gate stats_s4.v_pgpgout = CPU_STAT(&cpu_stats_all.vm, "pgpgout");
3707c478bd9Sstevel@tonic-gate stats_s2.v_pswpin =
3717c478bd9Sstevel@tonic-gate stats_s3.v_pswpin =
3727c478bd9Sstevel@tonic-gate stats_s4.v_pswpin = CPU_STAT(&cpu_stats_all.vm, "pgswapin");
3737c478bd9Sstevel@tonic-gate stats_s2.v_pswpout =
3747c478bd9Sstevel@tonic-gate stats_s3.v_pswpout =
3757c478bd9Sstevel@tonic-gate stats_s4.v_pswpout = CPU_STAT(&cpu_stats_all.vm, "pgswapout");
3767c478bd9Sstevel@tonic-gate stats_s3.v_intr = CPU_STAT(&cpu_stats_all.sys, "intr");
3777c478bd9Sstevel@tonic-gate stats_s3.v_intr -= hz*(stats_s3.curtime.tv_sec - btm.tv_sec) +
3787c478bd9Sstevel@tonic-gate hz*(stats_s3.curtime.tv_usec - btm.tv_usec)/1000000;
3797c478bd9Sstevel@tonic-gate stats_s2.v_intr =
3807c478bd9Sstevel@tonic-gate stats_s4.v_intr = stats_s3.v_intr;
3817c478bd9Sstevel@tonic-gate /* swtch not in V1 */
3827c478bd9Sstevel@tonic-gate stats_s2.v_swtch =
3837c478bd9Sstevel@tonic-gate stats_s3.v_swtch =
3847c478bd9Sstevel@tonic-gate stats_s4.v_swtch = CPU_STAT(&cpu_stats_all.sys, "pswitch");
3857c478bd9Sstevel@tonic-gate
3867c478bd9Sstevel@tonic-gate #ifdef DEBUG
3877c478bd9Sstevel@tonic-gate fprintf(stderr,
3887c478bd9Sstevel@tonic-gate "pgin: %d pgout: %d swpin: %d swpout: %d intr: %d swtch: %d\n",
3897c478bd9Sstevel@tonic-gate stats_s3.v_pgpgin,
3907c478bd9Sstevel@tonic-gate stats_s3.v_pgpgout,
3917c478bd9Sstevel@tonic-gate stats_s3.v_pswpin,
3927c478bd9Sstevel@tonic-gate stats_s3.v_pswpout,
3937c478bd9Sstevel@tonic-gate stats_s3.v_intr,
3947c478bd9Sstevel@tonic-gate stats_s3.v_swtch);
3957c478bd9Sstevel@tonic-gate #endif
3967c478bd9Sstevel@tonic-gate /*
3977c478bd9Sstevel@tonic-gate * V2 and V3 of rstat are limited to RSTAT_DK_NDRIVE drives
3987c478bd9Sstevel@tonic-gate */
3997c478bd9Sstevel@tonic-gate memcpy(stats_s3.dk_xfer, stats_s4.dk_xfer.dk_xfer_val,
4007c478bd9Sstevel@tonic-gate RSTAT_DK_NDRIVE * sizeof (int));
4017c478bd9Sstevel@tonic-gate memcpy(stats_s2.dk_xfer, stats_s4.dk_xfer.dk_xfer_val,
4027c478bd9Sstevel@tonic-gate RSTAT_DK_NDRIVE * sizeof (int));
4037c478bd9Sstevel@tonic-gate #ifdef DEBUG
4047c478bd9Sstevel@tonic-gate fprintf(stderr, "dk_xfer: %d %d %d %d\n",
4057c478bd9Sstevel@tonic-gate stats_s4.dk_xfer.dk_xfer_val[0],
4067c478bd9Sstevel@tonic-gate stats_s4.dk_xfer.dk_xfer_val[1],
4077c478bd9Sstevel@tonic-gate stats_s4.dk_xfer.dk_xfer_val[2],
4087c478bd9Sstevel@tonic-gate stats_s4.dk_xfer.dk_xfer_val[3]);
4097c478bd9Sstevel@tonic-gate #endif
4107c478bd9Sstevel@tonic-gate
4117c478bd9Sstevel@tonic-gate stats_s2.if_ipackets =
4127c478bd9Sstevel@tonic-gate stats_s3.if_ipackets = stats_s4.if_ipackets;
4137c478bd9Sstevel@tonic-gate /* no s2 opackets */
4147c478bd9Sstevel@tonic-gate stats_s3.if_opackets = stats_s4.if_opackets;
4157c478bd9Sstevel@tonic-gate stats_s2.if_ierrors =
4167c478bd9Sstevel@tonic-gate stats_s3.if_ierrors = stats_s4.if_ierrors;
4177c478bd9Sstevel@tonic-gate stats_s2.if_oerrors =
4187c478bd9Sstevel@tonic-gate stats_s3.if_oerrors = stats_s4.if_oerrors;
4197c478bd9Sstevel@tonic-gate stats_s2.if_collisions =
4207c478bd9Sstevel@tonic-gate stats_s3.if_collisions = stats_s4.if_collisions;
4217c478bd9Sstevel@tonic-gate
4227c478bd9Sstevel@tonic-gate stats_s2.avenrun[0] =
4237c478bd9Sstevel@tonic-gate stats_s3.avenrun[0] =
4247c478bd9Sstevel@tonic-gate stats_s4.avenrun[0] = avenrun_1min_knp->value.ul;
4257c478bd9Sstevel@tonic-gate stats_s2.avenrun[1] =
4267c478bd9Sstevel@tonic-gate stats_s3.avenrun[1] =
4277c478bd9Sstevel@tonic-gate stats_s4.avenrun[1] = avenrun_5min_knp->value.ul;
4287c478bd9Sstevel@tonic-gate stats_s2.avenrun[2] =
4297c478bd9Sstevel@tonic-gate stats_s3.avenrun[2] =
4307c478bd9Sstevel@tonic-gate stats_s4.avenrun[2] = avenrun_15min_knp->value.ul;
4317c478bd9Sstevel@tonic-gate #ifdef DEBUG
4327c478bd9Sstevel@tonic-gate fprintf(stderr, "avenrun: %d %d %d\n", stats_s3.avenrun[0],
4337c478bd9Sstevel@tonic-gate stats_s3.avenrun[1], stats_s3.avenrun[2]);
4347c478bd9Sstevel@tonic-gate #endif
4357c478bd9Sstevel@tonic-gate signal(SIGALRM, updatestat);
4367c478bd9Sstevel@tonic-gate alarm(1);
4377c478bd9Sstevel@tonic-gate }
4387c478bd9Sstevel@tonic-gate
4397c478bd9Sstevel@tonic-gate /* --------------------------------- MIBGET -------------------------------- */
4407c478bd9Sstevel@tonic-gate
4417c478bd9Sstevel@tonic-gate static mib_item_t *
mibget(int sd)4427c478bd9Sstevel@tonic-gate mibget(int sd)
4437c478bd9Sstevel@tonic-gate {
4447c478bd9Sstevel@tonic-gate int flags;
4457c478bd9Sstevel@tonic-gate int j, getcode;
4467c478bd9Sstevel@tonic-gate struct strbuf ctlbuf, databuf;
4477c478bd9Sstevel@tonic-gate char buf[512];
4487c478bd9Sstevel@tonic-gate struct T_optmgmt_req *tor = (struct T_optmgmt_req *)buf;
4497c478bd9Sstevel@tonic-gate struct T_optmgmt_ack *toa = (struct T_optmgmt_ack *)buf;
4507c478bd9Sstevel@tonic-gate struct T_error_ack *tea = (struct T_error_ack *)buf;
4517c478bd9Sstevel@tonic-gate struct opthdr *req;
4527c478bd9Sstevel@tonic-gate mib_item_t *first_item = NULL;
4537c478bd9Sstevel@tonic-gate mib_item_t *last_item = NULL;
4547c478bd9Sstevel@tonic-gate mib_item_t *temp;
4557c478bd9Sstevel@tonic-gate
4567c478bd9Sstevel@tonic-gate tor->PRIM_type = T_SVR4_OPTMGMT_REQ;
4577c478bd9Sstevel@tonic-gate tor->OPT_offset = sizeof (struct T_optmgmt_req);
4587c478bd9Sstevel@tonic-gate tor->OPT_length = sizeof (struct opthdr);
4597c478bd9Sstevel@tonic-gate tor->MGMT_flags = T_CURRENT;
4607c478bd9Sstevel@tonic-gate req = (struct opthdr *)&tor[1];
4617c478bd9Sstevel@tonic-gate req->level = MIB2_IP; /* any MIB2_xxx value ok here */
4627c478bd9Sstevel@tonic-gate req->name = 0;
4637c478bd9Sstevel@tonic-gate req->len = 0;
4647c478bd9Sstevel@tonic-gate
4657c478bd9Sstevel@tonic-gate ctlbuf.buf = buf;
4667c478bd9Sstevel@tonic-gate ctlbuf.len = tor->OPT_length + tor->OPT_offset;
4677c478bd9Sstevel@tonic-gate flags = 0;
4687c478bd9Sstevel@tonic-gate if (putmsg(sd, &ctlbuf, NULL, flags) == -1) {
4697c478bd9Sstevel@tonic-gate perror("mibget: putmsg(ctl) failed");
4707c478bd9Sstevel@tonic-gate goto error_exit;
4717c478bd9Sstevel@tonic-gate }
4727c478bd9Sstevel@tonic-gate /*
4737c478bd9Sstevel@tonic-gate * each reply consists of a ctl part for one fixed structure
4747c478bd9Sstevel@tonic-gate * or table, as defined in mib2.h. The format is a T_OPTMGMT_ACK,
4757c478bd9Sstevel@tonic-gate * containing an opthdr structure. level/name identify the entry,
4767c478bd9Sstevel@tonic-gate * len is the size of the data part of the message.
4777c478bd9Sstevel@tonic-gate */
4787c478bd9Sstevel@tonic-gate req = (struct opthdr *)&toa[1];
4797c478bd9Sstevel@tonic-gate ctlbuf.maxlen = sizeof (buf);
4807c478bd9Sstevel@tonic-gate /*CSTYLED*/
4817c478bd9Sstevel@tonic-gate for (j = 1; ; j++) {
4827c478bd9Sstevel@tonic-gate flags = 0;
4837c478bd9Sstevel@tonic-gate getcode = getmsg(sd, &ctlbuf, NULL, &flags);
4847c478bd9Sstevel@tonic-gate if (getcode == -1) {
4857c478bd9Sstevel@tonic-gate #ifdef DEBUG_MIB
4867c478bd9Sstevel@tonic-gate perror("mibget getmsg(ctl) failed");
4877c478bd9Sstevel@tonic-gate fprintf(stderr, "# level name len\n");
4887c478bd9Sstevel@tonic-gate i = 0;
4897c478bd9Sstevel@tonic-gate for (last_item = first_item; last_item;
4907c478bd9Sstevel@tonic-gate last_item = last_item->next_item)
4917c478bd9Sstevel@tonic-gate fprintf(stderr, "%d %4d %5d %d\n", ++i,
4927c478bd9Sstevel@tonic-gate last_item->group,
4937c478bd9Sstevel@tonic-gate last_item->mib_id,
4947c478bd9Sstevel@tonic-gate last_item->length);
4957c478bd9Sstevel@tonic-gate #endif /* DEBUG_MIB */
4967c478bd9Sstevel@tonic-gate goto error_exit;
4977c478bd9Sstevel@tonic-gate }
4987c478bd9Sstevel@tonic-gate if (getcode == 0 &&
4997c478bd9Sstevel@tonic-gate (ctlbuf.len >= sizeof (struct T_optmgmt_ack)) &&
5007c478bd9Sstevel@tonic-gate (toa->PRIM_type == T_OPTMGMT_ACK) &&
5017c478bd9Sstevel@tonic-gate (toa->MGMT_flags == T_SUCCESS) &&
5027c478bd9Sstevel@tonic-gate req->len == 0) {
5037c478bd9Sstevel@tonic-gate #ifdef DEBUG_MIB
5047c478bd9Sstevel@tonic-gate fprintf(stderr,
5057c478bd9Sstevel@tonic-gate "mibget getmsg() %d returned EOD (level %d, name %d)\n",
5067c478bd9Sstevel@tonic-gate j, req->level, req->name);
5077c478bd9Sstevel@tonic-gate #endif /* DEBUG_MIB */
5087c478bd9Sstevel@tonic-gate return (first_item); /* this is EOD msg */
5097c478bd9Sstevel@tonic-gate }
5107c478bd9Sstevel@tonic-gate
5117c478bd9Sstevel@tonic-gate if (ctlbuf.len >= sizeof (struct T_error_ack) &&
5127c478bd9Sstevel@tonic-gate (tea->PRIM_type == T_ERROR_ACK)) {
5137c478bd9Sstevel@tonic-gate #ifdef DEBUG_MIB
5147c478bd9Sstevel@tonic-gate fprintf(stderr,
5157c478bd9Sstevel@tonic-gate "mibget %d gives T_ERROR_ACK: TLI_error = 0x%x, UNIX_error = 0x%x\n",
5167c478bd9Sstevel@tonic-gate j, getcode, tea->TLI_error, tea->UNIX_error);
5177c478bd9Sstevel@tonic-gate #endif /* DEBUG_MIB */
5187c478bd9Sstevel@tonic-gate errno = (tea->TLI_error == TSYSERR)
5197c478bd9Sstevel@tonic-gate ? tea->UNIX_error : EPROTO;
5207c478bd9Sstevel@tonic-gate goto error_exit;
5217c478bd9Sstevel@tonic-gate }
5227c478bd9Sstevel@tonic-gate
5237c478bd9Sstevel@tonic-gate if (getcode != MOREDATA ||
5247c478bd9Sstevel@tonic-gate (ctlbuf.len < sizeof (struct T_optmgmt_ack)) ||
5257c478bd9Sstevel@tonic-gate (toa->PRIM_type != T_OPTMGMT_ACK) ||
5267c478bd9Sstevel@tonic-gate (toa->MGMT_flags != T_SUCCESS)) {
5277c478bd9Sstevel@tonic-gate #ifdef DEBUG_MIB
5287c478bd9Sstevel@tonic-gate fprintf(stderr,
5297c478bd9Sstevel@tonic-gate "mibget getmsg(ctl) %d returned %d, ctlbuf.len = %d, PRIM_type = %d\n",
5307c478bd9Sstevel@tonic-gate j, getcode, ctlbuf.len, toa->PRIM_type);
5317c478bd9Sstevel@tonic-gate if (toa->PRIM_type == T_OPTMGMT_ACK)
5327c478bd9Sstevel@tonic-gate fprintf(stderr,
5337c478bd9Sstevel@tonic-gate "T_OPTMGMT_ACK: MGMT_flags = 0x%x, req->len = %d\n",
5347c478bd9Sstevel@tonic-gate toa->MGMT_flags, req->len);
5357c478bd9Sstevel@tonic-gate #endif /* DEBUG_MIB */
5367c478bd9Sstevel@tonic-gate errno = ENOMSG;
5377c478bd9Sstevel@tonic-gate goto error_exit;
5387c478bd9Sstevel@tonic-gate }
5397c478bd9Sstevel@tonic-gate
5407c478bd9Sstevel@tonic-gate temp = malloc(sizeof (mib_item_t));
5417c478bd9Sstevel@tonic-gate if (!temp) {
5427c478bd9Sstevel@tonic-gate perror("mibget malloc failed");
5437c478bd9Sstevel@tonic-gate goto error_exit;
5447c478bd9Sstevel@tonic-gate }
5457c478bd9Sstevel@tonic-gate if (last_item)
5467c478bd9Sstevel@tonic-gate last_item->next_item = temp;
5477c478bd9Sstevel@tonic-gate else
5487c478bd9Sstevel@tonic-gate first_item = temp;
5497c478bd9Sstevel@tonic-gate last_item = temp;
5507c478bd9Sstevel@tonic-gate last_item->next_item = NULL;
5517c478bd9Sstevel@tonic-gate last_item->group = req->level;
5527c478bd9Sstevel@tonic-gate last_item->mib_id = req->name;
5537c478bd9Sstevel@tonic-gate last_item->length = req->len;
5547c478bd9Sstevel@tonic-gate last_item->valp = malloc(req->len);
5557c478bd9Sstevel@tonic-gate #ifdef DEBUG_MIB
5567c478bd9Sstevel@tonic-gate fprintf(stderr,
5577c478bd9Sstevel@tonic-gate "msg %d: group = %4d mib_id = %5d length = %d\n",
5587c478bd9Sstevel@tonic-gate j, last_item->group, last_item->mib_id,
5597c478bd9Sstevel@tonic-gate last_item->length);
5607c478bd9Sstevel@tonic-gate #endif /* DEBUG_MIB */
5617c478bd9Sstevel@tonic-gate databuf.maxlen = last_item->length;
5627c478bd9Sstevel@tonic-gate databuf.buf = last_item->valp;
5637c478bd9Sstevel@tonic-gate databuf.len = 0;
5647c478bd9Sstevel@tonic-gate flags = 0;
5657c478bd9Sstevel@tonic-gate getcode = getmsg(sd, NULL, &databuf, &flags);
5667c478bd9Sstevel@tonic-gate if (getcode == -1) {
5677c478bd9Sstevel@tonic-gate perror("mibget getmsg(data) failed");
5687c478bd9Sstevel@tonic-gate goto error_exit;
5697c478bd9Sstevel@tonic-gate } else if (getcode != 0) {
5707c478bd9Sstevel@tonic-gate fprintf(stderr,
5717c478bd9Sstevel@tonic-gate "mibget getmsg(data) returned %d, databuf.maxlen = %d, databuf.len = %d\n",
5727c478bd9Sstevel@tonic-gate getcode, databuf.maxlen, databuf.len);
5737c478bd9Sstevel@tonic-gate goto error_exit;
5747c478bd9Sstevel@tonic-gate }
5757c478bd9Sstevel@tonic-gate }
5767c478bd9Sstevel@tonic-gate
5777c478bd9Sstevel@tonic-gate error_exit:
5787c478bd9Sstevel@tonic-gate while (first_item) {
5797c478bd9Sstevel@tonic-gate last_item = first_item;
5807c478bd9Sstevel@tonic-gate first_item = first_item->next_item;
5817c478bd9Sstevel@tonic-gate if (last_item->valp) {
5827c478bd9Sstevel@tonic-gate free(last_item->valp);
5837c478bd9Sstevel@tonic-gate }
5847c478bd9Sstevel@tonic-gate free(last_item);
5857c478bd9Sstevel@tonic-gate }
5867c478bd9Sstevel@tonic-gate return (first_item);
5877c478bd9Sstevel@tonic-gate }
5887c478bd9Sstevel@tonic-gate
5897c478bd9Sstevel@tonic-gate static int
mibopen(void)5907c478bd9Sstevel@tonic-gate mibopen(void)
5917c478bd9Sstevel@tonic-gate {
5927c478bd9Sstevel@tonic-gate int sd;
5937c478bd9Sstevel@tonic-gate
5947c478bd9Sstevel@tonic-gate /* gives us ip w/ arp on top */
5957c478bd9Sstevel@tonic-gate sd = open("/dev/arp", O_RDWR);
5967c478bd9Sstevel@tonic-gate if (sd == -1) {
5977c478bd9Sstevel@tonic-gate perror("arp open");
5987c478bd9Sstevel@tonic-gate close(sd);
5997c478bd9Sstevel@tonic-gate return (-1);
6007c478bd9Sstevel@tonic-gate }
6017c478bd9Sstevel@tonic-gate if (ioctl(sd, I_PUSH, "tcp") == -1) {
6027c478bd9Sstevel@tonic-gate perror("tcp I_PUSH");
6037c478bd9Sstevel@tonic-gate close(sd);
6047c478bd9Sstevel@tonic-gate return (-1);
6057c478bd9Sstevel@tonic-gate }
6067c478bd9Sstevel@tonic-gate if (ioctl(sd, I_PUSH, "udp") == -1) {
6077c478bd9Sstevel@tonic-gate perror("udp I_PUSH");
6087c478bd9Sstevel@tonic-gate close(sd);
6097c478bd9Sstevel@tonic-gate return (-1);
6107c478bd9Sstevel@tonic-gate }
6117c478bd9Sstevel@tonic-gate return (sd);
6127c478bd9Sstevel@tonic-gate }
6137c478bd9Sstevel@tonic-gate
6147c478bd9Sstevel@tonic-gate static char *
octetstr(char * buf,Octet_t * op,int code)6157c478bd9Sstevel@tonic-gate octetstr(char *buf, Octet_t *op, int code)
6167c478bd9Sstevel@tonic-gate {
6177c478bd9Sstevel@tonic-gate int i;
6187c478bd9Sstevel@tonic-gate char *cp;
6197c478bd9Sstevel@tonic-gate
6207c478bd9Sstevel@tonic-gate cp = buf;
6217c478bd9Sstevel@tonic-gate if (op)
6227c478bd9Sstevel@tonic-gate for (i = 0; i < op->o_length; i++)
6237c478bd9Sstevel@tonic-gate switch (code) {
6247c478bd9Sstevel@tonic-gate case 'd':
6257c478bd9Sstevel@tonic-gate sprintf(cp, "%d.", 0xff & op->o_bytes[i]);
6267c478bd9Sstevel@tonic-gate cp = strchr(cp, '\0');
6277c478bd9Sstevel@tonic-gate break;
6287c478bd9Sstevel@tonic-gate case 'a':
6297c478bd9Sstevel@tonic-gate *cp++ = op->o_bytes[i];
6307c478bd9Sstevel@tonic-gate break;
6317c478bd9Sstevel@tonic-gate case 'h':
6327c478bd9Sstevel@tonic-gate default:
6337c478bd9Sstevel@tonic-gate sprintf(cp, "%02x:", 0xff & op->o_bytes[i]);
6347c478bd9Sstevel@tonic-gate cp += 3;
6357c478bd9Sstevel@tonic-gate break;
6367c478bd9Sstevel@tonic-gate }
6377c478bd9Sstevel@tonic-gate if (code != 'a' && cp != buf)
6387c478bd9Sstevel@tonic-gate cp--;
6397c478bd9Sstevel@tonic-gate *cp = '\0';
6407c478bd9Sstevel@tonic-gate return (buf);
6417c478bd9Sstevel@tonic-gate }
6427c478bd9Sstevel@tonic-gate
6437c478bd9Sstevel@tonic-gate static void
fail(int do_perror,char * message,...)6447c478bd9Sstevel@tonic-gate fail(int do_perror, char *message, ...)
6457c478bd9Sstevel@tonic-gate {
6467c478bd9Sstevel@tonic-gate va_list args;
6477c478bd9Sstevel@tonic-gate
6487c478bd9Sstevel@tonic-gate va_start(args, message);
6497c478bd9Sstevel@tonic-gate fprintf(stderr, "%s: ", cmdname);
6507c478bd9Sstevel@tonic-gate vfprintf(stderr, message, args);
6517c478bd9Sstevel@tonic-gate va_end(args);
6527c478bd9Sstevel@tonic-gate if (do_perror)
6537c478bd9Sstevel@tonic-gate fprintf(stderr, ": %s", strerror(errno));
6547c478bd9Sstevel@tonic-gate fprintf(stderr, "\n");
6557c478bd9Sstevel@tonic-gate exit(2);
6567c478bd9Sstevel@tonic-gate }
6577c478bd9Sstevel@tonic-gate
6587c478bd9Sstevel@tonic-gate static void
safe_zalloc(void ** ptr,int size,int free_first)6597c478bd9Sstevel@tonic-gate safe_zalloc(void **ptr, int size, int free_first)
6607c478bd9Sstevel@tonic-gate {
6617c478bd9Sstevel@tonic-gate if (free_first && *ptr != NULL)
6627c478bd9Sstevel@tonic-gate free(*ptr);
6637c478bd9Sstevel@tonic-gate if ((*ptr = malloc(size)) == NULL)
6647c478bd9Sstevel@tonic-gate fail(1, "malloc failed");
6657c478bd9Sstevel@tonic-gate memset(*ptr, 0, size);
6667c478bd9Sstevel@tonic-gate }
6677c478bd9Sstevel@tonic-gate
6687c478bd9Sstevel@tonic-gate kid_t
safe_kstat_read(kstat_ctl_t * kctl,kstat_t * ksp,void * data)6697c478bd9Sstevel@tonic-gate safe_kstat_read(kstat_ctl_t *kctl, kstat_t *ksp, void *data)
6707c478bd9Sstevel@tonic-gate {
6717c478bd9Sstevel@tonic-gate kid_t kstat_chain_id = kstat_read(kctl, ksp, data);
6727c478bd9Sstevel@tonic-gate
6737c478bd9Sstevel@tonic-gate if (kstat_chain_id == -1)
6747c478bd9Sstevel@tonic-gate fail(1, "kstat_read(%x, '%s') failed", kctl, ksp->ks_name);
6757c478bd9Sstevel@tonic-gate return (kstat_chain_id);
6767c478bd9Sstevel@tonic-gate }
6777c478bd9Sstevel@tonic-gate
6787c478bd9Sstevel@tonic-gate kstat_t *
safe_kstat_lookup(kstat_ctl_t * kctl,char * ks_module,int ks_instance,char * ks_name)6797c478bd9Sstevel@tonic-gate safe_kstat_lookup(kstat_ctl_t *kctl, char *ks_module, int ks_instance,
6807c478bd9Sstevel@tonic-gate char *ks_name)
6817c478bd9Sstevel@tonic-gate {
6827c478bd9Sstevel@tonic-gate kstat_t *ksp = kstat_lookup(kctl, ks_module, ks_instance, ks_name);
6837c478bd9Sstevel@tonic-gate
6847c478bd9Sstevel@tonic-gate if (ksp == NULL)
6857c478bd9Sstevel@tonic-gate fail(0, "kstat_lookup('%s', %d, '%s') failed",
6867c478bd9Sstevel@tonic-gate ks_module == NULL ? "" : ks_module,
6877c478bd9Sstevel@tonic-gate ks_instance,
6887c478bd9Sstevel@tonic-gate ks_name == NULL ? "" : ks_name);
6897c478bd9Sstevel@tonic-gate return (ksp);
6907c478bd9Sstevel@tonic-gate }
6917c478bd9Sstevel@tonic-gate
6927c478bd9Sstevel@tonic-gate void *
safe_kstat_data_lookup(kstat_t * ksp,char * name)6937c478bd9Sstevel@tonic-gate safe_kstat_data_lookup(kstat_t *ksp, char *name)
6947c478bd9Sstevel@tonic-gate {
6957c478bd9Sstevel@tonic-gate void *fp = kstat_data_lookup(ksp, name);
6967c478bd9Sstevel@tonic-gate
6977c478bd9Sstevel@tonic-gate if (fp == NULL) {
6987c478bd9Sstevel@tonic-gate fail(0, "kstat_data_lookup('%s', '%s') failed",
6997c478bd9Sstevel@tonic-gate ksp->ks_name, name);
7007c478bd9Sstevel@tonic-gate }
7017c478bd9Sstevel@tonic-gate return (fp);
7027c478bd9Sstevel@tonic-gate }
7037c478bd9Sstevel@tonic-gate
7047c478bd9Sstevel@tonic-gate /*
7057c478bd9Sstevel@tonic-gate * Get various KIDs for subsequent system_stat_load operations.
7067c478bd9Sstevel@tonic-gate */
7077c478bd9Sstevel@tonic-gate
7087c478bd9Sstevel@tonic-gate static void
system_stat_init(void)7097c478bd9Sstevel@tonic-gate system_stat_init(void)
7107c478bd9Sstevel@tonic-gate {
7117c478bd9Sstevel@tonic-gate kstat_t *ksp;
7127c478bd9Sstevel@tonic-gate int i, nvmks;
7137c478bd9Sstevel@tonic-gate
7147c478bd9Sstevel@tonic-gate /*
7157c478bd9Sstevel@tonic-gate * Global statistics
7167c478bd9Sstevel@tonic-gate */
7177c478bd9Sstevel@tonic-gate
7187c478bd9Sstevel@tonic-gate system_misc_ksp = safe_kstat_lookup(kc, "unix", 0, "system_misc");
7197c478bd9Sstevel@tonic-gate
7207c478bd9Sstevel@tonic-gate safe_kstat_read(kc, system_misc_ksp, NULL);
7217c478bd9Sstevel@tonic-gate boot_time_knp = safe_kstat_data_lookup(system_misc_ksp, "boot_time");
7227c478bd9Sstevel@tonic-gate avenrun_1min_knp = safe_kstat_data_lookup(system_misc_ksp,
7237c478bd9Sstevel@tonic-gate "avenrun_1min");
7247c478bd9Sstevel@tonic-gate avenrun_5min_knp = safe_kstat_data_lookup(system_misc_ksp,
7257c478bd9Sstevel@tonic-gate "avenrun_5min");
7267c478bd9Sstevel@tonic-gate avenrun_15min_knp = safe_kstat_data_lookup(system_misc_ksp,
7277c478bd9Sstevel@tonic-gate "avenrun_15min");
7287c478bd9Sstevel@tonic-gate
7297c478bd9Sstevel@tonic-gate /*
7307c478bd9Sstevel@tonic-gate * Per-CPU statistics
7317c478bd9Sstevel@tonic-gate */
7327c478bd9Sstevel@tonic-gate
7337c478bd9Sstevel@tonic-gate ncpus = 0;
7347c478bd9Sstevel@tonic-gate for (ksp = kc->kc_chain; ksp; ksp = ksp->ks_next)
7357c478bd9Sstevel@tonic-gate if (strcmp(ksp->ks_module, "cpu") == 0 &&
7367c478bd9Sstevel@tonic-gate strcmp(ksp->ks_name, "sys") == 0)
7377c478bd9Sstevel@tonic-gate ncpus++;
7387c478bd9Sstevel@tonic-gate
7397c478bd9Sstevel@tonic-gate safe_zalloc((void **)&cpu_stats_list, ncpus * sizeof (*cpu_stats_list),
7407c478bd9Sstevel@tonic-gate 1);
7417c478bd9Sstevel@tonic-gate
7427c478bd9Sstevel@tonic-gate ncpus = 0;
7437c478bd9Sstevel@tonic-gate for (ksp = kc->kc_chain; ksp; ksp = ksp->ks_next)
7447c478bd9Sstevel@tonic-gate if (strcmp(ksp->ks_module, "cpu") == 0 &&
7457c478bd9Sstevel@tonic-gate strcmp(ksp->ks_name, "sys") == 0 &&
7467c478bd9Sstevel@tonic-gate kstat_read(kc, ksp, NULL) != -1) {
7477c478bd9Sstevel@tonic-gate kstat_copy(ksp, &cpu_stats_list[ncpus].sys,
7487c478bd9Sstevel@tonic-gate 1);
7497c478bd9Sstevel@tonic-gate if ((ksp = kstat_lookup(kc, "cpu", ksp->ks_instance,
7507c478bd9Sstevel@tonic-gate "vm")) != NULL && kstat_read(kc, ksp, NULL) != -1)
7517c478bd9Sstevel@tonic-gate kstat_copy(ksp, &cpu_stats_list[ncpus].vm, 1);
7527c478bd9Sstevel@tonic-gate else
7537c478bd9Sstevel@tonic-gate fail(0, "couldn't find per-CPU VM statistics");
7547c478bd9Sstevel@tonic-gate ncpus++;
7557c478bd9Sstevel@tonic-gate }
7567c478bd9Sstevel@tonic-gate
7577c478bd9Sstevel@tonic-gate if (ncpus == 0)
7587c478bd9Sstevel@tonic-gate fail(0, "couldn't find per-CPU statistics");
7597c478bd9Sstevel@tonic-gate }
7607c478bd9Sstevel@tonic-gate
7617c478bd9Sstevel@tonic-gate /*
7627c478bd9Sstevel@tonic-gate * load statistics, summing across CPUs where needed
7637c478bd9Sstevel@tonic-gate */
7647c478bd9Sstevel@tonic-gate
7657c478bd9Sstevel@tonic-gate static int
system_stat_load(void)7667c478bd9Sstevel@tonic-gate system_stat_load(void)
7677c478bd9Sstevel@tonic-gate {
7687c478bd9Sstevel@tonic-gate int i, j;
7697c478bd9Sstevel@tonic-gate _cpu_stats_t cs;
7707c478bd9Sstevel@tonic-gate ulong_t *np, *tp;
7717c478bd9Sstevel@tonic-gate
7727c478bd9Sstevel@tonic-gate /*
7737c478bd9Sstevel@tonic-gate * Global statistics
7747c478bd9Sstevel@tonic-gate */
7757c478bd9Sstevel@tonic-gate
7767c478bd9Sstevel@tonic-gate safe_kstat_read(kc, system_misc_ksp, NULL);
7777c478bd9Sstevel@tonic-gate
7787c478bd9Sstevel@tonic-gate /*
7797c478bd9Sstevel@tonic-gate * Per-CPU statistics.
7807c478bd9Sstevel@tonic-gate */
7817c478bd9Sstevel@tonic-gate
7827c478bd9Sstevel@tonic-gate for (i = 0; i < ncpus; i++) {
7837c478bd9Sstevel@tonic-gate if (kstat_read(kc, &cpu_stats_list[i].sys, NULL) == -1 ||
7847c478bd9Sstevel@tonic-gate kstat_read(kc, &cpu_stats_list[i].vm, NULL) == -1)
7857c478bd9Sstevel@tonic-gate return (1);
7867c478bd9Sstevel@tonic-gate if (i == 0) {
7877c478bd9Sstevel@tonic-gate kstat_copy(&cpu_stats_list[0].sys, &cpu_stats_all.sys,
7887c478bd9Sstevel@tonic-gate 1);
7897c478bd9Sstevel@tonic-gate kstat_copy(&cpu_stats_list[0].vm, &cpu_stats_all.vm, 1);
7907c478bd9Sstevel@tonic-gate } else {
7917c478bd9Sstevel@tonic-gate kstat_named_t *nkp;
7927c478bd9Sstevel@tonic-gate kstat_named_t *tkp;
7937c478bd9Sstevel@tonic-gate
7947c478bd9Sstevel@tonic-gate /*
7957c478bd9Sstevel@tonic-gate * Other CPUs' statistics are accumulated in
7967c478bd9Sstevel@tonic-gate * cpu_stats_all, initialized at the first iteration of
7977c478bd9Sstevel@tonic-gate * the loop.
7987c478bd9Sstevel@tonic-gate */
7997c478bd9Sstevel@tonic-gate nkp = (kstat_named_t *)cpu_stats_all.sys.ks_data;
8007c478bd9Sstevel@tonic-gate tkp = (kstat_named_t *)cpu_stats_list[i].sys.ks_data;
8017c478bd9Sstevel@tonic-gate for (j = 0; j < cpu_stats_list[i].sys.ks_ndata; j++)
8027c478bd9Sstevel@tonic-gate (nkp++)->value.ui64 += (tkp++)->value.ui64;
8037c478bd9Sstevel@tonic-gate nkp = (kstat_named_t *)cpu_stats_all.vm.ks_data;
8047c478bd9Sstevel@tonic-gate tkp = (kstat_named_t *)cpu_stats_list[i].vm.ks_data;
8057c478bd9Sstevel@tonic-gate for (j = 0; j < cpu_stats_list[i].vm.ks_ndata; j++)
8067c478bd9Sstevel@tonic-gate (nkp++)->value.ui64 += (tkp++)->value.ui64;
8077c478bd9Sstevel@tonic-gate }
8087c478bd9Sstevel@tonic-gate }
8097c478bd9Sstevel@tonic-gate return (0);
8107c478bd9Sstevel@tonic-gate }
8117c478bd9Sstevel@tonic-gate
8127c478bd9Sstevel@tonic-gate static int
kscmp(kstat_t * ks1,kstat_t * ks2)8137c478bd9Sstevel@tonic-gate kscmp(kstat_t *ks1, kstat_t *ks2)
8147c478bd9Sstevel@tonic-gate {
8157c478bd9Sstevel@tonic-gate int cmp;
8167c478bd9Sstevel@tonic-gate
8177c478bd9Sstevel@tonic-gate cmp = strcmp(ks1->ks_module, ks2->ks_module);
8187c478bd9Sstevel@tonic-gate if (cmp != 0)
8197c478bd9Sstevel@tonic-gate return (cmp);
8207c478bd9Sstevel@tonic-gate cmp = ks1->ks_instance - ks2->ks_instance;
8217c478bd9Sstevel@tonic-gate if (cmp != 0)
8227c478bd9Sstevel@tonic-gate return (cmp);
8237c478bd9Sstevel@tonic-gate return (strcmp(ks1->ks_name, ks2->ks_name));
8247c478bd9Sstevel@tonic-gate }
8257c478bd9Sstevel@tonic-gate
8267c478bd9Sstevel@tonic-gate static void
init_disks(void)8277c478bd9Sstevel@tonic-gate init_disks(void)
8287c478bd9Sstevel@tonic-gate {
8297c478bd9Sstevel@tonic-gate struct diskinfo *disk, *prevdisk, *comp;
8307c478bd9Sstevel@tonic-gate kstat_t *ksp;
8317c478bd9Sstevel@tonic-gate
8327c478bd9Sstevel@tonic-gate ndisks = 0;
8337c478bd9Sstevel@tonic-gate disk = &zerodisk;
8347c478bd9Sstevel@tonic-gate
8357c478bd9Sstevel@tonic-gate /*
8367c478bd9Sstevel@tonic-gate * Patch the snip in the diskinfo list (see below)
8377c478bd9Sstevel@tonic-gate */
8387c478bd9Sstevel@tonic-gate if (snip)
8397c478bd9Sstevel@tonic-gate lastdisk->next = snip;
8407c478bd9Sstevel@tonic-gate
8417c478bd9Sstevel@tonic-gate for (ksp = kc->kc_chain; ksp; ksp = ksp->ks_next) {
8427c478bd9Sstevel@tonic-gate
8437c478bd9Sstevel@tonic-gate if (ksp->ks_type != KSTAT_TYPE_IO ||
8447c478bd9Sstevel@tonic-gate strcmp(ksp->ks_class, "disk") != 0)
8457c478bd9Sstevel@tonic-gate continue;
8467c478bd9Sstevel@tonic-gate prevdisk = disk;
8477c478bd9Sstevel@tonic-gate if (disk->next)
8487c478bd9Sstevel@tonic-gate disk = disk->next;
8497c478bd9Sstevel@tonic-gate else {
8507c478bd9Sstevel@tonic-gate safe_zalloc((void **)&disk->next,
8517c478bd9Sstevel@tonic-gate sizeof (struct diskinfo), 0);
8527c478bd9Sstevel@tonic-gate disk = disk->next;
8537c478bd9Sstevel@tonic-gate disk->next = NULLDISK;
8547c478bd9Sstevel@tonic-gate }
8557c478bd9Sstevel@tonic-gate disk->ks = ksp;
8567c478bd9Sstevel@tonic-gate memset((void *)&disk->kios, 0, sizeof (kstat_io_t));
8577c478bd9Sstevel@tonic-gate disk->kios.wlastupdate = disk->ks->ks_crtime;
8587c478bd9Sstevel@tonic-gate disk->kios.rlastupdate = disk->ks->ks_crtime;
8597c478bd9Sstevel@tonic-gate
8607c478bd9Sstevel@tonic-gate /*
8617c478bd9Sstevel@tonic-gate * Insertion sort on (ks_module, ks_instance, ks_name)
8627c478bd9Sstevel@tonic-gate */
8637c478bd9Sstevel@tonic-gate comp = &zerodisk;
8647c478bd9Sstevel@tonic-gate while (kscmp(disk->ks, comp->next->ks) > 0)
8657c478bd9Sstevel@tonic-gate comp = comp->next;
8667c478bd9Sstevel@tonic-gate if (prevdisk != comp) {
8677c478bd9Sstevel@tonic-gate prevdisk->next = disk->next;
8687c478bd9Sstevel@tonic-gate disk->next = comp->next;
8697c478bd9Sstevel@tonic-gate comp->next = disk;
8707c478bd9Sstevel@tonic-gate disk = prevdisk;
8717c478bd9Sstevel@tonic-gate }
8727c478bd9Sstevel@tonic-gate ndisks++;
8737c478bd9Sstevel@tonic-gate }
8747c478bd9Sstevel@tonic-gate /*
8757c478bd9Sstevel@tonic-gate * Put a snip in the linked list of diskinfos. The idea:
8767c478bd9Sstevel@tonic-gate * If there was a state change such that now there are fewer
8777c478bd9Sstevel@tonic-gate * disks, we snip the list and retain the tail, rather than
8787c478bd9Sstevel@tonic-gate * freeing it. At the next state change, we clip the tail back on.
8797c478bd9Sstevel@tonic-gate * This prevents a lot of malloc/free activity, and it's simpler.
8807c478bd9Sstevel@tonic-gate */
8817c478bd9Sstevel@tonic-gate lastdisk = disk;
8827c478bd9Sstevel@tonic-gate snip = disk->next;
8837c478bd9Sstevel@tonic-gate disk->next = NULLDISK;
8847c478bd9Sstevel@tonic-gate
8857c478bd9Sstevel@tonic-gate firstdisk = zerodisk.next;
8867c478bd9Sstevel@tonic-gate
8877c478bd9Sstevel@tonic-gate if (ndisks > stats_s4.dk_xfer.dk_xfer_len) {
8887c478bd9Sstevel@tonic-gate stats_s4.dk_xfer.dk_xfer_len = ndisks;
8897c478bd9Sstevel@tonic-gate safe_zalloc((void **)&stats_s4.dk_xfer.dk_xfer_val,
8907c478bd9Sstevel@tonic-gate ndisks * sizeof (int), 1);
8917c478bd9Sstevel@tonic-gate }
8927c478bd9Sstevel@tonic-gate }
8937c478bd9Sstevel@tonic-gate
8947c478bd9Sstevel@tonic-gate static int
diskinfo_load(void)8957c478bd9Sstevel@tonic-gate diskinfo_load(void)
8967c478bd9Sstevel@tonic-gate {
8977c478bd9Sstevel@tonic-gate struct diskinfo *disk;
8987c478bd9Sstevel@tonic-gate int i;
8997c478bd9Sstevel@tonic-gate
9007c478bd9Sstevel@tonic-gate for (disk = firstdisk, i = 0; disk; disk = disk->next, i++) {
9017c478bd9Sstevel@tonic-gate if (kstat_read(kc, disk->ks, (void *)&disk->kios) == -1)
9027c478bd9Sstevel@tonic-gate return (1);
9037c478bd9Sstevel@tonic-gate stats_s4.dk_xfer.dk_xfer_val[i] = disk->kios.reads +
9047c478bd9Sstevel@tonic-gate disk->kios.writes;
9057c478bd9Sstevel@tonic-gate }
9067c478bd9Sstevel@tonic-gate return (0);
9077c478bd9Sstevel@tonic-gate }
9087c478bd9Sstevel@tonic-gate
9097c478bd9Sstevel@tonic-gate static void
init_net(void)9107c478bd9Sstevel@tonic-gate init_net(void)
9117c478bd9Sstevel@tonic-gate {
9127c478bd9Sstevel@tonic-gate static int sd;
9137c478bd9Sstevel@tonic-gate mib_item_t *item;
9147c478bd9Sstevel@tonic-gate mib2_ipAddrEntry_t *ap;
9157c478bd9Sstevel@tonic-gate char namebuf[KSTAT_STRLEN];
9167c478bd9Sstevel@tonic-gate struct netinfo *net, *prevnet, *comp;
9177c478bd9Sstevel@tonic-gate kstat_t *ksp;
9187c478bd9Sstevel@tonic-gate
9197c478bd9Sstevel@tonic-gate if (sd) {
9207c478bd9Sstevel@tonic-gate close(sd);
9217c478bd9Sstevel@tonic-gate }
9227c478bd9Sstevel@tonic-gate while (netstat_item) {
9237c478bd9Sstevel@tonic-gate item = netstat_item;
9247c478bd9Sstevel@tonic-gate netstat_item = netstat_item->next_item;
9257c478bd9Sstevel@tonic-gate if (item->valp) {
9267c478bd9Sstevel@tonic-gate free(item->valp);
9277c478bd9Sstevel@tonic-gate }
9287c478bd9Sstevel@tonic-gate free(item);
9297c478bd9Sstevel@tonic-gate }
9307c478bd9Sstevel@tonic-gate sd = mibopen();
9317c478bd9Sstevel@tonic-gate if (sd == -1) {
9327c478bd9Sstevel@tonic-gate #ifdef DEBUG
9337c478bd9Sstevel@tonic-gate fprintf(stderr, "mibopen() failed\n");
9347c478bd9Sstevel@tonic-gate #endif
9357c478bd9Sstevel@tonic-gate sd = 0;
9367c478bd9Sstevel@tonic-gate } else {
9377c478bd9Sstevel@tonic-gate if ((netstat_item = mibget(sd)) == NULL) {
9387c478bd9Sstevel@tonic-gate #ifdef DEBUG
9397c478bd9Sstevel@tonic-gate fprintf(stderr, "mibget() failed\n");
9407c478bd9Sstevel@tonic-gate #endif
9417c478bd9Sstevel@tonic-gate close(sd);
9427c478bd9Sstevel@tonic-gate sd = 0;
9437c478bd9Sstevel@tonic-gate }
9447c478bd9Sstevel@tonic-gate }
9457c478bd9Sstevel@tonic-gate #ifdef DEBUG
9467c478bd9Sstevel@tonic-gate fprintf(stderr, "mibget returned item: %x\n", netstat_item);
9477c478bd9Sstevel@tonic-gate #endif
9487c478bd9Sstevel@tonic-gate
9497c478bd9Sstevel@tonic-gate nnets = 0;
9507c478bd9Sstevel@tonic-gate net = &zeronet;
9517c478bd9Sstevel@tonic-gate
9527c478bd9Sstevel@tonic-gate if (netsnip)
9537c478bd9Sstevel@tonic-gate lastnet->next = netsnip;
9547c478bd9Sstevel@tonic-gate
9557c478bd9Sstevel@tonic-gate for (item = netstat_item; item; item = item->next_item) {
9567c478bd9Sstevel@tonic-gate #ifdef DEBUG_MIB
9577c478bd9Sstevel@tonic-gate fprintf(stderr, "\n--- Item %x ---\n", item);
9587c478bd9Sstevel@tonic-gate fprintf(stderr,
9597c478bd9Sstevel@tonic-gate "Group = %d, mib_id = %d, length = %d, valp = 0x%x\n",
9607c478bd9Sstevel@tonic-gate item->group, item->mib_id, item->length,
9617c478bd9Sstevel@tonic-gate item->valp);
9627c478bd9Sstevel@tonic-gate #endif
9637c478bd9Sstevel@tonic-gate if (item->group != MIB2_IP || item->mib_id != MIB2_IP_20)
9647c478bd9Sstevel@tonic-gate continue;
9657c478bd9Sstevel@tonic-gate ap = (mib2_ipAddrEntry_t *)item->valp;
9667c478bd9Sstevel@tonic-gate for (; (char *)ap < item->valp + item->length; ap++) {
9677c478bd9Sstevel@tonic-gate
9687c478bd9Sstevel@tonic-gate octetstr(namebuf, &ap->ipAdEntIfIndex, 'a');
9697c478bd9Sstevel@tonic-gate #ifdef DEBUG
9707c478bd9Sstevel@tonic-gate fprintf(stderr, "%s ", namebuf);
9717c478bd9Sstevel@tonic-gate #endif
9727c478bd9Sstevel@tonic-gate if (strlen(namebuf) == 0)
9737c478bd9Sstevel@tonic-gate continue;
9747c478bd9Sstevel@tonic-gate /*
9757c478bd9Sstevel@tonic-gate * We found a device of interest.
9767c478bd9Sstevel@tonic-gate * Now, let's see if there's a kstat for it.
977*d62bc4baSyz147064 * First we try to query the "link" kstats in case
978*d62bc4baSyz147064 * the link is renamed. If that fails, fallback
979*d62bc4baSyz147064 * to legacy ktats for those non-GLDv3 links.
9807c478bd9Sstevel@tonic-gate */
981*d62bc4baSyz147064 if (((ksp = kstat_lookup(kc, "link", 0, namebuf))
982*d62bc4baSyz147064 == NULL) && ((ksp = kstat_lookup(kc, NULL, -1,
983*d62bc4baSyz147064 namebuf)) == NULL)) {
9847c478bd9Sstevel@tonic-gate continue;
985*d62bc4baSyz147064 }
9867c478bd9Sstevel@tonic-gate if (ksp->ks_type != KSTAT_TYPE_NAMED)
9877c478bd9Sstevel@tonic-gate continue;
9887c478bd9Sstevel@tonic-gate if (kstat_read(kc, ksp, NULL) == -1)
9897c478bd9Sstevel@tonic-gate continue;
9907c478bd9Sstevel@tonic-gate prevnet = net;
9917c478bd9Sstevel@tonic-gate if (net->next)
9927c478bd9Sstevel@tonic-gate net = net->next;
9937c478bd9Sstevel@tonic-gate else {
9947c478bd9Sstevel@tonic-gate safe_zalloc((void **)&net->next,
9957c478bd9Sstevel@tonic-gate sizeof (struct netinfo), 0);
9967c478bd9Sstevel@tonic-gate net = net->next;
9977c478bd9Sstevel@tonic-gate net->next = NULLNET;
9987c478bd9Sstevel@tonic-gate }
9997c478bd9Sstevel@tonic-gate net->ks = ksp;
10007c478bd9Sstevel@tonic-gate net->ipackets = kstat_data_lookup(net->ks,
10017c478bd9Sstevel@tonic-gate "ipackets");
10027c478bd9Sstevel@tonic-gate net->opackets = kstat_data_lookup(net->ks,
10037c478bd9Sstevel@tonic-gate "opackets");
10047c478bd9Sstevel@tonic-gate net->ierrors = kstat_data_lookup(net->ks,
10057c478bd9Sstevel@tonic-gate "ierrors");
10067c478bd9Sstevel@tonic-gate net->oerrors = kstat_data_lookup(net->ks,
10077c478bd9Sstevel@tonic-gate "oerrors");
10087c478bd9Sstevel@tonic-gate net->collisions = kstat_data_lookup(net->ks,
10097c478bd9Sstevel@tonic-gate "collisions");
10107c478bd9Sstevel@tonic-gate /*
10117c478bd9Sstevel@tonic-gate * Insertion sort on the name
10127c478bd9Sstevel@tonic-gate */
10137c478bd9Sstevel@tonic-gate comp = &zeronet;
10147c478bd9Sstevel@tonic-gate while (strcmp(net->ks->ks_name,
10157c478bd9Sstevel@tonic-gate comp->next->ks->ks_name) > 0)
10167c478bd9Sstevel@tonic-gate comp = comp->next;
10177c478bd9Sstevel@tonic-gate if (prevnet != comp) {
10187c478bd9Sstevel@tonic-gate prevnet->next = net->next;
10197c478bd9Sstevel@tonic-gate net->next = comp->next;
10207c478bd9Sstevel@tonic-gate comp->next = net;
10217c478bd9Sstevel@tonic-gate net = prevnet;
10227c478bd9Sstevel@tonic-gate }
10237c478bd9Sstevel@tonic-gate nnets++;
10247c478bd9Sstevel@tonic-gate }
10257c478bd9Sstevel@tonic-gate #ifdef DEBUG
10267c478bd9Sstevel@tonic-gate fprintf(stderr, "\n");
10277c478bd9Sstevel@tonic-gate #endif
10287c478bd9Sstevel@tonic-gate }
10297c478bd9Sstevel@tonic-gate /*
10307c478bd9Sstevel@tonic-gate * Put a snip in the linked list of netinfos. The idea:
10317c478bd9Sstevel@tonic-gate * If there was a state change such that now there are fewer
10327c478bd9Sstevel@tonic-gate * nets, we snip the list and retain the tail, rather than
10337c478bd9Sstevel@tonic-gate * freeing it. At the next state change, we clip the tail back on.
10347c478bd9Sstevel@tonic-gate * This prevents a lot of malloc/free activity, and it's simpler.
10357c478bd9Sstevel@tonic-gate */
10367c478bd9Sstevel@tonic-gate lastnet = net;
10377c478bd9Sstevel@tonic-gate netsnip = net->next;
10387c478bd9Sstevel@tonic-gate net->next = NULLNET;
10397c478bd9Sstevel@tonic-gate
10407c478bd9Sstevel@tonic-gate firstnet = zeronet.next;
10417c478bd9Sstevel@tonic-gate }
10427c478bd9Sstevel@tonic-gate
10437c478bd9Sstevel@tonic-gate static int
netinfo_load(void)10447c478bd9Sstevel@tonic-gate netinfo_load(void)
10457c478bd9Sstevel@tonic-gate {
10467c478bd9Sstevel@tonic-gate struct netinfo *net;
10477c478bd9Sstevel@tonic-gate
10487c478bd9Sstevel@tonic-gate if (netstat_item == NULL) {
10497c478bd9Sstevel@tonic-gate #ifdef DEBUG
10507c478bd9Sstevel@tonic-gate fprintf(stderr, "No net stats\n");
10517c478bd9Sstevel@tonic-gate #endif
10527c478bd9Sstevel@tonic-gate return (0);
10537c478bd9Sstevel@tonic-gate }
10547c478bd9Sstevel@tonic-gate
10557c478bd9Sstevel@tonic-gate stats_s4.if_ipackets =
10567c478bd9Sstevel@tonic-gate stats_s4.if_opackets =
10577c478bd9Sstevel@tonic-gate stats_s4.if_ierrors =
10587c478bd9Sstevel@tonic-gate stats_s4.if_oerrors =
10597c478bd9Sstevel@tonic-gate stats_s4.if_collisions = 0;
10607c478bd9Sstevel@tonic-gate
10617c478bd9Sstevel@tonic-gate for (net = firstnet; net; net = net->next) {
10627c478bd9Sstevel@tonic-gate if (kstat_read(kc, net->ks, NULL) == -1)
10637c478bd9Sstevel@tonic-gate return (1);
10647c478bd9Sstevel@tonic-gate if (net->ipackets)
10657c478bd9Sstevel@tonic-gate stats_s4.if_ipackets += net->ipackets->value.ul;
10667c478bd9Sstevel@tonic-gate if (net->opackets)
10677c478bd9Sstevel@tonic-gate stats_s4.if_opackets += net->opackets->value.ul;
10687c478bd9Sstevel@tonic-gate if (net->ierrors)
10697c478bd9Sstevel@tonic-gate stats_s4.if_ierrors += net->ierrors->value.ul;
10707c478bd9Sstevel@tonic-gate if (net->oerrors)
10717c478bd9Sstevel@tonic-gate stats_s4.if_oerrors += net->oerrors->value.ul;
10727c478bd9Sstevel@tonic-gate if (net->collisions)
10737c478bd9Sstevel@tonic-gate stats_s4.if_collisions += net->collisions->value.ul;
10747c478bd9Sstevel@tonic-gate }
10757c478bd9Sstevel@tonic-gate #ifdef DEBUG
10767c478bd9Sstevel@tonic-gate fprintf(stderr,
10777c478bd9Sstevel@tonic-gate "ipackets: %d opackets: %d ierrors: %d oerrors: %d colls: %d\n",
10787c478bd9Sstevel@tonic-gate stats_s4.if_ipackets,
10797c478bd9Sstevel@tonic-gate stats_s4.if_opackets,
10807c478bd9Sstevel@tonic-gate stats_s4.if_ierrors,
10817c478bd9Sstevel@tonic-gate stats_s4.if_oerrors,
10827c478bd9Sstevel@tonic-gate stats_s4.if_collisions);
10837c478bd9Sstevel@tonic-gate #endif
10847c478bd9Sstevel@tonic-gate return (0);
10857c478bd9Sstevel@tonic-gate }
10867c478bd9Sstevel@tonic-gate
10877c478bd9Sstevel@tonic-gate static void
kstat_copy(kstat_t * src,kstat_t * dst,int fr)10887c478bd9Sstevel@tonic-gate kstat_copy(kstat_t *src, kstat_t *dst, int fr)
10897c478bd9Sstevel@tonic-gate {
10907c478bd9Sstevel@tonic-gate if (fr)
10917c478bd9Sstevel@tonic-gate free(dst->ks_data);
10927c478bd9Sstevel@tonic-gate *dst = *src;
10937c478bd9Sstevel@tonic-gate if (src->ks_data != NULL) {
10947c478bd9Sstevel@tonic-gate safe_zalloc(&dst->ks_data, src->ks_data_size, 0);
10957c478bd9Sstevel@tonic-gate (void) memcpy(dst->ks_data, src->ks_data, src->ks_data_size);
10967c478bd9Sstevel@tonic-gate } else {
10977c478bd9Sstevel@tonic-gate dst->ks_data = NULL;
10987c478bd9Sstevel@tonic-gate dst->ks_data_size = 0;
10997c478bd9Sstevel@tonic-gate }
11007c478bd9Sstevel@tonic-gate }
1101