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 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 * 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 * 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 * 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 * 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 * 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 * 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 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 * 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 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 * 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 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 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 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 * 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 * 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 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 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 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 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 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 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 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 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