1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2003 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate /* 30*7c478bd9Sstevel@tonic-gate * rstat service: built with rstat.x 31*7c478bd9Sstevel@tonic-gate */ 32*7c478bd9Sstevel@tonic-gate 33*7c478bd9Sstevel@tonic-gate #include <stdio.h> 34*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 35*7c478bd9Sstevel@tonic-gate #include <stdarg.h> 36*7c478bd9Sstevel@tonic-gate #include <string.h> 37*7c478bd9Sstevel@tonic-gate #include <signal.h> 38*7c478bd9Sstevel@tonic-gate #include <utmpx.h> 39*7c478bd9Sstevel@tonic-gate #include <nlist.h> 40*7c478bd9Sstevel@tonic-gate #include <fcntl.h> 41*7c478bd9Sstevel@tonic-gate #include <syslog.h> 42*7c478bd9Sstevel@tonic-gate #include <kstat.h> 43*7c478bd9Sstevel@tonic-gate 44*7c478bd9Sstevel@tonic-gate #include <rpc/rpc.h> 45*7c478bd9Sstevel@tonic-gate 46*7c478bd9Sstevel@tonic-gate #include <sys/socket.h> 47*7c478bd9Sstevel@tonic-gate #include <sys/cpuvar.h> 48*7c478bd9Sstevel@tonic-gate #include <sys/sysinfo.h> 49*7c478bd9Sstevel@tonic-gate #include <sys/systm.h> 50*7c478bd9Sstevel@tonic-gate #include <errno.h> 51*7c478bd9Sstevel@tonic-gate #include <sys/stropts.h> 52*7c478bd9Sstevel@tonic-gate #include <sys/tihdr.h> 53*7c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 54*7c478bd9Sstevel@tonic-gate 55*7c478bd9Sstevel@tonic-gate #include <net/if.h> 56*7c478bd9Sstevel@tonic-gate #include <inet/mib2.h> 57*7c478bd9Sstevel@tonic-gate 58*7c478bd9Sstevel@tonic-gate #include "rstat.h" 59*7c478bd9Sstevel@tonic-gate #include "rstat_v2.h" 60*7c478bd9Sstevel@tonic-gate 61*7c478bd9Sstevel@tonic-gate typedef struct { 62*7c478bd9Sstevel@tonic-gate kstat_t sys; 63*7c478bd9Sstevel@tonic-gate kstat_t vm; 64*7c478bd9Sstevel@tonic-gate } _cpu_stats_t; 65*7c478bd9Sstevel@tonic-gate 66*7c478bd9Sstevel@tonic-gate /* 67*7c478bd9Sstevel@tonic-gate * system and cpu stats 68*7c478bd9Sstevel@tonic-gate */ 69*7c478bd9Sstevel@tonic-gate static kstat_ctl_t *kc; /* libkstat cookie */ 70*7c478bd9Sstevel@tonic-gate static int ncpus; 71*7c478bd9Sstevel@tonic-gate static _cpu_stats_t *cpu_stats_list = NULL; 72*7c478bd9Sstevel@tonic-gate static kstat_t *system_misc_ksp; 73*7c478bd9Sstevel@tonic-gate static kstat_named_t *boot_time_knp; 74*7c478bd9Sstevel@tonic-gate static kstat_named_t *avenrun_1min_knp, *avenrun_5min_knp, *avenrun_15min_knp; 75*7c478bd9Sstevel@tonic-gate static int hz; 76*7c478bd9Sstevel@tonic-gate static struct timeval btm; /* boottime */ 77*7c478bd9Sstevel@tonic-gate 78*7c478bd9Sstevel@tonic-gate /* 79*7c478bd9Sstevel@tonic-gate * network interface stats 80*7c478bd9Sstevel@tonic-gate */ 81*7c478bd9Sstevel@tonic-gate 82*7c478bd9Sstevel@tonic-gate typedef struct mib_item_s { 83*7c478bd9Sstevel@tonic-gate struct mib_item_s *next_item; 84*7c478bd9Sstevel@tonic-gate long group; 85*7c478bd9Sstevel@tonic-gate long mib_id; 86*7c478bd9Sstevel@tonic-gate long length; 87*7c478bd9Sstevel@tonic-gate char *valp; 88*7c478bd9Sstevel@tonic-gate } mib_item_t; 89*7c478bd9Sstevel@tonic-gate 90*7c478bd9Sstevel@tonic-gate mib_item_t *netstat_item; 91*7c478bd9Sstevel@tonic-gate 92*7c478bd9Sstevel@tonic-gate /* 93*7c478bd9Sstevel@tonic-gate * disk stats 94*7c478bd9Sstevel@tonic-gate */ 95*7c478bd9Sstevel@tonic-gate 96*7c478bd9Sstevel@tonic-gate struct diskinfo { 97*7c478bd9Sstevel@tonic-gate struct diskinfo *next; 98*7c478bd9Sstevel@tonic-gate kstat_t *ks; 99*7c478bd9Sstevel@tonic-gate kstat_io_t kios; 100*7c478bd9Sstevel@tonic-gate }; 101*7c478bd9Sstevel@tonic-gate 102*7c478bd9Sstevel@tonic-gate #define NULLDISK (struct diskinfo *)0 103*7c478bd9Sstevel@tonic-gate static struct diskinfo zerodisk = { NULL, NULL }; 104*7c478bd9Sstevel@tonic-gate static struct diskinfo *firstdisk = NULLDISK; 105*7c478bd9Sstevel@tonic-gate static struct diskinfo *lastdisk = NULLDISK; 106*7c478bd9Sstevel@tonic-gate static struct diskinfo *snip = NULLDISK; 107*7c478bd9Sstevel@tonic-gate static int ndisks; 108*7c478bd9Sstevel@tonic-gate 109*7c478bd9Sstevel@tonic-gate /* 110*7c478bd9Sstevel@tonic-gate * net stats 111*7c478bd9Sstevel@tonic-gate */ 112*7c478bd9Sstevel@tonic-gate 113*7c478bd9Sstevel@tonic-gate struct netinfo { 114*7c478bd9Sstevel@tonic-gate struct netinfo *next; 115*7c478bd9Sstevel@tonic-gate kstat_t *ks; 116*7c478bd9Sstevel@tonic-gate kstat_named_t *ipackets; 117*7c478bd9Sstevel@tonic-gate kstat_named_t *opackets; 118*7c478bd9Sstevel@tonic-gate kstat_named_t *ierrors; 119*7c478bd9Sstevel@tonic-gate kstat_named_t *oerrors; 120*7c478bd9Sstevel@tonic-gate kstat_named_t *collisions; 121*7c478bd9Sstevel@tonic-gate }; 122*7c478bd9Sstevel@tonic-gate 123*7c478bd9Sstevel@tonic-gate #define NULLNET (struct netinfo *)0 124*7c478bd9Sstevel@tonic-gate static struct netinfo zeronet = { NULL, NULL, NULL, NULL, NULL, NULL, NULL }; 125*7c478bd9Sstevel@tonic-gate static struct netinfo *firstnet = NULLNET; 126*7c478bd9Sstevel@tonic-gate static struct netinfo *lastnet = NULLNET; 127*7c478bd9Sstevel@tonic-gate static struct netinfo *netsnip = NULLNET; 128*7c478bd9Sstevel@tonic-gate static int nnets; 129*7c478bd9Sstevel@tonic-gate 130*7c478bd9Sstevel@tonic-gate /* 131*7c478bd9Sstevel@tonic-gate * Define EXIT_WHEN_IDLE if you are able to have this program invoked 132*7c478bd9Sstevel@tonic-gate * automatically on demand (as from inetd). When defined, the service 133*7c478bd9Sstevel@tonic-gate * will terminated after being idle for 120 seconds. 134*7c478bd9Sstevel@tonic-gate */ 135*7c478bd9Sstevel@tonic-gate 136*7c478bd9Sstevel@tonic-gate #define EXIT_WHEN_IDLE 1 137*7c478bd9Sstevel@tonic-gate 138*7c478bd9Sstevel@tonic-gate int sincelastreq = 0; /* number of alarms since last request */ 139*7c478bd9Sstevel@tonic-gate #ifdef EXIT_WHEN_IDLE 140*7c478bd9Sstevel@tonic-gate #define CLOSEDOWN 120 /* how long to wait before exiting */ 141*7c478bd9Sstevel@tonic-gate #endif /* def EXIT_WHEN_IDLE */ 142*7c478bd9Sstevel@tonic-gate 143*7c478bd9Sstevel@tonic-gate statstime stats_s3; 144*7c478bd9Sstevel@tonic-gate statsvar stats_s4; 145*7c478bd9Sstevel@tonic-gate /* V2 support for backwards compatibility to pre-5.0 systems */ 146*7c478bd9Sstevel@tonic-gate statsswtch stats_s2; 147*7c478bd9Sstevel@tonic-gate 148*7c478bd9Sstevel@tonic-gate static stat_is_init = 0; 149*7c478bd9Sstevel@tonic-gate 150*7c478bd9Sstevel@tonic-gate static void fail(int, char *, ...); 151*7c478bd9Sstevel@tonic-gate static void safe_zalloc(void **, int, int); 152*7c478bd9Sstevel@tonic-gate static kid_t safe_kstat_read(kstat_ctl_t *, kstat_t *, void *); 153*7c478bd9Sstevel@tonic-gate static kstat_t *safe_kstat_lookup(kstat_ctl_t *, char *, int, char *); 154*7c478bd9Sstevel@tonic-gate static void *safe_kstat_data_lookup(kstat_t *, char *); 155*7c478bd9Sstevel@tonic-gate static void system_stat_init(void); 156*7c478bd9Sstevel@tonic-gate static int system_stat_load(void); 157*7c478bd9Sstevel@tonic-gate static void init_disks(void); 158*7c478bd9Sstevel@tonic-gate static int diskinfo_load(void); 159*7c478bd9Sstevel@tonic-gate static void init_net(void); 160*7c478bd9Sstevel@tonic-gate static int netinfo_load(void); 161*7c478bd9Sstevel@tonic-gate 162*7c478bd9Sstevel@tonic-gate static void updatestat(int); 163*7c478bd9Sstevel@tonic-gate 164*7c478bd9Sstevel@tonic-gate static mib_item_t *mibget(int sd); 165*7c478bd9Sstevel@tonic-gate static int mibopen(void); 166*7c478bd9Sstevel@tonic-gate static char *octetstr(char *buf, Octet_t *op, int code); 167*7c478bd9Sstevel@tonic-gate 168*7c478bd9Sstevel@tonic-gate static void kstat_copy(kstat_t *, kstat_t *, int); 169*7c478bd9Sstevel@tonic-gate 170*7c478bd9Sstevel@tonic-gate static char *cmdname = "rpc.rstatd"; 171*7c478bd9Sstevel@tonic-gate 172*7c478bd9Sstevel@tonic-gate #define CPU_STAT(ksp, name) (((kstat_named_t *)safe_kstat_data_lookup( \ 173*7c478bd9Sstevel@tonic-gate (ksp), (name)))->value.ui64) 174*7c478bd9Sstevel@tonic-gate static _cpu_stats_t cpu_stats_all = { 0 }; 175*7c478bd9Sstevel@tonic-gate 176*7c478bd9Sstevel@tonic-gate static void 177*7c478bd9Sstevel@tonic-gate stat_init(void) 178*7c478bd9Sstevel@tonic-gate { 179*7c478bd9Sstevel@tonic-gate struct utmpx *utmpx, utmpx_id; 180*7c478bd9Sstevel@tonic-gate 181*7c478bd9Sstevel@tonic-gate stat_is_init = 1; 182*7c478bd9Sstevel@tonic-gate 183*7c478bd9Sstevel@tonic-gate if ((kc = kstat_open()) == NULL) 184*7c478bd9Sstevel@tonic-gate fail(1, "kstat_open(): can't open /dev/kstat"); 185*7c478bd9Sstevel@tonic-gate 186*7c478bd9Sstevel@tonic-gate /* 187*7c478bd9Sstevel@tonic-gate * Preallocate minimal set of drive entries. 188*7c478bd9Sstevel@tonic-gate */ 189*7c478bd9Sstevel@tonic-gate 190*7c478bd9Sstevel@tonic-gate if (stats_s4.dk_xfer.dk_xfer_val == NULL) { 191*7c478bd9Sstevel@tonic-gate stats_s4.dk_xfer.dk_xfer_len = RSTAT_DK_NDRIVE; 192*7c478bd9Sstevel@tonic-gate stats_s4.dk_xfer.dk_xfer_val = 193*7c478bd9Sstevel@tonic-gate (int *)calloc(RSTAT_DK_NDRIVE, sizeof (int)); 194*7c478bd9Sstevel@tonic-gate } 195*7c478bd9Sstevel@tonic-gate 196*7c478bd9Sstevel@tonic-gate system_stat_init(); 197*7c478bd9Sstevel@tonic-gate init_disks(); 198*7c478bd9Sstevel@tonic-gate init_net(); 199*7c478bd9Sstevel@tonic-gate 200*7c478bd9Sstevel@tonic-gate /* 201*7c478bd9Sstevel@tonic-gate * To get the boot time, use utmpx, which is per-zone, but fall back 202*7c478bd9Sstevel@tonic-gate * to the system-wide kstat if utmpx is hosed for any reason. 203*7c478bd9Sstevel@tonic-gate */ 204*7c478bd9Sstevel@tonic-gate utmpx_id.ut_type = BOOT_TIME; 205*7c478bd9Sstevel@tonic-gate if ((utmpx = getutxid(&utmpx_id)) != NULL) 206*7c478bd9Sstevel@tonic-gate btm = utmpx->ut_tv; 207*7c478bd9Sstevel@tonic-gate else { 208*7c478bd9Sstevel@tonic-gate btm.tv_sec = boot_time_knp->value.ul; 209*7c478bd9Sstevel@tonic-gate btm.tv_usec = 0; /* don't bother with usecs for boot time */ 210*7c478bd9Sstevel@tonic-gate } 211*7c478bd9Sstevel@tonic-gate endutxent(); 212*7c478bd9Sstevel@tonic-gate stats_s4.boottime.tv_sec = 213*7c478bd9Sstevel@tonic-gate stats_s2.boottime.tv_sec = 214*7c478bd9Sstevel@tonic-gate stats_s3.boottime.tv_sec = btm.tv_sec; 215*7c478bd9Sstevel@tonic-gate stats_s4.boottime.tv_usec = 216*7c478bd9Sstevel@tonic-gate stats_s2.boottime.tv_usec = 217*7c478bd9Sstevel@tonic-gate stats_s3.boottime.tv_usec = btm.tv_usec; 218*7c478bd9Sstevel@tonic-gate 219*7c478bd9Sstevel@tonic-gate updatestat(0); 220*7c478bd9Sstevel@tonic-gate alarm(1); 221*7c478bd9Sstevel@tonic-gate signal(SIGALRM, updatestat); 222*7c478bd9Sstevel@tonic-gate sleep(2); /* allow for one wake-up */ 223*7c478bd9Sstevel@tonic-gate } 224*7c478bd9Sstevel@tonic-gate 225*7c478bd9Sstevel@tonic-gate statsvar * 226*7c478bd9Sstevel@tonic-gate rstatproc_stats_4_svc(argp, svcrq) 227*7c478bd9Sstevel@tonic-gate void *argp; 228*7c478bd9Sstevel@tonic-gate struct svc_req *svcrq; 229*7c478bd9Sstevel@tonic-gate { 230*7c478bd9Sstevel@tonic-gate if (! stat_is_init) 231*7c478bd9Sstevel@tonic-gate stat_init(); 232*7c478bd9Sstevel@tonic-gate #ifdef EXIT_WHEN_IDLE 233*7c478bd9Sstevel@tonic-gate sincelastreq = 0; 234*7c478bd9Sstevel@tonic-gate #endif 235*7c478bd9Sstevel@tonic-gate return (&stats_s4); 236*7c478bd9Sstevel@tonic-gate } 237*7c478bd9Sstevel@tonic-gate 238*7c478bd9Sstevel@tonic-gate statstime * 239*7c478bd9Sstevel@tonic-gate rstatproc_stats_3_svc(argp, svcrq) 240*7c478bd9Sstevel@tonic-gate void *argp; 241*7c478bd9Sstevel@tonic-gate struct svc_req *svcrq; 242*7c478bd9Sstevel@tonic-gate { 243*7c478bd9Sstevel@tonic-gate if (! stat_is_init) 244*7c478bd9Sstevel@tonic-gate stat_init(); 245*7c478bd9Sstevel@tonic-gate #ifdef EXIT_WHEN_IDLE 246*7c478bd9Sstevel@tonic-gate sincelastreq = 0; 247*7c478bd9Sstevel@tonic-gate #endif 248*7c478bd9Sstevel@tonic-gate return (&stats_s3); 249*7c478bd9Sstevel@tonic-gate } 250*7c478bd9Sstevel@tonic-gate 251*7c478bd9Sstevel@tonic-gate statsswtch * 252*7c478bd9Sstevel@tonic-gate rstatproc_stats_2_svc(argp, svcrq) 253*7c478bd9Sstevel@tonic-gate void *argp; 254*7c478bd9Sstevel@tonic-gate struct svc_req *svcrq; 255*7c478bd9Sstevel@tonic-gate { 256*7c478bd9Sstevel@tonic-gate if (! stat_is_init) 257*7c478bd9Sstevel@tonic-gate stat_init(); 258*7c478bd9Sstevel@tonic-gate #ifdef EXIT_WHEN_IDLE 259*7c478bd9Sstevel@tonic-gate sincelastreq = 0; 260*7c478bd9Sstevel@tonic-gate #endif 261*7c478bd9Sstevel@tonic-gate return (&stats_s2); 262*7c478bd9Sstevel@tonic-gate } 263*7c478bd9Sstevel@tonic-gate 264*7c478bd9Sstevel@tonic-gate 265*7c478bd9Sstevel@tonic-gate uint_t * 266*7c478bd9Sstevel@tonic-gate rstatproc_havedisk_4_svc(argp, svcrq) 267*7c478bd9Sstevel@tonic-gate void *argp; 268*7c478bd9Sstevel@tonic-gate struct svc_req *svcrq; 269*7c478bd9Sstevel@tonic-gate { 270*7c478bd9Sstevel@tonic-gate return (rstatproc_havedisk_3_svc(argp, svcrq)); 271*7c478bd9Sstevel@tonic-gate } 272*7c478bd9Sstevel@tonic-gate 273*7c478bd9Sstevel@tonic-gate uint_t * 274*7c478bd9Sstevel@tonic-gate rstatproc_havedisk_3_svc(argp, svcrq) 275*7c478bd9Sstevel@tonic-gate void *argp; 276*7c478bd9Sstevel@tonic-gate struct svc_req *svcrq; 277*7c478bd9Sstevel@tonic-gate { 278*7c478bd9Sstevel@tonic-gate static uint_t have; 279*7c478bd9Sstevel@tonic-gate 280*7c478bd9Sstevel@tonic-gate if (! stat_is_init) 281*7c478bd9Sstevel@tonic-gate stat_init(); 282*7c478bd9Sstevel@tonic-gate #ifdef EXIT_WHEN_IDLE 283*7c478bd9Sstevel@tonic-gate sincelastreq = 0; 284*7c478bd9Sstevel@tonic-gate #endif 285*7c478bd9Sstevel@tonic-gate have = (ndisks != 0); 286*7c478bd9Sstevel@tonic-gate return (&have); 287*7c478bd9Sstevel@tonic-gate } 288*7c478bd9Sstevel@tonic-gate 289*7c478bd9Sstevel@tonic-gate uint_t * 290*7c478bd9Sstevel@tonic-gate rstatproc_havedisk_2_svc(argp, svcrq) 291*7c478bd9Sstevel@tonic-gate void *argp; 292*7c478bd9Sstevel@tonic-gate struct svc_req *svcrq; 293*7c478bd9Sstevel@tonic-gate { 294*7c478bd9Sstevel@tonic-gate return (rstatproc_havedisk_3_svc(argp, svcrq)); 295*7c478bd9Sstevel@tonic-gate } 296*7c478bd9Sstevel@tonic-gate 297*7c478bd9Sstevel@tonic-gate void 298*7c478bd9Sstevel@tonic-gate updatestat(int ignored) 299*7c478bd9Sstevel@tonic-gate { 300*7c478bd9Sstevel@tonic-gate extern int _rpcpmstart; /* Started by a port monitor ? */ 301*7c478bd9Sstevel@tonic-gate extern int _rpcsvcdirty; /* Still serving ? */ 302*7c478bd9Sstevel@tonic-gate 303*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 304*7c478bd9Sstevel@tonic-gate fprintf(stderr, "entering updatestat\n"); 305*7c478bd9Sstevel@tonic-gate #endif 306*7c478bd9Sstevel@tonic-gate #ifdef EXIT_WHEN_IDLE 307*7c478bd9Sstevel@tonic-gate if (_rpcpmstart && sincelastreq >= CLOSEDOWN && !_rpcsvcdirty) { 308*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 309*7c478bd9Sstevel@tonic-gate fprintf(stderr, "about to closedown\n"); 310*7c478bd9Sstevel@tonic-gate #endif 311*7c478bd9Sstevel@tonic-gate exit(0); 312*7c478bd9Sstevel@tonic-gate } 313*7c478bd9Sstevel@tonic-gate sincelastreq++; 314*7c478bd9Sstevel@tonic-gate #endif /* def EXIT_WHEN_IDLE */ 315*7c478bd9Sstevel@tonic-gate 316*7c478bd9Sstevel@tonic-gate (void) alarm(0); 317*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 318*7c478bd9Sstevel@tonic-gate fprintf(stderr, "boottime: %d %d\n", stats_s3.boottime.tv_sec, 319*7c478bd9Sstevel@tonic-gate stats_s3.boottime.tv_usec); 320*7c478bd9Sstevel@tonic-gate #endif 321*7c478bd9Sstevel@tonic-gate while (system_stat_load() || diskinfo_load() || netinfo_load()) { 322*7c478bd9Sstevel@tonic-gate (void) kstat_chain_update(kc); 323*7c478bd9Sstevel@tonic-gate system_stat_init(); 324*7c478bd9Sstevel@tonic-gate init_disks(); 325*7c478bd9Sstevel@tonic-gate init_net(); 326*7c478bd9Sstevel@tonic-gate } 327*7c478bd9Sstevel@tonic-gate stats_s4.cp_time.cp_time_len = CPU_STATES; 328*7c478bd9Sstevel@tonic-gate if (stats_s4.cp_time.cp_time_val == NULL) 329*7c478bd9Sstevel@tonic-gate stats_s4.cp_time.cp_time_val = 330*7c478bd9Sstevel@tonic-gate malloc(stats_s4.cp_time.cp_time_len * sizeof (int)); 331*7c478bd9Sstevel@tonic-gate stats_s2.cp_time[RSTAT_CPU_USER] = 332*7c478bd9Sstevel@tonic-gate stats_s3.cp_time[RSTAT_CPU_USER] = 333*7c478bd9Sstevel@tonic-gate stats_s4.cp_time.cp_time_val[RSTAT_CPU_USER] = 334*7c478bd9Sstevel@tonic-gate CPU_STAT(&cpu_stats_all.sys, "cpu_ticks_user"); 335*7c478bd9Sstevel@tonic-gate stats_s2.cp_time[RSTAT_CPU_NICE] = 336*7c478bd9Sstevel@tonic-gate stats_s3.cp_time[RSTAT_CPU_NICE] = 337*7c478bd9Sstevel@tonic-gate stats_s4.cp_time.cp_time_val[RSTAT_CPU_NICE] = 338*7c478bd9Sstevel@tonic-gate CPU_STAT(&cpu_stats_all.sys, "cpu_ticks_wait"); 339*7c478bd9Sstevel@tonic-gate stats_s2.cp_time[RSTAT_CPU_SYS] = 340*7c478bd9Sstevel@tonic-gate stats_s3.cp_time[RSTAT_CPU_SYS] = 341*7c478bd9Sstevel@tonic-gate stats_s4.cp_time.cp_time_val[RSTAT_CPU_SYS] = 342*7c478bd9Sstevel@tonic-gate CPU_STAT(&cpu_stats_all.sys, "cpu_ticks_kernel"); 343*7c478bd9Sstevel@tonic-gate stats_s2.cp_time[RSTAT_CPU_IDLE] = 344*7c478bd9Sstevel@tonic-gate stats_s3.cp_time[RSTAT_CPU_IDLE] = 345*7c478bd9Sstevel@tonic-gate stats_s4.cp_time.cp_time_val[RSTAT_CPU_IDLE] = 346*7c478bd9Sstevel@tonic-gate CPU_STAT(&cpu_stats_all.sys, "cpu_ticks_idle"); 347*7c478bd9Sstevel@tonic-gate 348*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 349*7c478bd9Sstevel@tonic-gate fprintf(stderr, "cpu: %d %d %d %d\n", 350*7c478bd9Sstevel@tonic-gate CPU_STAT(&cpu_stats_all.sys, "cpu_ticks_user"), 351*7c478bd9Sstevel@tonic-gate CPU_STAT(&cpu_stats_all.sys, "cpu_ticks_wait"), 352*7c478bd9Sstevel@tonic-gate CPU_STAT(&cpu_stats_all.sys, "cpu_ticks_kernel"), 353*7c478bd9Sstevel@tonic-gate CPU_STAT(&cpu_stats_all.sys, "cpu_ticks_idle")); 354*7c478bd9Sstevel@tonic-gate fprintf(stderr, "cp_time: %d %d %d %d\n", 355*7c478bd9Sstevel@tonic-gate stats_s3.cp_time[RSTAT_CPU_USER], 356*7c478bd9Sstevel@tonic-gate stats_s3.cp_time[RSTAT_CPU_NICE], 357*7c478bd9Sstevel@tonic-gate stats_s3.cp_time[RSTAT_CPU_SYS], 358*7c478bd9Sstevel@tonic-gate stats_s3.cp_time[RSTAT_CPU_IDLE]); 359*7c478bd9Sstevel@tonic-gate #endif 360*7c478bd9Sstevel@tonic-gate 361*7c478bd9Sstevel@tonic-gate /* current time */ 362*7c478bd9Sstevel@tonic-gate gettimeofday((struct timeval *)&stats_s3.curtime, NULL); 363*7c478bd9Sstevel@tonic-gate stats_s4.curtime = stats_s3.curtime; 364*7c478bd9Sstevel@tonic-gate 365*7c478bd9Sstevel@tonic-gate stats_s2.v_pgpgin = 366*7c478bd9Sstevel@tonic-gate stats_s3.v_pgpgin = 367*7c478bd9Sstevel@tonic-gate stats_s4.v_pgpgin = CPU_STAT(&cpu_stats_all.vm, "pgpgin"); 368*7c478bd9Sstevel@tonic-gate stats_s2.v_pgpgout = 369*7c478bd9Sstevel@tonic-gate stats_s3.v_pgpgout = 370*7c478bd9Sstevel@tonic-gate stats_s4.v_pgpgout = CPU_STAT(&cpu_stats_all.vm, "pgpgout"); 371*7c478bd9Sstevel@tonic-gate stats_s2.v_pswpin = 372*7c478bd9Sstevel@tonic-gate stats_s3.v_pswpin = 373*7c478bd9Sstevel@tonic-gate stats_s4.v_pswpin = CPU_STAT(&cpu_stats_all.vm, "pgswapin"); 374*7c478bd9Sstevel@tonic-gate stats_s2.v_pswpout = 375*7c478bd9Sstevel@tonic-gate stats_s3.v_pswpout = 376*7c478bd9Sstevel@tonic-gate stats_s4.v_pswpout = CPU_STAT(&cpu_stats_all.vm, "pgswapout"); 377*7c478bd9Sstevel@tonic-gate stats_s3.v_intr = CPU_STAT(&cpu_stats_all.sys, "intr"); 378*7c478bd9Sstevel@tonic-gate stats_s3.v_intr -= hz*(stats_s3.curtime.tv_sec - btm.tv_sec) + 379*7c478bd9Sstevel@tonic-gate hz*(stats_s3.curtime.tv_usec - btm.tv_usec)/1000000; 380*7c478bd9Sstevel@tonic-gate stats_s2.v_intr = 381*7c478bd9Sstevel@tonic-gate stats_s4.v_intr = stats_s3.v_intr; 382*7c478bd9Sstevel@tonic-gate /* swtch not in V1 */ 383*7c478bd9Sstevel@tonic-gate stats_s2.v_swtch = 384*7c478bd9Sstevel@tonic-gate stats_s3.v_swtch = 385*7c478bd9Sstevel@tonic-gate stats_s4.v_swtch = CPU_STAT(&cpu_stats_all.sys, "pswitch"); 386*7c478bd9Sstevel@tonic-gate 387*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 388*7c478bd9Sstevel@tonic-gate fprintf(stderr, 389*7c478bd9Sstevel@tonic-gate "pgin: %d pgout: %d swpin: %d swpout: %d intr: %d swtch: %d\n", 390*7c478bd9Sstevel@tonic-gate stats_s3.v_pgpgin, 391*7c478bd9Sstevel@tonic-gate stats_s3.v_pgpgout, 392*7c478bd9Sstevel@tonic-gate stats_s3.v_pswpin, 393*7c478bd9Sstevel@tonic-gate stats_s3.v_pswpout, 394*7c478bd9Sstevel@tonic-gate stats_s3.v_intr, 395*7c478bd9Sstevel@tonic-gate stats_s3.v_swtch); 396*7c478bd9Sstevel@tonic-gate #endif 397*7c478bd9Sstevel@tonic-gate /* 398*7c478bd9Sstevel@tonic-gate * V2 and V3 of rstat are limited to RSTAT_DK_NDRIVE drives 399*7c478bd9Sstevel@tonic-gate */ 400*7c478bd9Sstevel@tonic-gate memcpy(stats_s3.dk_xfer, stats_s4.dk_xfer.dk_xfer_val, 401*7c478bd9Sstevel@tonic-gate RSTAT_DK_NDRIVE * sizeof (int)); 402*7c478bd9Sstevel@tonic-gate memcpy(stats_s2.dk_xfer, stats_s4.dk_xfer.dk_xfer_val, 403*7c478bd9Sstevel@tonic-gate RSTAT_DK_NDRIVE * sizeof (int)); 404*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 405*7c478bd9Sstevel@tonic-gate fprintf(stderr, "dk_xfer: %d %d %d %d\n", 406*7c478bd9Sstevel@tonic-gate stats_s4.dk_xfer.dk_xfer_val[0], 407*7c478bd9Sstevel@tonic-gate stats_s4.dk_xfer.dk_xfer_val[1], 408*7c478bd9Sstevel@tonic-gate stats_s4.dk_xfer.dk_xfer_val[2], 409*7c478bd9Sstevel@tonic-gate stats_s4.dk_xfer.dk_xfer_val[3]); 410*7c478bd9Sstevel@tonic-gate #endif 411*7c478bd9Sstevel@tonic-gate 412*7c478bd9Sstevel@tonic-gate stats_s2.if_ipackets = 413*7c478bd9Sstevel@tonic-gate stats_s3.if_ipackets = stats_s4.if_ipackets; 414*7c478bd9Sstevel@tonic-gate /* no s2 opackets */ 415*7c478bd9Sstevel@tonic-gate stats_s3.if_opackets = stats_s4.if_opackets; 416*7c478bd9Sstevel@tonic-gate stats_s2.if_ierrors = 417*7c478bd9Sstevel@tonic-gate stats_s3.if_ierrors = stats_s4.if_ierrors; 418*7c478bd9Sstevel@tonic-gate stats_s2.if_oerrors = 419*7c478bd9Sstevel@tonic-gate stats_s3.if_oerrors = stats_s4.if_oerrors; 420*7c478bd9Sstevel@tonic-gate stats_s2.if_collisions = 421*7c478bd9Sstevel@tonic-gate stats_s3.if_collisions = stats_s4.if_collisions; 422*7c478bd9Sstevel@tonic-gate 423*7c478bd9Sstevel@tonic-gate stats_s2.avenrun[0] = 424*7c478bd9Sstevel@tonic-gate stats_s3.avenrun[0] = 425*7c478bd9Sstevel@tonic-gate stats_s4.avenrun[0] = avenrun_1min_knp->value.ul; 426*7c478bd9Sstevel@tonic-gate stats_s2.avenrun[1] = 427*7c478bd9Sstevel@tonic-gate stats_s3.avenrun[1] = 428*7c478bd9Sstevel@tonic-gate stats_s4.avenrun[1] = avenrun_5min_knp->value.ul; 429*7c478bd9Sstevel@tonic-gate stats_s2.avenrun[2] = 430*7c478bd9Sstevel@tonic-gate stats_s3.avenrun[2] = 431*7c478bd9Sstevel@tonic-gate stats_s4.avenrun[2] = avenrun_15min_knp->value.ul; 432*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 433*7c478bd9Sstevel@tonic-gate fprintf(stderr, "avenrun: %d %d %d\n", stats_s3.avenrun[0], 434*7c478bd9Sstevel@tonic-gate stats_s3.avenrun[1], stats_s3.avenrun[2]); 435*7c478bd9Sstevel@tonic-gate #endif 436*7c478bd9Sstevel@tonic-gate signal(SIGALRM, updatestat); 437*7c478bd9Sstevel@tonic-gate alarm(1); 438*7c478bd9Sstevel@tonic-gate } 439*7c478bd9Sstevel@tonic-gate 440*7c478bd9Sstevel@tonic-gate /* --------------------------------- MIBGET -------------------------------- */ 441*7c478bd9Sstevel@tonic-gate 442*7c478bd9Sstevel@tonic-gate static mib_item_t * 443*7c478bd9Sstevel@tonic-gate mibget(int sd) 444*7c478bd9Sstevel@tonic-gate { 445*7c478bd9Sstevel@tonic-gate int flags; 446*7c478bd9Sstevel@tonic-gate int j, getcode; 447*7c478bd9Sstevel@tonic-gate struct strbuf ctlbuf, databuf; 448*7c478bd9Sstevel@tonic-gate char buf[512]; 449*7c478bd9Sstevel@tonic-gate struct T_optmgmt_req *tor = (struct T_optmgmt_req *)buf; 450*7c478bd9Sstevel@tonic-gate struct T_optmgmt_ack *toa = (struct T_optmgmt_ack *)buf; 451*7c478bd9Sstevel@tonic-gate struct T_error_ack *tea = (struct T_error_ack *)buf; 452*7c478bd9Sstevel@tonic-gate struct opthdr *req; 453*7c478bd9Sstevel@tonic-gate mib_item_t *first_item = NULL; 454*7c478bd9Sstevel@tonic-gate mib_item_t *last_item = NULL; 455*7c478bd9Sstevel@tonic-gate mib_item_t *temp; 456*7c478bd9Sstevel@tonic-gate 457*7c478bd9Sstevel@tonic-gate tor->PRIM_type = T_SVR4_OPTMGMT_REQ; 458*7c478bd9Sstevel@tonic-gate tor->OPT_offset = sizeof (struct T_optmgmt_req); 459*7c478bd9Sstevel@tonic-gate tor->OPT_length = sizeof (struct opthdr); 460*7c478bd9Sstevel@tonic-gate tor->MGMT_flags = T_CURRENT; 461*7c478bd9Sstevel@tonic-gate req = (struct opthdr *)&tor[1]; 462*7c478bd9Sstevel@tonic-gate req->level = MIB2_IP; /* any MIB2_xxx value ok here */ 463*7c478bd9Sstevel@tonic-gate req->name = 0; 464*7c478bd9Sstevel@tonic-gate req->len = 0; 465*7c478bd9Sstevel@tonic-gate 466*7c478bd9Sstevel@tonic-gate ctlbuf.buf = buf; 467*7c478bd9Sstevel@tonic-gate ctlbuf.len = tor->OPT_length + tor->OPT_offset; 468*7c478bd9Sstevel@tonic-gate flags = 0; 469*7c478bd9Sstevel@tonic-gate if (putmsg(sd, &ctlbuf, NULL, flags) == -1) { 470*7c478bd9Sstevel@tonic-gate perror("mibget: putmsg(ctl) failed"); 471*7c478bd9Sstevel@tonic-gate goto error_exit; 472*7c478bd9Sstevel@tonic-gate } 473*7c478bd9Sstevel@tonic-gate /* 474*7c478bd9Sstevel@tonic-gate * each reply consists of a ctl part for one fixed structure 475*7c478bd9Sstevel@tonic-gate * or table, as defined in mib2.h. The format is a T_OPTMGMT_ACK, 476*7c478bd9Sstevel@tonic-gate * containing an opthdr structure. level/name identify the entry, 477*7c478bd9Sstevel@tonic-gate * len is the size of the data part of the message. 478*7c478bd9Sstevel@tonic-gate */ 479*7c478bd9Sstevel@tonic-gate req = (struct opthdr *)&toa[1]; 480*7c478bd9Sstevel@tonic-gate ctlbuf.maxlen = sizeof (buf); 481*7c478bd9Sstevel@tonic-gate /*CSTYLED*/ 482*7c478bd9Sstevel@tonic-gate for (j = 1; ; j++) { 483*7c478bd9Sstevel@tonic-gate flags = 0; 484*7c478bd9Sstevel@tonic-gate getcode = getmsg(sd, &ctlbuf, NULL, &flags); 485*7c478bd9Sstevel@tonic-gate if (getcode == -1) { 486*7c478bd9Sstevel@tonic-gate #ifdef DEBUG_MIB 487*7c478bd9Sstevel@tonic-gate perror("mibget getmsg(ctl) failed"); 488*7c478bd9Sstevel@tonic-gate fprintf(stderr, "# level name len\n"); 489*7c478bd9Sstevel@tonic-gate i = 0; 490*7c478bd9Sstevel@tonic-gate for (last_item = first_item; last_item; 491*7c478bd9Sstevel@tonic-gate last_item = last_item->next_item) 492*7c478bd9Sstevel@tonic-gate fprintf(stderr, "%d %4d %5d %d\n", ++i, 493*7c478bd9Sstevel@tonic-gate last_item->group, 494*7c478bd9Sstevel@tonic-gate last_item->mib_id, 495*7c478bd9Sstevel@tonic-gate last_item->length); 496*7c478bd9Sstevel@tonic-gate #endif /* DEBUG_MIB */ 497*7c478bd9Sstevel@tonic-gate goto error_exit; 498*7c478bd9Sstevel@tonic-gate } 499*7c478bd9Sstevel@tonic-gate if (getcode == 0 && 500*7c478bd9Sstevel@tonic-gate (ctlbuf.len >= sizeof (struct T_optmgmt_ack)) && 501*7c478bd9Sstevel@tonic-gate (toa->PRIM_type == T_OPTMGMT_ACK) && 502*7c478bd9Sstevel@tonic-gate (toa->MGMT_flags == T_SUCCESS) && 503*7c478bd9Sstevel@tonic-gate req->len == 0) { 504*7c478bd9Sstevel@tonic-gate #ifdef DEBUG_MIB 505*7c478bd9Sstevel@tonic-gate fprintf(stderr, 506*7c478bd9Sstevel@tonic-gate "mibget getmsg() %d returned EOD (level %d, name %d)\n", 507*7c478bd9Sstevel@tonic-gate j, req->level, req->name); 508*7c478bd9Sstevel@tonic-gate #endif /* DEBUG_MIB */ 509*7c478bd9Sstevel@tonic-gate return (first_item); /* this is EOD msg */ 510*7c478bd9Sstevel@tonic-gate } 511*7c478bd9Sstevel@tonic-gate 512*7c478bd9Sstevel@tonic-gate if (ctlbuf.len >= sizeof (struct T_error_ack) && 513*7c478bd9Sstevel@tonic-gate (tea->PRIM_type == T_ERROR_ACK)) { 514*7c478bd9Sstevel@tonic-gate #ifdef DEBUG_MIB 515*7c478bd9Sstevel@tonic-gate fprintf(stderr, 516*7c478bd9Sstevel@tonic-gate "mibget %d gives T_ERROR_ACK: TLI_error = 0x%x, UNIX_error = 0x%x\n", 517*7c478bd9Sstevel@tonic-gate j, getcode, tea->TLI_error, tea->UNIX_error); 518*7c478bd9Sstevel@tonic-gate #endif /* DEBUG_MIB */ 519*7c478bd9Sstevel@tonic-gate errno = (tea->TLI_error == TSYSERR) 520*7c478bd9Sstevel@tonic-gate ? tea->UNIX_error : EPROTO; 521*7c478bd9Sstevel@tonic-gate goto error_exit; 522*7c478bd9Sstevel@tonic-gate } 523*7c478bd9Sstevel@tonic-gate 524*7c478bd9Sstevel@tonic-gate if (getcode != MOREDATA || 525*7c478bd9Sstevel@tonic-gate (ctlbuf.len < sizeof (struct T_optmgmt_ack)) || 526*7c478bd9Sstevel@tonic-gate (toa->PRIM_type != T_OPTMGMT_ACK) || 527*7c478bd9Sstevel@tonic-gate (toa->MGMT_flags != T_SUCCESS)) { 528*7c478bd9Sstevel@tonic-gate #ifdef DEBUG_MIB 529*7c478bd9Sstevel@tonic-gate fprintf(stderr, 530*7c478bd9Sstevel@tonic-gate "mibget getmsg(ctl) %d returned %d, ctlbuf.len = %d, PRIM_type = %d\n", 531*7c478bd9Sstevel@tonic-gate j, getcode, ctlbuf.len, toa->PRIM_type); 532*7c478bd9Sstevel@tonic-gate if (toa->PRIM_type == T_OPTMGMT_ACK) 533*7c478bd9Sstevel@tonic-gate fprintf(stderr, 534*7c478bd9Sstevel@tonic-gate "T_OPTMGMT_ACK: MGMT_flags = 0x%x, req->len = %d\n", 535*7c478bd9Sstevel@tonic-gate toa->MGMT_flags, req->len); 536*7c478bd9Sstevel@tonic-gate #endif /* DEBUG_MIB */ 537*7c478bd9Sstevel@tonic-gate errno = ENOMSG; 538*7c478bd9Sstevel@tonic-gate goto error_exit; 539*7c478bd9Sstevel@tonic-gate } 540*7c478bd9Sstevel@tonic-gate 541*7c478bd9Sstevel@tonic-gate temp = malloc(sizeof (mib_item_t)); 542*7c478bd9Sstevel@tonic-gate if (!temp) { 543*7c478bd9Sstevel@tonic-gate perror("mibget malloc failed"); 544*7c478bd9Sstevel@tonic-gate goto error_exit; 545*7c478bd9Sstevel@tonic-gate } 546*7c478bd9Sstevel@tonic-gate if (last_item) 547*7c478bd9Sstevel@tonic-gate last_item->next_item = temp; 548*7c478bd9Sstevel@tonic-gate else 549*7c478bd9Sstevel@tonic-gate first_item = temp; 550*7c478bd9Sstevel@tonic-gate last_item = temp; 551*7c478bd9Sstevel@tonic-gate last_item->next_item = NULL; 552*7c478bd9Sstevel@tonic-gate last_item->group = req->level; 553*7c478bd9Sstevel@tonic-gate last_item->mib_id = req->name; 554*7c478bd9Sstevel@tonic-gate last_item->length = req->len; 555*7c478bd9Sstevel@tonic-gate last_item->valp = malloc(req->len); 556*7c478bd9Sstevel@tonic-gate #ifdef DEBUG_MIB 557*7c478bd9Sstevel@tonic-gate fprintf(stderr, 558*7c478bd9Sstevel@tonic-gate "msg %d: group = %4d mib_id = %5d length = %d\n", 559*7c478bd9Sstevel@tonic-gate j, last_item->group, last_item->mib_id, 560*7c478bd9Sstevel@tonic-gate last_item->length); 561*7c478bd9Sstevel@tonic-gate #endif /* DEBUG_MIB */ 562*7c478bd9Sstevel@tonic-gate databuf.maxlen = last_item->length; 563*7c478bd9Sstevel@tonic-gate databuf.buf = last_item->valp; 564*7c478bd9Sstevel@tonic-gate databuf.len = 0; 565*7c478bd9Sstevel@tonic-gate flags = 0; 566*7c478bd9Sstevel@tonic-gate getcode = getmsg(sd, NULL, &databuf, &flags); 567*7c478bd9Sstevel@tonic-gate if (getcode == -1) { 568*7c478bd9Sstevel@tonic-gate perror("mibget getmsg(data) failed"); 569*7c478bd9Sstevel@tonic-gate goto error_exit; 570*7c478bd9Sstevel@tonic-gate } else if (getcode != 0) { 571*7c478bd9Sstevel@tonic-gate fprintf(stderr, 572*7c478bd9Sstevel@tonic-gate "mibget getmsg(data) returned %d, databuf.maxlen = %d, databuf.len = %d\n", 573*7c478bd9Sstevel@tonic-gate getcode, databuf.maxlen, databuf.len); 574*7c478bd9Sstevel@tonic-gate goto error_exit; 575*7c478bd9Sstevel@tonic-gate } 576*7c478bd9Sstevel@tonic-gate } 577*7c478bd9Sstevel@tonic-gate 578*7c478bd9Sstevel@tonic-gate error_exit: 579*7c478bd9Sstevel@tonic-gate while (first_item) { 580*7c478bd9Sstevel@tonic-gate last_item = first_item; 581*7c478bd9Sstevel@tonic-gate first_item = first_item->next_item; 582*7c478bd9Sstevel@tonic-gate if (last_item->valp) { 583*7c478bd9Sstevel@tonic-gate free(last_item->valp); 584*7c478bd9Sstevel@tonic-gate } 585*7c478bd9Sstevel@tonic-gate free(last_item); 586*7c478bd9Sstevel@tonic-gate } 587*7c478bd9Sstevel@tonic-gate return (first_item); 588*7c478bd9Sstevel@tonic-gate } 589*7c478bd9Sstevel@tonic-gate 590*7c478bd9Sstevel@tonic-gate static int 591*7c478bd9Sstevel@tonic-gate mibopen(void) 592*7c478bd9Sstevel@tonic-gate { 593*7c478bd9Sstevel@tonic-gate int sd; 594*7c478bd9Sstevel@tonic-gate 595*7c478bd9Sstevel@tonic-gate /* gives us ip w/ arp on top */ 596*7c478bd9Sstevel@tonic-gate sd = open("/dev/arp", O_RDWR); 597*7c478bd9Sstevel@tonic-gate if (sd == -1) { 598*7c478bd9Sstevel@tonic-gate perror("arp open"); 599*7c478bd9Sstevel@tonic-gate close(sd); 600*7c478bd9Sstevel@tonic-gate return (-1); 601*7c478bd9Sstevel@tonic-gate } 602*7c478bd9Sstevel@tonic-gate if (ioctl(sd, I_PUSH, "tcp") == -1) { 603*7c478bd9Sstevel@tonic-gate perror("tcp I_PUSH"); 604*7c478bd9Sstevel@tonic-gate close(sd); 605*7c478bd9Sstevel@tonic-gate return (-1); 606*7c478bd9Sstevel@tonic-gate } 607*7c478bd9Sstevel@tonic-gate if (ioctl(sd, I_PUSH, "udp") == -1) { 608*7c478bd9Sstevel@tonic-gate perror("udp I_PUSH"); 609*7c478bd9Sstevel@tonic-gate close(sd); 610*7c478bd9Sstevel@tonic-gate return (-1); 611*7c478bd9Sstevel@tonic-gate } 612*7c478bd9Sstevel@tonic-gate return (sd); 613*7c478bd9Sstevel@tonic-gate } 614*7c478bd9Sstevel@tonic-gate 615*7c478bd9Sstevel@tonic-gate static char * 616*7c478bd9Sstevel@tonic-gate octetstr(char *buf, Octet_t *op, int code) 617*7c478bd9Sstevel@tonic-gate { 618*7c478bd9Sstevel@tonic-gate int i; 619*7c478bd9Sstevel@tonic-gate char *cp; 620*7c478bd9Sstevel@tonic-gate 621*7c478bd9Sstevel@tonic-gate cp = buf; 622*7c478bd9Sstevel@tonic-gate if (op) 623*7c478bd9Sstevel@tonic-gate for (i = 0; i < op->o_length; i++) 624*7c478bd9Sstevel@tonic-gate switch (code) { 625*7c478bd9Sstevel@tonic-gate case 'd': 626*7c478bd9Sstevel@tonic-gate sprintf(cp, "%d.", 0xff & op->o_bytes[i]); 627*7c478bd9Sstevel@tonic-gate cp = strchr(cp, '\0'); 628*7c478bd9Sstevel@tonic-gate break; 629*7c478bd9Sstevel@tonic-gate case 'a': 630*7c478bd9Sstevel@tonic-gate *cp++ = op->o_bytes[i]; 631*7c478bd9Sstevel@tonic-gate break; 632*7c478bd9Sstevel@tonic-gate case 'h': 633*7c478bd9Sstevel@tonic-gate default: 634*7c478bd9Sstevel@tonic-gate sprintf(cp, "%02x:", 0xff & op->o_bytes[i]); 635*7c478bd9Sstevel@tonic-gate cp += 3; 636*7c478bd9Sstevel@tonic-gate break; 637*7c478bd9Sstevel@tonic-gate } 638*7c478bd9Sstevel@tonic-gate if (code != 'a' && cp != buf) 639*7c478bd9Sstevel@tonic-gate cp--; 640*7c478bd9Sstevel@tonic-gate *cp = '\0'; 641*7c478bd9Sstevel@tonic-gate return (buf); 642*7c478bd9Sstevel@tonic-gate } 643*7c478bd9Sstevel@tonic-gate 644*7c478bd9Sstevel@tonic-gate static void 645*7c478bd9Sstevel@tonic-gate fail(int do_perror, char *message, ...) 646*7c478bd9Sstevel@tonic-gate { 647*7c478bd9Sstevel@tonic-gate va_list args; 648*7c478bd9Sstevel@tonic-gate 649*7c478bd9Sstevel@tonic-gate va_start(args, message); 650*7c478bd9Sstevel@tonic-gate fprintf(stderr, "%s: ", cmdname); 651*7c478bd9Sstevel@tonic-gate vfprintf(stderr, message, args); 652*7c478bd9Sstevel@tonic-gate va_end(args); 653*7c478bd9Sstevel@tonic-gate if (do_perror) 654*7c478bd9Sstevel@tonic-gate fprintf(stderr, ": %s", strerror(errno)); 655*7c478bd9Sstevel@tonic-gate fprintf(stderr, "\n"); 656*7c478bd9Sstevel@tonic-gate exit(2); 657*7c478bd9Sstevel@tonic-gate } 658*7c478bd9Sstevel@tonic-gate 659*7c478bd9Sstevel@tonic-gate static void 660*7c478bd9Sstevel@tonic-gate safe_zalloc(void **ptr, int size, int free_first) 661*7c478bd9Sstevel@tonic-gate { 662*7c478bd9Sstevel@tonic-gate if (free_first && *ptr != NULL) 663*7c478bd9Sstevel@tonic-gate free(*ptr); 664*7c478bd9Sstevel@tonic-gate if ((*ptr = malloc(size)) == NULL) 665*7c478bd9Sstevel@tonic-gate fail(1, "malloc failed"); 666*7c478bd9Sstevel@tonic-gate memset(*ptr, 0, size); 667*7c478bd9Sstevel@tonic-gate } 668*7c478bd9Sstevel@tonic-gate 669*7c478bd9Sstevel@tonic-gate kid_t 670*7c478bd9Sstevel@tonic-gate safe_kstat_read(kstat_ctl_t *kctl, kstat_t *ksp, void *data) 671*7c478bd9Sstevel@tonic-gate { 672*7c478bd9Sstevel@tonic-gate kid_t kstat_chain_id = kstat_read(kctl, ksp, data); 673*7c478bd9Sstevel@tonic-gate 674*7c478bd9Sstevel@tonic-gate if (kstat_chain_id == -1) 675*7c478bd9Sstevel@tonic-gate fail(1, "kstat_read(%x, '%s') failed", kctl, ksp->ks_name); 676*7c478bd9Sstevel@tonic-gate return (kstat_chain_id); 677*7c478bd9Sstevel@tonic-gate } 678*7c478bd9Sstevel@tonic-gate 679*7c478bd9Sstevel@tonic-gate kstat_t * 680*7c478bd9Sstevel@tonic-gate safe_kstat_lookup(kstat_ctl_t *kctl, char *ks_module, int ks_instance, 681*7c478bd9Sstevel@tonic-gate char *ks_name) 682*7c478bd9Sstevel@tonic-gate { 683*7c478bd9Sstevel@tonic-gate kstat_t *ksp = kstat_lookup(kctl, ks_module, ks_instance, ks_name); 684*7c478bd9Sstevel@tonic-gate 685*7c478bd9Sstevel@tonic-gate if (ksp == NULL) 686*7c478bd9Sstevel@tonic-gate fail(0, "kstat_lookup('%s', %d, '%s') failed", 687*7c478bd9Sstevel@tonic-gate ks_module == NULL ? "" : ks_module, 688*7c478bd9Sstevel@tonic-gate ks_instance, 689*7c478bd9Sstevel@tonic-gate ks_name == NULL ? "" : ks_name); 690*7c478bd9Sstevel@tonic-gate return (ksp); 691*7c478bd9Sstevel@tonic-gate } 692*7c478bd9Sstevel@tonic-gate 693*7c478bd9Sstevel@tonic-gate void * 694*7c478bd9Sstevel@tonic-gate safe_kstat_data_lookup(kstat_t *ksp, char *name) 695*7c478bd9Sstevel@tonic-gate { 696*7c478bd9Sstevel@tonic-gate void *fp = kstat_data_lookup(ksp, name); 697*7c478bd9Sstevel@tonic-gate 698*7c478bd9Sstevel@tonic-gate if (fp == NULL) { 699*7c478bd9Sstevel@tonic-gate fail(0, "kstat_data_lookup('%s', '%s') failed", 700*7c478bd9Sstevel@tonic-gate ksp->ks_name, name); 701*7c478bd9Sstevel@tonic-gate } 702*7c478bd9Sstevel@tonic-gate return (fp); 703*7c478bd9Sstevel@tonic-gate } 704*7c478bd9Sstevel@tonic-gate 705*7c478bd9Sstevel@tonic-gate /* 706*7c478bd9Sstevel@tonic-gate * Get various KIDs for subsequent system_stat_load operations. 707*7c478bd9Sstevel@tonic-gate */ 708*7c478bd9Sstevel@tonic-gate 709*7c478bd9Sstevel@tonic-gate static void 710*7c478bd9Sstevel@tonic-gate system_stat_init(void) 711*7c478bd9Sstevel@tonic-gate { 712*7c478bd9Sstevel@tonic-gate kstat_t *ksp; 713*7c478bd9Sstevel@tonic-gate int i, nvmks; 714*7c478bd9Sstevel@tonic-gate 715*7c478bd9Sstevel@tonic-gate /* 716*7c478bd9Sstevel@tonic-gate * Global statistics 717*7c478bd9Sstevel@tonic-gate */ 718*7c478bd9Sstevel@tonic-gate 719*7c478bd9Sstevel@tonic-gate system_misc_ksp = safe_kstat_lookup(kc, "unix", 0, "system_misc"); 720*7c478bd9Sstevel@tonic-gate 721*7c478bd9Sstevel@tonic-gate safe_kstat_read(kc, system_misc_ksp, NULL); 722*7c478bd9Sstevel@tonic-gate boot_time_knp = safe_kstat_data_lookup(system_misc_ksp, "boot_time"); 723*7c478bd9Sstevel@tonic-gate avenrun_1min_knp = safe_kstat_data_lookup(system_misc_ksp, 724*7c478bd9Sstevel@tonic-gate "avenrun_1min"); 725*7c478bd9Sstevel@tonic-gate avenrun_5min_knp = safe_kstat_data_lookup(system_misc_ksp, 726*7c478bd9Sstevel@tonic-gate "avenrun_5min"); 727*7c478bd9Sstevel@tonic-gate avenrun_15min_knp = safe_kstat_data_lookup(system_misc_ksp, 728*7c478bd9Sstevel@tonic-gate "avenrun_15min"); 729*7c478bd9Sstevel@tonic-gate 730*7c478bd9Sstevel@tonic-gate /* 731*7c478bd9Sstevel@tonic-gate * Per-CPU statistics 732*7c478bd9Sstevel@tonic-gate */ 733*7c478bd9Sstevel@tonic-gate 734*7c478bd9Sstevel@tonic-gate ncpus = 0; 735*7c478bd9Sstevel@tonic-gate for (ksp = kc->kc_chain; ksp; ksp = ksp->ks_next) 736*7c478bd9Sstevel@tonic-gate if (strcmp(ksp->ks_module, "cpu") == 0 && 737*7c478bd9Sstevel@tonic-gate strcmp(ksp->ks_name, "sys") == 0) 738*7c478bd9Sstevel@tonic-gate ncpus++; 739*7c478bd9Sstevel@tonic-gate 740*7c478bd9Sstevel@tonic-gate safe_zalloc((void **)&cpu_stats_list, ncpus * sizeof (*cpu_stats_list), 741*7c478bd9Sstevel@tonic-gate 1); 742*7c478bd9Sstevel@tonic-gate 743*7c478bd9Sstevel@tonic-gate ncpus = 0; 744*7c478bd9Sstevel@tonic-gate for (ksp = kc->kc_chain; ksp; ksp = ksp->ks_next) 745*7c478bd9Sstevel@tonic-gate if (strcmp(ksp->ks_module, "cpu") == 0 && 746*7c478bd9Sstevel@tonic-gate strcmp(ksp->ks_name, "sys") == 0 && 747*7c478bd9Sstevel@tonic-gate kstat_read(kc, ksp, NULL) != -1) { 748*7c478bd9Sstevel@tonic-gate kstat_copy(ksp, &cpu_stats_list[ncpus].sys, 749*7c478bd9Sstevel@tonic-gate 1); 750*7c478bd9Sstevel@tonic-gate if ((ksp = kstat_lookup(kc, "cpu", ksp->ks_instance, 751*7c478bd9Sstevel@tonic-gate "vm")) != NULL && kstat_read(kc, ksp, NULL) != -1) 752*7c478bd9Sstevel@tonic-gate kstat_copy(ksp, &cpu_stats_list[ncpus].vm, 1); 753*7c478bd9Sstevel@tonic-gate else 754*7c478bd9Sstevel@tonic-gate fail(0, "couldn't find per-CPU VM statistics"); 755*7c478bd9Sstevel@tonic-gate ncpus++; 756*7c478bd9Sstevel@tonic-gate } 757*7c478bd9Sstevel@tonic-gate 758*7c478bd9Sstevel@tonic-gate if (ncpus == 0) 759*7c478bd9Sstevel@tonic-gate fail(0, "couldn't find per-CPU statistics"); 760*7c478bd9Sstevel@tonic-gate } 761*7c478bd9Sstevel@tonic-gate 762*7c478bd9Sstevel@tonic-gate /* 763*7c478bd9Sstevel@tonic-gate * load statistics, summing across CPUs where needed 764*7c478bd9Sstevel@tonic-gate */ 765*7c478bd9Sstevel@tonic-gate 766*7c478bd9Sstevel@tonic-gate static int 767*7c478bd9Sstevel@tonic-gate system_stat_load(void) 768*7c478bd9Sstevel@tonic-gate { 769*7c478bd9Sstevel@tonic-gate int i, j; 770*7c478bd9Sstevel@tonic-gate _cpu_stats_t cs; 771*7c478bd9Sstevel@tonic-gate ulong_t *np, *tp; 772*7c478bd9Sstevel@tonic-gate 773*7c478bd9Sstevel@tonic-gate /* 774*7c478bd9Sstevel@tonic-gate * Global statistics 775*7c478bd9Sstevel@tonic-gate */ 776*7c478bd9Sstevel@tonic-gate 777*7c478bd9Sstevel@tonic-gate safe_kstat_read(kc, system_misc_ksp, NULL); 778*7c478bd9Sstevel@tonic-gate 779*7c478bd9Sstevel@tonic-gate /* 780*7c478bd9Sstevel@tonic-gate * Per-CPU statistics. 781*7c478bd9Sstevel@tonic-gate */ 782*7c478bd9Sstevel@tonic-gate 783*7c478bd9Sstevel@tonic-gate for (i = 0; i < ncpus; i++) { 784*7c478bd9Sstevel@tonic-gate if (kstat_read(kc, &cpu_stats_list[i].sys, NULL) == -1 || 785*7c478bd9Sstevel@tonic-gate kstat_read(kc, &cpu_stats_list[i].vm, NULL) == -1) 786*7c478bd9Sstevel@tonic-gate return (1); 787*7c478bd9Sstevel@tonic-gate if (i == 0) { 788*7c478bd9Sstevel@tonic-gate kstat_copy(&cpu_stats_list[0].sys, &cpu_stats_all.sys, 789*7c478bd9Sstevel@tonic-gate 1); 790*7c478bd9Sstevel@tonic-gate kstat_copy(&cpu_stats_list[0].vm, &cpu_stats_all.vm, 1); 791*7c478bd9Sstevel@tonic-gate } else { 792*7c478bd9Sstevel@tonic-gate kstat_named_t *nkp; 793*7c478bd9Sstevel@tonic-gate kstat_named_t *tkp; 794*7c478bd9Sstevel@tonic-gate 795*7c478bd9Sstevel@tonic-gate /* 796*7c478bd9Sstevel@tonic-gate * Other CPUs' statistics are accumulated in 797*7c478bd9Sstevel@tonic-gate * cpu_stats_all, initialized at the first iteration of 798*7c478bd9Sstevel@tonic-gate * the loop. 799*7c478bd9Sstevel@tonic-gate */ 800*7c478bd9Sstevel@tonic-gate nkp = (kstat_named_t *)cpu_stats_all.sys.ks_data; 801*7c478bd9Sstevel@tonic-gate tkp = (kstat_named_t *)cpu_stats_list[i].sys.ks_data; 802*7c478bd9Sstevel@tonic-gate for (j = 0; j < cpu_stats_list[i].sys.ks_ndata; j++) 803*7c478bd9Sstevel@tonic-gate (nkp++)->value.ui64 += (tkp++)->value.ui64; 804*7c478bd9Sstevel@tonic-gate nkp = (kstat_named_t *)cpu_stats_all.vm.ks_data; 805*7c478bd9Sstevel@tonic-gate tkp = (kstat_named_t *)cpu_stats_list[i].vm.ks_data; 806*7c478bd9Sstevel@tonic-gate for (j = 0; j < cpu_stats_list[i].vm.ks_ndata; j++) 807*7c478bd9Sstevel@tonic-gate (nkp++)->value.ui64 += (tkp++)->value.ui64; 808*7c478bd9Sstevel@tonic-gate } 809*7c478bd9Sstevel@tonic-gate } 810*7c478bd9Sstevel@tonic-gate return (0); 811*7c478bd9Sstevel@tonic-gate } 812*7c478bd9Sstevel@tonic-gate 813*7c478bd9Sstevel@tonic-gate static int 814*7c478bd9Sstevel@tonic-gate kscmp(kstat_t *ks1, kstat_t *ks2) 815*7c478bd9Sstevel@tonic-gate { 816*7c478bd9Sstevel@tonic-gate int cmp; 817*7c478bd9Sstevel@tonic-gate 818*7c478bd9Sstevel@tonic-gate cmp = strcmp(ks1->ks_module, ks2->ks_module); 819*7c478bd9Sstevel@tonic-gate if (cmp != 0) 820*7c478bd9Sstevel@tonic-gate return (cmp); 821*7c478bd9Sstevel@tonic-gate cmp = ks1->ks_instance - ks2->ks_instance; 822*7c478bd9Sstevel@tonic-gate if (cmp != 0) 823*7c478bd9Sstevel@tonic-gate return (cmp); 824*7c478bd9Sstevel@tonic-gate return (strcmp(ks1->ks_name, ks2->ks_name)); 825*7c478bd9Sstevel@tonic-gate } 826*7c478bd9Sstevel@tonic-gate 827*7c478bd9Sstevel@tonic-gate static void 828*7c478bd9Sstevel@tonic-gate init_disks(void) 829*7c478bd9Sstevel@tonic-gate { 830*7c478bd9Sstevel@tonic-gate struct diskinfo *disk, *prevdisk, *comp; 831*7c478bd9Sstevel@tonic-gate kstat_t *ksp; 832*7c478bd9Sstevel@tonic-gate 833*7c478bd9Sstevel@tonic-gate ndisks = 0; 834*7c478bd9Sstevel@tonic-gate disk = &zerodisk; 835*7c478bd9Sstevel@tonic-gate 836*7c478bd9Sstevel@tonic-gate /* 837*7c478bd9Sstevel@tonic-gate * Patch the snip in the diskinfo list (see below) 838*7c478bd9Sstevel@tonic-gate */ 839*7c478bd9Sstevel@tonic-gate if (snip) 840*7c478bd9Sstevel@tonic-gate lastdisk->next = snip; 841*7c478bd9Sstevel@tonic-gate 842*7c478bd9Sstevel@tonic-gate for (ksp = kc->kc_chain; ksp; ksp = ksp->ks_next) { 843*7c478bd9Sstevel@tonic-gate 844*7c478bd9Sstevel@tonic-gate if (ksp->ks_type != KSTAT_TYPE_IO || 845*7c478bd9Sstevel@tonic-gate strcmp(ksp->ks_class, "disk") != 0) 846*7c478bd9Sstevel@tonic-gate continue; 847*7c478bd9Sstevel@tonic-gate prevdisk = disk; 848*7c478bd9Sstevel@tonic-gate if (disk->next) 849*7c478bd9Sstevel@tonic-gate disk = disk->next; 850*7c478bd9Sstevel@tonic-gate else { 851*7c478bd9Sstevel@tonic-gate safe_zalloc((void **)&disk->next, 852*7c478bd9Sstevel@tonic-gate sizeof (struct diskinfo), 0); 853*7c478bd9Sstevel@tonic-gate disk = disk->next; 854*7c478bd9Sstevel@tonic-gate disk->next = NULLDISK; 855*7c478bd9Sstevel@tonic-gate } 856*7c478bd9Sstevel@tonic-gate disk->ks = ksp; 857*7c478bd9Sstevel@tonic-gate memset((void *)&disk->kios, 0, sizeof (kstat_io_t)); 858*7c478bd9Sstevel@tonic-gate disk->kios.wlastupdate = disk->ks->ks_crtime; 859*7c478bd9Sstevel@tonic-gate disk->kios.rlastupdate = disk->ks->ks_crtime; 860*7c478bd9Sstevel@tonic-gate 861*7c478bd9Sstevel@tonic-gate /* 862*7c478bd9Sstevel@tonic-gate * Insertion sort on (ks_module, ks_instance, ks_name) 863*7c478bd9Sstevel@tonic-gate */ 864*7c478bd9Sstevel@tonic-gate comp = &zerodisk; 865*7c478bd9Sstevel@tonic-gate while (kscmp(disk->ks, comp->next->ks) > 0) 866*7c478bd9Sstevel@tonic-gate comp = comp->next; 867*7c478bd9Sstevel@tonic-gate if (prevdisk != comp) { 868*7c478bd9Sstevel@tonic-gate prevdisk->next = disk->next; 869*7c478bd9Sstevel@tonic-gate disk->next = comp->next; 870*7c478bd9Sstevel@tonic-gate comp->next = disk; 871*7c478bd9Sstevel@tonic-gate disk = prevdisk; 872*7c478bd9Sstevel@tonic-gate } 873*7c478bd9Sstevel@tonic-gate ndisks++; 874*7c478bd9Sstevel@tonic-gate } 875*7c478bd9Sstevel@tonic-gate /* 876*7c478bd9Sstevel@tonic-gate * Put a snip in the linked list of diskinfos. The idea: 877*7c478bd9Sstevel@tonic-gate * If there was a state change such that now there are fewer 878*7c478bd9Sstevel@tonic-gate * disks, we snip the list and retain the tail, rather than 879*7c478bd9Sstevel@tonic-gate * freeing it. At the next state change, we clip the tail back on. 880*7c478bd9Sstevel@tonic-gate * This prevents a lot of malloc/free activity, and it's simpler. 881*7c478bd9Sstevel@tonic-gate */ 882*7c478bd9Sstevel@tonic-gate lastdisk = disk; 883*7c478bd9Sstevel@tonic-gate snip = disk->next; 884*7c478bd9Sstevel@tonic-gate disk->next = NULLDISK; 885*7c478bd9Sstevel@tonic-gate 886*7c478bd9Sstevel@tonic-gate firstdisk = zerodisk.next; 887*7c478bd9Sstevel@tonic-gate 888*7c478bd9Sstevel@tonic-gate if (ndisks > stats_s4.dk_xfer.dk_xfer_len) { 889*7c478bd9Sstevel@tonic-gate stats_s4.dk_xfer.dk_xfer_len = ndisks; 890*7c478bd9Sstevel@tonic-gate safe_zalloc((void **)&stats_s4.dk_xfer.dk_xfer_val, 891*7c478bd9Sstevel@tonic-gate ndisks * sizeof (int), 1); 892*7c478bd9Sstevel@tonic-gate } 893*7c478bd9Sstevel@tonic-gate } 894*7c478bd9Sstevel@tonic-gate 895*7c478bd9Sstevel@tonic-gate static int 896*7c478bd9Sstevel@tonic-gate diskinfo_load(void) 897*7c478bd9Sstevel@tonic-gate { 898*7c478bd9Sstevel@tonic-gate struct diskinfo *disk; 899*7c478bd9Sstevel@tonic-gate int i; 900*7c478bd9Sstevel@tonic-gate 901*7c478bd9Sstevel@tonic-gate for (disk = firstdisk, i = 0; disk; disk = disk->next, i++) { 902*7c478bd9Sstevel@tonic-gate if (kstat_read(kc, disk->ks, (void *)&disk->kios) == -1) 903*7c478bd9Sstevel@tonic-gate return (1); 904*7c478bd9Sstevel@tonic-gate stats_s4.dk_xfer.dk_xfer_val[i] = disk->kios.reads + 905*7c478bd9Sstevel@tonic-gate disk->kios.writes; 906*7c478bd9Sstevel@tonic-gate } 907*7c478bd9Sstevel@tonic-gate return (0); 908*7c478bd9Sstevel@tonic-gate } 909*7c478bd9Sstevel@tonic-gate 910*7c478bd9Sstevel@tonic-gate static void 911*7c478bd9Sstevel@tonic-gate init_net(void) 912*7c478bd9Sstevel@tonic-gate { 913*7c478bd9Sstevel@tonic-gate static int sd; 914*7c478bd9Sstevel@tonic-gate mib_item_t *item; 915*7c478bd9Sstevel@tonic-gate mib2_ipAddrEntry_t *ap; 916*7c478bd9Sstevel@tonic-gate char namebuf[KSTAT_STRLEN]; 917*7c478bd9Sstevel@tonic-gate struct netinfo *net, *prevnet, *comp; 918*7c478bd9Sstevel@tonic-gate kstat_t *ksp; 919*7c478bd9Sstevel@tonic-gate 920*7c478bd9Sstevel@tonic-gate if (sd) { 921*7c478bd9Sstevel@tonic-gate close(sd); 922*7c478bd9Sstevel@tonic-gate } 923*7c478bd9Sstevel@tonic-gate while (netstat_item) { 924*7c478bd9Sstevel@tonic-gate item = netstat_item; 925*7c478bd9Sstevel@tonic-gate netstat_item = netstat_item->next_item; 926*7c478bd9Sstevel@tonic-gate if (item->valp) { 927*7c478bd9Sstevel@tonic-gate free(item->valp); 928*7c478bd9Sstevel@tonic-gate } 929*7c478bd9Sstevel@tonic-gate free(item); 930*7c478bd9Sstevel@tonic-gate } 931*7c478bd9Sstevel@tonic-gate sd = mibopen(); 932*7c478bd9Sstevel@tonic-gate if (sd == -1) { 933*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 934*7c478bd9Sstevel@tonic-gate fprintf(stderr, "mibopen() failed\n"); 935*7c478bd9Sstevel@tonic-gate #endif 936*7c478bd9Sstevel@tonic-gate sd = 0; 937*7c478bd9Sstevel@tonic-gate } else { 938*7c478bd9Sstevel@tonic-gate if ((netstat_item = mibget(sd)) == NULL) { 939*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 940*7c478bd9Sstevel@tonic-gate fprintf(stderr, "mibget() failed\n"); 941*7c478bd9Sstevel@tonic-gate #endif 942*7c478bd9Sstevel@tonic-gate close(sd); 943*7c478bd9Sstevel@tonic-gate sd = 0; 944*7c478bd9Sstevel@tonic-gate } 945*7c478bd9Sstevel@tonic-gate } 946*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 947*7c478bd9Sstevel@tonic-gate fprintf(stderr, "mibget returned item: %x\n", netstat_item); 948*7c478bd9Sstevel@tonic-gate #endif 949*7c478bd9Sstevel@tonic-gate 950*7c478bd9Sstevel@tonic-gate nnets = 0; 951*7c478bd9Sstevel@tonic-gate net = &zeronet; 952*7c478bd9Sstevel@tonic-gate 953*7c478bd9Sstevel@tonic-gate if (netsnip) 954*7c478bd9Sstevel@tonic-gate lastnet->next = netsnip; 955*7c478bd9Sstevel@tonic-gate 956*7c478bd9Sstevel@tonic-gate for (item = netstat_item; item; item = item->next_item) { 957*7c478bd9Sstevel@tonic-gate #ifdef DEBUG_MIB 958*7c478bd9Sstevel@tonic-gate fprintf(stderr, "\n--- Item %x ---\n", item); 959*7c478bd9Sstevel@tonic-gate fprintf(stderr, 960*7c478bd9Sstevel@tonic-gate "Group = %d, mib_id = %d, length = %d, valp = 0x%x\n", 961*7c478bd9Sstevel@tonic-gate item->group, item->mib_id, item->length, 962*7c478bd9Sstevel@tonic-gate item->valp); 963*7c478bd9Sstevel@tonic-gate #endif 964*7c478bd9Sstevel@tonic-gate if (item->group != MIB2_IP || item->mib_id != MIB2_IP_20) 965*7c478bd9Sstevel@tonic-gate continue; 966*7c478bd9Sstevel@tonic-gate ap = (mib2_ipAddrEntry_t *)item->valp; 967*7c478bd9Sstevel@tonic-gate for (; (char *)ap < item->valp + item->length; ap++) { 968*7c478bd9Sstevel@tonic-gate 969*7c478bd9Sstevel@tonic-gate octetstr(namebuf, &ap->ipAdEntIfIndex, 'a'); 970*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 971*7c478bd9Sstevel@tonic-gate fprintf(stderr, "%s ", namebuf); 972*7c478bd9Sstevel@tonic-gate #endif 973*7c478bd9Sstevel@tonic-gate if (strlen(namebuf) == 0) 974*7c478bd9Sstevel@tonic-gate continue; 975*7c478bd9Sstevel@tonic-gate /* 976*7c478bd9Sstevel@tonic-gate * We found a device of interest. 977*7c478bd9Sstevel@tonic-gate * Now, let's see if there's a kstat for it. 978*7c478bd9Sstevel@tonic-gate */ 979*7c478bd9Sstevel@tonic-gate if ((ksp = kstat_lookup(kc, NULL, -1, namebuf)) == NULL) 980*7c478bd9Sstevel@tonic-gate continue; 981*7c478bd9Sstevel@tonic-gate if (ksp->ks_type != KSTAT_TYPE_NAMED) 982*7c478bd9Sstevel@tonic-gate continue; 983*7c478bd9Sstevel@tonic-gate if (kstat_read(kc, ksp, NULL) == -1) 984*7c478bd9Sstevel@tonic-gate continue; 985*7c478bd9Sstevel@tonic-gate prevnet = net; 986*7c478bd9Sstevel@tonic-gate if (net->next) 987*7c478bd9Sstevel@tonic-gate net = net->next; 988*7c478bd9Sstevel@tonic-gate else { 989*7c478bd9Sstevel@tonic-gate safe_zalloc((void **)&net->next, 990*7c478bd9Sstevel@tonic-gate sizeof (struct netinfo), 0); 991*7c478bd9Sstevel@tonic-gate net = net->next; 992*7c478bd9Sstevel@tonic-gate net->next = NULLNET; 993*7c478bd9Sstevel@tonic-gate } 994*7c478bd9Sstevel@tonic-gate net->ks = ksp; 995*7c478bd9Sstevel@tonic-gate net->ipackets = kstat_data_lookup(net->ks, 996*7c478bd9Sstevel@tonic-gate "ipackets"); 997*7c478bd9Sstevel@tonic-gate net->opackets = kstat_data_lookup(net->ks, 998*7c478bd9Sstevel@tonic-gate "opackets"); 999*7c478bd9Sstevel@tonic-gate net->ierrors = kstat_data_lookup(net->ks, 1000*7c478bd9Sstevel@tonic-gate "ierrors"); 1001*7c478bd9Sstevel@tonic-gate net->oerrors = kstat_data_lookup(net->ks, 1002*7c478bd9Sstevel@tonic-gate "oerrors"); 1003*7c478bd9Sstevel@tonic-gate net->collisions = kstat_data_lookup(net->ks, 1004*7c478bd9Sstevel@tonic-gate "collisions"); 1005*7c478bd9Sstevel@tonic-gate /* 1006*7c478bd9Sstevel@tonic-gate * Insertion sort on the name 1007*7c478bd9Sstevel@tonic-gate */ 1008*7c478bd9Sstevel@tonic-gate comp = &zeronet; 1009*7c478bd9Sstevel@tonic-gate while (strcmp(net->ks->ks_name, 1010*7c478bd9Sstevel@tonic-gate comp->next->ks->ks_name) > 0) 1011*7c478bd9Sstevel@tonic-gate comp = comp->next; 1012*7c478bd9Sstevel@tonic-gate if (prevnet != comp) { 1013*7c478bd9Sstevel@tonic-gate prevnet->next = net->next; 1014*7c478bd9Sstevel@tonic-gate net->next = comp->next; 1015*7c478bd9Sstevel@tonic-gate comp->next = net; 1016*7c478bd9Sstevel@tonic-gate net = prevnet; 1017*7c478bd9Sstevel@tonic-gate } 1018*7c478bd9Sstevel@tonic-gate nnets++; 1019*7c478bd9Sstevel@tonic-gate } 1020*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 1021*7c478bd9Sstevel@tonic-gate fprintf(stderr, "\n"); 1022*7c478bd9Sstevel@tonic-gate #endif 1023*7c478bd9Sstevel@tonic-gate } 1024*7c478bd9Sstevel@tonic-gate /* 1025*7c478bd9Sstevel@tonic-gate * Put a snip in the linked list of netinfos. The idea: 1026*7c478bd9Sstevel@tonic-gate * If there was a state change such that now there are fewer 1027*7c478bd9Sstevel@tonic-gate * nets, we snip the list and retain the tail, rather than 1028*7c478bd9Sstevel@tonic-gate * freeing it. At the next state change, we clip the tail back on. 1029*7c478bd9Sstevel@tonic-gate * This prevents a lot of malloc/free activity, and it's simpler. 1030*7c478bd9Sstevel@tonic-gate */ 1031*7c478bd9Sstevel@tonic-gate lastnet = net; 1032*7c478bd9Sstevel@tonic-gate netsnip = net->next; 1033*7c478bd9Sstevel@tonic-gate net->next = NULLNET; 1034*7c478bd9Sstevel@tonic-gate 1035*7c478bd9Sstevel@tonic-gate firstnet = zeronet.next; 1036*7c478bd9Sstevel@tonic-gate } 1037*7c478bd9Sstevel@tonic-gate 1038*7c478bd9Sstevel@tonic-gate static int 1039*7c478bd9Sstevel@tonic-gate netinfo_load(void) 1040*7c478bd9Sstevel@tonic-gate { 1041*7c478bd9Sstevel@tonic-gate struct netinfo *net; 1042*7c478bd9Sstevel@tonic-gate 1043*7c478bd9Sstevel@tonic-gate if (netstat_item == NULL) { 1044*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 1045*7c478bd9Sstevel@tonic-gate fprintf(stderr, "No net stats\n"); 1046*7c478bd9Sstevel@tonic-gate #endif 1047*7c478bd9Sstevel@tonic-gate return (0); 1048*7c478bd9Sstevel@tonic-gate } 1049*7c478bd9Sstevel@tonic-gate 1050*7c478bd9Sstevel@tonic-gate stats_s4.if_ipackets = 1051*7c478bd9Sstevel@tonic-gate stats_s4.if_opackets = 1052*7c478bd9Sstevel@tonic-gate stats_s4.if_ierrors = 1053*7c478bd9Sstevel@tonic-gate stats_s4.if_oerrors = 1054*7c478bd9Sstevel@tonic-gate stats_s4.if_collisions = 0; 1055*7c478bd9Sstevel@tonic-gate 1056*7c478bd9Sstevel@tonic-gate for (net = firstnet; net; net = net->next) { 1057*7c478bd9Sstevel@tonic-gate if (kstat_read(kc, net->ks, NULL) == -1) 1058*7c478bd9Sstevel@tonic-gate return (1); 1059*7c478bd9Sstevel@tonic-gate if (net->ipackets) 1060*7c478bd9Sstevel@tonic-gate stats_s4.if_ipackets += net->ipackets->value.ul; 1061*7c478bd9Sstevel@tonic-gate if (net->opackets) 1062*7c478bd9Sstevel@tonic-gate stats_s4.if_opackets += net->opackets->value.ul; 1063*7c478bd9Sstevel@tonic-gate if (net->ierrors) 1064*7c478bd9Sstevel@tonic-gate stats_s4.if_ierrors += net->ierrors->value.ul; 1065*7c478bd9Sstevel@tonic-gate if (net->oerrors) 1066*7c478bd9Sstevel@tonic-gate stats_s4.if_oerrors += net->oerrors->value.ul; 1067*7c478bd9Sstevel@tonic-gate if (net->collisions) 1068*7c478bd9Sstevel@tonic-gate stats_s4.if_collisions += net->collisions->value.ul; 1069*7c478bd9Sstevel@tonic-gate } 1070*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 1071*7c478bd9Sstevel@tonic-gate fprintf(stderr, 1072*7c478bd9Sstevel@tonic-gate "ipackets: %d opackets: %d ierrors: %d oerrors: %d colls: %d\n", 1073*7c478bd9Sstevel@tonic-gate stats_s4.if_ipackets, 1074*7c478bd9Sstevel@tonic-gate stats_s4.if_opackets, 1075*7c478bd9Sstevel@tonic-gate stats_s4.if_ierrors, 1076*7c478bd9Sstevel@tonic-gate stats_s4.if_oerrors, 1077*7c478bd9Sstevel@tonic-gate stats_s4.if_collisions); 1078*7c478bd9Sstevel@tonic-gate #endif 1079*7c478bd9Sstevel@tonic-gate return (0); 1080*7c478bd9Sstevel@tonic-gate } 1081*7c478bd9Sstevel@tonic-gate 1082*7c478bd9Sstevel@tonic-gate static void 1083*7c478bd9Sstevel@tonic-gate kstat_copy(kstat_t *src, kstat_t *dst, int fr) 1084*7c478bd9Sstevel@tonic-gate { 1085*7c478bd9Sstevel@tonic-gate if (fr) 1086*7c478bd9Sstevel@tonic-gate free(dst->ks_data); 1087*7c478bd9Sstevel@tonic-gate *dst = *src; 1088*7c478bd9Sstevel@tonic-gate if (src->ks_data != NULL) { 1089*7c478bd9Sstevel@tonic-gate safe_zalloc(&dst->ks_data, src->ks_data_size, 0); 1090*7c478bd9Sstevel@tonic-gate (void) memcpy(dst->ks_data, src->ks_data, src->ks_data_size); 1091*7c478bd9Sstevel@tonic-gate } else { 1092*7c478bd9Sstevel@tonic-gate dst->ks_data = NULL; 1093*7c478bd9Sstevel@tonic-gate dst->ks_data_size = 0; 1094*7c478bd9Sstevel@tonic-gate } 1095*7c478bd9Sstevel@tonic-gate } 1096