13941Svenki /* 23941Svenki * CDDL HEADER START 33941Svenki * 43941Svenki * The contents of this file are subject to the terms of the 53941Svenki * Common Development and Distribution License (the "License"). 63941Svenki * You may not use this file except in compliance with the License. 73941Svenki * 83941Svenki * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 93941Svenki * or http://www.opensolaris.org/os/licensing. 103941Svenki * See the License for the specific language governing permissions 113941Svenki * and limitations under the License. 123941Svenki * 133941Svenki * When distributing Covered Code, include this CDDL HEADER in each 143941Svenki * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 153941Svenki * If applicable, add the following below this CDDL HEADER, with the 163941Svenki * fields enclosed by brackets "[]" replaced with your own identifying 173941Svenki * information: Portions Copyright [yyyy] [name of copyright owner] 183941Svenki * 193941Svenki * CDDL HEADER END 203941Svenki */ 213941Svenki 223941Svenki /* 23*5995Sfw157321 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 243941Svenki * Use is subject to license terms. 253941Svenki */ 263941Svenki 273941Svenki #pragma ident "%Z%%M% %I% %E% SMI" 283941Svenki 293941Svenki /* 303941Svenki * The SNMP picl plugin connects to the agent on the SP and creates 313941Svenki * and populates the /physical-platform subtree in picl tree for use 323941Svenki * by picl consumers. 333941Svenki */ 343941Svenki 353941Svenki #include <stdio.h> 363941Svenki #include <stdlib.h> 373941Svenki #include <string.h> 383941Svenki #include <syslog.h> 393941Svenki #include <stdarg.h> 403941Svenki #include <libgen.h> 413941Svenki #include <libintl.h> 423941Svenki #include <thread.h> 433941Svenki #include <synch.h> 443941Svenki #include <errno.h> 453941Svenki 463941Svenki #include <picldefs.h> 473941Svenki #include <picl.h> 483941Svenki #include <picltree.h> 493941Svenki 503941Svenki #include "picloids.h" 513941Svenki #include "libpiclsnmp.h" 523941Svenki #include "snmpplugin.h" 533941Svenki 543941Svenki #pragma init(snmpplugin_register) /* place in .init section */ 553941Svenki 563941Svenki picld_plugin_reg_t snmpplugin_reg = { 573941Svenki PICLD_PLUGIN_VERSION_1, 583941Svenki PICLD_PLUGIN_NON_CRITICAL, 593941Svenki "snmp_plugin", 603941Svenki snmpplugin_init, 613941Svenki snmpplugin_fini 623941Svenki }; 633941Svenki 643941Svenki static picl_snmphdl_t hdl; 653941Svenki 663941Svenki /* 673941Svenki * The stale_tree_rwlp protects the stale_xxx vars. The 'stale_tree' flag 683941Svenki * and the 'rebuild_tree' flag below are both initialized to B_TRUE to 693941Svenki * let the tree_builder() thread build the initial tree without blocking. 703941Svenki */ 713941Svenki static rwlock_t stale_tree_rwlp; 723941Svenki static boolean_t stale_tree = B_TRUE; 733941Svenki 743941Svenki /* 753941Svenki * vol_props, volprop_ndx and n_vol_props are protected by the stale_tree 763941Svenki * flag. They are read only when the stale_tree flag is B_FALSE and written 773941Svenki * to only when the flag is B_TRUE. 783941Svenki * 793941Svenki * The change_time (last changed time) is read by only one thread at a 803941Svenki * time when stale_tree is B_FALSE (protected by stale_tree_rwlp). It is 813941Svenki * written by only one thread (the tree builder) when stale_tree is B_TRUE. 823941Svenki * 833941Svenki * Note that strictly speaking, change_time should be uint_t (timeticks32). 843941Svenki * But keeping it as int is fine, since we don't do any arithmetic on it 853941Svenki * except equality check. 863941Svenki */ 873941Svenki static vol_prophdl_t *vol_props = NULL; 883941Svenki static int volprop_ndx = 0, n_vol_props = 0; 893941Svenki static int change_time = 0; 905723Sfw157321 static time_t change_time_check; 913941Svenki 923941Svenki /* 933941Svenki * The rebuild_tree_lock and cv are used by the tree builder thread. 943941Svenki * rebuild_tree has to be initialized to B_TRUE to let the tree_builder 953941Svenki * do the first build without blocking. 963941Svenki */ 973941Svenki static mutex_t rebuild_tree_lock; 983941Svenki static cond_t rebuild_tree_cv; 993941Svenki static boolean_t rebuild_tree = B_TRUE; 1005029Sfw157321 static boolean_t tree_builder_thr_exit = B_FALSE; 1015029Sfw157321 static thread_t tree_builder_thr_id; 1023941Svenki 1033941Svenki /* 1043941Svenki * These two should really not be global 1053941Svenki */ 1063941Svenki static picl_nodehdl_t *physplat_nodes = NULL; 1073941Svenki static int n_physplat_nodes = 0; 1083941Svenki 1093941Svenki static char *group1[] = { 1103941Svenki OID_entPhysicalDescr, 1113941Svenki OID_entPhysicalContainedIn, 1123941Svenki OID_entPhysicalClass, 1133941Svenki OID_entPhysicalName, 1143941Svenki OID_entPhysicalHardwareRev, 1153941Svenki OID_entPhysicalFirmwareRev, 1163941Svenki OID_entPhysicalSerialNum, 1173941Svenki OID_entPhysicalMfgName, 1183941Svenki OID_entPhysicalModelName, 1193941Svenki OID_entPhysicalIsFRU, 1203941Svenki 0 1213941Svenki }; 1223941Svenki 1233941Svenki static char *group2[] = { 1243941Svenki OID_sunPlatEquipmentHolderAcceptableTypes, 1253941Svenki OID_sunPlatCircuitPackReplaceable, 1263941Svenki OID_sunPlatCircuitPackHotSwappable, 1273941Svenki OID_sunPlatPhysicalClass, 1283941Svenki OID_sunPlatSensorClass, 1293941Svenki OID_sunPlatSensorType, 1303941Svenki OID_sunPlatAlarmType, 1313941Svenki OID_sunPlatPowerSupplyClass, 1323941Svenki 0 1333941Svenki }; 1343941Svenki 1355723Sfw157321 static char *group3[] = { 1365723Sfw157321 OID_sunPlatNumericSensorEnabledThresholds, 1375723Sfw157321 OID_sunPlatNumericSensorBaseUnits, 1385723Sfw157321 OID_sunPlatNumericSensorRateUnits, 1395723Sfw157321 0 1405723Sfw157321 }; 1415723Sfw157321 1425723Sfw157321 static char *group4[] = { 1435723Sfw157321 OID_sunPlatBinarySensorInterpretTrue, 1445723Sfw157321 OID_sunPlatBinarySensorInterpretFalse, 1455723Sfw157321 }; 1465723Sfw157321 1473941Svenki static char *volgroup1[] = { 1483941Svenki OID_sunPlatBinarySensorCurrent, 1493941Svenki OID_sunPlatBinarySensorExpected, 1503941Svenki 0 1513941Svenki }; 1523941Svenki 1533941Svenki static char *volgroup2[] = { 1543941Svenki OID_sunPlatNumericSensorExponent, 1553941Svenki OID_sunPlatNumericSensorCurrent, 1563941Svenki OID_sunPlatNumericSensorLowerThresholdFatal, 1573941Svenki OID_sunPlatNumericSensorLowerThresholdCritical, 1583941Svenki OID_sunPlatNumericSensorLowerThresholdNonCritical, 1593941Svenki OID_sunPlatNumericSensorUpperThresholdNonCritical, 1603941Svenki OID_sunPlatNumericSensorUpperThresholdCritical, 1613941Svenki OID_sunPlatNumericSensorUpperThresholdFatal, 1623941Svenki 0 1633941Svenki }; 1643941Svenki 1655723Sfw157321 static char *volgroup3[] = { 1665723Sfw157321 OID_sunPlatEquipmentOperationalState, 1675723Sfw157321 0 1685723Sfw157321 }; 1695723Sfw157321 1705723Sfw157321 static char *volgroup4[] = { 1715723Sfw157321 OID_sunPlatAlarmState, 1725723Sfw157321 0 1735723Sfw157321 }; 1745723Sfw157321 1755723Sfw157321 static char *volgroup5[] = { 1765723Sfw157321 OID_sunPlatBatteryStatus, 1775723Sfw157321 0 1785723Sfw157321 }; 1795723Sfw157321 1803941Svenki /* 1813941Svenki * The following two items must match the Sun Platform MIB specification 1823941Svenki * in their indices and values. 1833941Svenki */ 1843941Svenki static char *sensor_baseunits[] = { 1853941Svenki "", "other", "unknown", "degC", "degF", "degK", "volts", "amps", 1863941Svenki "watts", "joules", "coulombs", "va", "nits", "lumens", "lux", 1873941Svenki "candelas", "kPa", "psi", "newtons", "cfm", "rpm", "hertz", 1883941Svenki "seconds", "minutes", "hours", "days", "weeks", "mils", "inches", 1893941Svenki "feet", "cubicInches", "cubicFeet", "meters", "cubicCentimeters", 1903941Svenki "cubicMeters", "liters", "fluidOunces", "radians", "steradians", 1913941Svenki "revolutions", "cycles", "gravities", "ounces", "pounds", "footPounds", 1923941Svenki "ounceInches", "gauss", "gilberts", "henries", "farads", "ohms", 1933941Svenki "siemens", "moles", "becquerels", "ppm", "decibels", "dBA", "dbC", 1943941Svenki "grays", "sieverts", "colorTemperatureDegK", "bits", "bytes", "words", 1953941Svenki "doubleWords", "quadWords", "percentage" 1963941Svenki }; 1973941Svenki static const int n_baseunits = sizeof (sensor_baseunits) / sizeof (char *); 1983941Svenki 1993941Svenki static char *sensor_rateunits[] = { 2003941Svenki "", 2013941Svenki "none", 2023941Svenki "perMicroSecond", 2033941Svenki "perMilliSecond", 2043941Svenki "perSecond", 2053941Svenki "perMinute", 2063941Svenki "perHour", 2073941Svenki "perDay", 2083941Svenki "perWeek", 2093941Svenki "perMonth", 2103941Svenki "perYear" 2113941Svenki }; 2123941Svenki static const int n_rateunits = sizeof (sensor_rateunits) / sizeof (char *); 2133941Svenki 2143941Svenki /* 2153941Svenki * Local declarations 2163941Svenki */ 2173941Svenki static void snmpplugin_register(void); 2183941Svenki static void register_group(char **g, int is_volatile); 2193941Svenki static void *tree_builder(void *arg); 2203941Svenki static int build_physplat(picl_nodehdl_t *subtree_rootp); 2213941Svenki static void free_resources(picl_nodehdl_t subtree_root); 2223941Svenki 2233941Svenki static picl_nodehdl_t make_node(picl_nodehdl_t subtree_root, int row, 2243941Svenki int *snmp_syserr_p); 2253941Svenki static void save_nodeh(picl_nodehdl_t nodeh, int row); 2263941Svenki static picl_nodehdl_t lookup_nodeh(int row); 2273941Svenki 2283941Svenki static void save_volprop(picl_prophdl_t prop, char *oidstr, int row, 2293941Svenki int proptype); 2305723Sfw157321 static void check_for_stale_data(boolean_t nocache); 2313941Svenki static int read_volprop(ptree_rarg_t *parg, void *buf); 2323941Svenki 2333941Svenki static void threshold(picl_nodehdl_t node, char *oidstr, int row, 2343941Svenki char *propname, int *snmp_syserr_p); 2353941Svenki static void add_thresholds(picl_nodehdl_t node, int row, int *snmp_syserr_p); 2363941Svenki 2373941Svenki static char *get_slot_type(int row, int *snmp_syserr_p); 2383941Svenki static int add_volatile_prop(picl_nodehdl_t nodeh, char *name, 2393941Svenki int type, int access, int size, int (*rdfunc)(ptree_rarg_t *, void *), 2403941Svenki int (*wrfunc)(ptree_warg_t *, const void *), picl_prophdl_t *propp); 2413941Svenki static int add_string_prop(picl_nodehdl_t node, char *propname, char *propval); 2423941Svenki static int add_void_prop(picl_nodehdl_t node, char *propname); 2433941Svenki static void add_prop(picl_nodehdl_t nodeh, picl_prophdl_t *php, char *label, 2443941Svenki int row, sp_propid_t pp, int *snmp_syserr_p); 2453941Svenki 2463941Svenki static void log_msg(int pri, const char *fmt, ...); 2473941Svenki 2483941Svenki #ifdef SNMPPLUGIN_DEBUG 2493941Svenki static mutex_t snmpplugin_dbuf_lock; 2503941Svenki static char *snmpplugin_dbuf = NULL; 2513941Svenki static char *snmpplugin_dbuf_curp = NULL; 2523941Svenki static int snmpplugin_dbuf_sz = 0; 2533941Svenki static int snmpplugin_dbuf_overflow = 0; 2543941Svenki static char snmpplugin_lbuf[SNMPPLUGIN_DMAX_LINE]; 2553941Svenki 2563941Svenki static void snmpplugin_log_init(void); 2573941Svenki static void snmpplugin_log(const char *fmt, ...); 2583941Svenki static void snmpplugin_log_append(void); 2593941Svenki static void snmpplugin_dbuf_realloc(void); 2603941Svenki #endif 2613941Svenki 2623941Svenki static void 2633941Svenki snmpplugin_register(void) 2643941Svenki { 2653941Svenki (void) picld_plugin_register(&snmpplugin_reg); 2663941Svenki } 2673941Svenki 2683941Svenki static void 2693941Svenki register_group(char **g, int is_volatile) 2703941Svenki { 2713941Svenki int i, len = 0; 2723941Svenki int n_oids; 2733941Svenki char *p, *oidstrs; 2743941Svenki 2753941Svenki for (i = 0; g[i]; i++) 2763941Svenki len += strlen(g[i]) + 1; 2773941Svenki n_oids = i; 2783941Svenki 2793941Svenki if ((oidstrs = (char *)calloc(1, len)) == NULL) 2803941Svenki return; 2813941Svenki 2823941Svenki for (p = oidstrs, i = 0; g[i]; i++) { 2833941Svenki (void) strcpy(p, g[i]); 2843941Svenki p += strlen(g[i]) + 1; 2853941Svenki } 2863941Svenki 2873941Svenki snmp_register_group(hdl, oidstrs, n_oids, is_volatile); 2883941Svenki } 2893941Svenki 2903941Svenki void 2913941Svenki snmpplugin_init(void) 2923941Svenki { 2933941Svenki int ret; 2943941Svenki 2953941Svenki (void) mutex_init(&rebuild_tree_lock, USYNC_THREAD, NULL); 2963941Svenki (void) cond_init(&rebuild_tree_cv, USYNC_THREAD, NULL); 2973941Svenki (void) rwlock_init(&stale_tree_rwlp, USYNC_THREAD, NULL); 2985029Sfw157321 tree_builder_thr_exit = B_FALSE; 2995029Sfw157321 3003941Svenki LOGINIT(); 3013941Svenki 3023941Svenki /* 3033941Svenki * Create the tree-builder thread and let it take over 3043941Svenki */ 3053941Svenki LOGPRINTF("Tree-builder thread being created.\n"); 3063941Svenki if ((ret = thr_create(NULL, NULL, tree_builder, NULL, 3075029Sfw157321 THR_BOUND, &tree_builder_thr_id)) < 0) { 3083941Svenki log_msg(LOG_ERR, SNMPP_CANT_CREATE_TREE_BUILDER, ret); 3093941Svenki snmp_fini(hdl); 3105029Sfw157321 hdl = NULL; 3115029Sfw157321 (void) rwlock_destroy(&stale_tree_rwlp); 3125029Sfw157321 (void) cond_destroy(&rebuild_tree_cv); 3135029Sfw157321 (void) mutex_destroy(&rebuild_tree_lock); 3145029Sfw157321 tree_builder_thr_exit = B_TRUE; 3153941Svenki } 3163941Svenki } 3173941Svenki 3183941Svenki void 3193941Svenki snmpplugin_fini(void) 3203941Svenki { 3215029Sfw157321 3225029Sfw157321 if (tree_builder_thr_exit == B_TRUE) 3235029Sfw157321 return; 3243941Svenki 3255029Sfw157321 /* 3265029Sfw157321 * Make reads of volatile properties return PICL_PROPUNAVAILABLE 3275029Sfw157321 * since we're about to recycle the plug-in. No need to worry 3285029Sfw157321 * about removing /physical-platform since tree_builder() will 3295029Sfw157321 * take care of recycling it for us. 3305029Sfw157321 */ 3315029Sfw157321 (void) rw_wrlock(&stale_tree_rwlp); 3325029Sfw157321 stale_tree = B_TRUE; 3335029Sfw157321 if (vol_props) { 3345029Sfw157321 free(vol_props); 3355029Sfw157321 } 3365029Sfw157321 vol_props = NULL; 3375029Sfw157321 volprop_ndx = 0; 3385029Sfw157321 n_vol_props = 0; 3395029Sfw157321 (void) rw_unlock(&stale_tree_rwlp); 3405029Sfw157321 3415029Sfw157321 /* wake up the tree_builder thread, tell it to exit */ 3425029Sfw157321 (void) mutex_lock(&rebuild_tree_lock); 3435029Sfw157321 rebuild_tree = B_TRUE; 3445029Sfw157321 tree_builder_thr_exit = B_TRUE; 3455436Sfw157321 (void) cond_signal(&rebuild_tree_cv); 3465029Sfw157321 (void) mutex_unlock(&rebuild_tree_lock); 3475029Sfw157321 3485029Sfw157321 /* reap the thread */ 3495029Sfw157321 (void) thr_join(tree_builder_thr_id, NULL, NULL); 3505029Sfw157321 3515029Sfw157321 /* close the channel */ 3525029Sfw157321 if (hdl != NULL) { 3535029Sfw157321 snmp_fini(hdl); 3545029Sfw157321 hdl = NULL; 3555029Sfw157321 } 3565029Sfw157321 3575029Sfw157321 /* finish cleanup... */ 3583941Svenki (void) rwlock_destroy(&stale_tree_rwlp); 3593941Svenki (void) cond_destroy(&rebuild_tree_cv); 3603941Svenki (void) mutex_destroy(&rebuild_tree_lock); 3613941Svenki } 3623941Svenki 3633941Svenki /*ARGSUSED*/ 3643941Svenki static void * 3653941Svenki tree_builder(void *arg) 3663941Svenki { 3673941Svenki int ret, rv; 3683941Svenki picl_nodehdl_t root_node; 3693941Svenki picl_nodehdl_t physplat_root; 3703941Svenki picl_nodehdl_t old_physplat_root; 3713941Svenki 3723941Svenki /* 3733941Svenki * Initialize SNMP service 3743941Svenki */ 3753941Svenki LOGPRINTF("Initializing SNMP service.\n"); 3763941Svenki if ((hdl = snmp_init()) == NULL) { 3773941Svenki log_msg(LOG_ERR, SNMPP_CANT_INIT); 3783941Svenki return ((void *)-1); 3793941Svenki } 3803941Svenki 3813941Svenki /* 3823941Svenki * Register OID groupings for BULKGET optimizations 3833941Svenki */ 3843941Svenki LOGPRINTF("Registering OID groups.\n"); 3853941Svenki register_group(group1, 0); 3863941Svenki register_group(group2, 0); 3875723Sfw157321 register_group(group3, 0); 3885723Sfw157321 register_group(group4, 0); 3893941Svenki register_group(volgroup1, 1); 3903941Svenki register_group(volgroup2, 1); 3915723Sfw157321 register_group(volgroup3, 1); 3925723Sfw157321 register_group(volgroup4, 1); 3935723Sfw157321 register_group(volgroup5, 1); 3943941Svenki 3953941Svenki (void) mutex_lock(&rebuild_tree_lock); 3963941Svenki 3973941Svenki for (;;) { 3983941Svenki LOGPRINTF("tree_builder: check whether to rebuild subtree\n"); 3993941Svenki while (rebuild_tree == B_FALSE) 4003941Svenki (void) cond_wait(&rebuild_tree_cv, &rebuild_tree_lock); 4013941Svenki 4023941Svenki LOGPRINTF("tree_builder: woke up\n"); 4033941Svenki 4045029Sfw157321 if (tree_builder_thr_exit == B_TRUE) { 4055029Sfw157321 (void) mutex_unlock(&rebuild_tree_lock); 4065029Sfw157321 LOGPRINTF("tree_builder: time to exit\n"); 4075029Sfw157321 return (NULL); 4085029Sfw157321 } 4095029Sfw157321 4103941Svenki old_physplat_root = NULL; 4113941Svenki physplat_root = NULL; 4123941Svenki 4133941Svenki LOGPRINTF("tree_builder: getting root node\n"); 4143941Svenki if ((ret = ptree_get_root(&root_node)) != PICL_SUCCESS) { 4155029Sfw157321 (void) mutex_unlock(&rebuild_tree_lock); 4163941Svenki log_msg(LOG_ERR, SNMPP_NO_ROOT, ret); 4173941Svenki return ((void *)-2); 4183941Svenki } 4193941Svenki 4203941Svenki LOGPRINTF("tree_builder: getting existing physplat node\n"); 4213941Svenki rv = ptree_find_node(root_node, PICL_PROP_NAME, 4223941Svenki PICL_PTYPE_CHARSTRING, PICL_NODE_PHYSPLAT, 4233941Svenki sizeof (PICL_NODE_PHYSPLAT), &old_physplat_root); 4243941Svenki 4253941Svenki LOGPRINTF("tree_builder: building physical-platform\n"); 4263941Svenki if ((ret = build_physplat(&physplat_root)) < 0) { 4275029Sfw157321 (void) mutex_unlock(&rebuild_tree_lock); 4283941Svenki log_msg(LOG_ERR, SNMPP_CANT_CREATE_PHYSPLAT, ret); 4293941Svenki snmp_fini(hdl); 4305029Sfw157321 hdl = NULL; 4313941Svenki return ((void *)-3); 4323941Svenki } 4333941Svenki 4343941Svenki if (rv == PICL_SUCCESS && old_physplat_root != NULL) { 4353941Svenki LOGPRINTF("tree_builder: destroying existing nodes\n"); 4363941Svenki ptree_delete_node(old_physplat_root); 4373941Svenki ptree_destroy_node(old_physplat_root); 4383941Svenki } 4393941Svenki 4403941Svenki LOGPRINTF("tree_builder: attaching new subtree\n"); 4413941Svenki if ((ret = ptree_add_node(root_node, physplat_root)) < 0) { 4425029Sfw157321 (void) mutex_unlock(&rebuild_tree_lock); 4433941Svenki free_resources(physplat_root); 4443941Svenki log_msg(LOG_ERR, SNMPP_CANT_CREATE_PHYSPLAT, ret); 4453941Svenki snmp_fini(hdl); 4465029Sfw157321 hdl = NULL; 4473941Svenki return ((void *)-4); 4483941Svenki } 4493941Svenki 4503941Svenki LOGPRINTF("tree_builder: setting stale_tree to FALSE\n"); 4513941Svenki (void) rw_wrlock(&stale_tree_rwlp); 4523941Svenki stale_tree = B_FALSE; 4533941Svenki (void) rw_unlock(&stale_tree_rwlp); 4543941Svenki 4553941Svenki LOGPRINTF("tree_builder: setting rebuild_tree to FALSE\n"); 4563941Svenki rebuild_tree = B_FALSE; 4573941Svenki } 4583941Svenki 4593941Svenki /*NOTREACHED*/ 4603941Svenki return (NULL); 4613941Svenki } 4623941Svenki 4633941Svenki static int 4643941Svenki build_physplat(picl_nodehdl_t *subtree_rootp) 4653941Svenki { 4663941Svenki int change_time1; 4673941Svenki int row, nxtrow; 4683941Svenki int clr_linkreset = 0; 4693941Svenki int ret = 0; 4703941Svenki int snmp_syserr = 0; 4713941Svenki 4723941Svenki retry: 4733941Svenki (void) snmp_reinit(hdl, clr_linkreset); 4743941Svenki clr_linkreset = 0; 4753941Svenki 4763941Svenki /* 4773941Svenki * Record LastChangeTime before we start building the tree 4783941Svenki */ 4793941Svenki ret = snmp_get_int(hdl, OID_entLastChangeTime, 0, 4803941Svenki &change_time1, &snmp_syserr); 4813941Svenki if (ret < 0) { 4823941Svenki if (snmp_syserr == ECANCELED) { 4833941Svenki log_msg(LOG_WARNING, SNMPP_LINK_RESET); 4843941Svenki clr_linkreset = 1; 4853941Svenki goto retry; 4865723Sfw157321 } 4875723Sfw157321 log_msg(LOG_WARNING, SNMPP_CANT_FETCH_OBJECT_VAL, 4885723Sfw157321 snmp_syserr ? snmp_syserr : ret, OID_entLastChangeTime, 0); 4893941Svenki } 4903941Svenki 4913941Svenki /* 4923941Svenki * Create the physical-platform node 4933941Svenki */ 4943941Svenki ret = ptree_create_node(PICL_NODE_PHYSPLAT, PICL_CLASS_PICL, 4953941Svenki subtree_rootp); 4963941Svenki if (ret != PICL_SUCCESS) 4973941Svenki return (-1); 4983941Svenki 4993941Svenki /* 5003941Svenki * Scan entPhysicalTable and build the "physical-platform" subtree 5013941Svenki */ 5023941Svenki ret = 0; 5033941Svenki for (row = -1; ret == 0; row = nxtrow) { 5043941Svenki ret = snmp_get_nextrow(hdl, OID_entPhysicalDescr, 5053941Svenki row, &nxtrow, &snmp_syserr); 506*5995Sfw157321 if (ret == 0) 5073941Svenki (void) make_node(*subtree_rootp, nxtrow, &snmp_syserr); 508*5995Sfw157321 switch (snmp_syserr) { 509*5995Sfw157321 case ECANCELED: 5103941Svenki /* 5113941Svenki * If we get this error, a link reset must've 5123941Svenki * happened and we need to throw away everything 5133941Svenki * we have now and rebuild the tree again. 5143941Svenki */ 5153941Svenki log_msg(LOG_WARNING, SNMPP_LINK_RESET); 5163941Svenki free_resources(*subtree_rootp); 5173941Svenki clr_linkreset = 1; 5183941Svenki goto retry; 519*5995Sfw157321 /*NOTREACHED*/ 520*5995Sfw157321 break; 521*5995Sfw157321 case ENOSPC: /* end of MIB */ 522*5995Sfw157321 LOGPRINTF("build_physplat: end of MIB\n"); 523*5995Sfw157321 break; 524*5995Sfw157321 case ENOENT: /* end of table */ 525*5995Sfw157321 LOGPRINTF("build_physplat: end of table\n"); 526*5995Sfw157321 break; 527*5995Sfw157321 default: 528*5995Sfw157321 /* 529*5995Sfw157321 * make_node() will print messages so don't 530*5995Sfw157321 * repeat that exercise here. 531*5995Sfw157321 */ 532*5995Sfw157321 if (ret == -1) { 533*5995Sfw157321 log_msg(LOG_WARNING, 534*5995Sfw157321 SNMPP_CANT_FETCH_OBJECT_VAL, 535*5995Sfw157321 snmp_syserr ? snmp_syserr : ret, 536*5995Sfw157321 OID_entPhysicalDescr, row); 537*5995Sfw157321 } 5383941Svenki } 5393941Svenki } 5403941Svenki 5413941Svenki /* 5423941Svenki * Record LastChangeTime after we're done building the tree 5433941Svenki */ 5443941Svenki ret = snmp_get_int(hdl, OID_entLastChangeTime, 0, 5453941Svenki &change_time, &snmp_syserr); 5463941Svenki if (ret < 0) { 5473941Svenki if (snmp_syserr == ECANCELED) { 5483941Svenki log_msg(LOG_WARNING, SNMPP_LINK_RESET); 5493941Svenki free_resources(*subtree_rootp); 5503941Svenki clr_linkreset = 1; 5513941Svenki goto retry; 5523941Svenki } else 5535723Sfw157321 log_msg(LOG_WARNING, SNMPP_CANT_FETCH_OBJECT_VAL, 5545723Sfw157321 snmp_syserr ? snmp_syserr : ret, 5555723Sfw157321 OID_entLastChangeTime, row); 5563941Svenki } 5573941Svenki 5583941Svenki /* 5593941Svenki * If they don't match, some hotplugging must've happened, 5603941Svenki * free resources we've created and still holding, then go 5613941Svenki * back and retry 5623941Svenki */ 5633941Svenki if (change_time != change_time1) { 5643941Svenki LOGPRINTF("build_physplat: entLastChangeTime has changed!\n"); 5653941Svenki free_resources(*subtree_rootp); 5663941Svenki change_time1 = change_time; 5673941Svenki goto retry; 5683941Svenki } 5693941Svenki 5703941Svenki /* 5713941Svenki * The physplat_nodes table is no longer needed, free it 5723941Svenki */ 5733941Svenki if (physplat_nodes) { 5743941Svenki free(physplat_nodes); 5753941Svenki physplat_nodes = NULL; 5763941Svenki n_physplat_nodes = 0; 5773941Svenki } 5783941Svenki 5793941Svenki return (0); 5803941Svenki } 5813941Svenki 5823941Svenki /* 5833941Svenki * Destroy all resources that were created during the building 5843941Svenki * of the subtree 5853941Svenki */ 5863941Svenki static void 5873941Svenki free_resources(picl_nodehdl_t subtree_root) 5883941Svenki { 5893941Svenki if (physplat_nodes) { 5903941Svenki free(physplat_nodes); 5913941Svenki physplat_nodes = NULL; 5923941Svenki n_physplat_nodes = 0; 5933941Svenki } 5943941Svenki 5953941Svenki if (subtree_root) { 5963941Svenki (void) ptree_delete_node(subtree_root); 5973941Svenki (void) ptree_destroy_node(subtree_root); 5983941Svenki } 5993941Svenki 6003941Svenki if (vol_props) { 6013941Svenki free(vol_props); 6023941Svenki n_vol_props = 0; 6033941Svenki volprop_ndx = 0; 6043941Svenki } 6053941Svenki } 6063941Svenki 6073941Svenki static picl_nodehdl_t 6083941Svenki make_node(picl_nodehdl_t subtree_root, int row, int *snmp_syserr_p) 6093941Svenki { 6103941Svenki picl_nodehdl_t nodeh, parenth; 6113941Svenki picl_prophdl_t proph; 6123941Svenki char *phys_name, *node_name; 6133941Svenki int parent_row; 6143941Svenki int ent_physclass, sunplat_physclass; 6153941Svenki int sensor_class, sensor_type; 6163941Svenki int alarm_type; 6173941Svenki int ps_class; 6183941Svenki int ret; 6193941Svenki 6203941Svenki /* 6213941Svenki * If we've already created this picl node, just return it 6223941Svenki */ 6233941Svenki if ((nodeh = lookup_nodeh(row)) != NULL) 6243941Svenki return (nodeh); 6253941Svenki 6263941Svenki /* 6273941Svenki * If we are creating it only now, make sure we have the parent 6283941Svenki * created first; if there's no parent, then parent it to the 6293941Svenki * subtree's root node 6303941Svenki */ 6313941Svenki ret = snmp_get_int(hdl, OID_entPhysicalContainedIn, row, 6323941Svenki &parent_row, snmp_syserr_p); 6333941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 6343941Svenki if (ret < 0 || parent_row <= 0) 6353941Svenki parenth = subtree_root; 6363941Svenki else { 6373941Svenki parenth = make_node(subtree_root, parent_row, snmp_syserr_p); 6383941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 6393941Svenki if (parenth == NULL) 6403941Svenki parenth = subtree_root; 6413941Svenki } 6423941Svenki 6433941Svenki /* 6443941Svenki * Figure out the physical-platform node name from entPhysicalName; 6453941Svenki * all rows in the MIB that have a valid entPhysicalIndex should 6463941Svenki * have a physical name. 6473941Svenki */ 6483941Svenki ret = snmp_get_str(hdl, OID_entPhysicalName, row, 6493941Svenki &phys_name, snmp_syserr_p); 6503941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 6513941Svenki if (ret < 0 || phys_name == NULL) { 6523941Svenki log_msg(LOG_WARNING, SNMPP_NO_ENTPHYSNAME, row); 6533941Svenki return (NULL); 6543941Svenki } 6553941Svenki 6563941Svenki node_name = basename(phys_name); 6573941Svenki 6583941Svenki ret = snmp_get_int(hdl, OID_entPhysicalClass, row, 6593941Svenki &ent_physclass, snmp_syserr_p); 6603941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 6613941Svenki if (ret < 0) { 6625723Sfw157321 log_msg(LOG_WARNING, SNMPP_CANT_FETCH_OBJECT_VAL, 6635723Sfw157321 *snmp_syserr_p ? *snmp_syserr_p : ret, 6645723Sfw157321 OID_entPhysicalClass, row); 6653941Svenki free(phys_name); 6663941Svenki return (NULL); 6673941Svenki } 6683941Svenki 6693941Svenki switch (ent_physclass) { 6703941Svenki case SPC_OTHER: 6713941Svenki ret = snmp_get_int(hdl, OID_sunPlatPhysicalClass, row, 6723941Svenki &sunplat_physclass, snmp_syserr_p); 6733941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 6743941Svenki if (ret < 0) { 6755723Sfw157321 log_msg(LOG_WARNING, SNMPP_CANT_FETCH_OBJECT_VAL, 6765723Sfw157321 *snmp_syserr_p ? *snmp_syserr_p : ret, 6775723Sfw157321 OID_sunPlatPhysicalClass, row); 6783941Svenki free(phys_name); 6793941Svenki return (NULL); 6803941Svenki } 6813941Svenki 6823941Svenki if (sunplat_physclass == SSPC_ALARM) { 6833941Svenki ret = snmp_get_int(hdl, OID_sunPlatAlarmType, 6843941Svenki row, &alarm_type, snmp_syserr_p); 6853941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 6863941Svenki if (ret < 0) { 6873941Svenki log_msg(LOG_WARNING, 6885723Sfw157321 SNMPP_CANT_FETCH_OBJECT_VAL, 6895723Sfw157321 *snmp_syserr_p ? *snmp_syserr_p : ret, 6905723Sfw157321 OID_sunPlatAlarmType, row); 6913941Svenki free(phys_name); 6923941Svenki return (NULL); 6933941Svenki } 6943941Svenki 6953941Svenki if (alarm_type == SSAT_VISIBLE) { 6964802Sfw157321 ADD_NODE(PICL_CLASS_LED) 6973941Svenki } else { 6984802Sfw157321 ADD_NODE(PICL_CLASS_ALARM) 6993941Svenki } 7003941Svenki 7013941Svenki add_prop(nodeh, &proph, node_name, row, PP_STATE, 7023941Svenki snmp_syserr_p); 7033941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 7043941Svenki } else { 7053941Svenki ADD_NODE(PICL_CLASS_OTHER) 7063941Svenki } 7073941Svenki 7083941Svenki add_prop(nodeh, &proph, node_name, row, PP_OPSTATUS, 7093941Svenki snmp_syserr_p); 7103941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 7113941Svenki break; 7123941Svenki 7133941Svenki case SPC_UNKNOWN: 7143941Svenki ADD_NODE(PICL_CLASS_UNKNOWN) 7153941Svenki break; 7163941Svenki 7173941Svenki case SPC_CHASSIS: 7183941Svenki ADD_NODE(PICL_CLASS_CHASSIS) 7193941Svenki add_prop(nodeh, &proph, node_name, row, PP_OPSTATUS, 7203941Svenki snmp_syserr_p); 7213941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 7223941Svenki break; 7233941Svenki 7243941Svenki case SPC_BACKPLANE: 7253941Svenki ADD_NODE(PICL_CLASS_BACKPLANE) 7263941Svenki add_prop(nodeh, &proph, node_name, row, PP_OPSTATUS, 7273941Svenki snmp_syserr_p); 7283941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 7293941Svenki break; 7303941Svenki 7313941Svenki case SPC_CONTAINER: 7323941Svenki ADD_NODE(PICL_CLASS_CONTAINER) 7333941Svenki 7343941Svenki add_prop(nodeh, &proph, node_name, row, PP_OPSTATUS, 7353941Svenki snmp_syserr_p); 7363941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 7373941Svenki 7383941Svenki add_prop(nodeh, &proph, node_name, row, PP_SLOT_TYPE, 7393941Svenki snmp_syserr_p); 7403941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 7413941Svenki break; 7423941Svenki 7433941Svenki case SPC_POWERSUPPLY: 7443941Svenki ret = snmp_get_int(hdl, OID_sunPlatPowerSupplyClass, 7453941Svenki row, &ps_class, snmp_syserr_p); 7463941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 7473941Svenki if (ret < 0) { 7485723Sfw157321 log_msg(LOG_WARNING, SNMPP_CANT_FETCH_OBJECT_VAL, 7495723Sfw157321 *snmp_syserr_p ? *snmp_syserr_p : ret, 7505723Sfw157321 OID_sunPlatPowerSupplyClass, row); 7513941Svenki free(phys_name); 7523941Svenki return (NULL); 7533941Svenki } 7543941Svenki 7553941Svenki if (ps_class == SSPSC_BATTERY) { 7563941Svenki ADD_NODE(PICL_CLASS_BATTERY) 7573941Svenki add_prop(nodeh, &proph, node_name, row, 7583941Svenki PP_BATT_STATUS, snmp_syserr_p); 7593941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 7603941Svenki } else { 7613941Svenki ADD_NODE(PICL_CLASS_POWERSUPPLY) 7623941Svenki } 7633941Svenki add_prop(nodeh, &proph, node_name, row, PP_OPSTATUS, 7643941Svenki snmp_syserr_p); 7653941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 7663941Svenki break; 7673941Svenki 7683941Svenki case SPC_FAN: 7693941Svenki ADD_NODE(PICL_CLASS_FAN) 7703941Svenki add_prop(nodeh, &proph, node_name, row, PP_OPSTATUS, 7713941Svenki snmp_syserr_p); 7723941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 7733941Svenki break; 7743941Svenki 7753941Svenki case SPC_SENSOR: 7763941Svenki ret = snmp_get_int(hdl, OID_sunPlatSensorClass, 7773941Svenki row, &sensor_class, snmp_syserr_p); 7783941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 7793941Svenki if (ret < 0) { 7805723Sfw157321 log_msg(LOG_WARNING, SNMPP_CANT_FETCH_OBJECT_VAL, 7815723Sfw157321 *snmp_syserr_p ? *snmp_syserr_p : ret, 7825723Sfw157321 OID_sunPlatSensorClass, row); 7833941Svenki free(phys_name); 7843941Svenki return (NULL); 7853941Svenki } 7863941Svenki 7873941Svenki ret = snmp_get_int(hdl, OID_sunPlatSensorType, 7883941Svenki row, &sensor_type, snmp_syserr_p); 7893941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 7903941Svenki if (ret < 0) { 7915723Sfw157321 log_msg(LOG_WARNING, SNMPP_CANT_FETCH_OBJECT_VAL, 7925723Sfw157321 *snmp_syserr_p ? *snmp_syserr_p : ret, 7935723Sfw157321 OID_sunPlatSensorType, row); 7943941Svenki free(phys_name); 7953941Svenki return (NULL); 7963941Svenki } 7973941Svenki 7983941Svenki if (sensor_class == SSSC_NUMERIC) { 7993941Svenki if (sensor_type == SSST_TEMPERATURE) { 8003941Svenki ADD_NODE(PICL_CLASS_TEMPERATURE_SENSOR) 8013941Svenki add_prop(nodeh, &proph, node_name, row, 8023941Svenki PP_TEMPERATURE, snmp_syserr_p); 8033941Svenki } else if (sensor_type == SSST_VOLTAGE) { 8043941Svenki ADD_NODE(PICL_CLASS_VOLTAGE_SENSOR) 8053941Svenki add_prop(nodeh, &proph, node_name, row, 8063941Svenki PP_VOLTAGE, snmp_syserr_p); 8073941Svenki } else if (sensor_type == SSST_CURRENT) { 8083941Svenki ADD_NODE(PICL_CLASS_CURRENT_SENSOR) 8093941Svenki add_prop(nodeh, &proph, node_name, row, 8103941Svenki PP_CURRENT, snmp_syserr_p); 8113941Svenki } else if (sensor_type == SSST_TACHOMETER) { 8123941Svenki ADD_NODE(PICL_CLASS_RPM_SENSOR) 8133941Svenki add_prop(nodeh, &proph, node_name, row, 8143941Svenki PP_SPEED, snmp_syserr_p); 8153941Svenki } else { 8163941Svenki ADD_NODE(PICL_CLASS_SENSOR) 8173941Svenki add_prop(nodeh, &proph, node_name, row, 8183941Svenki PP_SENSOR_VALUE, snmp_syserr_p); 8193941Svenki } 8203941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 8213941Svenki 8223941Svenki add_prop(nodeh, &proph, node_name, row, 8233941Svenki PP_OPSTATUS, snmp_syserr_p); 8243941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 8253941Svenki 8263941Svenki add_prop(nodeh, &proph, node_name, row, 8273941Svenki PP_BASE_UNITS, snmp_syserr_p); 8283941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 8293941Svenki 8303941Svenki add_prop(nodeh, &proph, node_name, row, 8313941Svenki PP_EXPONENT, snmp_syserr_p); 8323941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 8333941Svenki 8343941Svenki add_prop(nodeh, &proph, node_name, row, 8353941Svenki PP_RATE_UNITS, snmp_syserr_p); 8363941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 8373941Svenki 8383941Svenki add_thresholds(nodeh, row, snmp_syserr_p); 8393941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 8403941Svenki 8413941Svenki } else if (sensor_class == SSSC_BINARY) { 8423941Svenki if (sensor_type == SSST_TEMPERATURE) { 8433941Svenki ADD_NODE(PICL_CLASS_TEMPERATURE_INDICATOR) 8443941Svenki } else if (sensor_type == SSST_VOLTAGE) { 8453941Svenki ADD_NODE(PICL_CLASS_VOLTAGE_INDICATOR) 8463941Svenki } else if (sensor_type == SSST_CURRENT) { 8473941Svenki ADD_NODE(PICL_CLASS_CURRENT_INDICATOR) 8483941Svenki } else if (sensor_type == SSST_TACHOMETER) { 8493941Svenki ADD_NODE(PICL_CLASS_RPM_INDICATOR) 8503941Svenki } else if (sensor_type == SSST_PRESENCE) { 8513941Svenki ADD_NODE(PICL_CLASS_PRESENCE_INDICATOR) 8523941Svenki } else { 8533941Svenki ADD_NODE(PICL_CLASS_INDICATOR) 8543941Svenki } 8553941Svenki 8563941Svenki add_prop(nodeh, &proph, node_name, row, PP_OPSTATUS, 8573941Svenki snmp_syserr_p); 8583941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 8593941Svenki 8603941Svenki add_prop(nodeh, &proph, node_name, row, PP_CONDITION, 8613941Svenki snmp_syserr_p); 8623941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 8633941Svenki 8643941Svenki add_prop(nodeh, &proph, node_name, row, PP_EXPECTED, 8653941Svenki snmp_syserr_p); 8663941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 8673941Svenki } else { 8683941Svenki log_msg(LOG_ERR, 8693941Svenki SNMPP_UNSUPP_SENSOR_CLASS, sensor_class, row); 8703941Svenki return (NULL); 8713941Svenki } 8723941Svenki break; 8733941Svenki 8743941Svenki case SPC_MODULE: 8753941Svenki ADD_NODE(PICL_CLASS_MODULE) 8763941Svenki 8773941Svenki add_prop(nodeh, &proph, node_name, row, PP_OPSTATUS, 8783941Svenki snmp_syserr_p); 8793941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 8803941Svenki 8813941Svenki add_prop(nodeh, &proph, node_name, row, PP_REPLACEABLE, 8823941Svenki snmp_syserr_p); 8833941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 8843941Svenki 8853941Svenki add_prop(nodeh, &proph, node_name, row, PP_HOTSWAPPABLE, 8863941Svenki snmp_syserr_p); 8873941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 8883941Svenki break; 8893941Svenki 8903941Svenki case SPC_PORT: 8913941Svenki ADD_NODE(PICL_CLASS_PORT) 8923941Svenki break; 8933941Svenki 8943941Svenki case SPC_STACK: 8953941Svenki ADD_NODE(PICL_CLASS_STACK) 8963941Svenki break; 8973941Svenki 8983941Svenki default: 8993941Svenki log_msg(LOG_WARNING, 9003941Svenki SNMPP_UNKNOWN_ENTPHYSCLASS, ent_physclass, row); 9013941Svenki free(phys_name); 9023941Svenki return (NULL); 9033941Svenki } 9043941Svenki 9053941Svenki add_prop(nodeh, &proph, node_name, row, PP_DESCRIPTION, snmp_syserr_p); 9063941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 9073941Svenki 9083941Svenki add_prop(nodeh, &proph, node_name, row, PP_LABEL, snmp_syserr_p); 9093941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 9103941Svenki 9113941Svenki add_prop(nodeh, &proph, node_name, row, PP_HW_REVISION, snmp_syserr_p); 9123941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 9133941Svenki 9143941Svenki add_prop(nodeh, &proph, node_name, row, PP_FW_REVISION, snmp_syserr_p); 9153941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 9163941Svenki 9173941Svenki add_prop(nodeh, &proph, node_name, row, PP_SERIAL_NUM, snmp_syserr_p); 9183941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 9193941Svenki 9203941Svenki add_prop(nodeh, &proph, node_name, row, PP_MFG_NAME, snmp_syserr_p); 9213941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 9223941Svenki 9233941Svenki add_prop(nodeh, &proph, node_name, row, PP_MODEL_NAME, snmp_syserr_p); 9243941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 9253941Svenki 9263941Svenki add_prop(nodeh, &proph, node_name, row, PP_IS_FRU, snmp_syserr_p); 9273941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 9283941Svenki 9293941Svenki free(phys_name); 9303941Svenki save_nodeh(nodeh, row); 9313941Svenki 9323941Svenki return (nodeh); 9333941Svenki } 9343941Svenki 9353941Svenki /* 9363941Svenki * Saves the node handle and the row id into physplat_nodes[]. If we're 9373941Svenki * doing this in response to a hotplug event, we should've freed the 9383941Svenki * old physplat_nodes before entering here to save the first node of the 9393941Svenki * new physplat subtree. 9403941Svenki */ 9413941Svenki static void 9423941Svenki save_nodeh(picl_nodehdl_t nodeh, int row) 9433941Svenki { 9443941Svenki size_t sz, count; 9453941Svenki picl_nodehdl_t *p; 9463941Svenki 9473941Svenki if (row >= n_physplat_nodes) { 9483941Svenki count = (((size_t)row >> NODE_BLOCK_SHIFT) + 1) * 9493941Svenki N_ELEMS_IN_NODE_BLOCK; 9503941Svenki sz = count * sizeof (picl_nodehdl_t); 9513941Svenki 9523941Svenki p = (picl_nodehdl_t *)calloc(count, sizeof (picl_nodehdl_t)); 9533941Svenki if (p == NULL) { 9543941Svenki log_msg(LOG_ERR, SNMPP_NO_MEM, sz); 9553941Svenki return; 9563941Svenki } 9573941Svenki 9583941Svenki if (physplat_nodes) { 9593941Svenki (void) memcpy((void *) p, (void *) physplat_nodes, 9603941Svenki n_physplat_nodes * sizeof (picl_nodehdl_t)); 9613941Svenki free((void *) physplat_nodes); 9623941Svenki } 9633941Svenki 9643941Svenki physplat_nodes = p; 9653941Svenki n_physplat_nodes = count; 9663941Svenki } 9673941Svenki 9683941Svenki physplat_nodes[row] = nodeh; 9693941Svenki } 9703941Svenki 9713941Svenki static picl_nodehdl_t 9723941Svenki lookup_nodeh(int row) 9733941Svenki { 9743941Svenki if (row >= n_physplat_nodes) 9753941Svenki return (NULL); 9763941Svenki 9773941Svenki return (physplat_nodes[row]); 9783941Svenki } 9793941Svenki 9803941Svenki /* 9813941Svenki * We enter this routine only when we are building the physical-platform 9823941Svenki * subtree, whether for the first time or in response to a hotplug event. 9833941Svenki * If we're here for rebuilding the tree, we have already set stale_tree 9843941Svenki * to be B_TRUE, so no one else would be accessing vol_props, n_vol_props 9853941Svenki * or volprop_ndx. If we're here to build the tree for the first time, 9863941Svenki * picld hasn't yet created doors and is running single-threaded, so no 9873941Svenki * one else would be accessing them anyway. 9883941Svenki */ 9893941Svenki static void 9903941Svenki save_volprop(picl_prophdl_t prop, char *oidstr, int row, int proptype) 9913941Svenki { 9923941Svenki vol_prophdl_t *p; 9933941Svenki int count; 9943941Svenki 9953941Svenki if (volprop_ndx == n_vol_props) { 9963941Svenki count = n_vol_props + N_ELEMS_IN_VOLPROP_BLOCK; 9973941Svenki p = (vol_prophdl_t *)calloc(count, sizeof (vol_prophdl_t)); 9983941Svenki if (p == NULL) { 9993941Svenki log_msg(LOG_ERR, SNMPP_NO_MEM, 10003941Svenki count * sizeof (vol_prophdl_t)); 10013941Svenki return; 10023941Svenki } 10033941Svenki 10043941Svenki if (vol_props) { 10053941Svenki (void) memcpy((void *) p, (void *) vol_props, 10063941Svenki n_vol_props * sizeof (vol_prophdl_t)); 10073941Svenki free((void *) vol_props); 10083941Svenki } 10093941Svenki 10103941Svenki vol_props = p; 10113941Svenki n_vol_props += N_ELEMS_IN_VOLPROP_BLOCK; 10123941Svenki } 10133941Svenki 10143941Svenki vol_props[volprop_ndx].prop = prop; 10153941Svenki vol_props[volprop_ndx].oidstr = oidstr; 10163941Svenki vol_props[volprop_ndx].row = row; 10173941Svenki vol_props[volprop_ndx].proptype = proptype; 10183941Svenki 10193941Svenki volprop_ndx++; 10203941Svenki } 10213941Svenki 10223941Svenki static void 10235723Sfw157321 check_for_stale_data(boolean_t nocache) 10243941Svenki { 10253941Svenki int cur_change_time; 10263941Svenki int ret; 10273941Svenki int snmp_syserr; 10283941Svenki 10293941Svenki (void) rw_wrlock(&stale_tree_rwlp); 10303941Svenki 10313941Svenki /* 10323941Svenki * Check if some other thread beat us to it 10333941Svenki */ 10343941Svenki if (stale_tree == B_TRUE) { 10353941Svenki (void) rw_unlock(&stale_tree_rwlp); 10363941Svenki return; 10373941Svenki } 10383941Svenki 10393941Svenki /* 10405723Sfw157321 * Cache OID_entLastChangeTime for up to 10 seconds before 10415723Sfw157321 * fetching it from ILOM again. This prevents us from fetching 10425723Sfw157321 * this value from ILOM when the we're filling or refreshing a 10435723Sfw157321 * whole bunch of items in the cache around the same time. 10445723Sfw157321 */ 10455723Sfw157321 if (nocache == B_FALSE && time(NULL) - change_time_check <= 10) { 10465723Sfw157321 (void) rw_unlock(&stale_tree_rwlp); 10475723Sfw157321 return; 10485723Sfw157321 } 10495723Sfw157321 10505723Sfw157321 /* 10513941Svenki * Check if mib data has changed (hotplug? link-reset?) 10523941Svenki */ 10533941Svenki ret = snmp_get_int(hdl, OID_entLastChangeTime, 0, &cur_change_time, 10543941Svenki &snmp_syserr); 10555723Sfw157321 (void) time(&change_time_check); 10563941Svenki if ((ret == 0) && (cur_change_time == change_time)) { 10573941Svenki (void) rw_unlock(&stale_tree_rwlp); 10583941Svenki return; 10593941Svenki } 10603941Svenki 10613941Svenki /* 10623941Svenki * If we can't read entLastChangeTime we assume we need to rebuild 10633941Svenki * the tree. This will also cover the case when we need to rebuild 10643941Svenki * the tree because a link reset had happened. 10653941Svenki */ 10663941Svenki LOGPRINTF2("check_for_stale_data: LastChange times have changed, " 10673941Svenki "(%#x != %#x)\n", change_time, cur_change_time); 10683941Svenki 10693941Svenki /* 10703941Svenki * If the mib data has changed, we need to rebuild the physical-platform 10713941Svenki * subtree. To do this, we set a flag to mark the tree stale, 10723941Svenki * so that any future reads to get value of volatile properties will 10733941Svenki * return PICL_PROPVALUNAVAILABLE, until the stale_tree flag 10743941Svenki * is reset by the tree builder thread. 10753941Svenki */ 10763941Svenki stale_tree = B_TRUE; 10773941Svenki if (vol_props) { 10783941Svenki free(vol_props); 10793941Svenki } 10803941Svenki vol_props = NULL; 10813941Svenki volprop_ndx = 0; 10823941Svenki n_vol_props = 0; 10833941Svenki 10843941Svenki (void) rw_unlock(&stale_tree_rwlp); 10853941Svenki 10863941Svenki (void) mutex_lock(&rebuild_tree_lock); 10873941Svenki rebuild_tree = B_TRUE; 10883941Svenki (void) cond_signal(&rebuild_tree_cv); 10893941Svenki LOGPRINTF("check_for_stale_data: signalled tree builder\n"); 10903941Svenki (void) mutex_unlock(&rebuild_tree_lock); 10913941Svenki } 10923941Svenki 10933941Svenki /* 10943941Svenki * This is the critical routine. This callback is invoked by picl whenever 10953941Svenki * it needs to fetch the value of a volatile property. The first thing we 10963941Svenki * must do, however, is to see if there has been a hotplug or a link-reset 10973941Svenki * event since the last time we built the tree and whether we need to 10983941Svenki * rebuild the tree. If so, we do whatever is necessary to make that happen, 10993941Svenki * but return PICL_PROPVALUNAVAILABLE for now, without making any further 11003941Svenki * snmp requests or accessing any globals. 11013941Svenki */ 11023941Svenki static int 11033941Svenki read_volprop(ptree_rarg_t *parg, void *buf) 11043941Svenki { 11053941Svenki char *pstr; 11063941Svenki int propval; 11073941Svenki int i, ndx; 11083941Svenki int ret; 11093941Svenki int snmp_syserr = 0; 11103941Svenki 11113941Svenki /* 11123941Svenki * First check for any event that would make us throw away 11133941Svenki * the existing /physical-platform subtree and rebuild 11143941Svenki * another one. If we are rebuilding the subtree, we just 11153941Svenki * return the stale value until the tree is fully built. 11163941Svenki */ 11175723Sfw157321 check_for_stale_data(B_FALSE); 11183941Svenki 11193941Svenki (void) rw_rdlock(&stale_tree_rwlp); 11203941Svenki 11213941Svenki if (stale_tree == B_TRUE) { 11223941Svenki (void) rw_unlock(&stale_tree_rwlp); 11233941Svenki return (PICL_PROPVALUNAVAILABLE); 11243941Svenki } 11253941Svenki 11263941Svenki for (i = 0; i < volprop_ndx; i++) { 11273941Svenki if (vol_props[i].prop == parg->proph) { 11283941Svenki ndx = i; 11293941Svenki break; 11303941Svenki } 11313941Svenki } 11323941Svenki if (i == volprop_ndx) { 11335723Sfw157321 (void) rw_unlock(&stale_tree_rwlp); 11343941Svenki log_msg(LOG_ERR, SNMPP_CANT_FIND_VOLPROP, parg->proph); 11353941Svenki return (PICL_FAILURE); 11363941Svenki } 11373941Svenki 11383941Svenki /* 11393941Svenki * If we can't read the value, return failure. Even if this was 11403941Svenki * due to a link reset, between the check for stale data and now, 11413941Svenki * the next volatile callback by picl will initiate a tree-rebuild. 11423941Svenki */ 11433941Svenki ret = snmp_get_int(hdl, vol_props[ndx].oidstr, vol_props[ndx].row, 11443941Svenki &propval, &snmp_syserr); 11453941Svenki if (ret < 0) { 11465723Sfw157321 (void) rw_unlock(&stale_tree_rwlp); 11475723Sfw157321 check_for_stale_data(B_TRUE); 11485723Sfw157321 if (stale_tree == B_TRUE) { 11495723Sfw157321 return (PICL_PROPVALUNAVAILABLE); 11505723Sfw157321 } 11515723Sfw157321 log_msg(LOG_ERR, SNMPP_CANT_FETCH_OBJECT_VAL, 11525723Sfw157321 snmp_syserr ? snmp_syserr : ret, 11535723Sfw157321 vol_props[ndx].oidstr, vol_props[ndx].row); 11543941Svenki return (PICL_FAILURE); 11553941Svenki } 11563941Svenki 11573941Svenki switch (vol_props[ndx].proptype) { 11583941Svenki case VPT_PLATOPSTATE: 11593941Svenki if (propval == SSOS_DISABLED) { 11603941Svenki (void) strlcpy(buf, STR_SSOS_DISABLED, MAX_OPSTATE_LEN); 11613941Svenki } else if (propval == SSOS_ENABLED) { 11623941Svenki (void) strlcpy(buf, STR_SSOS_ENABLED, MAX_OPSTATE_LEN); 11633941Svenki } else { 11645723Sfw157321 (void) rw_unlock(&stale_tree_rwlp); 11653941Svenki log_msg(LOG_ERR, SNMPP_INV_PLAT_EQUIP_OPSTATE, 11663941Svenki propval, vol_props[ndx].row); 11673941Svenki return (PICL_FAILURE); 11683941Svenki } 11693941Svenki break; 11703941Svenki 11713941Svenki case VPT_NUMSENSOR: 11723941Svenki (void) memcpy(buf, &propval, sizeof (propval)); 11733941Svenki break; 11743941Svenki 11753941Svenki case VPT_BINSENSOR: 11763941Svenki if (propval == ST_TRUE) { 11773941Svenki ret = snmp_get_str(hdl, 11783941Svenki OID_sunPlatBinarySensorInterpretTrue, 11793941Svenki vol_props[ndx].row, &pstr, &snmp_syserr); 11805723Sfw157321 if (snmp_syserr == ECANCELED) { 11815723Sfw157321 (void) rw_unlock(&stale_tree_rwlp); 11825723Sfw157321 if (pstr) 11835723Sfw157321 free(pstr); 11843941Svenki return (PICL_FAILURE); 11855723Sfw157321 } 11863941Svenki if (ret < 0 || pstr == NULL) { 11875723Sfw157321 log_msg(LOG_ERR, SNMPP_CANT_FETCH_OBJECT_VAL, 11885723Sfw157321 snmp_syserr ? snmp_syserr : ret, 11895723Sfw157321 OID_sunPlatBinarySensorInterpretTrue, 11905723Sfw157321 vol_props[ndx].row); 11913941Svenki (void) strlcpy(buf, STR_ST_TRUE, 11923941Svenki MAX_TRUTHVAL_LEN); 11933941Svenki } else { 11943941Svenki (void) strlcpy(buf, pstr, MAX_TRUTHVAL_LEN); 11955723Sfw157321 } 11965723Sfw157321 if (pstr) 11973941Svenki free(pstr); 11983941Svenki } else if (propval == ST_FALSE) { 11993941Svenki ret = snmp_get_str(hdl, 12003941Svenki OID_sunPlatBinarySensorInterpretFalse, 12013941Svenki vol_props[ndx].row, &pstr, &snmp_syserr); 12025723Sfw157321 if (snmp_syserr == ECANCELED) { 12035723Sfw157321 (void) rw_unlock(&stale_tree_rwlp); 12045723Sfw157321 if (pstr) 12055723Sfw157321 free(pstr); 12063941Svenki return (PICL_FAILURE); 12075723Sfw157321 } 12083941Svenki if (ret < 0 || pstr == NULL) { 12095723Sfw157321 log_msg(LOG_ERR, SNMPP_CANT_FETCH_OBJECT_VAL, 12105723Sfw157321 snmp_syserr ? snmp_syserr : ret, 12115723Sfw157321 OID_sunPlatBinarySensorInterpretFalse, 12125723Sfw157321 vol_props[ndx].row); 12133941Svenki (void) strlcpy(buf, STR_ST_FALSE, 12143941Svenki MAX_TRUTHVAL_LEN); 12153941Svenki } else { 12163941Svenki (void) strlcpy(buf, pstr, MAX_TRUTHVAL_LEN); 12175723Sfw157321 } 12185723Sfw157321 if (pstr) 12193941Svenki free(pstr); 12203941Svenki } else { 12215723Sfw157321 (void) rw_unlock(&stale_tree_rwlp); 12223941Svenki log_msg(LOG_ERR, SNMPP_INV_PLAT_BINSNSR_CURRENT, 12233941Svenki propval, vol_props[ndx].row); 12243941Svenki return (PICL_FAILURE); 12253941Svenki } 12263941Svenki break; 12273941Svenki 12283941Svenki case VPT_ALARMSTATE: 12293941Svenki if (propval == SSAS_OFF) { 12303941Svenki (void) strlcpy(buf, STR_SSAS_OFF, MAX_ALARMSTATE_LEN); 12313941Svenki } else if (propval == SSAS_STEADY) { 12323941Svenki (void) strlcpy(buf, STR_SSAS_STEADY, 12333941Svenki MAX_ALARMSTATE_LEN); 12343941Svenki } else if (propval == SSAS_ALTERNATING) { 12353941Svenki (void) strlcpy(buf, STR_SSAS_ALTERNATING, 12363941Svenki MAX_ALARMSTATE_LEN); 12373941Svenki } else { 12383941Svenki (void) strlcpy(buf, STR_SSAS_UNKNOWN, 12393941Svenki MAX_ALARMSTATE_LEN); 12403941Svenki } 12413941Svenki break; 12423941Svenki 12433941Svenki case VPT_BATTERYSTATUS: 12443941Svenki switch (propval) { 12453941Svenki case SSBS_OTHER: 12463941Svenki (void) strlcpy(buf, STR_SSBS_OTHER, 12473941Svenki MAX_BATTERYSTATUS_LEN); 12483941Svenki break; 12493941Svenki case SSBS_FULLYCHARGED: 12503941Svenki (void) strlcpy(buf, STR_SSBS_FULLYCHARGED, 12513941Svenki MAX_BATTERYSTATUS_LEN); 12523941Svenki break; 12533941Svenki case SSBS_LOW: 12543941Svenki (void) strlcpy(buf, STR_SSBS_LOW, 12553941Svenki MAX_BATTERYSTATUS_LEN); 12563941Svenki break; 12573941Svenki case SSBS_CRITICAL: 12583941Svenki (void) strlcpy(buf, STR_SSBS_CRITICAL, 12593941Svenki MAX_BATTERYSTATUS_LEN); 12603941Svenki break; 12613941Svenki case SSBS_CHARGING: 12623941Svenki (void) strlcpy(buf, STR_SSBS_CHARGING, 12633941Svenki MAX_BATTERYSTATUS_LEN); 12643941Svenki break; 12653941Svenki case SSBS_CHARGING_AND_LOW: 12663941Svenki (void) strlcpy(buf, STR_SSBS_CHARGING_AND_LOW, 12673941Svenki MAX_BATTERYSTATUS_LEN); 12683941Svenki break; 12693941Svenki case SSBS_CHARGING_AND_HIGH: 12703941Svenki (void) strlcpy(buf, STR_SSBS_CHARGING_AND_HIGH, 12713941Svenki MAX_BATTERYSTATUS_LEN); 12723941Svenki break; 12733941Svenki case SSBS_CHARGING_AND_CRITICAL: 12743941Svenki (void) strlcpy(buf, STR_SSBS_CHARGING_AND_CRITICAL, 12753941Svenki MAX_BATTERYSTATUS_LEN); 12763941Svenki break; 12773941Svenki case SSBS_UNDEFINED: 12783941Svenki (void) strlcpy(buf, STR_SSBS_UNDEFINED, 12793941Svenki MAX_BATTERYSTATUS_LEN); 12803941Svenki break; 12813941Svenki case SSBS_PARTIALLY_CHARGED: 12823941Svenki (void) strlcpy(buf, STR_SSBS_PARTIALLY_CHARGED, 12833941Svenki MAX_BATTERYSTATUS_LEN); 12843941Svenki break; 12853941Svenki case SSBS_UNKNOWN: 12863941Svenki default: 12873941Svenki (void) strlcpy(buf, STR_SSBS_UNKNOWN, 12883941Svenki MAX_BATTERYSTATUS_LEN); 12893941Svenki break; 12903941Svenki } 12913941Svenki break; 12923941Svenki } 12933941Svenki 12943941Svenki (void) rw_unlock(&stale_tree_rwlp); 12953941Svenki 12963941Svenki return (PICL_SUCCESS); 12973941Svenki } 12983941Svenki 12993941Svenki static void 13003941Svenki threshold(picl_nodehdl_t node, char *oidstr, int row, char *propname, 13013941Svenki int *snmp_syserr_p) 13023941Svenki { 13033941Svenki picl_prophdl_t prop; 13043941Svenki int err; 13053941Svenki int val; 13063941Svenki 13075723Sfw157321 if ((err = snmp_get_int(hdl, oidstr, row, &val, snmp_syserr_p)) != -1) { 13083941Svenki err = add_volatile_prop(node, propname, PICL_PTYPE_INT, 13093941Svenki PICL_READ, sizeof (int), read_volprop, NULL, &prop); 13103941Svenki if (err == PICL_SUCCESS) 13113941Svenki save_volprop(prop, oidstr, row, VPT_NUMSENSOR); 13125723Sfw157321 } else 13135723Sfw157321 log_msg(LOG_ERR, SNMPP_CANT_FETCH_OBJECT_VAL, 13145723Sfw157321 *snmp_syserr_p ? *snmp_syserr_p : err, oidstr, row); 13153941Svenki } 13163941Svenki 13173941Svenki static void 13183941Svenki add_thresholds(picl_nodehdl_t node, int row, int *snmp_syserr_p) 13193941Svenki { 13203941Svenki uchar_t *bitstr = NULL; 13213941Svenki uchar_t enabled; 13223941Svenki uint_t nbytes; 13233941Svenki int ret; 13243941Svenki 13255723Sfw157321 ret = snmp_get_str(hdl, 13265723Sfw157321 OID_sunPlatNumericSensorEnabledThresholds, 13275723Sfw157321 row, (char **)&bitstr, snmp_syserr_p); 13285723Sfw157321 if (ret == -1) { 13295723Sfw157321 log_msg(LOG_ERR, SNMPP_CANT_FETCH_OBJECT_VAL, 13305723Sfw157321 *snmp_syserr_p ? *snmp_syserr_p : ret, 13315723Sfw157321 OID_sunPlatNumericSensorEnabledThresholds, row); 13325723Sfw157321 } else { 13335723Sfw157321 nbytes = strlen((const char *)bitstr); 13345723Sfw157321 } 13355723Sfw157321 13365723Sfw157321 CHECK_LINKRESET_VOID(snmp_syserr_p); 13373941Svenki 13385723Sfw157321 /* 13395723Sfw157321 * No bit string of threshold masks was returned, so we can't 13405723Sfw157321 * assume that any thresholds exist. 13415723Sfw157321 * 13425723Sfw157321 * This mask prevents us from attempting to fetch thresholds 13435723Sfw157321 * which don't apply to the sensor or that aren't there anyway, 13445723Sfw157321 * That speeds up the plug-in significantly since otherwise it 13455723Sfw157321 * takes several seconds to time out. 13465723Sfw157321 */ 13475723Sfw157321 if (ret < 0 || bitstr == NULL || nbytes == 0 || 2 < nbytes) { 13485723Sfw157321 if (bitstr) 13495723Sfw157321 free(bitstr); 13505723Sfw157321 return; 13515723Sfw157321 } else if (nbytes == 1) { 13523941Svenki /* 13533941Svenki * The ALOM snmp agent doesn't adhere to the BER rules for 13543941Svenki * encoding bit strings. While the BER states that bitstrings 13553941Svenki * must begin from the second octet after length, and the 13563941Svenki * first octet after length must indicate the number of unused 13573941Svenki * bits in the last octet, the snmp agent simply sends the 13583941Svenki * bitstring data as if it were octet string -- that is, the 13593941Svenki * "unused bits" octet is missing. 13603941Svenki */ 13613941Svenki enabled = bitstr[0]; 13623941Svenki } else if (nbytes == 2) 13633941Svenki enabled = bitstr[1]; 13643941Svenki 13653941Svenki if (bitstr) { 13663941Svenki free(bitstr); 13673941Svenki } 13683941Svenki 13693941Svenki if (enabled & LOWER_FATAL) { 13703941Svenki threshold(node, 13713941Svenki OID_sunPlatNumericSensorLowerThresholdFatal, row, 13723941Svenki PICL_PROP_LOW_POWER_OFF, snmp_syserr_p); 13733941Svenki CHECK_LINKRESET_VOID(snmp_syserr_p) 13743941Svenki } 13753941Svenki if (enabled & LOWER_CRITICAL) { 13763941Svenki threshold(node, 13773941Svenki OID_sunPlatNumericSensorLowerThresholdCritical, row, 13783941Svenki PICL_PROP_LOW_SHUTDOWN, snmp_syserr_p); 13793941Svenki CHECK_LINKRESET_VOID(snmp_syserr_p) 13803941Svenki } 13813941Svenki if (enabled & LOWER_NON_CRITICAL) { 13823941Svenki threshold(node, 13833941Svenki OID_sunPlatNumericSensorLowerThresholdNonCritical, row, 13843941Svenki PICL_PROP_LOW_WARNING, snmp_syserr_p); 13853941Svenki CHECK_LINKRESET_VOID(snmp_syserr_p) 13863941Svenki } 13873941Svenki if (enabled & UPPER_NON_CRITICAL) { 13883941Svenki threshold(node, 13893941Svenki OID_sunPlatNumericSensorUpperThresholdNonCritical, row, 13904802Sfw157321 PICL_PROP_HIGH_WARNING, snmp_syserr_p); 13913941Svenki CHECK_LINKRESET_VOID(snmp_syserr_p) 13923941Svenki } 13933941Svenki if (enabled & UPPER_CRITICAL) { 13943941Svenki threshold(node, 13953941Svenki OID_sunPlatNumericSensorUpperThresholdCritical, row, 13963941Svenki PICL_PROP_HIGH_SHUTDOWN, snmp_syserr_p); 13973941Svenki CHECK_LINKRESET_VOID(snmp_syserr_p) 13983941Svenki } 13993941Svenki if (enabled & UPPER_FATAL) { 14003941Svenki threshold(node, 14013941Svenki OID_sunPlatNumericSensorUpperThresholdFatal, row, 14024802Sfw157321 PICL_PROP_HIGH_POWER_OFF, snmp_syserr_p); 14033941Svenki CHECK_LINKRESET_VOID(snmp_syserr_p) 14043941Svenki } 14053941Svenki } 14063941Svenki 14073941Svenki static char * 14083941Svenki get_slot_type(int row, int *snmp_syserr_p) 14093941Svenki { 14103941Svenki char *p; 14113941Svenki char *slott = NULL; 14123941Svenki int ret; 14133941Svenki 14143941Svenki ret = snmp_get_str(hdl, OID_sunPlatEquipmentHolderAcceptableTypes, 14153941Svenki row, &p, snmp_syserr_p); 14163941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 14173941Svenki 14183941Svenki if ((ret == 0) && p && *p) { 14193941Svenki slott = p; 14203941Svenki if ((p = strchr(slott, '\n')) != NULL) 14213941Svenki *p = 0; 14223941Svenki } else { 14233941Svenki log_msg(LOG_WARNING, SNMPP_NO_SLOT_TYPE, row); 14243941Svenki if (p) { 14253941Svenki free(p); 14263941Svenki } 14273941Svenki } 14283941Svenki 14293941Svenki return (slott); 14303941Svenki } 14313941Svenki 14323941Svenki /* 14333941Svenki * Create and add the specified volatile property 14343941Svenki */ 14353941Svenki static int 14363941Svenki add_volatile_prop(picl_nodehdl_t node, char *name, int type, int access, 14373941Svenki int size, int (*rdfunc)(ptree_rarg_t *, void *), 14383941Svenki int (*wrfunc)(ptree_warg_t *, const void *), picl_prophdl_t *propp) 14393941Svenki { 14403941Svenki ptree_propinfo_t propinfo; 14413941Svenki picl_prophdl_t prop; 14423941Svenki int err; 14433941Svenki 14443941Svenki err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 14453941Svenki type, (access|PICL_VOLATILE), size, name, rdfunc, wrfunc); 14463941Svenki if (err != PICL_SUCCESS) { 14473941Svenki log_msg(LOG_ERR, SNMPP_CANT_INIT_PROPINFO, err); 14483941Svenki return (err); 14493941Svenki } 14503941Svenki 14513941Svenki err = ptree_create_and_add_prop(node, &propinfo, NULL, &prop); 14523941Svenki if (err != PICL_SUCCESS) { 14533941Svenki log_msg(LOG_ERR, SNMPP_CANT_ADD_PROP, err, node); 14543941Svenki return (err); 14553941Svenki } 14563941Svenki 14573941Svenki if (propp) 14583941Svenki *propp = prop; 14593941Svenki 14603941Svenki return (PICL_SUCCESS); 14613941Svenki } 14623941Svenki 14633941Svenki /* 14643941Svenki * Add the specified string property to the node 14653941Svenki */ 14663941Svenki static int 14673941Svenki add_string_prop(picl_nodehdl_t node, char *propname, char *propval) 14683941Svenki { 14693941Svenki ptree_propinfo_t propinfo; 14703941Svenki int err; 14713941Svenki 14723941Svenki err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 14733941Svenki PICL_PTYPE_CHARSTRING, PICL_READ, strlen(propval) + 1, 14743941Svenki propname, NULL, NULL); 14753941Svenki if (err != PICL_SUCCESS) { 14763941Svenki log_msg(LOG_ERR, SNMPP_CANT_INIT_STR_PROPINFO, err); 14773941Svenki return (err); 14783941Svenki } 14793941Svenki 14803941Svenki err = ptree_create_and_add_prop(node, &propinfo, propval, NULL); 14813941Svenki if (err != PICL_SUCCESS) { 14823941Svenki log_msg(LOG_ERR, SNMPP_CANT_ADD_STR_PROP, err, node); 14833941Svenki return (err); 14843941Svenki } 14853941Svenki 14863941Svenki return (PICL_SUCCESS); 14873941Svenki } 14883941Svenki 14893941Svenki /* 14903941Svenki * Add the specified void property to the node 14913941Svenki */ 14923941Svenki static int 14933941Svenki add_void_prop(picl_nodehdl_t node, char *propname) 14943941Svenki { 14953941Svenki ptree_propinfo_t propinfo; 14963941Svenki int err; 14973941Svenki 14983941Svenki err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 14993941Svenki PICL_PTYPE_VOID, PICL_READ, 0, propname, NULL, NULL); 15003941Svenki if (err != PICL_SUCCESS) { 15013941Svenki log_msg(LOG_ERR, SNMPP_CANT_INIT_VOID_PROPINFO, err); 15023941Svenki return (err); 15033941Svenki } 15043941Svenki 15053941Svenki err = ptree_create_and_add_prop(node, &propinfo, NULL, NULL); 15063941Svenki if (err != PICL_SUCCESS) { 15073941Svenki log_msg(LOG_ERR, SNMPP_CANT_ADD_VOID_PROP, err, node); 15083941Svenki return (err); 15093941Svenki } 15103941Svenki 15113941Svenki return (PICL_SUCCESS); 15123941Svenki } 15133941Svenki 15143941Svenki static void 15153941Svenki add_prop(picl_nodehdl_t nodeh, picl_prophdl_t *php, char *label, 15163941Svenki int row, sp_propid_t pp, int *snmp_syserr_p) 15173941Svenki { 15183941Svenki char *serial_num; 15193941Svenki char *slot_type; 15203941Svenki char *fw_revision, *hw_revision; 15213941Svenki char *mfg_name, *model_name; 15223941Svenki char *phys_descr; 15233941Svenki int val; 15243941Svenki int ret; 15253941Svenki 15263941Svenki switch (pp) { 15273941Svenki case PP_SERIAL_NUM: 15283941Svenki ret = snmp_get_str(hdl, OID_entPhysicalSerialNum, 15293941Svenki row, &serial_num, snmp_syserr_p); 15303941Svenki CHECK_LINKRESET_VOID(snmp_syserr_p) 15313941Svenki if ((ret == 0) && serial_num && *serial_num) { 15323941Svenki (void) add_string_prop(nodeh, 15333941Svenki PICL_PROP_SERIAL_NUMBER, serial_num); 15343941Svenki free((void *) serial_num); 15353941Svenki } 15365723Sfw157321 if (ret == -1) 15375723Sfw157321 log_msg(LOG_ERR, SNMPP_CANT_FETCH_OBJECT_VAL, 15385723Sfw157321 *snmp_syserr_p ? *snmp_syserr_p : ret, 15395723Sfw157321 OID_entPhysicalSerialNum, row); 15403941Svenki break; 15413941Svenki 15423941Svenki case PP_SLOT_TYPE: 15433941Svenki if ((slot_type = get_slot_type(row, snmp_syserr_p)) == NULL) { 15443941Svenki CHECK_LINKRESET_VOID(snmp_syserr_p) 15453941Svenki (void) add_string_prop(nodeh, 15463941Svenki PICL_PROP_SLOT_TYPE, DEFAULT_SLOT_TYPE); 15473941Svenki } else { 15483941Svenki (void) add_string_prop(nodeh, 15493941Svenki PICL_PROP_SLOT_TYPE, slot_type); 15503941Svenki free((void *) slot_type); 15513941Svenki } 15523941Svenki break; 15533941Svenki 15543941Svenki case PP_STATE: 15553941Svenki ret = add_volatile_prop(nodeh, PICL_PROP_STATE, 15563941Svenki PICL_PTYPE_CHARSTRING, PICL_READ, MAX_ALARMSTATE_LEN, 15573941Svenki read_volprop, NULL, php); 15583941Svenki if (ret == PICL_SUCCESS) { 15593941Svenki save_volprop(*php, OID_sunPlatAlarmState, row, 15603941Svenki VPT_ALARMSTATE); 15613941Svenki } 15623941Svenki break; 15633941Svenki 15643941Svenki case PP_OPSTATUS: 15653941Svenki ret = add_volatile_prop(nodeh, PICL_PROP_OPERATIONAL_STATUS, 15663941Svenki PICL_PTYPE_CHARSTRING, PICL_READ, MAX_OPSTATE_LEN, 15673941Svenki read_volprop, NULL, php); 15683941Svenki if (ret == PICL_SUCCESS) { 15693941Svenki save_volprop(*php, 15703941Svenki OID_sunPlatEquipmentOperationalState, row, 15713941Svenki VPT_PLATOPSTATE); 15723941Svenki } 15733941Svenki break; 15743941Svenki 15753941Svenki case PP_BATT_STATUS: 15763941Svenki ret = add_volatile_prop(nodeh, PICL_PROP_BATTERY_STATUS, 15774802Sfw157321 PICL_PTYPE_CHARSTRING, PICL_READ, MAX_BATTERYSTATUS_LEN, 15784802Sfw157321 read_volprop, NULL, php); 15793941Svenki if (ret == PICL_SUCCESS) { 15803941Svenki save_volprop(*php, OID_sunPlatBatteryStatus, row, 15813941Svenki VPT_BATTERYSTATUS); 15823941Svenki } 15833941Svenki break; 15843941Svenki 15853941Svenki case PP_TEMPERATURE: 15863941Svenki ret = add_volatile_prop(nodeh, PICL_PROP_TEMPERATURE, 15873941Svenki PICL_PTYPE_INT, PICL_READ, sizeof (int), read_volprop, 15883941Svenki NULL, php); 15893941Svenki if (ret == PICL_SUCCESS) { 15903941Svenki save_volprop(*php, OID_sunPlatNumericSensorCurrent, 15913941Svenki row, VPT_NUMSENSOR); 15923941Svenki } 15933941Svenki break; 15943941Svenki 15953941Svenki case PP_VOLTAGE: 15963941Svenki ret = add_volatile_prop(nodeh, PICL_PROP_VOLTAGE, 15973941Svenki PICL_PTYPE_INT, PICL_READ, sizeof (int), read_volprop, 15983941Svenki NULL, php); 15993941Svenki if (ret == PICL_SUCCESS) { 16003941Svenki save_volprop(*php, OID_sunPlatNumericSensorCurrent, 16013941Svenki row, VPT_NUMSENSOR); 16023941Svenki } 16033941Svenki break; 16043941Svenki 16053941Svenki case PP_CURRENT: 16063941Svenki ret = add_volatile_prop(nodeh, PICL_PROP_CURRENT, 16073941Svenki PICL_PTYPE_INT, PICL_READ, sizeof (int), read_volprop, 16083941Svenki NULL, php); 16093941Svenki if (ret == PICL_SUCCESS) { 16103941Svenki save_volprop(*php, OID_sunPlatNumericSensorCurrent, 16113941Svenki row, VPT_NUMSENSOR); 16123941Svenki } 16133941Svenki break; 16143941Svenki 16153941Svenki case PP_SPEED: 16163941Svenki ret = add_volatile_prop(nodeh, PICL_PROP_SPEED, PICL_PTYPE_INT, 16173941Svenki PICL_READ, sizeof (int), read_volprop, NULL, php); 16183941Svenki if (ret == PICL_SUCCESS) { 16193941Svenki save_volprop(*php, OID_sunPlatNumericSensorCurrent, 16203941Svenki row, VPT_NUMSENSOR); 16213941Svenki } 16223941Svenki break; 16233941Svenki 16243941Svenki case PP_SENSOR_VALUE: 16253941Svenki ret = add_volatile_prop(nodeh, PICL_PROP_SENSOR_VALUE, 16263941Svenki PICL_PTYPE_INT, PICL_READ, sizeof (int), read_volprop, 16273941Svenki NULL, php); 16283941Svenki if (ret == PICL_SUCCESS) { 16293941Svenki save_volprop(*php, OID_sunPlatNumericSensorCurrent, 16303941Svenki row, VPT_NUMSENSOR); 16313941Svenki } 16323941Svenki break; 16333941Svenki 16343941Svenki case PP_CONDITION: 16353941Svenki ret = add_volatile_prop(nodeh, PICL_PROP_CONDITION, 16363941Svenki PICL_PTYPE_CHARSTRING, PICL_READ, MAX_TRUTHVAL_LEN, 16373941Svenki read_volprop, NULL, php); 16383941Svenki if (ret == PICL_SUCCESS) { 16393941Svenki save_volprop(*php, OID_sunPlatBinarySensorCurrent, 16403941Svenki row, VPT_BINSENSOR); 16413941Svenki } 16423941Svenki break; 16433941Svenki 16443941Svenki case PP_EXPECTED: 16453941Svenki ret = add_volatile_prop(nodeh, PICL_PROP_EXPECTED, 16463941Svenki PICL_PTYPE_CHARSTRING, PICL_READ, MAX_TRUTHVAL_LEN, 16473941Svenki read_volprop, NULL, php); 16483941Svenki if (ret == PICL_SUCCESS) { 16493941Svenki save_volprop(*php, OID_sunPlatBinarySensorExpected, 16503941Svenki row, VPT_BINSENSOR); 16513941Svenki } 16523941Svenki break; 16533941Svenki 16545436Sfw157321 case PP_EXPONENT: 16555436Sfw157321 ret = add_volatile_prop(nodeh, PICL_PROP_EXPONENT, 16565436Sfw157321 PICL_PTYPE_INT, PICL_READ, sizeof (int), read_volprop, 16575436Sfw157321 NULL, php); 16585436Sfw157321 if (ret == PICL_SUCCESS) { 16595436Sfw157321 save_volprop(*php, OID_sunPlatNumericSensorExponent, 16605436Sfw157321 row, VPT_NUMSENSOR); 16615436Sfw157321 } 16625436Sfw157321 break; 16635436Sfw157321 16643941Svenki case PP_REPLACEABLE: 16653941Svenki ret = snmp_get_int(hdl, OID_sunPlatCircuitPackReplaceable, 16663941Svenki row, &val, snmp_syserr_p); 16673941Svenki CHECK_LINKRESET_VOID(snmp_syserr_p) 16683941Svenki if ((ret == 0) && (val == ST_TRUE)) 16693941Svenki (void) add_void_prop(nodeh, PICL_PROP_IS_REPLACEABLE); 16705723Sfw157321 if (ret == -1) 16715723Sfw157321 log_msg(LOG_ERR, SNMPP_CANT_FETCH_OBJECT_VAL, 16725723Sfw157321 *snmp_syserr_p ? *snmp_syserr_p : ret, 16735723Sfw157321 OID_sunPlatCircuitPackReplaceable, row); 16743941Svenki break; 16753941Svenki 16763941Svenki case PP_HOTSWAPPABLE: 16773941Svenki ret = snmp_get_int(hdl, OID_sunPlatCircuitPackHotSwappable, 16783941Svenki row, &val, snmp_syserr_p); 16793941Svenki CHECK_LINKRESET_VOID(snmp_syserr_p) 16803941Svenki if ((ret == 0) && (val == ST_TRUE)) 16813941Svenki (void) add_void_prop(nodeh, PICL_PROP_IS_HOT_SWAPPABLE); 16825723Sfw157321 if (ret == -1) 16835723Sfw157321 log_msg(LOG_ERR, SNMPP_CANT_FETCH_OBJECT_VAL, 16845723Sfw157321 *snmp_syserr_p ? *snmp_syserr_p : ret, 16855723Sfw157321 OID_sunPlatCircuitPackHotSwappable, row); 16863941Svenki break; 16873941Svenki 16883941Svenki case PP_IS_FRU: 16893941Svenki ret = snmp_get_int(hdl, OID_entPhysicalIsFRU, row, 16903941Svenki &val, snmp_syserr_p); 16913941Svenki CHECK_LINKRESET_VOID(snmp_syserr_p) 16923941Svenki if ((ret == 0) && (val == ST_TRUE)) 16933941Svenki (void) add_void_prop(nodeh, PICL_PROP_IS_FRU); 16945723Sfw157321 if (ret == -1) 16955723Sfw157321 log_msg(LOG_ERR, SNMPP_CANT_FETCH_OBJECT_VAL, 16965723Sfw157321 *snmp_syserr_p ? *snmp_syserr_p : ret, 16975723Sfw157321 OID_entPhysicalIsFRU, row); 16983941Svenki break; 16993941Svenki 17003941Svenki case PP_HW_REVISION: 17013941Svenki ret = snmp_get_str(hdl, OID_entPhysicalHardwareRev, 17023941Svenki row, &hw_revision, snmp_syserr_p); 17033941Svenki CHECK_LINKRESET_VOID(snmp_syserr_p) 17043941Svenki if ((ret == 0) && hw_revision && *hw_revision) { 17053941Svenki (void) add_string_prop(nodeh, 17063941Svenki PICL_PROP_HW_REVISION, hw_revision); 17073941Svenki free((void *) hw_revision); 17083941Svenki } 17095723Sfw157321 if (ret == -1) 17105723Sfw157321 log_msg(LOG_ERR, SNMPP_CANT_FETCH_OBJECT_VAL, 17115723Sfw157321 *snmp_syserr_p ? *snmp_syserr_p : ret, 17125723Sfw157321 OID_entPhysicalHardwareRev, row); 17133941Svenki break; 17143941Svenki 17153941Svenki case PP_FW_REVISION: 17163941Svenki ret = snmp_get_str(hdl, OID_entPhysicalFirmwareRev, 17173941Svenki row, &fw_revision, snmp_syserr_p); 17183941Svenki CHECK_LINKRESET_VOID(snmp_syserr_p) 17193941Svenki if ((ret == 0) && fw_revision && *fw_revision) { 17203941Svenki (void) add_string_prop(nodeh, 17213941Svenki PICL_PROP_FW_REVISION, fw_revision); 17223941Svenki free((void *) fw_revision); 17233941Svenki } 17245723Sfw157321 if (ret == -1) 17255723Sfw157321 log_msg(LOG_ERR, SNMPP_CANT_FETCH_OBJECT_VAL, 17265723Sfw157321 *snmp_syserr_p ? *snmp_syserr_p : ret, 17275723Sfw157321 OID_entPhysicalFirmwareRev, row); 17283941Svenki break; 17293941Svenki 17303941Svenki case PP_MFG_NAME: 17313941Svenki ret = snmp_get_str(hdl, OID_entPhysicalMfgName, 17323941Svenki row, &mfg_name, snmp_syserr_p); 17333941Svenki CHECK_LINKRESET_VOID(snmp_syserr_p) 17343941Svenki if ((ret == 0) && mfg_name && *mfg_name) { 17353941Svenki (void) add_string_prop(nodeh, 17363941Svenki PICL_PROP_MFG_NAME, mfg_name); 17373941Svenki free((void *) mfg_name); 17383941Svenki } 17395723Sfw157321 if (ret == -1) 17405723Sfw157321 log_msg(LOG_ERR, SNMPP_CANT_FETCH_OBJECT_VAL, 17415723Sfw157321 *snmp_syserr_p ? *snmp_syserr_p : ret, 17425723Sfw157321 OID_entPhysicalMfgName, row); 17433941Svenki break; 17443941Svenki 17453941Svenki case PP_MODEL_NAME: 17463941Svenki ret = snmp_get_str(hdl, OID_entPhysicalModelName, 17473941Svenki row, &model_name, snmp_syserr_p); 17483941Svenki CHECK_LINKRESET_VOID(snmp_syserr_p) 17493941Svenki if ((ret == 0) && model_name && *model_name) { 17503941Svenki (void) add_string_prop(nodeh, 17513941Svenki PICL_PROP_MODEL_NAME, model_name); 17523941Svenki free((void *) model_name); 17533941Svenki } 17545723Sfw157321 if (ret == -1) 17555723Sfw157321 log_msg(LOG_ERR, SNMPP_CANT_FETCH_OBJECT_VAL, 17565723Sfw157321 *snmp_syserr_p ? *snmp_syserr_p : ret, 17575723Sfw157321 OID_entPhysicalModelName, row); 17583941Svenki break; 17593941Svenki 17603941Svenki case PP_DESCRIPTION: 17613941Svenki ret = snmp_get_str(hdl, OID_entPhysicalDescr, 17623941Svenki row, &phys_descr, snmp_syserr_p); 17633941Svenki CHECK_LINKRESET_VOID(snmp_syserr_p) 17643941Svenki if ((ret == 0) && phys_descr && *phys_descr) { 17654802Sfw157321 (void) add_string_prop(nodeh, 17664802Sfw157321 PICL_PROP_PHYS_DESCRIPTION, phys_descr); 17674802Sfw157321 free((void *) phys_descr); 17683941Svenki } 17695723Sfw157321 if (ret == -1) 17705723Sfw157321 log_msg(LOG_ERR, SNMPP_CANT_FETCH_OBJECT_VAL, 17715723Sfw157321 *snmp_syserr_p ? *snmp_syserr_p : ret, 17725723Sfw157321 OID_entPhysicalDescr, row); 17733941Svenki break; 17743941Svenki 17753941Svenki case PP_LABEL: 17763941Svenki if (label && *label) 17773941Svenki (void) add_string_prop(nodeh, PICL_PROP_LABEL, label); 17783941Svenki break; 17793941Svenki 17803941Svenki case PP_BASE_UNITS: 17813941Svenki ret = snmp_get_int(hdl, OID_sunPlatNumericSensorBaseUnits, 17823941Svenki row, &val, snmp_syserr_p); 17833941Svenki CHECK_LINKRESET_VOID(snmp_syserr_p) 17843941Svenki if ((ret == 0) && (val > 0) && (val < n_baseunits)) { 17853941Svenki (void) add_string_prop(nodeh, 17863941Svenki PICL_PROP_BASE_UNITS, sensor_baseunits[val]); 17873941Svenki } 17885723Sfw157321 if (ret == -1) 17895723Sfw157321 log_msg(LOG_ERR, SNMPP_CANT_FETCH_OBJECT_VAL, 17905723Sfw157321 *snmp_syserr_p ? *snmp_syserr_p : ret, 17915723Sfw157321 OID_sunPlatNumericSensorBaseUnits, row); 17923941Svenki break; 17933941Svenki 17943941Svenki case PP_RATE_UNITS: 17953941Svenki ret = snmp_get_int(hdl, OID_sunPlatNumericSensorRateUnits, 17963941Svenki row, &val, snmp_syserr_p); 17973941Svenki CHECK_LINKRESET_VOID(snmp_syserr_p) 17983941Svenki if ((ret == 0) && (val > 0) && (val < n_rateunits)) { 17993941Svenki (void) add_string_prop(nodeh, 18003941Svenki PICL_PROP_RATE_UNITS, sensor_rateunits[val]); 18013941Svenki } 18025723Sfw157321 if (ret == -1) 18035723Sfw157321 log_msg(LOG_ERR, SNMPP_CANT_FETCH_OBJECT_VAL, 18045723Sfw157321 *snmp_syserr_p ? *snmp_syserr_p : ret, 18055723Sfw157321 OID_sunPlatNumericSensorRateUnits, row); 18063941Svenki break; 18073941Svenki } 18083941Svenki } 18093941Svenki 18103941Svenki /*VARARGS2*/ 18113941Svenki static void 18123941Svenki log_msg(int pri, const char *fmt, ...) 18133941Svenki { 18143941Svenki va_list ap; 18153941Svenki 18163941Svenki va_start(ap, fmt); 18173941Svenki vsyslog(pri, fmt, ap); 18183941Svenki va_end(ap); 18193941Svenki } 18203941Svenki 18213941Svenki #ifdef SNMPPLUGIN_DEBUG 18223941Svenki 18233941Svenki static void 18243941Svenki snmpplugin_log_init(void) 18253941Svenki { 18263941Svenki (void) mutex_init(&snmpplugin_dbuf_lock, USYNC_THREAD, NULL); 18273941Svenki } 18283941Svenki 18293941Svenki static void 18303941Svenki snmpplugin_log(const char *fmt, ...) 18313941Svenki { 18323941Svenki va_list ap; 18333941Svenki 18343941Svenki (void) mutex_lock(&snmpplugin_dbuf_lock); 18353941Svenki 18363941Svenki va_start(ap, fmt); 18373941Svenki (void) vsnprintf(snmpplugin_lbuf, SNMPPLUGIN_DMAX_LINE, fmt, ap); 18383941Svenki snmpplugin_log_append(); 18393941Svenki va_end(ap); 18403941Svenki 18413941Svenki (void) mutex_unlock(&snmpplugin_dbuf_lock); 18423941Svenki } 18433941Svenki 18443941Svenki static void 18453941Svenki snmpplugin_log_append(void) 18463941Svenki { 18473941Svenki int len; 18483941Svenki 18493941Svenki len = strlen(snmpplugin_lbuf); 18503941Svenki 18513941Svenki if ((snmpplugin_dbuf_curp + len) >= 18523941Svenki (snmpplugin_dbuf + snmpplugin_dbuf_sz)) { 18533941Svenki snmpplugin_dbuf_realloc(); 18543941Svenki if (snmpplugin_dbuf == NULL) { 18553941Svenki return; 18563941Svenki } 18573941Svenki } 18583941Svenki 18593941Svenki (void) strcpy(snmpplugin_dbuf_curp, snmpplugin_lbuf); 18603941Svenki snmpplugin_dbuf_curp += len; 18613941Svenki } 18623941Svenki 18633941Svenki static void 18643941Svenki snmpplugin_dbuf_realloc(void) 18653941Svenki { 18663941Svenki char *p; 18673941Svenki size_t offset = 0; 18683941Svenki size_t count; 18693941Svenki 18703941Svenki count = snmpplugin_dbuf_sz + SNMPPLUGIN_DBLOCK_SZ; 18713941Svenki if ((p = (char *)calloc(count, 1)) == NULL) { 18723941Svenki snmpplugin_dbuf_overflow++; 18733941Svenki snmpplugin_dbuf_curp = snmpplugin_dbuf; 18743941Svenki return; 18753941Svenki } 18763941Svenki 18773941Svenki if (snmpplugin_dbuf) { 18783941Svenki offset = snmpplugin_dbuf_curp - snmpplugin_dbuf; 18793941Svenki (void) memcpy(p, snmpplugin_dbuf, snmpplugin_dbuf_sz); 18803941Svenki free(snmpplugin_dbuf); 18813941Svenki } 18823941Svenki 18833941Svenki snmpplugin_dbuf = p; 18843941Svenki snmpplugin_dbuf_sz += SNMPPLUGIN_DBLOCK_SZ; 18853941Svenki 18863941Svenki snmpplugin_dbuf_curp = snmpplugin_dbuf + offset; 18873941Svenki } 18883941Svenki #endif 1889