/** * @file * lwip Private MIB * * @todo create MIB file for this example * @note the lwip enterprise tree root (26381) is owned by the lwIP project. * It is NOT allowed to allocate new objects under this ID (26381) without our, * the lwip developers, permission! * * Please apply for your own ID with IANA: http://www.iana.org/numbers.html * * lwip OBJECT IDENTIFIER ::= { enterprises 26381 } * example OBJECT IDENTIFIER ::= { lwip 1 } */ /* * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE. * * Author: Christiaan Simons */ #include "private_mib.h" #if LWIP_SNMP /** Directory where the sensor files are */ #define SENSORS_DIR "w:\\sensors" /** Set to 1 to read sensor values from files (in directory defined by SENSORS_DIR) */ #define SENSORS_USE_FILES 0 /** Set to 1 to search sensor files at startup (in directory defined by SENSORS_DIR) */ #define SENSORS_SEARCH_FILES 0 #if SENSORS_SEARCH_FILES #include #include #include #include #include #include #endif /* SENSORS_SEARCH_FILES */ #include #include #include "lwip/snmp_msg.h" #include "lwip/snmp_asn1.h" #if !SENSORS_USE_FILES || !SENSORS_SEARCH_FILES /** When not using & searching files, defines the number of sensors */ #define SENSOR_COUNT 2 #endif /* !SENSORS_USE_FILES || !SENSORS_SEARCH_FILES */ #if !SENSORS_USE_FILES /** When not using files, contains the values of the sensors */ s32_t sensor_values[SENSOR_COUNT]; #endif /* !SENSORS_USE_FILES */ /* This example presents a table for a few (at most 10) sensors. Sensor detection takes place at initialization (once only). Sensors may and can not be added or removed after agent has started. Note this is only a limitation of this crude example, the agent does support dynamic object insertions and removals. You'll need to manually create a directory called "sensors" and a few single line text files with an integer temperature value. The files must be called [0..9].txt. ./sensors/0.txt [content: 20] ./sensors/3.txt [content: 75] The sensor values may be changed in runtime by editing the text files in the "sensors" directory. */ #define SENSOR_MAX 10 #define SENSOR_NAME_LEN 20 struct sensor_inf { char sensor_files[SENSOR_MAX][SENSOR_NAME_LEN + 1]; /* (Sparse) list of sensors (table index), the actual "hot insertion" is done in lwip_privmib_init() */ struct mib_list_rootnode sensor_list_rn; }; struct sensor_inf sensor_addr_inf = { {{0}}, { NULL, NULL, NULL, NULL, MIB_NODE_LR, 0, NULL, NULL, 0 } }; static u16_t sensorentry_length(void* addr_inf, u8_t level); static s32_t sensorentry_idcmp(void* addr_inf, u8_t level, u16_t idx, s32_t sub_id); static void sensorentry_get_subid(void* addr_inf, u8_t level, u16_t idx, s32_t *sub_id); static void sensorentry_get_object_def_q(void* addr_inf, u8_t rid, u8_t ident_len, s32_t *ident); static void sensorentry_get_object_def_a(u8_t rid, u8_t ident_len, s32_t *ident, struct obj_def *od); static void sensorentry_get_object_def_pc(u8_t rid, u8_t ident_len, s32_t *ident); static void sensorentry_get_value_q(u8_t rid, struct obj_def *od); static void sensorentry_get_value_a(u8_t rid, struct obj_def *od, u16_t len, void *value); static void sensorentry_get_value_pc(u8_t rid, struct obj_def *od); static void sensorentry_set_test_q(u8_t rid, struct obj_def *od); static u8_t sensorentry_set_test_a(u8_t rid, struct obj_def *od, u16_t len, void *value); static void sensorentry_set_test_pc(u8_t rid, struct obj_def *od); static void sensorentry_set_value_q(u8_t rid, struct obj_def *od, u16_t len, void *value); static void sensorentry_set_value_a(u8_t rid, struct obj_def *od, u16_t len, void *value); static void sensorentry_set_value_pc(u8_t rid, struct obj_def *od); /* sensorentry .1.3.6.1.4.1.26381.1.1.1 (.level0.level1) where level 0 is the object identifier (temperature) and level 1 the index */ static struct mib_external_node sensorentry = { &noleafs_get_object_def, &noleafs_get_value, &noleafs_set_test, &noleafs_set_value, MIB_NODE_EX, 0, &sensor_addr_inf, /* 0 tree_levels (empty table) at power-up, 2 when one or more sensors are detected */ 0, &sensorentry_length, &sensorentry_idcmp, &sensorentry_get_subid, &sensorentry_get_object_def_q, &sensorentry_get_value_q, &sensorentry_set_test_q, &sensorentry_set_value_q, &sensorentry_get_object_def_a, &sensorentry_get_value_a, &sensorentry_set_test_a, &sensorentry_set_value_a, &sensorentry_get_object_def_pc, &sensorentry_get_value_pc, &sensorentry_set_test_pc, &sensorentry_set_value_pc }; /* sensortable .1.3.6.1.4.1.26381.1.1 */ static const s32_t sensortable_ids[1] = { 1 }; static struct mib_node* const sensortable_nodes[1] = { (struct mib_node* const)&sensorentry }; static const struct mib_array_node sensortable = { &noleafs_get_object_def, &noleafs_get_value, &noleafs_set_test, &noleafs_set_value, MIB_NODE_AR, 1, sensortable_ids, sensortable_nodes }; /* example .1.3.6.1.4.1.26381.1 */ static const s32_t example_ids[1] = { 1 }; static struct mib_node* const example_nodes[1] = { (struct mib_node* const)&sensortable }; static const struct mib_array_node example = { &noleafs_get_object_def, &noleafs_get_value, &noleafs_set_test, &noleafs_set_value, MIB_NODE_AR, 1, example_ids, example_nodes }; /* lwip .1.3.6.1.4.1.26381 */ static const s32_t lwip_ids[1] = { 1 }; static struct mib_node* const lwip_nodes[1] = { (struct mib_node* const)&example }; static const struct mib_array_node lwip = { &noleafs_get_object_def, &noleafs_get_value, &noleafs_set_test, &noleafs_set_value, MIB_NODE_AR, 1, lwip_ids, lwip_nodes }; /* enterprises .1.3.6.1.4.1 */ static const s32_t enterprises_ids[1] = { 26381 }; static struct mib_node* const enterprises_nodes[1] = { (struct mib_node* const)&lwip }; static const struct mib_array_node enterprises = { &noleafs_get_object_def, &noleafs_get_value, &noleafs_set_test, &noleafs_set_value, MIB_NODE_AR, 1, enterprises_ids, enterprises_nodes }; /* private .1.3.6.1.4 */ static const s32_t private_ids[1] = { 1 }; static struct mib_node* const private_nodes[1] = { (struct mib_node* const)&enterprises }; const struct mib_array_node mib_private = { &noleafs_get_object_def, &noleafs_get_value, &noleafs_set_test, &noleafs_set_value, MIB_NODE_AR, 1, private_ids, private_nodes }; /** * Initialises this private MIB before use. * @see main.c */ void lwip_privmib_init(void) { #if SENSORS_USE_FILES && SENSORS_SEARCH_FILES char *buf, *ebuf, *cp; size_t bufsize; int nbytes; struct stat sb; struct dirent *dp; int fd; #else /* SENSORS_USE_FILES && SENSORS_SEARCH_FILES */ int i; #endif /* SENSORS_USE_FILES && SENSORS_SEARCH_FILES */ printf("SNMP private MIB start, detecting sensors.\n"); #if SENSORS_USE_FILES && SENSORS_SEARCH_FILES /* look for sensors in sensors directory */ fd = open(SENSORS_DIR, O_RDONLY); if (fd > -1) { fstat(fd, &sb); bufsize = sb.st_size; if (bufsize < sb.st_blksize) { bufsize = sb.st_blksize; } buf = malloc(bufsize); if (buf != NULL) { do { long base; nbytes = getdirentries(fd, buf, bufsize, &base); if (nbytes > 0) { ebuf = buf + nbytes; cp = buf; while (cp < ebuf) { dp = (struct dirent *)cp; if (isdigit(dp->d_name[0])) { struct mib_list_node *dummy; unsigned char idx; idx = dp->d_name[0] - '0'; snmp_mib_node_insert(&sensor_addr_inf.sensor_list_rn,idx,&dummy); strncpy(&sensor_addr_inf.sensor_files[idx][0],dp->d_name,SENSOR_NAME_LEN); printf("%s\n", sensor_addr_inf.sensor_files[idx]); } cp += dp->d_reclen; } } } while (nbytes > 0); free(buf); } close(fd); } #else /* SENSORS_USE_FILES && SENSORS_SEARCH_FILES */ for (i = 0; i < SENSOR_COUNT; i++) { struct mib_list_node *dummy; s32_t idx = i; char name[256]; sprintf(name, "%d.txt", i); snmp_mib_node_insert(&sensor_addr_inf.sensor_list_rn, idx, &dummy); strncpy(&sensor_addr_inf.sensor_files[idx][0], name, SENSOR_NAME_LEN); printf("%s\n", sensor_addr_inf.sensor_files[idx]); #if !SENSORS_USE_FILES /* initialize sensor value to != zero */ sensor_values[i] = 11 * (i+1); #endif /* !SENSORS_USE_FILES */ } #endif /* SENSORS_USE_FILE && SENSORS_SEARCH_FILES */ if (sensor_addr_inf.sensor_list_rn.count != 0) { /* enable sensor table, 2 tree_levels under this node one for the registers and one for the index */ sensorentry.tree_levels = 2; } } static u16_t sensorentry_length(void* addr_inf, u8_t level) { struct sensor_inf *sensors = (struct sensor_inf *)addr_inf; if (level == 0) { /* one object (temperature) */ return 1; } else if (level == 1) { /* number of sensor indexes */ return sensors->sensor_list_rn.count; } else { return 0; } } static s32_t sensorentry_idcmp(void* addr_inf, u8_t level, u16_t idx, s32_t sub_id) { struct sensor_inf *sensors = (struct sensor_inf *)addr_inf; if (level == 0) { return ((s32_t)(idx + 1) - sub_id); } else if (level == 1) { struct mib_list_node *ln; u16_t i; i = 0; ln = sensors->sensor_list_rn.head; while (i < idx) { i++; ln = ln->next; } LWIP_ASSERT("ln != NULL", ln != NULL); return (ln->objid - sub_id); } else { return -1; } } static void sensorentry_get_subid(void* addr_inf, u8_t level, u16_t idx, s32_t *sub_id) { struct sensor_inf *sensors = (struct sensor_inf *)addr_inf; if (level == 0) { *sub_id = idx + 1; } else if (level == 1) { struct mib_list_node *ln; u16_t i; i = 0; ln = sensors->sensor_list_rn.head; while (i < idx) { i++; ln = ln->next; } LWIP_ASSERT("ln != NULL", ln != NULL); *sub_id = ln->objid; } } /** * Async question for object definition */ static void sensorentry_get_object_def_q(void* addr_inf, u8_t rid, u8_t ident_len, s32_t *ident) { s32_t sensor_register, sensor_address; LWIP_UNUSED_ARG(addr_inf); LWIP_UNUSED_ARG(rid); ident_len += 1; ident -= 1; /* send request */ sensor_register = ident[0]; sensor_address = ident[1]; LWIP_DEBUGF(SNMP_MIB_DEBUG,("sensor_request reg=%"S32_F" addr=%"S32_F"\n", sensor_register, sensor_address)); /* fake async quesion/answer */ snmp_msg_event(rid); } static void sensorentry_get_object_def_a(u8_t rid, u8_t ident_len, s32_t *ident, struct obj_def *od) { LWIP_UNUSED_ARG(rid); /* return to object name, adding index depth (1) */ ident_len += 1; ident -= 1; if (ident_len == 2) { od->id_inst_len = ident_len; od->id_inst_ptr = ident; od->instance = MIB_OBJECT_TAB; od->access = MIB_OBJECT_READ_WRITE; od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG); od->v_len = sizeof(s32_t); } else { LWIP_DEBUGF(SNMP_MIB_DEBUG,("sensorentry_get_object_def_a: no scalar\n")); od->instance = MIB_OBJECT_NONE; } } static void sensorentry_get_object_def_pc(u8_t rid, u8_t ident_len, s32_t *ident) { LWIP_UNUSED_ARG(rid); LWIP_UNUSED_ARG(ident_len); LWIP_UNUSED_ARG(ident); /* nop */ } static void sensorentry_get_value_q(u8_t rid, struct obj_def *od) { LWIP_UNUSED_ARG(od); /* fake async quesion/answer */ snmp_msg_event(rid); } static void sensorentry_get_value_a(u8_t rid, struct obj_def *od, u16_t len, void *value) { s32_t i; s32_t *temperature = (s32_t *)value; #if SENSORS_USE_FILES FILE* sensf; char senspath[sizeof(SENSORS_DIR)+1+SENSOR_NAME_LEN+1] = SENSORS_DIR"/"; #endif /* SENSORS_USE_FILES */ LWIP_UNUSED_ARG(rid); LWIP_UNUSED_ARG(len); i = od->id_inst_ptr[1]; #if SENSORS_USE_FILES strncpy(&senspath[sizeof(SENSORS_DIR)], sensor_addr_inf.sensor_files[i], SENSOR_NAME_LEN); sensf = fopen(senspath,"r"); if (sensf != NULL) { fscanf(sensf,"%"S32_F,temperature); fclose(sensf); } #else /* SENSORS_USE_FILES */ if (i < SENSOR_COUNT) { *temperature = sensor_values[i]; } #endif /* SENSORS_USE_FILES */ } static void sensorentry_get_value_pc(u8_t rid, struct obj_def *od) { LWIP_UNUSED_ARG(rid); LWIP_UNUSED_ARG(od); /* nop */ } static void sensorentry_set_test_q(u8_t rid, struct obj_def *od) { LWIP_UNUSED_ARG(od); /* fake async quesion/answer */ snmp_msg_event(rid); } static u8_t sensorentry_set_test_a(u8_t rid, struct obj_def *od, u16_t len, void *value) { LWIP_UNUSED_ARG(rid); LWIP_UNUSED_ARG(od); LWIP_UNUSED_ARG(len); LWIP_UNUSED_ARG(value); /* sensors are read-only */ return 1; /* 0 -> read only, != 0 -> read/write */ } static void sensorentry_set_test_pc(u8_t rid, struct obj_def *od) { LWIP_UNUSED_ARG(rid); LWIP_UNUSED_ARG(od); /* nop */ } static void sensorentry_set_value_q(u8_t rid, struct obj_def *od, u16_t len, void *value) { LWIP_UNUSED_ARG(rid); LWIP_UNUSED_ARG(od); LWIP_UNUSED_ARG(len); LWIP_UNUSED_ARG(value); /* fake async quesion/answer */ snmp_msg_event(rid); } static void sensorentry_set_value_a(u8_t rid, struct obj_def *od, u16_t len, void *value) { s32_t i; s32_t *temperature = (s32_t *)value; #if SENSORS_USE_FILES FILE* sensf; char senspath[sizeof(SENSORS_DIR)+1+SENSOR_NAME_LEN+1] = SENSORS_DIR"/"; #endif /* SENSORS_USE_FILES */ LWIP_UNUSED_ARG(rid); LWIP_UNUSED_ARG(len); i = od->id_inst_ptr[1]; #if SENSORS_USE_FILES strncpy(&senspath[sizeof(SENSORS_DIR)], sensor_addr_inf.sensor_files[i], SENSOR_NAME_LEN); sensf = fopen(senspath, "w"); if (sensf != NULL) { fprintf(sensf, "%"S32_F, temperature); fclose(sensf); } #else /* SENSORS_USE_FILES */ if (i < SENSOR_COUNT) { sensor_values[i] = *temperature; } #endif /* SENSORS_USE_FILES */ } static void sensorentry_set_value_pc(u8_t rid, struct obj_def *od) { LWIP_UNUSED_ARG(rid); LWIP_UNUSED_ARG(od); /* nop */ } #endif /* LWIP_SNMP */