summaryrefslogtreecommitdiff
path: root/contrib/examples/snmp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/examples/snmp')
-rw-r--r--contrib/examples/snmp/snmp_example.c80
-rw-r--r--contrib/examples/snmp/snmp_example.h43
-rw-r--r--contrib/examples/snmp/snmp_private_mib/lwip_prvmib.c401
-rw-r--r--contrib/examples/snmp/snmp_private_mib/private_mib.h26
-rw-r--r--contrib/examples/snmp/snmp_v3/snmpv3_dummy.c395
-rw-r--r--contrib/examples/snmp/snmp_v3/snmpv3_dummy.h53
6 files changed, 998 insertions, 0 deletions
diff --git a/contrib/examples/snmp/snmp_example.c b/contrib/examples/snmp/snmp_example.c
new file mode 100644
index 00000000000..59524747980
--- /dev/null
+++ b/contrib/examples/snmp/snmp_example.c
@@ -0,0 +1,80 @@
+/*
+ * 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.
+ *
+ * This file is part of the lwIP TCP/IP stack.
+ *
+ * Author: Dirk Ziegelmeier <dziegel@gmx.de>
+ *
+ */
+
+#include "lwip/netif.h"
+#include "lwip/apps/snmp.h"
+#include "lwip/apps/snmp_mib2.h"
+#include "lwip/apps/snmpv3.h"
+#include "lwip/apps/snmp_snmpv2_framework.h"
+#include "lwip/apps/snmp_snmpv2_usm.h"
+#include "examples/snmp/snmp_v3/snmpv3_dummy.h"
+#include "examples/snmp/snmp_private_mib/private_mib.h"
+#include "snmp_example.h"
+
+#if LWIP_SNMP
+static const struct snmp_mib *mibs[] = {
+ &mib2,
+ &mib_private
+#if LWIP_SNMP_V3
+ , &snmpframeworkmib
+ , &snmpusmmib
+#endif
+};
+#endif /* LWIP_SNMP */
+
+void
+snmp_example_init(void)
+{
+#if LWIP_SNMP
+ s32_t req_nr;
+ lwip_privmib_init();
+#if SNMP_LWIP_MIB2
+#if SNMP_USE_NETCONN
+ snmp_threadsync_init(&snmp_mib2_lwip_locks, snmp_mib2_lwip_synchronizer);
+#endif /* SNMP_USE_NETCONN */
+ snmp_mib2_set_syscontact_readonly((const u8_t*)"root", NULL);
+ snmp_mib2_set_syslocation_readonly((const u8_t*)"lwIP development PC", NULL);
+ snmp_mib2_set_sysdescr((const u8_t*)"lwIP example", NULL);
+#endif /* SNMP_LWIP_MIB2 */
+
+#if LWIP_SNMP_V3
+ snmpv3_dummy_init();
+#endif
+
+ snmp_set_mibs(mibs, LWIP_ARRAYSIZE(mibs));
+ snmp_init();
+
+ snmp_trap_dst_ip_set(0, &netif_default->gw);
+ snmp_trap_dst_enable(0, 1);
+
+ snmp_send_inform_generic(SNMP_GENTRAP_COLDSTART, NULL, &req_nr);
+ snmp_send_trap_generic(SNMP_GENTRAP_COLDSTART);
+
+#endif /* LWIP_SNMP */
+}
diff --git a/contrib/examples/snmp/snmp_example.h b/contrib/examples/snmp/snmp_example.h
new file mode 100644
index 00000000000..fafcd68f2b1
--- /dev/null
+++ b/contrib/examples/snmp/snmp_example.h
@@ -0,0 +1,43 @@
+/*
+ * 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.
+ *
+ * This file is part of the lwIP TCP/IP stack.
+ *
+ * Author: Dirk Ziegelmeier <dziegel@gmx.de>
+ *
+ */
+
+#ifndef SNMP_EXAMPLE_H
+#define SNMP_EXAMPLE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void snmp_example_init(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* SNMP_EXAMPLE_H */
diff --git a/contrib/examples/snmp/snmp_private_mib/lwip_prvmib.c b/contrib/examples/snmp/snmp_private_mib/lwip_prvmib.c
new file mode 100644
index 00000000000..51a49fe158a
--- /dev/null
+++ b/contrib/examples/snmp/snmp_private_mib/lwip_prvmib.c
@@ -0,0 +1,401 @@
+/**
+ * @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 <christiaan.simons@axon.tv>
+ */
+
+#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 <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <dirent.h>
+#endif /* SENSORS_SEARCH_FILES */
+
+#include <string.h>
+#include <stdio.h>
+
+#include "lwip/apps/snmp_table.h"
+#include "lwip/apps/snmp_scalar.h"
+
+#if !SENSORS_USE_FILES || !SENSORS_SEARCH_FILES
+/** When not using & searching files, defines the number of sensors */
+#define SENSOR_COUNT 4
+#endif /* !SENSORS_USE_FILES || !SENSORS_SEARCH_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
+{
+ u8_t num;
+
+ char file[SENSOR_NAME_LEN + 1];
+
+#if !SENSORS_USE_FILES
+ /** When not using files, contains the value of the sensor */
+ s32_t value;
+#endif /* !SENSORS_USE_FILES */
+};
+
+static struct sensor_inf sensors[SENSOR_MAX];
+
+static s16_t sensor_count_get_value(struct snmp_node_instance* instance, void* value);
+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);
+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);
+static s16_t sensor_table_get_value(struct snmp_node_instance* instance, void* value);
+static snmp_err_t sensor_table_set_value(struct snmp_node_instance* instance, u16_t len, void *value);
+
+/* sensorentry .1.3.6.1.4.1.26381.1.1.1 (.level0.level1)
+ where level 0 is the table column (temperature/file name)
+ and level 1 the table row (sensor index) */
+static const struct snmp_table_col_def sensor_table_columns[] = {
+ { 1, SNMP_ASN1_TYPE_INTEGER, SNMP_NODE_INSTANCE_READ_WRITE },
+ { 2, SNMP_ASN1_TYPE_OCTET_STRING, SNMP_NODE_INSTANCE_READ_ONLY }
+};
+
+/* sensortable .1.3.6.1.4.1.26381.1.1 */
+static const struct snmp_table_node sensor_table = SNMP_TABLE_CREATE(
+ 1, sensor_table_columns,
+ sensor_table_get_cell_instance, sensor_table_get_next_cell_instance,
+ sensor_table_get_value, snmp_set_test_ok, sensor_table_set_value);
+
+/* sensorcount .1.3.6.1.4.1.26381.1.2 */
+static const struct snmp_scalar_node sensor_count = SNMP_SCALAR_CREATE_NODE_READONLY(
+ 2, SNMP_ASN1_TYPE_INTEGER, sensor_count_get_value);
+
+/* example .1.3.6.1.4.1.26381.1 */
+static const struct snmp_node* const example_nodes[] = {
+ &sensor_table.node.node,
+ &sensor_count.node.node
+};
+static const struct snmp_tree_node example_node = SNMP_CREATE_TREE_NODE(1, example_nodes);
+
+static const u32_t prvmib_base_oid[] = { 1,3,6,1,4,1,26381,1 };
+const struct snmp_mib mib_private = SNMP_MIB_CREATE(prvmib_base_oid, &example_node.node);
+
+#if 0
+/* for reference: we could also have expressed it like this: */
+
+/* lwip .1.3.6.1.4.1.26381 */
+static const struct snmp_node* const lwip_nodes[] = {
+ &example_node.node
+};
+static const struct snmp_tree_node lwip_node = SNMP_CREATE_TREE_NODE(26381, lwip_nodes);
+
+/* enterprises .1.3.6.1.4.1 */
+static const struct snmp_node* const enterprises_nodes[] = {
+ &lwip_node.node
+};
+static const struct snmp_tree_node enterprises_node = SNMP_CREATE_TREE_NODE(1, enterprises_nodes);
+
+/* private .1.3.6.1.4 */
+static const struct snmp_node* const private_nodes[] = {
+ &enterprises_node.node
+};
+static const struct snmp_tree_node private_root = SNMP_CREATE_TREE_NODE(4, private_nodes);
+
+static const u32_t prvmib_base_oid[] = { 1,3,6,1,4 };
+const struct snmp_mib mib_private = SNMP_MIB_CREATE(prvmib_base_oid, &private_root.node);
+#endif
+
+/**
+ * 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 */
+ u8_t i;
+#endif /* SENSORS_USE_FILES && SENSORS_SEARCH_FILES */
+
+ memset(sensors, 0, sizeof(sensors));
+
+ 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 < (size_t)sb.st_blksize)
+ {
+ bufsize = sb.st_blksize;
+ }
+ buf = (char*)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 (lwip_isdigit(dp->d_name[0]))
+ {
+ unsigned char idx = dp->d_name[0] - '0';
+
+ sensors[idx].num = idx+1;
+ strncpy(&sensors[idx].file[0], dp->d_name, SENSOR_NAME_LEN);
+ printf("%s\n", sensors[idx].file);
+ }
+ 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++) {
+ sensors[i].num = (u8_t)(i + 1);
+ snprintf(sensors[i].file, sizeof(sensors[i].file), "%d.txt", i);
+
+#if !SENSORS_USE_FILES
+ /* initialize sensor value to != zero */
+ sensors[i].value = 11 * (i+1);
+#endif /* !SENSORS_USE_FILES */
+ }
+#endif /* SENSORS_USE_FILE && SENSORS_SEARCH_FILES */
+}
+
+/* sensorcount .1.3.6.1.4.1.26381.1.2 */
+static s16_t
+sensor_count_get_value(struct snmp_node_instance* instance, void* value)
+{
+ size_t count = 0;
+ u32_t *uint_ptr = (u32_t*)value;
+
+ LWIP_UNUSED_ARG(instance);
+
+ for(count=0; count<LWIP_ARRAYSIZE(sensors); count++) {
+ if(sensors[count].num == 0) {
+ *uint_ptr = (u32_t)count;
+ return sizeof(*uint_ptr);
+ }
+ }
+
+ return 0;
+}
+
+/* sensortable .1.3.6.1.4.1.26381.1.1 */
+/* list of allowed value ranges for incoming OID */
+static const struct snmp_oid_range sensor_table_oid_ranges[] = {
+ { 1, SENSOR_MAX+1 }
+};
+
+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)
+{
+ u32_t sensor_num;
+ size_t i;
+
+ LWIP_UNUSED_ARG(column);
+
+ /* check if incoming OID length and if values are in plausible range */
+ if(!snmp_oid_in_range(row_oid, row_oid_len, sensor_table_oid_ranges, LWIP_ARRAYSIZE(sensor_table_oid_ranges))) {
+ return SNMP_ERR_NOSUCHINSTANCE;
+ }
+
+ /* get sensor index from incoming OID */
+ sensor_num = row_oid[0];
+
+ /* find sensor with index */
+ for(i=0; i<LWIP_ARRAYSIZE(sensors); i++) {
+ if(sensors[i].num != 0) {
+ if(sensors[i].num == sensor_num) {
+ /* store sensor index for subsequent operations (get/test/set) */
+ cell_instance->reference.u32 = (u32_t)i;
+ return SNMP_ERR_NOERROR;
+ }
+ }
+ }
+
+ /* not found */
+ return SNMP_ERR_NOSUCHINSTANCE;
+}
+
+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)
+{
+ size_t i;
+ struct snmp_next_oid_state state;
+ u32_t result_temp[LWIP_ARRAYSIZE(sensor_table_oid_ranges)];
+
+ LWIP_UNUSED_ARG(column);
+
+ /* init struct to search next oid */
+ snmp_next_oid_init(&state, row_oid->id, row_oid->len, result_temp, LWIP_ARRAYSIZE(sensor_table_oid_ranges));
+
+ /* iterate over all possible OIDs to find the next one */
+ for(i=0; i<LWIP_ARRAYSIZE(sensors); i++) {
+ if(sensors[i].num != 0) {
+ u32_t test_oid[LWIP_ARRAYSIZE(sensor_table_oid_ranges)];
+
+ test_oid[0] = sensors[i].num;
+
+ /* check generated OID: is it a candidate for the next one? */
+ snmp_next_oid_check(&state, test_oid, LWIP_ARRAYSIZE(sensor_table_oid_ranges), (void*)i);
+ }
+ }
+
+ /* did we find a next one? */
+ if(state.status == SNMP_NEXT_OID_STATUS_SUCCESS) {
+ snmp_oid_assign(row_oid, state.next_oid, state.next_oid_len);
+ /* store sensor index for subsequent operations (get/test/set) */
+ cell_instance->reference.u32 = LWIP_CONST_CAST(u32_t, state.reference);
+ return SNMP_ERR_NOERROR;
+ }
+
+ /* not found */
+ return SNMP_ERR_NOSUCHINSTANCE;
+}
+
+static s16_t
+sensor_table_get_value(struct snmp_node_instance* instance, void* value)
+{
+ u32_t i = instance->reference.u32;
+ s32_t *temperature = (s32_t *)value;
+
+ switch (SNMP_TABLE_GET_COLUMN_FROM_OID(instance->instance_oid.id))
+ {
+ case 1: /* sensor value */
+#if SENSORS_USE_FILES
+ FILE* sensf;
+ char senspath[sizeof(SENSORS_DIR)+1+SENSOR_NAME_LEN+1] = SENSORS_DIR"/";
+
+ strncpy(&senspath[sizeof(SENSORS_DIR)],
+ sensors[i].file,
+ SENSOR_NAME_LEN);
+ sensf = fopen(senspath,"r");
+ if (sensf != NULL)
+ {
+ fscanf(sensf,"%"S32_F,temperature);
+ fclose(sensf);
+ }
+#else /* SENSORS_USE_FILES */
+ *temperature = sensors[i].value;
+#endif /* SENSORS_USE_FILES */
+ return sizeof(s32_t);
+ case 2: /* file name */
+ MEMCPY(value, sensors[i].file, strlen(sensors[i].file));
+ return (s16_t)strlen(sensors[i].file);
+ default:
+ return 0;
+ }
+}
+
+static snmp_err_t
+sensor_table_set_value(struct snmp_node_instance* instance, u16_t len, void *value)
+{
+ u32_t i = instance->reference.u32;
+ s32_t *temperature = (s32_t *)value;
+#if SENSORS_USE_FILES
+ FILE* sensf;
+ char senspath[sizeof(SENSORS_DIR)+1+SENSOR_NAME_LEN+1] = SENSORS_DIR"/";
+
+ strncpy(&senspath[sizeof(SENSORS_DIR)],
+ sensors[i].file,
+ SENSOR_NAME_LEN);
+ sensf = fopen(senspath, "w");
+ if (sensf != NULL)
+ {
+ fprintf(sensf, "%"S32_F, *temperature);
+ fclose(sensf);
+ }
+#else /* SENSORS_USE_FILES */
+ sensors[i].value = *temperature;
+#endif /* SENSORS_USE_FILES */
+
+ LWIP_UNUSED_ARG(len);
+
+ return SNMP_ERR_NOERROR;
+}
+
+#endif /* LWIP_SNMP */
diff --git a/contrib/examples/snmp/snmp_private_mib/private_mib.h b/contrib/examples/snmp/snmp_private_mib/private_mib.h
new file mode 100644
index 00000000000..69be8a4fc58
--- /dev/null
+++ b/contrib/examples/snmp/snmp_private_mib/private_mib.h
@@ -0,0 +1,26 @@
+/**
+ * @file
+ * Exports Private lwIP MIB
+ */
+
+#ifndef LWIP_HDR_PRIVATE_MIB_H
+#define LWIP_HDR_PRIVATE_MIB_H
+
+#include "lwip/apps/snmp_opts.h"
+
+#include "lwip/apps/snmp_core.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* export MIB */
+extern const struct snmp_mib mib_private;
+
+void lwip_privmib_init(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/contrib/examples/snmp/snmp_v3/snmpv3_dummy.c b/contrib/examples/snmp/snmp_v3/snmpv3_dummy.c
new file mode 100644
index 00000000000..a7c53ed73ac
--- /dev/null
+++ b/contrib/examples/snmp/snmp_v3/snmpv3_dummy.c
@@ -0,0 +1,395 @@
+/**
+ * @file
+ * Dummy SNMPv3 functions.
+ */
+
+/*
+ * Copyright (c) 2016 Elias Oenal.
+ * 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: Elias Oenal <lwip@eliasoenal.com>
+ * Dirk Ziegelmeier <dirk@ziegelmeier.net>
+ */
+
+#include "lwip/apps/snmpv3.h"
+#include "snmpv3_dummy.h"
+#include <string.h>
+#include "lwip/err.h"
+#include "lwip/def.h"
+#include "lwip/timeouts.h"
+
+#if LWIP_SNMP && LWIP_SNMP_V3
+
+struct user_table_entry {
+ char username[32];
+ snmpv3_auth_algo_t auth_algo;
+ u8_t auth_key[20];
+ snmpv3_priv_algo_t priv_algo;
+ u8_t priv_key[20];
+};
+
+static struct user_table_entry user_table[] = {
+ { "lwip", SNMP_V3_AUTH_ALGO_INVAL, "" , SNMP_V3_PRIV_ALGO_INVAL, "" },
+ { "piwl", SNMP_V3_AUTH_ALGO_INVAL, "" , SNMP_V3_PRIV_ALGO_INVAL, "" },
+ { "test", SNMP_V3_AUTH_ALGO_INVAL, "" , SNMP_V3_PRIV_ALGO_INVAL, "" }
+};
+
+static char snmpv3_engineid[32];
+static u8_t snmpv3_engineid_len;
+
+static u32_t enginetime = 0;
+
+/* In this implementation engineboots is volatile. In a real world application this value should be stored in non-volatile memory.*/
+static u32_t engineboots = 0;
+
+/**
+ * @brief Get the user table entry for the given username.
+ *
+ * @param[in] username pointer to the username
+ *
+ * @return pointer to the user table entry or NULL if not found.
+ */
+static struct user_table_entry*
+get_user(const char *username)
+{
+ size_t i;
+
+ for (i = 0; i < LWIP_ARRAYSIZE(user_table); i++) {
+ if (strnlen(username, 32) != strnlen(user_table[i].username, 32)) {
+ continue;
+ }
+
+ if (memcmp(username, user_table[i].username, strnlen(username, 32)) == 0) {
+ return &user_table[i];
+ }
+ }
+
+ return NULL;
+}
+
+u8_t
+snmpv3_get_amount_of_users(void)
+{
+ return LWIP_ARRAYSIZE(user_table);
+}
+
+/**
+ * @brief Get the username of a user number (index)
+ * @param username is a pointer to a string.
+ * @param index is the user index.
+ * @return ERR_OK if user is found, ERR_VAL is user is not found.
+ */
+err_t
+snmpv3_get_username(char *username, u8_t index)
+{
+ if (index < LWIP_ARRAYSIZE(user_table)) {
+ MEMCPY(username, user_table[index].username, sizeof(user_table[0].username));
+ return ERR_OK;
+ }
+
+ return ERR_VAL;
+}
+
+/**
+ * Timer callback function that increments enginetime and reschedules itself.
+ *
+ * @param arg unused argument
+ */
+static void
+snmpv3_enginetime_timer(void *arg)
+{
+ LWIP_UNUSED_ARG(arg);
+
+ enginetime++;
+
+ /* This handles the engine time reset */
+ snmpv3_get_engine_time_internal();
+
+ /* restart timer */
+ sys_timeout(1000, snmpv3_enginetime_timer, NULL);
+}
+
+err_t
+snmpv3_set_user_auth_algo(const char *username, snmpv3_auth_algo_t algo)
+{
+ struct user_table_entry *p = get_user(username);
+
+ if (p) {
+ switch (algo) {
+ case SNMP_V3_AUTH_ALGO_INVAL:
+ if (p->priv_algo != SNMP_V3_PRIV_ALGO_INVAL) {
+ /* Privacy MUST be disabled before configuring authentication */
+ break;
+ } else {
+ p->auth_algo = algo;
+ return ERR_OK;
+ }
+#if LWIP_SNMP_V3_CRYPTO
+ case SNMP_V3_AUTH_ALGO_MD5:
+ case SNMP_V3_AUTH_ALGO_SHA:
+#endif
+ p->auth_algo = algo;
+ return ERR_OK;
+ default:
+ break;
+ }
+ }
+
+ return ERR_VAL;
+}
+
+err_t
+snmpv3_set_user_priv_algo(const char *username, snmpv3_priv_algo_t algo)
+{
+ struct user_table_entry *p = get_user(username);
+
+ if (p) {
+ switch (algo) {
+#if LWIP_SNMP_V3_CRYPTO
+ case SNMP_V3_PRIV_ALGO_AES:
+ case SNMP_V3_PRIV_ALGO_DES:
+ if (p->auth_algo == SNMP_V3_AUTH_ALGO_INVAL) {
+ /* Authentication MUST be enabled before configuring privacy */
+ break;
+ } else {
+ p->priv_algo = algo;
+ return ERR_OK;
+ }
+#endif
+ case SNMP_V3_PRIV_ALGO_INVAL:
+ p->priv_algo = algo;
+ return ERR_OK;
+ default:
+ break;
+ }
+ }
+
+ return ERR_VAL;
+}
+
+err_t
+snmpv3_set_user_auth_key(const char *username, const char *password)
+{
+ struct user_table_entry *p = get_user(username);
+ const char *engineid;
+ u8_t engineid_len;
+
+ if (p) {
+ /* password should be at least 8 characters long */
+ if (strlen(password) >= 8) {
+ memset(p->auth_key, 0, sizeof(p->auth_key));
+ snmpv3_get_engine_id(&engineid, &engineid_len);
+ switch (p->auth_algo) {
+ case SNMP_V3_AUTH_ALGO_INVAL:
+ return ERR_OK;
+#if LWIP_SNMP_V3_CRYPTO
+ case SNMP_V3_AUTH_ALGO_MD5:
+ snmpv3_password_to_key_md5((const u8_t*)password, strlen(password), (const u8_t*)engineid, engineid_len, p->auth_key);
+ return ERR_OK;
+ case SNMP_V3_AUTH_ALGO_SHA:
+ snmpv3_password_to_key_sha((const u8_t*)password, strlen(password), (const u8_t*)engineid, engineid_len, p->auth_key);
+ return ERR_OK;
+#endif
+ default:
+ return ERR_VAL;
+ }
+ }
+ }
+
+ return ERR_VAL;
+}
+
+err_t
+snmpv3_set_user_priv_key(const char *username, const char *password)
+{
+ struct user_table_entry *p = get_user(username);
+ const char *engineid;
+ u8_t engineid_len;
+
+ if (p) {
+ /* password should be at least 8 characters long */
+ if (strlen(password) >= 8) {
+ memset(p->priv_key, 0, sizeof(p->priv_key));
+ snmpv3_get_engine_id(&engineid, &engineid_len);
+ switch (p->auth_algo) {
+ case SNMP_V3_AUTH_ALGO_INVAL:
+ return ERR_OK;
+#if LWIP_SNMP_V3_CRYPTO
+ case SNMP_V3_AUTH_ALGO_MD5:
+ snmpv3_password_to_key_md5((const u8_t*)password, strlen(password), (const u8_t*)engineid, engineid_len, p->priv_key);
+ return ERR_OK;
+ case SNMP_V3_AUTH_ALGO_SHA:
+ snmpv3_password_to_key_sha((const u8_t*)password, strlen(password), (const u8_t*)engineid, engineid_len, p->priv_key);
+ return ERR_OK;
+#endif
+ default:
+ return ERR_VAL;
+ }
+ }
+ }
+
+ return ERR_VAL;
+}
+
+/**
+ * @brief Get the storage type of the given username.
+ *
+ * @param[in] username pointer to the username
+ * @param[out] type the storage type
+ *
+ * @return ERR_OK if the user was found, ERR_VAL if not.
+ */
+err_t
+snmpv3_get_user_storagetype(const char *username, snmpv3_user_storagetype_t *type)
+{
+ if (get_user(username) != NULL) {
+ /* Found user in user table
+ * In this dummy implementation, storage is permanent because no user can be deleted.
+ * All changes to users are lost after a reboot.*/
+ *type = SNMP_V3_USER_STORAGETYPE_PERMANENT;
+ return ERR_OK;
+ }
+
+ return ERR_VAL;
+}
+
+/**
+ * @param username is a pointer to a string.
+ * @param auth_algo is a pointer to u8_t. The implementation has to set this if user was found.
+ * @param auth_key is a pointer to a pointer to a string. Implementation has to set this if user was found.
+ * @param priv_algo is a pointer to u8_t. The implementation has to set this if user was found.
+ * @param priv_key is a pointer to a pointer to a string. Implementation has to set this if user was found.
+ */
+err_t
+snmpv3_get_user(const char* username, snmpv3_auth_algo_t *auth_algo, u8_t *auth_key, snmpv3_priv_algo_t *priv_algo, u8_t *priv_key)
+{
+ const struct user_table_entry *p;
+
+ /* The msgUserName specifies the user (principal) on whose behalf the
+ message is being exchanged. Note that a zero-length userName will
+ not match any user, but it can be used for snmpEngineID discovery. */
+ if(strlen(username) == 0) {
+ return ERR_OK;
+ }
+
+ p = get_user(username);
+
+ if (!p) {
+ return ERR_VAL;
+ }
+
+ if (auth_algo != NULL) {
+ *auth_algo = p->auth_algo;
+ }
+ if(auth_key != NULL) {
+ MEMCPY(auth_key, p->auth_key, sizeof(p->auth_key));
+ }
+ if (priv_algo != NULL) {
+ *priv_algo = p->priv_algo;
+ }
+ if(priv_key != NULL) {
+ MEMCPY(priv_key, p->priv_key, sizeof(p->priv_key));
+ }
+ return ERR_OK;
+}
+
+/**
+ * Get engine ID from persistence
+ */
+void
+snmpv3_get_engine_id(const char **id, u8_t *len)
+{
+ *id = snmpv3_engineid;
+ *len = snmpv3_engineid_len;
+}
+
+/**
+ * Store engine ID in persistence
+ */
+err_t
+snmpv3_set_engine_id(const char *id, u8_t len)
+{
+ MEMCPY(snmpv3_engineid, id, len);
+ snmpv3_engineid_len = len;
+ return ERR_OK;
+}
+
+/**
+ * Get engine boots from persistence. Must be increased on each boot.
+ */
+u32_t
+snmpv3_get_engine_boots(void)
+{
+ return engineboots;
+}
+
+/**
+ * Store engine boots in persistence
+ */
+void
+snmpv3_set_engine_boots(u32_t boots)
+{
+ engineboots = boots;
+}
+
+/**
+ * RFC3414 2.2.2.
+ * Once the timer reaches 2147483647 it gets reset to zero and the
+ * engine boot ups get incremented.
+ */
+u32_t
+snmpv3_get_engine_time(void)
+{
+ return enginetime;
+}
+
+/**
+ * Reset current engine time to 0
+ */
+void
+snmpv3_reset_engine_time(void)
+{
+ enginetime = 0;
+}
+
+/**
+ * Initialize dummy SNMPv3 implementation
+ */
+void
+snmpv3_dummy_init(void)
+{
+ snmpv3_set_engine_id("FOO", 3);
+
+ snmpv3_set_user_auth_algo("lwip", SNMP_V3_AUTH_ALGO_SHA);
+ snmpv3_set_user_auth_key("lwip", "maplesyrup");
+
+ snmpv3_set_user_priv_algo("lwip", SNMP_V3_PRIV_ALGO_DES);
+ snmpv3_set_user_priv_key("lwip", "maplesyrup");
+
+ /* Start the engine time timer */
+ snmpv3_enginetime_timer(NULL);
+}
+
+#endif /* LWIP_SNMP && LWIP_SNMP_V3 */
diff --git a/contrib/examples/snmp/snmp_v3/snmpv3_dummy.h b/contrib/examples/snmp/snmp_v3/snmpv3_dummy.h
new file mode 100644
index 00000000000..ba25b6d7d58
--- /dev/null
+++ b/contrib/examples/snmp/snmp_v3/snmpv3_dummy.h
@@ -0,0 +1,53 @@
+/**
+ * @file
+ * Dummy SNMPv3 functions.
+ */
+
+/*
+ * Copyright (c) 2017 Dirk Ziegelmeier.
+ * 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: Dirk Ziegelmeier <dziegel@gmx.de>
+ */
+
+#ifndef LWIP_HDR_APPS_SNMP_V3_DUMMY_H
+#define LWIP_HDR_APPS_SNMP_V3_DUMMY_H
+
+#include "lwip/apps/snmp_opts.h"
+#include "lwip/err.h"
+#include "lwip/apps/snmpv3.h"
+
+#if LWIP_SNMP && LWIP_SNMP_V3
+
+err_t snmpv3_set_user_auth_algo(const char *username, snmpv3_auth_algo_t algo);
+err_t snmpv3_set_user_priv_algo(const char *username, snmpv3_priv_algo_t algo);
+err_t snmpv3_set_user_auth_key(const char *username, const char *password);
+err_t snmpv3_set_user_priv_key(const char *username, const char *password);
+
+void snmpv3_dummy_init(void);
+
+#endif /* LWIP_SNMP && LWIP_SNMP_V3 */
+
+#endif /* LWIP_HDR_APPS_SNMP_V3_DUMMY_H */