46 #if (LWIP_SNMP && (SNMP_TRAP_DESTINATIONS<=0)) 47 #error "If you want to use SNMP, you have to define SNMP_TRAP_DESTINATIONS>=1 in your lwipopts.h" 49 #if (!LWIP_UDP && LWIP_SNMP) 50 #error "If you want to use SNMP, you have to define LWIP_UDP=1 in your lwipopts.h" 53 struct snmp_statistics snmp_stats;
55 static const struct snmp_obj_id* snmp_device_enterprise_oid = &snmp_device_enterprise_oid_default;
57 const u32_t snmp_zero_dot_zero_values[] = { 0, 0 };
58 const struct snmp_obj_id_const_ref snmp_zero_dot_zero = {
LWIP_ARRAYSIZE(snmp_zero_dot_zero_values), snmp_zero_dot_zero_values };
63 static const struct snmp_mib *default_mibs[] = { &mib2 };
64 static u8_t snmp_num_mibs = 1;
66 static const struct snmp_mib *default_mibs[] = {
NULL };
67 static u8_t snmp_num_mibs = 0;
71 static struct snmp_mib const **snmp_mibs = default_mibs;
83 snmp_set_mibs(
const struct snmp_mib **mibs,
u8_t num_mibs)
86 LWIP_ASSERT(
"num_mibs pointer must be != 0", (num_mibs != 0));
88 snmp_num_mibs = num_mibs;
91 void snmp_set_device_enterprise_oid(
const struct snmp_obj_id* device_enterprise_oid)
93 if (device_enterprise_oid ==
NULL) {
94 snmp_device_enterprise_oid = &snmp_device_enterprise_oid_default;
96 snmp_device_enterprise_oid = device_enterprise_oid;
100 const struct snmp_obj_id* snmp_get_device_enterprise_oid(
void)
102 return snmp_device_enterprise_oid;
112 snmp_oid_to_ip4(
const u32_t *oid, ip4_addr_t *ip)
114 if((oid[0] > 0xFF) ||
118 ip4_addr_copy(*ip, *IP4_ADDR_ANY);
122 IP4_ADDR(ip, oid[0], oid[1], oid[2], oid[3]);
132 snmp_ip4_to_oid(
const ip4_addr_t *ip,
u32_t *oid)
134 oid[0] = ip4_addr1(ip);
135 oid[1] = ip4_addr2(ip);
136 oid[2] = ip4_addr3(ip);
137 oid[3] = ip4_addr4(ip);
148 snmp_oid_to_ip6(
const u32_t *oid, ip6_addr_t *ip)
150 if((oid[0] > 0xFF) ||
166 ip6_addr_set_any(ip);
170 ip->addr[0] = (oid[0] << 24) | (oid[1] << 16) | (oid[2] << 8) | (oid[3] << 0);
171 ip->addr[1] = (oid[4] << 24) | (oid[5] << 16) | (oid[6] << 8) | (oid[7] << 0);
172 ip->addr[2] = (oid[8] << 24) | (oid[9] << 16) | (oid[10] << 8) | (oid[11] << 0);
173 ip->addr[3] = (oid[12] << 24) | (oid[13] << 16) | (oid[14] << 8) | (oid[15] << 0);
183 snmp_ip6_to_oid(
const ip6_addr_t *ip,
u32_t *oid)
185 oid[0] = (ip->addr[0] & 0xFF000000) >> 24;
186 oid[1] = (ip->addr[0] & 0x00FF0000) >> 16;
187 oid[2] = (ip->addr[0] & 0x0000FF00) >> 8;
188 oid[3] = (ip->addr[0] & 0x000000FF) >> 0;
189 oid[4] = (ip->addr[1] & 0xFF000000) >> 24;
190 oid[5] = (ip->addr[1] & 0x00FF0000) >> 16;
191 oid[6] = (ip->addr[1] & 0x0000FF00) >> 8;
192 oid[7] = (ip->addr[1] & 0x000000FF) >> 0;
193 oid[8] = (ip->addr[2] & 0xFF000000) >> 24;
194 oid[9] = (ip->addr[2] & 0x00FF0000) >> 16;
195 oid[10] = (ip->addr[2] & 0x0000FF00) >> 8;
196 oid[11] = (ip->addr[2] & 0x000000FF) >> 0;
197 oid[12] = (ip->addr[3] & 0xFF000000) >> 24;
198 oid[13] = (ip->addr[3] & 0x00FF0000) >> 16;
199 oid[14] = (ip->addr[3] & 0x0000FF00) >> 8;
200 oid[15] = (ip->addr[3] & 0x000000FF) >> 0;
204 #if LWIP_IPV4 || LWIP_IPV6 217 idx = snmp_ip_to_oid(ip, oid);
237 snmp_ip6_to_oid(
ip_2_ip6(ip), &oid[2]);
246 snmp_ip4_to_oid(ip_2_ip4(ip), &oid[2]);
282 if(!snmp_oid_to_ip4(&oid[2], ip_2_ip4(ip))) {
290 }
else if(oid[0] == 2) {
303 if(!snmp_oid_to_ip6(&oid[2],
ip_2_ip6(ip))) {
330 idx += snmp_oid_to_ip(&oid[idx], oid_len-idx, ip);
336 if(oid_len < (idx+1)) {
339 if(oid[idx] > 0xffff) {
342 *port = (
u16_t)oid[idx];
351 snmp_oid_assign(
struct snmp_obj_id* target,
const u32_t *oid,
u8_t oid_len)
355 target->len = oid_len;
363 snmp_oid_prefix(
struct snmp_obj_id* target,
const u32_t *oid,
u8_t oid_len)
371 for (i = target->len-1; i>=0; i--)
373 target->id[i + oid_len] = target->id[i];
382 snmp_oid_combine(
struct snmp_obj_id* target,
const u32_t *oid1,
u8_t oid1_len,
const u32_t *oid2,
u8_t oid2_len)
384 snmp_oid_assign(target, oid1, oid1_len);
385 snmp_oid_append(target, oid2, oid2_len);
389 snmp_oid_append(
struct snmp_obj_id* target,
const u32_t *oid,
u8_t oid_len)
394 MEMCPY(&target->id[target->len], oid, oid_len *
sizeof(
u32_t));
395 target->len += oid_len;
403 LWIP_ASSERT(
"'oid1' param must not be NULL or 'oid1_len' param be 0!", (oid1 !=
NULL) || (oid1_len == 0));
404 LWIP_ASSERT(
"'oid2' param must not be NULL or 'oid2_len' param be 0!", (oid2 !=
NULL) || (oid2_len == 0));
406 while ((level < oid1_len) && (level < oid2_len))
423 if (oid1_len < oid2_len)
427 if (oid1_len > oid2_len)
439 return (snmp_oid_compare(oid1, oid1_len, oid2, oid2_len) == 0)? 1 : 0;
442 static const struct snmp_mib*
443 snmp_get_mib_from_oid(
const u32_t *oid,
u8_t oid_len)
445 const u32_t* list_oid;
446 const u32_t* searched_oid;
449 u8_t max_match_len = 0;
450 const struct snmp_mib* matched_mib =
NULL;
453 LWIP_ASSERT(
"'oid_len' param must be greater than 0!", (oid_len > 0));
455 for (i=0; i<snmp_num_mibs; i++)
457 LWIP_ASSERT(
"MIB array not initialized correctly", (snmp_mibs[i] !=
NULL));
458 LWIP_ASSERT(
"MIB array not initialized correctly - base OID is NULL", (snmp_mibs[i]->base_oid !=
NULL));
460 if (oid_len >= snmp_mibs[i]->base_oid_len)
462 l = snmp_mibs[i]->base_oid_len;
463 list_oid = snmp_mibs[i]->base_oid;
468 if (*list_oid != *searched_oid)
478 if ((l == 0) && (snmp_mibs[i]->base_oid_len > max_match_len))
480 max_match_len = snmp_mibs[i]->base_oid_len;
481 matched_mib = snmp_mibs[i];
489 static const struct snmp_mib*
490 snmp_get_next_mib(
const u32_t *oid,
u8_t oid_len)
493 const struct snmp_mib* next_mib =
NULL;
496 LWIP_ASSERT(
"'oid_len' param must be greater than 0!", (oid_len > 0));
498 for (i=0; i<snmp_num_mibs; i++)
500 if (snmp_mibs[i]->base_oid !=
NULL)
503 if (snmp_oid_compare(snmp_mibs[i]->base_oid, snmp_mibs[i]->base_oid_len, oid, oid_len) > 0)
505 if ((next_mib ==
NULL) || (snmp_oid_compare(snmp_mibs[i]->base_oid, snmp_mibs[i]->base_oid_len, next_mib->base_oid, next_mib->base_oid_len) < 0))
507 next_mib = snmp_mibs[i];
516 static const struct snmp_mib*
517 snmp_get_mib_between(
const u32_t *oid1,
u8_t oid1_len,
const u32_t *oid2,
u8_t oid2_len)
519 const struct snmp_mib* next_mib = snmp_get_next_mib(oid1, oid1_len);
522 LWIP_ASSERT(
"'oid2_len' param must be greater than 0!", (oid2_len > 0));
524 if (next_mib !=
NULL)
526 if (snmp_oid_compare(next_mib->base_oid, next_mib->base_oid_len, oid2, oid2_len) < 0)
536 snmp_get_node_instance_from_oid(
const u32_t *oid,
u8_t oid_len,
struct snmp_node_instance* node_instance)
538 u8_t result = SNMP_ERR_NOSUCHOBJECT;
539 const struct snmp_mib *mib;
540 const struct snmp_node *mn =
NULL;
542 mib = snmp_get_mib_from_oid(oid, oid_len);
544 u8_t oid_instance_len;
546 mn = snmp_mib_tree_resolve_exact(mib, oid, oid_len, &oid_instance_len);
547 if ((mn !=
NULL) && (mn->node_type != SNMP_NODE_TREE)) {
549 const struct snmp_leaf_node* leaf_node = (
const struct snmp_leaf_node*)mn;
551 node_instance->node = mn;
552 snmp_oid_assign(&node_instance->instance_oid, oid + (oid_len - oid_instance_len), oid_instance_len);
554 result = leaf_node->get_instance(
556 oid_len - oid_instance_len,
560 if(result == SNMP_ERR_NOERROR) {
561 if(((node_instance->access & SNMP_NODE_INSTANCE_ACCESS_READ) != 0) && (node_instance->get_value ==
NULL)) {
562 LWIP_DEBUGF(
SNMP_DEBUG, (
"SNMP inconsistent access: node is readable but no get_value function is specified\n"));
564 if(((node_instance->access & SNMP_NODE_INSTANCE_ACCESS_WRITE) != 0) && (node_instance->set_value ==
NULL)) {
565 LWIP_DEBUGF(
SNMP_DEBUG, (
"SNMP inconsistent access: node is writable but no set_value and/or set_test function is specified\n"));
576 snmp_get_next_node_instance_from_oid(
const u32_t *oid,
u8_t oid_len, snmp_validate_node_instance_method validate_node_instance_method,
void* validate_node_instance_arg,
struct snmp_obj_id* node_oid,
struct snmp_node_instance* node_instance)
578 const struct snmp_mib *mib;
579 const struct snmp_node *mn =
NULL;
581 u8_t start_oid_len = 0;
584 mib = snmp_get_mib_from_oid(oid, oid_len);
587 mib = snmp_get_next_mib(oid, oid_len);
590 start_oid = mib->base_oid;
591 start_oid_len = mib->base_oid_len;
595 start_oid_len = oid_len;
599 while ((mib !=
NULL) && (mn ==
NULL)) {
600 u8_t oid_instance_len;
603 mn = snmp_mib_tree_resolve_exact(mib, start_oid, start_oid_len, &oid_instance_len);
605 snmp_oid_assign(node_oid, start_oid, start_oid_len - oid_instance_len);
606 snmp_oid_assign(&node_instance->instance_oid, start_oid + (start_oid_len - oid_instance_len), oid_instance_len);
609 mn = snmp_mib_tree_resolve_next(mib, start_oid, start_oid_len, node_oid);
610 node_instance->instance_oid.len = 0;
614 node_instance->node = mn;
620 node_instance->asn1_type = 0;
621 node_instance->access = SNMP_NODE_INSTANCE_NOT_ACCESSIBLE;
622 node_instance->get_value =
NULL;
623 node_instance->set_test =
NULL;
624 node_instance->set_value =
NULL;
625 node_instance->release_instance =
NULL;
626 node_instance->reference.ptr =
NULL;
627 node_instance->reference_len = 0;
629 result = ((
const struct snmp_leaf_node*)mn)->get_next_instance(
634 if (result == SNMP_ERR_NOERROR)
637 if(((node_instance->access & SNMP_NODE_INSTANCE_ACCESS_READ) != 0) && (node_instance->get_value ==
NULL)) {
638 LWIP_DEBUGF(
SNMP_DEBUG, (
"SNMP inconsistent access: node is readable but no get_value function is specified\n"));
640 if(((node_instance->access & SNMP_NODE_INSTANCE_ACCESS_WRITE) != 0) && (node_instance->set_value ==
NULL)) {
641 LWIP_DEBUGF(
SNMP_DEBUG, (
"SNMP inconsistent access: node is writable but no set_value function is specified\n"));
646 if ((validate_node_instance_method ==
NULL) || (validate_node_instance_method(node_instance, validate_node_instance_arg) == SNMP_ERR_NOERROR))
649 snmp_oid_append(node_oid, node_instance->instance_oid.id, node_instance->instance_oid.len);
653 if (node_instance->release_instance !=
NULL) {
654 node_instance->release_instance(node_instance);
664 if (node_instance->release_instance !=
NULL) {
665 node_instance->release_instance(node_instance);
669 mn = snmp_mib_tree_resolve_next(mib, node_oid->id, node_oid->len, &node_instance->instance_oid);
673 snmp_oid_assign(node_oid, node_instance->instance_oid.id, node_instance->instance_oid.len);
674 node_instance->instance_oid.len = 0;
675 node_instance->node = mn;
688 const struct snmp_mib *intermediate_mib;
689 intermediate_mib = snmp_get_mib_between(start_oid, start_oid_len, node_oid->id, node_oid->len);
691 if (intermediate_mib !=
NULL) {
693 if (node_instance->release_instance !=
NULL) {
694 node_instance->release_instance(node_instance);
698 mib = intermediate_mib;
699 start_oid = mib->base_oid;
700 start_oid_len = mib->base_oid_len;
710 const struct snmp_mib *next_mib;
711 next_mib = snmp_get_next_mib(start_oid, start_oid_len);
714 if ((next_mib !=
NULL) && (next_mib->base_oid_len > mib->base_oid_len) &&
715 (snmp_oid_compare(next_mib->base_oid, mib->base_oid_len, mib->base_oid, mib->base_oid_len) == 0)) {
718 start_oid = mib->base_oid;
719 start_oid_len = mib->base_oid_len;
722 if (mib->base_oid_len > 1) {
723 mib = snmp_get_mib_from_oid(mib->base_oid, mib->base_oid_len - 1);
730 start_oid = mib->base_oid;
731 start_oid_len = mib->base_oid_len;
743 return SNMP_ERR_ENDOFMIBVIEW;
746 return SNMP_ERR_NOERROR;
753 const struct snmp_node *
754 snmp_mib_tree_resolve_exact(
const struct snmp_mib *mib,
const u32_t *oid,
u8_t oid_len,
u8_t* oid_instance_len)
756 const struct snmp_node*
const* node = &mib->root_node;
757 u8_t oid_offset = mib->base_oid_len;
759 while ((oid_offset < oid_len) && ((*node)->node_type == SNMP_NODE_TREE))
762 u32_t subnode_oid = *(oid + oid_offset);
764 u32_t i = (*(
const struct snmp_tree_node*
const*)node)->subnode_count;
765 node = (*(
const struct snmp_tree_node*
const*)node)->subnodes;
766 while ((i > 0) && ((*node)->oid != subnode_oid))
781 if ((*node)->node_type != SNMP_NODE_TREE)
784 *oid_instance_len = oid_len - oid_offset;
791 const struct snmp_node*
792 snmp_mib_tree_resolve_next(
const struct snmp_mib *mib,
const u32_t *oid,
u8_t oid_len,
struct snmp_obj_id* oidret)
794 u8_t oid_offset = mib->base_oid_len;
795 const struct snmp_node*
const* node;
800 if (mib->root_node->node_type != SNMP_NODE_TREE)
807 node_stack[nsi] = (
const struct snmp_tree_node*)mib->root_node;
808 while (oid_offset < oid_len)
811 u32_t i = node_stack[nsi]->subnode_count;
812 node = node_stack[nsi]->subnodes;
814 subnode_oid = *(oid + oid_offset);
816 while ((i > 0) && ((*node)->oid != subnode_oid))
822 if ((i == 0) || ((*node)->node_type != SNMP_NODE_TREE))
828 node_stack[nsi] = (
const struct snmp_tree_node*)(*node);
834 if (oid_offset >= oid_len)
841 subnode_oid = *(oid + oid_offset) + 1;
846 const struct snmp_node* subnode =
NULL;
849 s32_t i = node_stack[nsi]->subnode_count;
850 node = node_stack[nsi]->subnodes;
853 if ((*node)->oid == subnode_oid)
858 else if (((*node)->oid > subnode_oid) && ((subnode ==
NULL) || ((*node)->oid < subnode->oid)))
870 subnode_oid = node_stack[nsi]->node.oid + 1;
875 if (subnode->node_type == SNMP_NODE_TREE)
879 node_stack[nsi] = (
const struct snmp_tree_node*)subnode;
885 snmp_oid_assign(oidret, mib->base_oid, mib->base_oid_len);
889 oidret->id[oidret->len] = node_stack[i]->node.oid;
894 oidret->id[oidret->len] = subnode->oid;
906 snmp_next_oid_init(
struct snmp_next_oid_state *state,
907 const u32_t *start_oid,
u8_t start_oid_len,
908 u32_t *next_oid_buf,
u8_t next_oid_max_len)
910 state->start_oid = start_oid;
911 state->start_oid_len = start_oid_len;
912 state->next_oid = next_oid_buf;
913 state->next_oid_len = 0;
914 state->next_oid_max_len = next_oid_max_len;
915 state->status = SNMP_NEXT_OID_STATUS_NO_MATCH;
919 snmp_next_oid_precheck(
struct snmp_next_oid_state *state,
const u32_t *oid,
const u8_t oid_len)
921 if (state->status != SNMP_NEXT_OID_STATUS_BUF_TO_SMALL)
923 u8_t start_oid_len = (oid_len < state->start_oid_len) ? oid_len : state->start_oid_len;
926 if (snmp_oid_compare(oid, oid_len, state->start_oid, start_oid_len) >= 0)
929 if ((state->status == SNMP_NEXT_OID_STATUS_NO_MATCH) ||
930 (snmp_oid_compare(oid, oid_len, state->next_oid, state->next_oid_len) < 0))
941 snmp_next_oid_check(
struct snmp_next_oid_state *state,
const u32_t *oid,
const u8_t oid_len,
void* reference)
944 if (state->status != SNMP_NEXT_OID_STATUS_BUF_TO_SMALL)
947 if (snmp_oid_compare(oid, oid_len, state->start_oid, state->start_oid_len) > 0)
950 if ((state->status == SNMP_NEXT_OID_STATUS_NO_MATCH) ||
951 (snmp_oid_compare(oid, oid_len, state->next_oid, state->next_oid_len) < 0))
953 if (oid_len <= state->next_oid_max_len)
955 MEMCPY(state->next_oid, oid, oid_len *
sizeof(
u32_t));
956 state->next_oid_len = oid_len;
957 state->status = SNMP_NEXT_OID_STATUS_SUCCESS;
958 state->reference = reference;
963 state->status = SNMP_NEXT_OID_STATUS_BUF_TO_SMALL;
973 snmp_oid_in_range(
const u32_t *oid_in,
u8_t oid_len,
const struct snmp_oid_range *oid_ranges,
u8_t oid_ranges_len)
977 if(oid_len != oid_ranges_len) {
981 for(i=0; i<oid_ranges_len; i++)
983 if((oid_in[i] < oid_ranges[i].min) || (oid_in[i] > oid_ranges[i].max)) {
992 snmp_set_test_ok(
struct snmp_node_instance* instance,
u16_t value_len,
void* value)
998 return SNMP_ERR_NOERROR;
1014 snmp_decode_bits(
const u8_t *buf,
u32_t buf_len,
u32_t *bit_value)
1017 u8_t bits_processed = 0;
1020 while (buf_len > 0) {
1023 if (bits_processed >= 32) {
1031 *bit_value |= (1 << bits_processed);
1036 while ((bits_processed % 8) != 0);
1038 bits_processed += 8;
1049 snmp_decode_truthvalue(
const s32_t *asn1_value,
u8_t *bool_value)
1059 if ((asn1_value ==
NULL) || (bool_value ==
NULL)) {
1063 if (*asn1_value == 1) {
1065 }
else if (*asn1_value == 2) {
1091 u8_t min_bytes = (bit_count + 7) / 8;
1093 while ((buf_len > 0) && (bit_value != 0x00)) {
1097 if (bit_value & 0x01) {
1114 if (len < min_bytes)
1119 while ((len < min_bytes) && (buf_len > 0))
1132 snmp_encode_truthvalue(
s32_t *asn1_value,
u32_t bool_value)
1142 if (asn1_value ==
NULL) {
1152 return sizeof(
s32_t);
#define SNMP_MAX_OBJ_ID_LEN
#define MEMCPY(dst, src, len)
#define LWIP_ASSERT(message, assertion)
#define LWIP_ARRAYSIZE(x)
#define SNMP_DEVICE_ENTERPRISE_OID
#define IP_SET_TYPE(ipaddr, iptype)
#define SNMP_DEVICE_ENTERPRISE_OID_LEN
#define LWIP_DEBUGF(debug, message)
#define LWIP_UNUSED_ARG(x)