#include #include #include #include #include "hw_sensors_private.h" static int _sensor_load( void ); static void _sensor_free( void ); static int _sensorAutoUpdate = 0; /* 0 means on-demand caching */ static void _sensor_update_stats( unsigned int, void* ); netsnmp_cache *_sensor_cache = NULL; netsnmp_container *_sensor_container = NULL; static int _sensor_idx = 0; void init_hw_sensors( void ) { if ( _sensor_container ) return; /* Already initialised */ DEBUGMSGTL(("sensors", "Initialise Hardware Sensors module\n")); /* * Define a container to hold the basic list of sensors * The four LM-SENSOR-MIB containers will be created in * the relevant initialisation routine(s) */ _sensor_container = netsnmp_container_find("sensorTable:table_container"); if ( NULL == _sensor_container ) { snmp_log( LOG_ERR, "failed to create container for sensorTable"); return; } netsnmp_sensor_arch_init( ); /* * If we're sampling the sensor information automatically, * then arrange for this to be triggered regularly. * * If we're not sampling these values regularly, * create a suitable cache handler instead. */ if ( _sensorAutoUpdate ) { DEBUGMSGTL(("sensors", "Reloading Hardware Sensors automatically (%d)\n", _sensorAutoUpdate)); snmp_alarm_register( _sensorAutoUpdate, SA_REPEAT, _sensor_update_stats, NULL ); } else { _sensor_cache = netsnmp_cache_create( 5, netsnmp_sensor_load, netsnmp_sensor_free, NULL, 0 ); DEBUGMSGTL(("sensors", "Reloading Hardware Sensors on-demand (%p)\n", _sensor_cache)); } } void shutdown_hw_sensors( void ) { _sensor_free(); } /* * Return the main sensor container */ netsnmp_container *get_sensor_container( void ) { return _sensor_container; } /* * Return the main sensor cache control structure (if defined) */ netsnmp_cache *get_sensor_cache( void ) { return _sensor_cache; } /* * Wrapper routine for automatically updating sensor statistics */ void _sensor_update_stats( unsigned int clientreg, void *data ) { _sensor_free(); _sensor_load(); } /* * Wrapper routine for re-loading sensor statistics on demand */ int netsnmp_sensor_load( netsnmp_cache *cache, void *data ) { return _sensor_load(); } /* * Wrapper routine for releasing expired sensor statistics */ void netsnmp_sensor_free( netsnmp_cache *cache, void *data ) { _sensor_free(); } /* * Architecture-independent processing of loading sensor statistics */ static int _sensor_load( void ) { netsnmp_sensor_arch_load( NULL, NULL ); return 0; } /* * Architecture-independent release of sensor statistics */ static void _sensor_free( void ) { netsnmp_sensor_info *sp; for (sp = CONTAINER_FIRST( _sensor_container ); sp; sp = CONTAINER_NEXT( _sensor_container, sp )) { sp->flags &= ~ NETSNMP_SENSOR_FLAG_ACTIVE; } } /* * Retrieve a sensor entry by name, * or (optionally) insert a new one into the container */ netsnmp_sensor_info * sensor_by_name( const char *name, int create_type ) { netsnmp_sensor_info *sp; DEBUGMSGTL(("sensors:name", "Get sensor entry (%s)\n", name)); /* * Look through the list for a matching entry */ /* .. or use a secondary index container ?? */ for (sp = CONTAINER_FIRST( _sensor_container ); sp; sp = CONTAINER_NEXT( _sensor_container, sp )) { if ( !strcmp( name, sp->name )) return sp; } /* * Not found... */ if ( create_type == NETSNMP_SENSOR_FIND_EXIST ) { DEBUGMSGTL(("sensors:name", "No such sensor entry\n")); return NULL; } /* * ... so let's create a new one, using the type supplied */ sp = SNMP_MALLOC_TYPEDEF( netsnmp_sensor_info ); if ( sp ) { if (strlen(name) >= sizeof(sp->name)) { snmp_log(LOG_ERR, "Sensor name is too large: %s\n", name); free(sp); return NULL; } strlcpy(sp->name, name, sizeof(sp->name)); sp->type = create_type; /* * Set up the index value. * * All this trouble, just for a simple integer. * Surely there must be a better way? */ sp->idx.len = 1; sp->idx.oids = SNMP_MALLOC_TYPEDEF( oid ); sp->idx.oids[0] = ++_sensor_idx; } DEBUGMSGTL(("sensors:name", "Create sensor entry (type = %d, index = %d\n", create_type, _sensor_idx)); CONTAINER_INSERT( _sensor_container, sp ); return sp; }