1*3941Svenki /* 2*3941Svenki * CDDL HEADER START 3*3941Svenki * 4*3941Svenki * The contents of this file are subject to the terms of the 5*3941Svenki * Common Development and Distribution License (the "License"). 6*3941Svenki * You may not use this file except in compliance with the License. 7*3941Svenki * 8*3941Svenki * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*3941Svenki * or http://www.opensolaris.org/os/licensing. 10*3941Svenki * See the License for the specific language governing permissions 11*3941Svenki * and limitations under the License. 12*3941Svenki * 13*3941Svenki * When distributing Covered Code, include this CDDL HEADER in each 14*3941Svenki * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*3941Svenki * If applicable, add the following below this CDDL HEADER, with the 16*3941Svenki * fields enclosed by brackets "[]" replaced with your own identifying 17*3941Svenki * information: Portions Copyright [yyyy] [name of copyright owner] 18*3941Svenki * 19*3941Svenki * CDDL HEADER END 20*3941Svenki */ 21*3941Svenki 22*3941Svenki /* 23*3941Svenki * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 24*3941Svenki * Use is subject to license terms. 25*3941Svenki */ 26*3941Svenki 27*3941Svenki #pragma ident "%Z%%M% %I% %E% SMI" 28*3941Svenki 29*3941Svenki /* 30*3941Svenki * The SNMP picl plugin connects to the agent on the SP and creates 31*3941Svenki * and populates the /physical-platform subtree in picl tree for use 32*3941Svenki * by picl consumers. 33*3941Svenki */ 34*3941Svenki 35*3941Svenki #include <stdio.h> 36*3941Svenki #include <stdlib.h> 37*3941Svenki #include <string.h> 38*3941Svenki #include <syslog.h> 39*3941Svenki #include <stdarg.h> 40*3941Svenki #include <libgen.h> 41*3941Svenki #include <libintl.h> 42*3941Svenki #include <thread.h> 43*3941Svenki #include <synch.h> 44*3941Svenki #include <errno.h> 45*3941Svenki 46*3941Svenki #include <picldefs.h> 47*3941Svenki #include <picl.h> 48*3941Svenki #include <picltree.h> 49*3941Svenki 50*3941Svenki #include "picloids.h" 51*3941Svenki #include "libpiclsnmp.h" 52*3941Svenki #include "snmpplugin.h" 53*3941Svenki 54*3941Svenki #pragma init(snmpplugin_register) /* place in .init section */ 55*3941Svenki 56*3941Svenki picld_plugin_reg_t snmpplugin_reg = { 57*3941Svenki PICLD_PLUGIN_VERSION_1, 58*3941Svenki PICLD_PLUGIN_NON_CRITICAL, 59*3941Svenki "snmp_plugin", 60*3941Svenki snmpplugin_init, 61*3941Svenki snmpplugin_fini 62*3941Svenki }; 63*3941Svenki 64*3941Svenki static picl_snmphdl_t hdl; 65*3941Svenki 66*3941Svenki /* 67*3941Svenki * The stale_tree_rwlp protects the stale_xxx vars. The 'stale_tree' flag 68*3941Svenki * and the 'rebuild_tree' flag below are both initialized to B_TRUE to 69*3941Svenki * let the tree_builder() thread build the initial tree without blocking. 70*3941Svenki */ 71*3941Svenki static rwlock_t stale_tree_rwlp; 72*3941Svenki static boolean_t stale_tree = B_TRUE; 73*3941Svenki 74*3941Svenki /* 75*3941Svenki * vol_props, volprop_ndx and n_vol_props are protected by the stale_tree 76*3941Svenki * flag. They are read only when the stale_tree flag is B_FALSE and written 77*3941Svenki * to only when the flag is B_TRUE. 78*3941Svenki * 79*3941Svenki * The change_time (last changed time) is read by only one thread at a 80*3941Svenki * time when stale_tree is B_FALSE (protected by stale_tree_rwlp). It is 81*3941Svenki * written by only one thread (the tree builder) when stale_tree is B_TRUE. 82*3941Svenki * 83*3941Svenki * Note that strictly speaking, change_time should be uint_t (timeticks32). 84*3941Svenki * But keeping it as int is fine, since we don't do any arithmetic on it 85*3941Svenki * except equality check. 86*3941Svenki */ 87*3941Svenki static vol_prophdl_t *vol_props = NULL; 88*3941Svenki static int volprop_ndx = 0, n_vol_props = 0; 89*3941Svenki static int change_time = 0; 90*3941Svenki 91*3941Svenki /* 92*3941Svenki * The rebuild_tree_lock and cv are used by the tree builder thread. 93*3941Svenki * rebuild_tree has to be initialized to B_TRUE to let the tree_builder 94*3941Svenki * do the first build without blocking. 95*3941Svenki */ 96*3941Svenki static mutex_t rebuild_tree_lock; 97*3941Svenki static cond_t rebuild_tree_cv; 98*3941Svenki static boolean_t rebuild_tree = B_TRUE; 99*3941Svenki 100*3941Svenki /* 101*3941Svenki * These two should really not be global 102*3941Svenki */ 103*3941Svenki static picl_nodehdl_t *physplat_nodes = NULL; 104*3941Svenki static int n_physplat_nodes = 0; 105*3941Svenki 106*3941Svenki static char *group1[] = { 107*3941Svenki OID_entPhysicalDescr, 108*3941Svenki OID_entPhysicalContainedIn, 109*3941Svenki OID_entPhysicalClass, 110*3941Svenki OID_entPhysicalName, 111*3941Svenki OID_entPhysicalHardwareRev, 112*3941Svenki OID_entPhysicalFirmwareRev, 113*3941Svenki OID_entPhysicalSerialNum, 114*3941Svenki OID_entPhysicalMfgName, 115*3941Svenki OID_entPhysicalModelName, 116*3941Svenki OID_entPhysicalIsFRU, 117*3941Svenki 0 118*3941Svenki }; 119*3941Svenki 120*3941Svenki static char *group2[] = { 121*3941Svenki OID_sunPlatEquipmentHolderAcceptableTypes, 122*3941Svenki OID_sunPlatCircuitPackReplaceable, 123*3941Svenki OID_sunPlatCircuitPackHotSwappable, 124*3941Svenki OID_sunPlatPhysicalClass, 125*3941Svenki OID_sunPlatSensorClass, 126*3941Svenki OID_sunPlatSensorType, 127*3941Svenki OID_sunPlatAlarmType, 128*3941Svenki OID_sunPlatPowerSupplyClass, 129*3941Svenki 0 130*3941Svenki }; 131*3941Svenki 132*3941Svenki static char *volgroup1[] = { 133*3941Svenki OID_sunPlatBinarySensorCurrent, 134*3941Svenki OID_sunPlatBinarySensorExpected, 135*3941Svenki OID_sunPlatBinarySensorInterpretTrue, 136*3941Svenki OID_sunPlatBinarySensorInterpretFalse, 137*3941Svenki 0 138*3941Svenki }; 139*3941Svenki 140*3941Svenki static char *volgroup2[] = { 141*3941Svenki OID_sunPlatNumericSensorBaseUnits, 142*3941Svenki OID_sunPlatNumericSensorExponent, 143*3941Svenki OID_sunPlatNumericSensorRateUnits, 144*3941Svenki OID_sunPlatNumericSensorCurrent, 145*3941Svenki OID_sunPlatNumericSensorLowerThresholdFatal, 146*3941Svenki OID_sunPlatNumericSensorLowerThresholdCritical, 147*3941Svenki OID_sunPlatNumericSensorLowerThresholdNonCritical, 148*3941Svenki OID_sunPlatNumericSensorUpperThresholdNonCritical, 149*3941Svenki OID_sunPlatNumericSensorUpperThresholdCritical, 150*3941Svenki OID_sunPlatNumericSensorUpperThresholdFatal, 151*3941Svenki 0 152*3941Svenki }; 153*3941Svenki 154*3941Svenki /* 155*3941Svenki * The following two items must match the Sun Platform MIB specification 156*3941Svenki * in their indices and values. 157*3941Svenki */ 158*3941Svenki static char *sensor_baseunits[] = { 159*3941Svenki "", "other", "unknown", "degC", "degF", "degK", "volts", "amps", 160*3941Svenki "watts", "joules", "coulombs", "va", "nits", "lumens", "lux", 161*3941Svenki "candelas", "kPa", "psi", "newtons", "cfm", "rpm", "hertz", 162*3941Svenki "seconds", "minutes", "hours", "days", "weeks", "mils", "inches", 163*3941Svenki "feet", "cubicInches", "cubicFeet", "meters", "cubicCentimeters", 164*3941Svenki "cubicMeters", "liters", "fluidOunces", "radians", "steradians", 165*3941Svenki "revolutions", "cycles", "gravities", "ounces", "pounds", "footPounds", 166*3941Svenki "ounceInches", "gauss", "gilberts", "henries", "farads", "ohms", 167*3941Svenki "siemens", "moles", "becquerels", "ppm", "decibels", "dBA", "dbC", 168*3941Svenki "grays", "sieverts", "colorTemperatureDegK", "bits", "bytes", "words", 169*3941Svenki "doubleWords", "quadWords", "percentage" 170*3941Svenki }; 171*3941Svenki static const int n_baseunits = sizeof (sensor_baseunits) / sizeof (char *); 172*3941Svenki 173*3941Svenki static char *sensor_rateunits[] = { 174*3941Svenki "", 175*3941Svenki "none", 176*3941Svenki "perMicroSecond", 177*3941Svenki "perMilliSecond", 178*3941Svenki "perSecond", 179*3941Svenki "perMinute", 180*3941Svenki "perHour", 181*3941Svenki "perDay", 182*3941Svenki "perWeek", 183*3941Svenki "perMonth", 184*3941Svenki "perYear" 185*3941Svenki }; 186*3941Svenki static const int n_rateunits = sizeof (sensor_rateunits) / sizeof (char *); 187*3941Svenki 188*3941Svenki /* 189*3941Svenki * Local declarations 190*3941Svenki */ 191*3941Svenki static void snmpplugin_register(void); 192*3941Svenki static void register_group(char **g, int is_volatile); 193*3941Svenki static void *tree_builder(void *arg); 194*3941Svenki static int build_physplat(picl_nodehdl_t *subtree_rootp); 195*3941Svenki static void free_resources(picl_nodehdl_t subtree_root); 196*3941Svenki 197*3941Svenki static picl_nodehdl_t make_node(picl_nodehdl_t subtree_root, int row, 198*3941Svenki int *snmp_syserr_p); 199*3941Svenki static void save_nodeh(picl_nodehdl_t nodeh, int row); 200*3941Svenki static picl_nodehdl_t lookup_nodeh(int row); 201*3941Svenki 202*3941Svenki static void save_volprop(picl_prophdl_t prop, char *oidstr, int row, 203*3941Svenki int proptype); 204*3941Svenki static void check_for_stale_data(void); 205*3941Svenki static int read_volprop(ptree_rarg_t *parg, void *buf); 206*3941Svenki 207*3941Svenki static void threshold(picl_nodehdl_t node, char *oidstr, int row, 208*3941Svenki char *propname, int *snmp_syserr_p); 209*3941Svenki static void add_thresholds(picl_nodehdl_t node, int row, int *snmp_syserr_p); 210*3941Svenki 211*3941Svenki static char *get_slot_type(int row, int *snmp_syserr_p); 212*3941Svenki static int add_volatile_prop(picl_nodehdl_t nodeh, char *name, 213*3941Svenki int type, int access, int size, int (*rdfunc)(ptree_rarg_t *, void *), 214*3941Svenki int (*wrfunc)(ptree_warg_t *, const void *), picl_prophdl_t *propp); 215*3941Svenki static int add_string_prop(picl_nodehdl_t node, char *propname, char *propval); 216*3941Svenki static int add_void_prop(picl_nodehdl_t node, char *propname); 217*3941Svenki static int add_int_prop(picl_nodehdl_t node, char *propname, int val); 218*3941Svenki static void add_prop(picl_nodehdl_t nodeh, picl_prophdl_t *php, char *label, 219*3941Svenki int row, sp_propid_t pp, int *snmp_syserr_p); 220*3941Svenki 221*3941Svenki static void log_msg(int pri, const char *fmt, ...); 222*3941Svenki 223*3941Svenki #ifdef SNMPPLUGIN_DEBUG 224*3941Svenki static mutex_t snmpplugin_dbuf_lock; 225*3941Svenki static char *snmpplugin_dbuf = NULL; 226*3941Svenki static char *snmpplugin_dbuf_curp = NULL; 227*3941Svenki static int snmpplugin_dbuf_sz = 0; 228*3941Svenki static int snmpplugin_dbuf_overflow = 0; 229*3941Svenki static char snmpplugin_lbuf[SNMPPLUGIN_DMAX_LINE]; 230*3941Svenki 231*3941Svenki static void snmpplugin_log_init(void); 232*3941Svenki static void snmpplugin_log(const char *fmt, ...); 233*3941Svenki static void snmpplugin_log_append(void); 234*3941Svenki static void snmpplugin_dbuf_realloc(void); 235*3941Svenki #endif 236*3941Svenki 237*3941Svenki static void 238*3941Svenki snmpplugin_register(void) 239*3941Svenki { 240*3941Svenki (void) picld_plugin_register(&snmpplugin_reg); 241*3941Svenki } 242*3941Svenki 243*3941Svenki static void 244*3941Svenki register_group(char **g, int is_volatile) 245*3941Svenki { 246*3941Svenki int i, len = 0; 247*3941Svenki int n_oids; 248*3941Svenki char *p, *oidstrs; 249*3941Svenki 250*3941Svenki for (i = 0; g[i]; i++) 251*3941Svenki len += strlen(g[i]) + 1; 252*3941Svenki n_oids = i; 253*3941Svenki 254*3941Svenki if ((oidstrs = (char *)calloc(1, len)) == NULL) 255*3941Svenki return; 256*3941Svenki 257*3941Svenki for (p = oidstrs, i = 0; g[i]; i++) { 258*3941Svenki (void) strcpy(p, g[i]); 259*3941Svenki p += strlen(g[i]) + 1; 260*3941Svenki } 261*3941Svenki 262*3941Svenki snmp_register_group(hdl, oidstrs, n_oids, is_volatile); 263*3941Svenki } 264*3941Svenki 265*3941Svenki void 266*3941Svenki snmpplugin_init(void) 267*3941Svenki { 268*3941Svenki int ret; 269*3941Svenki 270*3941Svenki (void) mutex_init(&rebuild_tree_lock, USYNC_THREAD, NULL); 271*3941Svenki (void) cond_init(&rebuild_tree_cv, USYNC_THREAD, NULL); 272*3941Svenki (void) rwlock_init(&stale_tree_rwlp, USYNC_THREAD, NULL); 273*3941Svenki LOGINIT(); 274*3941Svenki 275*3941Svenki /* 276*3941Svenki * Create the tree-builder thread and let it take over 277*3941Svenki */ 278*3941Svenki LOGPRINTF("Tree-builder thread being created.\n"); 279*3941Svenki if ((ret = thr_create(NULL, NULL, tree_builder, NULL, 280*3941Svenki THR_BOUND, NULL)) < 0) { 281*3941Svenki log_msg(LOG_ERR, SNMPP_CANT_CREATE_TREE_BUILDER, ret); 282*3941Svenki snmp_fini(hdl); 283*3941Svenki return; 284*3941Svenki } 285*3941Svenki } 286*3941Svenki 287*3941Svenki void 288*3941Svenki snmpplugin_fini(void) 289*3941Svenki { 290*3941Svenki snmp_fini(hdl); 291*3941Svenki 292*3941Svenki (void) rwlock_destroy(&stale_tree_rwlp); 293*3941Svenki (void) cond_destroy(&rebuild_tree_cv); 294*3941Svenki (void) mutex_destroy(&rebuild_tree_lock); 295*3941Svenki } 296*3941Svenki 297*3941Svenki /*ARGSUSED*/ 298*3941Svenki static void * 299*3941Svenki tree_builder(void *arg) 300*3941Svenki { 301*3941Svenki int ret, rv; 302*3941Svenki picl_nodehdl_t root_node; 303*3941Svenki picl_nodehdl_t physplat_root; 304*3941Svenki picl_nodehdl_t old_physplat_root; 305*3941Svenki 306*3941Svenki /* 307*3941Svenki * Initialize SNMP service 308*3941Svenki */ 309*3941Svenki LOGPRINTF("Initializing SNMP service.\n"); 310*3941Svenki if ((hdl = snmp_init()) == NULL) { 311*3941Svenki log_msg(LOG_ERR, SNMPP_CANT_INIT); 312*3941Svenki return ((void *)-1); 313*3941Svenki } 314*3941Svenki 315*3941Svenki /* 316*3941Svenki * Register OID groupings for BULKGET optimizations 317*3941Svenki */ 318*3941Svenki LOGPRINTF("Registering OID groups.\n"); 319*3941Svenki register_group(group1, 0); 320*3941Svenki register_group(group2, 0); 321*3941Svenki register_group(volgroup1, 1); 322*3941Svenki register_group(volgroup2, 1); 323*3941Svenki 324*3941Svenki (void) mutex_lock(&rebuild_tree_lock); 325*3941Svenki 326*3941Svenki for (;;) { 327*3941Svenki LOGPRINTF("tree_builder: check whether to rebuild subtree\n"); 328*3941Svenki while (rebuild_tree == B_FALSE) 329*3941Svenki (void) cond_wait(&rebuild_tree_cv, &rebuild_tree_lock); 330*3941Svenki 331*3941Svenki LOGPRINTF("tree_builder: woke up\n"); 332*3941Svenki 333*3941Svenki old_physplat_root = NULL; 334*3941Svenki physplat_root = NULL; 335*3941Svenki 336*3941Svenki LOGPRINTF("tree_builder: getting root node\n"); 337*3941Svenki if ((ret = ptree_get_root(&root_node)) != PICL_SUCCESS) { 338*3941Svenki log_msg(LOG_ERR, SNMPP_NO_ROOT, ret); 339*3941Svenki return ((void *)-2); 340*3941Svenki } 341*3941Svenki 342*3941Svenki LOGPRINTF("tree_builder: getting existing physplat node\n"); 343*3941Svenki rv = ptree_find_node(root_node, PICL_PROP_NAME, 344*3941Svenki PICL_PTYPE_CHARSTRING, PICL_NODE_PHYSPLAT, 345*3941Svenki sizeof (PICL_NODE_PHYSPLAT), &old_physplat_root); 346*3941Svenki 347*3941Svenki LOGPRINTF("tree_builder: building physical-platform\n"); 348*3941Svenki if ((ret = build_physplat(&physplat_root)) < 0) { 349*3941Svenki log_msg(LOG_ERR, SNMPP_CANT_CREATE_PHYSPLAT, ret); 350*3941Svenki snmp_fini(hdl); 351*3941Svenki return ((void *)-3); 352*3941Svenki } 353*3941Svenki 354*3941Svenki if (rv == PICL_SUCCESS && old_physplat_root != NULL) { 355*3941Svenki LOGPRINTF("tree_builder: destroying existing nodes\n"); 356*3941Svenki ptree_delete_node(old_physplat_root); 357*3941Svenki ptree_destroy_node(old_physplat_root); 358*3941Svenki } 359*3941Svenki 360*3941Svenki LOGPRINTF("tree_builder: attaching new subtree\n"); 361*3941Svenki if ((ret = ptree_add_node(root_node, physplat_root)) < 0) { 362*3941Svenki free_resources(physplat_root); 363*3941Svenki log_msg(LOG_ERR, SNMPP_CANT_CREATE_PHYSPLAT, ret); 364*3941Svenki snmp_fini(hdl); 365*3941Svenki return ((void *)-4); 366*3941Svenki } 367*3941Svenki 368*3941Svenki LOGPRINTF("tree_builder: setting stale_tree to FALSE\n"); 369*3941Svenki (void) rw_wrlock(&stale_tree_rwlp); 370*3941Svenki stale_tree = B_FALSE; 371*3941Svenki (void) rw_unlock(&stale_tree_rwlp); 372*3941Svenki 373*3941Svenki LOGPRINTF("tree_builder: setting rebuild_tree to FALSE\n"); 374*3941Svenki rebuild_tree = B_FALSE; 375*3941Svenki } 376*3941Svenki 377*3941Svenki /*NOTREACHED*/ 378*3941Svenki return (NULL); 379*3941Svenki } 380*3941Svenki 381*3941Svenki static int 382*3941Svenki build_physplat(picl_nodehdl_t *subtree_rootp) 383*3941Svenki { 384*3941Svenki int change_time1; 385*3941Svenki int row, nxtrow; 386*3941Svenki int clr_linkreset = 0; 387*3941Svenki int ret = 0; 388*3941Svenki int snmp_syserr = 0; 389*3941Svenki 390*3941Svenki retry: 391*3941Svenki (void) snmp_reinit(hdl, clr_linkreset); 392*3941Svenki clr_linkreset = 0; 393*3941Svenki 394*3941Svenki /* 395*3941Svenki * Record LastChangeTime before we start building the tree 396*3941Svenki */ 397*3941Svenki ret = snmp_get_int(hdl, OID_entLastChangeTime, 0, 398*3941Svenki &change_time1, &snmp_syserr); 399*3941Svenki if (ret < 0) { 400*3941Svenki if (snmp_syserr == ECANCELED) { 401*3941Svenki log_msg(LOG_WARNING, SNMPP_LINK_RESET); 402*3941Svenki clr_linkreset = 1; 403*3941Svenki goto retry; 404*3941Svenki } else 405*3941Svenki log_msg(LOG_WARNING, SNMPP_CANT_FETCH_OBJECT_VAL, ret); 406*3941Svenki } 407*3941Svenki 408*3941Svenki /* 409*3941Svenki * Create the physical-platform node 410*3941Svenki */ 411*3941Svenki ret = ptree_create_node(PICL_NODE_PHYSPLAT, PICL_CLASS_PICL, 412*3941Svenki subtree_rootp); 413*3941Svenki if (ret != PICL_SUCCESS) 414*3941Svenki return (-1); 415*3941Svenki 416*3941Svenki /* 417*3941Svenki * Scan entPhysicalTable and build the "physical-platform" subtree 418*3941Svenki */ 419*3941Svenki ret = 0; 420*3941Svenki for (row = -1; ret == 0; row = nxtrow) { 421*3941Svenki ret = snmp_get_nextrow(hdl, OID_entPhysicalDescr, 422*3941Svenki row, &nxtrow, &snmp_syserr); 423*3941Svenki if (ret == 0) { 424*3941Svenki (void) make_node(*subtree_rootp, nxtrow, &snmp_syserr); 425*3941Svenki } 426*3941Svenki 427*3941Svenki if (snmp_syserr == ECANCELED) { 428*3941Svenki /* 429*3941Svenki * If we get this error, a link reset must've 430*3941Svenki * happened and we need to throw away everything 431*3941Svenki * we have now and rebuild the tree again. 432*3941Svenki */ 433*3941Svenki log_msg(LOG_WARNING, SNMPP_LINK_RESET); 434*3941Svenki free_resources(*subtree_rootp); 435*3941Svenki clr_linkreset = 1; 436*3941Svenki goto retry; 437*3941Svenki } 438*3941Svenki } 439*3941Svenki 440*3941Svenki /* 441*3941Svenki * Record LastChangeTime after we're done building the tree 442*3941Svenki */ 443*3941Svenki ret = snmp_get_int(hdl, OID_entLastChangeTime, 0, 444*3941Svenki &change_time, &snmp_syserr); 445*3941Svenki if (ret < 0) { 446*3941Svenki if (snmp_syserr == ECANCELED) { 447*3941Svenki log_msg(LOG_WARNING, SNMPP_LINK_RESET); 448*3941Svenki free_resources(*subtree_rootp); 449*3941Svenki clr_linkreset = 1; 450*3941Svenki goto retry; 451*3941Svenki } else 452*3941Svenki log_msg(LOG_WARNING, SNMPP_CANT_FETCH_OBJECT_VAL, ret); 453*3941Svenki } 454*3941Svenki 455*3941Svenki /* 456*3941Svenki * If they don't match, some hotplugging must've happened, 457*3941Svenki * free resources we've created and still holding, then go 458*3941Svenki * back and retry 459*3941Svenki */ 460*3941Svenki if (change_time != change_time1) { 461*3941Svenki LOGPRINTF("build_physplat: entLastChangeTime has changed!\n"); 462*3941Svenki free_resources(*subtree_rootp); 463*3941Svenki change_time1 = change_time; 464*3941Svenki goto retry; 465*3941Svenki } 466*3941Svenki 467*3941Svenki /* 468*3941Svenki * The physplat_nodes table is no longer needed, free it 469*3941Svenki */ 470*3941Svenki if (physplat_nodes) { 471*3941Svenki free(physplat_nodes); 472*3941Svenki physplat_nodes = NULL; 473*3941Svenki n_physplat_nodes = 0; 474*3941Svenki } 475*3941Svenki 476*3941Svenki return (0); 477*3941Svenki } 478*3941Svenki 479*3941Svenki /* 480*3941Svenki * Destroy all resources that were created during the building 481*3941Svenki * of the subtree 482*3941Svenki */ 483*3941Svenki static void 484*3941Svenki free_resources(picl_nodehdl_t subtree_root) 485*3941Svenki { 486*3941Svenki if (physplat_nodes) { 487*3941Svenki free(physplat_nodes); 488*3941Svenki physplat_nodes = NULL; 489*3941Svenki n_physplat_nodes = 0; 490*3941Svenki } 491*3941Svenki 492*3941Svenki if (subtree_root) { 493*3941Svenki (void) ptree_delete_node(subtree_root); 494*3941Svenki (void) ptree_destroy_node(subtree_root); 495*3941Svenki } 496*3941Svenki 497*3941Svenki if (vol_props) { 498*3941Svenki free(vol_props); 499*3941Svenki n_vol_props = 0; 500*3941Svenki volprop_ndx = 0; 501*3941Svenki } 502*3941Svenki } 503*3941Svenki 504*3941Svenki static picl_nodehdl_t 505*3941Svenki make_node(picl_nodehdl_t subtree_root, int row, int *snmp_syserr_p) 506*3941Svenki { 507*3941Svenki picl_nodehdl_t nodeh, parenth; 508*3941Svenki picl_prophdl_t proph; 509*3941Svenki char *phys_name, *node_name; 510*3941Svenki int parent_row; 511*3941Svenki int ent_physclass, sunplat_physclass; 512*3941Svenki int sensor_class, sensor_type; 513*3941Svenki int alarm_type; 514*3941Svenki int ps_class; 515*3941Svenki int ret; 516*3941Svenki 517*3941Svenki /* 518*3941Svenki * If we've already created this picl node, just return it 519*3941Svenki */ 520*3941Svenki if ((nodeh = lookup_nodeh(row)) != NULL) 521*3941Svenki return (nodeh); 522*3941Svenki 523*3941Svenki /* 524*3941Svenki * If we are creating it only now, make sure we have the parent 525*3941Svenki * created first; if there's no parent, then parent it to the 526*3941Svenki * subtree's root node 527*3941Svenki */ 528*3941Svenki ret = snmp_get_int(hdl, OID_entPhysicalContainedIn, row, 529*3941Svenki &parent_row, snmp_syserr_p); 530*3941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 531*3941Svenki if (ret < 0 || parent_row <= 0) 532*3941Svenki parenth = subtree_root; 533*3941Svenki else { 534*3941Svenki parenth = make_node(subtree_root, parent_row, snmp_syserr_p); 535*3941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 536*3941Svenki if (parenth == NULL) 537*3941Svenki parenth = subtree_root; 538*3941Svenki } 539*3941Svenki 540*3941Svenki /* 541*3941Svenki * Figure out the physical-platform node name from entPhysicalName; 542*3941Svenki * all rows in the MIB that have a valid entPhysicalIndex should 543*3941Svenki * have a physical name. 544*3941Svenki */ 545*3941Svenki ret = snmp_get_str(hdl, OID_entPhysicalName, row, 546*3941Svenki &phys_name, snmp_syserr_p); 547*3941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 548*3941Svenki if (ret < 0 || phys_name == NULL) { 549*3941Svenki log_msg(LOG_WARNING, SNMPP_NO_ENTPHYSNAME, row); 550*3941Svenki return (NULL); 551*3941Svenki } 552*3941Svenki 553*3941Svenki node_name = basename(phys_name); 554*3941Svenki 555*3941Svenki ret = snmp_get_int(hdl, OID_entPhysicalClass, row, 556*3941Svenki &ent_physclass, snmp_syserr_p); 557*3941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 558*3941Svenki if (ret < 0) { 559*3941Svenki log_msg(LOG_WARNING, SNMPP_CANT_FETCH_OBJECT_VAL, ret); 560*3941Svenki free(phys_name); 561*3941Svenki return (NULL); 562*3941Svenki } 563*3941Svenki 564*3941Svenki switch (ent_physclass) { 565*3941Svenki case SPC_OTHER: 566*3941Svenki ret = snmp_get_int(hdl, OID_sunPlatPhysicalClass, row, 567*3941Svenki &sunplat_physclass, snmp_syserr_p); 568*3941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 569*3941Svenki if (ret < 0) { 570*3941Svenki log_msg(LOG_WARNING, SNMPP_CANT_FETCH_OBJECT_VAL, ret); 571*3941Svenki free(phys_name); 572*3941Svenki return (NULL); 573*3941Svenki } 574*3941Svenki 575*3941Svenki if (sunplat_physclass == SSPC_ALARM) { 576*3941Svenki ret = snmp_get_int(hdl, OID_sunPlatAlarmType, 577*3941Svenki row, &alarm_type, snmp_syserr_p); 578*3941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 579*3941Svenki if (ret < 0) { 580*3941Svenki log_msg(LOG_WARNING, 581*3941Svenki SNMPP_CANT_FETCH_OBJECT_VAL, ret); 582*3941Svenki free(phys_name); 583*3941Svenki return (NULL); 584*3941Svenki } 585*3941Svenki 586*3941Svenki if (alarm_type == SSAT_VISIBLE) { 587*3941Svenki ADD_NODE(PICL_CLASS_LED) 588*3941Svenki } else { 589*3941Svenki ADD_NODE(PICL_CLASS_ALARM) 590*3941Svenki } 591*3941Svenki 592*3941Svenki add_prop(nodeh, &proph, node_name, row, PP_STATE, 593*3941Svenki snmp_syserr_p); 594*3941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 595*3941Svenki } else { 596*3941Svenki ADD_NODE(PICL_CLASS_OTHER) 597*3941Svenki } 598*3941Svenki 599*3941Svenki add_prop(nodeh, &proph, node_name, row, PP_OPSTATUS, 600*3941Svenki snmp_syserr_p); 601*3941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 602*3941Svenki break; 603*3941Svenki 604*3941Svenki case SPC_UNKNOWN: 605*3941Svenki ADD_NODE(PICL_CLASS_UNKNOWN) 606*3941Svenki break; 607*3941Svenki 608*3941Svenki case SPC_CHASSIS: 609*3941Svenki ADD_NODE(PICL_CLASS_CHASSIS) 610*3941Svenki add_prop(nodeh, &proph, node_name, row, PP_OPSTATUS, 611*3941Svenki snmp_syserr_p); 612*3941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 613*3941Svenki break; 614*3941Svenki 615*3941Svenki case SPC_BACKPLANE: 616*3941Svenki ADD_NODE(PICL_CLASS_BACKPLANE) 617*3941Svenki add_prop(nodeh, &proph, node_name, row, PP_OPSTATUS, 618*3941Svenki snmp_syserr_p); 619*3941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 620*3941Svenki break; 621*3941Svenki 622*3941Svenki case SPC_CONTAINER: 623*3941Svenki ADD_NODE(PICL_CLASS_CONTAINER) 624*3941Svenki 625*3941Svenki add_prop(nodeh, &proph, node_name, row, PP_OPSTATUS, 626*3941Svenki snmp_syserr_p); 627*3941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 628*3941Svenki 629*3941Svenki add_prop(nodeh, &proph, node_name, row, PP_SLOT_TYPE, 630*3941Svenki snmp_syserr_p); 631*3941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 632*3941Svenki break; 633*3941Svenki 634*3941Svenki case SPC_POWERSUPPLY: 635*3941Svenki ret = snmp_get_int(hdl, OID_sunPlatPowerSupplyClass, 636*3941Svenki row, &ps_class, snmp_syserr_p); 637*3941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 638*3941Svenki if (ret < 0) { 639*3941Svenki log_msg(LOG_WARNING, SNMPP_CANT_FETCH_OBJECT_VAL, ret); 640*3941Svenki free(phys_name); 641*3941Svenki return (NULL); 642*3941Svenki } 643*3941Svenki 644*3941Svenki if (ps_class == SSPSC_BATTERY) { 645*3941Svenki ADD_NODE(PICL_CLASS_BATTERY) 646*3941Svenki add_prop(nodeh, &proph, node_name, row, 647*3941Svenki PP_BATT_STATUS, snmp_syserr_p); 648*3941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 649*3941Svenki } else { 650*3941Svenki ADD_NODE(PICL_CLASS_POWERSUPPLY) 651*3941Svenki } 652*3941Svenki add_prop(nodeh, &proph, node_name, row, PP_OPSTATUS, 653*3941Svenki snmp_syserr_p); 654*3941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 655*3941Svenki break; 656*3941Svenki 657*3941Svenki case SPC_FAN: 658*3941Svenki ADD_NODE(PICL_CLASS_FAN) 659*3941Svenki add_prop(nodeh, &proph, node_name, row, PP_OPSTATUS, 660*3941Svenki snmp_syserr_p); 661*3941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 662*3941Svenki break; 663*3941Svenki 664*3941Svenki case SPC_SENSOR: 665*3941Svenki ret = snmp_get_int(hdl, OID_sunPlatSensorClass, 666*3941Svenki row, &sensor_class, snmp_syserr_p); 667*3941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 668*3941Svenki if (ret < 0) { 669*3941Svenki log_msg(LOG_WARNING, SNMPP_CANT_FETCH_OBJECT_VAL, ret); 670*3941Svenki free(phys_name); 671*3941Svenki return (NULL); 672*3941Svenki } 673*3941Svenki 674*3941Svenki ret = snmp_get_int(hdl, OID_sunPlatSensorType, 675*3941Svenki row, &sensor_type, snmp_syserr_p); 676*3941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 677*3941Svenki if (ret < 0) { 678*3941Svenki log_msg(LOG_WARNING, SNMPP_CANT_FETCH_OBJECT_VAL, ret); 679*3941Svenki free(phys_name); 680*3941Svenki return (NULL); 681*3941Svenki } 682*3941Svenki 683*3941Svenki if (sensor_class == SSSC_NUMERIC) { 684*3941Svenki if (sensor_type == SSST_TEMPERATURE) { 685*3941Svenki ADD_NODE(PICL_CLASS_TEMPERATURE_SENSOR) 686*3941Svenki add_prop(nodeh, &proph, node_name, row, 687*3941Svenki PP_TEMPERATURE, snmp_syserr_p); 688*3941Svenki } else if (sensor_type == SSST_VOLTAGE) { 689*3941Svenki ADD_NODE(PICL_CLASS_VOLTAGE_SENSOR) 690*3941Svenki add_prop(nodeh, &proph, node_name, row, 691*3941Svenki PP_VOLTAGE, snmp_syserr_p); 692*3941Svenki } else if (sensor_type == SSST_CURRENT) { 693*3941Svenki ADD_NODE(PICL_CLASS_CURRENT_SENSOR) 694*3941Svenki add_prop(nodeh, &proph, node_name, row, 695*3941Svenki PP_CURRENT, snmp_syserr_p); 696*3941Svenki } else if (sensor_type == SSST_TACHOMETER) { 697*3941Svenki ADD_NODE(PICL_CLASS_RPM_SENSOR) 698*3941Svenki add_prop(nodeh, &proph, node_name, row, 699*3941Svenki PP_SPEED, snmp_syserr_p); 700*3941Svenki } else { 701*3941Svenki ADD_NODE(PICL_CLASS_SENSOR) 702*3941Svenki add_prop(nodeh, &proph, node_name, row, 703*3941Svenki PP_SENSOR_VALUE, snmp_syserr_p); 704*3941Svenki } 705*3941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 706*3941Svenki 707*3941Svenki add_prop(nodeh, &proph, node_name, row, 708*3941Svenki PP_OPSTATUS, snmp_syserr_p); 709*3941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 710*3941Svenki 711*3941Svenki add_prop(nodeh, &proph, node_name, row, 712*3941Svenki PP_BASE_UNITS, snmp_syserr_p); 713*3941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 714*3941Svenki 715*3941Svenki add_prop(nodeh, &proph, node_name, row, 716*3941Svenki PP_EXPONENT, snmp_syserr_p); 717*3941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 718*3941Svenki 719*3941Svenki add_prop(nodeh, &proph, node_name, row, 720*3941Svenki PP_RATE_UNITS, snmp_syserr_p); 721*3941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 722*3941Svenki 723*3941Svenki add_thresholds(nodeh, row, snmp_syserr_p); 724*3941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 725*3941Svenki 726*3941Svenki } else if (sensor_class == SSSC_BINARY) { 727*3941Svenki if (sensor_type == SSST_TEMPERATURE) { 728*3941Svenki ADD_NODE(PICL_CLASS_TEMPERATURE_INDICATOR) 729*3941Svenki } else if (sensor_type == SSST_VOLTAGE) { 730*3941Svenki ADD_NODE(PICL_CLASS_VOLTAGE_INDICATOR) 731*3941Svenki } else if (sensor_type == SSST_CURRENT) { 732*3941Svenki ADD_NODE(PICL_CLASS_CURRENT_INDICATOR) 733*3941Svenki } else if (sensor_type == SSST_TACHOMETER) { 734*3941Svenki ADD_NODE(PICL_CLASS_RPM_INDICATOR) 735*3941Svenki } else if (sensor_type == SSST_PRESENCE) { 736*3941Svenki ADD_NODE(PICL_CLASS_PRESENCE_INDICATOR) 737*3941Svenki } else { 738*3941Svenki ADD_NODE(PICL_CLASS_INDICATOR) 739*3941Svenki } 740*3941Svenki 741*3941Svenki add_prop(nodeh, &proph, node_name, row, PP_OPSTATUS, 742*3941Svenki snmp_syserr_p); 743*3941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 744*3941Svenki 745*3941Svenki add_prop(nodeh, &proph, node_name, row, PP_CONDITION, 746*3941Svenki snmp_syserr_p); 747*3941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 748*3941Svenki 749*3941Svenki add_prop(nodeh, &proph, node_name, row, PP_EXPECTED, 750*3941Svenki snmp_syserr_p); 751*3941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 752*3941Svenki } else { 753*3941Svenki log_msg(LOG_ERR, 754*3941Svenki SNMPP_UNSUPP_SENSOR_CLASS, sensor_class, row); 755*3941Svenki return (NULL); 756*3941Svenki } 757*3941Svenki break; 758*3941Svenki 759*3941Svenki case SPC_MODULE: 760*3941Svenki ADD_NODE(PICL_CLASS_MODULE) 761*3941Svenki 762*3941Svenki add_prop(nodeh, &proph, node_name, row, PP_OPSTATUS, 763*3941Svenki snmp_syserr_p); 764*3941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 765*3941Svenki 766*3941Svenki add_prop(nodeh, &proph, node_name, row, PP_REPLACEABLE, 767*3941Svenki snmp_syserr_p); 768*3941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 769*3941Svenki 770*3941Svenki add_prop(nodeh, &proph, node_name, row, PP_HOTSWAPPABLE, 771*3941Svenki snmp_syserr_p); 772*3941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 773*3941Svenki break; 774*3941Svenki 775*3941Svenki case SPC_PORT: 776*3941Svenki ADD_NODE(PICL_CLASS_PORT) 777*3941Svenki break; 778*3941Svenki 779*3941Svenki case SPC_STACK: 780*3941Svenki ADD_NODE(PICL_CLASS_STACK) 781*3941Svenki break; 782*3941Svenki 783*3941Svenki default: 784*3941Svenki log_msg(LOG_WARNING, 785*3941Svenki SNMPP_UNKNOWN_ENTPHYSCLASS, ent_physclass, row); 786*3941Svenki free(phys_name); 787*3941Svenki return (NULL); 788*3941Svenki } 789*3941Svenki 790*3941Svenki add_prop(nodeh, &proph, node_name, row, PP_DESCRIPTION, snmp_syserr_p); 791*3941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 792*3941Svenki 793*3941Svenki add_prop(nodeh, &proph, node_name, row, PP_LABEL, snmp_syserr_p); 794*3941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 795*3941Svenki 796*3941Svenki add_prop(nodeh, &proph, node_name, row, PP_HW_REVISION, snmp_syserr_p); 797*3941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 798*3941Svenki 799*3941Svenki add_prop(nodeh, &proph, node_name, row, PP_FW_REVISION, snmp_syserr_p); 800*3941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 801*3941Svenki 802*3941Svenki add_prop(nodeh, &proph, node_name, row, PP_SERIAL_NUM, snmp_syserr_p); 803*3941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 804*3941Svenki 805*3941Svenki add_prop(nodeh, &proph, node_name, row, PP_MFG_NAME, snmp_syserr_p); 806*3941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 807*3941Svenki 808*3941Svenki add_prop(nodeh, &proph, node_name, row, PP_MODEL_NAME, snmp_syserr_p); 809*3941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 810*3941Svenki 811*3941Svenki add_prop(nodeh, &proph, node_name, row, PP_IS_FRU, snmp_syserr_p); 812*3941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 813*3941Svenki 814*3941Svenki free(phys_name); 815*3941Svenki save_nodeh(nodeh, row); 816*3941Svenki 817*3941Svenki return (nodeh); 818*3941Svenki } 819*3941Svenki 820*3941Svenki /* 821*3941Svenki * Saves the node handle and the row id into physplat_nodes[]. If we're 822*3941Svenki * doing this in response to a hotplug event, we should've freed the 823*3941Svenki * old physplat_nodes before entering here to save the first node of the 824*3941Svenki * new physplat subtree. 825*3941Svenki */ 826*3941Svenki static void 827*3941Svenki save_nodeh(picl_nodehdl_t nodeh, int row) 828*3941Svenki { 829*3941Svenki size_t sz, count; 830*3941Svenki picl_nodehdl_t *p; 831*3941Svenki 832*3941Svenki if (row >= n_physplat_nodes) { 833*3941Svenki count = (((size_t)row >> NODE_BLOCK_SHIFT) + 1) * 834*3941Svenki N_ELEMS_IN_NODE_BLOCK; 835*3941Svenki sz = count * sizeof (picl_nodehdl_t); 836*3941Svenki 837*3941Svenki p = (picl_nodehdl_t *)calloc(count, sizeof (picl_nodehdl_t)); 838*3941Svenki if (p == NULL) { 839*3941Svenki log_msg(LOG_ERR, SNMPP_NO_MEM, sz); 840*3941Svenki return; 841*3941Svenki } 842*3941Svenki 843*3941Svenki if (physplat_nodes) { 844*3941Svenki (void) memcpy((void *) p, (void *) physplat_nodes, 845*3941Svenki n_physplat_nodes * sizeof (picl_nodehdl_t)); 846*3941Svenki free((void *) physplat_nodes); 847*3941Svenki } 848*3941Svenki 849*3941Svenki physplat_nodes = p; 850*3941Svenki n_physplat_nodes = count; 851*3941Svenki } 852*3941Svenki 853*3941Svenki physplat_nodes[row] = nodeh; 854*3941Svenki } 855*3941Svenki 856*3941Svenki static picl_nodehdl_t 857*3941Svenki lookup_nodeh(int row) 858*3941Svenki { 859*3941Svenki if (row >= n_physplat_nodes) 860*3941Svenki return (NULL); 861*3941Svenki 862*3941Svenki return (physplat_nodes[row]); 863*3941Svenki } 864*3941Svenki 865*3941Svenki /* 866*3941Svenki * We enter this routine only when we are building the physical-platform 867*3941Svenki * subtree, whether for the first time or in response to a hotplug event. 868*3941Svenki * If we're here for rebuilding the tree, we have already set stale_tree 869*3941Svenki * to be B_TRUE, so no one else would be accessing vol_props, n_vol_props 870*3941Svenki * or volprop_ndx. If we're here to build the tree for the first time, 871*3941Svenki * picld hasn't yet created doors and is running single-threaded, so no 872*3941Svenki * one else would be accessing them anyway. 873*3941Svenki */ 874*3941Svenki static void 875*3941Svenki save_volprop(picl_prophdl_t prop, char *oidstr, int row, int proptype) 876*3941Svenki { 877*3941Svenki vol_prophdl_t *p; 878*3941Svenki int count; 879*3941Svenki 880*3941Svenki if (volprop_ndx == n_vol_props) { 881*3941Svenki count = n_vol_props + N_ELEMS_IN_VOLPROP_BLOCK; 882*3941Svenki p = (vol_prophdl_t *)calloc(count, sizeof (vol_prophdl_t)); 883*3941Svenki if (p == NULL) { 884*3941Svenki log_msg(LOG_ERR, SNMPP_NO_MEM, 885*3941Svenki count * sizeof (vol_prophdl_t)); 886*3941Svenki return; 887*3941Svenki } 888*3941Svenki 889*3941Svenki if (vol_props) { 890*3941Svenki (void) memcpy((void *) p, (void *) vol_props, 891*3941Svenki n_vol_props * sizeof (vol_prophdl_t)); 892*3941Svenki free((void *) vol_props); 893*3941Svenki } 894*3941Svenki 895*3941Svenki vol_props = p; 896*3941Svenki n_vol_props += N_ELEMS_IN_VOLPROP_BLOCK; 897*3941Svenki } 898*3941Svenki 899*3941Svenki vol_props[volprop_ndx].prop = prop; 900*3941Svenki vol_props[volprop_ndx].oidstr = oidstr; 901*3941Svenki vol_props[volprop_ndx].row = row; 902*3941Svenki vol_props[volprop_ndx].proptype = proptype; 903*3941Svenki 904*3941Svenki volprop_ndx++; 905*3941Svenki } 906*3941Svenki 907*3941Svenki static void 908*3941Svenki check_for_stale_data(void) 909*3941Svenki { 910*3941Svenki int cur_change_time; 911*3941Svenki int ret; 912*3941Svenki int snmp_syserr; 913*3941Svenki 914*3941Svenki (void) rw_wrlock(&stale_tree_rwlp); 915*3941Svenki 916*3941Svenki /* 917*3941Svenki * Check if some other thread beat us to it 918*3941Svenki */ 919*3941Svenki if (stale_tree == B_TRUE) { 920*3941Svenki (void) rw_unlock(&stale_tree_rwlp); 921*3941Svenki return; 922*3941Svenki } 923*3941Svenki 924*3941Svenki /* 925*3941Svenki * Check if mib data has changed (hotplug? link-reset?) 926*3941Svenki */ 927*3941Svenki ret = snmp_get_int(hdl, OID_entLastChangeTime, 0, &cur_change_time, 928*3941Svenki &snmp_syserr); 929*3941Svenki if ((ret == 0) && (cur_change_time == change_time)) { 930*3941Svenki (void) rw_unlock(&stale_tree_rwlp); 931*3941Svenki return; 932*3941Svenki } 933*3941Svenki 934*3941Svenki /* 935*3941Svenki * If we can't read entLastChangeTime we assume we need to rebuild 936*3941Svenki * the tree. This will also cover the case when we need to rebuild 937*3941Svenki * the tree because a link reset had happened. 938*3941Svenki */ 939*3941Svenki LOGPRINTF2("check_for_stale_data: LastChange times have changed, " 940*3941Svenki "(%#x != %#x)\n", change_time, cur_change_time); 941*3941Svenki 942*3941Svenki /* 943*3941Svenki * If the mib data has changed, we need to rebuild the physical-platform 944*3941Svenki * subtree. To do this, we set a flag to mark the tree stale, 945*3941Svenki * so that any future reads to get value of volatile properties will 946*3941Svenki * return PICL_PROPVALUNAVAILABLE, until the stale_tree flag 947*3941Svenki * is reset by the tree builder thread. 948*3941Svenki */ 949*3941Svenki stale_tree = B_TRUE; 950*3941Svenki if (vol_props) { 951*3941Svenki free(vol_props); 952*3941Svenki } 953*3941Svenki vol_props = NULL; 954*3941Svenki volprop_ndx = 0; 955*3941Svenki n_vol_props = 0; 956*3941Svenki 957*3941Svenki (void) rw_unlock(&stale_tree_rwlp); 958*3941Svenki 959*3941Svenki (void) mutex_lock(&rebuild_tree_lock); 960*3941Svenki rebuild_tree = B_TRUE; 961*3941Svenki (void) cond_signal(&rebuild_tree_cv); 962*3941Svenki LOGPRINTF("check_for_stale_data: signalled tree builder\n"); 963*3941Svenki (void) mutex_unlock(&rebuild_tree_lock); 964*3941Svenki } 965*3941Svenki 966*3941Svenki /* 967*3941Svenki * This is the critical routine. This callback is invoked by picl whenever 968*3941Svenki * it needs to fetch the value of a volatile property. The first thing we 969*3941Svenki * must do, however, is to see if there has been a hotplug or a link-reset 970*3941Svenki * event since the last time we built the tree and whether we need to 971*3941Svenki * rebuild the tree. If so, we do whatever is necessary to make that happen, 972*3941Svenki * but return PICL_PROPVALUNAVAILABLE for now, without making any further 973*3941Svenki * snmp requests or accessing any globals. 974*3941Svenki */ 975*3941Svenki static int 976*3941Svenki read_volprop(ptree_rarg_t *parg, void *buf) 977*3941Svenki { 978*3941Svenki char *pstr; 979*3941Svenki int propval; 980*3941Svenki int i, ndx; 981*3941Svenki int ret; 982*3941Svenki int snmp_syserr = 0; 983*3941Svenki 984*3941Svenki /* 985*3941Svenki * First check for any event that would make us throw away 986*3941Svenki * the existing /physical-platform subtree and rebuild 987*3941Svenki * another one. If we are rebuilding the subtree, we just 988*3941Svenki * return the stale value until the tree is fully built. 989*3941Svenki */ 990*3941Svenki check_for_stale_data(); 991*3941Svenki 992*3941Svenki (void) rw_rdlock(&stale_tree_rwlp); 993*3941Svenki 994*3941Svenki if (stale_tree == B_TRUE) { 995*3941Svenki (void) rw_unlock(&stale_tree_rwlp); 996*3941Svenki return (PICL_PROPVALUNAVAILABLE); 997*3941Svenki } 998*3941Svenki 999*3941Svenki for (i = 0; i < volprop_ndx; i++) { 1000*3941Svenki if (vol_props[i].prop == parg->proph) { 1001*3941Svenki ndx = i; 1002*3941Svenki break; 1003*3941Svenki } 1004*3941Svenki } 1005*3941Svenki if (i == volprop_ndx) { 1006*3941Svenki log_msg(LOG_ERR, SNMPP_CANT_FIND_VOLPROP, parg->proph); 1007*3941Svenki return (PICL_FAILURE); 1008*3941Svenki } 1009*3941Svenki 1010*3941Svenki /* 1011*3941Svenki * If we can't read the value, return failure. Even if this was 1012*3941Svenki * due to a link reset, between the check for stale data and now, 1013*3941Svenki * the next volatile callback by picl will initiate a tree-rebuild. 1014*3941Svenki */ 1015*3941Svenki ret = snmp_get_int(hdl, vol_props[ndx].oidstr, vol_props[ndx].row, 1016*3941Svenki &propval, &snmp_syserr); 1017*3941Svenki if (ret < 0) { 1018*3941Svenki log_msg(LOG_ERR, SNMPP_CANT_FETCH_OBJECT_VAL, ret); 1019*3941Svenki return (PICL_FAILURE); 1020*3941Svenki } 1021*3941Svenki 1022*3941Svenki switch (vol_props[ndx].proptype) { 1023*3941Svenki case VPT_PLATOPSTATE: 1024*3941Svenki if (propval == SSOS_DISABLED) { 1025*3941Svenki (void) strlcpy(buf, STR_SSOS_DISABLED, MAX_OPSTATE_LEN); 1026*3941Svenki } else if (propval == SSOS_ENABLED) { 1027*3941Svenki (void) strlcpy(buf, STR_SSOS_ENABLED, MAX_OPSTATE_LEN); 1028*3941Svenki } else { 1029*3941Svenki log_msg(LOG_ERR, SNMPP_INV_PLAT_EQUIP_OPSTATE, 1030*3941Svenki propval, vol_props[ndx].row); 1031*3941Svenki return (PICL_FAILURE); 1032*3941Svenki } 1033*3941Svenki break; 1034*3941Svenki 1035*3941Svenki case VPT_NUMSENSOR: 1036*3941Svenki (void) memcpy(buf, &propval, sizeof (propval)); 1037*3941Svenki break; 1038*3941Svenki 1039*3941Svenki case VPT_BINSENSOR: 1040*3941Svenki if (propval == ST_TRUE) { 1041*3941Svenki ret = snmp_get_str(hdl, 1042*3941Svenki OID_sunPlatBinarySensorInterpretTrue, 1043*3941Svenki vol_props[ndx].row, &pstr, &snmp_syserr); 1044*3941Svenki if (snmp_syserr == ECANCELED) 1045*3941Svenki return (PICL_FAILURE); 1046*3941Svenki if (ret < 0 || pstr == NULL) { 1047*3941Svenki (void) strlcpy(buf, STR_ST_TRUE, 1048*3941Svenki MAX_TRUTHVAL_LEN); 1049*3941Svenki } else { 1050*3941Svenki (void) strlcpy(buf, pstr, MAX_TRUTHVAL_LEN); 1051*3941Svenki free(pstr); 1052*3941Svenki } 1053*3941Svenki } else if (propval == ST_FALSE) { 1054*3941Svenki ret = snmp_get_str(hdl, 1055*3941Svenki OID_sunPlatBinarySensorInterpretFalse, 1056*3941Svenki vol_props[ndx].row, &pstr, &snmp_syserr); 1057*3941Svenki if (snmp_syserr == ECANCELED) 1058*3941Svenki return (PICL_FAILURE); 1059*3941Svenki if (ret < 0 || pstr == NULL) { 1060*3941Svenki (void) strlcpy(buf, STR_ST_FALSE, 1061*3941Svenki MAX_TRUTHVAL_LEN); 1062*3941Svenki } else { 1063*3941Svenki (void) strlcpy(buf, pstr, MAX_TRUTHVAL_LEN); 1064*3941Svenki free(pstr); 1065*3941Svenki } 1066*3941Svenki } else { 1067*3941Svenki log_msg(LOG_ERR, SNMPP_INV_PLAT_BINSNSR_CURRENT, 1068*3941Svenki propval, vol_props[ndx].row); 1069*3941Svenki return (PICL_FAILURE); 1070*3941Svenki } 1071*3941Svenki break; 1072*3941Svenki 1073*3941Svenki case VPT_ALARMSTATE: 1074*3941Svenki if (propval == SSAS_OFF) { 1075*3941Svenki (void) strlcpy(buf, STR_SSAS_OFF, MAX_ALARMSTATE_LEN); 1076*3941Svenki } else if (propval == SSAS_STEADY) { 1077*3941Svenki (void) strlcpy(buf, STR_SSAS_STEADY, 1078*3941Svenki MAX_ALARMSTATE_LEN); 1079*3941Svenki } else if (propval == SSAS_ALTERNATING) { 1080*3941Svenki (void) strlcpy(buf, STR_SSAS_ALTERNATING, 1081*3941Svenki MAX_ALARMSTATE_LEN); 1082*3941Svenki } else { 1083*3941Svenki (void) strlcpy(buf, STR_SSAS_UNKNOWN, 1084*3941Svenki MAX_ALARMSTATE_LEN); 1085*3941Svenki } 1086*3941Svenki break; 1087*3941Svenki 1088*3941Svenki case VPT_BATTERYSTATUS: 1089*3941Svenki switch (propval) { 1090*3941Svenki case SSBS_OTHER: 1091*3941Svenki (void) strlcpy(buf, STR_SSBS_OTHER, 1092*3941Svenki MAX_BATTERYSTATUS_LEN); 1093*3941Svenki break; 1094*3941Svenki case SSBS_FULLYCHARGED: 1095*3941Svenki (void) strlcpy(buf, STR_SSBS_FULLYCHARGED, 1096*3941Svenki MAX_BATTERYSTATUS_LEN); 1097*3941Svenki break; 1098*3941Svenki case SSBS_LOW: 1099*3941Svenki (void) strlcpy(buf, STR_SSBS_LOW, 1100*3941Svenki MAX_BATTERYSTATUS_LEN); 1101*3941Svenki break; 1102*3941Svenki case SSBS_CRITICAL: 1103*3941Svenki (void) strlcpy(buf, STR_SSBS_CRITICAL, 1104*3941Svenki MAX_BATTERYSTATUS_LEN); 1105*3941Svenki break; 1106*3941Svenki case SSBS_CHARGING: 1107*3941Svenki (void) strlcpy(buf, STR_SSBS_CHARGING, 1108*3941Svenki MAX_BATTERYSTATUS_LEN); 1109*3941Svenki break; 1110*3941Svenki case SSBS_CHARGING_AND_LOW: 1111*3941Svenki (void) strlcpy(buf, STR_SSBS_CHARGING_AND_LOW, 1112*3941Svenki MAX_BATTERYSTATUS_LEN); 1113*3941Svenki break; 1114*3941Svenki case SSBS_CHARGING_AND_HIGH: 1115*3941Svenki (void) strlcpy(buf, STR_SSBS_CHARGING_AND_HIGH, 1116*3941Svenki MAX_BATTERYSTATUS_LEN); 1117*3941Svenki break; 1118*3941Svenki case SSBS_CHARGING_AND_CRITICAL: 1119*3941Svenki (void) strlcpy(buf, STR_SSBS_CHARGING_AND_CRITICAL, 1120*3941Svenki MAX_BATTERYSTATUS_LEN); 1121*3941Svenki break; 1122*3941Svenki case SSBS_UNDEFINED: 1123*3941Svenki (void) strlcpy(buf, STR_SSBS_UNDEFINED, 1124*3941Svenki MAX_BATTERYSTATUS_LEN); 1125*3941Svenki break; 1126*3941Svenki case SSBS_PARTIALLY_CHARGED: 1127*3941Svenki (void) strlcpy(buf, STR_SSBS_PARTIALLY_CHARGED, 1128*3941Svenki MAX_BATTERYSTATUS_LEN); 1129*3941Svenki break; 1130*3941Svenki case SSBS_UNKNOWN: 1131*3941Svenki default: 1132*3941Svenki (void) strlcpy(buf, STR_SSBS_UNKNOWN, 1133*3941Svenki MAX_BATTERYSTATUS_LEN); 1134*3941Svenki break; 1135*3941Svenki } 1136*3941Svenki break; 1137*3941Svenki } 1138*3941Svenki 1139*3941Svenki (void) rw_unlock(&stale_tree_rwlp); 1140*3941Svenki 1141*3941Svenki return (PICL_SUCCESS); 1142*3941Svenki } 1143*3941Svenki 1144*3941Svenki static void 1145*3941Svenki threshold(picl_nodehdl_t node, char *oidstr, int row, char *propname, 1146*3941Svenki int *snmp_syserr_p) 1147*3941Svenki { 1148*3941Svenki picl_prophdl_t prop; 1149*3941Svenki int err; 1150*3941Svenki int val; 1151*3941Svenki 1152*3941Svenki if (snmp_get_int(hdl, oidstr, row, &val, snmp_syserr_p) != -1) { 1153*3941Svenki err = add_volatile_prop(node, propname, PICL_PTYPE_INT, 1154*3941Svenki PICL_READ, sizeof (int), read_volprop, NULL, &prop); 1155*3941Svenki if (err == PICL_SUCCESS) 1156*3941Svenki save_volprop(prop, oidstr, row, VPT_NUMSENSOR); 1157*3941Svenki } 1158*3941Svenki } 1159*3941Svenki 1160*3941Svenki static void 1161*3941Svenki add_thresholds(picl_nodehdl_t node, int row, int *snmp_syserr_p) 1162*3941Svenki { 1163*3941Svenki uchar_t *bitstr = NULL; 1164*3941Svenki uchar_t enabled; 1165*3941Svenki uint_t nbytes; 1166*3941Svenki int ret; 1167*3941Svenki 1168*3941Svenki ret = snmp_get_bitstr(hdl, OID_sunPlatNumericSensorEnabledThresholds, 1169*3941Svenki row, &bitstr, &nbytes, snmp_syserr_p); 1170*3941Svenki CHECK_LINKRESET_VOID(snmp_syserr_p) 1171*3941Svenki 1172*3941Svenki if (ret < 0 || bitstr == NULL || nbytes > 2) 1173*3941Svenki enabled = 0xff; 1174*3941Svenki else if (nbytes == 1) { 1175*3941Svenki /* 1176*3941Svenki * The ALOM snmp agent doesn't adhere to the BER rules for 1177*3941Svenki * encoding bit strings. While the BER states that bitstrings 1178*3941Svenki * must begin from the second octet after length, and the 1179*3941Svenki * first octet after length must indicate the number of unused 1180*3941Svenki * bits in the last octet, the snmp agent simply sends the 1181*3941Svenki * bitstring data as if it were octet string -- that is, the 1182*3941Svenki * "unused bits" octet is missing. 1183*3941Svenki */ 1184*3941Svenki enabled = bitstr[0]; 1185*3941Svenki } else if (nbytes == 2) 1186*3941Svenki enabled = bitstr[1]; 1187*3941Svenki 1188*3941Svenki if (bitstr) { 1189*3941Svenki free(bitstr); 1190*3941Svenki } 1191*3941Svenki 1192*3941Svenki if (enabled & LOWER_FATAL) { 1193*3941Svenki threshold(node, 1194*3941Svenki OID_sunPlatNumericSensorLowerThresholdFatal, row, 1195*3941Svenki PICL_PROP_LOW_POWER_OFF, snmp_syserr_p); 1196*3941Svenki CHECK_LINKRESET_VOID(snmp_syserr_p) 1197*3941Svenki } 1198*3941Svenki if (enabled & LOWER_CRITICAL) { 1199*3941Svenki threshold(node, 1200*3941Svenki OID_sunPlatNumericSensorLowerThresholdCritical, row, 1201*3941Svenki PICL_PROP_LOW_SHUTDOWN, snmp_syserr_p); 1202*3941Svenki CHECK_LINKRESET_VOID(snmp_syserr_p) 1203*3941Svenki } 1204*3941Svenki if (enabled & LOWER_NON_CRITICAL) { 1205*3941Svenki threshold(node, 1206*3941Svenki OID_sunPlatNumericSensorLowerThresholdNonCritical, row, 1207*3941Svenki PICL_PROP_LOW_WARNING, snmp_syserr_p); 1208*3941Svenki CHECK_LINKRESET_VOID(snmp_syserr_p) 1209*3941Svenki } 1210*3941Svenki if (enabled & UPPER_NON_CRITICAL) { 1211*3941Svenki threshold(node, 1212*3941Svenki OID_sunPlatNumericSensorUpperThresholdNonCritical, row, 1213*3941Svenki PICL_PROP_HIGH_POWER_OFF, snmp_syserr_p); 1214*3941Svenki CHECK_LINKRESET_VOID(snmp_syserr_p) 1215*3941Svenki } 1216*3941Svenki if (enabled & UPPER_CRITICAL) { 1217*3941Svenki threshold(node, 1218*3941Svenki OID_sunPlatNumericSensorUpperThresholdCritical, row, 1219*3941Svenki PICL_PROP_HIGH_SHUTDOWN, snmp_syserr_p); 1220*3941Svenki CHECK_LINKRESET_VOID(snmp_syserr_p) 1221*3941Svenki } 1222*3941Svenki if (enabled & UPPER_FATAL) { 1223*3941Svenki threshold(node, 1224*3941Svenki OID_sunPlatNumericSensorUpperThresholdFatal, row, 1225*3941Svenki PICL_PROP_HIGH_WARNING, snmp_syserr_p); 1226*3941Svenki CHECK_LINKRESET_VOID(snmp_syserr_p) 1227*3941Svenki } 1228*3941Svenki } 1229*3941Svenki 1230*3941Svenki static char * 1231*3941Svenki get_slot_type(int row, int *snmp_syserr_p) 1232*3941Svenki { 1233*3941Svenki char *p; 1234*3941Svenki char *slott = NULL; 1235*3941Svenki int ret; 1236*3941Svenki 1237*3941Svenki ret = snmp_get_str(hdl, OID_sunPlatEquipmentHolderAcceptableTypes, 1238*3941Svenki row, &p, snmp_syserr_p); 1239*3941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 1240*3941Svenki 1241*3941Svenki if ((ret == 0) && p && *p) { 1242*3941Svenki slott = p; 1243*3941Svenki if ((p = strchr(slott, '\n')) != NULL) 1244*3941Svenki *p = 0; 1245*3941Svenki } else { 1246*3941Svenki log_msg(LOG_WARNING, SNMPP_NO_SLOT_TYPE, row); 1247*3941Svenki if (p) { 1248*3941Svenki free(p); 1249*3941Svenki } 1250*3941Svenki } 1251*3941Svenki 1252*3941Svenki return (slott); 1253*3941Svenki } 1254*3941Svenki 1255*3941Svenki /* 1256*3941Svenki * Create and add the specified volatile property 1257*3941Svenki */ 1258*3941Svenki static int 1259*3941Svenki add_volatile_prop(picl_nodehdl_t node, char *name, int type, int access, 1260*3941Svenki int size, int (*rdfunc)(ptree_rarg_t *, void *), 1261*3941Svenki int (*wrfunc)(ptree_warg_t *, const void *), picl_prophdl_t *propp) 1262*3941Svenki { 1263*3941Svenki ptree_propinfo_t propinfo; 1264*3941Svenki picl_prophdl_t prop; 1265*3941Svenki int err; 1266*3941Svenki 1267*3941Svenki err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 1268*3941Svenki type, (access|PICL_VOLATILE), size, name, rdfunc, wrfunc); 1269*3941Svenki if (err != PICL_SUCCESS) { 1270*3941Svenki log_msg(LOG_ERR, SNMPP_CANT_INIT_PROPINFO, err); 1271*3941Svenki return (err); 1272*3941Svenki } 1273*3941Svenki 1274*3941Svenki err = ptree_create_and_add_prop(node, &propinfo, NULL, &prop); 1275*3941Svenki if (err != PICL_SUCCESS) { 1276*3941Svenki log_msg(LOG_ERR, SNMPP_CANT_ADD_PROP, err, node); 1277*3941Svenki return (err); 1278*3941Svenki } 1279*3941Svenki 1280*3941Svenki if (propp) 1281*3941Svenki *propp = prop; 1282*3941Svenki 1283*3941Svenki return (PICL_SUCCESS); 1284*3941Svenki } 1285*3941Svenki 1286*3941Svenki /* 1287*3941Svenki * Add the specified string property to the node 1288*3941Svenki */ 1289*3941Svenki static int 1290*3941Svenki add_string_prop(picl_nodehdl_t node, char *propname, char *propval) 1291*3941Svenki { 1292*3941Svenki ptree_propinfo_t propinfo; 1293*3941Svenki int err; 1294*3941Svenki 1295*3941Svenki err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 1296*3941Svenki PICL_PTYPE_CHARSTRING, PICL_READ, strlen(propval) + 1, 1297*3941Svenki propname, NULL, NULL); 1298*3941Svenki if (err != PICL_SUCCESS) { 1299*3941Svenki log_msg(LOG_ERR, SNMPP_CANT_INIT_STR_PROPINFO, err); 1300*3941Svenki return (err); 1301*3941Svenki } 1302*3941Svenki 1303*3941Svenki err = ptree_create_and_add_prop(node, &propinfo, propval, NULL); 1304*3941Svenki if (err != PICL_SUCCESS) { 1305*3941Svenki log_msg(LOG_ERR, SNMPP_CANT_ADD_STR_PROP, err, node); 1306*3941Svenki return (err); 1307*3941Svenki } 1308*3941Svenki 1309*3941Svenki return (PICL_SUCCESS); 1310*3941Svenki } 1311*3941Svenki 1312*3941Svenki /* 1313*3941Svenki * Add the specified void property to the node 1314*3941Svenki */ 1315*3941Svenki static int 1316*3941Svenki add_void_prop(picl_nodehdl_t node, char *propname) 1317*3941Svenki { 1318*3941Svenki ptree_propinfo_t propinfo; 1319*3941Svenki int err; 1320*3941Svenki 1321*3941Svenki err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 1322*3941Svenki PICL_PTYPE_VOID, PICL_READ, 0, propname, NULL, NULL); 1323*3941Svenki if (err != PICL_SUCCESS) { 1324*3941Svenki log_msg(LOG_ERR, SNMPP_CANT_INIT_VOID_PROPINFO, err); 1325*3941Svenki return (err); 1326*3941Svenki } 1327*3941Svenki 1328*3941Svenki err = ptree_create_and_add_prop(node, &propinfo, NULL, NULL); 1329*3941Svenki if (err != PICL_SUCCESS) { 1330*3941Svenki log_msg(LOG_ERR, SNMPP_CANT_ADD_VOID_PROP, err, node); 1331*3941Svenki return (err); 1332*3941Svenki } 1333*3941Svenki 1334*3941Svenki return (PICL_SUCCESS); 1335*3941Svenki } 1336*3941Svenki 1337*3941Svenki static int 1338*3941Svenki add_int_prop(picl_nodehdl_t node, char *propname, int val) 1339*3941Svenki { 1340*3941Svenki ptree_propinfo_t propinfo; 1341*3941Svenki int propval = val; 1342*3941Svenki int err; 1343*3941Svenki 1344*3941Svenki err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 1345*3941Svenki PICL_PTYPE_INT, PICL_READ, sizeof (int), 1346*3941Svenki propname, NULL, NULL); 1347*3941Svenki if (err != PICL_SUCCESS) { 1348*3941Svenki log_msg(LOG_ERR, SNMPP_CANT_INIT_INT_PROPINFO, err); 1349*3941Svenki return (err); 1350*3941Svenki } 1351*3941Svenki 1352*3941Svenki err = ptree_create_and_add_prop(node, &propinfo, &propval, NULL); 1353*3941Svenki if (err != PICL_SUCCESS) { 1354*3941Svenki log_msg(LOG_ERR, SNMPP_CANT_ADD_INT_PROP, err, node); 1355*3941Svenki return (err); 1356*3941Svenki } 1357*3941Svenki 1358*3941Svenki return (PICL_SUCCESS); 1359*3941Svenki } 1360*3941Svenki 1361*3941Svenki static void 1362*3941Svenki add_prop(picl_nodehdl_t nodeh, picl_prophdl_t *php, char *label, 1363*3941Svenki int row, sp_propid_t pp, int *snmp_syserr_p) 1364*3941Svenki { 1365*3941Svenki char *serial_num; 1366*3941Svenki char *slot_type; 1367*3941Svenki char *fw_revision, *hw_revision; 1368*3941Svenki char *mfg_name, *model_name; 1369*3941Svenki char *phys_descr; 1370*3941Svenki int val; 1371*3941Svenki int ret; 1372*3941Svenki 1373*3941Svenki switch (pp) { 1374*3941Svenki case PP_SERIAL_NUM: 1375*3941Svenki ret = snmp_get_str(hdl, OID_entPhysicalSerialNum, 1376*3941Svenki row, &serial_num, snmp_syserr_p); 1377*3941Svenki CHECK_LINKRESET_VOID(snmp_syserr_p) 1378*3941Svenki if ((ret == 0) && serial_num && *serial_num) { 1379*3941Svenki (void) add_string_prop(nodeh, 1380*3941Svenki PICL_PROP_SERIAL_NUMBER, serial_num); 1381*3941Svenki free((void *) serial_num); 1382*3941Svenki } 1383*3941Svenki break; 1384*3941Svenki 1385*3941Svenki case PP_SLOT_TYPE: 1386*3941Svenki if ((slot_type = get_slot_type(row, snmp_syserr_p)) == NULL) { 1387*3941Svenki CHECK_LINKRESET_VOID(snmp_syserr_p) 1388*3941Svenki (void) add_string_prop(nodeh, 1389*3941Svenki PICL_PROP_SLOT_TYPE, DEFAULT_SLOT_TYPE); 1390*3941Svenki } else { 1391*3941Svenki (void) add_string_prop(nodeh, 1392*3941Svenki PICL_PROP_SLOT_TYPE, slot_type); 1393*3941Svenki free((void *) slot_type); 1394*3941Svenki } 1395*3941Svenki break; 1396*3941Svenki 1397*3941Svenki case PP_STATE: 1398*3941Svenki ret = add_volatile_prop(nodeh, PICL_PROP_STATE, 1399*3941Svenki PICL_PTYPE_CHARSTRING, PICL_READ, MAX_ALARMSTATE_LEN, 1400*3941Svenki read_volprop, NULL, php); 1401*3941Svenki if (ret == PICL_SUCCESS) { 1402*3941Svenki save_volprop(*php, OID_sunPlatAlarmState, row, 1403*3941Svenki VPT_ALARMSTATE); 1404*3941Svenki } 1405*3941Svenki break; 1406*3941Svenki 1407*3941Svenki case PP_OPSTATUS: 1408*3941Svenki ret = add_volatile_prop(nodeh, PICL_PROP_OPERATIONAL_STATUS, 1409*3941Svenki PICL_PTYPE_CHARSTRING, PICL_READ, MAX_OPSTATE_LEN, 1410*3941Svenki read_volprop, NULL, php); 1411*3941Svenki if (ret == PICL_SUCCESS) { 1412*3941Svenki save_volprop(*php, 1413*3941Svenki OID_sunPlatEquipmentOperationalState, row, 1414*3941Svenki VPT_PLATOPSTATE); 1415*3941Svenki } 1416*3941Svenki break; 1417*3941Svenki 1418*3941Svenki case PP_BATT_STATUS: 1419*3941Svenki ret = add_volatile_prop(nodeh, PICL_PROP_BATTERY_STATUS, 1420*3941Svenki PICL_PTYPE_CHARSTRING, PICL_READ, MAX_BATTERYSTATUS_LEN, 1421*3941Svenki read_volprop, NULL, php); 1422*3941Svenki if (ret == PICL_SUCCESS) { 1423*3941Svenki save_volprop(*php, OID_sunPlatBatteryStatus, row, 1424*3941Svenki VPT_BATTERYSTATUS); 1425*3941Svenki } 1426*3941Svenki break; 1427*3941Svenki 1428*3941Svenki case PP_TEMPERATURE: 1429*3941Svenki ret = add_volatile_prop(nodeh, PICL_PROP_TEMPERATURE, 1430*3941Svenki PICL_PTYPE_INT, PICL_READ, sizeof (int), read_volprop, 1431*3941Svenki NULL, php); 1432*3941Svenki if (ret == PICL_SUCCESS) { 1433*3941Svenki save_volprop(*php, OID_sunPlatNumericSensorCurrent, 1434*3941Svenki row, VPT_NUMSENSOR); 1435*3941Svenki } 1436*3941Svenki break; 1437*3941Svenki 1438*3941Svenki case PP_VOLTAGE: 1439*3941Svenki ret = add_volatile_prop(nodeh, PICL_PROP_VOLTAGE, 1440*3941Svenki PICL_PTYPE_INT, PICL_READ, sizeof (int), read_volprop, 1441*3941Svenki NULL, php); 1442*3941Svenki if (ret == PICL_SUCCESS) { 1443*3941Svenki save_volprop(*php, OID_sunPlatNumericSensorCurrent, 1444*3941Svenki row, VPT_NUMSENSOR); 1445*3941Svenki } 1446*3941Svenki break; 1447*3941Svenki 1448*3941Svenki case PP_CURRENT: 1449*3941Svenki ret = add_volatile_prop(nodeh, PICL_PROP_CURRENT, 1450*3941Svenki PICL_PTYPE_INT, PICL_READ, sizeof (int), read_volprop, 1451*3941Svenki NULL, php); 1452*3941Svenki if (ret == PICL_SUCCESS) { 1453*3941Svenki save_volprop(*php, OID_sunPlatNumericSensorCurrent, 1454*3941Svenki row, VPT_NUMSENSOR); 1455*3941Svenki } 1456*3941Svenki break; 1457*3941Svenki 1458*3941Svenki case PP_SPEED: 1459*3941Svenki ret = add_volatile_prop(nodeh, PICL_PROP_SPEED, PICL_PTYPE_INT, 1460*3941Svenki PICL_READ, sizeof (int), read_volprop, NULL, php); 1461*3941Svenki if (ret == PICL_SUCCESS) { 1462*3941Svenki save_volprop(*php, OID_sunPlatNumericSensorCurrent, 1463*3941Svenki row, VPT_NUMSENSOR); 1464*3941Svenki } 1465*3941Svenki break; 1466*3941Svenki 1467*3941Svenki case PP_SENSOR_VALUE: 1468*3941Svenki ret = add_volatile_prop(nodeh, PICL_PROP_SENSOR_VALUE, 1469*3941Svenki PICL_PTYPE_INT, PICL_READ, sizeof (int), read_volprop, 1470*3941Svenki NULL, php); 1471*3941Svenki if (ret == PICL_SUCCESS) { 1472*3941Svenki save_volprop(*php, OID_sunPlatNumericSensorCurrent, 1473*3941Svenki row, VPT_NUMSENSOR); 1474*3941Svenki } 1475*3941Svenki break; 1476*3941Svenki 1477*3941Svenki case PP_CONDITION: 1478*3941Svenki ret = add_volatile_prop(nodeh, PICL_PROP_CONDITION, 1479*3941Svenki PICL_PTYPE_CHARSTRING, PICL_READ, MAX_TRUTHVAL_LEN, 1480*3941Svenki read_volprop, NULL, php); 1481*3941Svenki if (ret == PICL_SUCCESS) { 1482*3941Svenki save_volprop(*php, OID_sunPlatBinarySensorCurrent, 1483*3941Svenki row, VPT_BINSENSOR); 1484*3941Svenki } 1485*3941Svenki break; 1486*3941Svenki 1487*3941Svenki case PP_EXPECTED: 1488*3941Svenki ret = add_volatile_prop(nodeh, PICL_PROP_EXPECTED, 1489*3941Svenki PICL_PTYPE_CHARSTRING, PICL_READ, MAX_TRUTHVAL_LEN, 1490*3941Svenki read_volprop, NULL, php); 1491*3941Svenki if (ret == PICL_SUCCESS) { 1492*3941Svenki save_volprop(*php, OID_sunPlatBinarySensorExpected, 1493*3941Svenki row, VPT_BINSENSOR); 1494*3941Svenki } 1495*3941Svenki break; 1496*3941Svenki 1497*3941Svenki case PP_REPLACEABLE: 1498*3941Svenki ret = snmp_get_int(hdl, OID_sunPlatCircuitPackReplaceable, 1499*3941Svenki row, &val, snmp_syserr_p); 1500*3941Svenki CHECK_LINKRESET_VOID(snmp_syserr_p) 1501*3941Svenki if ((ret == 0) && (val == ST_TRUE)) 1502*3941Svenki (void) add_void_prop(nodeh, PICL_PROP_IS_REPLACEABLE); 1503*3941Svenki break; 1504*3941Svenki 1505*3941Svenki case PP_HOTSWAPPABLE: 1506*3941Svenki ret = snmp_get_int(hdl, OID_sunPlatCircuitPackHotSwappable, 1507*3941Svenki row, &val, snmp_syserr_p); 1508*3941Svenki CHECK_LINKRESET_VOID(snmp_syserr_p) 1509*3941Svenki if ((ret == 0) && (val == ST_TRUE)) 1510*3941Svenki (void) add_void_prop(nodeh, PICL_PROP_IS_HOT_SWAPPABLE); 1511*3941Svenki break; 1512*3941Svenki 1513*3941Svenki case PP_IS_FRU: 1514*3941Svenki ret = snmp_get_int(hdl, OID_entPhysicalIsFRU, row, 1515*3941Svenki &val, snmp_syserr_p); 1516*3941Svenki CHECK_LINKRESET_VOID(snmp_syserr_p) 1517*3941Svenki if ((ret == 0) && (val == ST_TRUE)) 1518*3941Svenki (void) add_void_prop(nodeh, PICL_PROP_IS_FRU); 1519*3941Svenki break; 1520*3941Svenki 1521*3941Svenki case PP_HW_REVISION: 1522*3941Svenki ret = snmp_get_str(hdl, OID_entPhysicalHardwareRev, 1523*3941Svenki row, &hw_revision, snmp_syserr_p); 1524*3941Svenki CHECK_LINKRESET_VOID(snmp_syserr_p) 1525*3941Svenki if ((ret == 0) && hw_revision && *hw_revision) { 1526*3941Svenki (void) add_string_prop(nodeh, 1527*3941Svenki PICL_PROP_HW_REVISION, hw_revision); 1528*3941Svenki free((void *) hw_revision); 1529*3941Svenki } 1530*3941Svenki break; 1531*3941Svenki 1532*3941Svenki case PP_FW_REVISION: 1533*3941Svenki ret = snmp_get_str(hdl, OID_entPhysicalFirmwareRev, 1534*3941Svenki row, &fw_revision, snmp_syserr_p); 1535*3941Svenki CHECK_LINKRESET_VOID(snmp_syserr_p) 1536*3941Svenki if ((ret == 0) && fw_revision && *fw_revision) { 1537*3941Svenki (void) add_string_prop(nodeh, 1538*3941Svenki PICL_PROP_FW_REVISION, fw_revision); 1539*3941Svenki free((void *) fw_revision); 1540*3941Svenki } 1541*3941Svenki break; 1542*3941Svenki 1543*3941Svenki case PP_MFG_NAME: 1544*3941Svenki ret = snmp_get_str(hdl, OID_entPhysicalMfgName, 1545*3941Svenki row, &mfg_name, snmp_syserr_p); 1546*3941Svenki CHECK_LINKRESET_VOID(snmp_syserr_p) 1547*3941Svenki if ((ret == 0) && mfg_name && *mfg_name) { 1548*3941Svenki (void) add_string_prop(nodeh, 1549*3941Svenki PICL_PROP_MFG_NAME, mfg_name); 1550*3941Svenki free((void *) mfg_name); 1551*3941Svenki } 1552*3941Svenki break; 1553*3941Svenki 1554*3941Svenki case PP_MODEL_NAME: 1555*3941Svenki ret = snmp_get_str(hdl, OID_entPhysicalModelName, 1556*3941Svenki row, &model_name, snmp_syserr_p); 1557*3941Svenki CHECK_LINKRESET_VOID(snmp_syserr_p) 1558*3941Svenki if ((ret == 0) && model_name && *model_name) { 1559*3941Svenki (void) add_string_prop(nodeh, 1560*3941Svenki PICL_PROP_MODEL_NAME, model_name); 1561*3941Svenki free((void *) model_name); 1562*3941Svenki } 1563*3941Svenki break; 1564*3941Svenki 1565*3941Svenki case PP_DESCRIPTION: 1566*3941Svenki ret = snmp_get_str(hdl, OID_entPhysicalDescr, 1567*3941Svenki row, &phys_descr, snmp_syserr_p); 1568*3941Svenki CHECK_LINKRESET_VOID(snmp_syserr_p) 1569*3941Svenki if ((ret == 0) && phys_descr && *phys_descr) { 1570*3941Svenki (void) add_string_prop(nodeh, 1571*3941Svenki PICL_PROP_PHYS_DESCRIPTION, phys_descr); 1572*3941Svenki free((void *) phys_descr); 1573*3941Svenki } 1574*3941Svenki break; 1575*3941Svenki 1576*3941Svenki case PP_LABEL: 1577*3941Svenki if (label && *label) 1578*3941Svenki (void) add_string_prop(nodeh, PICL_PROP_LABEL, label); 1579*3941Svenki break; 1580*3941Svenki 1581*3941Svenki case PP_BASE_UNITS: 1582*3941Svenki ret = snmp_get_int(hdl, OID_sunPlatNumericSensorBaseUnits, 1583*3941Svenki row, &val, snmp_syserr_p); 1584*3941Svenki CHECK_LINKRESET_VOID(snmp_syserr_p) 1585*3941Svenki if ((ret == 0) && (val > 0) && (val < n_baseunits)) { 1586*3941Svenki (void) add_string_prop(nodeh, 1587*3941Svenki PICL_PROP_BASE_UNITS, sensor_baseunits[val]); 1588*3941Svenki } 1589*3941Svenki break; 1590*3941Svenki 1591*3941Svenki case PP_RATE_UNITS: 1592*3941Svenki ret = snmp_get_int(hdl, OID_sunPlatNumericSensorRateUnits, 1593*3941Svenki row, &val, snmp_syserr_p); 1594*3941Svenki CHECK_LINKRESET_VOID(snmp_syserr_p) 1595*3941Svenki if ((ret == 0) && (val > 0) && (val < n_rateunits)) { 1596*3941Svenki (void) add_string_prop(nodeh, 1597*3941Svenki PICL_PROP_RATE_UNITS, sensor_rateunits[val]); 1598*3941Svenki } 1599*3941Svenki break; 1600*3941Svenki 1601*3941Svenki case PP_EXPONENT: 1602*3941Svenki ret = snmp_get_int(hdl, OID_sunPlatNumericSensorExponent, 1603*3941Svenki row, &val, snmp_syserr_p); 1604*3941Svenki CHECK_LINKRESET_VOID(snmp_syserr_p) 1605*3941Svenki if (ret == 0) 1606*3941Svenki (void) add_int_prop(nodeh, PICL_PROP_EXPONENT, val); 1607*3941Svenki break; 1608*3941Svenki } 1609*3941Svenki } 1610*3941Svenki 1611*3941Svenki /*VARARGS2*/ 1612*3941Svenki static void 1613*3941Svenki log_msg(int pri, const char *fmt, ...) 1614*3941Svenki { 1615*3941Svenki va_list ap; 1616*3941Svenki 1617*3941Svenki va_start(ap, fmt); 1618*3941Svenki vsyslog(pri, fmt, ap); 1619*3941Svenki va_end(ap); 1620*3941Svenki } 1621*3941Svenki 1622*3941Svenki #ifdef SNMPPLUGIN_DEBUG 1623*3941Svenki 1624*3941Svenki static void 1625*3941Svenki snmpplugin_log_init(void) 1626*3941Svenki { 1627*3941Svenki (void) mutex_init(&snmpplugin_dbuf_lock, USYNC_THREAD, NULL); 1628*3941Svenki } 1629*3941Svenki 1630*3941Svenki static void 1631*3941Svenki snmpplugin_log(const char *fmt, ...) 1632*3941Svenki { 1633*3941Svenki va_list ap; 1634*3941Svenki 1635*3941Svenki (void) mutex_lock(&snmpplugin_dbuf_lock); 1636*3941Svenki 1637*3941Svenki va_start(ap, fmt); 1638*3941Svenki (void) vsnprintf(snmpplugin_lbuf, SNMPPLUGIN_DMAX_LINE, fmt, ap); 1639*3941Svenki snmpplugin_log_append(); 1640*3941Svenki va_end(ap); 1641*3941Svenki 1642*3941Svenki (void) mutex_unlock(&snmpplugin_dbuf_lock); 1643*3941Svenki } 1644*3941Svenki 1645*3941Svenki static void 1646*3941Svenki snmpplugin_log_append(void) 1647*3941Svenki { 1648*3941Svenki int len; 1649*3941Svenki 1650*3941Svenki len = strlen(snmpplugin_lbuf); 1651*3941Svenki 1652*3941Svenki if ((snmpplugin_dbuf_curp + len) >= 1653*3941Svenki (snmpplugin_dbuf + snmpplugin_dbuf_sz)) { 1654*3941Svenki snmpplugin_dbuf_realloc(); 1655*3941Svenki if (snmpplugin_dbuf == NULL) { 1656*3941Svenki (void) mutex_unlock(&snmpplugin_dbuf_lock); 1657*3941Svenki return; 1658*3941Svenki } 1659*3941Svenki } 1660*3941Svenki 1661*3941Svenki (void) strcpy(snmpplugin_dbuf_curp, snmpplugin_lbuf); 1662*3941Svenki snmpplugin_dbuf_curp += len; 1663*3941Svenki } 1664*3941Svenki 1665*3941Svenki static void 1666*3941Svenki snmpplugin_dbuf_realloc(void) 1667*3941Svenki { 1668*3941Svenki char *p; 1669*3941Svenki size_t offset = 0; 1670*3941Svenki size_t count; 1671*3941Svenki 1672*3941Svenki count = snmpplugin_dbuf_sz + SNMPPLUGIN_DBLOCK_SZ; 1673*3941Svenki if ((p = (char *)calloc(count, 1)) == NULL) { 1674*3941Svenki snmpplugin_dbuf_overflow++; 1675*3941Svenki snmpplugin_dbuf_curp = snmpplugin_dbuf; 1676*3941Svenki return; 1677*3941Svenki } 1678*3941Svenki 1679*3941Svenki if (snmpplugin_dbuf) { 1680*3941Svenki offset = snmpplugin_dbuf_curp - snmpplugin_dbuf; 1681*3941Svenki (void) memcpy(p, snmpplugin_dbuf, snmpplugin_dbuf_sz); 1682*3941Svenki free(snmpplugin_dbuf); 1683*3941Svenki } 1684*3941Svenki 1685*3941Svenki snmpplugin_dbuf = p; 1686*3941Svenki snmpplugin_dbuf_sz += SNMPPLUGIN_DBLOCK_SZ; 1687*3941Svenki 1688*3941Svenki snmpplugin_dbuf_curp = snmpplugin_dbuf + offset; 1689*3941Svenki } 1690*3941Svenki #endif 1691