summaryrefslogtreecommitdiff
path: root/agent/mibgroup/ucd-snmp/lmsensorsMib.c
blob: 5a506970b62c662e0ee1109f03e563574b1155a9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
#include <net-snmp/net-snmp-config.h>
#include <net-snmp/net-snmp-includes.h>
#include <net-snmp/agent/net-snmp-agent-includes.h>
#include <net-snmp/agent/hardware/sensors.h>
#include "hardware/sensors/hw_sensors.h"
#include "ucd-snmp/lmsensorsMib.h"

netsnmp_container *sensorContainer = NULL;

void initialize_lmSensorsTable(const char *tableName, const oid *tableOID,
                               netsnmp_container_op *filter, int mult );

int _sensor_filter_temp( netsnmp_container *c, const void *v );
int _sensor_filter_fan(  netsnmp_container *c, const void *v );
int _sensor_filter_volt( netsnmp_container *c, const void *v );
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 *)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;
    netsnmp_container_table_register( reg, table_info, container, 0 );

    /*
     * 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  = (int)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;
}