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*11471SMichael.Bergknoff@Sun.COM * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
243941Svenki * Use is subject to license terms.
253941Svenki */
263941Svenki
273941Svenki /*
283941Svenki * The SNMP picl plugin connects to the agent on the SP and creates
293941Svenki * and populates the /physical-platform subtree in picl tree for use
303941Svenki * by picl consumers.
313941Svenki */
323941Svenki
333941Svenki #include <stdio.h>
343941Svenki #include <stdlib.h>
353941Svenki #include <string.h>
363941Svenki #include <syslog.h>
373941Svenki #include <stdarg.h>
383941Svenki #include <libgen.h>
393941Svenki #include <libintl.h>
403941Svenki #include <thread.h>
413941Svenki #include <synch.h>
423941Svenki #include <errno.h>
437746SKelly.Moyer@Sun.COM #include <time.h>
44*11471SMichael.Bergknoff@Sun.COM #include <signal.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 /*
1047746SKelly.Moyer@Sun.COM * The cache_refresh thread periodically queries the snmp cache refresh work
1057746SKelly.Moyer@Sun.COM * queue and processes jobs from it to keep cache entries from expiring. It
1067746SKelly.Moyer@Sun.COM * attempts to run in cycles of CACHE_REFRESH_CYCLE seconds each, first
1077746SKelly.Moyer@Sun.COM * processing cache refresh jobs and then sleeping for the remainder of the
1087746SKelly.Moyer@Sun.COM * cycle once the next refresh job expiration is at least
1097746SKelly.Moyer@Sun.COM * CACHE_REFRESH_MIN_WINDOW seconds in the future.
1107746SKelly.Moyer@Sun.COM *
1117746SKelly.Moyer@Sun.COM * NOTE: By using a thread to keep the SNMP cache refreshed in the background,
1127746SKelly.Moyer@Sun.COM * we are both adding load to the system and reducing the system's ability to
1137746SKelly.Moyer@Sun.COM * operate in power-saving mode when there is minimal load. While these
1147746SKelly.Moyer@Sun.COM * tradeoffs are acceptable at this time in light of customer concerns about
1157746SKelly.Moyer@Sun.COM * performance, it may be desirable in the future to move this work into the
1167746SKelly.Moyer@Sun.COM * firmware. Also, while the current cycle times performed well on the largest
1177746SKelly.Moyer@Sun.COM * sun4v config currently available (Batoka), they may need to be revisited for
1187746SKelly.Moyer@Sun.COM * future systems if the number of sensors increases significantly.
1197746SKelly.Moyer@Sun.COM */
1207746SKelly.Moyer@Sun.COM #define CACHE_REFRESH_CYCLE 60
1217746SKelly.Moyer@Sun.COM #define CACHE_REFRESH_MIN_WINDOW 75
1227746SKelly.Moyer@Sun.COM static mutex_t cache_refresh_lock;
1237746SKelly.Moyer@Sun.COM static cond_t cache_refresh_cv;
1247746SKelly.Moyer@Sun.COM static boolean_t cache_refresh_thr_exit = B_FALSE;
1257746SKelly.Moyer@Sun.COM static thread_t cache_refresh_thr_id;
1267746SKelly.Moyer@Sun.COM
1277746SKelly.Moyer@Sun.COM /*
1283941Svenki * These two should really not be global
1293941Svenki */
1303941Svenki static picl_nodehdl_t *physplat_nodes = NULL;
1313941Svenki static int n_physplat_nodes = 0;
1323941Svenki
1333941Svenki static char *group1[] = {
1343941Svenki OID_entPhysicalDescr,
1353941Svenki OID_entPhysicalContainedIn,
1363941Svenki OID_entPhysicalClass,
1373941Svenki OID_entPhysicalName,
1383941Svenki OID_entPhysicalHardwareRev,
1393941Svenki OID_entPhysicalFirmwareRev,
1403941Svenki OID_entPhysicalSerialNum,
1413941Svenki OID_entPhysicalMfgName,
1423941Svenki OID_entPhysicalModelName,
1433941Svenki OID_entPhysicalIsFRU,
1443941Svenki 0
1453941Svenki };
1463941Svenki
1473941Svenki static char *group2[] = {
1483941Svenki OID_sunPlatEquipmentHolderAcceptableTypes,
1493941Svenki OID_sunPlatCircuitPackReplaceable,
1503941Svenki OID_sunPlatCircuitPackHotSwappable,
1513941Svenki OID_sunPlatPhysicalClass,
1523941Svenki OID_sunPlatSensorClass,
1533941Svenki OID_sunPlatSensorType,
1543941Svenki OID_sunPlatAlarmType,
1553941Svenki OID_sunPlatPowerSupplyClass,
1563941Svenki 0
1573941Svenki };
1583941Svenki
1595723Sfw157321 static char *group3[] = {
1605723Sfw157321 OID_sunPlatNumericSensorEnabledThresholds,
1615723Sfw157321 OID_sunPlatNumericSensorBaseUnits,
1625723Sfw157321 OID_sunPlatNumericSensorRateUnits,
1635723Sfw157321 0
1645723Sfw157321 };
1655723Sfw157321
1665723Sfw157321 static char *group4[] = {
1675723Sfw157321 OID_sunPlatBinarySensorInterpretTrue,
1685723Sfw157321 OID_sunPlatBinarySensorInterpretFalse,
1698411SKelly.Moyer@Sun.COM 0
1705723Sfw157321 };
1715723Sfw157321
1723941Svenki static char *volgroup1[] = {
1733941Svenki OID_sunPlatBinarySensorCurrent,
1743941Svenki OID_sunPlatBinarySensorExpected,
1753941Svenki 0
1763941Svenki };
1773941Svenki
1783941Svenki static char *volgroup2[] = {
1793941Svenki OID_sunPlatNumericSensorExponent,
1803941Svenki OID_sunPlatNumericSensorCurrent,
1813941Svenki OID_sunPlatNumericSensorLowerThresholdFatal,
1823941Svenki OID_sunPlatNumericSensorLowerThresholdCritical,
1833941Svenki OID_sunPlatNumericSensorLowerThresholdNonCritical,
1843941Svenki OID_sunPlatNumericSensorUpperThresholdNonCritical,
1853941Svenki OID_sunPlatNumericSensorUpperThresholdCritical,
1863941Svenki OID_sunPlatNumericSensorUpperThresholdFatal,
1873941Svenki 0
1883941Svenki };
1893941Svenki
1905723Sfw157321 static char *volgroup3[] = {
1915723Sfw157321 OID_sunPlatEquipmentOperationalState,
1925723Sfw157321 0
1935723Sfw157321 };
1945723Sfw157321
1955723Sfw157321 static char *volgroup4[] = {
1965723Sfw157321 OID_sunPlatAlarmState,
1975723Sfw157321 0
1985723Sfw157321 };
1995723Sfw157321
2005723Sfw157321 static char *volgroup5[] = {
2015723Sfw157321 OID_sunPlatBatteryStatus,
2025723Sfw157321 0
2035723Sfw157321 };
2045723Sfw157321
2053941Svenki /*
2063941Svenki * The following two items must match the Sun Platform MIB specification
2073941Svenki * in their indices and values.
2083941Svenki */
2093941Svenki static char *sensor_baseunits[] = {
2103941Svenki "", "other", "unknown", "degC", "degF", "degK", "volts", "amps",
2113941Svenki "watts", "joules", "coulombs", "va", "nits", "lumens", "lux",
2123941Svenki "candelas", "kPa", "psi", "newtons", "cfm", "rpm", "hertz",
2133941Svenki "seconds", "minutes", "hours", "days", "weeks", "mils", "inches",
2143941Svenki "feet", "cubicInches", "cubicFeet", "meters", "cubicCentimeters",
2153941Svenki "cubicMeters", "liters", "fluidOunces", "radians", "steradians",
2163941Svenki "revolutions", "cycles", "gravities", "ounces", "pounds", "footPounds",
2173941Svenki "ounceInches", "gauss", "gilberts", "henries", "farads", "ohms",
2183941Svenki "siemens", "moles", "becquerels", "ppm", "decibels", "dBA", "dbC",
2193941Svenki "grays", "sieverts", "colorTemperatureDegK", "bits", "bytes", "words",
2203941Svenki "doubleWords", "quadWords", "percentage"
2213941Svenki };
2223941Svenki static const int n_baseunits = sizeof (sensor_baseunits) / sizeof (char *);
2233941Svenki
2243941Svenki static char *sensor_rateunits[] = {
2253941Svenki "",
2263941Svenki "none",
2273941Svenki "perMicroSecond",
2283941Svenki "perMilliSecond",
2293941Svenki "perSecond",
2303941Svenki "perMinute",
2313941Svenki "perHour",
2323941Svenki "perDay",
2333941Svenki "perWeek",
2343941Svenki "perMonth",
2353941Svenki "perYear"
2363941Svenki };
2373941Svenki static const int n_rateunits = sizeof (sensor_rateunits) / sizeof (char *);
2383941Svenki
2393941Svenki /*
2403941Svenki * Local declarations
2413941Svenki */
2423941Svenki static void snmpplugin_register(void);
2433941Svenki static void register_group(char **g, int is_volatile);
2443941Svenki static void *tree_builder(void *arg);
2453941Svenki static int build_physplat(picl_nodehdl_t *subtree_rootp);
2463941Svenki static void free_resources(picl_nodehdl_t subtree_root);
2473941Svenki
2483941Svenki static picl_nodehdl_t make_node(picl_nodehdl_t subtree_root, int row,
2493941Svenki int *snmp_syserr_p);
2503941Svenki static void save_nodeh(picl_nodehdl_t nodeh, int row);
2513941Svenki static picl_nodehdl_t lookup_nodeh(int row);
2523941Svenki
2533941Svenki static void save_volprop(picl_prophdl_t prop, char *oidstr, int row,
2543941Svenki int proptype);
2555723Sfw157321 static void check_for_stale_data(boolean_t nocache);
2563941Svenki static int read_volprop(ptree_rarg_t *parg, void *buf);
2573941Svenki
2583941Svenki static void threshold(picl_nodehdl_t node, char *oidstr, int row,
2593941Svenki char *propname, int *snmp_syserr_p);
2603941Svenki static void add_thresholds(picl_nodehdl_t node, int row, int *snmp_syserr_p);
2613941Svenki
2623941Svenki static char *get_slot_type(int row, int *snmp_syserr_p);
2633941Svenki static int add_volatile_prop(picl_nodehdl_t nodeh, char *name,
2643941Svenki int type, int access, int size, int (*rdfunc)(ptree_rarg_t *, void *),
2653941Svenki int (*wrfunc)(ptree_warg_t *, const void *), picl_prophdl_t *propp);
2663941Svenki static int add_string_prop(picl_nodehdl_t node, char *propname, char *propval);
2673941Svenki static int add_void_prop(picl_nodehdl_t node, char *propname);
2683941Svenki static void add_prop(picl_nodehdl_t nodeh, picl_prophdl_t *php, char *label,
2693941Svenki int row, sp_propid_t pp, int *snmp_syserr_p);
2703941Svenki
2717746SKelly.Moyer@Sun.COM static void *cache_refresher(void *arg);
2727746SKelly.Moyer@Sun.COM static void cache_refresher_fini(void);
2737746SKelly.Moyer@Sun.COM
2743941Svenki static void log_msg(int pri, const char *fmt, ...);
2753941Svenki
2763941Svenki #ifdef SNMPPLUGIN_DEBUG
2773941Svenki static mutex_t snmpplugin_dbuf_lock;
2783941Svenki static char *snmpplugin_dbuf = NULL;
2793941Svenki static char *snmpplugin_dbuf_curp = NULL;
2803941Svenki static int snmpplugin_dbuf_sz = 0;
2813941Svenki static int snmpplugin_dbuf_overflow = 0;
2823941Svenki static char snmpplugin_lbuf[SNMPPLUGIN_DMAX_LINE];
2833941Svenki
2843941Svenki static void snmpplugin_log_init(void);
2853941Svenki static void snmpplugin_log(const char *fmt, ...);
2863941Svenki static void snmpplugin_log_append(void);
2873941Svenki static void snmpplugin_dbuf_realloc(void);
2883941Svenki #endif
2893941Svenki
2903941Svenki static void
snmpplugin_register(void)2913941Svenki snmpplugin_register(void)
2923941Svenki {
2933941Svenki (void) picld_plugin_register(&snmpplugin_reg);
2943941Svenki }
2953941Svenki
2963941Svenki static void
register_group(char ** g,int is_volatile)2973941Svenki register_group(char **g, int is_volatile)
2983941Svenki {
2993941Svenki int i, len = 0;
3003941Svenki int n_oids;
3013941Svenki char *p, *oidstrs;
3023941Svenki
3033941Svenki for (i = 0; g[i]; i++)
3043941Svenki len += strlen(g[i]) + 1;
3053941Svenki n_oids = i;
3063941Svenki
3073941Svenki if ((oidstrs = (char *)calloc(1, len)) == NULL)
3083941Svenki return;
3093941Svenki
3103941Svenki for (p = oidstrs, i = 0; g[i]; i++) {
3113941Svenki (void) strcpy(p, g[i]);
3123941Svenki p += strlen(g[i]) + 1;
3133941Svenki }
3143941Svenki
3153941Svenki snmp_register_group(hdl, oidstrs, n_oids, is_volatile);
3167382SMichael.Bergknoff@Sun.COM free(oidstrs);
3173941Svenki }
3183941Svenki
3193941Svenki void
snmpplugin_init(void)3203941Svenki snmpplugin_init(void)
3213941Svenki {
3223941Svenki int ret;
3233941Svenki
3243941Svenki (void) mutex_init(&rebuild_tree_lock, USYNC_THREAD, NULL);
3253941Svenki (void) cond_init(&rebuild_tree_cv, USYNC_THREAD, NULL);
3263941Svenki (void) rwlock_init(&stale_tree_rwlp, USYNC_THREAD, NULL);
3275029Sfw157321 tree_builder_thr_exit = B_FALSE;
3285029Sfw157321
3293941Svenki LOGINIT();
3303941Svenki
3313941Svenki /*
3323941Svenki * Create the tree-builder thread and let it take over
3333941Svenki */
3343941Svenki LOGPRINTF("Tree-builder thread being created.\n");
3353941Svenki if ((ret = thr_create(NULL, NULL, tree_builder, NULL,
3365029Sfw157321 THR_BOUND, &tree_builder_thr_id)) < 0) {
3373941Svenki log_msg(LOG_ERR, SNMPP_CANT_CREATE_TREE_BUILDER, ret);
3383941Svenki snmp_fini(hdl);
3395029Sfw157321 hdl = NULL;
3405029Sfw157321 (void) rwlock_destroy(&stale_tree_rwlp);
3415029Sfw157321 (void) cond_destroy(&rebuild_tree_cv);
3425029Sfw157321 (void) mutex_destroy(&rebuild_tree_lock);
3435029Sfw157321 tree_builder_thr_exit = B_TRUE;
3447746SKelly.Moyer@Sun.COM
3457746SKelly.Moyer@Sun.COM return;
3467746SKelly.Moyer@Sun.COM }
3477746SKelly.Moyer@Sun.COM
3487746SKelly.Moyer@Sun.COM /*
3497746SKelly.Moyer@Sun.COM * While the cache refresher thread does improve performance, it is not
3507746SKelly.Moyer@Sun.COM * integral to the proper function of the plugin. If we fail to create
3517746SKelly.Moyer@Sun.COM * the thread for some reason, we will simply continue without
3527746SKelly.Moyer@Sun.COM * refreshing.
3537746SKelly.Moyer@Sun.COM */
3547746SKelly.Moyer@Sun.COM (void) mutex_init(&cache_refresh_lock, USYNC_THREAD, NULL);
3557746SKelly.Moyer@Sun.COM (void) cond_init(&cache_refresh_cv, USYNC_THREAD, NULL);
3567746SKelly.Moyer@Sun.COM cache_refresh_thr_exit = B_FALSE;
3577746SKelly.Moyer@Sun.COM
3587746SKelly.Moyer@Sun.COM LOGPRINTF("Cache refresher thread being created.\n");
3597746SKelly.Moyer@Sun.COM if (thr_create(NULL, NULL, cache_refresher, NULL, THR_BOUND,
3607746SKelly.Moyer@Sun.COM &cache_refresh_thr_id) < 0) {
3617746SKelly.Moyer@Sun.COM (void) cond_destroy(&cache_refresh_cv);
3627746SKelly.Moyer@Sun.COM (void) mutex_destroy(&cache_refresh_lock);
3637746SKelly.Moyer@Sun.COM cache_refresh_thr_exit = B_TRUE;
3643941Svenki }
3653941Svenki }
3663941Svenki
3673941Svenki void
snmpplugin_fini(void)3683941Svenki snmpplugin_fini(void)
3693941Svenki {
3705029Sfw157321
3715029Sfw157321 if (tree_builder_thr_exit == B_TRUE)
3725029Sfw157321 return;
3733941Svenki
3745029Sfw157321 /*
3755029Sfw157321 * Make reads of volatile properties return PICL_PROPUNAVAILABLE
3765029Sfw157321 * since we're about to recycle the plug-in. No need to worry
3775029Sfw157321 * about removing /physical-platform since tree_builder() will
3785029Sfw157321 * take care of recycling it for us.
3795029Sfw157321 */
3805029Sfw157321 (void) rw_wrlock(&stale_tree_rwlp);
3815029Sfw157321 stale_tree = B_TRUE;
3825029Sfw157321 if (vol_props) {
3835029Sfw157321 free(vol_props);
3845029Sfw157321 }
3855029Sfw157321 vol_props = NULL;
3865029Sfw157321 volprop_ndx = 0;
3875029Sfw157321 n_vol_props = 0;
3885029Sfw157321 (void) rw_unlock(&stale_tree_rwlp);
3895029Sfw157321
3907746SKelly.Moyer@Sun.COM /* clean up the cache_refresher thread and structures */
3917746SKelly.Moyer@Sun.COM cache_refresher_fini();
3927746SKelly.Moyer@Sun.COM
3935029Sfw157321 /* wake up the tree_builder thread, tell it to exit */
3945029Sfw157321 (void) mutex_lock(&rebuild_tree_lock);
3955029Sfw157321 rebuild_tree = B_TRUE;
3965029Sfw157321 tree_builder_thr_exit = B_TRUE;
3975436Sfw157321 (void) cond_signal(&rebuild_tree_cv);
3985029Sfw157321 (void) mutex_unlock(&rebuild_tree_lock);
3995029Sfw157321
400*11471SMichael.Bergknoff@Sun.COM /* send SIGUSR1 to get tree_builder out of a blocked system call */
401*11471SMichael.Bergknoff@Sun.COM (void) thr_kill(tree_builder_thr_id, SIGUSR1);
402*11471SMichael.Bergknoff@Sun.COM
4035029Sfw157321 /* reap the thread */
4045029Sfw157321 (void) thr_join(tree_builder_thr_id, NULL, NULL);
4055029Sfw157321
4065029Sfw157321 /* close the channel */
4075029Sfw157321 if (hdl != NULL) {
4085029Sfw157321 snmp_fini(hdl);
4095029Sfw157321 hdl = NULL;
4105029Sfw157321 }
4115029Sfw157321
4125029Sfw157321 /* finish cleanup... */
4133941Svenki (void) rwlock_destroy(&stale_tree_rwlp);
4143941Svenki (void) cond_destroy(&rebuild_tree_cv);
4153941Svenki (void) mutex_destroy(&rebuild_tree_lock);
4163941Svenki }
4173941Svenki
4183941Svenki /*ARGSUSED*/
419*11471SMichael.Bergknoff@Sun.COM static void
usr1_handler(int sig,siginfo_t * siginfo,void * sigctx)420*11471SMichael.Bergknoff@Sun.COM usr1_handler(int sig, siginfo_t *siginfo, void *sigctx)
421*11471SMichael.Bergknoff@Sun.COM {
422*11471SMichael.Bergknoff@Sun.COM /*
423*11471SMichael.Bergknoff@Sun.COM * Nothing to do here.
424*11471SMichael.Bergknoff@Sun.COM * The act of catching the signal causes any cond_wait() or blocked
425*11471SMichael.Bergknoff@Sun.COM * system call to return EINTR. This is used to trigger early exit from
426*11471SMichael.Bergknoff@Sun.COM * the tree builder thread which may be blocked in snmp_init. More work
427*11471SMichael.Bergknoff@Sun.COM * would be required to allow early exit if the tree builder thread is
428*11471SMichael.Bergknoff@Sun.COM * already in its main processing loop and not blocked in cond_wait.
429*11471SMichael.Bergknoff@Sun.COM */
430*11471SMichael.Bergknoff@Sun.COM }
431*11471SMichael.Bergknoff@Sun.COM
432*11471SMichael.Bergknoff@Sun.COM /*ARGSUSED*/
4333941Svenki static void *
tree_builder(void * arg)4343941Svenki tree_builder(void *arg)
4353941Svenki {
4363941Svenki int ret, rv;
4373941Svenki picl_nodehdl_t root_node;
4383941Svenki picl_nodehdl_t physplat_root;
4393941Svenki picl_nodehdl_t old_physplat_root;
440*11471SMichael.Bergknoff@Sun.COM struct sigaction act;
441*11471SMichael.Bergknoff@Sun.COM
442*11471SMichael.Bergknoff@Sun.COM /*
443*11471SMichael.Bergknoff@Sun.COM * catch SIGUSR1 to allow early exit from snmp_init which may block
444*11471SMichael.Bergknoff@Sun.COM * indefinitely in a guest domain.
445*11471SMichael.Bergknoff@Sun.COM */
446*11471SMichael.Bergknoff@Sun.COM act.sa_sigaction = usr1_handler;
447*11471SMichael.Bergknoff@Sun.COM (void) sigemptyset(&act.sa_mask);
448*11471SMichael.Bergknoff@Sun.COM act.sa_flags = 0;
449*11471SMichael.Bergknoff@Sun.COM if (sigaction(SIGUSR1, &act, NULL) == -1) {
450*11471SMichael.Bergknoff@Sun.COM syslog(LOG_ERR, SIGACT_FAILED, strsignal(SIGUSR1),
451*11471SMichael.Bergknoff@Sun.COM strerror(errno));
452*11471SMichael.Bergknoff@Sun.COM }
4533941Svenki
4543941Svenki /*
4553941Svenki * Initialize SNMP service
4563941Svenki */
4573941Svenki LOGPRINTF("Initializing SNMP service.\n");
4583941Svenki if ((hdl = snmp_init()) == NULL) {
4593941Svenki log_msg(LOG_ERR, SNMPP_CANT_INIT);
4603941Svenki return ((void *)-1);
4613941Svenki }
4623941Svenki
4633941Svenki /*
4643941Svenki * Register OID groupings for BULKGET optimizations
4653941Svenki */
4663941Svenki LOGPRINTF("Registering OID groups.\n");
4673941Svenki register_group(group1, 0);
4683941Svenki register_group(group2, 0);
4695723Sfw157321 register_group(group3, 0);
4705723Sfw157321 register_group(group4, 0);
4713941Svenki register_group(volgroup1, 1);
4723941Svenki register_group(volgroup2, 1);
4735723Sfw157321 register_group(volgroup3, 1);
4745723Sfw157321 register_group(volgroup4, 1);
4755723Sfw157321 register_group(volgroup5, 1);
4763941Svenki
4773941Svenki (void) mutex_lock(&rebuild_tree_lock);
4783941Svenki
4793941Svenki for (;;) {
4803941Svenki LOGPRINTF("tree_builder: check whether to rebuild subtree\n");
4813941Svenki while (rebuild_tree == B_FALSE)
4823941Svenki (void) cond_wait(&rebuild_tree_cv, &rebuild_tree_lock);
4833941Svenki
4843941Svenki LOGPRINTF("tree_builder: woke up\n");
4853941Svenki
4865029Sfw157321 if (tree_builder_thr_exit == B_TRUE) {
4875029Sfw157321 (void) mutex_unlock(&rebuild_tree_lock);
4885029Sfw157321 LOGPRINTF("tree_builder: time to exit\n");
4895029Sfw157321 return (NULL);
4905029Sfw157321 }
4915029Sfw157321
4923941Svenki old_physplat_root = NULL;
4933941Svenki physplat_root = NULL;
4943941Svenki
4953941Svenki LOGPRINTF("tree_builder: getting root node\n");
4963941Svenki if ((ret = ptree_get_root(&root_node)) != PICL_SUCCESS) {
4975029Sfw157321 (void) mutex_unlock(&rebuild_tree_lock);
4983941Svenki log_msg(LOG_ERR, SNMPP_NO_ROOT, ret);
4993941Svenki return ((void *)-2);
5003941Svenki }
5013941Svenki
5023941Svenki LOGPRINTF("tree_builder: getting existing physplat node\n");
5033941Svenki rv = ptree_find_node(root_node, PICL_PROP_NAME,
5043941Svenki PICL_PTYPE_CHARSTRING, PICL_NODE_PHYSPLAT,
5053941Svenki sizeof (PICL_NODE_PHYSPLAT), &old_physplat_root);
5063941Svenki
5073941Svenki LOGPRINTF("tree_builder: building physical-platform\n");
5083941Svenki if ((ret = build_physplat(&physplat_root)) < 0) {
5095029Sfw157321 (void) mutex_unlock(&rebuild_tree_lock);
5103941Svenki log_msg(LOG_ERR, SNMPP_CANT_CREATE_PHYSPLAT, ret);
5117746SKelly.Moyer@Sun.COM cache_refresher_fini();
5123941Svenki snmp_fini(hdl);
5135029Sfw157321 hdl = NULL;
5143941Svenki return ((void *)-3);
5153941Svenki }
5163941Svenki
5173941Svenki if (rv == PICL_SUCCESS && old_physplat_root != NULL) {
5183941Svenki LOGPRINTF("tree_builder: destroying existing nodes\n");
5193941Svenki ptree_delete_node(old_physplat_root);
5203941Svenki ptree_destroy_node(old_physplat_root);
5213941Svenki }
5223941Svenki
5233941Svenki LOGPRINTF("tree_builder: attaching new subtree\n");
5243941Svenki if ((ret = ptree_add_node(root_node, physplat_root)) < 0) {
5255029Sfw157321 (void) mutex_unlock(&rebuild_tree_lock);
5263941Svenki free_resources(physplat_root);
5273941Svenki log_msg(LOG_ERR, SNMPP_CANT_CREATE_PHYSPLAT, ret);
5287746SKelly.Moyer@Sun.COM cache_refresher_fini();
5293941Svenki snmp_fini(hdl);
5305029Sfw157321 hdl = NULL;
5313941Svenki return ((void *)-4);
5323941Svenki }
5333941Svenki
5343941Svenki LOGPRINTF("tree_builder: setting stale_tree to FALSE\n");
5353941Svenki (void) rw_wrlock(&stale_tree_rwlp);
5363941Svenki stale_tree = B_FALSE;
5373941Svenki (void) rw_unlock(&stale_tree_rwlp);
5383941Svenki
5393941Svenki LOGPRINTF("tree_builder: setting rebuild_tree to FALSE\n");
5403941Svenki rebuild_tree = B_FALSE;
5413941Svenki }
5423941Svenki
5433941Svenki /*NOTREACHED*/
5443941Svenki return (NULL);
5453941Svenki }
5463941Svenki
5473941Svenki static int
build_physplat(picl_nodehdl_t * subtree_rootp)5483941Svenki build_physplat(picl_nodehdl_t *subtree_rootp)
5493941Svenki {
5503941Svenki int change_time1;
5513941Svenki int row, nxtrow;
5523941Svenki int clr_linkreset = 0;
5533941Svenki int ret = 0;
5543941Svenki int snmp_syserr = 0;
5553941Svenki
5563941Svenki retry:
5573941Svenki (void) snmp_reinit(hdl, clr_linkreset);
5583941Svenki clr_linkreset = 0;
5593941Svenki
5603941Svenki /*
5613941Svenki * Record LastChangeTime before we start building the tree
5623941Svenki */
5633941Svenki ret = snmp_get_int(hdl, OID_entLastChangeTime, 0,
5643941Svenki &change_time1, &snmp_syserr);
5653941Svenki if (ret < 0) {
5663941Svenki if (snmp_syserr == ECANCELED) {
5676751Sfw157321 LOGPRINTF(SNMPP_LINK_RESET);
5683941Svenki clr_linkreset = 1;
5693941Svenki goto retry;
5705723Sfw157321 }
5715723Sfw157321 log_msg(LOG_WARNING, SNMPP_CANT_FETCH_OBJECT_VAL,
5725723Sfw157321 snmp_syserr ? snmp_syserr : ret, OID_entLastChangeTime, 0);
5733941Svenki }
5743941Svenki
5753941Svenki /*
5763941Svenki * Create the physical-platform node
5773941Svenki */
5783941Svenki ret = ptree_create_node(PICL_NODE_PHYSPLAT, PICL_CLASS_PICL,
5793941Svenki subtree_rootp);
5803941Svenki if (ret != PICL_SUCCESS)
5813941Svenki return (-1);
5823941Svenki
5833941Svenki /*
5843941Svenki * Scan entPhysicalTable and build the "physical-platform" subtree
5853941Svenki */
5863941Svenki ret = 0;
5873941Svenki for (row = -1; ret == 0; row = nxtrow) {
5883941Svenki ret = snmp_get_nextrow(hdl, OID_entPhysicalDescr,
5893941Svenki row, &nxtrow, &snmp_syserr);
5905995Sfw157321 if (ret == 0)
5913941Svenki (void) make_node(*subtree_rootp, nxtrow, &snmp_syserr);
5925995Sfw157321 switch (snmp_syserr) {
5935995Sfw157321 case ECANCELED:
5943941Svenki /*
5953941Svenki * If we get this error, a link reset must've
5963941Svenki * happened and we need to throw away everything
5973941Svenki * we have now and rebuild the tree again.
5983941Svenki */
5993941Svenki log_msg(LOG_WARNING, SNMPP_LINK_RESET);
6003941Svenki free_resources(*subtree_rootp);
6013941Svenki clr_linkreset = 1;
6023941Svenki goto retry;
6035995Sfw157321 /*NOTREACHED*/
6045995Sfw157321 break;
6055995Sfw157321 case ENOSPC: /* end of MIB */
6065995Sfw157321 LOGPRINTF("build_physplat: end of MIB\n");
6075995Sfw157321 break;
6085995Sfw157321 case ENOENT: /* end of table */
6095995Sfw157321 LOGPRINTF("build_physplat: end of table\n");
6105995Sfw157321 break;
6115995Sfw157321 default:
6125995Sfw157321 /*
6135995Sfw157321 * make_node() will print messages so don't
6145995Sfw157321 * repeat that exercise here.
6155995Sfw157321 */
6165995Sfw157321 if (ret == -1) {
6175995Sfw157321 log_msg(LOG_WARNING,
6185995Sfw157321 SNMPP_CANT_FETCH_OBJECT_VAL,
6195995Sfw157321 snmp_syserr ? snmp_syserr : ret,
6205995Sfw157321 OID_entPhysicalDescr, row);
6215995Sfw157321 }
6223941Svenki }
6233941Svenki }
6243941Svenki
6253941Svenki /*
6263941Svenki * Record LastChangeTime after we're done building the tree
6273941Svenki */
6283941Svenki ret = snmp_get_int(hdl, OID_entLastChangeTime, 0,
6293941Svenki &change_time, &snmp_syserr);
6303941Svenki if (ret < 0) {
6313941Svenki if (snmp_syserr == ECANCELED) {
6323941Svenki log_msg(LOG_WARNING, SNMPP_LINK_RESET);
6333941Svenki free_resources(*subtree_rootp);
6343941Svenki clr_linkreset = 1;
6353941Svenki goto retry;
6363941Svenki } else
6375723Sfw157321 log_msg(LOG_WARNING, SNMPP_CANT_FETCH_OBJECT_VAL,
6385723Sfw157321 snmp_syserr ? snmp_syserr : ret,
6395723Sfw157321 OID_entLastChangeTime, row);
6403941Svenki }
6413941Svenki
6423941Svenki /*
6433941Svenki * If they don't match, some hotplugging must've happened,
6443941Svenki * free resources we've created and still holding, then go
6453941Svenki * back and retry
6463941Svenki */
6473941Svenki if (change_time != change_time1) {
6483941Svenki LOGPRINTF("build_physplat: entLastChangeTime has changed!\n");
6493941Svenki free_resources(*subtree_rootp);
6503941Svenki change_time1 = change_time;
6513941Svenki goto retry;
6523941Svenki }
6533941Svenki
6543941Svenki /*
6553941Svenki * The physplat_nodes table is no longer needed, free it
6563941Svenki */
6573941Svenki if (physplat_nodes) {
6583941Svenki free(physplat_nodes);
6593941Svenki physplat_nodes = NULL;
6603941Svenki n_physplat_nodes = 0;
6613941Svenki }
6623941Svenki
6633941Svenki return (0);
6643941Svenki }
6653941Svenki
6663941Svenki /*
6673941Svenki * Destroy all resources that were created during the building
6683941Svenki * of the subtree
6693941Svenki */
6703941Svenki static void
free_resources(picl_nodehdl_t subtree_root)6713941Svenki free_resources(picl_nodehdl_t subtree_root)
6723941Svenki {
6733941Svenki if (physplat_nodes) {
6743941Svenki free(physplat_nodes);
6753941Svenki physplat_nodes = NULL;
6763941Svenki n_physplat_nodes = 0;
6773941Svenki }
6783941Svenki
6793941Svenki if (subtree_root) {
6803941Svenki (void) ptree_delete_node(subtree_root);
6813941Svenki (void) ptree_destroy_node(subtree_root);
6823941Svenki }
6833941Svenki
6843941Svenki if (vol_props) {
6853941Svenki free(vol_props);
68610406SMichael.Bergknoff@Sun.COM vol_props = NULL;
6873941Svenki n_vol_props = 0;
6883941Svenki volprop_ndx = 0;
6893941Svenki }
6903941Svenki }
6913941Svenki
6923941Svenki static picl_nodehdl_t
make_node(picl_nodehdl_t subtree_root,int row,int * snmp_syserr_p)6933941Svenki make_node(picl_nodehdl_t subtree_root, int row, int *snmp_syserr_p)
6943941Svenki {
6953941Svenki picl_nodehdl_t nodeh, parenth;
6963941Svenki picl_prophdl_t proph;
6973941Svenki char *phys_name, *node_name;
6983941Svenki int parent_row;
6993941Svenki int ent_physclass, sunplat_physclass;
7003941Svenki int sensor_class, sensor_type;
7013941Svenki int alarm_type;
7023941Svenki int ps_class;
7033941Svenki int ret;
7043941Svenki
7053941Svenki /*
7063941Svenki * If we've already created this picl node, just return it
7073941Svenki */
7083941Svenki if ((nodeh = lookup_nodeh(row)) != NULL)
7093941Svenki return (nodeh);
7103941Svenki
7113941Svenki /*
7123941Svenki * If we are creating it only now, make sure we have the parent
7133941Svenki * created first; if there's no parent, then parent it to the
7143941Svenki * subtree's root node
7153941Svenki */
7163941Svenki ret = snmp_get_int(hdl, OID_entPhysicalContainedIn, row,
7173941Svenki &parent_row, snmp_syserr_p);
7183941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL)
7193941Svenki if (ret < 0 || parent_row <= 0)
7203941Svenki parenth = subtree_root;
7213941Svenki else {
7223941Svenki parenth = make_node(subtree_root, parent_row, snmp_syserr_p);
7233941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL)
7243941Svenki if (parenth == NULL)
7253941Svenki parenth = subtree_root;
7263941Svenki }
7273941Svenki
7283941Svenki /*
7293941Svenki * Figure out the physical-platform node name from entPhysicalName;
7303941Svenki * all rows in the MIB that have a valid entPhysicalIndex should
7313941Svenki * have a physical name.
7323941Svenki */
7333941Svenki ret = snmp_get_str(hdl, OID_entPhysicalName, row,
7343941Svenki &phys_name, snmp_syserr_p);
7353941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL)
7363941Svenki if (ret < 0 || phys_name == NULL) {
7373941Svenki log_msg(LOG_WARNING, SNMPP_NO_ENTPHYSNAME, row);
7383941Svenki return (NULL);
7393941Svenki }
7403941Svenki
7413941Svenki node_name = basename(phys_name);
7423941Svenki
7433941Svenki ret = snmp_get_int(hdl, OID_entPhysicalClass, row,
7443941Svenki &ent_physclass, snmp_syserr_p);
7453941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL)
7463941Svenki if (ret < 0) {
7475723Sfw157321 log_msg(LOG_WARNING, SNMPP_CANT_FETCH_OBJECT_VAL,
7485723Sfw157321 *snmp_syserr_p ? *snmp_syserr_p : ret,
7495723Sfw157321 OID_entPhysicalClass, row);
7503941Svenki free(phys_name);
7513941Svenki return (NULL);
7523941Svenki }
7533941Svenki
7543941Svenki switch (ent_physclass) {
7553941Svenki case SPC_OTHER:
7563941Svenki ret = snmp_get_int(hdl, OID_sunPlatPhysicalClass, row,
7573941Svenki &sunplat_physclass, snmp_syserr_p);
7583941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL)
7593941Svenki if (ret < 0) {
7605723Sfw157321 log_msg(LOG_WARNING, SNMPP_CANT_FETCH_OBJECT_VAL,
7615723Sfw157321 *snmp_syserr_p ? *snmp_syserr_p : ret,
7625723Sfw157321 OID_sunPlatPhysicalClass, row);
7633941Svenki free(phys_name);
7643941Svenki return (NULL);
7653941Svenki }
7663941Svenki
7673941Svenki if (sunplat_physclass == SSPC_ALARM) {
7683941Svenki ret = snmp_get_int(hdl, OID_sunPlatAlarmType,
7693941Svenki row, &alarm_type, snmp_syserr_p);
7703941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL)
7713941Svenki if (ret < 0) {
7723941Svenki log_msg(LOG_WARNING,
7735723Sfw157321 SNMPP_CANT_FETCH_OBJECT_VAL,
7745723Sfw157321 *snmp_syserr_p ? *snmp_syserr_p : ret,
7755723Sfw157321 OID_sunPlatAlarmType, row);
7763941Svenki free(phys_name);
7773941Svenki return (NULL);
7783941Svenki }
7793941Svenki
7803941Svenki if (alarm_type == SSAT_VISIBLE) {
7814802Sfw157321 ADD_NODE(PICL_CLASS_LED)
7823941Svenki } else {
7834802Sfw157321 ADD_NODE(PICL_CLASS_ALARM)
7843941Svenki }
7853941Svenki
7863941Svenki add_prop(nodeh, &proph, node_name, row, PP_STATE,
7873941Svenki snmp_syserr_p);
7883941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL)
7893941Svenki } else {
7903941Svenki ADD_NODE(PICL_CLASS_OTHER)
7913941Svenki }
7923941Svenki
7933941Svenki add_prop(nodeh, &proph, node_name, row, PP_OPSTATUS,
7943941Svenki snmp_syserr_p);
7953941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL)
7963941Svenki break;
7973941Svenki
7983941Svenki case SPC_UNKNOWN:
7993941Svenki ADD_NODE(PICL_CLASS_UNKNOWN)
8003941Svenki break;
8013941Svenki
8023941Svenki case SPC_CHASSIS:
8033941Svenki ADD_NODE(PICL_CLASS_CHASSIS)
8043941Svenki add_prop(nodeh, &proph, node_name, row, PP_OPSTATUS,
8053941Svenki snmp_syserr_p);
8063941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL)
8073941Svenki break;
8083941Svenki
8093941Svenki case SPC_BACKPLANE:
8103941Svenki ADD_NODE(PICL_CLASS_BACKPLANE)
8113941Svenki add_prop(nodeh, &proph, node_name, row, PP_OPSTATUS,
8123941Svenki snmp_syserr_p);
8133941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL)
8143941Svenki break;
8153941Svenki
8163941Svenki case SPC_CONTAINER:
8173941Svenki ADD_NODE(PICL_CLASS_CONTAINER)
8183941Svenki
8193941Svenki add_prop(nodeh, &proph, node_name, row, PP_OPSTATUS,
8203941Svenki snmp_syserr_p);
8213941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL)
8223941Svenki
8233941Svenki add_prop(nodeh, &proph, node_name, row, PP_SLOT_TYPE,
8243941Svenki snmp_syserr_p);
8253941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL)
8263941Svenki break;
8273941Svenki
8283941Svenki case SPC_POWERSUPPLY:
8293941Svenki ret = snmp_get_int(hdl, OID_sunPlatPowerSupplyClass,
8303941Svenki row, &ps_class, snmp_syserr_p);
8313941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL)
8323941Svenki if (ret < 0) {
8335723Sfw157321 log_msg(LOG_WARNING, SNMPP_CANT_FETCH_OBJECT_VAL,
8345723Sfw157321 *snmp_syserr_p ? *snmp_syserr_p : ret,
8355723Sfw157321 OID_sunPlatPowerSupplyClass, row);
8363941Svenki free(phys_name);
8373941Svenki return (NULL);
8383941Svenki }
8393941Svenki
8403941Svenki if (ps_class == SSPSC_BATTERY) {
8413941Svenki ADD_NODE(PICL_CLASS_BATTERY)
8423941Svenki add_prop(nodeh, &proph, node_name, row,
8433941Svenki PP_BATT_STATUS, snmp_syserr_p);
8443941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL)
8453941Svenki } else {
8463941Svenki ADD_NODE(PICL_CLASS_POWERSUPPLY)
8473941Svenki }
8483941Svenki add_prop(nodeh, &proph, node_name, row, PP_OPSTATUS,
8493941Svenki snmp_syserr_p);
8503941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL)
8513941Svenki break;
8523941Svenki
8533941Svenki case SPC_FAN:
8543941Svenki ADD_NODE(PICL_CLASS_FAN)
8553941Svenki add_prop(nodeh, &proph, node_name, row, PP_OPSTATUS,
8563941Svenki snmp_syserr_p);
8573941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL)
8583941Svenki break;
8593941Svenki
8603941Svenki case SPC_SENSOR:
8613941Svenki ret = snmp_get_int(hdl, OID_sunPlatSensorClass,
8623941Svenki row, &sensor_class, snmp_syserr_p);
8633941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL)
8643941Svenki if (ret < 0) {
8655723Sfw157321 log_msg(LOG_WARNING, SNMPP_CANT_FETCH_OBJECT_VAL,
8665723Sfw157321 *snmp_syserr_p ? *snmp_syserr_p : ret,
8675723Sfw157321 OID_sunPlatSensorClass, row);
8683941Svenki free(phys_name);
8693941Svenki return (NULL);
8703941Svenki }
8713941Svenki
8723941Svenki ret = snmp_get_int(hdl, OID_sunPlatSensorType,
8733941Svenki row, &sensor_type, snmp_syserr_p);
8743941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL)
8753941Svenki if (ret < 0) {
8765723Sfw157321 log_msg(LOG_WARNING, SNMPP_CANT_FETCH_OBJECT_VAL,
8775723Sfw157321 *snmp_syserr_p ? *snmp_syserr_p : ret,
8785723Sfw157321 OID_sunPlatSensorType, row);
8793941Svenki free(phys_name);
8803941Svenki return (NULL);
8813941Svenki }
8823941Svenki
8833941Svenki if (sensor_class == SSSC_NUMERIC) {
8843941Svenki if (sensor_type == SSST_TEMPERATURE) {
8853941Svenki ADD_NODE(PICL_CLASS_TEMPERATURE_SENSOR)
8863941Svenki add_prop(nodeh, &proph, node_name, row,
8873941Svenki PP_TEMPERATURE, snmp_syserr_p);
8883941Svenki } else if (sensor_type == SSST_VOLTAGE) {
8893941Svenki ADD_NODE(PICL_CLASS_VOLTAGE_SENSOR)
8903941Svenki add_prop(nodeh, &proph, node_name, row,
8913941Svenki PP_VOLTAGE, snmp_syserr_p);
8923941Svenki } else if (sensor_type == SSST_CURRENT) {
8933941Svenki ADD_NODE(PICL_CLASS_CURRENT_SENSOR)
8943941Svenki add_prop(nodeh, &proph, node_name, row,
8953941Svenki PP_CURRENT, snmp_syserr_p);
8963941Svenki } else if (sensor_type == SSST_TACHOMETER) {
8973941Svenki ADD_NODE(PICL_CLASS_RPM_SENSOR)
8983941Svenki add_prop(nodeh, &proph, node_name, row,
8993941Svenki PP_SPEED, snmp_syserr_p);
9003941Svenki } else {
9013941Svenki ADD_NODE(PICL_CLASS_SENSOR)
9023941Svenki add_prop(nodeh, &proph, node_name, row,
9033941Svenki PP_SENSOR_VALUE, snmp_syserr_p);
9043941Svenki }
9053941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL)
9063941Svenki
9073941Svenki add_prop(nodeh, &proph, node_name, row,
9083941Svenki PP_OPSTATUS, snmp_syserr_p);
9093941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL)
9103941Svenki
9113941Svenki add_prop(nodeh, &proph, node_name, row,
9123941Svenki PP_BASE_UNITS, snmp_syserr_p);
9133941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL)
9143941Svenki
9153941Svenki add_prop(nodeh, &proph, node_name, row,
9163941Svenki PP_EXPONENT, snmp_syserr_p);
9173941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL)
9183941Svenki
9193941Svenki add_prop(nodeh, &proph, node_name, row,
9203941Svenki PP_RATE_UNITS, snmp_syserr_p);
9213941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL)
9223941Svenki
9233941Svenki add_thresholds(nodeh, row, snmp_syserr_p);
9243941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL)
9253941Svenki
9263941Svenki } else if (sensor_class == SSSC_BINARY) {
9273941Svenki if (sensor_type == SSST_TEMPERATURE) {
9283941Svenki ADD_NODE(PICL_CLASS_TEMPERATURE_INDICATOR)
9293941Svenki } else if (sensor_type == SSST_VOLTAGE) {
9303941Svenki ADD_NODE(PICL_CLASS_VOLTAGE_INDICATOR)
9313941Svenki } else if (sensor_type == SSST_CURRENT) {
9323941Svenki ADD_NODE(PICL_CLASS_CURRENT_INDICATOR)
9333941Svenki } else if (sensor_type == SSST_TACHOMETER) {
9343941Svenki ADD_NODE(PICL_CLASS_RPM_INDICATOR)
9353941Svenki } else if (sensor_type == SSST_PRESENCE) {
9363941Svenki ADD_NODE(PICL_CLASS_PRESENCE_INDICATOR)
9373941Svenki } else {
9383941Svenki ADD_NODE(PICL_CLASS_INDICATOR)
9393941Svenki }
9403941Svenki
9413941Svenki add_prop(nodeh, &proph, node_name, row, PP_OPSTATUS,
9423941Svenki snmp_syserr_p);
9433941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL)
9443941Svenki
9453941Svenki add_prop(nodeh, &proph, node_name, row, PP_CONDITION,
9463941Svenki snmp_syserr_p);
9473941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL)
9483941Svenki
9493941Svenki add_prop(nodeh, &proph, node_name, row, PP_EXPECTED,
9503941Svenki snmp_syserr_p);
9513941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL)
9523941Svenki } else {
9533941Svenki log_msg(LOG_ERR,
9543941Svenki SNMPP_UNSUPP_SENSOR_CLASS, sensor_class, row);
9553941Svenki return (NULL);
9563941Svenki }
9573941Svenki break;
9583941Svenki
9593941Svenki case SPC_MODULE:
9603941Svenki ADD_NODE(PICL_CLASS_MODULE)
9613941Svenki
9623941Svenki add_prop(nodeh, &proph, node_name, row, PP_OPSTATUS,
9633941Svenki snmp_syserr_p);
9643941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL)
9653941Svenki
9663941Svenki add_prop(nodeh, &proph, node_name, row, PP_REPLACEABLE,
9673941Svenki snmp_syserr_p);
9683941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL)
9693941Svenki
9703941Svenki add_prop(nodeh, &proph, node_name, row, PP_HOTSWAPPABLE,
9713941Svenki snmp_syserr_p);
9723941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL)
9733941Svenki break;
9743941Svenki
9753941Svenki case SPC_PORT:
9763941Svenki ADD_NODE(PICL_CLASS_PORT)
9773941Svenki break;
9783941Svenki
9793941Svenki case SPC_STACK:
9803941Svenki ADD_NODE(PICL_CLASS_STACK)
9813941Svenki break;
9823941Svenki
9833941Svenki default:
9843941Svenki log_msg(LOG_WARNING,
9853941Svenki SNMPP_UNKNOWN_ENTPHYSCLASS, ent_physclass, row);
9863941Svenki free(phys_name);
9873941Svenki return (NULL);
9883941Svenki }
9893941Svenki
9903941Svenki add_prop(nodeh, &proph, node_name, row, PP_DESCRIPTION, snmp_syserr_p);
9913941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL)
9923941Svenki
9933941Svenki add_prop(nodeh, &proph, node_name, row, PP_LABEL, snmp_syserr_p);
9943941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL)
9953941Svenki
9963941Svenki add_prop(nodeh, &proph, node_name, row, PP_HW_REVISION, snmp_syserr_p);
9973941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL)
9983941Svenki
9993941Svenki add_prop(nodeh, &proph, node_name, row, PP_FW_REVISION, snmp_syserr_p);
10003941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL)
10013941Svenki
10023941Svenki add_prop(nodeh, &proph, node_name, row, PP_SERIAL_NUM, snmp_syserr_p);
10033941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL)
10043941Svenki
10053941Svenki add_prop(nodeh, &proph, node_name, row, PP_MFG_NAME, snmp_syserr_p);
10063941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL)
10073941Svenki
10083941Svenki add_prop(nodeh, &proph, node_name, row, PP_MODEL_NAME, snmp_syserr_p);
10093941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL)
10103941Svenki
10113941Svenki add_prop(nodeh, &proph, node_name, row, PP_IS_FRU, snmp_syserr_p);
10123941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL)
10133941Svenki
10143941Svenki free(phys_name);
10153941Svenki save_nodeh(nodeh, row);
10163941Svenki
10173941Svenki return (nodeh);
10183941Svenki }
10193941Svenki
10203941Svenki /*
10213941Svenki * Saves the node handle and the row id into physplat_nodes[]. If we're
10223941Svenki * doing this in response to a hotplug event, we should've freed the
10233941Svenki * old physplat_nodes before entering here to save the first node of the
10243941Svenki * new physplat subtree.
10253941Svenki */
10263941Svenki static void
save_nodeh(picl_nodehdl_t nodeh,int row)10273941Svenki save_nodeh(picl_nodehdl_t nodeh, int row)
10283941Svenki {
10293941Svenki size_t sz, count;
10303941Svenki picl_nodehdl_t *p;
10313941Svenki
10323941Svenki if (row >= n_physplat_nodes) {
10333941Svenki count = (((size_t)row >> NODE_BLOCK_SHIFT) + 1) *
10343941Svenki N_ELEMS_IN_NODE_BLOCK;
10353941Svenki sz = count * sizeof (picl_nodehdl_t);
10363941Svenki
10373941Svenki p = (picl_nodehdl_t *)calloc(count, sizeof (picl_nodehdl_t));
10383941Svenki if (p == NULL) {
10393941Svenki log_msg(LOG_ERR, SNMPP_NO_MEM, sz);
10403941Svenki return;
10413941Svenki }
10423941Svenki
10433941Svenki if (physplat_nodes) {
10443941Svenki (void) memcpy((void *) p, (void *) physplat_nodes,
10453941Svenki n_physplat_nodes * sizeof (picl_nodehdl_t));
10463941Svenki free((void *) physplat_nodes);
10473941Svenki }
10483941Svenki
10493941Svenki physplat_nodes = p;
10503941Svenki n_physplat_nodes = count;
10513941Svenki }
10523941Svenki
10533941Svenki physplat_nodes[row] = nodeh;
10543941Svenki }
10553941Svenki
10563941Svenki static picl_nodehdl_t
lookup_nodeh(int row)10573941Svenki lookup_nodeh(int row)
10583941Svenki {
10593941Svenki if (row >= n_physplat_nodes)
10603941Svenki return (NULL);
10613941Svenki
10623941Svenki return (physplat_nodes[row]);
10633941Svenki }
10643941Svenki
10653941Svenki /*
10663941Svenki * We enter this routine only when we are building the physical-platform
10673941Svenki * subtree, whether for the first time or in response to a hotplug event.
10683941Svenki * If we're here for rebuilding the tree, we have already set stale_tree
10693941Svenki * to be B_TRUE, so no one else would be accessing vol_props, n_vol_props
10703941Svenki * or volprop_ndx. If we're here to build the tree for the first time,
10713941Svenki * picld hasn't yet created doors and is running single-threaded, so no
10723941Svenki * one else would be accessing them anyway.
10733941Svenki */
10743941Svenki static void
save_volprop(picl_prophdl_t prop,char * oidstr,int row,int proptype)10753941Svenki save_volprop(picl_prophdl_t prop, char *oidstr, int row, int proptype)
10763941Svenki {
10773941Svenki vol_prophdl_t *p;
10783941Svenki int count;
10793941Svenki
10803941Svenki if (volprop_ndx == n_vol_props) {
10813941Svenki count = n_vol_props + N_ELEMS_IN_VOLPROP_BLOCK;
10823941Svenki p = (vol_prophdl_t *)calloc(count, sizeof (vol_prophdl_t));
10833941Svenki if (p == NULL) {
10843941Svenki log_msg(LOG_ERR, SNMPP_NO_MEM,
10853941Svenki count * sizeof (vol_prophdl_t));
10863941Svenki return;
10873941Svenki }
10883941Svenki
10893941Svenki if (vol_props) {
10903941Svenki (void) memcpy((void *) p, (void *) vol_props,
10913941Svenki n_vol_props * sizeof (vol_prophdl_t));
10923941Svenki free((void *) vol_props);
10933941Svenki }
10943941Svenki
10953941Svenki vol_props = p;
10963941Svenki n_vol_props += N_ELEMS_IN_VOLPROP_BLOCK;
10973941Svenki }
10983941Svenki
10993941Svenki vol_props[volprop_ndx].prop = prop;
11003941Svenki vol_props[volprop_ndx].oidstr = oidstr;
11013941Svenki vol_props[volprop_ndx].row = row;
11023941Svenki vol_props[volprop_ndx].proptype = proptype;
11033941Svenki
11043941Svenki volprop_ndx++;
11053941Svenki }
11063941Svenki
11073941Svenki static void
check_for_stale_data(boolean_t nocache)11085723Sfw157321 check_for_stale_data(boolean_t nocache)
11093941Svenki {
11103941Svenki int cur_change_time;
11113941Svenki int ret;
11123941Svenki int snmp_syserr;
11133941Svenki
11143941Svenki (void) rw_wrlock(&stale_tree_rwlp);
11153941Svenki
11163941Svenki /*
11173941Svenki * Check if some other thread beat us to it
11183941Svenki */
11193941Svenki if (stale_tree == B_TRUE) {
11203941Svenki (void) rw_unlock(&stale_tree_rwlp);
11213941Svenki return;
11223941Svenki }
11233941Svenki
11243941Svenki /*
11255723Sfw157321 * Cache OID_entLastChangeTime for up to 10 seconds before
11265723Sfw157321 * fetching it from ILOM again. This prevents us from fetching
11275723Sfw157321 * this value from ILOM when the we're filling or refreshing a
11285723Sfw157321 * whole bunch of items in the cache around the same time.
11295723Sfw157321 */
11305723Sfw157321 if (nocache == B_FALSE && time(NULL) - change_time_check <= 10) {
11315723Sfw157321 (void) rw_unlock(&stale_tree_rwlp);
11325723Sfw157321 return;
11335723Sfw157321 }
11345723Sfw157321
11355723Sfw157321 /*
11363941Svenki * Check if mib data has changed (hotplug? link-reset?)
11373941Svenki */
11387935SMichael.Bergknoff@Sun.COM do {
11397935SMichael.Bergknoff@Sun.COM snmp_syserr = 0;
11407935SMichael.Bergknoff@Sun.COM ret = snmp_get_int(hdl, OID_entLastChangeTime, 0,
11417935SMichael.Bergknoff@Sun.COM &cur_change_time, &snmp_syserr);
11427935SMichael.Bergknoff@Sun.COM (void) time(&change_time_check);
11437935SMichael.Bergknoff@Sun.COM if ((ret == 0) && (cur_change_time == change_time)) {
11447935SMichael.Bergknoff@Sun.COM (void) rw_unlock(&stale_tree_rwlp);
11457935SMichael.Bergknoff@Sun.COM return;
11467935SMichael.Bergknoff@Sun.COM }
11477935SMichael.Bergknoff@Sun.COM } while (ret != 0 && snmp_syserr == EINTR);
11483941Svenki
11493941Svenki /*
11503941Svenki * If we can't read entLastChangeTime we assume we need to rebuild
11513941Svenki * the tree. This will also cover the case when we need to rebuild
11523941Svenki * the tree because a link reset had happened.
11533941Svenki */
11543941Svenki LOGPRINTF2("check_for_stale_data: LastChange times have changed, "
11553941Svenki "(%#x != %#x)\n", change_time, cur_change_time);
11563941Svenki
11573941Svenki /*
11583941Svenki * If the mib data has changed, we need to rebuild the physical-platform
11593941Svenki * subtree. To do this, we set a flag to mark the tree stale,
11603941Svenki * so that any future reads to get value of volatile properties will
11613941Svenki * return PICL_PROPVALUNAVAILABLE, until the stale_tree flag
11623941Svenki * is reset by the tree builder thread.
11633941Svenki */
11643941Svenki stale_tree = B_TRUE;
11653941Svenki if (vol_props) {
11663941Svenki free(vol_props);
11673941Svenki }
11683941Svenki vol_props = NULL;
11693941Svenki volprop_ndx = 0;
11703941Svenki n_vol_props = 0;
11713941Svenki
11723941Svenki (void) rw_unlock(&stale_tree_rwlp);
11733941Svenki
11743941Svenki (void) mutex_lock(&rebuild_tree_lock);
11753941Svenki rebuild_tree = B_TRUE;
11763941Svenki (void) cond_signal(&rebuild_tree_cv);
11773941Svenki LOGPRINTF("check_for_stale_data: signalled tree builder\n");
11783941Svenki (void) mutex_unlock(&rebuild_tree_lock);
11793941Svenki }
11803941Svenki
11813941Svenki /*
11823941Svenki * This is the critical routine. This callback is invoked by picl whenever
11833941Svenki * it needs to fetch the value of a volatile property. The first thing we
11843941Svenki * must do, however, is to see if there has been a hotplug or a link-reset
11853941Svenki * event since the last time we built the tree and whether we need to
11863941Svenki * rebuild the tree. If so, we do whatever is necessary to make that happen,
11873941Svenki * but return PICL_PROPVALUNAVAILABLE for now, without making any further
11883941Svenki * snmp requests or accessing any globals.
11893941Svenki */
11903941Svenki static int
read_volprop(ptree_rarg_t * parg,void * buf)11913941Svenki read_volprop(ptree_rarg_t *parg, void *buf)
11923941Svenki {
11933941Svenki char *pstr;
11943941Svenki int propval;
11953941Svenki int i, ndx;
11963941Svenki int ret;
11973941Svenki int snmp_syserr = 0;
11983941Svenki
11993941Svenki /*
12003941Svenki * First check for any event that would make us throw away
12013941Svenki * the existing /physical-platform subtree and rebuild
12023941Svenki * another one. If we are rebuilding the subtree, we just
12033941Svenki * return the stale value until the tree is fully built.
12043941Svenki */
12055723Sfw157321 check_for_stale_data(B_FALSE);
12063941Svenki
12073941Svenki (void) rw_rdlock(&stale_tree_rwlp);
12083941Svenki
12093941Svenki if (stale_tree == B_TRUE) {
12103941Svenki (void) rw_unlock(&stale_tree_rwlp);
12113941Svenki return (PICL_PROPVALUNAVAILABLE);
12123941Svenki }
12133941Svenki
12143941Svenki for (i = 0; i < volprop_ndx; i++) {
12153941Svenki if (vol_props[i].prop == parg->proph) {
12163941Svenki ndx = i;
12173941Svenki break;
12183941Svenki }
12193941Svenki }
12203941Svenki if (i == volprop_ndx) {
12215723Sfw157321 (void) rw_unlock(&stale_tree_rwlp);
12223941Svenki log_msg(LOG_ERR, SNMPP_CANT_FIND_VOLPROP, parg->proph);
12233941Svenki return (PICL_FAILURE);
12243941Svenki }
12253941Svenki
12263941Svenki /*
12273941Svenki * If we can't read the value, return failure. Even if this was
12283941Svenki * due to a link reset, between the check for stale data and now,
12293941Svenki * the next volatile callback by picl will initiate a tree-rebuild.
12303941Svenki */
12313941Svenki ret = snmp_get_int(hdl, vol_props[ndx].oidstr, vol_props[ndx].row,
12323941Svenki &propval, &snmp_syserr);
12333941Svenki if (ret < 0) {
12345723Sfw157321 (void) rw_unlock(&stale_tree_rwlp);
12355723Sfw157321 check_for_stale_data(B_TRUE);
12365723Sfw157321 if (stale_tree == B_TRUE) {
12375723Sfw157321 return (PICL_PROPVALUNAVAILABLE);
12385723Sfw157321 }
12395723Sfw157321 log_msg(LOG_ERR, SNMPP_CANT_FETCH_OBJECT_VAL,
12405723Sfw157321 snmp_syserr ? snmp_syserr : ret,
12415723Sfw157321 vol_props[ndx].oidstr, vol_props[ndx].row);
12423941Svenki return (PICL_FAILURE);
12433941Svenki }
12443941Svenki
12453941Svenki switch (vol_props[ndx].proptype) {
12463941Svenki case VPT_PLATOPSTATE:
12473941Svenki if (propval == SSOS_DISABLED) {
12483941Svenki (void) strlcpy(buf, STR_SSOS_DISABLED, MAX_OPSTATE_LEN);
12493941Svenki } else if (propval == SSOS_ENABLED) {
12503941Svenki (void) strlcpy(buf, STR_SSOS_ENABLED, MAX_OPSTATE_LEN);
12513941Svenki } else {
12525723Sfw157321 (void) rw_unlock(&stale_tree_rwlp);
12533941Svenki log_msg(LOG_ERR, SNMPP_INV_PLAT_EQUIP_OPSTATE,
12543941Svenki propval, vol_props[ndx].row);
12553941Svenki return (PICL_FAILURE);
12563941Svenki }
12573941Svenki break;
12583941Svenki
12593941Svenki case VPT_NUMSENSOR:
12603941Svenki (void) memcpy(buf, &propval, sizeof (propval));
12613941Svenki break;
12623941Svenki
12633941Svenki case VPT_BINSENSOR:
12643941Svenki if (propval == ST_TRUE) {
12653941Svenki ret = snmp_get_str(hdl,
12663941Svenki OID_sunPlatBinarySensorInterpretTrue,
12673941Svenki vol_props[ndx].row, &pstr, &snmp_syserr);
12685723Sfw157321 if (snmp_syserr == ECANCELED) {
12695723Sfw157321 (void) rw_unlock(&stale_tree_rwlp);
12705723Sfw157321 if (pstr)
12715723Sfw157321 free(pstr);
12723941Svenki return (PICL_FAILURE);
12735723Sfw157321 }
12743941Svenki if (ret < 0 || pstr == NULL) {
12755723Sfw157321 log_msg(LOG_ERR, SNMPP_CANT_FETCH_OBJECT_VAL,
12765723Sfw157321 snmp_syserr ? snmp_syserr : ret,
12775723Sfw157321 OID_sunPlatBinarySensorInterpretTrue,
12785723Sfw157321 vol_props[ndx].row);
12793941Svenki (void) strlcpy(buf, STR_ST_TRUE,
12803941Svenki MAX_TRUTHVAL_LEN);
12813941Svenki } else {
12823941Svenki (void) strlcpy(buf, pstr, MAX_TRUTHVAL_LEN);
12835723Sfw157321 }
12845723Sfw157321 if (pstr)
12853941Svenki free(pstr);
12863941Svenki } else if (propval == ST_FALSE) {
12873941Svenki ret = snmp_get_str(hdl,
12883941Svenki OID_sunPlatBinarySensorInterpretFalse,
12893941Svenki vol_props[ndx].row, &pstr, &snmp_syserr);
12905723Sfw157321 if (snmp_syserr == ECANCELED) {
12915723Sfw157321 (void) rw_unlock(&stale_tree_rwlp);
12925723Sfw157321 if (pstr)
12935723Sfw157321 free(pstr);
12943941Svenki return (PICL_FAILURE);
12955723Sfw157321 }
12963941Svenki if (ret < 0 || pstr == NULL) {
12975723Sfw157321 log_msg(LOG_ERR, SNMPP_CANT_FETCH_OBJECT_VAL,
12985723Sfw157321 snmp_syserr ? snmp_syserr : ret,
12995723Sfw157321 OID_sunPlatBinarySensorInterpretFalse,
13005723Sfw157321 vol_props[ndx].row);
13013941Svenki (void) strlcpy(buf, STR_ST_FALSE,
13023941Svenki MAX_TRUTHVAL_LEN);
13033941Svenki } else {
13043941Svenki (void) strlcpy(buf, pstr, MAX_TRUTHVAL_LEN);
13055723Sfw157321 }
13065723Sfw157321 if (pstr)
13073941Svenki free(pstr);
13083941Svenki } else {
13095723Sfw157321 (void) rw_unlock(&stale_tree_rwlp);
13103941Svenki log_msg(LOG_ERR, SNMPP_INV_PLAT_BINSNSR_CURRENT,
13113941Svenki propval, vol_props[ndx].row);
13123941Svenki return (PICL_FAILURE);
13133941Svenki }
13143941Svenki break;
13153941Svenki
13163941Svenki case VPT_ALARMSTATE:
13173941Svenki if (propval == SSAS_OFF) {
13183941Svenki (void) strlcpy(buf, STR_SSAS_OFF, MAX_ALARMSTATE_LEN);
13193941Svenki } else if (propval == SSAS_STEADY) {
13203941Svenki (void) strlcpy(buf, STR_SSAS_STEADY,
13213941Svenki MAX_ALARMSTATE_LEN);
13223941Svenki } else if (propval == SSAS_ALTERNATING) {
13233941Svenki (void) strlcpy(buf, STR_SSAS_ALTERNATING,
13243941Svenki MAX_ALARMSTATE_LEN);
13253941Svenki } else {
13263941Svenki (void) strlcpy(buf, STR_SSAS_UNKNOWN,
13273941Svenki MAX_ALARMSTATE_LEN);
13283941Svenki }
13293941Svenki break;
13303941Svenki
13313941Svenki case VPT_BATTERYSTATUS:
13323941Svenki switch (propval) {
13333941Svenki case SSBS_OTHER:
13343941Svenki (void) strlcpy(buf, STR_SSBS_OTHER,
13353941Svenki MAX_BATTERYSTATUS_LEN);
13363941Svenki break;
13373941Svenki case SSBS_FULLYCHARGED:
13383941Svenki (void) strlcpy(buf, STR_SSBS_FULLYCHARGED,
13393941Svenki MAX_BATTERYSTATUS_LEN);
13403941Svenki break;
13413941Svenki case SSBS_LOW:
13423941Svenki (void) strlcpy(buf, STR_SSBS_LOW,
13433941Svenki MAX_BATTERYSTATUS_LEN);
13443941Svenki break;
13453941Svenki case SSBS_CRITICAL:
13463941Svenki (void) strlcpy(buf, STR_SSBS_CRITICAL,
13473941Svenki MAX_BATTERYSTATUS_LEN);
13483941Svenki break;
13493941Svenki case SSBS_CHARGING:
13503941Svenki (void) strlcpy(buf, STR_SSBS_CHARGING,
13513941Svenki MAX_BATTERYSTATUS_LEN);
13523941Svenki break;
13533941Svenki case SSBS_CHARGING_AND_LOW:
13543941Svenki (void) strlcpy(buf, STR_SSBS_CHARGING_AND_LOW,
13553941Svenki MAX_BATTERYSTATUS_LEN);
13563941Svenki break;
13573941Svenki case SSBS_CHARGING_AND_HIGH:
13583941Svenki (void) strlcpy(buf, STR_SSBS_CHARGING_AND_HIGH,
13593941Svenki MAX_BATTERYSTATUS_LEN);
13603941Svenki break;
13613941Svenki case SSBS_CHARGING_AND_CRITICAL:
13623941Svenki (void) strlcpy(buf, STR_SSBS_CHARGING_AND_CRITICAL,
13633941Svenki MAX_BATTERYSTATUS_LEN);
13643941Svenki break;
13653941Svenki case SSBS_UNDEFINED:
13663941Svenki (void) strlcpy(buf, STR_SSBS_UNDEFINED,
13673941Svenki MAX_BATTERYSTATUS_LEN);
13683941Svenki break;
13693941Svenki case SSBS_PARTIALLY_CHARGED:
13703941Svenki (void) strlcpy(buf, STR_SSBS_PARTIALLY_CHARGED,
13713941Svenki MAX_BATTERYSTATUS_LEN);
13723941Svenki break;
13733941Svenki case SSBS_UNKNOWN:
13743941Svenki default:
13753941Svenki (void) strlcpy(buf, STR_SSBS_UNKNOWN,
13763941Svenki MAX_BATTERYSTATUS_LEN);
13773941Svenki break;
13783941Svenki }
13793941Svenki break;
13803941Svenki }
13813941Svenki
13823941Svenki (void) rw_unlock(&stale_tree_rwlp);
13833941Svenki
13843941Svenki return (PICL_SUCCESS);
13853941Svenki }
13863941Svenki
13873941Svenki static void
threshold(picl_nodehdl_t node,char * oidstr,int row,char * propname,int * snmp_syserr_p)13883941Svenki threshold(picl_nodehdl_t node, char *oidstr, int row, char *propname,
13893941Svenki int *snmp_syserr_p)
13903941Svenki {
13913941Svenki picl_prophdl_t prop;
13923941Svenki int err;
13933941Svenki int val;
13943941Svenki
13955723Sfw157321 if ((err = snmp_get_int(hdl, oidstr, row, &val, snmp_syserr_p)) != -1) {
13963941Svenki err = add_volatile_prop(node, propname, PICL_PTYPE_INT,
13973941Svenki PICL_READ, sizeof (int), read_volprop, NULL, &prop);
13983941Svenki if (err == PICL_SUCCESS)
13993941Svenki save_volprop(prop, oidstr, row, VPT_NUMSENSOR);
14005723Sfw157321 } else
14015723Sfw157321 log_msg(LOG_ERR, SNMPP_CANT_FETCH_OBJECT_VAL,
14025723Sfw157321 *snmp_syserr_p ? *snmp_syserr_p : err, oidstr, row);
14033941Svenki }
14043941Svenki
14053941Svenki static void
add_thresholds(picl_nodehdl_t node,int row,int * snmp_syserr_p)14063941Svenki add_thresholds(picl_nodehdl_t node, int row, int *snmp_syserr_p)
14073941Svenki {
14083941Svenki uchar_t *bitstr = NULL;
14093941Svenki uchar_t enabled;
14103941Svenki uint_t nbytes;
14113941Svenki int ret;
14123941Svenki
14135723Sfw157321 ret = snmp_get_str(hdl,
14145723Sfw157321 OID_sunPlatNumericSensorEnabledThresholds,
14155723Sfw157321 row, (char **)&bitstr, snmp_syserr_p);
14165723Sfw157321 if (ret == -1) {
14175723Sfw157321 log_msg(LOG_ERR, SNMPP_CANT_FETCH_OBJECT_VAL,
14185723Sfw157321 *snmp_syserr_p ? *snmp_syserr_p : ret,
14195723Sfw157321 OID_sunPlatNumericSensorEnabledThresholds, row);
14205723Sfw157321 } else {
14215723Sfw157321 nbytes = strlen((const char *)bitstr);
14225723Sfw157321 }
14235723Sfw157321
14245723Sfw157321 CHECK_LINKRESET_VOID(snmp_syserr_p);
14253941Svenki
14265723Sfw157321 /*
14275723Sfw157321 * No bit string of threshold masks was returned, so we can't
14285723Sfw157321 * assume that any thresholds exist.
14295723Sfw157321 *
14305723Sfw157321 * This mask prevents us from attempting to fetch thresholds
14315723Sfw157321 * which don't apply to the sensor or that aren't there anyway,
14325723Sfw157321 * That speeds up the plug-in significantly since otherwise it
14335723Sfw157321 * takes several seconds to time out.
14345723Sfw157321 */
14355723Sfw157321 if (ret < 0 || bitstr == NULL || nbytes == 0 || 2 < nbytes) {
14365723Sfw157321 if (bitstr)
14375723Sfw157321 free(bitstr);
14385723Sfw157321 return;
14395723Sfw157321 } else if (nbytes == 1) {
14403941Svenki /*
14413941Svenki * The ALOM snmp agent doesn't adhere to the BER rules for
14423941Svenki * encoding bit strings. While the BER states that bitstrings
14433941Svenki * must begin from the second octet after length, and the
14443941Svenki * first octet after length must indicate the number of unused
14453941Svenki * bits in the last octet, the snmp agent simply sends the
14463941Svenki * bitstring data as if it were octet string -- that is, the
14473941Svenki * "unused bits" octet is missing.
14483941Svenki */
14493941Svenki enabled = bitstr[0];
14503941Svenki } else if (nbytes == 2)
14513941Svenki enabled = bitstr[1];
14523941Svenki
14533941Svenki if (bitstr) {
14543941Svenki free(bitstr);
14553941Svenki }
14563941Svenki
14573941Svenki if (enabled & LOWER_FATAL) {
14583941Svenki threshold(node,
14593941Svenki OID_sunPlatNumericSensorLowerThresholdFatal, row,
14603941Svenki PICL_PROP_LOW_POWER_OFF, snmp_syserr_p);
14613941Svenki CHECK_LINKRESET_VOID(snmp_syserr_p)
14623941Svenki }
14633941Svenki if (enabled & LOWER_CRITICAL) {
14643941Svenki threshold(node,
14653941Svenki OID_sunPlatNumericSensorLowerThresholdCritical, row,
14663941Svenki PICL_PROP_LOW_SHUTDOWN, snmp_syserr_p);
14673941Svenki CHECK_LINKRESET_VOID(snmp_syserr_p)
14683941Svenki }
14693941Svenki if (enabled & LOWER_NON_CRITICAL) {
14703941Svenki threshold(node,
14713941Svenki OID_sunPlatNumericSensorLowerThresholdNonCritical, row,
14723941Svenki PICL_PROP_LOW_WARNING, snmp_syserr_p);
14733941Svenki CHECK_LINKRESET_VOID(snmp_syserr_p)
14743941Svenki }
14753941Svenki if (enabled & UPPER_NON_CRITICAL) {
14763941Svenki threshold(node,
14773941Svenki OID_sunPlatNumericSensorUpperThresholdNonCritical, row,
14784802Sfw157321 PICL_PROP_HIGH_WARNING, snmp_syserr_p);
14793941Svenki CHECK_LINKRESET_VOID(snmp_syserr_p)
14803941Svenki }
14813941Svenki if (enabled & UPPER_CRITICAL) {
14823941Svenki threshold(node,
14833941Svenki OID_sunPlatNumericSensorUpperThresholdCritical, row,
14843941Svenki PICL_PROP_HIGH_SHUTDOWN, snmp_syserr_p);
14853941Svenki CHECK_LINKRESET_VOID(snmp_syserr_p)
14863941Svenki }
14873941Svenki if (enabled & UPPER_FATAL) {
14883941Svenki threshold(node,
14893941Svenki OID_sunPlatNumericSensorUpperThresholdFatal, row,
14904802Sfw157321 PICL_PROP_HIGH_POWER_OFF, snmp_syserr_p);
14913941Svenki CHECK_LINKRESET_VOID(snmp_syserr_p)
14923941Svenki }
14933941Svenki }
14943941Svenki
14953941Svenki static char *
get_slot_type(int row,int * snmp_syserr_p)14963941Svenki get_slot_type(int row, int *snmp_syserr_p)
14973941Svenki {
14983941Svenki char *p;
14993941Svenki char *slott = NULL;
15003941Svenki int ret;
15013941Svenki
15023941Svenki ret = snmp_get_str(hdl, OID_sunPlatEquipmentHolderAcceptableTypes,
15033941Svenki row, &p, snmp_syserr_p);
15043941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL)
15053941Svenki
15063941Svenki if ((ret == 0) && p && *p) {
15073941Svenki slott = p;
15083941Svenki if ((p = strchr(slott, '\n')) != NULL)
15093941Svenki *p = 0;
15103941Svenki } else {
15113941Svenki log_msg(LOG_WARNING, SNMPP_NO_SLOT_TYPE, row);
15123941Svenki if (p) {
15133941Svenki free(p);
15143941Svenki }
15153941Svenki }
15163941Svenki
15173941Svenki return (slott);
15183941Svenki }
15193941Svenki
15203941Svenki /*
15213941Svenki * Create and add the specified volatile property
15223941Svenki */
15233941Svenki static int
add_volatile_prop(picl_nodehdl_t node,char * name,int type,int access,int size,int (* rdfunc)(ptree_rarg_t *,void *),int (* wrfunc)(ptree_warg_t *,const void *),picl_prophdl_t * propp)15243941Svenki add_volatile_prop(picl_nodehdl_t node, char *name, int type, int access,
15253941Svenki int size, int (*rdfunc)(ptree_rarg_t *, void *),
15263941Svenki int (*wrfunc)(ptree_warg_t *, const void *), picl_prophdl_t *propp)
15273941Svenki {
15283941Svenki ptree_propinfo_t propinfo;
15293941Svenki picl_prophdl_t prop;
15303941Svenki int err;
15313941Svenki
15323941Svenki err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
15333941Svenki type, (access|PICL_VOLATILE), size, name, rdfunc, wrfunc);
15343941Svenki if (err != PICL_SUCCESS) {
15353941Svenki log_msg(LOG_ERR, SNMPP_CANT_INIT_PROPINFO, err);
15363941Svenki return (err);
15373941Svenki }
15383941Svenki
15393941Svenki err = ptree_create_and_add_prop(node, &propinfo, NULL, &prop);
15403941Svenki if (err != PICL_SUCCESS) {
15413941Svenki log_msg(LOG_ERR, SNMPP_CANT_ADD_PROP, err, node);
15423941Svenki return (err);
15433941Svenki }
15443941Svenki
15453941Svenki if (propp)
15463941Svenki *propp = prop;
15473941Svenki
15483941Svenki return (PICL_SUCCESS);
15493941Svenki }
15503941Svenki
15513941Svenki /*
15523941Svenki * Add the specified string property to the node
15533941Svenki */
15543941Svenki static int
add_string_prop(picl_nodehdl_t node,char * propname,char * propval)15553941Svenki add_string_prop(picl_nodehdl_t node, char *propname, char *propval)
15563941Svenki {
15573941Svenki ptree_propinfo_t propinfo;
15583941Svenki int err;
15593941Svenki
15607382SMichael.Bergknoff@Sun.COM if (*propval == '\0')
15617382SMichael.Bergknoff@Sun.COM return (PICL_SUCCESS);
15627382SMichael.Bergknoff@Sun.COM
15633941Svenki err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
15643941Svenki PICL_PTYPE_CHARSTRING, PICL_READ, strlen(propval) + 1,
15653941Svenki propname, NULL, NULL);
15663941Svenki if (err != PICL_SUCCESS) {
15673941Svenki log_msg(LOG_ERR, SNMPP_CANT_INIT_STR_PROPINFO, err);
15683941Svenki return (err);
15693941Svenki }
15703941Svenki
15713941Svenki err = ptree_create_and_add_prop(node, &propinfo, propval, NULL);
15723941Svenki if (err != PICL_SUCCESS) {
15733941Svenki log_msg(LOG_ERR, SNMPP_CANT_ADD_STR_PROP, err, node);
15743941Svenki return (err);
15753941Svenki }
15763941Svenki
15773941Svenki return (PICL_SUCCESS);
15783941Svenki }
15793941Svenki
15803941Svenki /*
15813941Svenki * Add the specified void property to the node
15823941Svenki */
15833941Svenki static int
add_void_prop(picl_nodehdl_t node,char * propname)15843941Svenki add_void_prop(picl_nodehdl_t node, char *propname)
15853941Svenki {
15863941Svenki ptree_propinfo_t propinfo;
15873941Svenki int err;
15883941Svenki
15893941Svenki err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
15903941Svenki PICL_PTYPE_VOID, PICL_READ, 0, propname, NULL, NULL);
15913941Svenki if (err != PICL_SUCCESS) {
15923941Svenki log_msg(LOG_ERR, SNMPP_CANT_INIT_VOID_PROPINFO, err);
15933941Svenki return (err);
15943941Svenki }
15953941Svenki
15963941Svenki err = ptree_create_and_add_prop(node, &propinfo, NULL, NULL);
15973941Svenki if (err != PICL_SUCCESS) {
15983941Svenki log_msg(LOG_ERR, SNMPP_CANT_ADD_VOID_PROP, err, node);
15993941Svenki return (err);
16003941Svenki }
16013941Svenki
16023941Svenki return (PICL_SUCCESS);
16033941Svenki }
16043941Svenki
16053941Svenki static void
add_prop(picl_nodehdl_t nodeh,picl_prophdl_t * php,char * label,int row,sp_propid_t pp,int * snmp_syserr_p)16063941Svenki add_prop(picl_nodehdl_t nodeh, picl_prophdl_t *php, char *label,
16073941Svenki int row, sp_propid_t pp, int *snmp_syserr_p)
16083941Svenki {
16093941Svenki char *serial_num;
16103941Svenki char *slot_type;
16113941Svenki char *fw_revision, *hw_revision;
16123941Svenki char *mfg_name, *model_name;
16133941Svenki char *phys_descr;
16143941Svenki int val;
16153941Svenki int ret;
16163941Svenki
16173941Svenki switch (pp) {
16183941Svenki case PP_SERIAL_NUM:
16193941Svenki ret = snmp_get_str(hdl, OID_entPhysicalSerialNum,
16203941Svenki row, &serial_num, snmp_syserr_p);
16213941Svenki CHECK_LINKRESET_VOID(snmp_syserr_p)
16227382SMichael.Bergknoff@Sun.COM if ((ret == 0) && serial_num) {
16233941Svenki (void) add_string_prop(nodeh,
16243941Svenki PICL_PROP_SERIAL_NUMBER, serial_num);
16253941Svenki free((void *) serial_num);
16263941Svenki }
16275723Sfw157321 if (ret == -1)
16285723Sfw157321 log_msg(LOG_ERR, SNMPP_CANT_FETCH_OBJECT_VAL,
16295723Sfw157321 *snmp_syserr_p ? *snmp_syserr_p : ret,
16305723Sfw157321 OID_entPhysicalSerialNum, row);
16313941Svenki break;
16323941Svenki
16333941Svenki case PP_SLOT_TYPE:
16343941Svenki if ((slot_type = get_slot_type(row, snmp_syserr_p)) == NULL) {
16353941Svenki CHECK_LINKRESET_VOID(snmp_syserr_p)
16363941Svenki (void) add_string_prop(nodeh,
16373941Svenki PICL_PROP_SLOT_TYPE, DEFAULT_SLOT_TYPE);
16383941Svenki } else {
16393941Svenki (void) add_string_prop(nodeh,
16403941Svenki PICL_PROP_SLOT_TYPE, slot_type);
16413941Svenki free((void *) slot_type);
16423941Svenki }
16433941Svenki break;
16443941Svenki
16453941Svenki case PP_STATE:
16463941Svenki ret = add_volatile_prop(nodeh, PICL_PROP_STATE,
16473941Svenki PICL_PTYPE_CHARSTRING, PICL_READ, MAX_ALARMSTATE_LEN,
16483941Svenki read_volprop, NULL, php);
16493941Svenki if (ret == PICL_SUCCESS) {
16503941Svenki save_volprop(*php, OID_sunPlatAlarmState, row,
16513941Svenki VPT_ALARMSTATE);
16523941Svenki }
16533941Svenki break;
16543941Svenki
16553941Svenki case PP_OPSTATUS:
16563941Svenki ret = add_volatile_prop(nodeh, PICL_PROP_OPERATIONAL_STATUS,
16573941Svenki PICL_PTYPE_CHARSTRING, PICL_READ, MAX_OPSTATE_LEN,
16583941Svenki read_volprop, NULL, php);
16593941Svenki if (ret == PICL_SUCCESS) {
16603941Svenki save_volprop(*php,
16613941Svenki OID_sunPlatEquipmentOperationalState, row,
16623941Svenki VPT_PLATOPSTATE);
16633941Svenki }
16643941Svenki break;
16653941Svenki
16663941Svenki case PP_BATT_STATUS:
16673941Svenki ret = add_volatile_prop(nodeh, PICL_PROP_BATTERY_STATUS,
16684802Sfw157321 PICL_PTYPE_CHARSTRING, PICL_READ, MAX_BATTERYSTATUS_LEN,
16694802Sfw157321 read_volprop, NULL, php);
16703941Svenki if (ret == PICL_SUCCESS) {
16713941Svenki save_volprop(*php, OID_sunPlatBatteryStatus, row,
16723941Svenki VPT_BATTERYSTATUS);
16733941Svenki }
16743941Svenki break;
16753941Svenki
16763941Svenki case PP_TEMPERATURE:
16773941Svenki ret = add_volatile_prop(nodeh, PICL_PROP_TEMPERATURE,
16783941Svenki PICL_PTYPE_INT, PICL_READ, sizeof (int), read_volprop,
16793941Svenki NULL, php);
16803941Svenki if (ret == PICL_SUCCESS) {
16813941Svenki save_volprop(*php, OID_sunPlatNumericSensorCurrent,
16823941Svenki row, VPT_NUMSENSOR);
16833941Svenki }
16843941Svenki break;
16853941Svenki
16863941Svenki case PP_VOLTAGE:
16873941Svenki ret = add_volatile_prop(nodeh, PICL_PROP_VOLTAGE,
16883941Svenki PICL_PTYPE_INT, PICL_READ, sizeof (int), read_volprop,
16893941Svenki NULL, php);
16903941Svenki if (ret == PICL_SUCCESS) {
16913941Svenki save_volprop(*php, OID_sunPlatNumericSensorCurrent,
16923941Svenki row, VPT_NUMSENSOR);
16933941Svenki }
16943941Svenki break;
16953941Svenki
16963941Svenki case PP_CURRENT:
16973941Svenki ret = add_volatile_prop(nodeh, PICL_PROP_CURRENT,
16983941Svenki PICL_PTYPE_INT, PICL_READ, sizeof (int), read_volprop,
16993941Svenki NULL, php);
17003941Svenki if (ret == PICL_SUCCESS) {
17013941Svenki save_volprop(*php, OID_sunPlatNumericSensorCurrent,
17023941Svenki row, VPT_NUMSENSOR);
17033941Svenki }
17043941Svenki break;
17053941Svenki
17063941Svenki case PP_SPEED:
17073941Svenki ret = add_volatile_prop(nodeh, PICL_PROP_SPEED, PICL_PTYPE_INT,
17083941Svenki PICL_READ, sizeof (int), read_volprop, NULL, php);
17093941Svenki if (ret == PICL_SUCCESS) {
17103941Svenki save_volprop(*php, OID_sunPlatNumericSensorCurrent,
17113941Svenki row, VPT_NUMSENSOR);
17123941Svenki }
17133941Svenki break;
17143941Svenki
17153941Svenki case PP_SENSOR_VALUE:
17163941Svenki ret = add_volatile_prop(nodeh, PICL_PROP_SENSOR_VALUE,
17173941Svenki PICL_PTYPE_INT, PICL_READ, sizeof (int), read_volprop,
17183941Svenki NULL, php);
17193941Svenki if (ret == PICL_SUCCESS) {
17203941Svenki save_volprop(*php, OID_sunPlatNumericSensorCurrent,
17213941Svenki row, VPT_NUMSENSOR);
17223941Svenki }
17233941Svenki break;
17243941Svenki
17253941Svenki case PP_CONDITION:
17263941Svenki ret = add_volatile_prop(nodeh, PICL_PROP_CONDITION,
17273941Svenki PICL_PTYPE_CHARSTRING, PICL_READ, MAX_TRUTHVAL_LEN,
17283941Svenki read_volprop, NULL, php);
17293941Svenki if (ret == PICL_SUCCESS) {
17303941Svenki save_volprop(*php, OID_sunPlatBinarySensorCurrent,
17313941Svenki row, VPT_BINSENSOR);
17323941Svenki }
17333941Svenki break;
17343941Svenki
17353941Svenki case PP_EXPECTED:
17363941Svenki ret = add_volatile_prop(nodeh, PICL_PROP_EXPECTED,
17373941Svenki PICL_PTYPE_CHARSTRING, PICL_READ, MAX_TRUTHVAL_LEN,
17383941Svenki read_volprop, NULL, php);
17393941Svenki if (ret == PICL_SUCCESS) {
17403941Svenki save_volprop(*php, OID_sunPlatBinarySensorExpected,
17413941Svenki row, VPT_BINSENSOR);
17423941Svenki }
17433941Svenki break;
17443941Svenki
17455436Sfw157321 case PP_EXPONENT:
17465436Sfw157321 ret = add_volatile_prop(nodeh, PICL_PROP_EXPONENT,
17475436Sfw157321 PICL_PTYPE_INT, PICL_READ, sizeof (int), read_volprop,
17485436Sfw157321 NULL, php);
17495436Sfw157321 if (ret == PICL_SUCCESS) {
17505436Sfw157321 save_volprop(*php, OID_sunPlatNumericSensorExponent,
17515436Sfw157321 row, VPT_NUMSENSOR);
17525436Sfw157321 }
17535436Sfw157321 break;
17545436Sfw157321
17553941Svenki case PP_REPLACEABLE:
17563941Svenki ret = snmp_get_int(hdl, OID_sunPlatCircuitPackReplaceable,
17573941Svenki row, &val, snmp_syserr_p);
17583941Svenki CHECK_LINKRESET_VOID(snmp_syserr_p)
17593941Svenki if ((ret == 0) && (val == ST_TRUE))
17603941Svenki (void) add_void_prop(nodeh, PICL_PROP_IS_REPLACEABLE);
17615723Sfw157321 if (ret == -1)
17625723Sfw157321 log_msg(LOG_ERR, SNMPP_CANT_FETCH_OBJECT_VAL,
17635723Sfw157321 *snmp_syserr_p ? *snmp_syserr_p : ret,
17645723Sfw157321 OID_sunPlatCircuitPackReplaceable, row);
17653941Svenki break;
17663941Svenki
17673941Svenki case PP_HOTSWAPPABLE:
17683941Svenki ret = snmp_get_int(hdl, OID_sunPlatCircuitPackHotSwappable,
17693941Svenki row, &val, snmp_syserr_p);
17703941Svenki CHECK_LINKRESET_VOID(snmp_syserr_p)
17713941Svenki if ((ret == 0) && (val == ST_TRUE))
17723941Svenki (void) add_void_prop(nodeh, PICL_PROP_IS_HOT_SWAPPABLE);
17735723Sfw157321 if (ret == -1)
17745723Sfw157321 log_msg(LOG_ERR, SNMPP_CANT_FETCH_OBJECT_VAL,
17755723Sfw157321 *snmp_syserr_p ? *snmp_syserr_p : ret,
17765723Sfw157321 OID_sunPlatCircuitPackHotSwappable, row);
17773941Svenki break;
17783941Svenki
17793941Svenki case PP_IS_FRU:
17803941Svenki ret = snmp_get_int(hdl, OID_entPhysicalIsFRU, row,
17813941Svenki &val, snmp_syserr_p);
17823941Svenki CHECK_LINKRESET_VOID(snmp_syserr_p)
17833941Svenki if ((ret == 0) && (val == ST_TRUE))
17843941Svenki (void) add_void_prop(nodeh, PICL_PROP_IS_FRU);
17855723Sfw157321 if (ret == -1)
17865723Sfw157321 log_msg(LOG_ERR, SNMPP_CANT_FETCH_OBJECT_VAL,
17875723Sfw157321 *snmp_syserr_p ? *snmp_syserr_p : ret,
17885723Sfw157321 OID_entPhysicalIsFRU, row);
17893941Svenki break;
17903941Svenki
17913941Svenki case PP_HW_REVISION:
17923941Svenki ret = snmp_get_str(hdl, OID_entPhysicalHardwareRev,
17933941Svenki row, &hw_revision, snmp_syserr_p);
17943941Svenki CHECK_LINKRESET_VOID(snmp_syserr_p)
17957382SMichael.Bergknoff@Sun.COM if ((ret == 0) && hw_revision) {
17963941Svenki (void) add_string_prop(nodeh,
17973941Svenki PICL_PROP_HW_REVISION, hw_revision);
17983941Svenki free((void *) hw_revision);
17993941Svenki }
18005723Sfw157321 if (ret == -1)
18015723Sfw157321 log_msg(LOG_ERR, SNMPP_CANT_FETCH_OBJECT_VAL,
18025723Sfw157321 *snmp_syserr_p ? *snmp_syserr_p : ret,
18035723Sfw157321 OID_entPhysicalHardwareRev, row);
18043941Svenki break;
18053941Svenki
18063941Svenki case PP_FW_REVISION:
18073941Svenki ret = snmp_get_str(hdl, OID_entPhysicalFirmwareRev,
18083941Svenki row, &fw_revision, snmp_syserr_p);
18093941Svenki CHECK_LINKRESET_VOID(snmp_syserr_p)
18107382SMichael.Bergknoff@Sun.COM if ((ret == 0) && fw_revision) {
18113941Svenki (void) add_string_prop(nodeh,
18123941Svenki PICL_PROP_FW_REVISION, fw_revision);
18133941Svenki free((void *) fw_revision);
18143941Svenki }
18155723Sfw157321 if (ret == -1)
18165723Sfw157321 log_msg(LOG_ERR, SNMPP_CANT_FETCH_OBJECT_VAL,
18175723Sfw157321 *snmp_syserr_p ? *snmp_syserr_p : ret,
18185723Sfw157321 OID_entPhysicalFirmwareRev, row);
18193941Svenki break;
18203941Svenki
18213941Svenki case PP_MFG_NAME:
18223941Svenki ret = snmp_get_str(hdl, OID_entPhysicalMfgName,
18233941Svenki row, &mfg_name, snmp_syserr_p);
18243941Svenki CHECK_LINKRESET_VOID(snmp_syserr_p)
18257382SMichael.Bergknoff@Sun.COM if ((ret == 0) && mfg_name) {
18263941Svenki (void) add_string_prop(nodeh,
18273941Svenki PICL_PROP_MFG_NAME, mfg_name);
18283941Svenki free((void *) mfg_name);
18293941Svenki }
18305723Sfw157321 if (ret == -1)
18315723Sfw157321 log_msg(LOG_ERR, SNMPP_CANT_FETCH_OBJECT_VAL,
18325723Sfw157321 *snmp_syserr_p ? *snmp_syserr_p : ret,
18335723Sfw157321 OID_entPhysicalMfgName, row);
18343941Svenki break;
18353941Svenki
18363941Svenki case PP_MODEL_NAME:
18373941Svenki ret = snmp_get_str(hdl, OID_entPhysicalModelName,
18383941Svenki row, &model_name, snmp_syserr_p);
18393941Svenki CHECK_LINKRESET_VOID(snmp_syserr_p)
18407382SMichael.Bergknoff@Sun.COM if ((ret == 0) && model_name) {
18413941Svenki (void) add_string_prop(nodeh,
18423941Svenki PICL_PROP_MODEL_NAME, model_name);
18433941Svenki free((void *) model_name);
18443941Svenki }
18455723Sfw157321 if (ret == -1)
18465723Sfw157321 log_msg(LOG_ERR, SNMPP_CANT_FETCH_OBJECT_VAL,
18475723Sfw157321 *snmp_syserr_p ? *snmp_syserr_p : ret,
18485723Sfw157321 OID_entPhysicalModelName, row);
18493941Svenki break;
18503941Svenki
18513941Svenki case PP_DESCRIPTION:
18523941Svenki ret = snmp_get_str(hdl, OID_entPhysicalDescr,
18533941Svenki row, &phys_descr, snmp_syserr_p);
18543941Svenki CHECK_LINKRESET_VOID(snmp_syserr_p)
18557382SMichael.Bergknoff@Sun.COM if ((ret == 0) && phys_descr) {
18564802Sfw157321 (void) add_string_prop(nodeh,
18574802Sfw157321 PICL_PROP_PHYS_DESCRIPTION, phys_descr);
18584802Sfw157321 free((void *) phys_descr);
18593941Svenki }
18605723Sfw157321 if (ret == -1)
18615723Sfw157321 log_msg(LOG_ERR, SNMPP_CANT_FETCH_OBJECT_VAL,
18625723Sfw157321 *snmp_syserr_p ? *snmp_syserr_p : ret,
18635723Sfw157321 OID_entPhysicalDescr, row);
18643941Svenki break;
18653941Svenki
18663941Svenki case PP_LABEL:
18673941Svenki if (label && *label)
18683941Svenki (void) add_string_prop(nodeh, PICL_PROP_LABEL, label);
18693941Svenki break;
18703941Svenki
18713941Svenki case PP_BASE_UNITS:
18723941Svenki ret = snmp_get_int(hdl, OID_sunPlatNumericSensorBaseUnits,
18733941Svenki row, &val, snmp_syserr_p);
18743941Svenki CHECK_LINKRESET_VOID(snmp_syserr_p)
18753941Svenki if ((ret == 0) && (val > 0) && (val < n_baseunits)) {
18763941Svenki (void) add_string_prop(nodeh,
18773941Svenki PICL_PROP_BASE_UNITS, sensor_baseunits[val]);
18783941Svenki }
18795723Sfw157321 if (ret == -1)
18805723Sfw157321 log_msg(LOG_ERR, SNMPP_CANT_FETCH_OBJECT_VAL,
18815723Sfw157321 *snmp_syserr_p ? *snmp_syserr_p : ret,
18825723Sfw157321 OID_sunPlatNumericSensorBaseUnits, row);
18833941Svenki break;
18843941Svenki
18853941Svenki case PP_RATE_UNITS:
18863941Svenki ret = snmp_get_int(hdl, OID_sunPlatNumericSensorRateUnits,
18873941Svenki row, &val, snmp_syserr_p);
18883941Svenki CHECK_LINKRESET_VOID(snmp_syserr_p)
18893941Svenki if ((ret == 0) && (val > 0) && (val < n_rateunits)) {
18903941Svenki (void) add_string_prop(nodeh,
18913941Svenki PICL_PROP_RATE_UNITS, sensor_rateunits[val]);
18923941Svenki }
18935723Sfw157321 if (ret == -1)
18945723Sfw157321 log_msg(LOG_ERR, SNMPP_CANT_FETCH_OBJECT_VAL,
18955723Sfw157321 *snmp_syserr_p ? *snmp_syserr_p : ret,
18965723Sfw157321 OID_sunPlatNumericSensorRateUnits, row);
18973941Svenki break;
18983941Svenki }
18993941Svenki }
19003941Svenki
19017746SKelly.Moyer@Sun.COM /*
19027746SKelly.Moyer@Sun.COM * Initialize the SNMP library's cache refresh subsystem, then periodically
19037746SKelly.Moyer@Sun.COM * process refresh job to prevent cache entries from expiring.
19047746SKelly.Moyer@Sun.COM */
19057746SKelly.Moyer@Sun.COM /*ARGSUSED*/
19067746SKelly.Moyer@Sun.COM static void *
cache_refresher(void * arg)19077746SKelly.Moyer@Sun.COM cache_refresher(void *arg)
19087746SKelly.Moyer@Sun.COM {
19097746SKelly.Moyer@Sun.COM int jobs;
19107746SKelly.Moyer@Sun.COM int next_expiration;
19117746SKelly.Moyer@Sun.COM timestruc_t to;
19127746SKelly.Moyer@Sun.COM hrtime_t cycle_start, cycle_elapsed;
19137746SKelly.Moyer@Sun.COM
19147746SKelly.Moyer@Sun.COM /*
19157746SKelly.Moyer@Sun.COM * Initialize refresh subsystem
19167746SKelly.Moyer@Sun.COM */
19177746SKelly.Moyer@Sun.COM LOGPRINTF("Initializing SNMP refresh subsystem.\n");
19187746SKelly.Moyer@Sun.COM if (snmp_refresh_init() < 0) {
19197746SKelly.Moyer@Sun.COM return ((void *)-1);
19207746SKelly.Moyer@Sun.COM }
19217746SKelly.Moyer@Sun.COM
19227746SKelly.Moyer@Sun.COM (void) mutex_lock(&cache_refresh_lock);
19237746SKelly.Moyer@Sun.COM
19247746SKelly.Moyer@Sun.COM
19257746SKelly.Moyer@Sun.COM for (;;) {
19267746SKelly.Moyer@Sun.COM cycle_start = gethrtime();
19277746SKelly.Moyer@Sun.COM
19287746SKelly.Moyer@Sun.COM /*
19297746SKelly.Moyer@Sun.COM * Process jobs from the snmp cache refresh work queue until one
19307746SKelly.Moyer@Sun.COM * of the following conditions is true:
19317746SKelly.Moyer@Sun.COM * 1) we are told to exit, or
19327746SKelly.Moyer@Sun.COM * 2) we have processed at least as many jobs as recommended by
19337746SKelly.Moyer@Sun.COM * the library, and the next job expiration is at least
19347746SKelly.Moyer@Sun.COM * CACHE_REFRESH_MIN_WINDOW * seconds away.
19357746SKelly.Moyer@Sun.COM */
19367746SKelly.Moyer@Sun.COM jobs = snmp_refresh_get_cycle_hint(CACHE_REFRESH_CYCLE);
19377746SKelly.Moyer@Sun.COM while ((cache_refresh_thr_exit == B_FALSE) && (jobs > 0)) {
19387746SKelly.Moyer@Sun.COM (void) snmp_refresh_process_job();
19397746SKelly.Moyer@Sun.COM jobs--;
19407746SKelly.Moyer@Sun.COM }
19417746SKelly.Moyer@Sun.COM
19427746SKelly.Moyer@Sun.COM next_expiration = snmp_refresh_get_next_expiration();
19437746SKelly.Moyer@Sun.COM while ((cache_refresh_thr_exit == B_FALSE) &&
19447746SKelly.Moyer@Sun.COM ((next_expiration >= 0) &&
19457746SKelly.Moyer@Sun.COM (next_expiration < CACHE_REFRESH_MIN_WINDOW))) {
19467746SKelly.Moyer@Sun.COM (void) snmp_refresh_process_job();
19477746SKelly.Moyer@Sun.COM next_expiration = snmp_refresh_get_next_expiration();
19487746SKelly.Moyer@Sun.COM }
19497746SKelly.Moyer@Sun.COM
19507746SKelly.Moyer@Sun.COM /*
19517746SKelly.Moyer@Sun.COM * As long as we haven't been told to exit, sleep for
19527746SKelly.Moyer@Sun.COM * CACHE_REFRESH_CYCLE seconds minus the amount of time that has
19537746SKelly.Moyer@Sun.COM * elapsed since this cycle started. If the elapsed time is
19547746SKelly.Moyer@Sun.COM * equal to or greater than 60 seconds, skip sleeping entirely.
19557746SKelly.Moyer@Sun.COM */
19567746SKelly.Moyer@Sun.COM cycle_elapsed = (gethrtime() - cycle_start) / NANOSEC;
19577746SKelly.Moyer@Sun.COM if ((cache_refresh_thr_exit == B_FALSE) &&
19587746SKelly.Moyer@Sun.COM (cycle_elapsed < CACHE_REFRESH_CYCLE)) {
19597746SKelly.Moyer@Sun.COM to.tv_sec = CACHE_REFRESH_CYCLE - cycle_elapsed;
19607746SKelly.Moyer@Sun.COM to.tv_nsec = 0;
19617746SKelly.Moyer@Sun.COM (void) cond_reltimedwait(&cache_refresh_cv,
19627746SKelly.Moyer@Sun.COM &cache_refresh_lock, &to);
19637746SKelly.Moyer@Sun.COM }
19647746SKelly.Moyer@Sun.COM
19657746SKelly.Moyer@Sun.COM /*
19667746SKelly.Moyer@Sun.COM * If we have been told to exit, clean up and bail out.
19677746SKelly.Moyer@Sun.COM */
19687746SKelly.Moyer@Sun.COM if (cache_refresh_thr_exit == B_TRUE) {
19697746SKelly.Moyer@Sun.COM snmp_refresh_fini();
19707746SKelly.Moyer@Sun.COM (void) mutex_unlock(&cache_refresh_lock);
19717746SKelly.Moyer@Sun.COM LOGPRINTF("cache_refresher: time to exit\n");
19727746SKelly.Moyer@Sun.COM return (NULL);
19737746SKelly.Moyer@Sun.COM }
19747746SKelly.Moyer@Sun.COM
19757746SKelly.Moyer@Sun.COM }
19767746SKelly.Moyer@Sun.COM
19777746SKelly.Moyer@Sun.COM /*NOTREACHED*/
19787746SKelly.Moyer@Sun.COM return (NULL);
19797746SKelly.Moyer@Sun.COM }
19807746SKelly.Moyer@Sun.COM
19817746SKelly.Moyer@Sun.COM /*
19827746SKelly.Moyer@Sun.COM * Check to see if the cache_refresher thread is running. If it is, signal it
19837746SKelly.Moyer@Sun.COM * to terminate and clean up associated data structures.
19847746SKelly.Moyer@Sun.COM */
19857746SKelly.Moyer@Sun.COM void
cache_refresher_fini(void)19867746SKelly.Moyer@Sun.COM cache_refresher_fini(void)
19877746SKelly.Moyer@Sun.COM {
19887746SKelly.Moyer@Sun.COM /* if the thread isn't running, there is nothing to do */
19897746SKelly.Moyer@Sun.COM if (cache_refresh_thr_exit == B_TRUE)
19907746SKelly.Moyer@Sun.COM return;
19917746SKelly.Moyer@Sun.COM
19927746SKelly.Moyer@Sun.COM /* wake up the cache_refresher thread, tell it to exit */
19937746SKelly.Moyer@Sun.COM (void) mutex_lock(&cache_refresh_lock);
19947746SKelly.Moyer@Sun.COM cache_refresh_thr_exit = B_TRUE;
19957746SKelly.Moyer@Sun.COM (void) cond_signal(&cache_refresh_cv);
19967746SKelly.Moyer@Sun.COM (void) mutex_unlock(&cache_refresh_lock);
19977746SKelly.Moyer@Sun.COM
19987746SKelly.Moyer@Sun.COM /* reap the thread */
19997746SKelly.Moyer@Sun.COM (void) thr_join(cache_refresh_thr_id, NULL, NULL);
20007746SKelly.Moyer@Sun.COM
20017746SKelly.Moyer@Sun.COM /* finish cleanup... */
20027746SKelly.Moyer@Sun.COM (void) cond_destroy(&cache_refresh_cv);
20037746SKelly.Moyer@Sun.COM (void) mutex_destroy(&cache_refresh_lock);
20047746SKelly.Moyer@Sun.COM }
20057746SKelly.Moyer@Sun.COM
20063941Svenki /*VARARGS2*/
20073941Svenki static void
log_msg(int pri,const char * fmt,...)20083941Svenki log_msg(int pri, const char *fmt, ...)
20093941Svenki {
20103941Svenki va_list ap;
20113941Svenki
20123941Svenki va_start(ap, fmt);
20133941Svenki vsyslog(pri, fmt, ap);
20143941Svenki va_end(ap);
20153941Svenki }
20163941Svenki
20173941Svenki #ifdef SNMPPLUGIN_DEBUG
20183941Svenki
20193941Svenki static void
snmpplugin_log_init(void)20203941Svenki snmpplugin_log_init(void)
20213941Svenki {
20223941Svenki (void) mutex_init(&snmpplugin_dbuf_lock, USYNC_THREAD, NULL);
20233941Svenki }
20243941Svenki
20253941Svenki static void
snmpplugin_log(const char * fmt,...)20263941Svenki snmpplugin_log(const char *fmt, ...)
20273941Svenki {
20283941Svenki va_list ap;
20293941Svenki
20303941Svenki (void) mutex_lock(&snmpplugin_dbuf_lock);
20313941Svenki
20323941Svenki va_start(ap, fmt);
20333941Svenki (void) vsnprintf(snmpplugin_lbuf, SNMPPLUGIN_DMAX_LINE, fmt, ap);
20343941Svenki snmpplugin_log_append();
20353941Svenki va_end(ap);
20363941Svenki
20373941Svenki (void) mutex_unlock(&snmpplugin_dbuf_lock);
20383941Svenki }
20393941Svenki
20403941Svenki static void
snmpplugin_log_append(void)20413941Svenki snmpplugin_log_append(void)
20423941Svenki {
20433941Svenki int len;
20443941Svenki
20453941Svenki len = strlen(snmpplugin_lbuf);
20463941Svenki
20473941Svenki if ((snmpplugin_dbuf_curp + len) >=
20483941Svenki (snmpplugin_dbuf + snmpplugin_dbuf_sz)) {
20493941Svenki snmpplugin_dbuf_realloc();
20503941Svenki if (snmpplugin_dbuf == NULL) {
20513941Svenki return;
20523941Svenki }
20533941Svenki }
20543941Svenki
20553941Svenki (void) strcpy(snmpplugin_dbuf_curp, snmpplugin_lbuf);
20563941Svenki snmpplugin_dbuf_curp += len;
20573941Svenki }
20583941Svenki
20593941Svenki static void
snmpplugin_dbuf_realloc(void)20603941Svenki snmpplugin_dbuf_realloc(void)
20613941Svenki {
20623941Svenki char *p;
20633941Svenki size_t offset = 0;
20643941Svenki size_t count;
20653941Svenki
20663941Svenki count = snmpplugin_dbuf_sz + SNMPPLUGIN_DBLOCK_SZ;
20673941Svenki if ((p = (char *)calloc(count, 1)) == NULL) {
20683941Svenki snmpplugin_dbuf_overflow++;
20693941Svenki snmpplugin_dbuf_curp = snmpplugin_dbuf;
20703941Svenki return;
20713941Svenki }
20723941Svenki
20733941Svenki if (snmpplugin_dbuf) {
20743941Svenki offset = snmpplugin_dbuf_curp - snmpplugin_dbuf;
20753941Svenki (void) memcpy(p, snmpplugin_dbuf, snmpplugin_dbuf_sz);
20763941Svenki free(snmpplugin_dbuf);
20773941Svenki }
20783941Svenki
20793941Svenki snmpplugin_dbuf = p;
20803941Svenki snmpplugin_dbuf_sz += SNMPPLUGIN_DBLOCK_SZ;
20813941Svenki
20823941Svenki snmpplugin_dbuf_curp = snmpplugin_dbuf + offset;
20833941Svenki }
20843941Svenki #endif
2085