#ifdef HAVE_INTTYPES_H #include #endif #include #include #include #include #include "hardware/sensors/hw_sensors.h" #include "ucd-snmp/lmsensorsMib.h" netsnmp_container *sensorContainer = NULL; static void initialize_lmSensorsTable(const char *tableName, const oid *tableOID, netsnmp_container_op *filter, int mult); static int _sensor_filter_temp( netsnmp_container *c, const void *v ); static int _sensor_filter_fan( netsnmp_container *c, const void *v ); static int _sensor_filter_volt( netsnmp_container *c, const void *v ); static int _sensor_filter_misc( netsnmp_container *c, const void *v ); static const oid lmTempSensorsTable_oid[] = {1,3,6,1,4,1,2021,13,16,2}; static const oid lmFanSensorsTable_oid[] = {1,3,6,1,4,1,2021,13,16,3}; static const oid lmVoltSensorsTable_oid[] = {1,3,6,1,4,1,2021,13,16,4}; static const oid lmMiscSensorsTable_oid[] = {1,3,6,1,4,1,2021,13,16,5}; /* All the tables have the same length root OID */ const size_t lmSensorsTables_oid_len = OID_LENGTH(lmMiscSensorsTable_oid); /* Initialise the LM Sensors MIB module */ void init_lmsensorsMib(void) { DEBUGMSGTL(("ucd-snmp/lmsensorsMib","Initializing LM-SENSORS-MIB tables\n")); /* * Initialise the four LM-SENSORS-MIB tables * * They are almost identical, so we can use the same registration code. */ initialize_lmSensorsTable( "lmTempSensorsTable", lmTempSensorsTable_oid, _sensor_filter_temp, 1000 ); /* MIB asks for mC */ initialize_lmSensorsTable( "lmFanSensorsTable", lmFanSensorsTable_oid, _sensor_filter_fan, 1); initialize_lmSensorsTable( "lmVoltSensorsTable", lmVoltSensorsTable_oid, _sensor_filter_volt, 1000 ); /* MIB asks for mV */ initialize_lmSensorsTable( "lmMiscSensorsTable", lmMiscSensorsTable_oid, _sensor_filter_misc, 1 ); } /* * Common initialisation code, used for setting up all four tables */ void initialize_lmSensorsTable(const char *tableName, const oid *tableOID, netsnmp_container_op *filter, int mult ) { netsnmp_handler_registration *reg; netsnmp_table_registration_info *table_info; netsnmp_cache *cache; netsnmp_container *container; /* * Ensure the HAL sensors module has been initialised, * and retrieve the main sensors container. * This table will then be registered using a filter on this container. */ sensorContainer = get_sensor_container(); if ( !sensorContainer ) { init_hw_sensors( ); sensorContainer = get_sensor_container(); } container = netsnmp_container_find("sensorTable:table_container"); container->insert_filter = filter; netsnmp_container_add_index( sensorContainer, container ); /* * Create a basic registration structure for the table */ reg = netsnmp_create_handler_registration( tableName, lmSensorsTables_handler, tableOID, lmSensorsTables_oid_len, HANDLER_CAN_RONLY ); /* * Register the table using the filtered container * Include an indicator of any scaling to be applied to the sensor value */ reg->my_reg_void = (void *)(uintptr_t)mult; table_info = SNMP_MALLOC_TYPEDEF( netsnmp_table_registration_info ); netsnmp_table_helper_add_indexes(table_info, ASN_INTEGER, 0); table_info->min_column = COLUMN_LMSENSORS_INDEX; table_info->max_column = COLUMN_LMSENSORS_VALUE; if (netsnmp_container_table_register(reg, table_info, container, 0) != SNMPERR_SUCCESS) { snmp_log(LOG_ERR, "Failed to register the sensors container table\n"); return; } /* * If the HAL sensors module was configured as an on-demand caching * module (rather than being automatically loaded regularly), * then ensure this table makes use of that cache. */ cache = get_sensor_cache(); if ( cache ) { netsnmp_inject_handler_before( reg, netsnmp_cache_handler_get( cache ), "table_container"); } } /* * Container filters for the four tables * * Used to ensure that sensor entries appear in the appropriate table. */ int _sensor_filter_temp( netsnmp_container *c, const void *v ) { const netsnmp_sensor_info *sp = (const netsnmp_sensor_info *)v; /* Only matches temperature sensors */ return (( sp->type == NETSNMP_SENSOR_TYPE_TEMPERATURE ) ? 0 : 1 ); } int _sensor_filter_fan( netsnmp_container *c, const void *v ) { const netsnmp_sensor_info *sp = (const netsnmp_sensor_info *)v; /* Only matches fan sensors */ return (( sp->type == NETSNMP_SENSOR_TYPE_RPM ) ? 0 : 1 ); } int _sensor_filter_volt( netsnmp_container *c, const void *v ) { const netsnmp_sensor_info *sp = (const netsnmp_sensor_info *)v; /* Only matches voltage sensors (AC or DC) */ return ((( sp->type == NETSNMP_SENSOR_TYPE_VOLTAGE_DC ) || ( sp->type == NETSNMP_SENSOR_TYPE_VOLTAGE_AC )) ? 0 : 1 ); } int _sensor_filter_misc( netsnmp_container *c, const void *v ) { const netsnmp_sensor_info *sp = (const netsnmp_sensor_info *)v; /* Matches everything except temperature, fan or voltage sensors */ return ((( sp->type == NETSNMP_SENSOR_TYPE_TEMPERATURE ) || ( sp->type == NETSNMP_SENSOR_TYPE_RPM ) || ( sp->type == NETSNMP_SENSOR_TYPE_VOLTAGE_DC ) || ( sp->type == NETSNMP_SENSOR_TYPE_VOLTAGE_AC )) ? 1 : 0 ); } /* * Handle requests for any of the four lmXxxxSensorsTables * * This is possible because all the table share the * same structure and behaviour. */ int lmSensorsTables_handler( netsnmp_mib_handler *handler, netsnmp_handler_registration *reginfo, netsnmp_agent_request_info *reqinfo, netsnmp_request_info *requests) { netsnmp_request_info *request; netsnmp_table_request_info *table_info; netsnmp_sensor_info *sensor_info; int mult = (uintptr_t)reginfo->my_reg_void; DEBUGMSGTL(( "ucd-snmp/lmsensorsMib","lmSensorsTables_handler - root: ")); DEBUGMSGOID(("ucd-snmp/lmsensorsMib", reginfo->rootoid, reginfo->rootoid_len)); DEBUGMSG(( "ucd-snmp/lmsensorsMib",", mode %d\n", reqinfo->mode )); /* * This is a read-only table, so we only need to handle GET requests. * (The container helper converts GETNEXT->GET requests automatically). */ switch (reqinfo->mode) { case MODE_GET: for (request=requests; request; request=request->next) { sensor_info = (netsnmp_sensor_info *) netsnmp_container_table_extract_context(request); if ( !sensor_info ) { netsnmp_set_request_error(reqinfo, request, SNMP_NOSUCHINSTANCE); continue; } table_info = netsnmp_extract_table_info(request); switch (table_info->colnum) { case COLUMN_LMSENSORS_INDEX: snmp_set_var_typed_integer( request->requestvb, ASN_INTEGER, sensor_info->idx.oids[0]); break; case COLUMN_LMSENSORS_DEVICE: if ( sensor_info->descr[0] != '\0' ) { snmp_set_var_typed_value( request->requestvb, ASN_OCTET_STR, sensor_info->descr, strlen(sensor_info->descr)); } else { snmp_set_var_typed_value( request->requestvb, ASN_OCTET_STR, sensor_info->name, strlen(sensor_info->name)); } break; case COLUMN_LMSENSORS_VALUE: /* Multiply the value by the appropriate scaling factor for this table */ snmp_set_var_typed_integer( request->requestvb, ASN_GAUGE, (int)(mult*sensor_info->value)); break; default: netsnmp_set_request_error(reqinfo, request, SNMP_NOSUCHOBJECT); break; } } break; } return SNMP_ERR_NOERROR; }