diff --git a/src/core/snmp/mib2.c b/src/core/snmp/mib2.c index 54cfb294..384d7052 100644 --- a/src/core/snmp/mib2.c +++ b/src/core/snmp/mib2.c @@ -267,6 +267,8 @@ struct mib_ram_array_node tcpconntable = { const mib_scalar_node tcp_scalar = { &tcp_get_object_def, &tcp_get_value, + &noleafs_set_test, + &noleafs_set_value, MIB_NODE_SC, 0 }; diff --git a/src/core/snmp/mib_structs.c b/src/core/snmp/mib_structs.c index 8ce5a07c..d1a76248 100644 --- a/src/core/snmp/mib_structs.c +++ b/src/core/snmp/mib_structs.c @@ -447,14 +447,15 @@ snmp_mib_node_delete(struct mib_list_rootnode *rn, struct mib_list_node *n) * @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 + * @param np points to the found object instance (rerurn) * @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) +snmp_search_tree(struct mib_node *node, u8_t ident_len, s32_t *ident, struct snmp_name_ptr *np) { - u8_t node_type; + u8_t node_type, ext_level; + ext_level = 0; LWIP_DEBUGF(SNMP_MIB_DEBUG,("node==%p *ident==%"S32_F"\n",(void*)node,*ident)); while (node != NULL) { @@ -481,20 +482,9 @@ snmp_search_tree(struct mib_node *node, u8_t ident_len, s32_t *ident, struct obj { /* 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\n")); - return NULL; - } + np->ident_len = ident_len; + np->ident = ident; + return (struct mib_node*)an; } else { @@ -507,14 +497,14 @@ snmp_search_tree(struct mib_node *node, u8_t ident_len, s32_t *ident, struct obj else { /* search failed, identifier mismatch (nosuchname) */ - LWIP_DEBUGF(SNMP_MIB_DEBUG,("search failed *ident==%"S32_F"\n",*ident)); + LWIP_DEBUGF(SNMP_MIB_DEBUG,("an search failed *ident==%"S32_F"\n",*ident)); return NULL; } } else { /* search failed, short object identifier (nosuchname) */ - LWIP_DEBUGF(SNMP_MIB_DEBUG,("search failed, short object identifier\n")); + LWIP_DEBUGF(SNMP_MIB_DEBUG,("an search failed, short object identifier\n")); return NULL; } } @@ -539,18 +529,9 @@ snmp_search_tree(struct mib_node *node, u8_t ident_len, s32_t *ident, struct obj LWIP_DEBUGF(SNMP_MIB_DEBUG,("ln->objid==%"S32_F" *ident==%"S32_F"\n",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\n")); - return NULL; - } + np->ident_len = ident_len; + np->ident = ident; + return (struct mib_node*)lrn; } else { @@ -563,38 +544,43 @@ snmp_search_tree(struct mib_node *node, u8_t ident_len, s32_t *ident, struct obj else { /* search failed */ - LWIP_DEBUGF(SNMP_MIB_DEBUG,("search failed *ident==%"S32_F"\n",*ident)); + LWIP_DEBUGF(SNMP_MIB_DEBUG,("ln search failed *ident==%"S32_F"\n",*ident)); return NULL; } } else { /* search failed, short object identifier (nosuchname) */ - LWIP_DEBUGF(SNMP_MIB_DEBUG,("search failed, short object identifier\n")); + LWIP_DEBUGF(SNMP_MIB_DEBUG,("ln search failed, short object identifier\n")); return NULL; } } else if(node_type == MIB_NODE_EX) { struct mib_external_node *en; - u16_t i; + u16_t i, len; if (ident_len > 0) { /* external node (addressing and access via functions) */ en = (struct mib_external_node *)node; + i = 0; - while ((i < en->count) && en->ident_cmp(i,*ident)) + len = en->level_length(en->addr_inf,ext_level); + while ((i < len) && (en->ident_cmp(en->addr_inf,ext_level,i,*ident) != 0)) { i++; } - if (i < en->count) + if (i < len) { - if (en->get_nptr(i) == NULL) + s32_t debug_id; + + en->get_objid(en->addr_inf,ext_level,i,&debug_id); + LWIP_DEBUGF(SNMP_MIB_DEBUG,("en->objid==%"S32_F" *ident==%"S32_F"\n",debug_id,*ident)); + if ((ext_level + 1) == en->tree_levels) { -/** @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); + np->ident_len = ident_len; + np->ident = ident; return (struct mib_node*)en; } else @@ -602,20 +588,20 @@ snmp_search_tree(struct mib_node *node, u8_t ident_len, s32_t *ident, struct obj /* found it, proceed to child */ ident_len--; ident++; - node = (struct mib_node*)en->get_nptr(i); + ext_level++; } } else { /* search failed */ - LWIP_DEBUGF(SNMP_MIB_DEBUG,("search failed *ident==%"S32_F"\n",*ident)); + LWIP_DEBUGF(SNMP_MIB_DEBUG,("en search failed *ident==%"S32_F"\n",*ident)); return NULL; } } else { /* search failed, short object identifier (nosuchname) */ - LWIP_DEBUGF(SNMP_MIB_DEBUG,("search failed, short object identifier\n")); + LWIP_DEBUGF(SNMP_MIB_DEBUG,("en search failed, short object identifier\n")); return NULL; } } @@ -626,7 +612,8 @@ snmp_search_tree(struct mib_node *node, u8_t ident_len, s32_t *ident, struct obj sn = (mib_scalar_node *)node; if ((ident_len == 1) && (*ident == 0)) { - sn->get_object_def(ident_len, ident, object_def); + np->ident_len = ident_len; + np->ident = ident; return (struct mib_node*)sn; } else diff --git a/src/core/snmp/msg_in.c b/src/core/snmp/msg_in.c index c50c6fe5..0832f601 100644 --- a/src/core/snmp/msg_in.c +++ b/src/core/snmp/msg_in.c @@ -121,11 +121,13 @@ snmp_msg_event(struct snmp_msg_pstat *msg_ps) } if (msg_ps->rt == SNMP_ASN1_PDU_GET_REQ) { + struct snmp_name_ptr np; + /** test object identifier for .iso.org.dod.internet prefix */ if (snmp_iso_prefix_tst(msg_ps->vb_ptr->ident_len, msg_ps->vb_ptr->ident)) { mn = snmp_search_tree((struct mib_node*)&internet, msg_ps->vb_ptr->ident_len - 4, - msg_ps->vb_ptr->ident + 4, &object_def); + msg_ps->vb_ptr->ident + 4, &np); } else { @@ -137,14 +139,35 @@ snmp_msg_event(struct snmp_msg_pstat *msg_ps) { /* external object */ msg_ps->state = SNMP_MSG_EXTERNAL; + mn->get_object_def_r(np.ident_len, np.ident, &object_def); + if (object_def.instance != MIB_OBJECT_NONE) + { + mn = mn; + } + else + { + /* search failed, object id points to unknown object (nosuchname) */ + mn = NULL; + } } else { /* internal object */ - msg_ps->state = SNMP_MSG_INTERNAL; + msg_ps->state = SNMP_MSG_INTERNAL; + mn->get_object_def(np.ident_len, np.ident, &object_def); + if (object_def.instance != MIB_OBJECT_NONE) + { + mn = mn; + } + else + { + /* search failed, object id points to unknown object (nosuchname) */ + mn = NULL; + } + msg_ps->state = SNMP_MSG_DEMUX; } } - else + if (mn != NULL) { /* mn == NULL, noSuchName */ snmp_varbind_list_free(&msg_ps->outvb); @@ -264,8 +287,26 @@ snmp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *addr, /** test object identifier for .iso.org.dod.internet prefix */ if (snmp_iso_prefix_tst(msg_ps->invb.head->ident_len, msg_ps->invb.head->ident)) { + struct snmp_name_ptr np; + mn = snmp_search_tree((struct mib_node*)&internet, msg_ps->invb.head->ident_len - 4, - msg_ps->invb.head->ident + 4, &object_def); + msg_ps->invb.head->ident + 4, &np); + if (mn != NULL) + { + /* retrieve object definition with get_object_def() + is it scalar, table item, external or non-existent? */ + mn->get_object_def(np.ident_len, np.ident, &object_def); + if (object_def.instance != MIB_OBJECT_NONE) + { + mn = mn; + } + else + { + /* search failed, object id points to unknown object (nosuchname) */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("mn search failed, object not in this MIB\n")); + mn = NULL; + } + } } else { @@ -377,8 +418,26 @@ snmp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *addr, /** test object identifier for .iso.org.dod.internet prefix */ if (snmp_iso_prefix_tst(msg_ps->invb.head->ident_len, msg_ps->invb.head->ident)) { + struct snmp_name_ptr np; + mn = snmp_search_tree((struct mib_node*)&internet, msg_ps->invb.head->ident_len - 4, - msg_ps->invb.head->ident + 4, &object_def); + msg_ps->invb.head->ident + 4, &np); + if (mn != NULL) + { + /* retrieve object definition with get_object_def() + is it scalar, table item, external or non-existent? */ + mn->get_object_def(np.ident_len, np.ident, &object_def); + if (object_def.instance != MIB_OBJECT_NONE) + { + mn = mn; + } + else + { + /* search failed, object id points to unknown object (nosuchname) */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("mn search failed, object not in this MIB\n")); + mn = NULL; + } + } } else { diff --git a/src/include/lwip/snmp_structs.h b/src/include/lwip/snmp_structs.h index d4371b28..5fa3f45f 100644 --- a/src/include/lwip/snmp_structs.h +++ b/src/include/lwip/snmp_structs.h @@ -75,6 +75,12 @@ struct obj_def s32_t *id_inst_ptr; }; +struct snmp_name_ptr +{ + u8_t ident_len; + s32_t *ident; +}; + /** MIB const scalar (.0) node */ #define MIB_NODE_SC 0x01 /** MIB const array node */ @@ -172,7 +178,7 @@ struct mib_list_rootnode }; /** 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 */ + using 'tree_level' and 'idx', with a range 0 .. (level_length() - 1) */ struct mib_external_node { /* inherited "base class" members */ @@ -185,16 +191,23 @@ struct mib_external_node u16_t maxlength; /* aditional struct members */ - void (*req_object_def)(u8_t ident_len, s32_t *ident); - void (*getreq_value)(struct obj_def *od); - - /** compares object sub identifier with externally available id + /** points to an extenal (in memory) record of some sort of addressing + information, passed to and interpreted by the funtions below */ + void* addr_inf; + /** tree levels under this node */ + u8_t tree_levels; + /** number of objects at this level */ + u16_t (*level_length)(void* addr_inf, u8_t level); + /** compares object sub identifier with external 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; + s32_t (*ident_cmp)(void* addr_inf, u8_t level, u16_t idx, s32_t sub_id); + void (*get_objid)(void* addr_inf, u8_t level, u16_t idx, s32_t *sub_id); + + /** async requests */ + void (*get_object_def_r)(u8_t ident_len, s32_t *ident, struct obj_def *od); + void (*get_value_r)(struct obj_def *od, u16_t len, void *value); + u8_t (*set_test_r)(struct obj_def *od, u16_t len, void *value); + void (*set_value_r)(struct obj_def *od, u16_t len, void *value); }; /** export MIB tree from mib2.c */ @@ -220,7 +233,7 @@ s8_t snmp_mib_node_insert(struct mib_list_rootnode *rn, s32_t objid, struct mib_ s8_t snmp_mib_node_find(struct mib_list_rootnode *rn, s32_t objid, struct mib_list_node **fn); struct mib_list_rootnode *snmp_mib_node_delete(struct mib_list_rootnode *rn, struct mib_list_node *n); -struct mib_node* snmp_search_tree(struct mib_node *node, u8_t ident_len, s32_t *ident, struct obj_def *object_def); +struct mib_node* snmp_search_tree(struct mib_node *node, u8_t ident_len, s32_t *ident, struct snmp_name_ptr *np); struct mib_node* snmp_expand_tree(struct mib_node *node, u8_t ident_len, s32_t *ident, struct snmp_obj_id *oidret); u8_t snmp_iso_prefix_tst(u8_t ident_len, s32_t *ident); u8_t snmp_iso_prefix_expand(u8_t ident_len, s32_t *ident, struct snmp_obj_id *oidret);