[457] | 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 */
|
---|