xref: /onnv-gate/usr/src/cmd/picl/plugins/sun4v/snmp/snmpplugin.c (revision 5995:670e9a45c101)
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