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