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