From d8922d0410095609c04c40639e3bd9bce3abf74a Mon Sep 17 00:00:00 2001 From: christiaans Date: Fri, 14 Jul 2006 12:54:38 +0000 Subject: [PATCH] Added minimalistic SNMP GET functionality. --- CHANGELOG | 29 +- src/core/snmp/mib2.c | 1038 +++++++++++++++++++++++++++---- src/core/snmp/mib_structs.c | 224 +++++++ src/core/snmp/msg_in.c | 77 ++- src/core/snmp/msg_out.c | 9 +- src/include/lwip/snmp.h | 2 +- src/include/lwip/snmp_structs.h | 179 ++++++ 7 files changed, 1431 insertions(+), 127 deletions(-) create mode 100644 src/core/snmp/mib_structs.c create mode 100644 src/include/lwip/snmp_structs.h diff --git a/CHANGELOG b/CHANGELOG index ad8ee4d4..7a816d15 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -25,6 +25,30 @@ HISTORY * [Enter new changes just after this line - do not remove this line] + ++ New features: + + 2006-07-14 Christiaan Simons + * mib_structs.c: added + * include/lwip/snmp_structs.h: added + * netif.{c,h}, netif/ethernetif.c: added SNMP statistics to netif struct + * mib2.c: changed, inserted object tree + * msg_{in,out}.c: changed, added minimalistic GET functionality (needs work) + + 2006-07-06 Christiaan Simons + * snmp/asn1_{enc,dec}.c added + * snmp/mib2.c added + * snmp/msg_{in,out}.c added + * include/lwip/snmp_asn1.h added + * include/lwip/snmp_msg.h added + * doc/snmp_agent.txt added + + 2006-03-29 Christiaan Simons + * inet.c, inet.h: Added platform byteswap support. + Added LWIP_PLATFORM_BYTESWAP define (defaults to 0) and + optional LWIP_PLATFORM_HTONS(), LWIP_PLATFORM_HTONL() macros. + + ++ Bug fixes: + 2006-06-27 Christiaan Simons * api_msg.c: Applied patch for cold case (bug #11135). In accept_function() ensure newconn->callback is always initialized. @@ -41,11 +65,6 @@ HISTORY * api_lib.c: Removed conn->sem creation and destruction from netconn_write() and added sys_sem_new to netconn_new_*. - 2006-03-29 Christiaan Simons - * inet.c, inet.h: Added platform byteswap support. - Added LWIP_PLATFORM_BYTESWAP define (defaults to 0) and - optional LWIP_PLATFORM_HTONS(), LWIP_PLATFORM_HTONL() macros. - (STABLE-1_1_1) 2006-03-03 Christiaan Simons diff --git a/src/core/snmp/mib2.c b/src/core/snmp/mib2.c index 76142df9..e3ec4462 100644 --- a/src/core/snmp/mib2.c +++ b/src/core/snmp/mib2.c @@ -35,130 +35,411 @@ #include "arch/cc.h" #include "lwip/opt.h" #include "lwip/snmp.h" +#include "lwip/netif.h" #include "lwip/snmp_asn1.h" -/* #include "lwip/snmp_structs.h" */ +#include "lwip/snmp_structs.h" #if LWIP_SNMP -#ifndef SNMP_ENTERPRISE_ID /** * IANA assigned enterprise ID for lwIP is 26381 * @see http://www.iana.org/assignments/enterprise-numbers + * * @note this enterprise ID is assigned to the lwIP project, * all object identifiers living under this ID are assigned * by the lwIP maintainers (contact Christiaan Simons)! + * @note don't change this define, use snmp_set_sysobjid() * * If you need to create your own private MIB you'll need * to apply for your own enterprise ID with IANA: * http://www.iana.org/numbers.html */ #define SNMP_ENTERPRISE_ID 26381 -#endif -#ifndef SNMP_SYSOBJID_LEN #define SNMP_SYSOBJID_LEN 5 -#endif -#ifndef SNMP_SYSOBJID #define SNMP_SYSOBJID {6, 1, 4, 1, SNMP_ENTERPRISE_ID} + +#ifndef SNMP_SYSSERVICES +#define SNMP_SYSSERVICES ((1 << 6) | (1 << 3) | ((IP_FORWARD) << 2)) #endif -/** @todo MIB-tree will be inserted here */ +/** @todo publish this in snmp.h (for use in private mib) */ +void noleafs_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od); +void noleafs_get_value(u8_t ident_len, s32_t *ident, u16_t len, void *value); + +static void system_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od); +static void system_get_value(u8_t ident_len, s32_t *ident, u16_t len, void *value); +static void interfaces_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od); +static void interfaces_get_value(u8_t ident_len, s32_t *ident, u16_t len, void *value); +static void ifentry_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od); +static void ifentry_get_value(u8_t ident_len, s32_t *ident, u16_t len, void *value); + +/* snmp .1.3.6.1.2.1.11 */ +const s32_t snmp_ids[29] = { + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 24, 25, 26, 27, 28, 29, 30 +}; +struct mib_node* const snmp_nodes[29] = { + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +}; +const struct mib_array_node snmp = { + &noleafs_get_object_def, + &noleafs_get_value, + MIB_NODE_AR, + 29, + snmp_ids, + snmp_nodes +}; + +/* dot3 and EtherLike MIB not planned. (transmission .1.3.6.1.2.1.10) */ +/* historical (some say hysterical). (cmot .1.3.6.1.2.1.9) */ +/* lwIP has no EGP, thus may not implement it. (egp .1.3.6.1.2.1.8) */ + +/* udp .1.3.6.1.2.1.7 */ +const s32_t udp_ids[5] = { 1, 2, 3, 4, 5 }; +struct mib_node* const udp_nodes[5] = { + NULL, NULL, NULL, NULL, /** @todo udpTable */ NULL +}; +const struct mib_array_node udp = { + &noleafs_get_object_def, + &noleafs_get_value, + MIB_NODE_AR, + 5, + udp_ids, + udp_nodes +}; + +/* tcp .1.3.6.1.2.1.6 */ +const s32_t tcp_ids[15] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }; +struct mib_node* const tcp_nodes[15] = { + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + /** @todo tcpConnTable */ NULL, NULL, NULL +}; +const struct mib_array_node tcp = { + &noleafs_get_object_def, + &noleafs_get_value, + MIB_NODE_AR, + 15, + tcp_ids, + tcp_nodes +}; + +/* icmp .1.3.6.1.2.1.5 */ +const s32_t icmp_ids[26] = { 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 }; +struct mib_node* const icmp_nodes[26] = { + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL +}; +const struct mib_array_node icmp = { + &noleafs_get_object_def, + &noleafs_get_value, + MIB_NODE_AR, + 26, + icmp_ids, + icmp_nodes +}; + +/* ip .1.3.6.1.2.1.4 */ +const s32_t ip_ids[23] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23 }; +struct mib_node* const ip_nodes[23] = { + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, /** @todo ipAddrTable */ NULL, /** @todo ipRouteTable */ NULL, /** @todo ipNetToMediaTable */ NULL, NULL +}; +const struct mib_array_node ip = { + &noleafs_get_object_def, + &noleafs_get_value, + MIB_NODE_AR, + 23, + ip_ids, + ip_nodes +}; + +/* at .1.3.6.1.2.1.3 */ +const s32_t at_ids[1] = { 1 }; +struct mib_node* const at_nodes[1] = { /** @todo atTable*/ NULL }; +const struct mib_array_node at = { + &noleafs_get_object_def, + &noleafs_get_value, + MIB_NODE_AR, + 1, + at_ids, + at_nodes +}; + +const s32_t ifentry_ids[22] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22 }; +struct mib_node* const ifentry_nodes[22] = { + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL +}; +const struct mib_array_node ifentry = { + &ifentry_get_object_def, + &ifentry_get_value, + MIB_NODE_AR, + 22, + ifentry_ids, + ifentry_nodes +}; + +const s32_t iftable_id = 1; +struct mib_node* const iftable_node = (struct mib_node* const)&ifentry; +const struct mib_array_node iftable = { + &noleafs_get_object_def, + &noleafs_get_value, + MIB_NODE_AR, + 1, + &iftable_id, + &iftable_node +}; + +/* interfaces .1.3.6.1.2.1.2 */ +const s32_t interfaces_ids[2] = { 1, 2 }; +struct mib_node* const interfaces_nodes[2] = { NULL, (struct mib_node* const)&iftable }; +const struct mib_array_node interfaces = { + &interfaces_get_object_def, + &interfaces_get_value, + MIB_NODE_AR, + 2, + interfaces_ids, + interfaces_nodes +}; + +/* 0 1 2 3 4 5 6 */ +/* system .1.3.6.1.2.1.1 */ +const s32_t sys_tem_ids[7] = { 1, 2, 3, 4, 5, 6, 7 }; +struct mib_node* const sys_tem_nodes[7] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL }; +/* work around name issue with 'sys_tem', some compiler(s?) seem to reserve 'system' */ +const struct mib_array_node sys_tem = { + &system_get_object_def, + &system_get_value, + MIB_NODE_AR, + 7, + sys_tem_ids, + sys_tem_nodes +}; + +/* mib-2 .1.3.6.1.2.1 */ +const s32_t mib2_ids[8] = { 1, 2, 3, 4, 5, 6, 7, 11 }; +struct mib_node* const mib2_nodes[8] = { + (struct mib_node* const)&sys_tem, + (struct mib_node* const)&interfaces, + (struct mib_node* const)&at, + (struct mib_node* const)&ip, + (struct mib_node* const)&icmp, + (struct mib_node* const)&tcp, + (struct mib_node* const)&udp, + (struct mib_node* const)&snmp +}; +const struct mib_array_node mib2 = { + &noleafs_get_object_def, + &noleafs_get_value, + MIB_NODE_AR, + 8, + mib2_ids, + mib2_nodes +}; + +/* mgmt .1.3.6.1.2 */ +const s32_t mgmt_ids[1] = { 1 }; +struct mib_node* const mgmt_nodes[1] = { (struct mib_node* const)&mib2 }; +const struct mib_array_node mgmt = { + &noleafs_get_object_def, + &noleafs_get_value, + MIB_NODE_AR, + 1, + mgmt_ids, + mgmt_nodes +}; + +/* internet .1.3.6.1 */ +#if SNMP_PRIVATE_MIB +s32_t internet_ids[2] = { 2, 4 }; +struct mib_node* const internet_nodes[2] = { (struct mib_node* const)&mgmt, (struct mib_node* const)&private }; +const struct mib_array_node internet = { + &noleafs_get_object_def, + &noleafs_get_value, + MIB_NODE_AR, + 2, + internet_ids, + internet_nodes +}; +#else +const s32_t internet_ids[1] = { 2 }; +struct mib_node* const internet_nodes[1] = { (struct mib_node* const)&mgmt }; +const struct mib_array_node internet = { + &noleafs_get_object_def, + &noleafs_get_value, + MIB_NODE_AR, + 1, + internet_ids, + internet_nodes +}; +#endif /** .iso.org.dod.internet.mgmt.mib-2.sysObjectID */ -const struct snmp_obj_id sysobjid = {SNMP_SYSOBJID_LEN, SNMP_SYSOBJID}; +static struct snmp_obj_id sysobjid = {SNMP_SYSOBJID_LEN, SNMP_SYSOBJID}; /** enterprise ID for generic TRAPs, .iso.org.dod.internet.mgmt.mib-2.snmp */ -const struct snmp_obj_id snmpgrp_id = {5,{6,1,2,1,11}}; +static struct snmp_obj_id snmpgrp_id = {5,{6,1,2,1,11}}; +/** .iso.org.dod.internet.mgmt.mib-2.sysServices */ +static const s32_t sysservices = SNMP_SYSSERVICES; + +/** .iso.org.dod.internet.mgmt.mib-2.sysDescr */ +static u8_t sysdescr_len = 4; +static u8_t sysdescr[255] = "lwIP"; +static u8_t syscontact_len = 0; +static u8_t syscontact[255]; +static u8_t sysname_len = 0; +static u8_t sysname[255]; +static u8_t syslocation_len = 0; +static u8_t syslocation[255]; +/** .iso.org.dod.internet.mgmt.mib-2.interfaces.ifTable.ifEntry.ifSpecific */ +static const struct snmp_obj_id ifspecific = {0, {0}}; /* mib-2.system counter(s) */ -static u32_t sysuptime; -/* mib-2.interfaces counter(s) */ -static u32_t ifinoctets, - ifinucastpkts, - ifinnucastpkts, - ifindiscards, - ifoutoctets, - ifoutucastpkts, - ifoutnucastpkts, - ifoutdiscards; +static u32_t sysuptime = 0; + /* mib-2.ip counter(s) */ -static u32_t ipindelivers, - ipinreceives, - ipindiscards, - ipoutdiscards, - ipoutrequests, - ipunknownprotos; +static u32_t ipindelivers = 0, + ipinreceives = 0, + ipindiscards = 0, + ipoutdiscards = 0, + ipoutrequests = 0, + ipunknownprotos = 0; /* mib-2.icmp counter(s) */ -static u32_t icmpinmsgs, - icmpinerrors, - icmpindestunreachs, - icmpintimeexcds, - icmpinparmprobs, - icmpinsrcquenchs, - icmpinredirects, - icmpinechos, - icmpinechoreps, - icmpintimestamps, - icmpintimestampreps, - icmpinaddrmasks, - icmpinaddrmaskreps, - icmpoutmsgs, - icmpouterrors, - icmpoutdestunreachs, - icmpouttimeexcds, - icmpoutparmprobs, - icmpoutsrcquenchs, - icmpoutredirects, - icmpoutechos, - icmpoutechoreps, - icmpouttimestamps, - icmpouttimestampreps, - icmpoutaddrmasks, - icmpoutaddrmaskreps; +static u32_t icmpinmsgs = 0, + icmpinerrors = 0, + icmpindestunreachs = 0, + icmpintimeexcds = 0, + icmpinparmprobs = 0, + icmpinsrcquenchs = 0, + icmpinredirects = 0, + icmpinechos = 0, + icmpinechoreps = 0, + icmpintimestamps = 0, + icmpintimestampreps = 0, + icmpinaddrmasks = 0, + icmpinaddrmaskreps = 0, + icmpoutmsgs = 0, + icmpouterrors = 0, + icmpoutdestunreachs = 0, + icmpouttimeexcds = 0, + icmpoutparmprobs = 0, + icmpoutsrcquenchs = 0, + icmpoutredirects = 0, + icmpoutechos = 0, + icmpoutechoreps = 0, + icmpouttimestamps = 0, + icmpouttimestampreps = 0, + icmpoutaddrmasks = 0, + icmpoutaddrmaskreps = 0; /* mib-2.tcp counter(s) */ -static u32_t tcpactiveopens, - tcppassiveopens, - tcpattemptfails, - tcpestabresets, - tcpcurrestab, - tcpinsegs, - tcpoutsegs, - tcpretranssegs, - tcpinerrs, - tcpoutrsts; +static u32_t tcpactiveopens = 0, + tcppassiveopens = 0, + tcpattemptfails = 0, + tcpestabresets = 0, + tcpcurrestab = 0, + tcpinsegs = 0, + tcpoutsegs = 0, + tcpretranssegs = 0, + tcpinerrs = 0, + tcpoutrsts = 0; /* mib-2.udp counter(s) */ -static u32_t udpindatagrams, - udpnoports, - udpinerrors, - udpoutdatagrams; +static u32_t udpindatagrams = 0, + udpnoports = 0, + udpinerrors = 0, + udpoutdatagrams = 0; /* mib-2.snmp counter(s) */ -static u32_t snmpinpkts, - snmpoutpkts, - snmpinbadversions, - snmpinbadcommunitynames, - snmpinbadcommunityuses, - snmpinasnparseerrs, - snmpintoobigs, - snmpinnosuchnames, - snmpinbadvalues, - snmpinreadonlys, - snmpingenerrs, - snmpintotalreqvars, - snmpintotalsetvars, - snmpingetrequests, - snmpingetnexts, - snmpinsetrequests, - snmpingetresponses, - snmpintraps, - snmpouttoobigs, - snmpoutnosuchnames, - snmpoutbadvalues, - snmpoutgenerrs, - snmpoutgetrequests, - snmpoutgetnexts, - snmpoutsetrequests, - snmpoutgetresponses, - snmpouttraps; +static u32_t snmpinpkts = 0, + snmpoutpkts = 0, + snmpinbadversions = 0, + snmpinbadcommunitynames = 0, + snmpinbadcommunityuses = 0, + snmpinasnparseerrs = 0, + snmpintoobigs = 0, + snmpinnosuchnames = 0, + snmpinbadvalues = 0, + snmpinreadonlys = 0, + snmpingenerrs = 0, + snmpintotalreqvars = 0, + snmpintotalsetvars = 0, + snmpingetrequests = 0, + snmpingetnexts = 0, + snmpinsetrequests = 0, + snmpingetresponses = 0, + snmpintraps = 0, + snmpouttoobigs = 0, + snmpoutnosuchnames = 0, + snmpoutbadvalues = 0, + snmpoutgenerrs = 0, + snmpoutgetrequests = 0, + snmpoutgetnexts = 0, + snmpoutsetrequests = 0, + snmpoutgetresponses = 0, + snmpouttraps = 0; + + /* prototypes of the following functions are in lwip/src/include/lwip/snmp.h */ +/** + * Copy octet string. + * + * @param dst points to destination + * @param src points to source + * @param n number of octets to copy. + */ +void ocstrncpy(u8_t *dst, u8_t *src, u8_t n) +{ + while (n > 0) + { + n--; + *dst++ = *src++; + } +} + +/** + * Copy object identifier (s32_t) array. + * + * @param dst points to destination + * @param src points to source + * @param n number of sub identifiers to copy. + */ +void objectidncpy(s32_t *dst, s32_t *src, u8_t n) +{ + while(n > 0) + { + n--; + *dst++ = *src++; + } +} + +/** + * Initializes sysDescr value. + * + * @param str if non-NULL then copy str + * @param strlen string length, excluding zero terminator + */ +void snmp_set_sysdesr(u8_t* str, u8_t strlen) +{ + if (str != NULL) + { + strlen = ((strlen < sizeof(sysdescr))?(strlen):(sizeof(sysdescr))); + ocstrncpy(sysdescr, str, strlen); + } +} + +void snmp_get_sysobjid_ptr(struct snmp_obj_id **oid) +{ + *oid = &sysobjid; +} + +/** + * Initializes sysObjectID value. + * + * @param oid points to stuct snmp_obj_id to copy + */ +void snmp_set_sysobjid(struct snmp_obj_id *oid) +{ + sysobjid = *oid; +} /** * Must be called at regular 10 msec interval from a timer interrupt @@ -174,49 +455,90 @@ void snmp_get_sysuptime(u32_t *value) *value = sysuptime; } -void snmp_get_sysobjid(const struct snmp_obj_id **oid) +/** + * Initializes sysContact value (from lwIP external non-volatile memory). + * + * @param str if non-NULL then copy str + * @param strlen string length, excluding zero terminator + */ +void snmp_set_syscontact(u8_t *ocstr, u8_t ocstrlen) { - *oid = &sysobjid; + if (ocstr != NULL) + { + ocstrlen = ((ocstrlen < sizeof(syscontact))?(ocstrlen):(sizeof(syscontact))); + ocstrncpy(syscontact, ocstr, ocstrlen); + } } -void snmp_add_ifinoctets(u32_t value) +/** + * Initializes sysName value (from lwIP external non-volatile memory). + * + * @param str if non-NULL then copy str + * @param strlen string length, excluding zero terminator + */ +void snmp_set_sysname(u8_t *ocstr, u8_t ocstrlen) { - ifinoctets += value; + if (ocstr != NULL) + { + ocstrlen = ((ocstrlen < sizeof(sysname))?(ocstrlen):(sizeof(sysname))); + ocstrncpy(sysname, ocstr, ocstrlen); + } } -void snmp_inc_ifinucastpkts(void) +/** + * Initializes sysLocation value (from lwIP external non-volatile memory). + * + * @param str if non-NULL then copy str + * @param strlen string length, excluding zero terminator + */ +void snmp_set_syslocation(u8_t *ocstr, u8_t ocstrlen) { - ifinucastpkts++; + if (ocstr != NULL) + { + ocstrlen = ((ocstrlen < sizeof(syslocation))?(ocstrlen):(sizeof(syslocation))); + ocstrncpy(syslocation, ocstr, ocstrlen); + } } -void snmp_inc_ifinnucastpkts(void) + +void snmp_add_ifinoctets(struct netif *ni, u32_t value) { - ifinnucastpkts++; + ni->ifinoctets += value; } -void snmp_inc_ifindiscards(void) +void snmp_inc_ifinucastpkts(struct netif *ni) { - ifindiscards++; + (ni->ifinucastpkts)++; } -void snmp_add_ifoutoctets(u32_t value) +void snmp_inc_ifinnucastpkts(struct netif *ni) { - ifoutoctets += value; + (ni->ifinnucastpkts)++; } -void snmp_inc_ifoutucastpkts(void) +void snmp_inc_ifindiscards(struct netif *ni) { - ifoutucastpkts++; + (ni->ifindiscards)++; } -void snmp_inc_ifoutnucastpkts(void) +void snmp_add_ifoutoctets(struct netif *ni, u32_t value) { - ifoutnucastpkts++; + ni->ifoutoctets += value; } -void snmp_inc_ifoutdiscards(void) +void snmp_inc_ifoutucastpkts(struct netif *ni) { - ifoutdiscards++; + (ni->ifoutucastpkts)++; +} + +void snmp_inc_ifoutnucastpkts(struct netif *ni) +{ + (ni->ifoutnucastpkts)++; +} + +void snmp_inc_ifoutdiscards(struct netif *ni) +{ + (ni->ifoutdiscards)++; } void snmp_inc_ipindelivers(void) @@ -585,9 +907,503 @@ void snmp_inc_snmpouttraps(void) snmpouttraps++; } -void snmp_get_snmpgrpid(const struct snmp_obj_id **oid) +void snmp_get_snmpgrpid_ptr(struct snmp_obj_id **oid) { *oid = &snmpgrp_id; } + +void +noleafs_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od) +{ + if(ident_len){} + if(ident){} + od->instance = MIB_OBJECT_NONE; +} + +void +noleafs_get_value(u8_t ident_len, s32_t *ident, u16_t len, void *value) +{ + if(ident_len){} + if(ident){} + if(len){} + if(value){} +} + + + + +/** + * Returns systems object definitions. + * + * @param ident_len the address length (2) + * @param ident points to objectname.0 (object id trailer) + * @param od points to object definition. + */ +static void +system_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od) +{ + u8_t id; + + if ((ident_len == 2) && (ident[1] == 0)) + { + od->id_inst_len = ident_len; + od->id_inst_ptr = ident; + + id = ident[0]; + LWIP_DEBUGF(SNMP_MIB_DEBUG,("get_object_def system.%"U16_F".0",(u16_t)id)); + switch (id) + { + case 1: /* sysDescr */ + od->instance = MIB_OBJECT_SCALAR; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR); + od->v_len = sysdescr_len; + break; + case 2: /* sysObjectID */ + od->instance = MIB_OBJECT_SCALAR; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OBJ_ID); + od->v_len = SNMP_SYSOBJID_LEN * sizeof(s32_t); + break; + case 3: /* sysUpTime */ + od->instance = MIB_OBJECT_SCALAR; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_TIMETICKS); + od->v_len = sizeof(u32_t); + break; + case 4: /* sysContact */ + od->instance = MIB_OBJECT_SCALAR; + od->access = MIB_OBJECT_READ_WRITE; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR); + od->v_len = syscontact_len; + break; + case 5: /* sysName */ + od->instance = MIB_OBJECT_SCALAR; + od->access = MIB_OBJECT_READ_WRITE; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR); + od->v_len = sysname_len; + break; + case 6: /* sysLocation */ + od->instance = MIB_OBJECT_SCALAR; + od->access = MIB_OBJECT_READ_WRITE; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR); + od->v_len = syslocation_len; + break; + case 7: /* sysServices */ + od->instance = MIB_OBJECT_SCALAR; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG); + od->v_len = sizeof(s32_t); + break; + default: + od->instance = MIB_OBJECT_NONE; + break; + }; + } + else + { + LWIP_DEBUGF(SNMP_MIB_DEBUG,("system_get_object_def: no scalar")); + od->instance = MIB_OBJECT_NONE; + } +} + +/** + * Returns system object value. + * + * @param ident_len the address length (2) + * @param ident points to objectname.0 (object id trailer) + * @param len return value space (in bytes) + * @param value points to (varbind) space to copy value into. + */ +static void +system_get_value(u8_t ident_len, s32_t *ident, u16_t len, void *value) +{ + u8_t id; + + id = ident[0]; + switch (id) + { + case 1: /* sysDescr */ + ocstrncpy(value,sysdescr,len); + break; + case 2: /* sysObjectID */ + objectidncpy((s32_t*)value,(s32_t*)sysobjid.id,len / sizeof(s32_t)); + break; + case 3: /* sysUpTime */ + if (len == sizeof(u32_t)) + { + u32_t *uint_ptr = value; + + *uint_ptr = sysuptime; + } + break; + case 4: /* sysContact */ + ocstrncpy(value,syscontact,len); + break; + case 5: /* sysName */ + ocstrncpy(value,sysname,len); + break; + case 6: /* sysLocation */ + ocstrncpy(value,syslocation,len); + break; + case 7: /* sysServices */ + if (len == sizeof(s32_t)) + { + s32_t *sint_ptr = value; + + *sint_ptr = sysservices; + } + break; + default: + break; + }; + if (ident_len){} +} + +/** + * Returns interfaces.ifnumber object definition. + * + * @param ident_len the address length (2) + * @param ident points to objectname.index + * @param od points to object definition. + */ +static void +interfaces_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od) +{ + if ((ident_len == 2) && (ident[0] == 1) && (ident[1] == 0)) + { + od->id_inst_len = ident_len; + od->id_inst_ptr = ident; + + od->instance = MIB_OBJECT_SCALAR; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG); + od->v_len = sizeof(s32_t); + } + else + { + LWIP_DEBUGF(SNMP_MIB_DEBUG,("interfaces_get_object_def: no scalar")); + od->instance = MIB_OBJECT_NONE; + } + if (ident_len){} +} + +/** + * Returns interfaces.ifnumber object value. + * + * @param ident_len the address length (2) + * @param ident points to objectname.0 (object id trailer) + * @param len return value space (in bytes) + * @param value points to (varbind) space to copy value into. + */ +static void +interfaces_get_value(u8_t ident_len, s32_t *ident, u16_t len, void *value) +{ + if (ident[0] == 1) + { + if (len == sizeof(s32_t)) + { + s32_t *sint_ptr = value; + *sint_ptr = netif_cnt; + } + } + if (ident_len){} +} + +/** + * Returns ifentry object definitions. + * + * @param ident_len the address length (2) + * @param ident points to objectname.index + * @param od points to object definition. + */ +static void +ifentry_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od) +{ + u8_t id; + + if ((ident_len == 2) && (ident[1] > 0) && (ident[1] <= netif_cnt)) + { + od->id_inst_len = ident_len; + od->id_inst_ptr = ident; + + id = ident[0]; + LWIP_DEBUGF(SNMP_MIB_DEBUG,("get_object_def ifentry.%"U16_F".",(u16_t)id)); + switch (id) + { + case 1: /* ifIndex */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG); + od->v_len = sizeof(s32_t); + break; + case 2: /* ifDescr */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR); + /** @todo this should be some sort of sizeof(struct netif.name) */ + od->v_len = 2; + break; + case 3: /* ifType */ + case 4: /* ifMtu */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG); + od->v_len = sizeof(s32_t); + break; + case 5: /* ifSpeed */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_GAUGE); + od->v_len = sizeof(u32_t); + break; + case 6: /* ifPhysAddress */ + { + struct netif *netif = netif_list; + u16_t i, ifidx; + + ifidx = ident[1] - 1; + i = 0; + while ((netif != NULL) && (i < ifidx)) + { + netif = netif->next; + i++; + } + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR); + od->v_len = netif->hwaddr_len; + } + break; + case 7: /* ifAdminStatus */ + 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); + break; + case 8: /* ifOperStatus */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG); + od->v_len = sizeof(s32_t); + break; + case 9: /* ifLastChange */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_TIMETICKS); + od->v_len = sizeof(u32_t); + break; + case 10: /* ifInOctets */ + case 11: /* ifInUcastPkts */ + case 12: /* ifInNUcastPkts */ + case 13: /* ifInDiscarts */ + case 14: /* ifInErrors */ + case 15: /* ifInUnkownProtos */ + case 16: /* ifOutOctets */ + case 17: /* ifOutUcastPkts */ + case 18: /* ifOutNUcastPkts */ + case 19: /* ifOutDiscarts */ + case 20: /* ifOutErrors */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_COUNTER); + od->v_len = sizeof(u32_t); + break; + case 21: /* ifOutQLen */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_GAUGE); + od->v_len = sizeof(u32_t); + break; + case 22: /* ifSpecific */ + /* @bug not returning null object id ... */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OBJ_ID); + od->v_len = ifspecific.len * sizeof(s32_t); + break; + default: + od->instance = MIB_OBJECT_NONE; + break; + }; + } + else + { + LWIP_DEBUGF(SNMP_MIB_DEBUG,("ifentry_get_object_def: no scalar")); + od->instance = MIB_OBJECT_NONE; + } +} + +/** + * Returns ifentry object value. + * + * @param ident_len the address length (2) + * @param ident points to objectname.0 (object id trailer) + * @param len return value space (in bytes) + * @param value points to (varbind) space to copy value into. + */ +static void +ifentry_get_value(u8_t ident_len, s32_t *ident, u16_t len, void *value) +{ + struct netif *netif = netif_list; + u16_t i, ifidx; + u8_t id; + + ifidx = ident[1] - 1; + i = 0; + while ((netif != NULL) && (i < ifidx)) + { + netif = netif->next; + i++; + } + id = ident[0]; + switch (id) + { + case 1: /* ifIndex */ + if (len == sizeof(s32_t)) + { + s32_t *sint_ptr = value; + *sint_ptr = ident[1]; + } + break; + case 2: /* ifDescr */ + ocstrncpy(value,(u8_t*)netif->name,len); + break; + case 3: /* ifType */ + if (len == sizeof(s32_t)) + { + s32_t *sint_ptr = value; + *sint_ptr = netif->link_type; + } + break; + case 4: /* ifMtu */ + if (len == sizeof(s32_t)) + { + s32_t *sint_ptr = value; + *sint_ptr = netif->mtu; + } + break; + case 5: /* ifSpeed */ + if (len == sizeof(u32_t)) + { + u32_t *uint_ptr = value; + *uint_ptr = netif->link_speed; + } + break; + case 6: /* ifPhysAddress */ + ocstrncpy(value,netif->hwaddr,len); + break; + case 7: /* ifAdminStatus */ + case 8: /* ifOperStatus */ + if (len == sizeof(s32_t)) + { + s32_t *sint_ptr = value; + if (netif_is_up(netif)) + { + *sint_ptr = 1; + } + else + { + *sint_ptr = 2; + } + } + break; + case 9: /* ifLastChange */ + if (len == sizeof(u32_t)) + { + u32_t *uint_ptr = value; + *uint_ptr = netif->ts; + } + break; + case 10: /* ifInOctets */ + if (len == sizeof(u32_t)) + { + u32_t *uint_ptr = value; + *uint_ptr = netif->ifinoctets; + } + break; + case 11: /* ifInUcastPkts */ + if (len == sizeof(u32_t)) + { + u32_t *uint_ptr = value; + *uint_ptr = netif->ifinucastpkts; + } + break; + case 12: /* ifInNUcastPkts */ + if (len == sizeof(u32_t)) + { + u32_t *uint_ptr = value; + *uint_ptr = netif->ifinnucastpkts; + } + break; + case 13: /* ifInDiscarts */ + if (len == sizeof(u32_t)) + { + u32_t *uint_ptr = value; + *uint_ptr = netif->ifindiscards; + } + break; + case 14: /* ifInErrors */ + case 15: /* ifInUnkownProtos */ + /** @todo add these counters! */ + if (len == sizeof(u32_t)) + { + u32_t *uint_ptr = value; + *uint_ptr = 0; + } + break; + case 16: /* ifOutOctets */ + if (len == sizeof(u32_t)) + { + u32_t *uint_ptr = value; + *uint_ptr = netif->ifoutoctets; + } + break; + case 17: /* ifOutUcastPkts */ + if (len == sizeof(u32_t)) + { + u32_t *uint_ptr = value; + *uint_ptr = netif->ifoutucastpkts; + } + break; + case 18: /* ifOutNUcastPkts */ + if (len == sizeof(u32_t)) + { + u32_t *uint_ptr = value; + *uint_ptr = netif->ifoutnucastpkts; + } + break; + case 19: /* ifOutDiscarts */ + if (len == sizeof(u32_t)) + { + u32_t *uint_ptr = value; + *uint_ptr = netif->ifoutdiscards; + } + break; + case 20: /* ifOutErrors */ + /** @todo add this counter! */ + if (len == sizeof(u32_t)) + { + u32_t *uint_ptr = value; + *uint_ptr = 0; + } + break; + case 21: /* ifOutQLen */ + /** @todo figure out if this must be 0 (no queue) or 1? */ + if (len == sizeof(u32_t)) + { + u32_t *uint_ptr = value; + *uint_ptr = 0; + } + break; + case 22: /* ifSpecific */ + objectidncpy((s32_t*)value,(s32_t*)ifspecific.id,len / sizeof(s32_t)); + break; + default: + break; + }; + if (ident_len){} +} + #endif /* LWIP_SNMP */ \ No newline at end of file diff --git a/src/core/snmp/mib_structs.c b/src/core/snmp/mib_structs.c new file mode 100644 index 00000000..0d2dfd8e --- /dev/null +++ b/src/core/snmp/mib_structs.c @@ -0,0 +1,224 @@ +/** + * @file + * [EXPERIMENTAL] Generic MIB tree access/construction functions. + */ + +/* + * 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 "lwip/opt.h" +#include "lwip/snmp_structs.h" + +#if LWIP_SNMP + +/** + * Searches tree for the supplied (scalar?) object identifier. + * + * @param node points to the root of the tree ('.internet') + * @param ident_len the length of the supplied object identifier + * @param ident points to the array of sub identifiers + * @param object_def points to the object definition to return + * @return pointer to the requested parent (!) node if success, NULL otherwise + */ +struct mib_node * +snmp_search_tree(struct mib_node *node, u8_t ident_len, s32_t *ident, struct obj_def *object_def) +{ + u8_t node_type; + + LWIP_DEBUGF(SNMP_MIB_DEBUG,("node==%p *ident==%"S32_F,(void*)node,*ident)); + while (node != NULL) + { + node_type = node->node_type; + if ((node_type == MIB_NODE_AR) || (node_type == MIB_NODE_RA)) + { + struct mib_array_node *an; + u16_t i; + + /* array node (internal ROM or RAM, fixed length) */ + an = (struct mib_array_node *)node; + i = 0; + while ((i < an->maxlength) && (an->objid[i] != *ident)) + { + i++; + } + if (i < an->maxlength) + { + if (ident_len > 0) + { + /* found it, if available proceed to child, otherwise inspect leaf */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("an->objid[%"U16_F"]==%"S32_F" *ident==%"S32_F,i,an->objid[i],*ident)); + if (an->nptr[i] == NULL) + { + /* a scalar leaf OR table, + inspect remaining instance number / table index */ + /* retrieve object definition with get_object_def() + is it scalar, or a valid table item, or non-existent? */ + an->get_object_def(ident_len, ident, object_def); + if (object_def->instance != MIB_OBJECT_NONE) + { + /** @todo return something more usefull ?? */ + return (struct mib_node*)an; + } + else + { + /* search failed, object id points to unknown object (nosuchname) */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("search failed, object not in this MIB")); + return NULL; + } + } + else + { + /* follow next child pointer */ + ident++; + ident_len--; + node = an->nptr[i]; + } + } + else + { + /* search failed, short object identifier (nosuchname) */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("search failed, short object identifier")); + return NULL; + } + } + else + { + /* search failed, identifier mismatch (nosuchname) */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("search failed *ident==%"S32_F,*ident)); + return NULL; + } + } + else if(node_type == MIB_NODE_LR) + { + struct mib_list_rootnode *lrn; + struct mib_list_node *ln; + + /* list root node (internal 'RAM', variable length) */ + lrn = (struct mib_list_rootnode *)node; + ln = lrn->head; + /* iterate over list, head to tail */ + while ((ln != NULL) && (ln->objid != *ident)) + { + ln = ln->next; + } + if (ln != NULL) + { + if (ident_len > 0) + { + /* found it, proceed to child */; + LWIP_DEBUGF(SNMP_MIB_DEBUG,("ln->objid==%"S32_F" *ident==%"S32_F,ln->objid,*ident)); + if (ln->nptr == NULL) + { + lrn->get_object_def(ident_len, ident, object_def); + if (object_def->instance != MIB_OBJECT_NONE) + { + /** @todo return something more usefull ?? */ + return (struct mib_node*)lrn; + } + else + { + /* search failed, object id points to unknown object (nosuchname) */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("search failed, object not in this MIB")); + return NULL; + } + } + else + { + /* follow next child pointer */ + ident_len--; + ident++; + node = ln->nptr; + } + } + else + { + /* search failed, short object identifier (nosuchname) */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("search failed, short object identifier")); + return NULL; + } + } + else + { + /* search failed */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("search failed *ident==%"S32_F,*ident)); + return NULL; + } + } + else if(node_type == MIB_NODE_EX) + { + struct mib_external_node *en; + u16_t i; + + /* external node (addressing and access via functions) */ + en = (struct mib_external_node *)node; + i = 0; + while ((i < en->count) && en->ident_cmp(i,*ident)) + { + i++; + } + if (i < en->count) + { + if (ident_len > 0) + { + if (en->get_nptr(i) == NULL) + { +/** @todo, this object is elsewhere, we can only start the request, + but can't return something usefull yet.*/ + en->req_object_def(ident_len, ident); + return (struct mib_node*)en; + } + else + { + /* found it, proceed to child */ + ident_len--; + ident++; + node = (struct mib_node*)en->get_nptr(i); + } + } + else + { + /* search failed, short object identifier (nosuchname) */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("search failed, short object identifier")); + return NULL; + } + } + else + { + /* search failed */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("search failed *ident==%"S32_F,*ident)); + return NULL; + } + } + } + /* done, found nothing */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("search failed node==%p",(void*)node)); + return NULL; +} + +#endif /* LWIP_SNMP */ diff --git a/src/core/snmp/msg_in.c b/src/core/snmp/msg_in.c index 28b9ebb3..eb3857f7 100644 --- a/src/core/snmp/msg_in.c +++ b/src/core/snmp/msg_in.c @@ -47,9 +47,11 @@ #include "lwip/snmp_asn1.h" #include "lwip/snmp_msg.h" +#include "lwip/snmp_structs.h" #if LWIP_SNMP +#define LWIP_SNMP_DBG_LOOPBACK_TST 0 #define SNMP_CONCURRENT_REQUESTS 2 /* public (non-static) constants */ @@ -72,8 +74,16 @@ static void snmp_varbind_list_free(struct snmp_varbind_root *root); static void snmp_varbind_tail_add(struct snmp_varbind_root *root, struct snmp_varbind *vb); static struct snmp_varbind* snmp_varbind_tail_remove(struct snmp_varbind_root *root); +/** @todo: move this to header */ +extern const struct mib_array_node internet; +extern const struct mib_array_node sys_tem; /* test only */ -void snmp_init(void) +/** + * Starts SNMP Agent. + * Allocates UDP pcb and binds it to IP_ADDR_ANY port 161. + */ +void +snmp_init(void) { struct snmp_msg_pstat *msg_ps; u8_t i; @@ -95,6 +105,14 @@ void snmp_init(void) trap_msg.pcb = snmp1_pcb; } +/** + * + */ +void +snmp_msg_event(void) +{ +} + /* lwIP UDP receive callback function */ static void snmp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *addr, u16_t port) @@ -155,14 +173,65 @@ snmp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *addr, err_ret = snmp_pdu_dec_varbindlist(p, varbind_ofs, &varbind_ofs, msg_ps); if (err_ret == ERR_OK) { + struct mib_node *mn; + struct obj_def object_def; + /* we've decoded the incoming message, release input msg now */ pbuf_free(p); LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_recv varbind cnt=%"U16_F"\n",(u16_t)msg_ps->invb.count)); - /** @todo EXPERIMENTAL dumb echo, this is not how the agent should respond. - This is for test purposes only, do not use this in real world!! */ - msg_ps->outvb = msg_ps->invb; + if (msg_ps->rt == SNMP_ASN1_PDU_GET_REQ) + { + /** @todo check if count > 0 and if we got .iso.dod.internet and iterate from vb 0 .. count-1 */ + mn = snmp_search_tree((struct mib_node*)&internet, msg_ps->invb.head->ident_len - 2 /* trim iso.dod.internet */, + msg_ps->invb.head->ident + 2, &object_def); + if (mn != NULL) + { + LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_recv mn=%p sys_tem=%p node_typ=%"U16_F, + (void*)mn,(void*)&sys_tem,(u16_t)mn->node_type)); + + if (msg_ps->invb.head->value != NULL) + { + LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_recv free value before vb recycle")); + mem_free(msg_ps->invb.head->value); + } + msg_ps->invb.head->value_type = object_def.asn_type; + msg_ps->invb.head->value_len = object_def.v_len; + msg_ps->invb.head->value = mem_malloc(object_def.v_len); + if (msg_ps->invb.head->value != NULL) + { + mn->get_value(object_def.id_inst_len, object_def.id_inst_ptr, object_def.v_len, msg_ps->invb.head->value); + } + else + { + LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_recv couldn't allocate variable space")); + } + msg_ps->outvb = msg_ps->invb; + } + else + { + /* mn == NULL, noSuchName */ + msg_ps->error_status = SNMP_ES_NOSUCHNAME; + /** @todo current varbind index */ + msg_ps->error_index = 1; + msg_ps->outvb.head = NULL; + msg_ps->outvb.tail = NULL; + msg_ps->outvb.count = 0; + msg_ps->outvb.seqlen = 0; + msg_ps->outvb.seqlenlen = 1; + } + } + else + { + /* request != GET */ + /** @todo EXPERIMENTAL dumb echo, this is not how the agent should respond. + This is for test purposes only, do not use this in real world!! */ + msg_ps->outvb = msg_ps->invb; + msg_ps->error_status = SNMP_ES_NOERROR; + msg_ps->error_index = 0; + } + err_ret = snmp_send_response(msg_ps); if (err_ret == ERR_MEM) { diff --git a/src/core/snmp/msg_out.c b/src/core/snmp/msg_out.c index 09049feb..e9e9bec8 100644 --- a/src/core/snmp/msg_out.c +++ b/src/core/snmp/msg_out.c @@ -76,7 +76,7 @@ static u16_t snmp_varbind_list_enc(struct snmp_varbind_root *root, struct pbuf * * @return ERR_OK when success, ERR_MEM if we're out of memory * * @note the caller is responsible for filling in outvb in the m_stat - * @todo caller must provide error-status and index ... + * and provide error-status and index (except for tooBig errors) ... */ err_t snmp_send_response(struct snmp_msg_pstat *m_stat) @@ -86,9 +86,6 @@ snmp_send_response(struct snmp_msg_pstat *m_stat) u16_t tot_len; err_t err; - m_stat->error_status = SNMP_ES_NOERROR; - m_stat->error_index = 0; - /* pass 0, calculate length fields */ tot_len = snmp_varbind_list_sum(&m_stat->outvb); tot_len = snmp_resp_header_sum(m_stat, tot_len); @@ -207,12 +204,12 @@ snmp_send_trap(struct ip_addr *dst, s8_t generic_trap, s32_t specific_trap) if (generic_trap == 6) { /* enterprise-Specific trap */ - snmp_get_sysobjid(&trap_msg.enterprise); + snmp_get_sysobjid_ptr(&trap_msg.enterprise); } else { /* generic (MIB-II) trap */ - snmp_get_snmpgrpid(&trap_msg.enterprise); + snmp_get_snmpgrpid_ptr(&trap_msg.enterprise); } snmp_get_sysuptime(&trap_msg.ts); diff --git a/src/include/lwip/snmp.h b/src/include/lwip/snmp.h index 244cdd8e..7fc0fda1 100644 --- a/src/include/lwip/snmp.h +++ b/src/include/lwip/snmp.h @@ -49,7 +49,7 @@ struct snmp_obj_id }; /* system */ -void snmp_set_sysdesr(char* str, u8_t strlen); +void snmp_set_sysdesr(u8_t* str, u8_t strlen); void snmp_set_sysobjid(struct snmp_obj_id *oid); void snmp_get_sysobjid_ptr(struct snmp_obj_id **oid); void snmp_inc_sysuptime(void); diff --git a/src/include/lwip/snmp_structs.h b/src/include/lwip/snmp_structs.h new file mode 100644 index 00000000..c5de341e --- /dev/null +++ b/src/include/lwip/snmp_structs.h @@ -0,0 +1,179 @@ +/** + * @file + * [EXPERIMENTAL] Generic MIB tree structures. + * + * @todo namespace prefixes + */ + +/* + * 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 + */ + +#ifndef __LWIP_SNMP_STRUCTS_H__ +#define __LWIP_SNMP_STRUCTS_H__ + +#include "lwip/opt.h" +#include "arch/cc.h" + +#if SNMP_PRIVATE_MIB +#include "private_mib.h" +#endif + +/* MIB object instance */ +#define MIB_OBJECT_NONE 0 +#define MIB_OBJECT_SCALAR 1 +#define MIB_OBJECT_TAB 2 + +/* MIB object access */ +#define MIB_OBJECT_READ_ONLY 0 +#define MIB_OBJECT_READ_WRITE 1 +#define MIB_OBJECT_WRITE_ONLY 2 +#define MIB_OBJECT_NOT_ACCESSIBLE 3 + +/** object definition returned by (get_object_def)() */ +struct obj_def +{ + /* MIB_OBJECT_NONE (0), MIB_OBJECT_SCALAR (1), MIB_OBJECT_TAB (2) */ + u8_t instance; + /* 0 read-only, 1 read-write, 2 write-only, 3 not-accessible */ + u8_t access; + /* ASN type for this object */ + u8_t asn_type; + /* value length (host length) */ + u16_t v_len; + /* length of instance part of supplied object identifier */ + u8_t id_inst_len; + /* instance part of supplied object identifier */ + s32_t *id_inst_ptr; +}; + +/** MIB const array node */ +#define MIB_NODE_AR 0x01 +/** MIB array node (mem_malloced from RAM) */ +#define MIB_NODE_RA 0x02 +/** MIB list root node (mem_malloced from RAM) */ +#define MIB_NODE_LR 0x03 +/** MIB node for external objects */ +#define MIB_NODE_EX 0x04 + +/** node "base class" layout, the mandatory fields for a node */ +struct mib_node +{ + /** returns struct obj_def for the given object identifier */ + void (*get_object_def)(u8_t ident_len, s32_t *ident, struct obj_def *od); + /** returns object value for the given object identifier, + @note the caller must allocate at least len bytes for the value */ + void (*get_value)(u8_t ident_len, s32_t *ident, u16_t len, void *value); + /** @todo set_value() */ + /** One out of MIB_NODE_AR, MIB_NODE_LR or MIB_NODE_EX */ + const u8_t node_type; + /* array or max list length */ + const u16_t maxlength; +}; + +/** derived node, points to a fixed size const array + of sub-identifiers plus a 'child' pointer */ +struct mib_array_node +{ + /* inherited "base class" */ + const void (*get_object_def)(u8_t ident_len, s32_t *ident, struct obj_def *od); + const void (*get_value)(u8_t ident_len, s32_t *ident, u16_t len, void *value); + const u8_t node_type; + const u16_t maxlength; + + /* aditional struct members */ + const s32_t *objid; + struct mib_node* const *nptr; +}; + +/** derived node, points to a fixed size mem_malloced array + of sub-identifiers plus a 'child' pointer */ +struct mib_ram_array_node +{ + /* inherited "base class" */ + void (*get_object_def)(u8_t ident_len, s32_t *ident, struct obj_def *od); + void (*get_value)(u8_t ident_len, s32_t *ident, u16_t len, void *value); + u8_t node_type; + u16_t maxlength; + + /* aditional struct members */ + s32_t *objid; + struct mib_node **nptr; +}; + +struct mib_list_node +{ + struct mib_list_node *prev; + struct mib_list_node *next; + s32_t objid; + struct mib_node *nptr; +}; + +/** derived node, points to a doubly linked list + of sub-identifiers plus a 'child' pointer */ +struct mib_list_rootnode +{ + /* inherited "base class" */ + void (*get_object_def)(u8_t ident_len, s32_t *ident, struct obj_def *od); + void (*get_value)(u8_t ident_len, s32_t *ident, u16_t len, void *value); + u8_t node_type; + u16_t maxlength; + + /* aditional struct members */ + struct mib_list_node *head; + struct mib_list_node *tail; + /* counts list nodes in list */ + u16_t count; +}; + +/** derived node, has access functions for mib object in external memory or device + using index ('idx'), with a range 0 .. (count - 1) to address these objects */ +struct mib_external_node +{ + /* inherited "base class" */ + void (*get_object_def)(u8_t ident_len, s32_t *ident, struct obj_def *od); + void (*get_value)(u8_t ident_len, s32_t *ident, u16_t len, void *value); + u8_t node_type; + u16_t maxlength; + + /* aditional struct members */ + void (*req_object_def)(u8_t ident_len, s32_t *ident); + void (*getreq_value)(u8_t ident_len, s32_t *ident); + + /** compares object sub identifier with externally available id + return zero when equal, nonzero when unequal */ + u16_t (*ident_cmp)(u16_t idx, s32_t sub_id); + /** returns next pointer for given index (NULL for scalar 'leaf') */ + struct mib_extern_node* (*get_nptr)(u16_t idx); + /* counts actual number of external objects */ + u16_t count; +}; + +struct mib_node* snmp_search_tree(struct mib_node *node, u8_t ident_len, s32_t *ident, struct obj_def *object_def); + +#endif