56 snmp_write_callback_fct snmp_write_callback =
NULL;
57 void* snmp_write_callback_arg =
NULL;
64 snmp_get_community(
void)
66 return snmp_community;
77 snmp_set_community(
const char *
const community)
80 snmp_community = community;
88 snmp_get_community_write(
void)
90 return snmp_community_write;
98 snmp_get_community_trap(
void)
100 return snmp_community_trap;
111 snmp_set_community_write(
const char *
const community)
114 snmp_community_write = community;
125 snmp_set_community_trap(
const char *
const community)
128 snmp_community_trap = community;
132 snmp_set_write_callback(snmp_write_callback_fct write_callback,
void* callback_arg)
134 snmp_write_callback = write_callback;
135 snmp_write_callback_arg = callback_arg;
142 static err_t snmp_process_get_request(
struct snmp_request *request);
143 static err_t snmp_process_getnext_request(
struct snmp_request *request);
144 static err_t snmp_process_getbulk_request(
struct snmp_request *request);
145 static err_t snmp_process_set_request(
struct snmp_request *request);
147 static err_t snmp_parse_inbound_frame(
struct snmp_request *request);
148 static err_t snmp_prepare_outbound_frame(
struct snmp_request *request);
149 static err_t snmp_append_outbound_varbind(
struct snmp_request *request,
struct snmp_varbind* varbind);
150 static err_t snmp_complete_outbound_frame(
struct snmp_request *request);
151 static void snmp_execute_write_callbacks(
struct snmp_request *request);
162 struct snmp_request request;
164 memset(&request, 0,
sizeof(request));
165 request.handle = handle;
166 request.source_ip = source_ip;
167 request.source_port = port;
168 request.inbound_pbuf = p;
172 err = snmp_parse_inbound_frame(&request);
174 err = snmp_prepare_outbound_frame(&request);
177 if (request.error_status == SNMP_ERR_NOERROR) {
179 if (request.request_type == SNMP_ASN1_CONTEXT_PDU_GET_REQ) {
180 err = snmp_process_get_request(&request);
181 }
else if (request.request_type == SNMP_ASN1_CONTEXT_PDU_GET_NEXT_REQ) {
182 err = snmp_process_getnext_request(&request);
183 }
else if (request.request_type == SNMP_ASN1_CONTEXT_PDU_GET_BULK_REQ) {
184 err = snmp_process_getbulk_request(&request);
185 }
else if (request.request_type == SNMP_ASN1_CONTEXT_PDU_SET_REQ) {
186 err = snmp_process_set_request(&request);
191 err = snmp_complete_outbound_frame(&request);
194 err = snmp_sendto(request.handle, request.outbound_pbuf, request.source_ip, request.source_port);
196 if ((request.request_type == SNMP_ASN1_CONTEXT_PDU_SET_REQ)
197 && (request.error_status == SNMP_ERR_NOERROR)
198 && (snmp_write_callback !=
NULL)) {
200 snmp_execute_write_callbacks(&request);
206 if (request.outbound_pbuf !=
NULL) {
213 snmp_msg_getnext_validate_node_inst(
struct snmp_node_instance* node_instance,
void* validate_arg)
215 if (((node_instance->access & SNMP_NODE_INSTANCE_ACCESS_READ) != SNMP_NODE_INSTANCE_ACCESS_READ) || (node_instance->get_value ==
NULL)) {
216 return SNMP_ERR_NOSUCHINSTANCE;
219 if ((node_instance->asn1_type == SNMP_ASN1_TYPE_COUNTER64) && (((
struct snmp_request*)validate_arg)->version == SNMP_VERSION_1)) {
221 return SNMP_ERR_NOSUCHINSTANCE;
224 return SNMP_ERR_NOERROR;
228 snmp_process_varbind(
struct snmp_request *request,
struct snmp_varbind *vb,
u8_t get_next)
231 struct snmp_node_instance node_instance;
232 memset(&node_instance, 0,
sizeof(node_instance));
235 struct snmp_obj_id result_oid;
236 request->error_status = snmp_get_next_node_instance_from_oid(vb->oid.id, vb->oid.len, snmp_msg_getnext_validate_node_inst, request, &result_oid, &node_instance);
238 if (request->error_status == SNMP_ERR_NOERROR) {
239 snmp_oid_assign(&vb->oid, result_oid.id, result_oid.len);
242 request->error_status = snmp_get_node_instance_from_oid(vb->oid.id, vb->oid.len, &node_instance);
244 if (request->error_status == SNMP_ERR_NOERROR) {
246 request->error_status = snmp_msg_getnext_validate_node_inst(&node_instance, request);
248 if (request->error_status != SNMP_ERR_NOERROR) {
249 if (node_instance.release_instance !=
NULL) {
250 node_instance.release_instance(&node_instance);
256 if (request->error_status != SNMP_ERR_NOERROR)
258 if (request->error_status >= SNMP_VARBIND_EXCEPTION_OFFSET) {
259 if (request->version == SNMP_VERSION_2c) {
261 vb->type = (SNMP_ASN1_CONTENTTYPE_PRIMITIVE | SNMP_ASN1_CLASS_CONTEXT | (request->error_status & SNMP_VARBIND_EXCEPTION_MASK));
264 err = snmp_append_outbound_varbind(request, vb);
267 request->error_status = SNMP_ERR_NOERROR;
269 request->error_status = SNMP_ERR_TOOBIG;
271 request->error_status = SNMP_ERR_GENERROR;
276 request->error_status = SNMP_ERR_GENERROR;
279 vb->type = node_instance.asn1_type;
280 vb->value_len = node_instance.get_value(&node_instance, vb->value);
283 err = snmp_append_outbound_varbind(request, vb);
285 request->error_status = SNMP_ERR_TOOBIG;
286 }
else if (err !=
ERR_OK) {
287 request->error_status = SNMP_ERR_GENERROR;
290 if (node_instance.release_instance !=
NULL) {
291 node_instance.release_instance(&node_instance);
303 snmp_process_get_request(
struct snmp_request *request)
305 snmp_vb_enumerator_err_t err;
306 struct snmp_varbind vb;
307 vb.value = request->value_buffer;
311 while (request->error_status == SNMP_ERR_NOERROR) {
312 err = snmp_vb_enumerator_get_next(&request->inbound_varbind_enumerator, &vb);
313 if (err == SNMP_VB_ENUMERATOR_ERR_OK) {
314 if ((vb.type == SNMP_ASN1_TYPE_NULL) && (vb.value_len == 0)) {
315 snmp_process_varbind(request, &vb, 0);
317 request->error_status = SNMP_ERR_GENERROR;
319 }
else if (err == SNMP_VB_ENUMERATOR_ERR_EOVB) {
322 }
else if (err == SNMP_VB_ENUMERATOR_ERR_ASN1ERROR) {
326 request->error_status = SNMP_ERR_GENERROR;
339 snmp_process_getnext_request(
struct snmp_request *request)
341 snmp_vb_enumerator_err_t err;
342 struct snmp_varbind vb;
343 vb.value = request->value_buffer;
347 while (request->error_status == SNMP_ERR_NOERROR) {
348 err = snmp_vb_enumerator_get_next(&request->inbound_varbind_enumerator, &vb);
349 if (err == SNMP_VB_ENUMERATOR_ERR_OK) {
350 if ((vb.type == SNMP_ASN1_TYPE_NULL) && (vb.value_len == 0)) {
351 snmp_process_varbind(request, &vb, 1);
353 request->error_status = SNMP_ERR_GENERROR;
355 }
else if (err == SNMP_VB_ENUMERATOR_ERR_EOVB) {
358 }
else if (err == SNMP_VB_ENUMERATOR_ERR_ASN1ERROR) {
362 request->error_status = SNMP_ERR_GENERROR;
375 snmp_process_getbulk_request(
struct snmp_request *request)
377 snmp_vb_enumerator_err_t err;
378 s32_t non_repeaters = request->non_repeaters;
380 u16_t repetition_offset = 0;
381 struct snmp_varbind_enumerator repetition_varbind_enumerator;
382 struct snmp_varbind vb;
383 vb.value = request->value_buffer;
388 repetitions = request->max_repetitions;
394 while (request->error_status == SNMP_ERR_NOERROR) {
395 if (non_repeaters == 0) {
396 repetition_offset = request->outbound_pbuf_stream.offset;
398 if (repetitions == 0) {
405 err = snmp_vb_enumerator_get_next(&request->inbound_varbind_enumerator, &vb);
406 if (err == SNMP_VB_ENUMERATOR_ERR_EOVB) {
409 }
else if (err == SNMP_VB_ENUMERATOR_ERR_ASN1ERROR) {
412 }
else if ((err != SNMP_VB_ENUMERATOR_ERR_OK) || (vb.type != SNMP_ASN1_TYPE_NULL) || (vb.value_len != 0)) {
413 request->error_status = SNMP_ERR_GENERROR;
415 snmp_process_varbind(request, &vb, 1);
421 while ((request->error_status == SNMP_ERR_NOERROR) && (repetitions > 0) && (request->outbound_pbuf_stream.offset != repetition_offset)) {
423 u8_t all_endofmibview = 1;
425 snmp_vb_enumerator_init(&repetition_varbind_enumerator, request->outbound_pbuf, repetition_offset, request->outbound_pbuf_stream.offset - repetition_offset);
426 repetition_offset = request->outbound_pbuf_stream.offset;
428 while (request->error_status == SNMP_ERR_NOERROR) {
430 err = snmp_vb_enumerator_get_next(&repetition_varbind_enumerator, &vb);
431 if (err == SNMP_VB_ENUMERATOR_ERR_OK) {
432 vb.value = request->value_buffer;
433 snmp_process_varbind(request, &vb, 1);
435 if (request->error_status != SNMP_ERR_NOERROR) {
437 request->error_index = request->non_repeaters + repetition_varbind_enumerator.varbind_count;
438 }
else if (vb.type != (SNMP_ASN1_CONTENTTYPE_PRIMITIVE | SNMP_ASN1_CLASS_CONTEXT | SNMP_ASN1_CONTEXT_VARBIND_END_OF_MIB_VIEW)) {
439 all_endofmibview = 0;
441 }
else if (err == SNMP_VB_ENUMERATOR_ERR_EOVB) {
445 LWIP_DEBUGF(
SNMP_DEBUG, (
"Very strange, we cannot parse the varbind output that we created just before!"));
446 request->error_status = SNMP_ERR_GENERROR;
447 request->error_index = request->non_repeaters + repetition_varbind_enumerator.varbind_count;
451 if ((request->error_status == SNMP_ERR_NOERROR) && all_endofmibview) {
459 if (request->error_status == SNMP_ERR_TOOBIG) {
461 request->error_status = SNMP_ERR_NOERROR;
473 snmp_process_set_request(
struct snmp_request *request)
475 snmp_vb_enumerator_err_t err;
476 struct snmp_varbind vb;
477 vb.value = request->value_buffer;
482 while (request->error_status == SNMP_ERR_NOERROR) {
483 err = snmp_vb_enumerator_get_next(&request->inbound_varbind_enumerator, &vb);
484 if (err == SNMP_VB_ENUMERATOR_ERR_OK) {
485 struct snmp_node_instance node_instance;
486 memset(&node_instance, 0,
sizeof(node_instance));
488 request->error_status = snmp_get_node_instance_from_oid(vb.oid.id, vb.oid.len, &node_instance);
489 if (request->error_status == SNMP_ERR_NOERROR)
491 if (node_instance.asn1_type != vb.type) {
492 request->error_status = SNMP_ERR_WRONGTYPE;
493 }
else if (((node_instance.access & SNMP_NODE_INSTANCE_ACCESS_WRITE) != SNMP_NODE_INSTANCE_ACCESS_WRITE) || (node_instance.set_value ==
NULL)) {
494 request->error_status = SNMP_ERR_NOTWRITABLE;
496 if (node_instance.set_test !=
NULL) {
497 request->error_status = node_instance.set_test(&node_instance, vb.value_len, vb.value);
501 if (node_instance.release_instance !=
NULL) {
502 node_instance.release_instance(&node_instance);
506 else if (err == SNMP_VB_ENUMERATOR_ERR_EOVB) {
509 }
else if (err == SNMP_VB_ENUMERATOR_ERR_INVALIDLENGTH) {
510 request->error_status = SNMP_ERR_WRONGLENGTH;
511 }
else if (err == SNMP_VB_ENUMERATOR_ERR_ASN1ERROR) {
515 request->error_status = SNMP_ERR_GENERROR;
520 if (request->error_status == SNMP_ERR_NOERROR) {
521 snmp_vb_enumerator_init(&request->inbound_varbind_enumerator, request->inbound_pbuf, request->inbound_varbind_offset, request->inbound_varbind_len);
522 while (request->error_status == SNMP_ERR_NOERROR) {
523 err = snmp_vb_enumerator_get_next(&request->inbound_varbind_enumerator, &vb);
524 if (err == SNMP_VB_ENUMERATOR_ERR_OK) {
525 struct snmp_node_instance node_instance;
526 memset(&node_instance, 0,
sizeof(node_instance));
527 request->error_status = snmp_get_node_instance_from_oid(vb.oid.id, vb.oid.len, &node_instance);
528 if (request->error_status == SNMP_ERR_NOERROR)
530 if (node_instance.set_value(&node_instance, vb.value_len, vb.value) != SNMP_ERR_NOERROR)
532 if (request->inbound_varbind_enumerator.varbind_count == 1) {
533 request->error_status = SNMP_ERR_COMMITFAILED;
536 request->error_status = SNMP_ERR_UNDOFAILED;
540 if (node_instance.release_instance !=
NULL) {
541 node_instance.release_instance(&node_instance);
544 }
else if (err == SNMP_VB_ENUMERATOR_ERR_EOVB) {
549 request->error_status = SNMP_ERR_GENERROR;
557 #define PARSE_EXEC(code, retValue) \ 558 if ((code) != ERR_OK) { \ 559 LWIP_DEBUGF(SNMP_DEBUG, ("Malformed ASN.1 detected.\n")); \ 560 snmp_stats.inasnparseerrs++; \ 564 #define PARSE_ASSERT(cond, retValue) \ 566 LWIP_DEBUGF(SNMP_DEBUG, ("SNMP parse assertion failed!: " # cond)); \ 567 snmp_stats.inasnparseerrs++; \ 571 #define BUILD_EXEC(code, retValue) \ 572 if ((code) != ERR_OK) { \ 573 LWIP_DEBUGF(SNMP_DEBUG, ("SNMP error during creation of outbound frame!: " # code)); \ 577 #define IF_PARSE_EXEC(code) PARSE_EXEC(code, ERR_ABRT) 578 #define IF_PARSE_ASSERT(code) PARSE_ASSERT(code, ERR_ABRT) 589 snmp_parse_inbound_frame(
struct snmp_request *request)
591 struct snmp_pbuf_stream pbuf_stream;
592 struct snmp_asn1_tlv tlv;
593 s32_t parent_tlv_value_len;
597 IF_PARSE_EXEC(snmp_pbuf_stream_init(&pbuf_stream, request->inbound_pbuf, 0, request->inbound_pbuf->tot_len));
600 IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv));
601 IF_PARSE_ASSERT((tlv.type == SNMP_ASN1_TYPE_SEQUENCE) && (tlv.value_len == pbuf_stream.length));
602 parent_tlv_value_len = tlv.value_len;
605 IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv));
606 IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_INTEGER);
607 parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv);
608 IF_PARSE_ASSERT(parent_tlv_value_len > 0);
610 IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &s32_value));
611 if ((s32_value != SNMP_VERSION_1) && (s32_value != SNMP_VERSION_2c)) {
613 snmp_stats.inbadversions++;
616 request->version = (
u8_t)s32_value;
619 IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv));
620 IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_OCTET_STRING);
621 parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv);
622 IF_PARSE_ASSERT(parent_tlv_value_len > 0);
624 err = snmp_asn1_dec_raw(&pbuf_stream, tlv.value_len, request->community, &request->community_strlen,
SNMP_MAX_COMMUNITY_STR_LEN);
627 request->community_strlen = 0;
628 snmp_pbuf_stream_seek(&pbuf_stream, tlv.value_len);
630 IF_PARSE_ASSERT(err ==
ERR_OK);
633 request->community[request->community_strlen] = 0;
636 IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv));
637 IF_PARSE_ASSERT(tlv.value_len == pbuf_stream.length);
638 parent_tlv_value_len = tlv.value_len;
642 case (SNMP_ASN1_CLASS_CONTEXT | SNMP_ASN1_CONTENTTYPE_CONSTRUCTED | SNMP_ASN1_CONTEXT_PDU_GET_REQ):
644 snmp_stats.ingetrequests++;
646 case (SNMP_ASN1_CLASS_CONTEXT | SNMP_ASN1_CONTENTTYPE_CONSTRUCTED | SNMP_ASN1_CONTEXT_PDU_GET_NEXT_REQ):
648 snmp_stats.ingetnexts++;
650 case (SNMP_ASN1_CLASS_CONTEXT | SNMP_ASN1_CONTENTTYPE_CONSTRUCTED | SNMP_ASN1_CONTEXT_PDU_GET_BULK_REQ):
652 if (request->version < SNMP_VERSION_2c) {
657 case (SNMP_ASN1_CLASS_CONTEXT | SNMP_ASN1_CONTENTTYPE_CONSTRUCTED | SNMP_ASN1_CONTEXT_PDU_SET_REQ):
659 snmp_stats.insetrequests++;
667 request->request_type = tlv.type & SNMP_ASN1_DATATYPE_MASK;
670 if (request->community_strlen == 0) {
672 snmp_stats.inbadcommunitynames++;
673 snmp_authfail_trap();
675 }
else if (request->request_type == SNMP_ASN1_CONTEXT_PDU_SET_REQ) {
678 request->error_status = SNMP_ERR_NOTWRITABLE;
679 request->error_index = 1;
682 snmp_stats.inbadcommunitynames++;
683 snmp_authfail_trap();
689 snmp_stats.inbadcommunitynames++;
690 snmp_authfail_trap();
696 IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv));
697 IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_INTEGER);
698 parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv);
699 IF_PARSE_ASSERT(parent_tlv_value_len > 0);
701 IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &request->request_id));
704 IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv));
705 IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_INTEGER);
706 parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv);
707 IF_PARSE_ASSERT(parent_tlv_value_len > 0);
709 if (request->request_type == SNMP_ASN1_CONTEXT_PDU_GET_BULK_REQ) {
710 IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &request->non_repeaters));
711 if (request->non_repeaters < 0) {
713 request->non_repeaters = 0;
717 IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &s32_value));
718 IF_PARSE_ASSERT(s32_value == SNMP_ERR_NOERROR);
722 IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv));
723 IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_INTEGER);
724 parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv);
725 IF_PARSE_ASSERT(parent_tlv_value_len > 0);
727 if (request->request_type == SNMP_ASN1_CONTEXT_PDU_GET_BULK_REQ) {
728 IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &request->max_repetitions));
729 if (request->max_repetitions < 0) {
731 request->max_repetitions = 0;
734 IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &request->error_index));
735 IF_PARSE_ASSERT(s32_value == 0);
739 IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv));
740 IF_PARSE_ASSERT((tlv.type == SNMP_ASN1_TYPE_SEQUENCE) && (tlv.value_len == pbuf_stream.length));
742 request->inbound_varbind_offset = pbuf_stream.offset;
743 request->inbound_varbind_len = pbuf_stream.length;
744 snmp_vb_enumerator_init(&(request->inbound_varbind_enumerator), request->inbound_pbuf, request->inbound_varbind_offset, request->inbound_varbind_len);
749 #define OF_BUILD_EXEC(code) BUILD_EXEC(code, ERR_ABRT) 752 snmp_prepare_outbound_frame(
struct snmp_request *request)
754 struct snmp_asn1_tlv tlv;
755 struct snmp_pbuf_stream* pbuf_stream = &(request->outbound_pbuf_stream);
759 if (request->outbound_pbuf ==
NULL) {
763 snmp_pbuf_stream_init(pbuf_stream, request->outbound_pbuf, 0, request->outbound_pbuf->tot_len);
766 SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 3, 0);
767 OF_BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) );
770 SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 0);
771 snmp_asn1_enc_s32t_cnt(request->version, &tlv.value_len);
772 OF_BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) );
773 OF_BUILD_EXEC( snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, request->version) );
776 SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 0, request->community_strlen);
777 OF_BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) );
778 OF_BUILD_EXEC( snmp_asn1_enc_raw(pbuf_stream, request->community, request->community_strlen) );
781 request->outbound_pdu_offset = pbuf_stream->offset;
782 SNMP_ASN1_SET_TLV_PARAMS(tlv, (SNMP_ASN1_CLASS_CONTEXT | SNMP_ASN1_CONTENTTYPE_CONSTRUCTED | SNMP_ASN1_CONTEXT_PDU_GET_RESP), 3, 0);
783 OF_BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) );
786 SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 0);
787 snmp_asn1_enc_s32t_cnt(request->request_id, &tlv.value_len);
788 OF_BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) );
789 OF_BUILD_EXEC( snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, request->request_id) );
792 SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 1);
793 OF_BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) );
794 request->outbound_error_status_offset = pbuf_stream->offset;
795 OF_BUILD_EXEC( snmp_pbuf_stream_write(pbuf_stream, 0) );
798 SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 1);
799 OF_BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) );
800 request->outbound_error_index_offset = pbuf_stream->offset;
801 OF_BUILD_EXEC( snmp_pbuf_stream_write(pbuf_stream, 0) );
804 SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 3, 0);
805 OF_BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) );
807 request->outbound_varbind_offset = pbuf_stream->offset;
812 #define OVB_BUILD_EXEC(code) BUILD_EXEC(code, ERR_ABRT) 815 snmp_append_outbound_varbind(
struct snmp_request *request,
struct snmp_varbind* varbind)
817 struct snmp_asn1_tlv tlv;
818 u8_t vb_len_len, oid_len_len, value_len_len;
819 u16_t vb_value_len, oid_value_len, value_value_len;
822 snmp_asn1_enc_oid_cnt(varbind->oid.id, varbind->oid.len, &oid_value_len);
823 snmp_asn1_enc_length_cnt(oid_value_len, &oid_len_len);
825 if (varbind->value_len == 0) {
827 }
else if (varbind->value_len & SNMP_GET_VALUE_RAW_DATA) {
828 value_value_len = varbind->value_len & (~SNMP_GET_VALUE_RAW_DATA);
830 switch (varbind->type)
832 case SNMP_ASN1_TYPE_INTEGER:
833 if (varbind->value_len !=
sizeof(
s32_t)) {
836 snmp_asn1_enc_s32t_cnt(*((
s32_t*)varbind->value) , &value_value_len);
838 case SNMP_ASN1_TYPE_COUNTER:
839 case SNMP_ASN1_TYPE_GAUGE:
840 case SNMP_ASN1_TYPE_TIMETICKS:
841 if (varbind->value_len !=
sizeof(
u32_t)) {
844 snmp_asn1_enc_u32t_cnt(*((
u32_t*)varbind->value) , &value_value_len);
846 case SNMP_ASN1_TYPE_OCTET_STRING:
847 case SNMP_ASN1_TYPE_IPADDR:
848 case SNMP_ASN1_TYPE_OPAQUE:
849 value_value_len = varbind->value_len;
851 case SNMP_ASN1_TYPE_NULL:
852 if (varbind->value_len != 0) {
857 case SNMP_ASN1_TYPE_OBJECT_ID:
858 if ((varbind->value_len %
sizeof(
u32_t)) != 0) {
861 snmp_asn1_enc_oid_cnt((
u32_t*)varbind->value, varbind->value_len /
sizeof(
u32_t), &value_value_len);
863 case SNMP_ASN1_TYPE_COUNTER64:
864 if (varbind->value_len != (2 *
sizeof(
u32_t))) {
867 snmp_asn1_enc_u64t_cnt((
u32_t*)varbind->value , &value_value_len);
874 snmp_asn1_enc_length_cnt(value_value_len, &value_len_len);
876 vb_value_len = 1 + oid_len_len + oid_value_len + 1 + value_len_len + value_value_len;
877 snmp_asn1_enc_length_cnt(vb_value_len, &vb_len_len);
882 if ((1 + vb_len_len + vb_value_len) > request->outbound_pbuf_stream.length) {
887 SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, vb_len_len, vb_value_len);
888 OVB_BUILD_EXEC( snmp_ans1_enc_tlv(&(request->outbound_pbuf_stream), &tlv) );
891 SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OBJECT_ID, oid_len_len, oid_value_len);
892 OVB_BUILD_EXEC( snmp_ans1_enc_tlv(&(request->outbound_pbuf_stream), &tlv) );
893 OVB_BUILD_EXEC( snmp_asn1_enc_oid(&(request->outbound_pbuf_stream), varbind->oid.id, varbind->oid.len) );
896 SNMP_ASN1_SET_TLV_PARAMS(tlv, varbind->type, value_len_len, value_value_len);
897 OVB_BUILD_EXEC( snmp_ans1_enc_tlv(&(request->outbound_pbuf_stream), &tlv) );
899 if (value_value_len > 0) {
900 if (varbind->value_len & SNMP_GET_VALUE_RAW_DATA) {
901 OVB_BUILD_EXEC( snmp_asn1_enc_raw(&(request->outbound_pbuf_stream), (
u8_t*)varbind->value, value_value_len) );
903 switch (varbind->type)
905 case SNMP_ASN1_TYPE_INTEGER:
906 OVB_BUILD_EXEC( snmp_asn1_enc_s32t(&(request->outbound_pbuf_stream), value_value_len, *((
s32_t*)varbind->value)) );
908 case SNMP_ASN1_TYPE_COUNTER:
909 case SNMP_ASN1_TYPE_GAUGE:
910 case SNMP_ASN1_TYPE_TIMETICKS:
911 OVB_BUILD_EXEC( snmp_asn1_enc_u32t(&(request->outbound_pbuf_stream), value_value_len, *((
u32_t*)varbind->value)) );
913 case SNMP_ASN1_TYPE_OCTET_STRING:
914 case SNMP_ASN1_TYPE_IPADDR:
915 case SNMP_ASN1_TYPE_OPAQUE:
916 OVB_BUILD_EXEC( snmp_asn1_enc_raw(&(request->outbound_pbuf_stream), (
u8_t*)varbind->value, value_value_len) );
917 value_value_len = varbind->value_len;
919 case SNMP_ASN1_TYPE_OBJECT_ID:
920 OVB_BUILD_EXEC( snmp_asn1_enc_oid(&(request->outbound_pbuf_stream), (
u32_t*)varbind->value, varbind->value_len /
sizeof(
u32_t)) );
922 case SNMP_ASN1_TYPE_COUNTER64:
923 OVB_BUILD_EXEC( snmp_asn1_enc_u64t(&(request->outbound_pbuf_stream), value_value_len, (
u32_t*)varbind->value) );
936 snmp_complete_outbound_frame(
struct snmp_request *request)
938 struct snmp_asn1_tlv tlv;
941 if (request->version == SNMP_VERSION_1) {
942 if (request->error_status != SNMP_ERR_NOERROR) {
944 switch (request->error_status) {
948 case SNMP_ERR_NOSUCHINSTANCE:
949 case SNMP_ERR_NOSUCHOBJECT:
950 case SNMP_ERR_ENDOFMIBVIEW:
951 request->error_status = SNMP_ERR_NOSUCHNAME;
break;
953 case SNMP_ERR_WRONGVALUE:
954 case SNMP_ERR_WRONGENCODING:
955 case SNMP_ERR_WRONGTYPE:
956 case SNMP_ERR_WRONGLENGTH:
957 case SNMP_ERR_INCONSISTENTVALUE:
958 request->error_status = SNMP_ERR_BADVALUE;
break;
959 case SNMP_ERR_NOACCESS:
960 case SNMP_ERR_NOTWRITABLE:
961 case SNMP_ERR_NOCREATION:
962 case SNMP_ERR_INCONSISTENTNAME:
963 case SNMP_ERR_AUTHORIZATIONERROR:
964 request->error_status = SNMP_ERR_NOSUCHNAME;
break;
965 case SNMP_ERR_RESOURCEUNAVAILABLE:
966 case SNMP_ERR_COMMITFAILED:
967 case SNMP_ERR_UNDOFAILED:
969 request->error_status = SNMP_ERR_GENERROR;
break;
973 if (request->error_status >= SNMP_VARBIND_EXCEPTION_OFFSET) {
975 LWIP_DEBUGF(
SNMP_DEBUG, (
"snmp_complete_outbound_frame() > Found v2 request with varbind exception code stored as error status!\n"));
980 if ((request->error_status != SNMP_ERR_NOERROR) || (request->request_type == SNMP_ASN1_CONTEXT_PDU_SET_REQ)) {
982 struct snmp_pbuf_stream inbound_stream;
983 OF_BUILD_EXEC( snmp_pbuf_stream_init(&inbound_stream, request->inbound_pbuf, request->inbound_varbind_offset, request->inbound_varbind_len) );
984 OF_BUILD_EXEC( snmp_pbuf_stream_init(&(request->outbound_pbuf_stream), request->outbound_pbuf, request->outbound_varbind_offset, request->outbound_pbuf->tot_len - request->outbound_varbind_offset) );
985 snmp_pbuf_stream_writeto(&inbound_stream, &(request->outbound_pbuf_stream), 0);
988 frame_size = request->outbound_pbuf_stream.offset;
991 SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 3, frame_size - 1 - 3);
992 OF_BUILD_EXEC( snmp_pbuf_stream_init(&(request->outbound_pbuf_stream), request->outbound_pbuf, 0, request->outbound_pbuf->tot_len) );
993 OF_BUILD_EXEC( snmp_ans1_enc_tlv(&(request->outbound_pbuf_stream), &tlv) );
996 SNMP_ASN1_SET_TLV_PARAMS(tlv, (SNMP_ASN1_CLASS_CONTEXT | SNMP_ASN1_CONTENTTYPE_CONSTRUCTED | SNMP_ASN1_CONTEXT_PDU_GET_RESP), 3, frame_size - request->outbound_pdu_offset - 1 - 3);
997 OF_BUILD_EXEC( snmp_pbuf_stream_seek_abs(&(request->outbound_pbuf_stream), request->outbound_pdu_offset) );
998 OF_BUILD_EXEC( snmp_ans1_enc_tlv(&(request->outbound_pbuf_stream), &tlv) );
1001 if (request->error_status != 0) {
1003 snmp_asn1_enc_s32t_cnt(request->error_status, &len);
1008 OF_BUILD_EXEC( snmp_pbuf_stream_seek_abs(&(request->outbound_pbuf_stream), request->outbound_error_status_offset) );
1009 OF_BUILD_EXEC( snmp_asn1_enc_s32t(&(request->outbound_pbuf_stream), len, request->error_status) );
1012 switch (request->error_status) {
1013 case SNMP_ERR_TOOBIG:
1014 snmp_stats.outtoobigs++;
1016 case SNMP_ERR_NOSUCHNAME:
1017 snmp_stats.outnosuchnames++;
1019 case SNMP_ERR_BADVALUE:
1020 snmp_stats.outbadvalues++;
1022 case SNMP_ERR_GENERROR:
1024 snmp_stats.outgenerrs++;
1028 if (request->error_status == SNMP_ERR_TOOBIG) {
1029 request->error_index = 0;
1030 }
else if (request->error_index == 0) {
1032 request->error_index = request->inbound_varbind_enumerator.varbind_count;
1035 if (request->request_type == SNMP_ASN1_CONTEXT_PDU_SET_REQ) {
1036 snmp_stats.intotalsetvars += request->inbound_varbind_enumerator.varbind_count;
1038 snmp_stats.intotalreqvars += request->inbound_varbind_enumerator.varbind_count;
1043 if (request->error_index != 0) {
1045 snmp_asn1_enc_s32t_cnt(request->error_index, &len);
1050 OF_BUILD_EXEC( snmp_pbuf_stream_seek_abs(&(request->outbound_pbuf_stream), request->outbound_error_index_offset) );
1051 OF_BUILD_EXEC( snmp_asn1_enc_s32t(&(request->outbound_pbuf_stream), len, request->error_index) );
1055 SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 3, frame_size - request->outbound_varbind_offset);
1056 OF_BUILD_EXEC( snmp_pbuf_stream_seek_abs(&(request->outbound_pbuf_stream), request->outbound_varbind_offset - 1 - 3) );
1057 OF_BUILD_EXEC( snmp_ans1_enc_tlv(&(request->outbound_pbuf_stream), &tlv) );
1061 snmp_stats.outgetresponses++;
1062 snmp_stats.outpkts++;
1068 snmp_execute_write_callbacks(
struct snmp_request *request)
1070 struct snmp_varbind_enumerator inbound_varbind_enumerator;
1071 struct snmp_varbind vb;
1073 snmp_vb_enumerator_init(&inbound_varbind_enumerator, request->inbound_pbuf, request->inbound_varbind_offset, request->inbound_varbind_len);
1076 while (snmp_vb_enumerator_get_next(&inbound_varbind_enumerator, &vb) ==
ERR_OK) {
1077 snmp_write_callback(vb.oid.id, vb.oid.len, snmp_write_callback_arg);
1087 snmp_vb_enumerator_init(
struct snmp_varbind_enumerator* enumerator,
struct pbuf* p,
u16_t offset,
u16_t length)
1089 snmp_pbuf_stream_init(&(enumerator->pbuf_stream), p, offset, length);
1090 enumerator->varbind_count = 0;
1093 #define VB_PARSE_EXEC(code) PARSE_EXEC(code, SNMP_VB_ENUMERATOR_ERR_ASN1ERROR) 1094 #define VB_PARSE_ASSERT(code) PARSE_ASSERT(code, SNMP_VB_ENUMERATOR_ERR_ASN1ERROR) 1096 snmp_vb_enumerator_err_t
1097 snmp_vb_enumerator_get_next(
struct snmp_varbind_enumerator* enumerator,
struct snmp_varbind* varbind)
1099 struct snmp_asn1_tlv tlv;
1103 if (enumerator->pbuf_stream.length == 0)
1105 return SNMP_VB_ENUMERATOR_ERR_EOVB;
1107 enumerator->varbind_count++;
1110 VB_PARSE_EXEC(snmp_asn1_dec_tlv(&(enumerator->pbuf_stream), &tlv));
1111 VB_PARSE_ASSERT((tlv.type == SNMP_ASN1_TYPE_SEQUENCE) && (tlv.value_len <= enumerator->pbuf_stream.length));
1112 varbind_len = tlv.value_len;
1115 VB_PARSE_EXEC(snmp_asn1_dec_tlv(&(enumerator->pbuf_stream), &tlv));
1116 VB_PARSE_ASSERT((tlv.type == SNMP_ASN1_TYPE_OBJECT_ID) && (SNMP_ASN1_TLV_LENGTH(tlv) < varbind_len) && (tlv.value_len < enumerator->pbuf_stream.length));
1118 VB_PARSE_EXEC(snmp_asn1_dec_oid(&(enumerator->pbuf_stream), tlv.value_len, varbind->oid.id, &(varbind->oid.len),
SNMP_MAX_OBJ_ID_LEN));
1119 varbind_len -= SNMP_ASN1_TLV_LENGTH(tlv);
1122 VB_PARSE_EXEC(snmp_asn1_dec_tlv(&(enumerator->pbuf_stream), &tlv));
1123 VB_PARSE_ASSERT((SNMP_ASN1_TLV_LENGTH(tlv) == varbind_len) && (tlv.value_len <= enumerator->pbuf_stream.length));
1124 varbind->type = tlv.type;
1127 if (varbind->value !=
NULL) {
1128 switch (varbind->type) {
1129 case SNMP_ASN1_TYPE_INTEGER:
1130 VB_PARSE_EXEC(snmp_asn1_dec_s32t(&(enumerator->pbuf_stream), tlv.value_len, (
s32_t*)varbind->value));
1131 varbind->value_len =
sizeof(
s32_t*);
1133 case SNMP_ASN1_TYPE_COUNTER:
1134 case SNMP_ASN1_TYPE_GAUGE:
1135 case SNMP_ASN1_TYPE_TIMETICKS:
1136 VB_PARSE_EXEC(snmp_asn1_dec_u32t(&(enumerator->pbuf_stream), tlv.value_len, (
u32_t*)varbind->value));
1137 varbind->value_len =
sizeof(
u32_t*);
1139 case SNMP_ASN1_TYPE_OCTET_STRING:
1140 case SNMP_ASN1_TYPE_OPAQUE:
1141 err = snmp_asn1_dec_raw(&(enumerator->pbuf_stream), tlv.value_len, (
u8_t*)varbind->value, &varbind->value_len,
SNMP_MAX_VALUE_SIZE);
1143 return SNMP_VB_ENUMERATOR_ERR_INVALIDLENGTH;
1145 VB_PARSE_ASSERT(err ==
ERR_OK);
1147 case SNMP_ASN1_TYPE_NULL:
1148 varbind->value_len = 0;
1150 case SNMP_ASN1_TYPE_OBJECT_ID:
1152 err = snmp_asn1_dec_oid(&(enumerator->pbuf_stream), tlv.value_len, (
u32_t*)varbind->value, &tlv.length_len,
SNMP_MAX_OBJ_ID_LEN);
1154 return SNMP_VB_ENUMERATOR_ERR_INVALIDLENGTH;
1156 VB_PARSE_ASSERT(err ==
ERR_OK);
1157 varbind->value_len = tlv.length_len *
sizeof(
u32_t);
1159 case SNMP_ASN1_TYPE_IPADDR:
1160 if (tlv.value_len == 4) {
1162 VB_PARSE_EXEC(snmp_asn1_dec_raw(&(enumerator->pbuf_stream), tlv.value_len, (
u8_t*)varbind->value, &varbind->value_len,
SNMP_MAX_VALUE_SIZE));
1167 case SNMP_ASN1_TYPE_COUNTER64:
1168 VB_PARSE_EXEC(snmp_asn1_dec_u64t(&(enumerator->pbuf_stream), tlv.value_len, (
u32_t*)varbind->value));
1169 varbind->value_len = 2 *
sizeof(
u32_t*);
1176 snmp_pbuf_stream_seek(&(enumerator->pbuf_stream), tlv.value_len);
1177 varbind->value_len = tlv.value_len;
1180 return SNMP_VB_ENUMERATOR_ERR_OK;
#define SNMP_COMMUNITY_WRITE
#define SNMP_LWIP_GETBULK_MAX_REPETITIONS
void pbuf_realloc(struct pbuf *p, u16_t new_len)
#define SNMP_MAX_OBJ_ID_LEN
struct pbuf * pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type)
u8_t pbuf_free(struct pbuf *p)
#define LWIP_ASSERT(message, assertion)
#define SNMP_COMMUNITY_TRAP
#define SNMP_MAX_COMMUNITY_STR_LEN
#define SNMP_MAX_VALUE_SIZE
#define LWIP_DEBUGF(debug, message)