1 | /**
|
---|
2 | * @file
|
---|
3 | * lwip Private MIB
|
---|
4 | *
|
---|
5 | * @todo create MIB file for this example
|
---|
6 | * @note the lwip enterprise tree root (26381) is owned by the lwIP project.
|
---|
7 | * It is NOT allowed to allocate new objects under this ID (26381) without our,
|
---|
8 | * the lwip developers, permission!
|
---|
9 | *
|
---|
10 | * Please apply for your own ID with IANA: http://www.iana.org/numbers.html
|
---|
11 | *
|
---|
12 | * lwip OBJECT IDENTIFIER ::= { enterprises 26381 }
|
---|
13 | * example OBJECT IDENTIFIER ::= { lwip 1 }
|
---|
14 | */
|
---|
15 |
|
---|
16 | /*
|
---|
17 | * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands.
|
---|
18 | * All rights reserved.
|
---|
19 | *
|
---|
20 | * Redistribution and use in source and binary forms, with or without modification,
|
---|
21 | * are permitted provided that the following conditions are met:
|
---|
22 | *
|
---|
23 | * 1. Redistributions of source code must retain the above copyright notice,
|
---|
24 | * this list of conditions and the following disclaimer.
|
---|
25 | * 2. Redistributions in binary form must reproduce the above copyright notice,
|
---|
26 | * this list of conditions and the following disclaimer in the documentation
|
---|
27 | * and/or other materials provided with the distribution.
|
---|
28 | * 3. The name of the author may not be used to endorse or promote products
|
---|
29 | * derived from this software without specific prior written permission.
|
---|
30 | *
|
---|
31 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
---|
32 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
---|
33 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
---|
34 | * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
---|
35 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
---|
36 | * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
---|
37 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
---|
38 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
---|
39 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
---|
40 | * OF SUCH DAMAGE.
|
---|
41 | *
|
---|
42 | * Author: Christiaan Simons <christiaan.simons@axon.tv>
|
---|
43 | */
|
---|
44 |
|
---|
45 | #include "private_mib.h"
|
---|
46 |
|
---|
47 | #if LWIP_SNMP
|
---|
48 |
|
---|
49 | /** Directory where the sensor files are */
|
---|
50 | #define SENSORS_DIR "w:\\sensors"
|
---|
51 | /** Set to 1 to read sensor values from files (in directory defined by SENSORS_DIR) */
|
---|
52 | #define SENSORS_USE_FILES 0
|
---|
53 | /** Set to 1 to search sensor files at startup (in directory defined by SENSORS_DIR) */
|
---|
54 | #define SENSORS_SEARCH_FILES 0
|
---|
55 |
|
---|
56 | #if SENSORS_SEARCH_FILES
|
---|
57 | #include <sys/stat.h>
|
---|
58 | #include <sys/types.h>
|
---|
59 | #include <unistd.h>
|
---|
60 | #include <fcntl.h>
|
---|
61 | #include <dirent.h>
|
---|
62 | #endif /* SENSORS_SEARCH_FILES */
|
---|
63 |
|
---|
64 | #include <string.h>
|
---|
65 | #include <stdio.h>
|
---|
66 |
|
---|
67 | #include "lwip/apps/snmp_table.h"
|
---|
68 | #include "lwip/apps/snmp_scalar.h"
|
---|
69 |
|
---|
70 | #if !SENSORS_USE_FILES || !SENSORS_SEARCH_FILES
|
---|
71 | /** When not using & searching files, defines the number of sensors */
|
---|
72 | #define SENSOR_COUNT 4
|
---|
73 | #endif /* !SENSORS_USE_FILES || !SENSORS_SEARCH_FILES */
|
---|
74 |
|
---|
75 | /*
|
---|
76 | This example presents a table for a few (at most 10) sensors.
|
---|
77 | Sensor detection takes place at initialization (once only).
|
---|
78 | Sensors may and can not be added or removed after agent
|
---|
79 | has started. Note this is only a limitation of this crude example,
|
---|
80 | the agent does support dynamic object insertions and removals.
|
---|
81 |
|
---|
82 | You'll need to manually create a directory called "sensors" and
|
---|
83 | a few single line text files with an integer temperature value.
|
---|
84 | The files must be called [0..9].txt.
|
---|
85 |
|
---|
86 | ./sensors/0.txt [content: 20]
|
---|
87 | ./sensors/3.txt [content: 75]
|
---|
88 |
|
---|
89 | The sensor values may be changed in runtime by editing the
|
---|
90 | text files in the "sensors" directory.
|
---|
91 | */
|
---|
92 |
|
---|
93 | #define SENSOR_MAX 10
|
---|
94 | #define SENSOR_NAME_LEN 20
|
---|
95 |
|
---|
96 | struct sensor_inf
|
---|
97 | {
|
---|
98 | u8_t num;
|
---|
99 |
|
---|
100 | char file[SENSOR_NAME_LEN + 1];
|
---|
101 |
|
---|
102 | #if !SENSORS_USE_FILES
|
---|
103 | /** When not using files, contains the value of the sensor */
|
---|
104 | s32_t value;
|
---|
105 | #endif /* !SENSORS_USE_FILES */
|
---|
106 | };
|
---|
107 |
|
---|
108 | static struct sensor_inf sensors[SENSOR_MAX];
|
---|
109 |
|
---|
110 | static s16_t sensor_count_get_value(struct snmp_node_instance* instance, void* value);
|
---|
111 | static snmp_err_t sensor_table_get_cell_instance(const u32_t* column, const u32_t* row_oid, u8_t row_oid_len, struct snmp_node_instance* cell_instance);
|
---|
112 | static snmp_err_t sensor_table_get_next_cell_instance(const u32_t* column, struct snmp_obj_id* row_oid, struct snmp_node_instance* cell_instance);
|
---|
113 | static s16_t sensor_table_get_value(struct snmp_node_instance* instance, void* value);
|
---|
114 | static snmp_err_t sensor_table_set_value(struct snmp_node_instance* instance, u16_t len, void *value);
|
---|
115 |
|
---|
116 | /* sensorentry .1.3.6.1.4.1.26381.1.1.1 (.level0.level1)
|
---|
117 | where level 0 is the table column (temperature/file name)
|
---|
118 | and level 1 the table row (sensor index) */
|
---|
119 | static const struct snmp_table_col_def sensor_table_columns[] = {
|
---|
120 | { 1, SNMP_ASN1_TYPE_INTEGER, SNMP_NODE_INSTANCE_READ_WRITE },
|
---|
121 | { 2, SNMP_ASN1_TYPE_OCTET_STRING, SNMP_NODE_INSTANCE_READ_ONLY }
|
---|
122 | };
|
---|
123 |
|
---|
124 | /* sensortable .1.3.6.1.4.1.26381.1.1 */
|
---|
125 | static const struct snmp_table_node sensor_table = SNMP_TABLE_CREATE(
|
---|
126 | 1, sensor_table_columns,
|
---|
127 | sensor_table_get_cell_instance, sensor_table_get_next_cell_instance,
|
---|
128 | sensor_table_get_value, snmp_set_test_ok, sensor_table_set_value);
|
---|
129 |
|
---|
130 | /* sensorcount .1.3.6.1.4.1.26381.1.2 */
|
---|
131 | static const struct snmp_scalar_node sensor_count = SNMP_SCALAR_CREATE_NODE_READONLY(
|
---|
132 | 2, SNMP_ASN1_TYPE_INTEGER, sensor_count_get_value);
|
---|
133 |
|
---|
134 | /* example .1.3.6.1.4.1.26381.1 */
|
---|
135 | static const struct snmp_node* const example_nodes[] = {
|
---|
136 | &sensor_table.node.node,
|
---|
137 | &sensor_count.node.node
|
---|
138 | };
|
---|
139 | static const struct snmp_tree_node example_node = SNMP_CREATE_TREE_NODE(1, example_nodes);
|
---|
140 |
|
---|
141 | static const u32_t prvmib_base_oid[] = { 1,3,6,1,4,1,26381,1 };
|
---|
142 | const struct snmp_mib mib_private = SNMP_MIB_CREATE(prvmib_base_oid, &example_node.node);
|
---|
143 |
|
---|
144 | #if 0
|
---|
145 | /* for reference: we could also have expressed it like this: */
|
---|
146 |
|
---|
147 | /* lwip .1.3.6.1.4.1.26381 */
|
---|
148 | static const struct snmp_node* const lwip_nodes[] = {
|
---|
149 | &example_node.node
|
---|
150 | };
|
---|
151 | static const struct snmp_tree_node lwip_node = SNMP_CREATE_TREE_NODE(26381, lwip_nodes);
|
---|
152 |
|
---|
153 | /* enterprises .1.3.6.1.4.1 */
|
---|
154 | static const struct snmp_node* const enterprises_nodes[] = {
|
---|
155 | &lwip_node.node
|
---|
156 | };
|
---|
157 | static const struct snmp_tree_node enterprises_node = SNMP_CREATE_TREE_NODE(1, enterprises_nodes);
|
---|
158 |
|
---|
159 | /* private .1.3.6.1.4 */
|
---|
160 | static const struct snmp_node* const private_nodes[] = {
|
---|
161 | &enterprises_node.node
|
---|
162 | };
|
---|
163 | static const struct snmp_tree_node private_root = SNMP_CREATE_TREE_NODE(4, private_nodes);
|
---|
164 |
|
---|
165 | static const u32_t prvmib_base_oid[] = { 1,3,6,1,4 };
|
---|
166 | const struct snmp_mib mib_private = SNMP_MIB_CREATE(prvmib_base_oid, &private_root.node);
|
---|
167 | #endif
|
---|
168 |
|
---|
169 | /**
|
---|
170 | * Initialises this private MIB before use.
|
---|
171 | * @see main.c
|
---|
172 | */
|
---|
173 | void
|
---|
174 | lwip_privmib_init(void)
|
---|
175 | {
|
---|
176 | #if SENSORS_USE_FILES && SENSORS_SEARCH_FILES
|
---|
177 | char *buf, *ebuf, *cp;
|
---|
178 | size_t bufsize;
|
---|
179 | int nbytes;
|
---|
180 | struct stat sb;
|
---|
181 | struct dirent *dp;
|
---|
182 | int fd;
|
---|
183 | #else /* SENSORS_USE_FILES && SENSORS_SEARCH_FILES */
|
---|
184 | u8_t i;
|
---|
185 | #endif /* SENSORS_USE_FILES && SENSORS_SEARCH_FILES */
|
---|
186 |
|
---|
187 | memset(sensors, 0, sizeof(sensors));
|
---|
188 |
|
---|
189 | printf("SNMP private MIB start, detecting sensors.\n");
|
---|
190 |
|
---|
191 | #if SENSORS_USE_FILES && SENSORS_SEARCH_FILES
|
---|
192 | /* look for sensors in sensors directory */
|
---|
193 | fd = open(SENSORS_DIR, O_RDONLY);
|
---|
194 | if (fd > -1)
|
---|
195 | {
|
---|
196 | fstat(fd, &sb);
|
---|
197 | bufsize = sb.st_size;
|
---|
198 | if (bufsize < (size_t)sb.st_blksize)
|
---|
199 | {
|
---|
200 | bufsize = sb.st_blksize;
|
---|
201 | }
|
---|
202 | buf = (char*)malloc(bufsize);
|
---|
203 | if (buf != NULL)
|
---|
204 | {
|
---|
205 | do
|
---|
206 | {
|
---|
207 | long base;
|
---|
208 |
|
---|
209 | nbytes = getdirentries(fd, buf, bufsize, &base);
|
---|
210 | if (nbytes > 0)
|
---|
211 | {
|
---|
212 | ebuf = buf + nbytes;
|
---|
213 | cp = buf;
|
---|
214 | while (cp < ebuf)
|
---|
215 | {
|
---|
216 | dp = (struct dirent *)cp;
|
---|
217 | if (lwip_isdigit(dp->d_name[0]))
|
---|
218 | {
|
---|
219 | unsigned char idx = dp->d_name[0] - '0';
|
---|
220 |
|
---|
221 | sensors[idx].num = idx+1;
|
---|
222 | strncpy(&sensors[idx].file[0], dp->d_name, SENSOR_NAME_LEN);
|
---|
223 | printf("%s\n", sensors[idx].file);
|
---|
224 | }
|
---|
225 | cp += dp->d_reclen;
|
---|
226 | }
|
---|
227 | }
|
---|
228 | }
|
---|
229 | while (nbytes > 0);
|
---|
230 |
|
---|
231 | free(buf);
|
---|
232 | }
|
---|
233 | close(fd);
|
---|
234 | }
|
---|
235 | #else /* SENSORS_USE_FILES && SENSORS_SEARCH_FILES */
|
---|
236 | for (i = 0; i < SENSOR_COUNT; i++) {
|
---|
237 | sensors[i].num = (u8_t)(i + 1);
|
---|
238 | snprintf(sensors[i].file, sizeof(sensors[i].file), "%d.txt", i);
|
---|
239 |
|
---|
240 | #if !SENSORS_USE_FILES
|
---|
241 | /* initialize sensor value to != zero */
|
---|
242 | sensors[i].value = 11 * (i+1);
|
---|
243 | #endif /* !SENSORS_USE_FILES */
|
---|
244 | }
|
---|
245 | #endif /* SENSORS_USE_FILE && SENSORS_SEARCH_FILES */
|
---|
246 | }
|
---|
247 |
|
---|
248 | /* sensorcount .1.3.6.1.4.1.26381.1.2 */
|
---|
249 | static s16_t
|
---|
250 | sensor_count_get_value(struct snmp_node_instance* instance, void* value)
|
---|
251 | {
|
---|
252 | size_t count = 0;
|
---|
253 | u32_t *uint_ptr = (u32_t*)value;
|
---|
254 |
|
---|
255 | LWIP_UNUSED_ARG(instance);
|
---|
256 |
|
---|
257 | for(count=0; count<LWIP_ARRAYSIZE(sensors); count++) {
|
---|
258 | if(sensors[count].num == 0) {
|
---|
259 | *uint_ptr = (u32_t)count;
|
---|
260 | return sizeof(*uint_ptr);
|
---|
261 | }
|
---|
262 | }
|
---|
263 |
|
---|
264 | return 0;
|
---|
265 | }
|
---|
266 |
|
---|
267 | /* sensortable .1.3.6.1.4.1.26381.1.1 */
|
---|
268 | /* list of allowed value ranges for incoming OID */
|
---|
269 | static const struct snmp_oid_range sensor_table_oid_ranges[] = {
|
---|
270 | { 1, SENSOR_MAX+1 }
|
---|
271 | };
|
---|
272 |
|
---|
273 | static snmp_err_t
|
---|
274 | sensor_table_get_cell_instance(const u32_t* column, const u32_t* row_oid, u8_t row_oid_len, struct snmp_node_instance* cell_instance)
|
---|
275 | {
|
---|
276 | u32_t sensor_num;
|
---|
277 | size_t i;
|
---|
278 |
|
---|
279 | LWIP_UNUSED_ARG(column);
|
---|
280 |
|
---|
281 | /* check if incoming OID length and if values are in plausible range */
|
---|
282 | if(!snmp_oid_in_range(row_oid, row_oid_len, sensor_table_oid_ranges, LWIP_ARRAYSIZE(sensor_table_oid_ranges))) {
|
---|
283 | return SNMP_ERR_NOSUCHINSTANCE;
|
---|
284 | }
|
---|
285 |
|
---|
286 | /* get sensor index from incoming OID */
|
---|
287 | sensor_num = row_oid[0];
|
---|
288 |
|
---|
289 | /* find sensor with index */
|
---|
290 | for(i=0; i<LWIP_ARRAYSIZE(sensors); i++) {
|
---|
291 | if(sensors[i].num != 0) {
|
---|
292 | if(sensors[i].num == sensor_num) {
|
---|
293 | /* store sensor index for subsequent operations (get/test/set) */
|
---|
294 | cell_instance->reference.u32 = (u32_t)i;
|
---|
295 | return SNMP_ERR_NOERROR;
|
---|
296 | }
|
---|
297 | }
|
---|
298 | }
|
---|
299 |
|
---|
300 | /* not found */
|
---|
301 | return SNMP_ERR_NOSUCHINSTANCE;
|
---|
302 | }
|
---|
303 |
|
---|
304 | static snmp_err_t
|
---|
305 | sensor_table_get_next_cell_instance(const u32_t* column, struct snmp_obj_id* row_oid, struct snmp_node_instance* cell_instance)
|
---|
306 | {
|
---|
307 | size_t i;
|
---|
308 | struct snmp_next_oid_state state;
|
---|
309 | u32_t result_temp[LWIP_ARRAYSIZE(sensor_table_oid_ranges)];
|
---|
310 |
|
---|
311 | LWIP_UNUSED_ARG(column);
|
---|
312 |
|
---|
313 | /* init struct to search next oid */
|
---|
314 | snmp_next_oid_init(&state, row_oid->id, row_oid->len, result_temp, LWIP_ARRAYSIZE(sensor_table_oid_ranges));
|
---|
315 |
|
---|
316 | /* iterate over all possible OIDs to find the next one */
|
---|
317 | for(i=0; i<LWIP_ARRAYSIZE(sensors); i++) {
|
---|
318 | if(sensors[i].num != 0) {
|
---|
319 | u32_t test_oid[LWIP_ARRAYSIZE(sensor_table_oid_ranges)];
|
---|
320 |
|
---|
321 | test_oid[0] = sensors[i].num;
|
---|
322 |
|
---|
323 | /* check generated OID: is it a candidate for the next one? */
|
---|
324 | snmp_next_oid_check(&state, test_oid, LWIP_ARRAYSIZE(sensor_table_oid_ranges), (void*)i);
|
---|
325 | }
|
---|
326 | }
|
---|
327 |
|
---|
328 | /* did we find a next one? */
|
---|
329 | if(state.status == SNMP_NEXT_OID_STATUS_SUCCESS) {
|
---|
330 | snmp_oid_assign(row_oid, state.next_oid, state.next_oid_len);
|
---|
331 | /* store sensor index for subsequent operations (get/test/set) */
|
---|
332 | cell_instance->reference.u32 = LWIP_CONST_CAST(u32_t, state.reference);
|
---|
333 | return SNMP_ERR_NOERROR;
|
---|
334 | }
|
---|
335 |
|
---|
336 | /* not found */
|
---|
337 | return SNMP_ERR_NOSUCHINSTANCE;
|
---|
338 | }
|
---|
339 |
|
---|
340 | static s16_t
|
---|
341 | sensor_table_get_value(struct snmp_node_instance* instance, void* value)
|
---|
342 | {
|
---|
343 | u32_t i = instance->reference.u32;
|
---|
344 | s32_t *temperature = (s32_t *)value;
|
---|
345 |
|
---|
346 | switch (SNMP_TABLE_GET_COLUMN_FROM_OID(instance->instance_oid.id))
|
---|
347 | {
|
---|
348 | case 1: /* sensor value */
|
---|
349 | #if SENSORS_USE_FILES
|
---|
350 | FILE* sensf;
|
---|
351 | char senspath[sizeof(SENSORS_DIR)+1+SENSOR_NAME_LEN+1] = SENSORS_DIR"/";
|
---|
352 |
|
---|
353 | strncpy(&senspath[sizeof(SENSORS_DIR)],
|
---|
354 | sensors[i].file,
|
---|
355 | SENSOR_NAME_LEN);
|
---|
356 | sensf = fopen(senspath,"r");
|
---|
357 | if (sensf != NULL)
|
---|
358 | {
|
---|
359 | fscanf(sensf,"%"S32_F,temperature);
|
---|
360 | fclose(sensf);
|
---|
361 | }
|
---|
362 | #else /* SENSORS_USE_FILES */
|
---|
363 | *temperature = sensors[i].value;
|
---|
364 | #endif /* SENSORS_USE_FILES */
|
---|
365 | return sizeof(s32_t);
|
---|
366 | case 2: /* file name */
|
---|
367 | MEMCPY(value, sensors[i].file, strlen(sensors[i].file));
|
---|
368 | return (s16_t)strlen(sensors[i].file);
|
---|
369 | default:
|
---|
370 | return 0;
|
---|
371 | }
|
---|
372 | }
|
---|
373 |
|
---|
374 | static snmp_err_t
|
---|
375 | sensor_table_set_value(struct snmp_node_instance* instance, u16_t len, void *value)
|
---|
376 | {
|
---|
377 | u32_t i = instance->reference.u32;
|
---|
378 | s32_t *temperature = (s32_t *)value;
|
---|
379 | #if SENSORS_USE_FILES
|
---|
380 | FILE* sensf;
|
---|
381 | char senspath[sizeof(SENSORS_DIR)+1+SENSOR_NAME_LEN+1] = SENSORS_DIR"/";
|
---|
382 |
|
---|
383 | strncpy(&senspath[sizeof(SENSORS_DIR)],
|
---|
384 | sensors[i].file,
|
---|
385 | SENSOR_NAME_LEN);
|
---|
386 | sensf = fopen(senspath, "w");
|
---|
387 | if (sensf != NULL)
|
---|
388 | {
|
---|
389 | fprintf(sensf, "%"S32_F, *temperature);
|
---|
390 | fclose(sensf);
|
---|
391 | }
|
---|
392 | #else /* SENSORS_USE_FILES */
|
---|
393 | sensors[i].value = *temperature;
|
---|
394 | #endif /* SENSORS_USE_FILES */
|
---|
395 |
|
---|
396 | LWIP_UNUSED_ARG(len);
|
---|
397 |
|
---|
398 | return SNMP_ERR_NOERROR;
|
---|
399 | }
|
---|
400 |
|
---|
401 | #endif /* LWIP_SNMP */
|
---|