BadVPN – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 /**
2 * @file
3 * SNMP message processing (RFC1157).
4 */
5  
6 /*
7 * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands.
8 * Copyright (c) 2016 Elias Oenal.
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without modification,
12 * are permitted provided that the following conditions are met:
13 *
14 * 1. Redistributions of source code must retain the above copyright notice,
15 * this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright notice,
17 * this list of conditions and the following disclaimer in the documentation
18 * and/or other materials provided with the distribution.
19 * 3. The name of the author may not be used to endorse or promote products
20 * derived from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
23 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
24 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
25 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
26 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
27 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
30 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
31 * OF SUCH DAMAGE.
32 *
33 * Author: Christiaan Simons <christiaan.simons@axon.tv>
34 * Martin Hentschel <info@cl-soft.de>
35 * Elias Oenal <lwip@eliasoenal.com>
36 */
37  
38 #include "lwip/apps/snmp_opts.h"
39  
40 #if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */
41  
42 #include "snmp_msg.h"
43 #include "snmp_asn1.h"
44 #include "snmp_core_priv.h"
45 #include "lwip/ip_addr.h"
46 #include "lwip/stats.h"
47  
48 #if LWIP_SNMP_V3
49 #include "lwip/apps/snmpv3.h"
50 #include "snmpv3_priv.h"
51 #ifdef LWIP_HOOK_FILENAME
52 #include LWIP_HOOK_FILENAME
53 #endif
54 #endif
55  
56 #include <string.h>
57  
58 #define SNMP_V3_AUTH_FLAG 0x01
59 #define SNMP_V3_PRIV_FLAG 0x02
60  
61 /* Security levels */
62 #define SNMP_V3_NOAUTHNOPRIV 0x00
63 #define SNMP_V3_AUTHNOPRIV SNMP_V3_AUTH_FLAG
64 #define SNMP_V3_AUTHPRIV (SNMP_V3_AUTH_FLAG | SNMP_V3_PRIV_FLAG)
65  
66 /* public (non-static) constants */
67 /** SNMP community string */
68 const char *snmp_community = SNMP_COMMUNITY;
69 /** SNMP community string for write access */
70 const char *snmp_community_write = SNMP_COMMUNITY_WRITE;
71 /** SNMP community string for sending traps */
72 const char *snmp_community_trap = SNMP_COMMUNITY_TRAP;
73  
74 snmp_write_callback_fct snmp_write_callback = NULL;
75 void *snmp_write_callback_arg = NULL;
76  
77 #if LWIP_SNMP_CONFIGURE_VERSIONS
78  
79 static u8_t v1_enabled = 1;
80 static u8_t v2c_enabled = 1;
81 static u8_t v3_enabled = 1;
82  
83 static u8_t
84 snmp_version_enabled(u8_t version)
85 {
86 LWIP_ASSERT("Invalid SNMP version", (version == SNMP_VERSION_1) || (version == SNMP_VERSION_2c)
87 #if LWIP_SNMP_V3
88 || (version == SNMP_VERSION_3)
89 #endif
90 );
91  
92 if (version == SNMP_VERSION_1) {
93 return v1_enabled;
94 } else if (version == SNMP_VERSION_2c) {
95 return v2c_enabled;
96 }
97 #if LWIP_SNMP_V3
98 else { /* version == SNMP_VERSION_3 */
99 return v3_enabled;
100 }
101 #endif
102 }
103  
104 u8_t
105 snmp_v1_enabled(void)
106 {
107 return snmp_version_enabled(SNMP_VERSION_1);
108 }
109  
110 u8_t
111 snmp_v2c_enabled(void)
112 {
113 return snmp_version_enabled(SNMP_VERSION_2c);
114 }
115  
116 u8_t
117 snmp_v3_enabled(void)
118 {
119 return snmp_version_enabled(SNMP_VERSION_3);
120 }
121  
122 static void
123 snmp_version_enable(u8_t version, u8_t enable)
124 {
125 LWIP_ASSERT("Invalid SNMP version", (version == SNMP_VERSION_1) || (version == SNMP_VERSION_2c)
126 #if LWIP_SNMP_V3
127 || (version == SNMP_VERSION_3)
128 #endif
129 );
130  
131 if (version == SNMP_VERSION_1) {
132 v1_enabled = enable;
133 } else if (version == SNMP_VERSION_2c) {
134 v2c_enabled = enable;
135 }
136 #if LWIP_SNMP_V3
137 else { /* version == SNMP_VERSION_3 */
138 v3_enabled = enable;
139 }
140 #endif
141 }
142  
143 void
144 snmp_v1_enable(u8_t enable)
145 {
146 snmp_version_enable(SNMP_VERSION_1, enable);
147 }
148  
149 void
150 snmp_v2c_enable(u8_t enable)
151 {
152 snmp_version_enable(SNMP_VERSION_2c, enable);
153 }
154  
155 void
156 snmp_v3_enable(u8_t enable)
157 {
158 snmp_version_enable(SNMP_VERSION_3, enable);
159 }
160  
161 #endif
162  
163 /**
164 * @ingroup snmp_core
165 * Returns current SNMP community string.
166 * @return current SNMP community string
167 */
168 const char *
169 snmp_get_community(void)
170 {
171 return snmp_community;
172 }
173  
174 /**
175 * @ingroup snmp_core
176 * Sets SNMP community string.
177 * The string itself (its storage) must be valid throughout the whole life of
178 * program (or until it is changed to sth else).
179 *
180 * @param community is a pointer to new community string
181 */
182 void
183 snmp_set_community(const char *const community)
184 {
185 LWIP_ASSERT("community string is too long!", strlen(community) <= SNMP_MAX_COMMUNITY_STR_LEN);
186 snmp_community = community;
187 }
188  
189 /**
190 * @ingroup snmp_core
191 * Returns current SNMP write-access community string.
192 * @return current SNMP write-access community string
193 */
194 const char *
195 snmp_get_community_write(void)
196 {
197 return snmp_community_write;
198 }
199  
200 /**
201 * @ingroup snmp_traps
202 * Returns current SNMP community string used for sending traps.
203 * @return current SNMP community string used for sending traps
204 */
205 const char *
206 snmp_get_community_trap(void)
207 {
208 return snmp_community_trap;
209 }
210  
211 /**
212 * @ingroup snmp_core
213 * Sets SNMP community string for write-access.
214 * The string itself (its storage) must be valid throughout the whole life of
215 * program (or until it is changed to sth else).
216 *
217 * @param community is a pointer to new write-access community string
218 */
219 void
220 snmp_set_community_write(const char *const community)
221 {
222 LWIP_ASSERT("community string must not be NULL", community != NULL);
223 LWIP_ASSERT("community string is too long!", strlen(community) <= SNMP_MAX_COMMUNITY_STR_LEN);
224 snmp_community_write = community;
225 }
226  
227 /**
228 * @ingroup snmp_traps
229 * Sets SNMP community string used for sending traps.
230 * The string itself (its storage) must be valid throughout the whole life of
231 * program (or until it is changed to sth else).
232 *
233 * @param community is a pointer to new trap community string
234 */
235 void
236 snmp_set_community_trap(const char *const community)
237 {
238 LWIP_ASSERT("community string is too long!", strlen(community) <= SNMP_MAX_COMMUNITY_STR_LEN);
239 snmp_community_trap = community;
240 }
241  
242 /**
243 * @ingroup snmp_core
244 * Callback fired on every successful write access
245 */
246 void
247 snmp_set_write_callback(snmp_write_callback_fct write_callback, void *callback_arg)
248 {
249 snmp_write_callback = write_callback;
250 snmp_write_callback_arg = callback_arg;
251 }
252  
253 /* ----------------------------------------------------------------------- */
254 /* forward declarations */
255 /* ----------------------------------------------------------------------- */
256  
257 static err_t snmp_process_get_request(struct snmp_request *request);
258 static err_t snmp_process_getnext_request(struct snmp_request *request);
259 static err_t snmp_process_getbulk_request(struct snmp_request *request);
260 static err_t snmp_process_set_request(struct snmp_request *request);
261  
262 static err_t snmp_parse_inbound_frame(struct snmp_request *request);
263 static err_t snmp_prepare_outbound_frame(struct snmp_request *request);
264 static err_t snmp_complete_outbound_frame(struct snmp_request *request);
265 static void snmp_execute_write_callbacks(struct snmp_request *request);
266  
267  
268 /* ----------------------------------------------------------------------- */
269 /* implementation */
270 /* ----------------------------------------------------------------------- */
271  
272 void
273 snmp_receive(void *handle, struct pbuf *p, const ip_addr_t *source_ip, u16_t port)
274 {
275 err_t err;
276 struct snmp_request request;
277  
278 memset(&request, 0, sizeof(request));
279 request.handle = handle;
280 request.source_ip = source_ip;
281 request.source_port = port;
282 request.inbound_pbuf = p;
283  
284 snmp_stats.inpkts++;
285  
286 err = snmp_parse_inbound_frame(&request);
287 if (err == ERR_OK) {
288 err = snmp_prepare_outbound_frame(&request);
289 if (err == ERR_OK) {
290  
291 if (request.error_status == SNMP_ERR_NOERROR) {
292 /* only process frame if we do not already have an error to return (e.g. all readonly) */
293 if (request.request_type == SNMP_ASN1_CONTEXT_PDU_GET_REQ) {
294 err = snmp_process_get_request(&request);
295 } else if (request.request_type == SNMP_ASN1_CONTEXT_PDU_GET_NEXT_REQ) {
296 err = snmp_process_getnext_request(&request);
297 } else if (request.request_type == SNMP_ASN1_CONTEXT_PDU_GET_BULK_REQ) {
298 err = snmp_process_getbulk_request(&request);
299 } else if (request.request_type == SNMP_ASN1_CONTEXT_PDU_SET_REQ) {
300 err = snmp_process_set_request(&request);
301 }
302 }
303 #if LWIP_SNMP_V3
304 else {
305 struct snmp_varbind vb;
306  
307 vb.next = NULL;
308 vb.prev = NULL;
309 vb.type = SNMP_ASN1_TYPE_COUNTER32;
310 vb.value_len = sizeof(u32_t);
311  
312 switch (request.error_status) {
313 case SNMP_ERR_AUTHORIZATIONERROR: {
314 static const u32_t oid[] = { 1, 3, 6, 1, 6, 3, 15, 1, 1, 5, 0 };
315 snmp_oid_assign(&vb.oid, oid, LWIP_ARRAYSIZE(oid));
316 vb.value = &snmp_stats.wrongdigests;
317 }
318 break;
319 case SNMP_ERR_UNKNOWN_ENGINEID: {
320 static const u32_t oid[] = { 1, 3, 6, 1, 6, 3, 15, 1, 1, 4, 0 };
321 snmp_oid_assign(&vb.oid, oid, LWIP_ARRAYSIZE(oid));
322 vb.value = &snmp_stats.unknownengineids;
323 }
324 break;
325 case SNMP_ERR_UNKNOWN_SECURITYNAME: {
326 static const u32_t oid[] = { 1, 3, 6, 1, 6, 3, 15, 1, 1, 3, 0 };
327 snmp_oid_assign(&vb.oid, oid, LWIP_ARRAYSIZE(oid));
328 vb.value = &snmp_stats.unknownusernames;
329 }
330 break;
331 case SNMP_ERR_UNSUPPORTED_SECLEVEL: {
332 static const u32_t oid[] = { 1, 3, 6, 1, 6, 3, 15, 1, 1, 1, 0 };
333 snmp_oid_assign(&vb.oid, oid, LWIP_ARRAYSIZE(oid));
334 vb.value = &snmp_stats.unsupportedseclevels;
335 }
336 break;
337 case SNMP_ERR_NOTINTIMEWINDOW: {
338 static const u32_t oid[] = { 1, 3, 6, 1, 6, 3, 15, 1, 1, 2, 0 };
339 snmp_oid_assign(&vb.oid, oid, LWIP_ARRAYSIZE(oid));
340 vb.value = &snmp_stats.notintimewindows;
341 }
342 break;
343 case SNMP_ERR_DECRYIPTION_ERROR: {
344 static const u32_t oid[] = { 1, 3, 6, 1, 6, 3, 15, 1, 1, 6, 0 };
345 snmp_oid_assign(&vb.oid, oid, LWIP_ARRAYSIZE(oid));
346 vb.value = &snmp_stats.decryptionerrors;
347 }
348 break;
349 default:
350 /* Unknown or unhandled error_status */
351 err = ERR_ARG;
352 }
353  
354 if (err == ERR_OK) {
355 snmp_append_outbound_varbind(&(request.outbound_pbuf_stream), &vb);
356 request.error_status = SNMP_ERR_NOERROR;
357 }
358  
359 request.request_out_type = (SNMP_ASN1_CLASS_CONTEXT | SNMP_ASN1_CONTENTTYPE_CONSTRUCTED | SNMP_ASN1_CONTEXT_PDU_REPORT);
360 request.request_id = request.msg_id;
361 }
362 #endif
363  
364 if (err == ERR_OK) {
365 err = snmp_complete_outbound_frame(&request);
366  
367 if (err == ERR_OK) {
368 err = snmp_sendto(request.handle, request.outbound_pbuf, request.source_ip, request.source_port);
369  
370 if ((request.request_type == SNMP_ASN1_CONTEXT_PDU_SET_REQ)
371 && (request.error_status == SNMP_ERR_NOERROR)
372 && (snmp_write_callback != NULL)) {
373 /* raise write notification for all written objects */
374 snmp_execute_write_callbacks(&request);
375 }
376 }
377 }
378 }
379  
380 if (request.outbound_pbuf != NULL) {
381 pbuf_free(request.outbound_pbuf);
382 }
383 }
384 }
385  
386 static u8_t
387 snmp_msg_getnext_validate_node_inst(struct snmp_node_instance *node_instance, void *validate_arg)
388 {
389 if (((node_instance->access & SNMP_NODE_INSTANCE_ACCESS_READ) != SNMP_NODE_INSTANCE_ACCESS_READ) || (node_instance->get_value == NULL)) {
390 return SNMP_ERR_NOSUCHINSTANCE;
391 }
392  
393 #if LWIP_HAVE_INT64
394 if ((node_instance->asn1_type == SNMP_ASN1_TYPE_COUNTER64) && (((struct snmp_request *)validate_arg)->version == SNMP_VERSION_1)) {
395 /* according to RFC 2089 skip Counter64 objects in GetNext requests from v1 clients */
396 return SNMP_ERR_NOSUCHINSTANCE;
397 }
398 #endif
399  
400 return SNMP_ERR_NOERROR;
401 }
402  
403 static void
404 snmp_process_varbind(struct snmp_request *request, struct snmp_varbind *vb, u8_t get_next)
405 {
406 err_t err;
407 struct snmp_node_instance node_instance;
408 memset(&node_instance, 0, sizeof(node_instance));
409  
410 if (get_next) {
411 struct snmp_obj_id result_oid;
412 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);
413  
414 if (request->error_status == SNMP_ERR_NOERROR) {
415 snmp_oid_assign(&vb->oid, result_oid.id, result_oid.len);
416 }
417 } else {
418 request->error_status = snmp_get_node_instance_from_oid(vb->oid.id, vb->oid.len, &node_instance);
419  
420 if (request->error_status == SNMP_ERR_NOERROR) {
421 /* use 'getnext_validate' method for validation to avoid code duplication (some checks have to be executed here) */
422 request->error_status = snmp_msg_getnext_validate_node_inst(&node_instance, request);
423  
424 if (request->error_status != SNMP_ERR_NOERROR) {
425 if (node_instance.release_instance != NULL) {
426 node_instance.release_instance(&node_instance);
427 }
428 }
429 }
430 }
431  
432 if (request->error_status != SNMP_ERR_NOERROR) {
433 if (request->error_status >= SNMP_VARBIND_EXCEPTION_OFFSET) {
434 if ((request->version == SNMP_VERSION_2c) || request->version == SNMP_VERSION_3) {
435 /* in SNMP v2c a varbind related exception is stored in varbind and not in frame header */
436 vb->type = (SNMP_ASN1_CONTENTTYPE_PRIMITIVE | SNMP_ASN1_CLASS_CONTEXT | (request->error_status & SNMP_VARBIND_EXCEPTION_MASK));
437 vb->value_len = 0;
438  
439 err = snmp_append_outbound_varbind(&(request->outbound_pbuf_stream), vb);
440 if (err == ERR_OK) {
441 /* we stored the exception in varbind -> go on */
442 request->error_status = SNMP_ERR_NOERROR;
443 } else if (err == ERR_BUF) {
444 request->error_status = SNMP_ERR_TOOBIG;
445 } else {
446 request->error_status = SNMP_ERR_GENERROR;
447 }
448 }
449 } else {
450 /* according to RFC 1157/1905, all other errors only return genError */
451 request->error_status = SNMP_ERR_GENERROR;
452 }
453 } else {
454 s16_t len = node_instance.get_value(&node_instance, vb->value);
455 vb->type = node_instance.asn1_type;
456  
457 if (len >= 0) {
458 vb->value_len = (u16_t)len; /* cast is OK because we checked >= 0 above */
459  
460 LWIP_ASSERT("SNMP_MAX_VALUE_SIZE is configured too low", (vb->value_len & ~SNMP_GET_VALUE_RAW_DATA) <= SNMP_MAX_VALUE_SIZE);
461 err = snmp_append_outbound_varbind(&request->outbound_pbuf_stream, vb);
462  
463 if (err == ERR_BUF) {
464 request->error_status = SNMP_ERR_TOOBIG;
465 } else if (err != ERR_OK) {
466 request->error_status = SNMP_ERR_GENERROR;
467 }
468 } else {
469 request->error_status = SNMP_ERR_GENERROR;
470 }
471  
472 if (node_instance.release_instance != NULL) {
473 node_instance.release_instance(&node_instance);
474 }
475 }
476 }
477  
478  
479 /**
480 * Service an internal or external event for SNMP GET.
481 *
482 * @param request points to the associated message process state
483 */
484 static err_t
485 snmp_process_get_request(struct snmp_request *request)
486 {
487 snmp_vb_enumerator_err_t err;
488 struct snmp_varbind vb;
489 vb.value = request->value_buffer;
490  
491 LWIP_DEBUGF(SNMP_DEBUG, ("SNMP get request\n"));
492  
493 while (request->error_status == SNMP_ERR_NOERROR) {
494 err = snmp_vb_enumerator_get_next(&request->inbound_varbind_enumerator, &vb);
495 if (err == SNMP_VB_ENUMERATOR_ERR_OK) {
496 if ((vb.type == SNMP_ASN1_TYPE_NULL) && (vb.value_len == 0)) {
497 snmp_process_varbind(request, &vb, 0);
498 } else {
499 request->error_status = SNMP_ERR_GENERROR;
500 }
501 } else if (err == SNMP_VB_ENUMERATOR_ERR_EOVB) {
502 /* no more varbinds in request */
503 break;
504 } else if (err == SNMP_VB_ENUMERATOR_ERR_ASN1ERROR) {
505 /* malformed ASN.1, don't answer */
506 return ERR_ARG;
507 } else {
508 request->error_status = SNMP_ERR_GENERROR;
509 }
510 }
511  
512 return ERR_OK;
513 }
514  
515 /**
516 * Service an internal or external event for SNMP GET.
517 *
518 * @param request points to the associated message process state
519 */
520 static err_t
521 snmp_process_getnext_request(struct snmp_request *request)
522 {
523 snmp_vb_enumerator_err_t err;
524 struct snmp_varbind vb;
525 vb.value = request->value_buffer;
526  
527 LWIP_DEBUGF(SNMP_DEBUG, ("SNMP get-next request\n"));
528  
529 while (request->error_status == SNMP_ERR_NOERROR) {
530 err = snmp_vb_enumerator_get_next(&request->inbound_varbind_enumerator, &vb);
531 if (err == SNMP_VB_ENUMERATOR_ERR_OK) {
532 if ((vb.type == SNMP_ASN1_TYPE_NULL) && (vb.value_len == 0)) {
533 snmp_process_varbind(request, &vb, 1);
534 } else {
535 request->error_status = SNMP_ERR_GENERROR;
536 }
537 } else if (err == SNMP_VB_ENUMERATOR_ERR_EOVB) {
538 /* no more varbinds in request */
539 break;
540 } else if (err == SNMP_VB_ENUMERATOR_ERR_ASN1ERROR) {
541 /* malformed ASN.1, don't answer */
542 return ERR_ARG;
543 } else {
544 request->error_status = SNMP_ERR_GENERROR;
545 }
546 }
547  
548 return ERR_OK;
549 }
550  
551 /**
552 * Service an internal or external event for SNMP GETBULKT.
553 *
554 * @param request points to the associated message process state
555 */
556 static err_t
557 snmp_process_getbulk_request(struct snmp_request *request)
558 {
559 snmp_vb_enumerator_err_t err;
560 s32_t non_repeaters = request->non_repeaters;
561 s32_t repetitions;
562 u16_t repetition_offset = 0;
563 struct snmp_varbind_enumerator repetition_varbind_enumerator;
564 struct snmp_varbind vb;
565 vb.value = request->value_buffer;
566  
567 if (SNMP_LWIP_GETBULK_MAX_REPETITIONS > 0) {
568 repetitions = LWIP_MIN(request->max_repetitions, SNMP_LWIP_GETBULK_MAX_REPETITIONS);
569 } else {
570 repetitions = request->max_repetitions;
571 }
572  
573 LWIP_DEBUGF(SNMP_DEBUG, ("SNMP get-bulk request\n"));
574  
575 /* process non repeaters and first repetition */
576 while (request->error_status == SNMP_ERR_NOERROR) {
577 if (non_repeaters == 0) {
578 repetition_offset = request->outbound_pbuf_stream.offset;
579  
580 if (repetitions == 0) {
581 /* do not resolve repeaters when repetitions is set to 0 */
582 break;
583 }
584 repetitions--;
585 }
586  
587 err = snmp_vb_enumerator_get_next(&request->inbound_varbind_enumerator, &vb);
588 if (err == SNMP_VB_ENUMERATOR_ERR_EOVB) {
589 /* no more varbinds in request */
590 break;
591 } else if (err == SNMP_VB_ENUMERATOR_ERR_ASN1ERROR) {
592 /* malformed ASN.1, don't answer */
593 return ERR_ARG;
594 } else if ((err != SNMP_VB_ENUMERATOR_ERR_OK) || (vb.type != SNMP_ASN1_TYPE_NULL) || (vb.value_len != 0)) {
595 request->error_status = SNMP_ERR_GENERROR;
596 } else {
597 snmp_process_varbind(request, &vb, 1);
598 non_repeaters--;
599 }
600 }
601  
602 /* process repetitions > 1 */
603 while ((request->error_status == SNMP_ERR_NOERROR) && (repetitions > 0) && (request->outbound_pbuf_stream.offset != repetition_offset)) {
604  
605 u8_t all_endofmibview = 1;
606  
607 snmp_vb_enumerator_init(&repetition_varbind_enumerator, request->outbound_pbuf, repetition_offset, request->outbound_pbuf_stream.offset - repetition_offset);
608 repetition_offset = request->outbound_pbuf_stream.offset; /* for next loop */
609  
610 while (request->error_status == SNMP_ERR_NOERROR) {
611 vb.value = NULL; /* do NOT decode value (we enumerate outbound buffer here, so all varbinds have values assigned) */
612 err = snmp_vb_enumerator_get_next(&repetition_varbind_enumerator, &vb);
613 if (err == SNMP_VB_ENUMERATOR_ERR_OK) {
614 vb.value = request->value_buffer;
615 snmp_process_varbind(request, &vb, 1);
616  
617 if (request->error_status != SNMP_ERR_NOERROR) {
618 /* already set correct error-index (here it cannot be taken from inbound varbind enumerator) */
619 request->error_index = request->non_repeaters + repetition_varbind_enumerator.varbind_count;
620 } else if (vb.type != (SNMP_ASN1_CONTENTTYPE_PRIMITIVE | SNMP_ASN1_CLASS_CONTEXT | SNMP_ASN1_CONTEXT_VARBIND_END_OF_MIB_VIEW)) {
621 all_endofmibview = 0;
622 }
623 } else if (err == SNMP_VB_ENUMERATOR_ERR_EOVB) {
624 /* no more varbinds in request */
625 break;
626 } else {
627 LWIP_DEBUGF(SNMP_DEBUG, ("Very strange, we cannot parse the varbind output that we created just before!"));
628 request->error_status = SNMP_ERR_GENERROR;
629 request->error_index = request->non_repeaters + repetition_varbind_enumerator.varbind_count;
630 }
631 }
632  
633 if ((request->error_status == SNMP_ERR_NOERROR) && all_endofmibview) {
634 /* stop when all varbinds in a loop return EndOfMibView */
635 break;
636 }
637  
638 repetitions--;
639 }
640  
641 if (request->error_status == SNMP_ERR_TOOBIG) {
642 /* for GetBulk it is ok, if not all requested variables fit into the response -> just return the varbinds added so far */
643 request->error_status = SNMP_ERR_NOERROR;
644 }
645  
646 return ERR_OK;
647 }
648  
649 /**
650 * Service an internal or external event for SNMP SET.
651 *
652 * @param request points to the associated message process state
653 */
654 static err_t
655 snmp_process_set_request(struct snmp_request *request)
656 {
657 snmp_vb_enumerator_err_t err;
658 struct snmp_varbind vb;
659 vb.value = request->value_buffer;
660  
661 LWIP_DEBUGF(SNMP_DEBUG, ("SNMP set request\n"));
662  
663 /* perform set test on all objects */
664 while (request->error_status == SNMP_ERR_NOERROR) {
665 err = snmp_vb_enumerator_get_next(&request->inbound_varbind_enumerator, &vb);
666 if (err == SNMP_VB_ENUMERATOR_ERR_OK) {
667 struct snmp_node_instance node_instance;
668 memset(&node_instance, 0, sizeof(node_instance));
669  
670 request->error_status = snmp_get_node_instance_from_oid(vb.oid.id, vb.oid.len, &node_instance);
671 if (request->error_status == SNMP_ERR_NOERROR) {
672 if (node_instance.asn1_type != vb.type) {
673 request->error_status = SNMP_ERR_WRONGTYPE;
674 } else if (((node_instance.access & SNMP_NODE_INSTANCE_ACCESS_WRITE) != SNMP_NODE_INSTANCE_ACCESS_WRITE) || (node_instance.set_value == NULL)) {
675 request->error_status = SNMP_ERR_NOTWRITABLE;
676 } else {
677 if (node_instance.set_test != NULL) {
678 request->error_status = node_instance.set_test(&node_instance, vb.value_len, vb.value);
679 }
680 }
681  
682 if (node_instance.release_instance != NULL) {
683 node_instance.release_instance(&node_instance);
684 }
685 }
686 } else if (err == SNMP_VB_ENUMERATOR_ERR_EOVB) {
687 /* no more varbinds in request */
688 break;
689 } else if (err == SNMP_VB_ENUMERATOR_ERR_INVALIDLENGTH) {
690 request->error_status = SNMP_ERR_WRONGLENGTH;
691 } else if (err == SNMP_VB_ENUMERATOR_ERR_ASN1ERROR) {
692 /* malformed ASN.1, don't answer */
693 return ERR_ARG;
694 } else {
695 request->error_status = SNMP_ERR_GENERROR;
696 }
697 }
698  
699 /* perform real set operation on all objects */
700 if (request->error_status == SNMP_ERR_NOERROR) {
701 snmp_vb_enumerator_init(&request->inbound_varbind_enumerator, request->inbound_pbuf, request->inbound_varbind_offset, request->inbound_varbind_len);
702 while (request->error_status == SNMP_ERR_NOERROR) {
703 err = snmp_vb_enumerator_get_next(&request->inbound_varbind_enumerator, &vb);
704 if (err == SNMP_VB_ENUMERATOR_ERR_OK) {
705 struct snmp_node_instance node_instance;
706 memset(&node_instance, 0, sizeof(node_instance));
707 request->error_status = snmp_get_node_instance_from_oid(vb.oid.id, vb.oid.len, &node_instance);
708 if (request->error_status == SNMP_ERR_NOERROR) {
709 if (node_instance.set_value(&node_instance, vb.value_len, vb.value) != SNMP_ERR_NOERROR) {
710 if (request->inbound_varbind_enumerator.varbind_count == 1) {
711 request->error_status = SNMP_ERR_COMMITFAILED;
712 } else {
713 /* we cannot undo the set operations done so far */
714 request->error_status = SNMP_ERR_UNDOFAILED;
715 }
716 }
717  
718 if (node_instance.release_instance != NULL) {
719 node_instance.release_instance(&node_instance);
720 }
721 }
722 } else if (err == SNMP_VB_ENUMERATOR_ERR_EOVB) {
723 /* no more varbinds in request */
724 break;
725 } else {
726 /* first time enumerating varbinds work but second time not, although nothing should have changed in between ??? */
727 request->error_status = SNMP_ERR_GENERROR;
728 }
729 }
730 }
731  
732 return ERR_OK;
733 }
734  
735 #define PARSE_EXEC(code, retValue) \
736 if ((code) != ERR_OK) { \
737 LWIP_DEBUGF(SNMP_DEBUG, ("Malformed ASN.1 detected.\n")); \
738 snmp_stats.inasnparseerrs++; \
739 return retValue; \
740 }
741  
742 #define PARSE_ASSERT(cond, retValue) \
743 if (!(cond)) { \
744 LWIP_DEBUGF(SNMP_DEBUG, ("SNMP parse assertion failed!: " # cond)); \
745 snmp_stats.inasnparseerrs++; \
746 return retValue; \
747 }
748  
749 #define BUILD_EXEC(code, retValue) \
750 if ((code) != ERR_OK) { \
751 LWIP_DEBUGF(SNMP_DEBUG, ("SNMP error during creation of outbound frame!: " # code)); \
752 return retValue; \
753 }
754  
755 #define IF_PARSE_EXEC(code) PARSE_EXEC(code, ERR_ARG)
756 #define IF_PARSE_ASSERT(code) PARSE_ASSERT(code, ERR_ARG)
757  
758 /**
759 * Checks and decodes incoming SNMP message header, logs header errors.
760 *
761 * @param request points to the current message request state return
762 * @return
763 * - ERR_OK SNMP header is sane and accepted
764 * - ERR_VAL SNMP header is either malformed or rejected
765 */
766 static err_t
767 snmp_parse_inbound_frame(struct snmp_request *request)
768 {
769 struct snmp_pbuf_stream pbuf_stream;
770 struct snmp_asn1_tlv tlv;
771 s32_t parent_tlv_value_len;
772 s32_t s32_value;
773 err_t err;
774 #if LWIP_SNMP_V3
775 snmpv3_auth_algo_t auth;
776 snmpv3_priv_algo_t priv;
777 #endif
778  
779 IF_PARSE_EXEC(snmp_pbuf_stream_init(&pbuf_stream, request->inbound_pbuf, 0, request->inbound_pbuf->tot_len));
780  
781 /* decode main container consisting of version, community and PDU */
782 IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv));
783 IF_PARSE_ASSERT((tlv.type == SNMP_ASN1_TYPE_SEQUENCE) && (tlv.value_len == pbuf_stream.length));
784 parent_tlv_value_len = tlv.value_len;
785  
786 /* decode version */
787 IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv));
788 IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_INTEGER);
789 parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv);
790 IF_PARSE_ASSERT(parent_tlv_value_len > 0);
791  
792 IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &s32_value));
793  
794 if (((s32_value != SNMP_VERSION_1) &&
795 (s32_value != SNMP_VERSION_2c)
796 #if LWIP_SNMP_V3
797 && (s32_value != SNMP_VERSION_3)
798 #endif
799 )
800 #if LWIP_SNMP_CONFIGURE_VERSIONS
801 || (!snmp_version_enabled(s32_value))
802 #endif
803 ) {
804 /* unsupported SNMP version */
805 snmp_stats.inbadversions++;
806 return ERR_ARG;
807 }
808 request->version = (u8_t)s32_value;
809  
810 #if LWIP_SNMP_V3
811 if (request->version == SNMP_VERSION_3) {
812 u16_t u16_value;
813 u16_t inbound_msgAuthenticationParameters_offset;
814  
815 /* SNMPv3 doesn't use communities */
816 /* @todo: Differentiate read/write access */
817 strncpy((char *)request->community, snmp_community, SNMP_MAX_COMMUNITY_STR_LEN);
818 request->community[SNMP_MAX_COMMUNITY_STR_LEN] = 0; /* ensure NULL termination (strncpy does NOT guarantee it!) */
819 request->community_strlen = (u16_t)strnlen((char *)request->community, SNMP_MAX_COMMUNITY_STR_LEN);
820  
821 /* RFC3414 globalData */
822 IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv));
823 IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_SEQUENCE);
824 parent_tlv_value_len -= SNMP_ASN1_TLV_HDR_LENGTH(tlv);
825 IF_PARSE_ASSERT(parent_tlv_value_len > 0);
826  
827 /* decode msgID */
828 IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv));
829 IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_INTEGER);
830 parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv);
831 IF_PARSE_ASSERT(parent_tlv_value_len > 0);
832  
833 IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &s32_value));
834 request->msg_id = s32_value;
835  
836 /* decode msgMaxSize */
837 IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv));
838 IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_INTEGER);
839 parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv);
840 IF_PARSE_ASSERT(parent_tlv_value_len > 0);
841  
842 IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &s32_value));
843 request->msg_max_size = s32_value;
844  
845 /* decode msgFlags */
846 IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv));
847 IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_OCTET_STRING);
848 parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv);
849 IF_PARSE_ASSERT(parent_tlv_value_len > 0);
850  
851 IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &s32_value));
852 request->msg_flags = (u8_t)s32_value;
853  
854 /* decode msgSecurityModel */
855 IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv));
856 IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_INTEGER);
857 parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv);
858 IF_PARSE_ASSERT(parent_tlv_value_len > 0);
859  
860 IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &s32_value));
861 request->msg_security_model = s32_value;
862  
863 /* RFC3414 msgSecurityParameters
864 * The User-based Security Model defines the contents of the OCTET
865 * STRING as a SEQUENCE.
866 *
867 * We skip the protective dummy OCTET STRING header
868 * to access the SEQUENCE header.
869 */
870 IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv));
871 IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_OCTET_STRING);
872 parent_tlv_value_len -= SNMP_ASN1_TLV_HDR_LENGTH(tlv);
873 IF_PARSE_ASSERT(parent_tlv_value_len > 0);
874  
875 /* msgSecurityParameters SEQUENCE header */
876 IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv));
877 IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_SEQUENCE);
878 parent_tlv_value_len -= SNMP_ASN1_TLV_HDR_LENGTH(tlv);
879 IF_PARSE_ASSERT(parent_tlv_value_len > 0);
880  
881 /* decode msgAuthoritativeEngineID */
882 IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv));
883 IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_OCTET_STRING);
884 parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv);
885 IF_PARSE_ASSERT(parent_tlv_value_len > 0);
886  
887 IF_PARSE_EXEC(snmp_asn1_dec_raw(&pbuf_stream, tlv.value_len, request->msg_authoritative_engine_id,
888 &u16_value, SNMP_V3_MAX_ENGINE_ID_LENGTH));
889 request->msg_authoritative_engine_id_len = (u8_t)u16_value;
890  
891 /* msgAuthoritativeEngineBoots */
892 IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv));
893 IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_INTEGER);
894 parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv);
895 IF_PARSE_ASSERT(parent_tlv_value_len > 0);
896 IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &request->msg_authoritative_engine_boots));
897  
898 /* msgAuthoritativeEngineTime */
899 IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv));
900 IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_INTEGER);
901 parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv);
902 IF_PARSE_ASSERT(parent_tlv_value_len > 0);
903 IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &request->msg_authoritative_engine_time));
904  
905 /* msgUserName */
906 IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv));
907 IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_OCTET_STRING);
908 parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv);
909 IF_PARSE_ASSERT(parent_tlv_value_len > 0);
910  
911 IF_PARSE_EXEC(snmp_asn1_dec_raw(&pbuf_stream, tlv.value_len, request->msg_user_name,
912 &u16_value, SNMP_V3_MAX_USER_LENGTH));
913 request->msg_user_name_len = (u8_t)u16_value;
914  
915 /* msgAuthenticationParameters */
916 memset(request->msg_authentication_parameters, 0, SNMP_V3_MAX_AUTH_PARAM_LENGTH);
917 IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv));
918 IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_OCTET_STRING);
919 parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv);
920 IF_PARSE_ASSERT(parent_tlv_value_len > 0);
921 /* Remember position */
922 inbound_msgAuthenticationParameters_offset = pbuf_stream.offset;
923 LWIP_UNUSED_ARG(inbound_msgAuthenticationParameters_offset);
924 /* Read auth parameters */
925 /* IF_PARSE_ASSERT(tlv.value_len <= SNMP_V3_MAX_AUTH_PARAM_LENGTH); */
926 IF_PARSE_EXEC(snmp_asn1_dec_raw(&pbuf_stream, tlv.value_len, request->msg_authentication_parameters,
927 &u16_value, tlv.value_len));
928 request->msg_authentication_parameters_len = (u8_t)u16_value;
929  
930 /* msgPrivacyParameters */
931 memset(request->msg_privacy_parameters, 0, SNMP_V3_MAX_PRIV_PARAM_LENGTH);
932 IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv));
933 IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_OCTET_STRING);
934 parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv);
935 IF_PARSE_ASSERT(parent_tlv_value_len > 0);
936  
937 IF_PARSE_EXEC(snmp_asn1_dec_raw(&pbuf_stream, tlv.value_len, request->msg_privacy_parameters,
938 &u16_value, SNMP_V3_MAX_PRIV_PARAM_LENGTH));
939 request->msg_privacy_parameters_len = (u8_t)u16_value;
940  
941 /* validate securityParameters here (do this after decoding because we don't want to increase other counters for wrong frames)
942 * 1) securityParameters was correctly serialized if we reach here.
943 * 2) securityParameters are already cached.
944 * 3) if msgAuthoritativeEngineID is unknown, zero-length or too long:
945 b) https://tools.ietf.org/html/rfc3414#section-7
946 */
947 {
948 const char *eid;
949 u8_t eid_len;
950  
951 snmpv3_get_engine_id(&eid, &eid_len);
952  
953 if ((request->msg_authoritative_engine_id_len == 0) ||
954 (request->msg_authoritative_engine_id_len != eid_len) ||
955 (memcmp(eid, request->msg_authoritative_engine_id, eid_len) != 0)) {
956 snmp_stats.unknownengineids++;
957 request->msg_flags = 0; /* noauthnopriv */
958 request->error_status = SNMP_ERR_UNKNOWN_ENGINEID;
959 return ERR_OK;
960 }
961 }
962  
963 /* 4) verify username */
964 if (snmpv3_get_user((char *)request->msg_user_name, &auth, NULL, &priv, NULL)) {
965 snmp_stats.unknownusernames++;
966 request->msg_flags = 0; /* noauthnopriv */
967 request->error_status = SNMP_ERR_UNKNOWN_SECURITYNAME;
968 return ERR_OK;
969 }
970  
971 /* 5) verify security level */
972 switch (request->msg_flags & (SNMP_V3_AUTH_FLAG | SNMP_V3_PRIV_FLAG)) {
973 case SNMP_V3_NOAUTHNOPRIV:
974 if ((auth != SNMP_V3_AUTH_ALGO_INVAL) || (priv != SNMP_V3_PRIV_ALGO_INVAL)) {
975 /* Invalid security level for user */
976 snmp_stats.unsupportedseclevels++;
977 request->msg_flags = SNMP_V3_NOAUTHNOPRIV;
978 request->error_status = SNMP_ERR_UNSUPPORTED_SECLEVEL;
979 return ERR_OK;
980 }
981 break;
982 #if LWIP_SNMP_V3_CRYPTO
983 case SNMP_V3_AUTHNOPRIV:
984 if ((auth == SNMP_V3_AUTH_ALGO_INVAL) || (priv != SNMP_V3_PRIV_ALGO_INVAL)) {
985 /* Invalid security level for user */
986 snmp_stats.unsupportedseclevels++;
987 request->msg_flags = SNMP_V3_NOAUTHNOPRIV;
988 request->error_status = SNMP_ERR_UNSUPPORTED_SECLEVEL;
989 return ERR_OK;
990 }
991 break;
992 case SNMP_V3_AUTHPRIV:
993 if ((auth == SNMP_V3_AUTH_ALGO_INVAL) || (priv == SNMP_V3_PRIV_ALGO_INVAL)) {
994 /* Invalid security level for user */
995 snmp_stats.unsupportedseclevels++;
996 request->msg_flags = SNMP_V3_NOAUTHNOPRIV;
997 request->error_status = SNMP_ERR_UNSUPPORTED_SECLEVEL;
998 return ERR_OK;
999 }
1000 break;
1001 #endif
1002 default:
1003 snmp_stats.unsupportedseclevels++;
1004 request->msg_flags = SNMP_V3_NOAUTHNOPRIV;
1005 request->error_status = SNMP_ERR_UNSUPPORTED_SECLEVEL;
1006 return ERR_OK;
1007 }
1008  
1009 /* 6) if securitylevel specifies authentication, authenticate message. */
1010 #if LWIP_SNMP_V3_CRYPTO
1011 if (request->msg_flags & SNMP_V3_AUTH_FLAG) {
1012 const u8_t zero_arr[SNMP_V3_MAX_AUTH_PARAM_LENGTH] = { 0 };
1013 u8_t key[20];
1014 u8_t hmac[LWIP_MAX(SNMP_V3_SHA_LEN, SNMP_V3_MD5_LEN)];
1015 struct snmp_pbuf_stream auth_stream;
1016  
1017 if (request->msg_authentication_parameters_len > SNMP_V3_MAX_AUTH_PARAM_LENGTH) {
1018 snmp_stats.wrongdigests++;
1019 request->msg_flags = SNMP_V3_NOAUTHNOPRIV;
1020 request->error_status = SNMP_ERR_AUTHORIZATIONERROR;
1021 return ERR_OK;
1022 }
1023  
1024 /* Rewind stream */
1025 IF_PARSE_EXEC(snmp_pbuf_stream_init(&auth_stream, request->inbound_pbuf, 0, request->inbound_pbuf->tot_len));
1026 IF_PARSE_EXEC(snmp_pbuf_stream_seek_abs(&auth_stream, inbound_msgAuthenticationParameters_offset));
1027 /* Set auth parameters to zero for verification */
1028 IF_PARSE_EXEC(snmp_asn1_enc_raw(&auth_stream, zero_arr, request->msg_authentication_parameters_len));
1029  
1030 /* Verify authentication */
1031 IF_PARSE_EXEC(snmp_pbuf_stream_init(&auth_stream, request->inbound_pbuf, 0, request->inbound_pbuf->tot_len));
1032  
1033 IF_PARSE_EXEC(snmpv3_get_user((char *)request->msg_user_name, &auth, key, NULL, NULL));
1034 IF_PARSE_EXEC(snmpv3_auth(&auth_stream, request->inbound_pbuf->tot_len, key, auth, hmac));
1035  
1036 if (memcmp(request->msg_authentication_parameters, hmac, SNMP_V3_MAX_AUTH_PARAM_LENGTH)) {
1037 snmp_stats.wrongdigests++;
1038 request->msg_flags = SNMP_V3_NOAUTHNOPRIV;
1039 request->error_status = SNMP_ERR_AUTHORIZATIONERROR;
1040 return ERR_OK;
1041 }
1042  
1043 /* 7) if securitylevel specifies authentication, verify engineboots, enginetime and lastenginetime */
1044 {
1045 s32_t boots = snmpv3_get_engine_boots_internal();
1046 if ((request->msg_authoritative_engine_boots != boots) || (boots == 2147483647UL)) {
1047 snmp_stats.notintimewindows++;
1048 request->msg_flags = SNMP_V3_AUTHNOPRIV;
1049 request->error_status = SNMP_ERR_NOTINTIMEWINDOW;
1050 return ERR_OK;
1051 }
1052 }
1053 {
1054 s32_t time = snmpv3_get_engine_time_internal();
1055 if (request->msg_authoritative_engine_time > time) {
1056 snmp_stats.notintimewindows++;
1057 request->msg_flags = SNMP_V3_AUTHNOPRIV;
1058 request->error_status = SNMP_ERR_NOTINTIMEWINDOW;
1059 return ERR_OK;
1060 } else if (time > 150) {
1061 if (request->msg_authoritative_engine_time < time - 150) {
1062 snmp_stats.notintimewindows++;
1063 request->msg_flags = SNMP_V3_AUTHNOPRIV;
1064 request->error_status = SNMP_ERR_NOTINTIMEWINDOW;
1065 return ERR_OK;
1066 }
1067 }
1068 }
1069 }
1070 #endif
1071  
1072 /* 8) if securitylevel specifies privacy, decrypt message. */
1073 #if LWIP_SNMP_V3_CRYPTO
1074 if (request->msg_flags & SNMP_V3_PRIV_FLAG) {
1075 /* Decrypt message */
1076  
1077 u8_t key[20];
1078  
1079 IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv));
1080 IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_OCTET_STRING);
1081 parent_tlv_value_len -= SNMP_ASN1_TLV_HDR_LENGTH(tlv);
1082 IF_PARSE_ASSERT(parent_tlv_value_len > 0);
1083  
1084 IF_PARSE_EXEC(snmpv3_get_user((char *)request->msg_user_name, NULL, NULL, &priv, key));
1085 if (snmpv3_crypt(&pbuf_stream, tlv.value_len, key,
1086 request->msg_privacy_parameters, request->msg_authoritative_engine_boots,
1087 request->msg_authoritative_engine_time, priv, SNMP_V3_PRIV_MODE_DECRYPT) != ERR_OK) {
1088 snmp_stats.decryptionerrors++;
1089 request->msg_flags = SNMP_V3_AUTHNOPRIV;
1090 request->error_status = SNMP_ERR_DECRYIPTION_ERROR;
1091 return ERR_OK;
1092 }
1093 }
1094 #endif
1095 /* 9) calculate max size of scoped pdu?
1096 * 10) securityname for user is retrieved from usertable?
1097 * 11) security data is cached?
1098 * 12)
1099 */
1100  
1101 /* Scoped PDU
1102 * Encryption context
1103 */
1104 IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv));
1105 IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_SEQUENCE);
1106 parent_tlv_value_len -= SNMP_ASN1_TLV_HDR_LENGTH(tlv);
1107 IF_PARSE_ASSERT(parent_tlv_value_len > 0);
1108  
1109 /* contextEngineID */
1110 IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv));
1111 IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_OCTET_STRING);
1112 parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv);
1113 IF_PARSE_ASSERT(parent_tlv_value_len > 0);
1114  
1115 IF_PARSE_EXEC(snmp_asn1_dec_raw(&pbuf_stream, tlv.value_len, request->context_engine_id,
1116 &u16_value, SNMP_V3_MAX_ENGINE_ID_LENGTH));
1117 request->context_engine_id_len = (u8_t)u16_value;
1118 /* TODO: do we need to verify this contextengineid too? */
1119  
1120 /* contextName */
1121 IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv));
1122 IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_OCTET_STRING);
1123 parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv);
1124 IF_PARSE_ASSERT(parent_tlv_value_len > 0);
1125  
1126 IF_PARSE_EXEC(snmp_asn1_dec_raw(&pbuf_stream, tlv.value_len, request->context_name,
1127 &u16_value, SNMP_V3_MAX_ENGINE_ID_LENGTH));
1128 request->context_name_len = (u8_t)u16_value;
1129 /* TODO: do we need to verify this contextname too? */
1130 } else
1131 #endif
1132 {
1133 /* decode community */
1134 IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv));
1135 IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_OCTET_STRING);
1136 parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv);
1137 IF_PARSE_ASSERT(parent_tlv_value_len > 0);
1138  
1139 err = snmp_asn1_dec_raw(&pbuf_stream, tlv.value_len, request->community, &request->community_strlen, SNMP_MAX_COMMUNITY_STR_LEN);
1140 if (err == ERR_MEM) {
1141 /* community string does not fit in our buffer -> its too long -> its invalid */
1142 request->community_strlen = 0;
1143 snmp_pbuf_stream_seek(&pbuf_stream, tlv.value_len);
1144 } else {
1145 IF_PARSE_ASSERT(err == ERR_OK);
1146 }
1147 /* add zero terminator */
1148 request->community[request->community_strlen] = 0;
1149 }
1150  
1151 /* decode PDU type (next container level) */
1152 IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv));
1153 IF_PARSE_ASSERT(tlv.value_len <= pbuf_stream.length);
1154 request->inbound_padding_len = pbuf_stream.length - tlv.value_len;
1155 parent_tlv_value_len = tlv.value_len;
1156  
1157 /* validate PDU type */
1158 switch (tlv.type) {
1159 case (SNMP_ASN1_CLASS_CONTEXT | SNMP_ASN1_CONTENTTYPE_CONSTRUCTED | SNMP_ASN1_CONTEXT_PDU_GET_REQ):
1160 /* GetRequest PDU */
1161 snmp_stats.ingetrequests++;
1162 break;
1163 case (SNMP_ASN1_CLASS_CONTEXT | SNMP_ASN1_CONTENTTYPE_CONSTRUCTED | SNMP_ASN1_CONTEXT_PDU_GET_NEXT_REQ):
1164 /* GetNextRequest PDU */
1165 snmp_stats.ingetnexts++;
1166 break;
1167 case (SNMP_ASN1_CLASS_CONTEXT | SNMP_ASN1_CONTENTTYPE_CONSTRUCTED | SNMP_ASN1_CONTEXT_PDU_GET_BULK_REQ):
1168 /* GetBulkRequest PDU */
1169 if (request->version < SNMP_VERSION_2c) {
1170 /* RFC2089: invalid, drop packet */
1171 return ERR_ARG;
1172 }
1173 break;
1174 case (SNMP_ASN1_CLASS_CONTEXT | SNMP_ASN1_CONTENTTYPE_CONSTRUCTED | SNMP_ASN1_CONTEXT_PDU_SET_REQ):
1175 /* SetRequest PDU */
1176 snmp_stats.insetrequests++;
1177 break;
1178 default:
1179 /* unsupported input PDU for this agent (no parse error) */
1180 LWIP_DEBUGF(SNMP_DEBUG, ("Unknown/Invalid SNMP PDU type received: %d", tlv.type)); \
1181 return ERR_ARG;
1182 }
1183 request->request_type = tlv.type & SNMP_ASN1_DATATYPE_MASK;
1184 request->request_out_type = (SNMP_ASN1_CLASS_CONTEXT | SNMP_ASN1_CONTENTTYPE_CONSTRUCTED | SNMP_ASN1_CONTEXT_PDU_GET_RESP);
1185  
1186 /* validate community (do this after decoding PDU type because we don't want to increase 'inbadcommunitynames' for wrong frame types */
1187 if (request->community_strlen == 0) {
1188 /* community string was too long or really empty*/
1189 snmp_stats.inbadcommunitynames++;
1190 snmp_authfail_trap();
1191 return ERR_ARG;
1192 } else if (request->request_type == SNMP_ASN1_CONTEXT_PDU_SET_REQ) {
1193 if (snmp_community_write[0] == 0) {
1194 /* our write community is empty, that means all our objects are readonly */
1195 request->error_status = SNMP_ERR_NOTWRITABLE;
1196 request->error_index = 1;
1197 } else if (strncmp(snmp_community_write, (const char *)request->community, SNMP_MAX_COMMUNITY_STR_LEN) != 0) {
1198 /* community name does not match */
1199 snmp_stats.inbadcommunitynames++;
1200 snmp_authfail_trap();
1201 return ERR_ARG;
1202 }
1203 } else {
1204 if (strncmp(snmp_community, (const char *)request->community, SNMP_MAX_COMMUNITY_STR_LEN) != 0) {
1205 /* community name does not match */
1206 snmp_stats.inbadcommunitynames++;
1207 snmp_authfail_trap();
1208 return ERR_ARG;
1209 }
1210 }
1211  
1212 /* decode request ID */
1213 IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv));
1214 IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_INTEGER);
1215 parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv);
1216 IF_PARSE_ASSERT(parent_tlv_value_len > 0);
1217  
1218 IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &request->request_id));
1219  
1220 /* decode error status / non-repeaters */
1221 IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv));
1222 IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_INTEGER);
1223 parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv);
1224 IF_PARSE_ASSERT(parent_tlv_value_len > 0);
1225  
1226 if (request->request_type == SNMP_ASN1_CONTEXT_PDU_GET_BULK_REQ) {
1227 IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &request->non_repeaters));
1228 if (request->non_repeaters < 0) {
1229 /* RFC 1905, 4.2.3 */
1230 request->non_repeaters = 0;
1231 }
1232 } else {
1233 /* only check valid value, don't touch 'request->error_status', maybe a response error status was already set to above; */
1234 IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &s32_value));
1235 IF_PARSE_ASSERT(s32_value == SNMP_ERR_NOERROR);
1236 }
1237  
1238 /* decode error index / max-repetitions */
1239 IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv));
1240 IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_INTEGER);
1241 parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv);
1242 IF_PARSE_ASSERT(parent_tlv_value_len > 0);
1243  
1244 if (request->request_type == SNMP_ASN1_CONTEXT_PDU_GET_BULK_REQ) {
1245 IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &request->max_repetitions));
1246 if (request->max_repetitions < 0) {
1247 /* RFC 1905, 4.2.3 */
1248 request->max_repetitions = 0;
1249 }
1250 } else {
1251 IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &request->error_index));
1252 IF_PARSE_ASSERT(s32_value == 0);
1253 }
1254  
1255 /* decode varbind-list type (next container level) */
1256 IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv));
1257 IF_PARSE_ASSERT((tlv.type == SNMP_ASN1_TYPE_SEQUENCE) && (tlv.value_len <= pbuf_stream.length));
1258  
1259 request->inbound_varbind_offset = pbuf_stream.offset;
1260 request->inbound_varbind_len = pbuf_stream.length - request->inbound_padding_len;
1261 snmp_vb_enumerator_init(&(request->inbound_varbind_enumerator), request->inbound_pbuf, request->inbound_varbind_offset, request->inbound_varbind_len);
1262  
1263 return ERR_OK;
1264 }
1265  
1266 #define OF_BUILD_EXEC(code) BUILD_EXEC(code, ERR_ARG)
1267  
1268 static err_t
1269 snmp_prepare_outbound_frame(struct snmp_request *request)
1270 {
1271 struct snmp_asn1_tlv tlv;
1272 struct snmp_pbuf_stream *pbuf_stream = &(request->outbound_pbuf_stream);
1273  
1274 /* try allocating pbuf(s) for maximum response size */
1275 request->outbound_pbuf = pbuf_alloc(PBUF_TRANSPORT, 1472, PBUF_RAM);
1276 if (request->outbound_pbuf == NULL) {
1277 return ERR_MEM;
1278 }
1279  
1280 snmp_pbuf_stream_init(pbuf_stream, request->outbound_pbuf, 0, request->outbound_pbuf->tot_len);
1281  
1282 /* 'Message' sequence */
1283 SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 3, 0);
1284 OF_BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) );
1285  
1286 /* version */
1287 SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 0);
1288 snmp_asn1_enc_s32t_cnt(request->version, &tlv.value_len);
1289 OF_BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) );
1290 OF_BUILD_EXEC( snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, request->version) );
1291  
1292 #if LWIP_SNMP_V3
1293 if (request->version < SNMP_VERSION_3) {
1294 #endif
1295 /* community */
1296 SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 0, request->community_strlen);
1297 OF_BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) );
1298 OF_BUILD_EXEC( snmp_asn1_enc_raw(pbuf_stream, request->community, request->community_strlen) );
1299 #if LWIP_SNMP_V3
1300 } else {
1301 const char *id;
1302  
1303 /* globalData */
1304 request->outbound_msg_global_data_offset = pbuf_stream->offset;
1305 SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 1, 0);
1306 OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv));
1307  
1308 /* msgID */
1309 SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 1);
1310 snmp_asn1_enc_s32t_cnt(request->msg_id, &tlv.value_len);
1311 OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv));
1312 OF_BUILD_EXEC(snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, request->msg_id));
1313  
1314 /* msgMaxSize */
1315 SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 1);
1316 snmp_asn1_enc_s32t_cnt(request->msg_max_size, &tlv.value_len);
1317 OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv));
1318 OF_BUILD_EXEC(snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, request->msg_max_size));
1319  
1320 /* msgFlags */
1321 SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 0, 1);
1322 OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv));
1323 OF_BUILD_EXEC(snmp_asn1_enc_raw(pbuf_stream, &request->msg_flags, 1));
1324  
1325 /* msgSecurityModel */
1326 SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 1);
1327 snmp_asn1_enc_s32t_cnt(request->msg_security_model, &tlv.value_len);
1328 OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv));
1329 OF_BUILD_EXEC(snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, request->msg_security_model));
1330  
1331 /* end of msgGlobalData */
1332 request->outbound_msg_global_data_end = pbuf_stream->offset;
1333  
1334 /* msgSecurityParameters */
1335 request->outbound_msg_security_parameters_str_offset = pbuf_stream->offset;
1336 SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 1, 0);
1337 OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv));
1338  
1339 request->outbound_msg_security_parameters_seq_offset = pbuf_stream->offset;
1340 SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 1, 0);
1341 OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv));
1342  
1343 /* msgAuthoritativeEngineID */
1344 snmpv3_get_engine_id(&id, &request->msg_authoritative_engine_id_len);
1345 MEMCPY(request->msg_authoritative_engine_id, id, request->msg_authoritative_engine_id_len);
1346 SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 0, request->msg_authoritative_engine_id_len);
1347 OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv));
1348 OF_BUILD_EXEC(snmp_asn1_enc_raw(pbuf_stream, request->msg_authoritative_engine_id, request->msg_authoritative_engine_id_len));
1349  
1350 request->msg_authoritative_engine_time = snmpv3_get_engine_time();
1351 request->msg_authoritative_engine_boots = snmpv3_get_engine_boots();
1352  
1353 /* msgAuthoritativeEngineBoots */
1354 SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 0);
1355 snmp_asn1_enc_s32t_cnt(request->msg_authoritative_engine_boots, &tlv.value_len);
1356 OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv));
1357 OF_BUILD_EXEC(snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, request->msg_authoritative_engine_boots));
1358  
1359 /* msgAuthoritativeEngineTime */
1360 SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 0);
1361 snmp_asn1_enc_s32t_cnt(request->msg_authoritative_engine_time, &tlv.value_len);
1362 OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv));
1363 OF_BUILD_EXEC(snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, request->msg_authoritative_engine_time));
1364  
1365 /* msgUserName */
1366 SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 0, request->msg_user_name_len);
1367 OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv));
1368 OF_BUILD_EXEC(snmp_asn1_enc_raw(pbuf_stream, request->msg_user_name, request->msg_user_name_len));
1369  
1370 #if LWIP_SNMP_V3_CRYPTO
1371 /* msgAuthenticationParameters */
1372 if (request->msg_flags & SNMP_V3_AUTH_FLAG) {
1373 memset(request->msg_authentication_parameters, 0, SNMP_V3_MAX_AUTH_PARAM_LENGTH);
1374 request->outbound_msg_authentication_parameters_offset = pbuf_stream->offset;
1375 SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 1, SNMP_V3_MAX_AUTH_PARAM_LENGTH);
1376 OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv));
1377 OF_BUILD_EXEC(snmp_asn1_enc_raw(pbuf_stream, request->msg_authentication_parameters, SNMP_V3_MAX_AUTH_PARAM_LENGTH));
1378 } else
1379 #endif
1380 {
1381 SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 0, 0);
1382 OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv));
1383 }
1384  
1385 #if LWIP_SNMP_V3_CRYPTO
1386 /* msgPrivacyParameters */
1387 if (request->msg_flags & SNMP_V3_PRIV_FLAG) {
1388 snmpv3_build_priv_param(request->msg_privacy_parameters);
1389  
1390 SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 0, SNMP_V3_MAX_PRIV_PARAM_LENGTH);
1391 OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv));
1392 OF_BUILD_EXEC(snmp_asn1_enc_raw(pbuf_stream, request->msg_privacy_parameters, SNMP_V3_MAX_PRIV_PARAM_LENGTH));
1393 } else
1394 #endif
1395 {
1396 SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 0, 0);
1397 OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv) );
1398 }
1399  
1400 /* End of msgSecurityParameters, so we can calculate the length of this sequence later */
1401 request->outbound_msg_security_parameters_end = pbuf_stream->offset;
1402  
1403 #if LWIP_SNMP_V3_CRYPTO
1404 /* For encryption we have to encapsulate the payload in an octet string */
1405 if (request->msg_flags & SNMP_V3_PRIV_FLAG) {
1406 request->outbound_scoped_pdu_string_offset = pbuf_stream->offset;
1407 SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 3, 0);
1408 OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv));
1409 }
1410 #endif
1411 /* Scoped PDU
1412 * Encryption context
1413 */
1414 request->outbound_scoped_pdu_seq_offset = pbuf_stream->offset;
1415 SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 3, 0);
1416 OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv));
1417  
1418 /* contextEngineID */
1419 snmpv3_get_engine_id(&id, &request->context_engine_id_len);
1420 MEMCPY(request->context_engine_id, id, request->context_engine_id_len);
1421 SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 0, request->context_engine_id_len);
1422 OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv));
1423 OF_BUILD_EXEC(snmp_asn1_enc_raw(pbuf_stream, request->context_engine_id, request->context_engine_id_len));
1424  
1425 /* contextName */
1426 SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 0, request->context_name_len);
1427 OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv));
1428 OF_BUILD_EXEC(snmp_asn1_enc_raw(pbuf_stream, request->context_name, request->context_name_len));
1429 }
1430 #endif
1431  
1432 /* 'PDU' sequence */
1433 request->outbound_pdu_offset = pbuf_stream->offset;
1434 SNMP_ASN1_SET_TLV_PARAMS(tlv, request->request_out_type, 3, 0);
1435 OF_BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) );
1436  
1437 /* request ID */
1438 SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 0);
1439 snmp_asn1_enc_s32t_cnt(request->request_id, &tlv.value_len);
1440 OF_BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) );
1441 OF_BUILD_EXEC( snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, request->request_id) );
1442  
1443 /* error status */
1444 SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 1);
1445 OF_BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) );
1446 request->outbound_error_status_offset = pbuf_stream->offset;
1447 OF_BUILD_EXEC( snmp_pbuf_stream_write(pbuf_stream, 0) );
1448  
1449 /* error index */
1450 SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 1);
1451 OF_BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) );
1452 request->outbound_error_index_offset = pbuf_stream->offset;
1453 OF_BUILD_EXEC( snmp_pbuf_stream_write(pbuf_stream, 0) );
1454  
1455 /* 'VarBindList' sequence */
1456 SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 3, 0);
1457 OF_BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) );
1458  
1459 request->outbound_varbind_offset = pbuf_stream->offset;
1460  
1461 return ERR_OK;
1462 }
1463  
1464 /** Calculate the length of a varbind list */
1465 err_t
1466 snmp_varbind_length(struct snmp_varbind *varbind, struct snmp_varbind_len *len)
1467 {
1468 /* calculate required lengths */
1469 snmp_asn1_enc_oid_cnt(varbind->oid.id, varbind->oid.len, &len->oid_value_len);
1470 snmp_asn1_enc_length_cnt(len->oid_value_len, &len->oid_len_len);
1471  
1472 if (varbind->value_len == 0) {
1473 len->value_value_len = 0;
1474 } else if (varbind->value_len & SNMP_GET_VALUE_RAW_DATA) {
1475 len->value_value_len = varbind->value_len & (~SNMP_GET_VALUE_RAW_DATA);
1476 } else {
1477 switch (varbind->type) {
1478 case SNMP_ASN1_TYPE_INTEGER:
1479 if (varbind->value_len != sizeof (s32_t)) {
1480 return ERR_VAL;
1481 }
1482 snmp_asn1_enc_s32t_cnt(*((s32_t *) varbind->value), &len->value_value_len);
1483 break;
1484 case SNMP_ASN1_TYPE_COUNTER:
1485 case SNMP_ASN1_TYPE_GAUGE:
1486 case SNMP_ASN1_TYPE_TIMETICKS:
1487 if (varbind->value_len != sizeof (u32_t)) {
1488 return ERR_VAL;
1489 }
1490 snmp_asn1_enc_u32t_cnt(*((u32_t *) varbind->value), &len->value_value_len);
1491 break;
1492 case SNMP_ASN1_TYPE_OCTET_STRING:
1493 case SNMP_ASN1_TYPE_IPADDR:
1494 case SNMP_ASN1_TYPE_OPAQUE:
1495 len->value_value_len = varbind->value_len;
1496 break;
1497 case SNMP_ASN1_TYPE_NULL:
1498 if (varbind->value_len != 0) {
1499 return ERR_VAL;
1500 }
1501 len->value_value_len = 0;
1502 break;
1503 case SNMP_ASN1_TYPE_OBJECT_ID:
1504 if ((varbind->value_len & 0x03) != 0) {
1505 return ERR_VAL;
1506 }
1507 snmp_asn1_enc_oid_cnt((u32_t *) varbind->value, varbind->value_len >> 2, &len->value_value_len);
1508 break;
1509 #if LWIP_HAVE_INT64
1510 case SNMP_ASN1_TYPE_COUNTER64:
1511 if (varbind->value_len != sizeof(u64_t)) {
1512 return ERR_VAL;
1513 }
1514 snmp_asn1_enc_u64t_cnt(*(u64_t *)varbind->value, &len->value_value_len);
1515 break;
1516 #endif
1517 default:
1518 /* unsupported type */
1519 return ERR_VAL;
1520 }
1521 }
1522 snmp_asn1_enc_length_cnt(len->value_value_len, &len->value_len_len);
1523  
1524 len->vb_value_len = 1 + len->oid_len_len + len->oid_value_len + 1 + len->value_len_len + len->value_value_len;
1525 snmp_asn1_enc_length_cnt(len->vb_value_len, &len->vb_len_len);
1526  
1527 return ERR_OK;
1528 }
1529  
1530 #define OVB_BUILD_EXEC(code) BUILD_EXEC(code, ERR_ARG)
1531  
1532 err_t
1533 snmp_append_outbound_varbind(struct snmp_pbuf_stream *pbuf_stream, struct snmp_varbind *varbind)
1534 {
1535 struct snmp_asn1_tlv tlv;
1536 struct snmp_varbind_len len;
1537 err_t err;
1538  
1539 err = snmp_varbind_length(varbind, &len);
1540  
1541 if (err != ERR_OK) {
1542 return err;
1543 }
1544  
1545 /* check length already before adding first data because in case of GetBulk,
1546 * data added so far is returned and therefore no partial data shall be added
1547 */
1548 if ((1 + len.vb_len_len + len.vb_value_len) > pbuf_stream->length) {
1549 return ERR_BUF;
1550 }
1551  
1552 /* 'VarBind' sequence */
1553 SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, len.vb_len_len, len.vb_value_len);
1554 OVB_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv));
1555  
1556 /* VarBind OID */
1557 SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OBJECT_ID, len.oid_len_len, len.oid_value_len);
1558 OVB_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv));
1559 OVB_BUILD_EXEC(snmp_asn1_enc_oid(pbuf_stream, varbind->oid.id, varbind->oid.len));
1560  
1561 /* VarBind value */
1562 SNMP_ASN1_SET_TLV_PARAMS(tlv, varbind->type, len.value_len_len, len.value_value_len);
1563 OVB_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv));
1564  
1565 if (len.value_value_len > 0) {
1566 if (varbind->value_len & SNMP_GET_VALUE_RAW_DATA) {
1567 OVB_BUILD_EXEC(snmp_asn1_enc_raw(pbuf_stream, (u8_t *) varbind->value, len.value_value_len));
1568 } else {
1569 switch (varbind->type) {
1570 case SNMP_ASN1_TYPE_INTEGER:
1571 OVB_BUILD_EXEC(snmp_asn1_enc_s32t(pbuf_stream, len.value_value_len, *((s32_t *) varbind->value)));
1572 break;
1573 case SNMP_ASN1_TYPE_COUNTER:
1574 case SNMP_ASN1_TYPE_GAUGE:
1575 case SNMP_ASN1_TYPE_TIMETICKS:
1576 OVB_BUILD_EXEC(snmp_asn1_enc_u32t(pbuf_stream, len.value_value_len, *((u32_t *) varbind->value)));
1577 break;
1578 case SNMP_ASN1_TYPE_OCTET_STRING:
1579 case SNMP_ASN1_TYPE_IPADDR:
1580 case SNMP_ASN1_TYPE_OPAQUE:
1581 OVB_BUILD_EXEC(snmp_asn1_enc_raw(pbuf_stream, (u8_t *) varbind->value, len.value_value_len));
1582 len.value_value_len = varbind->value_len;
1583 break;
1584 case SNMP_ASN1_TYPE_OBJECT_ID:
1585 OVB_BUILD_EXEC(snmp_asn1_enc_oid(pbuf_stream, (u32_t *) varbind->value, varbind->value_len / sizeof (u32_t)));
1586 break;
1587 #if LWIP_HAVE_INT64
1588 case SNMP_ASN1_TYPE_COUNTER64:
1589 OVB_BUILD_EXEC(snmp_asn1_enc_u64t(pbuf_stream, len.value_value_len, *(u64_t *) varbind->value));
1590 break;
1591 #endif
1592 default:
1593 LWIP_ASSERT("Unknown variable type", 0);
1594 break;
1595 }
1596 }
1597 }
1598  
1599 return ERR_OK;
1600 }
1601  
1602 static err_t
1603 snmp_complete_outbound_frame(struct snmp_request *request)
1604 {
1605 struct snmp_asn1_tlv tlv;
1606 u16_t frame_size;
1607 u8_t outbound_padding = 0;
1608  
1609 if (request->version == SNMP_VERSION_1) {
1610 if (request->error_status != SNMP_ERR_NOERROR) {
1611 /* map v2c error codes to v1 compliant error code (according to RFC 2089) */
1612 switch (request->error_status) {
1613 /* mapping of implementation specific "virtual" error codes
1614 * (during processing of frame we already stored them in error_status field,
1615 * so no need to check all varbinds here for those exceptions as suggested by RFC) */
1616 case SNMP_ERR_NOSUCHINSTANCE:
1617 case SNMP_ERR_NOSUCHOBJECT:
1618 case SNMP_ERR_ENDOFMIBVIEW:
1619 request->error_status = SNMP_ERR_NOSUCHNAME;
1620 break;
1621 /* mapping according to RFC */
1622 case SNMP_ERR_WRONGVALUE:
1623 case SNMP_ERR_WRONGENCODING:
1624 case SNMP_ERR_WRONGTYPE:
1625 case SNMP_ERR_WRONGLENGTH:
1626 case SNMP_ERR_INCONSISTENTVALUE:
1627 request->error_status = SNMP_ERR_BADVALUE;
1628 break;
1629 case SNMP_ERR_NOACCESS:
1630 case SNMP_ERR_NOTWRITABLE:
1631 case SNMP_ERR_NOCREATION:
1632 case SNMP_ERR_INCONSISTENTNAME:
1633 case SNMP_ERR_AUTHORIZATIONERROR:
1634 request->error_status = SNMP_ERR_NOSUCHNAME;
1635 break;
1636 case SNMP_ERR_RESOURCEUNAVAILABLE:
1637 case SNMP_ERR_COMMITFAILED:
1638 case SNMP_ERR_UNDOFAILED:
1639 default:
1640 request->error_status = SNMP_ERR_GENERROR;
1641 break;
1642 }
1643 }
1644 } else {
1645 if (request->request_type == SNMP_ASN1_CONTEXT_PDU_SET_REQ) {
1646 /* map error codes to according to RFC 1905 (4.2.5. The SetRequest-PDU) return 'NotWritable' for unknown OIDs) */
1647 switch (request->error_status) {
1648 case SNMP_ERR_NOSUCHINSTANCE:
1649 case SNMP_ERR_NOSUCHOBJECT:
1650 case SNMP_ERR_ENDOFMIBVIEW:
1651 request->error_status = SNMP_ERR_NOTWRITABLE;
1652 break;
1653 default:
1654 break;
1655 }
1656 }
1657  
1658 if (request->error_status >= SNMP_VARBIND_EXCEPTION_OFFSET) {
1659 /* should never occur because v2 frames store exceptions directly inside varbinds and not as frame error_status */
1660 LWIP_DEBUGF(SNMP_DEBUG, ("snmp_complete_outbound_frame() > Found v2 request with varbind exception code stored as error status!\n"));
1661 return ERR_ARG;
1662 }
1663 }
1664  
1665 if ((request->error_status != SNMP_ERR_NOERROR) || (request->request_type == SNMP_ASN1_CONTEXT_PDU_SET_REQ)) {
1666 /* all inbound vars are returned in response without any modification for error responses and successful set requests*/
1667 struct snmp_pbuf_stream inbound_stream;
1668 OF_BUILD_EXEC( snmp_pbuf_stream_init(&inbound_stream, request->inbound_pbuf, request->inbound_varbind_offset, request->inbound_varbind_len) );
1669 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) );
1670 OF_BUILD_EXEC( snmp_pbuf_stream_writeto(&inbound_stream, &(request->outbound_pbuf_stream), 0) );
1671 }
1672  
1673 frame_size = request->outbound_pbuf_stream.offset;
1674  
1675 #if LWIP_SNMP_V3 && LWIP_SNMP_V3_CRYPTO
1676 /* Calculate padding for encryption */
1677 if (request->version == SNMP_VERSION_3 && (request->msg_flags & SNMP_V3_PRIV_FLAG)) {
1678 u8_t i;
1679 outbound_padding = (8 - (u8_t)((frame_size - request->outbound_scoped_pdu_seq_offset) & 0x07)) & 0x07;
1680 for (i = 0; i < outbound_padding; i++) {
1681 OF_BUILD_EXEC( snmp_pbuf_stream_write(&request->outbound_pbuf_stream, 0) );
1682 }
1683 }
1684 #endif
1685  
1686 /* complete missing length in 'Message' sequence ; 'Message' tlv is located at the beginning (offset 0) */
1687 SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 3, frame_size + outbound_padding - 1 - 3); /* - type - length_len(fixed, see snmp_prepare_outbound_frame()) */
1688 OF_BUILD_EXEC( snmp_pbuf_stream_init(&(request->outbound_pbuf_stream), request->outbound_pbuf, 0, request->outbound_pbuf->tot_len) );
1689 OF_BUILD_EXEC( snmp_ans1_enc_tlv(&(request->outbound_pbuf_stream), &tlv) );
1690  
1691 #if LWIP_SNMP_V3
1692 if (request->version == SNMP_VERSION_3) {
1693 /* complete missing length in 'globalData' sequence */
1694 /* - type - length_len(fixed, see snmp_prepare_outbound_frame()) */
1695 SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 1, request->outbound_msg_global_data_end
1696 - request->outbound_msg_global_data_offset - 1 - 1);
1697 OF_BUILD_EXEC(snmp_pbuf_stream_seek_abs(&(request->outbound_pbuf_stream), request->outbound_msg_global_data_offset));
1698 OF_BUILD_EXEC(snmp_ans1_enc_tlv(&(request->outbound_pbuf_stream), &tlv));
1699  
1700 /* complete missing length in 'msgSecurityParameters' sequence */
1701 SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 1, request->outbound_msg_security_parameters_end
1702 - request->outbound_msg_security_parameters_str_offset - 1 - 1);
1703 OF_BUILD_EXEC(snmp_pbuf_stream_seek_abs(&(request->outbound_pbuf_stream), request->outbound_msg_security_parameters_str_offset));
1704 OF_BUILD_EXEC(snmp_ans1_enc_tlv(&(request->outbound_pbuf_stream), &tlv));
1705  
1706 SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 1, request->outbound_msg_security_parameters_end
1707 - request->outbound_msg_security_parameters_seq_offset - 1 - 1);
1708 OF_BUILD_EXEC(snmp_pbuf_stream_seek_abs(&(request->outbound_pbuf_stream), request->outbound_msg_security_parameters_seq_offset));
1709 OF_BUILD_EXEC(snmp_ans1_enc_tlv(&(request->outbound_pbuf_stream), &tlv));
1710  
1711 /* complete missing length in scoped PDU sequence */
1712 SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 3, frame_size - request->outbound_scoped_pdu_seq_offset - 1 - 3);
1713 OF_BUILD_EXEC(snmp_pbuf_stream_seek_abs(&(request->outbound_pbuf_stream), request->outbound_scoped_pdu_seq_offset));
1714 OF_BUILD_EXEC(snmp_ans1_enc_tlv(&(request->outbound_pbuf_stream), &tlv));
1715 }
1716 #endif
1717  
1718 /* complete missing length in 'PDU' sequence */
1719 SNMP_ASN1_SET_TLV_PARAMS(tlv, request->request_out_type, 3,
1720 frame_size - request->outbound_pdu_offset - 1 - 3); /* - type - length_len(fixed, see snmp_prepare_outbound_frame()) */
1721 OF_BUILD_EXEC( snmp_pbuf_stream_seek_abs(&(request->outbound_pbuf_stream), request->outbound_pdu_offset) );
1722 OF_BUILD_EXEC( snmp_ans1_enc_tlv(&(request->outbound_pbuf_stream), &tlv) );
1723  
1724 /* process and encode final error status */
1725 if (request->error_status != 0) {
1726 u16_t len;
1727 snmp_asn1_enc_s32t_cnt(request->error_status, &len);
1728 if (len != 1) {
1729 /* error, we only reserved one byte for it */
1730 return ERR_ARG;
1731 }
1732 OF_BUILD_EXEC( snmp_pbuf_stream_seek_abs(&(request->outbound_pbuf_stream), request->outbound_error_status_offset) );
1733 OF_BUILD_EXEC( snmp_asn1_enc_s32t(&(request->outbound_pbuf_stream), len, request->error_status) );
1734  
1735 /* for compatibility to v1, log statistics; in v2 (RFC 1907) these statistics are obsoleted */
1736 switch (request->error_status) {
1737 case SNMP_ERR_TOOBIG:
1738 snmp_stats.outtoobigs++;
1739 break;
1740 case SNMP_ERR_NOSUCHNAME:
1741 snmp_stats.outnosuchnames++;
1742 break;
1743 case SNMP_ERR_BADVALUE:
1744 snmp_stats.outbadvalues++;
1745 break;
1746 case SNMP_ERR_GENERROR:
1747 default:
1748 snmp_stats.outgenerrs++;
1749 break;
1750 }
1751  
1752 if (request->error_status == SNMP_ERR_TOOBIG) {
1753 request->error_index = 0; /* defined by RFC 1157 */
1754 } else if (request->error_index == 0) {
1755 /* set index to varbind where error occured (if not already set before, e.g. during GetBulk processing) */
1756 request->error_index = request->inbound_varbind_enumerator.varbind_count;
1757 }
1758 } else {
1759 if (request->request_type == SNMP_ASN1_CONTEXT_PDU_SET_REQ) {
1760 snmp_stats.intotalsetvars += request->inbound_varbind_enumerator.varbind_count;
1761 } else {
1762 snmp_stats.intotalreqvars += request->inbound_varbind_enumerator.varbind_count;
1763 }
1764 }
1765  
1766 /* encode final error index*/
1767 if (request->error_index != 0) {
1768 u16_t len;
1769 snmp_asn1_enc_s32t_cnt(request->error_index, &len);
1770 if (len != 1) {
1771 /* error, we only reserved one byte for it */
1772 return ERR_VAL;
1773 }
1774 OF_BUILD_EXEC( snmp_pbuf_stream_seek_abs(&(request->outbound_pbuf_stream), request->outbound_error_index_offset) );
1775 OF_BUILD_EXEC( snmp_asn1_enc_s32t(&(request->outbound_pbuf_stream), len, request->error_index) );
1776 }
1777  
1778 /* complete missing length in 'VarBindList' sequence ; 'VarBindList' tlv is located directly before varbind offset */
1779 SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 3, frame_size - request->outbound_varbind_offset);
1780 OF_BUILD_EXEC( snmp_pbuf_stream_seek_abs(&(request->outbound_pbuf_stream), request->outbound_varbind_offset - 1 - 3) ); /* - type - length_len(fixed, see snmp_prepare_outbound_frame()) */
1781 OF_BUILD_EXEC( snmp_ans1_enc_tlv(&(request->outbound_pbuf_stream), &tlv) );
1782  
1783 /* Authenticate response */
1784 #if LWIP_SNMP_V3 && LWIP_SNMP_V3_CRYPTO
1785 /* Encrypt response */
1786 if (request->version == SNMP_VERSION_3 && (request->msg_flags & SNMP_V3_PRIV_FLAG)) {
1787 u8_t key[20];
1788 snmpv3_priv_algo_t algo;
1789  
1790 /* complete missing length in PDU sequence */
1791 OF_BUILD_EXEC(snmp_pbuf_stream_init(&request->outbound_pbuf_stream, request->outbound_pbuf, 0, request->outbound_pbuf->tot_len));
1792 OF_BUILD_EXEC(snmp_pbuf_stream_seek_abs(&(request->outbound_pbuf_stream), request->outbound_scoped_pdu_string_offset));
1793 SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 3, frame_size + outbound_padding
1794 - request->outbound_scoped_pdu_string_offset - 1 - 3);
1795 OF_BUILD_EXEC(snmp_ans1_enc_tlv(&(request->outbound_pbuf_stream), &tlv));
1796  
1797 OF_BUILD_EXEC(snmpv3_get_user((char *)request->msg_user_name, NULL, NULL, &algo, key));
1798  
1799 OF_BUILD_EXEC(snmpv3_crypt(&request->outbound_pbuf_stream, tlv.value_len, key,
1800 request->msg_privacy_parameters, request->msg_authoritative_engine_boots,
1801 request->msg_authoritative_engine_time, algo, SNMP_V3_PRIV_MODE_ENCRYPT));
1802 }
1803  
1804 if (request->version == SNMP_VERSION_3 && (request->msg_flags & SNMP_V3_AUTH_FLAG)) {
1805 u8_t key[20];
1806 snmpv3_auth_algo_t algo;
1807 u8_t hmac[20];
1808  
1809 OF_BUILD_EXEC(snmpv3_get_user((char *)request->msg_user_name, &algo, key, NULL, NULL));
1810 OF_BUILD_EXEC(snmp_pbuf_stream_init(&(request->outbound_pbuf_stream),
1811 request->outbound_pbuf, 0, request->outbound_pbuf->tot_len));
1812 OF_BUILD_EXEC(snmpv3_auth(&request->outbound_pbuf_stream, frame_size + outbound_padding, key, algo, hmac));
1813  
1814 MEMCPY(request->msg_authentication_parameters, hmac, SNMP_V3_MAX_AUTH_PARAM_LENGTH);
1815 OF_BUILD_EXEC(snmp_pbuf_stream_init(&request->outbound_pbuf_stream,
1816 request->outbound_pbuf, 0, request->outbound_pbuf->tot_len));
1817 OF_BUILD_EXEC(snmp_pbuf_stream_seek_abs(&request->outbound_pbuf_stream,
1818 request->outbound_msg_authentication_parameters_offset));
1819  
1820 SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 1, SNMP_V3_MAX_AUTH_PARAM_LENGTH);
1821 OF_BUILD_EXEC(snmp_ans1_enc_tlv(&request->outbound_pbuf_stream, &tlv));
1822 OF_BUILD_EXEC(snmp_asn1_enc_raw(&request->outbound_pbuf_stream,
1823 request->msg_authentication_parameters, SNMP_V3_MAX_AUTH_PARAM_LENGTH));
1824 }
1825 #endif
1826  
1827 pbuf_realloc(request->outbound_pbuf, frame_size + outbound_padding);
1828  
1829 snmp_stats.outgetresponses++;
1830 snmp_stats.outpkts++;
1831  
1832 return ERR_OK;
1833 }
1834  
1835 static void
1836 snmp_execute_write_callbacks(struct snmp_request *request)
1837 {
1838 struct snmp_varbind_enumerator inbound_varbind_enumerator;
1839 struct snmp_varbind vb;
1840  
1841 snmp_vb_enumerator_init(&inbound_varbind_enumerator, request->inbound_pbuf, request->inbound_varbind_offset, request->inbound_varbind_len);
1842 vb.value = NULL; /* do NOT decode value (we enumerate outbound buffer here, so all varbinds have values assigned, which we don't need here) */
1843  
1844 while (snmp_vb_enumerator_get_next(&inbound_varbind_enumerator, &vb) == SNMP_VB_ENUMERATOR_ERR_OK) {
1845 snmp_write_callback(vb.oid.id, vb.oid.len, snmp_write_callback_arg);
1846 }
1847 }
1848  
1849  
1850 /* ----------------------------------------------------------------------- */
1851 /* VarBind enumerator methods */
1852 /* ----------------------------------------------------------------------- */
1853  
1854 void
1855 snmp_vb_enumerator_init(struct snmp_varbind_enumerator *enumerator, struct pbuf *p, u16_t offset, u16_t length)
1856 {
1857 snmp_pbuf_stream_init(&(enumerator->pbuf_stream), p, offset, length);
1858 enumerator->varbind_count = 0;
1859 }
1860  
1861 #define VB_PARSE_EXEC(code) PARSE_EXEC(code, SNMP_VB_ENUMERATOR_ERR_ASN1ERROR)
1862 #define VB_PARSE_ASSERT(code) PARSE_ASSERT(code, SNMP_VB_ENUMERATOR_ERR_ASN1ERROR)
1863  
1864 snmp_vb_enumerator_err_t
1865 snmp_vb_enumerator_get_next(struct snmp_varbind_enumerator *enumerator, struct snmp_varbind *varbind)
1866 {
1867 struct snmp_asn1_tlv tlv;
1868 u16_t varbind_len;
1869 err_t err;
1870  
1871 if (enumerator->pbuf_stream.length == 0) {
1872 return SNMP_VB_ENUMERATOR_ERR_EOVB;
1873 }
1874 enumerator->varbind_count++;
1875  
1876 /* decode varbind itself (parent container of a varbind) */
1877 VB_PARSE_EXEC(snmp_asn1_dec_tlv(&(enumerator->pbuf_stream), &tlv));
1878 VB_PARSE_ASSERT((tlv.type == SNMP_ASN1_TYPE_SEQUENCE) && (tlv.value_len <= enumerator->pbuf_stream.length));
1879 varbind_len = tlv.value_len;
1880  
1881 /* decode varbind name (object id) */
1882 VB_PARSE_EXEC(snmp_asn1_dec_tlv(&(enumerator->pbuf_stream), &tlv));
1883 VB_PARSE_ASSERT((tlv.type == SNMP_ASN1_TYPE_OBJECT_ID) && (SNMP_ASN1_TLV_LENGTH(tlv) < varbind_len) && (tlv.value_len < enumerator->pbuf_stream.length));
1884  
1885 VB_PARSE_EXEC(snmp_asn1_dec_oid(&(enumerator->pbuf_stream), tlv.value_len, varbind->oid.id, &(varbind->oid.len), SNMP_MAX_OBJ_ID_LEN));
1886 varbind_len -= SNMP_ASN1_TLV_LENGTH(tlv);
1887  
1888 /* decode varbind value (object id) */
1889 VB_PARSE_EXEC(snmp_asn1_dec_tlv(&(enumerator->pbuf_stream), &tlv));
1890 VB_PARSE_ASSERT((SNMP_ASN1_TLV_LENGTH(tlv) == varbind_len) && (tlv.value_len <= enumerator->pbuf_stream.length));
1891 varbind->type = tlv.type;
1892  
1893 /* shall the value be decoded ? */
1894 if (varbind->value != NULL) {
1895 switch (varbind->type) {
1896 case SNMP_ASN1_TYPE_INTEGER:
1897 VB_PARSE_EXEC(snmp_asn1_dec_s32t(&(enumerator->pbuf_stream), tlv.value_len, (s32_t *)varbind->value));
1898 varbind->value_len = sizeof(s32_t);
1899 break;
1900 case SNMP_ASN1_TYPE_COUNTER:
1901 case SNMP_ASN1_TYPE_GAUGE:
1902 case SNMP_ASN1_TYPE_TIMETICKS:
1903 VB_PARSE_EXEC(snmp_asn1_dec_u32t(&(enumerator->pbuf_stream), tlv.value_len, (u32_t *)varbind->value));
1904 varbind->value_len = sizeof(u32_t);
1905 break;
1906 case SNMP_ASN1_TYPE_OCTET_STRING:
1907 case SNMP_ASN1_TYPE_OPAQUE:
1908 err = snmp_asn1_dec_raw(&(enumerator->pbuf_stream), tlv.value_len, (u8_t *)varbind->value, &varbind->value_len, SNMP_MAX_VALUE_SIZE);
1909 if (err == ERR_MEM) {
1910 return SNMP_VB_ENUMERATOR_ERR_INVALIDLENGTH;
1911 }
1912 VB_PARSE_ASSERT(err == ERR_OK);
1913 break;
1914 case SNMP_ASN1_TYPE_NULL:
1915 varbind->value_len = 0;
1916 break;
1917 case SNMP_ASN1_TYPE_OBJECT_ID:
1918 /* misuse tlv.length_len as OID_length transporter */
1919 err = snmp_asn1_dec_oid(&(enumerator->pbuf_stream), tlv.value_len, (u32_t *)varbind->value, &tlv.length_len, SNMP_MAX_OBJ_ID_LEN);
1920 if (err == ERR_MEM) {
1921 return SNMP_VB_ENUMERATOR_ERR_INVALIDLENGTH;
1922 }
1923 VB_PARSE_ASSERT(err == ERR_OK);
1924 varbind->value_len = tlv.length_len * sizeof(u32_t);
1925 break;
1926 case SNMP_ASN1_TYPE_IPADDR:
1927 if (tlv.value_len == 4) {
1928 /* must be exactly 4 octets! */
1929 VB_PARSE_EXEC(snmp_asn1_dec_raw(&(enumerator->pbuf_stream), tlv.value_len, (u8_t *)varbind->value, &varbind->value_len, SNMP_MAX_VALUE_SIZE));
1930 } else {
1931 VB_PARSE_ASSERT(0);
1932 }
1933 break;
1934 #if LWIP_HAVE_INT64
1935 case SNMP_ASN1_TYPE_COUNTER64:
1936 VB_PARSE_EXEC(snmp_asn1_dec_u64t(&(enumerator->pbuf_stream), tlv.value_len, (u64_t *)varbind->value));
1937 varbind->value_len = sizeof(u64_t);
1938 break;
1939 #endif
1940 default:
1941 VB_PARSE_ASSERT(0);
1942 break;
1943 }
1944 } else {
1945 snmp_pbuf_stream_seek(&(enumerator->pbuf_stream), tlv.value_len);
1946 varbind->value_len = tlv.value_len;
1947 }
1948  
1949 return SNMP_VB_ENUMERATOR_ERR_OK;
1950 }
1951  
1952 #endif /* LWIP_SNMP */