Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: TYBLE16_simple_data_logger TYBLE16_MP3_Air
lwip_snmp_msg.c
00001 /** 00002 * @file 00003 * SNMP message processing (RFC1157). 00004 */ 00005 00006 /* 00007 * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. 00008 * Copyright (c) 2016 Elias Oenal. 00009 * All rights reserved. 00010 * 00011 * Redistribution and use in source and binary forms, with or without modification, 00012 * are permitted provided that the following conditions are met: 00013 * 00014 * 1. Redistributions of source code must retain the above copyright notice, 00015 * this list of conditions and the following disclaimer. 00016 * 2. Redistributions in binary form must reproduce the above copyright notice, 00017 * this list of conditions and the following disclaimer in the documentation 00018 * and/or other materials provided with the distribution. 00019 * 3. The name of the author may not be used to endorse or promote products 00020 * derived from this software without specific prior written permission. 00021 * 00022 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 00023 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 00024 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 00025 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00026 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 00027 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00028 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00029 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 00030 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 00031 * OF SUCH DAMAGE. 00032 * 00033 * Author: Christiaan Simons <christiaan.simons@axon.tv> 00034 * Martin Hentschel <info@cl-soft.de> 00035 * Elias Oenal <lwip@eliasoenal.com> 00036 */ 00037 00038 #include "lwip/apps/snmp_opts.h" 00039 00040 #if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ 00041 00042 #include "snmp_msg.h" 00043 #include "snmp_asn1.h" 00044 #include "snmp_core_priv.h" 00045 #include "lwip/ip_addr.h" 00046 #include "lwip/stats.h" 00047 00048 #if LWIP_SNMP_V3 00049 #include "lwip/apps/snmpv3.h" 00050 #include "snmpv3_priv.h" 00051 #ifdef LWIP_HOOK_FILENAME 00052 #include LWIP_HOOK_FILENAME 00053 #endif 00054 #endif 00055 00056 #include <string.h> 00057 00058 #define SNMP_V3_AUTH_FLAG 0x01 00059 #define SNMP_V3_PRIV_FLAG 0x02 00060 00061 /* Security levels */ 00062 #define SNMP_V3_NOAUTHNOPRIV 0x00 00063 #define SNMP_V3_AUTHNOPRIV SNMP_V3_AUTH_FLAG 00064 #define SNMP_V3_AUTHPRIV (SNMP_V3_AUTH_FLAG | SNMP_V3_PRIV_FLAG) 00065 00066 /* public (non-static) constants */ 00067 /** SNMP community string */ 00068 const char *snmp_community = SNMP_COMMUNITY; 00069 /** SNMP community string for write access */ 00070 const char *snmp_community_write = SNMP_COMMUNITY_WRITE; 00071 /** SNMP community string for sending traps */ 00072 const char *snmp_community_trap = SNMP_COMMUNITY_TRAP; 00073 00074 snmp_write_callback_fct snmp_write_callback = NULL; 00075 void *snmp_write_callback_arg = NULL; 00076 00077 #if LWIP_SNMP_CONFIGURE_VERSIONS 00078 00079 static u8_t v1_enabled = 1; 00080 static u8_t v2c_enabled = 1; 00081 static u8_t v3_enabled = 1; 00082 00083 static u8_t 00084 snmp_version_enabled(u8_t version) 00085 { 00086 if (version == SNMP_VERSION_1) { 00087 return v1_enabled; 00088 } else if (version == SNMP_VERSION_2c) { 00089 return v2c_enabled; 00090 } 00091 #if LWIP_SNMP_V3 00092 else if (version == SNMP_VERSION_3) { 00093 return v3_enabled; 00094 } 00095 #endif 00096 else { 00097 LWIP_ASSERT("Invalid SNMP version", 0); 00098 return 0; 00099 } 00100 } 00101 00102 u8_t 00103 snmp_v1_enabled(void) 00104 { 00105 return snmp_version_enabled(SNMP_VERSION_1); 00106 } 00107 00108 u8_t 00109 snmp_v2c_enabled(void) 00110 { 00111 return snmp_version_enabled(SNMP_VERSION_2c); 00112 } 00113 00114 u8_t 00115 snmp_v3_enabled(void) 00116 { 00117 return snmp_version_enabled(SNMP_VERSION_3); 00118 } 00119 00120 static void 00121 snmp_version_enable(u8_t version, u8_t enable) 00122 { 00123 if (version == SNMP_VERSION_1) { 00124 v1_enabled = enable; 00125 } else if (version == SNMP_VERSION_2c) { 00126 v2c_enabled = enable; 00127 } 00128 #if LWIP_SNMP_V3 00129 else if (version == SNMP_VERSION_3) { 00130 v3_enabled = enable; 00131 } 00132 #endif 00133 else { 00134 LWIP_ASSERT("Invalid SNMP version", 0); 00135 } 00136 } 00137 00138 void 00139 snmp_v1_enable(u8_t enable) 00140 { 00141 snmp_version_enable(SNMP_VERSION_1, enable); 00142 } 00143 00144 void 00145 snmp_v2c_enable(u8_t enable) 00146 { 00147 snmp_version_enable(SNMP_VERSION_2c, enable); 00148 } 00149 00150 void 00151 snmp_v3_enable(u8_t enable) 00152 { 00153 snmp_version_enable(SNMP_VERSION_3, enable); 00154 } 00155 00156 #endif 00157 00158 /** 00159 * @ingroup snmp_core 00160 * Returns current SNMP community string. 00161 * @return current SNMP community string 00162 */ 00163 const char * 00164 snmp_get_community(void) 00165 { 00166 return snmp_community; 00167 } 00168 00169 /** 00170 * @ingroup snmp_core 00171 * Sets SNMP community string. 00172 * The string itself (its storage) must be valid throughout the whole life of 00173 * program (or until it is changed to sth else). 00174 * 00175 * @param community is a pointer to new community string 00176 */ 00177 void 00178 snmp_set_community(const char *const community) 00179 { 00180 LWIP_ASSERT_CORE_LOCKED(); 00181 LWIP_ASSERT("community string is too long!", strlen(community) <= SNMP_MAX_COMMUNITY_STR_LEN); 00182 snmp_community = community; 00183 } 00184 00185 /** 00186 * @ingroup snmp_core 00187 * Returns current SNMP write-access community string. 00188 * @return current SNMP write-access community string 00189 */ 00190 const char * 00191 snmp_get_community_write(void) 00192 { 00193 return snmp_community_write; 00194 } 00195 00196 /** 00197 * @ingroup snmp_traps 00198 * Returns current SNMP community string used for sending traps. 00199 * @return current SNMP community string used for sending traps 00200 */ 00201 const char * 00202 snmp_get_community_trap(void) 00203 { 00204 return snmp_community_trap; 00205 } 00206 00207 /** 00208 * @ingroup snmp_core 00209 * Sets SNMP community string for write-access. 00210 * The string itself (its storage) must be valid throughout the whole life of 00211 * program (or until it is changed to sth else). 00212 * 00213 * @param community is a pointer to new write-access community string 00214 */ 00215 void 00216 snmp_set_community_write(const char *const community) 00217 { 00218 LWIP_ASSERT_CORE_LOCKED(); 00219 LWIP_ASSERT("community string must not be NULL", community != NULL); 00220 LWIP_ASSERT("community string is too long!", strlen(community) <= SNMP_MAX_COMMUNITY_STR_LEN); 00221 snmp_community_write = community; 00222 } 00223 00224 /** 00225 * @ingroup snmp_traps 00226 * Sets SNMP community string used for sending traps. 00227 * The string itself (its storage) must be valid throughout the whole life of 00228 * program (or until it is changed to sth else). 00229 * 00230 * @param community is a pointer to new trap community string 00231 */ 00232 void 00233 snmp_set_community_trap(const char *const community) 00234 { 00235 LWIP_ASSERT_CORE_LOCKED(); 00236 LWIP_ASSERT("community string is too long!", strlen(community) <= SNMP_MAX_COMMUNITY_STR_LEN); 00237 snmp_community_trap = community; 00238 } 00239 00240 /** 00241 * @ingroup snmp_core 00242 * Callback fired on every successful write access 00243 */ 00244 void 00245 snmp_set_write_callback(snmp_write_callback_fct write_callback, void *callback_arg) 00246 { 00247 LWIP_ASSERT_CORE_LOCKED(); 00248 snmp_write_callback = write_callback; 00249 snmp_write_callback_arg = callback_arg; 00250 } 00251 00252 /* ----------------------------------------------------------------------- */ 00253 /* forward declarations */ 00254 /* ----------------------------------------------------------------------- */ 00255 00256 static err_t snmp_process_get_request(struct snmp_request *request); 00257 static err_t snmp_process_getnext_request(struct snmp_request *request); 00258 static err_t snmp_process_getbulk_request(struct snmp_request *request); 00259 static err_t snmp_process_set_request(struct snmp_request *request); 00260 00261 static err_t snmp_parse_inbound_frame(struct snmp_request *request); 00262 static err_t snmp_prepare_outbound_frame(struct snmp_request *request); 00263 static err_t snmp_complete_outbound_frame(struct snmp_request *request); 00264 static void snmp_execute_write_callbacks(struct snmp_request *request); 00265 00266 00267 /* ----------------------------------------------------------------------- */ 00268 /* implementation */ 00269 /* ----------------------------------------------------------------------- */ 00270 00271 void 00272 snmp_receive(void *handle, struct pbuf *p, const ip_addr_t *source_ip, u16_t port) 00273 { 00274 err_t err; 00275 struct snmp_request request; 00276 00277 memset(&request, 0, sizeof(request)); 00278 request.handle = handle; 00279 request.source_ip = source_ip; 00280 request.source_port = port; 00281 request.inbound_pbuf = p; 00282 00283 snmp_stats.inpkts++; 00284 00285 err = snmp_parse_inbound_frame(&request); 00286 if (err == ERR_OK) { 00287 err = snmp_prepare_outbound_frame(&request); 00288 if (err == ERR_OK) { 00289 00290 if (request.error_status == SNMP_ERR_NOERROR) { 00291 /* only process frame if we do not already have an error to return (e.g. all readonly) */ 00292 if (request.request_type == SNMP_ASN1_CONTEXT_PDU_GET_REQ) { 00293 err = snmp_process_get_request(&request); 00294 } else if (request.request_type == SNMP_ASN1_CONTEXT_PDU_GET_NEXT_REQ) { 00295 err = snmp_process_getnext_request(&request); 00296 } else if (request.request_type == SNMP_ASN1_CONTEXT_PDU_GET_BULK_REQ) { 00297 err = snmp_process_getbulk_request(&request); 00298 } else if (request.request_type == SNMP_ASN1_CONTEXT_PDU_SET_REQ) { 00299 err = snmp_process_set_request(&request); 00300 } 00301 } 00302 #if LWIP_SNMP_V3 00303 else { 00304 struct snmp_varbind vb; 00305 00306 vb.next = NULL; 00307 vb.prev = NULL; 00308 vb.type = SNMP_ASN1_TYPE_COUNTER32; 00309 vb.value_len = sizeof(u32_t); 00310 00311 switch (request.error_status) { 00312 case SNMP_ERR_AUTHORIZATIONERROR: { 00313 static const u32_t oid[] = { 1, 3, 6, 1, 6, 3, 15, 1, 1, 5, 0 }; 00314 snmp_oid_assign(&vb.oid, oid, LWIP_ARRAYSIZE(oid)); 00315 vb.value = &snmp_stats.wrongdigests; 00316 } 00317 break; 00318 case SNMP_ERR_UNKNOWN_ENGINEID: { 00319 static const u32_t oid[] = { 1, 3, 6, 1, 6, 3, 15, 1, 1, 4, 0 }; 00320 snmp_oid_assign(&vb.oid, oid, LWIP_ARRAYSIZE(oid)); 00321 vb.value = &snmp_stats.unknownengineids; 00322 } 00323 break; 00324 case SNMP_ERR_UNKNOWN_SECURITYNAME: { 00325 static const u32_t oid[] = { 1, 3, 6, 1, 6, 3, 15, 1, 1, 3, 0 }; 00326 snmp_oid_assign(&vb.oid, oid, LWIP_ARRAYSIZE(oid)); 00327 vb.value = &snmp_stats.unknownusernames; 00328 } 00329 break; 00330 case SNMP_ERR_UNSUPPORTED_SECLEVEL: { 00331 static const u32_t oid[] = { 1, 3, 6, 1, 6, 3, 15, 1, 1, 1, 0 }; 00332 snmp_oid_assign(&vb.oid, oid, LWIP_ARRAYSIZE(oid)); 00333 vb.value = &snmp_stats.unsupportedseclevels; 00334 } 00335 break; 00336 case SNMP_ERR_NOTINTIMEWINDOW: { 00337 static const u32_t oid[] = { 1, 3, 6, 1, 6, 3, 15, 1, 1, 2, 0 }; 00338 snmp_oid_assign(&vb.oid, oid, LWIP_ARRAYSIZE(oid)); 00339 vb.value = &snmp_stats.notintimewindows; 00340 } 00341 break; 00342 case SNMP_ERR_DECRYIPTION_ERROR: { 00343 static const u32_t oid[] = { 1, 3, 6, 1, 6, 3, 15, 1, 1, 6, 0 }; 00344 snmp_oid_assign(&vb.oid, oid, LWIP_ARRAYSIZE(oid)); 00345 vb.value = &snmp_stats.decryptionerrors; 00346 } 00347 break; 00348 default: 00349 /* Unknown or unhandled error_status */ 00350 err = ERR_ARG; 00351 } 00352 00353 if (err == ERR_OK) { 00354 snmp_append_outbound_varbind(&(request.outbound_pbuf_stream), &vb); 00355 request.error_status = SNMP_ERR_NOERROR; 00356 } 00357 00358 request.request_out_type = (SNMP_ASN1_CLASS_CONTEXT | SNMP_ASN1_CONTENTTYPE_CONSTRUCTED | SNMP_ASN1_CONTEXT_PDU_REPORT); 00359 request.request_id = request.msg_id; 00360 } 00361 #endif 00362 00363 if (err == ERR_OK) { 00364 err = snmp_complete_outbound_frame(&request); 00365 00366 if (err == ERR_OK) { 00367 err = snmp_sendto(request.handle, request.outbound_pbuf, request.source_ip, request.source_port); 00368 00369 if ((request.request_type == SNMP_ASN1_CONTEXT_PDU_SET_REQ) 00370 && (request.error_status == SNMP_ERR_NOERROR) 00371 && (snmp_write_callback != NULL)) { 00372 /* raise write notification for all written objects */ 00373 snmp_execute_write_callbacks(&request); 00374 } 00375 } 00376 } 00377 } 00378 00379 if (request.outbound_pbuf != NULL) { 00380 pbuf_free(request.outbound_pbuf); 00381 } 00382 } 00383 } 00384 00385 static u8_t 00386 snmp_msg_getnext_validate_node_inst(struct snmp_node_instance *node_instance, void *validate_arg) 00387 { 00388 if (((node_instance->access & SNMP_NODE_INSTANCE_ACCESS_READ) != SNMP_NODE_INSTANCE_ACCESS_READ) || (node_instance->get_value == NULL)) { 00389 return SNMP_ERR_NOSUCHINSTANCE; 00390 } 00391 00392 #if LWIP_HAVE_INT64 00393 if ((node_instance->asn1_type == SNMP_ASN1_TYPE_COUNTER64) && (((struct snmp_request *)validate_arg)->version == SNMP_VERSION_1)) { 00394 /* according to RFC 2089 skip Counter64 objects in GetNext requests from v1 clients */ 00395 return SNMP_ERR_NOSUCHINSTANCE; 00396 } 00397 #endif 00398 00399 return SNMP_ERR_NOERROR; 00400 } 00401 00402 static void 00403 snmp_process_varbind(struct snmp_request *request, struct snmp_varbind *vb, u8_t get_next) 00404 { 00405 err_t err; 00406 struct snmp_node_instance node_instance; 00407 memset(&node_instance, 0, sizeof(node_instance)); 00408 00409 if (get_next) { 00410 struct snmp_obj_id result_oid; 00411 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); 00412 00413 if (request->error_status == SNMP_ERR_NOERROR) { 00414 snmp_oid_assign(&vb->oid, result_oid.id, result_oid.len); 00415 } 00416 } else { 00417 request->error_status = snmp_get_node_instance_from_oid(vb->oid.id, vb->oid.len, &node_instance); 00418 00419 if (request->error_status == SNMP_ERR_NOERROR) { 00420 /* use 'getnext_validate' method for validation to avoid code duplication (some checks have to be executed here) */ 00421 request->error_status = snmp_msg_getnext_validate_node_inst(&node_instance, request); 00422 00423 if (request->error_status != SNMP_ERR_NOERROR) { 00424 if (node_instance.release_instance != NULL) { 00425 node_instance.release_instance(&node_instance); 00426 } 00427 } 00428 } 00429 } 00430 00431 if (request->error_status != SNMP_ERR_NOERROR) { 00432 if (request->error_status >= SNMP_VARBIND_EXCEPTION_OFFSET) { 00433 if ((request->version == SNMP_VERSION_2c) || request->version == SNMP_VERSION_3) { 00434 /* in SNMP v2c a varbind related exception is stored in varbind and not in frame header */ 00435 vb->type = (SNMP_ASN1_CONTENTTYPE_PRIMITIVE | SNMP_ASN1_CLASS_CONTEXT | (request->error_status & SNMP_VARBIND_EXCEPTION_MASK)); 00436 vb->value_len = 0; 00437 00438 err = snmp_append_outbound_varbind(&(request->outbound_pbuf_stream), vb); 00439 if (err == ERR_OK) { 00440 /* we stored the exception in varbind -> go on */ 00441 request->error_status = SNMP_ERR_NOERROR; 00442 } else if (err == ERR_BUF) { 00443 request->error_status = SNMP_ERR_TOOBIG; 00444 } else { 00445 request->error_status = SNMP_ERR_GENERROR; 00446 } 00447 } 00448 } else { 00449 /* according to RFC 1157/1905, all other errors only return genError */ 00450 request->error_status = SNMP_ERR_GENERROR; 00451 } 00452 } else { 00453 s16_t len = node_instance.get_value(&node_instance, vb->value); 00454 00455 if (len >= 0) { 00456 vb->value_len = (u16_t)len; /* cast is OK because we checked >= 0 above */ 00457 vb->type = node_instance.asn1_type; 00458 00459 LWIP_ASSERT("SNMP_MAX_VALUE_SIZE is configured too low", (vb->value_len & ~SNMP_GET_VALUE_RAW_DATA) <= SNMP_MAX_VALUE_SIZE); 00460 err = snmp_append_outbound_varbind(&request->outbound_pbuf_stream, vb); 00461 00462 if (err == ERR_BUF) { 00463 request->error_status = SNMP_ERR_TOOBIG; 00464 } else if (err != ERR_OK) { 00465 request->error_status = SNMP_ERR_GENERROR; 00466 } 00467 } else { 00468 request->error_status = SNMP_ERR_GENERROR; 00469 } 00470 00471 if (node_instance.release_instance != NULL) { 00472 node_instance.release_instance(&node_instance); 00473 } 00474 } 00475 } 00476 00477 00478 /** 00479 * Service an internal or external event for SNMP GET. 00480 * 00481 * @param request points to the associated message process state 00482 */ 00483 static err_t 00484 snmp_process_get_request(struct snmp_request *request) 00485 { 00486 snmp_vb_enumerator_err_t err; 00487 struct snmp_varbind vb; 00488 vb.value = request->value_buffer; 00489 00490 LWIP_DEBUGF(SNMP_DEBUG, ("SNMP get request\n")); 00491 00492 while (request->error_status == SNMP_ERR_NOERROR) { 00493 err = snmp_vb_enumerator_get_next(&request->inbound_varbind_enumerator, &vb); 00494 if (err == SNMP_VB_ENUMERATOR_ERR_OK) { 00495 if ((vb.type == SNMP_ASN1_TYPE_NULL) && (vb.value_len == 0)) { 00496 snmp_process_varbind(request, &vb, 0); 00497 } else { 00498 request->error_status = SNMP_ERR_GENERROR; 00499 } 00500 } else if (err == SNMP_VB_ENUMERATOR_ERR_EOVB) { 00501 /* no more varbinds in request */ 00502 break; 00503 } else if (err == SNMP_VB_ENUMERATOR_ERR_ASN1ERROR) { 00504 /* malformed ASN.1, don't answer */ 00505 return ERR_ARG; 00506 } else { 00507 request->error_status = SNMP_ERR_GENERROR; 00508 } 00509 } 00510 00511 return ERR_OK; 00512 } 00513 00514 /** 00515 * Service an internal or external event for SNMP GET. 00516 * 00517 * @param request points to the associated message process state 00518 */ 00519 static err_t 00520 snmp_process_getnext_request(struct snmp_request *request) 00521 { 00522 snmp_vb_enumerator_err_t err; 00523 struct snmp_varbind vb; 00524 vb.value = request->value_buffer; 00525 00526 LWIP_DEBUGF(SNMP_DEBUG, ("SNMP get-next request\n")); 00527 00528 while (request->error_status == SNMP_ERR_NOERROR) { 00529 err = snmp_vb_enumerator_get_next(&request->inbound_varbind_enumerator, &vb); 00530 if (err == SNMP_VB_ENUMERATOR_ERR_OK) { 00531 if ((vb.type == SNMP_ASN1_TYPE_NULL) && (vb.value_len == 0)) { 00532 snmp_process_varbind(request, &vb, 1); 00533 } else { 00534 request->error_status = SNMP_ERR_GENERROR; 00535 } 00536 } else if (err == SNMP_VB_ENUMERATOR_ERR_EOVB) { 00537 /* no more varbinds in request */ 00538 break; 00539 } else if (err == SNMP_VB_ENUMERATOR_ERR_ASN1ERROR) { 00540 /* malformed ASN.1, don't answer */ 00541 return ERR_ARG; 00542 } else { 00543 request->error_status = SNMP_ERR_GENERROR; 00544 } 00545 } 00546 00547 return ERR_OK; 00548 } 00549 00550 /** 00551 * Service an internal or external event for SNMP GETBULKT. 00552 * 00553 * @param request points to the associated message process state 00554 */ 00555 static err_t 00556 snmp_process_getbulk_request(struct snmp_request *request) 00557 { 00558 snmp_vb_enumerator_err_t err; 00559 s32_t non_repeaters = request->non_repeaters; 00560 s32_t repetitions; 00561 u16_t repetition_offset = 0; 00562 struct snmp_varbind_enumerator repetition_varbind_enumerator; 00563 struct snmp_varbind vb; 00564 vb.value = request->value_buffer; 00565 00566 if (SNMP_LWIP_GETBULK_MAX_REPETITIONS > 0) { 00567 repetitions = LWIP_MIN(request->max_repetitions, SNMP_LWIP_GETBULK_MAX_REPETITIONS); 00568 } else { 00569 repetitions = request->max_repetitions; 00570 } 00571 00572 LWIP_DEBUGF(SNMP_DEBUG, ("SNMP get-bulk request\n")); 00573 00574 /* process non repeaters and first repetition */ 00575 while (request->error_status == SNMP_ERR_NOERROR) { 00576 if (non_repeaters == 0) { 00577 repetition_offset = request->outbound_pbuf_stream.offset; 00578 00579 if (repetitions == 0) { 00580 /* do not resolve repeaters when repetitions is set to 0 */ 00581 break; 00582 } 00583 repetitions--; 00584 } 00585 00586 err = snmp_vb_enumerator_get_next(&request->inbound_varbind_enumerator, &vb); 00587 if (err == SNMP_VB_ENUMERATOR_ERR_EOVB) { 00588 /* no more varbinds in request */ 00589 break; 00590 } else if (err == SNMP_VB_ENUMERATOR_ERR_ASN1ERROR) { 00591 /* malformed ASN.1, don't answer */ 00592 return ERR_ARG; 00593 } else if ((err != SNMP_VB_ENUMERATOR_ERR_OK) || (vb.type != SNMP_ASN1_TYPE_NULL) || (vb.value_len != 0)) { 00594 request->error_status = SNMP_ERR_GENERROR; 00595 } else { 00596 snmp_process_varbind(request, &vb, 1); 00597 non_repeaters--; 00598 } 00599 } 00600 00601 /* process repetitions > 1 */ 00602 while ((request->error_status == SNMP_ERR_NOERROR) && (repetitions > 0) && (request->outbound_pbuf_stream.offset != repetition_offset)) { 00603 00604 u8_t all_endofmibview = 1; 00605 00606 snmp_vb_enumerator_init(&repetition_varbind_enumerator, request->outbound_pbuf, repetition_offset, request->outbound_pbuf_stream.offset - repetition_offset); 00607 repetition_offset = request->outbound_pbuf_stream.offset; /* for next loop */ 00608 00609 while (request->error_status == SNMP_ERR_NOERROR) { 00610 vb.value = NULL; /* do NOT decode value (we enumerate outbound buffer here, so all varbinds have values assigned) */ 00611 err = snmp_vb_enumerator_get_next(&repetition_varbind_enumerator, &vb); 00612 if (err == SNMP_VB_ENUMERATOR_ERR_OK) { 00613 vb.value = request->value_buffer; 00614 snmp_process_varbind(request, &vb, 1); 00615 00616 if (request->error_status != SNMP_ERR_NOERROR) { 00617 /* already set correct error-index (here it cannot be taken from inbound varbind enumerator) */ 00618 request->error_index = request->non_repeaters + repetition_varbind_enumerator.varbind_count; 00619 } else if (vb.type != (SNMP_ASN1_CONTENTTYPE_PRIMITIVE | SNMP_ASN1_CLASS_CONTEXT | SNMP_ASN1_CONTEXT_VARBIND_END_OF_MIB_VIEW)) { 00620 all_endofmibview = 0; 00621 } 00622 } else if (err == SNMP_VB_ENUMERATOR_ERR_EOVB) { 00623 /* no more varbinds in request */ 00624 break; 00625 } else { 00626 LWIP_DEBUGF(SNMP_DEBUG, ("Very strange, we cannot parse the varbind output that we created just before!")); 00627 request->error_status = SNMP_ERR_GENERROR; 00628 request->error_index = request->non_repeaters + repetition_varbind_enumerator.varbind_count; 00629 } 00630 } 00631 00632 if ((request->error_status == SNMP_ERR_NOERROR) && all_endofmibview) { 00633 /* stop when all varbinds in a loop return EndOfMibView */ 00634 break; 00635 } 00636 00637 repetitions--; 00638 } 00639 00640 if (request->error_status == SNMP_ERR_TOOBIG) { 00641 /* for GetBulk it is ok, if not all requested variables fit into the response -> just return the varbinds added so far */ 00642 request->error_status = SNMP_ERR_NOERROR; 00643 } 00644 00645 return ERR_OK; 00646 } 00647 00648 /** 00649 * Service an internal or external event for SNMP SET. 00650 * 00651 * @param request points to the associated message process state 00652 */ 00653 static err_t 00654 snmp_process_set_request(struct snmp_request *request) 00655 { 00656 snmp_vb_enumerator_err_t err; 00657 struct snmp_varbind vb; 00658 vb.value = request->value_buffer; 00659 00660 LWIP_DEBUGF(SNMP_DEBUG, ("SNMP set request\n")); 00661 00662 /* perform set test on all objects */ 00663 while (request->error_status == SNMP_ERR_NOERROR) { 00664 err = snmp_vb_enumerator_get_next(&request->inbound_varbind_enumerator, &vb); 00665 if (err == SNMP_VB_ENUMERATOR_ERR_OK) { 00666 struct snmp_node_instance node_instance; 00667 memset(&node_instance, 0, sizeof(node_instance)); 00668 00669 request->error_status = snmp_get_node_instance_from_oid(vb.oid.id, vb.oid.len, &node_instance); 00670 if (request->error_status == SNMP_ERR_NOERROR) { 00671 if (node_instance.asn1_type != vb.type) { 00672 request->error_status = SNMP_ERR_WRONGTYPE; 00673 } else if (((node_instance.access & SNMP_NODE_INSTANCE_ACCESS_WRITE) != SNMP_NODE_INSTANCE_ACCESS_WRITE) || (node_instance.set_value == NULL)) { 00674 request->error_status = SNMP_ERR_NOTWRITABLE; 00675 } else { 00676 if (node_instance.set_test != NULL) { 00677 request->error_status = node_instance.set_test(&node_instance, vb.value_len, vb.value); 00678 } 00679 } 00680 00681 if (node_instance.release_instance != NULL) { 00682 node_instance.release_instance(&node_instance); 00683 } 00684 } 00685 } else if (err == SNMP_VB_ENUMERATOR_ERR_EOVB) { 00686 /* no more varbinds in request */ 00687 break; 00688 } else if (err == SNMP_VB_ENUMERATOR_ERR_INVALIDLENGTH) { 00689 request->error_status = SNMP_ERR_WRONGLENGTH; 00690 } else if (err == SNMP_VB_ENUMERATOR_ERR_ASN1ERROR) { 00691 /* malformed ASN.1, don't answer */ 00692 return ERR_ARG; 00693 } else { 00694 request->error_status = SNMP_ERR_GENERROR; 00695 } 00696 } 00697 00698 /* perform real set operation on all objects */ 00699 if (request->error_status == SNMP_ERR_NOERROR) { 00700 snmp_vb_enumerator_init(&request->inbound_varbind_enumerator, request->inbound_pbuf, request->inbound_varbind_offset, request->inbound_varbind_len); 00701 while (request->error_status == SNMP_ERR_NOERROR) { 00702 err = snmp_vb_enumerator_get_next(&request->inbound_varbind_enumerator, &vb); 00703 if (err == SNMP_VB_ENUMERATOR_ERR_OK) { 00704 struct snmp_node_instance node_instance; 00705 memset(&node_instance, 0, sizeof(node_instance)); 00706 request->error_status = snmp_get_node_instance_from_oid(vb.oid.id, vb.oid.len, &node_instance); 00707 if (request->error_status == SNMP_ERR_NOERROR) { 00708 if (node_instance.set_value(&node_instance, vb.value_len, vb.value) != SNMP_ERR_NOERROR) { 00709 if (request->inbound_varbind_enumerator.varbind_count == 1) { 00710 request->error_status = SNMP_ERR_COMMITFAILED; 00711 } else { 00712 /* we cannot undo the set operations done so far */ 00713 request->error_status = SNMP_ERR_UNDOFAILED; 00714 } 00715 } 00716 00717 if (node_instance.release_instance != NULL) { 00718 node_instance.release_instance(&node_instance); 00719 } 00720 } 00721 } else if (err == SNMP_VB_ENUMERATOR_ERR_EOVB) { 00722 /* no more varbinds in request */ 00723 break; 00724 } else { 00725 /* first time enumerating varbinds work but second time not, although nothing should have changed in between ??? */ 00726 request->error_status = SNMP_ERR_GENERROR; 00727 } 00728 } 00729 } 00730 00731 return ERR_OK; 00732 } 00733 00734 #define PARSE_EXEC(code, retValue) \ 00735 if ((code) != ERR_OK) { \ 00736 LWIP_DEBUGF(SNMP_DEBUG, ("Malformed ASN.1 detected.\n")); \ 00737 snmp_stats.inasnparseerrs++; \ 00738 return retValue; \ 00739 } 00740 00741 #define PARSE_ASSERT(cond, retValue) \ 00742 if (!(cond)) { \ 00743 LWIP_DEBUGF(SNMP_DEBUG, ("SNMP parse assertion failed!: " # cond)); \ 00744 snmp_stats.inasnparseerrs++; \ 00745 return retValue; \ 00746 } 00747 00748 #define BUILD_EXEC(code, retValue) \ 00749 if ((code) != ERR_OK) { \ 00750 LWIP_DEBUGF(SNMP_DEBUG, ("SNMP error during creation of outbound frame!: " # code)); \ 00751 return retValue; \ 00752 } 00753 00754 #define IF_PARSE_EXEC(code) PARSE_EXEC(code, ERR_ARG) 00755 #define IF_PARSE_ASSERT(code) PARSE_ASSERT(code, ERR_ARG) 00756 00757 /** 00758 * Checks and decodes incoming SNMP message header, logs header errors. 00759 * 00760 * @param request points to the current message request state return 00761 * @return 00762 * - ERR_OK SNMP header is sane and accepted 00763 * - ERR_VAL SNMP header is either malformed or rejected 00764 */ 00765 static err_t 00766 snmp_parse_inbound_frame(struct snmp_request *request) 00767 { 00768 struct snmp_pbuf_stream pbuf_stream; 00769 struct snmp_asn1_tlv tlv; 00770 s32_t parent_tlv_value_len; 00771 s32_t s32_value; 00772 err_t err; 00773 #if LWIP_SNMP_V3 00774 snmpv3_auth_algo_t auth; 00775 snmpv3_priv_algo_t priv; 00776 #endif 00777 00778 IF_PARSE_EXEC(snmp_pbuf_stream_init(&pbuf_stream, request->inbound_pbuf, 0, request->inbound_pbuf->tot_len)); 00779 00780 /* decode main container consisting of version, community and PDU */ 00781 IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); 00782 IF_PARSE_ASSERT((tlv.type == SNMP_ASN1_TYPE_SEQUENCE) && (tlv.value_len == pbuf_stream.length)); 00783 parent_tlv_value_len = tlv.value_len; 00784 00785 /* decode version */ 00786 IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); 00787 IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_INTEGER); 00788 parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); 00789 IF_PARSE_ASSERT(parent_tlv_value_len > 0); 00790 00791 IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &s32_value)); 00792 00793 if (((s32_value != SNMP_VERSION_1) && 00794 (s32_value != SNMP_VERSION_2c) 00795 #if LWIP_SNMP_V3 00796 && (s32_value != SNMP_VERSION_3) 00797 #endif 00798 ) 00799 #if LWIP_SNMP_CONFIGURE_VERSIONS 00800 || (!snmp_version_enabled(s32_value)) 00801 #endif 00802 ) { 00803 /* unsupported SNMP version */ 00804 snmp_stats.inbadversions++; 00805 return ERR_ARG; 00806 } 00807 request->version = (u8_t)s32_value; 00808 00809 #if LWIP_SNMP_V3 00810 if (request->version == SNMP_VERSION_3) { 00811 u16_t u16_value; 00812 u16_t inbound_msgAuthenticationParameters_offset; 00813 00814 /* SNMPv3 doesn't use communities */ 00815 /* @todo: Differentiate read/write access */ 00816 strncpy((char *)request->community, snmp_community, SNMP_MAX_COMMUNITY_STR_LEN); 00817 request->community[SNMP_MAX_COMMUNITY_STR_LEN] = 0; /* ensure NULL termination (strncpy does NOT guarantee it!) */ 00818 request->community_strlen = (u16_t)strnlen((char *)request->community, SNMP_MAX_COMMUNITY_STR_LEN); 00819 00820 /* RFC3414 globalData */ 00821 IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); 00822 IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_SEQUENCE); 00823 parent_tlv_value_len -= SNMP_ASN1_TLV_HDR_LENGTH(tlv); 00824 IF_PARSE_ASSERT(parent_tlv_value_len > 0); 00825 00826 /* decode msgID */ 00827 IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); 00828 IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_INTEGER); 00829 parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); 00830 IF_PARSE_ASSERT(parent_tlv_value_len > 0); 00831 00832 IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &s32_value)); 00833 request->msg_id = s32_value; 00834 00835 /* decode msgMaxSize */ 00836 IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); 00837 IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_INTEGER); 00838 parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); 00839 IF_PARSE_ASSERT(parent_tlv_value_len > 0); 00840 00841 IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &s32_value)); 00842 request->msg_max_size = s32_value; 00843 00844 /* decode msgFlags */ 00845 IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); 00846 IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_OCTET_STRING); 00847 parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); 00848 IF_PARSE_ASSERT(parent_tlv_value_len > 0); 00849 00850 IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &s32_value)); 00851 request->msg_flags = (u8_t)s32_value; 00852 00853 /* decode msgSecurityModel */ 00854 IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); 00855 IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_INTEGER); 00856 parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); 00857 IF_PARSE_ASSERT(parent_tlv_value_len > 0); 00858 00859 IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &s32_value)); 00860 request->msg_security_model = s32_value; 00861 00862 /* RFC3414 msgSecurityParameters 00863 * The User-based Security Model defines the contents of the OCTET 00864 * STRING as a SEQUENCE. 00865 * 00866 * We skip the protective dummy OCTET STRING header 00867 * to access the SEQUENCE header. 00868 */ 00869 IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); 00870 IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_OCTET_STRING); 00871 parent_tlv_value_len -= SNMP_ASN1_TLV_HDR_LENGTH(tlv); 00872 IF_PARSE_ASSERT(parent_tlv_value_len > 0); 00873 00874 /* msgSecurityParameters SEQUENCE header */ 00875 IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); 00876 IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_SEQUENCE); 00877 parent_tlv_value_len -= SNMP_ASN1_TLV_HDR_LENGTH(tlv); 00878 IF_PARSE_ASSERT(parent_tlv_value_len > 0); 00879 00880 /* decode msgAuthoritativeEngineID */ 00881 IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); 00882 IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_OCTET_STRING); 00883 parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); 00884 IF_PARSE_ASSERT(parent_tlv_value_len > 0); 00885 00886 IF_PARSE_EXEC(snmp_asn1_dec_raw(&pbuf_stream, tlv.value_len, request->msg_authoritative_engine_id, 00887 &u16_value, SNMP_V3_MAX_ENGINE_ID_LENGTH)); 00888 request->msg_authoritative_engine_id_len = (u8_t)u16_value; 00889 00890 /* msgAuthoritativeEngineBoots */ 00891 IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); 00892 IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_INTEGER); 00893 parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); 00894 IF_PARSE_ASSERT(parent_tlv_value_len > 0); 00895 IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &request->msg_authoritative_engine_boots)); 00896 00897 /* msgAuthoritativeEngineTime */ 00898 IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); 00899 IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_INTEGER); 00900 parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); 00901 IF_PARSE_ASSERT(parent_tlv_value_len > 0); 00902 IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &request->msg_authoritative_engine_time)); 00903 00904 /* msgUserName */ 00905 IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); 00906 IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_OCTET_STRING); 00907 parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); 00908 IF_PARSE_ASSERT(parent_tlv_value_len > 0); 00909 00910 IF_PARSE_EXEC(snmp_asn1_dec_raw(&pbuf_stream, tlv.value_len, request->msg_user_name, 00911 &u16_value, SNMP_V3_MAX_USER_LENGTH)); 00912 request->msg_user_name_len = (u8_t)u16_value; 00913 00914 /* msgAuthenticationParameters */ 00915 memset(request->msg_authentication_parameters, 0, SNMP_V3_MAX_AUTH_PARAM_LENGTH); 00916 IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); 00917 IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_OCTET_STRING); 00918 parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); 00919 IF_PARSE_ASSERT(parent_tlv_value_len > 0); 00920 /* Remember position */ 00921 inbound_msgAuthenticationParameters_offset = pbuf_stream.offset; 00922 LWIP_UNUSED_ARG(inbound_msgAuthenticationParameters_offset); 00923 /* Read auth parameters */ 00924 /* IF_PARSE_ASSERT(tlv.value_len <= SNMP_V3_MAX_AUTH_PARAM_LENGTH); */ 00925 IF_PARSE_EXEC(snmp_asn1_dec_raw(&pbuf_stream, tlv.value_len, request->msg_authentication_parameters, 00926 &u16_value, tlv.value_len)); 00927 request->msg_authentication_parameters_len = (u8_t)u16_value; 00928 00929 /* msgPrivacyParameters */ 00930 memset(request->msg_privacy_parameters, 0, SNMP_V3_MAX_PRIV_PARAM_LENGTH); 00931 IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); 00932 IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_OCTET_STRING); 00933 parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); 00934 IF_PARSE_ASSERT(parent_tlv_value_len > 0); 00935 00936 IF_PARSE_EXEC(snmp_asn1_dec_raw(&pbuf_stream, tlv.value_len, request->msg_privacy_parameters, 00937 &u16_value, SNMP_V3_MAX_PRIV_PARAM_LENGTH)); 00938 request->msg_privacy_parameters_len = (u8_t)u16_value; 00939 00940 /* validate securityParameters here (do this after decoding because we don't want to increase other counters for wrong frames) 00941 * 1) securityParameters was correctly serialized if we reach here. 00942 * 2) securityParameters are already cached. 00943 * 3) if msgAuthoritativeEngineID is unknown, zero-length or too long: 00944 b) https://tools.ietf.org/html/rfc3414#section-7 00945 */ 00946 { 00947 const char *eid; 00948 u8_t eid_len; 00949 00950 snmpv3_get_engine_id(&eid, &eid_len); 00951 00952 if ((request->msg_authoritative_engine_id_len == 0) || 00953 (request->msg_authoritative_engine_id_len != eid_len) || 00954 (memcmp(eid, request->msg_authoritative_engine_id, eid_len) != 0)) { 00955 snmp_stats.unknownengineids++; 00956 request->msg_flags = 0; /* noauthnopriv */ 00957 request->error_status = SNMP_ERR_UNKNOWN_ENGINEID; 00958 return ERR_OK; 00959 } 00960 } 00961 00962 /* 4) verify username */ 00963 if (snmpv3_get_user((char *)request->msg_user_name, &auth, NULL, &priv, NULL)) { 00964 snmp_stats.unknownusernames++; 00965 request->msg_flags = 0; /* noauthnopriv */ 00966 request->error_status = SNMP_ERR_UNKNOWN_SECURITYNAME; 00967 return ERR_OK; 00968 } 00969 00970 /* 5) verify security level */ 00971 switch (request->msg_flags & (SNMP_V3_AUTH_FLAG | SNMP_V3_PRIV_FLAG)) { 00972 case SNMP_V3_NOAUTHNOPRIV: 00973 if ((auth != SNMP_V3_AUTH_ALGO_INVAL) || (priv != SNMP_V3_PRIV_ALGO_INVAL)) { 00974 /* Invalid security level for user */ 00975 snmp_stats.unsupportedseclevels++; 00976 request->msg_flags = SNMP_V3_NOAUTHNOPRIV; 00977 request->error_status = SNMP_ERR_UNSUPPORTED_SECLEVEL; 00978 return ERR_OK; 00979 } 00980 break; 00981 #if LWIP_SNMP_V3_CRYPTO 00982 case SNMP_V3_AUTHNOPRIV: 00983 if ((auth == SNMP_V3_AUTH_ALGO_INVAL) || (priv != SNMP_V3_PRIV_ALGO_INVAL)) { 00984 /* Invalid security level for user */ 00985 snmp_stats.unsupportedseclevels++; 00986 request->msg_flags = SNMP_V3_NOAUTHNOPRIV; 00987 request->error_status = SNMP_ERR_UNSUPPORTED_SECLEVEL; 00988 return ERR_OK; 00989 } 00990 break; 00991 case SNMP_V3_AUTHPRIV: 00992 if ((auth == SNMP_V3_AUTH_ALGO_INVAL) || (priv == SNMP_V3_PRIV_ALGO_INVAL)) { 00993 /* Invalid security level for user */ 00994 snmp_stats.unsupportedseclevels++; 00995 request->msg_flags = SNMP_V3_NOAUTHNOPRIV; 00996 request->error_status = SNMP_ERR_UNSUPPORTED_SECLEVEL; 00997 return ERR_OK; 00998 } 00999 break; 01000 #endif 01001 default: 01002 snmp_stats.unsupportedseclevels++; 01003 request->msg_flags = SNMP_V3_NOAUTHNOPRIV; 01004 request->error_status = SNMP_ERR_UNSUPPORTED_SECLEVEL; 01005 return ERR_OK; 01006 } 01007 01008 /* 6) if securitylevel specifies authentication, authenticate message. */ 01009 #if LWIP_SNMP_V3_CRYPTO 01010 if (request->msg_flags & SNMP_V3_AUTH_FLAG) { 01011 const u8_t zero_arr[SNMP_V3_MAX_AUTH_PARAM_LENGTH] = { 0 }; 01012 u8_t key[20]; 01013 u8_t hmac[LWIP_MAX(SNMP_V3_SHA_LEN, SNMP_V3_MD5_LEN)]; 01014 struct snmp_pbuf_stream auth_stream; 01015 01016 if (request->msg_authentication_parameters_len > SNMP_V3_MAX_AUTH_PARAM_LENGTH) { 01017 snmp_stats.wrongdigests++; 01018 request->msg_flags = SNMP_V3_NOAUTHNOPRIV; 01019 request->error_status = SNMP_ERR_AUTHORIZATIONERROR; 01020 return ERR_OK; 01021 } 01022 01023 /* Rewind stream */ 01024 IF_PARSE_EXEC(snmp_pbuf_stream_init(&auth_stream, request->inbound_pbuf, 0, request->inbound_pbuf->tot_len)); 01025 IF_PARSE_EXEC(snmp_pbuf_stream_seek_abs(&auth_stream, inbound_msgAuthenticationParameters_offset)); 01026 /* Set auth parameters to zero for verification */ 01027 IF_PARSE_EXEC(snmp_asn1_enc_raw(&auth_stream, zero_arr, request->msg_authentication_parameters_len)); 01028 01029 /* Verify authentication */ 01030 IF_PARSE_EXEC(snmp_pbuf_stream_init(&auth_stream, request->inbound_pbuf, 0, request->inbound_pbuf->tot_len)); 01031 01032 IF_PARSE_EXEC(snmpv3_get_user((char *)request->msg_user_name, &auth, key, NULL, NULL)); 01033 IF_PARSE_EXEC(snmpv3_auth(&auth_stream, request->inbound_pbuf->tot_len, key, auth, hmac)); 01034 01035 if (memcmp(request->msg_authentication_parameters, hmac, SNMP_V3_MAX_AUTH_PARAM_LENGTH)) { 01036 snmp_stats.wrongdigests++; 01037 request->msg_flags = SNMP_V3_NOAUTHNOPRIV; 01038 request->error_status = SNMP_ERR_AUTHORIZATIONERROR; 01039 return ERR_OK; 01040 } 01041 01042 /* 7) if securitylevel specifies authentication, verify engineboots, enginetime and lastenginetime */ 01043 { 01044 s32_t boots = snmpv3_get_engine_boots_internal(); 01045 if ((request->msg_authoritative_engine_boots != boots) || (boots == 2147483647UL)) { 01046 snmp_stats.notintimewindows++; 01047 request->msg_flags = SNMP_V3_AUTHNOPRIV; 01048 request->error_status = SNMP_ERR_NOTINTIMEWINDOW; 01049 return ERR_OK; 01050 } 01051 } 01052 { 01053 s32_t time = snmpv3_get_engine_time_internal(); 01054 if (request->msg_authoritative_engine_time > (time + 150)) { 01055 snmp_stats.notintimewindows++; 01056 request->msg_flags = SNMP_V3_AUTHNOPRIV; 01057 request->error_status = SNMP_ERR_NOTINTIMEWINDOW; 01058 return ERR_OK; 01059 } else if (time > 150) { 01060 if (request->msg_authoritative_engine_time < (time - 150)) { 01061 snmp_stats.notintimewindows++; 01062 request->msg_flags = SNMP_V3_AUTHNOPRIV; 01063 request->error_status = SNMP_ERR_NOTINTIMEWINDOW; 01064 return ERR_OK; 01065 } 01066 } 01067 } 01068 } 01069 #endif 01070 01071 /* 8) if securitylevel specifies privacy, decrypt message. */ 01072 #if LWIP_SNMP_V3_CRYPTO 01073 if (request->msg_flags & SNMP_V3_PRIV_FLAG) { 01074 /* Decrypt message */ 01075 01076 u8_t key[20]; 01077 01078 IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); 01079 IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_OCTET_STRING); 01080 parent_tlv_value_len -= SNMP_ASN1_TLV_HDR_LENGTH(tlv); 01081 IF_PARSE_ASSERT(parent_tlv_value_len > 0); 01082 01083 IF_PARSE_EXEC(snmpv3_get_user((char *)request->msg_user_name, NULL, NULL, &priv, key)); 01084 if (snmpv3_crypt(&pbuf_stream, tlv.value_len, key, 01085 request->msg_privacy_parameters, request->msg_authoritative_engine_boots, 01086 request->msg_authoritative_engine_time, priv, SNMP_V3_PRIV_MODE_DECRYPT) != ERR_OK) { 01087 snmp_stats.decryptionerrors++; 01088 request->msg_flags = SNMP_V3_AUTHNOPRIV; 01089 request->error_status = SNMP_ERR_DECRYIPTION_ERROR; 01090 return ERR_OK; 01091 } 01092 } 01093 #endif 01094 /* 9) calculate max size of scoped pdu? 01095 * 10) securityname for user is retrieved from usertable? 01096 * 11) security data is cached? 01097 * 12) 01098 */ 01099 01100 /* Scoped PDU 01101 * Encryption context 01102 */ 01103 IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); 01104 IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_SEQUENCE); 01105 parent_tlv_value_len -= SNMP_ASN1_TLV_HDR_LENGTH(tlv); 01106 IF_PARSE_ASSERT(parent_tlv_value_len > 0); 01107 01108 /* contextEngineID */ 01109 IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); 01110 IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_OCTET_STRING); 01111 parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); 01112 IF_PARSE_ASSERT(parent_tlv_value_len > 0); 01113 01114 IF_PARSE_EXEC(snmp_asn1_dec_raw(&pbuf_stream, tlv.value_len, request->context_engine_id, 01115 &u16_value, SNMP_V3_MAX_ENGINE_ID_LENGTH)); 01116 request->context_engine_id_len = (u8_t)u16_value; 01117 /* TODO: do we need to verify this contextengineid too? */ 01118 01119 /* contextName */ 01120 IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); 01121 IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_OCTET_STRING); 01122 parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); 01123 IF_PARSE_ASSERT(parent_tlv_value_len > 0); 01124 01125 IF_PARSE_EXEC(snmp_asn1_dec_raw(&pbuf_stream, tlv.value_len, request->context_name, 01126 &u16_value, SNMP_V3_MAX_ENGINE_ID_LENGTH)); 01127 request->context_name_len = (u8_t)u16_value; 01128 /* TODO: do we need to verify this contextname too? */ 01129 } else 01130 #endif 01131 { 01132 /* decode community */ 01133 IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); 01134 IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_OCTET_STRING); 01135 parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); 01136 IF_PARSE_ASSERT(parent_tlv_value_len > 0); 01137 01138 err = snmp_asn1_dec_raw(&pbuf_stream, tlv.value_len, request->community, &request->community_strlen, SNMP_MAX_COMMUNITY_STR_LEN); 01139 if (err == ERR_MEM) { 01140 /* community string does not fit in our buffer -> its too long -> its invalid */ 01141 request->community_strlen = 0; 01142 snmp_pbuf_stream_seek(&pbuf_stream, tlv.value_len); 01143 } else { 01144 IF_PARSE_ASSERT(err == ERR_OK); 01145 } 01146 /* add zero terminator */ 01147 request->community[request->community_strlen] = 0; 01148 } 01149 01150 /* decode PDU type (next container level) */ 01151 IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); 01152 IF_PARSE_ASSERT(tlv.value_len <= pbuf_stream.length); 01153 request->inbound_padding_len = pbuf_stream.length - tlv.value_len; 01154 parent_tlv_value_len = tlv.value_len; 01155 01156 /* validate PDU type */ 01157 switch (tlv.type) { 01158 case (SNMP_ASN1_CLASS_CONTEXT | SNMP_ASN1_CONTENTTYPE_CONSTRUCTED | SNMP_ASN1_CONTEXT_PDU_GET_REQ): 01159 /* GetRequest PDU */ 01160 snmp_stats.ingetrequests++; 01161 break; 01162 case (SNMP_ASN1_CLASS_CONTEXT | SNMP_ASN1_CONTENTTYPE_CONSTRUCTED | SNMP_ASN1_CONTEXT_PDU_GET_NEXT_REQ): 01163 /* GetNextRequest PDU */ 01164 snmp_stats.ingetnexts++; 01165 break; 01166 case (SNMP_ASN1_CLASS_CONTEXT | SNMP_ASN1_CONTENTTYPE_CONSTRUCTED | SNMP_ASN1_CONTEXT_PDU_GET_BULK_REQ): 01167 /* GetBulkRequest PDU */ 01168 if (request->version < SNMP_VERSION_2c) { 01169 /* RFC2089: invalid, drop packet */ 01170 return ERR_ARG; 01171 } 01172 break; 01173 case (SNMP_ASN1_CLASS_CONTEXT | SNMP_ASN1_CONTENTTYPE_CONSTRUCTED | SNMP_ASN1_CONTEXT_PDU_SET_REQ): 01174 /* SetRequest PDU */ 01175 snmp_stats.insetrequests++; 01176 break; 01177 default: 01178 /* unsupported input PDU for this agent (no parse error) */ 01179 LWIP_DEBUGF(SNMP_DEBUG, ("Unknown/Invalid SNMP PDU type received: %d", tlv.type)); \ 01180 return ERR_ARG; 01181 } 01182 request->request_type = tlv.type & SNMP_ASN1_DATATYPE_MASK; 01183 request->request_out_type = (SNMP_ASN1_CLASS_CONTEXT | SNMP_ASN1_CONTENTTYPE_CONSTRUCTED | SNMP_ASN1_CONTEXT_PDU_GET_RESP); 01184 01185 /* validate community (do this after decoding PDU type because we don't want to increase 'inbadcommunitynames' for wrong frame types */ 01186 if (request->community_strlen == 0) { 01187 /* community string was too long or really empty*/ 01188 snmp_stats.inbadcommunitynames++; 01189 snmp_authfail_trap(); 01190 return ERR_ARG; 01191 } else if (request->request_type == SNMP_ASN1_CONTEXT_PDU_SET_REQ) { 01192 if (snmp_community_write[0] == 0) { 01193 /* our write community is empty, that means all our objects are readonly */ 01194 request->error_status = SNMP_ERR_NOTWRITABLE; 01195 request->error_index = 1; 01196 } else if (strncmp(snmp_community_write, (const char *)request->community, SNMP_MAX_COMMUNITY_STR_LEN) != 0) { 01197 /* community name does not match */ 01198 snmp_stats.inbadcommunitynames++; 01199 snmp_authfail_trap(); 01200 return ERR_ARG; 01201 } 01202 } else { 01203 if (strncmp(snmp_community, (const char *)request->community, SNMP_MAX_COMMUNITY_STR_LEN) != 0) { 01204 /* community name does not match */ 01205 snmp_stats.inbadcommunitynames++; 01206 snmp_authfail_trap(); 01207 return ERR_ARG; 01208 } 01209 } 01210 01211 /* decode request ID */ 01212 IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); 01213 IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_INTEGER); 01214 parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); 01215 IF_PARSE_ASSERT(parent_tlv_value_len > 0); 01216 01217 IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &request->request_id)); 01218 01219 /* decode error status / non-repeaters */ 01220 IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); 01221 IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_INTEGER); 01222 parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); 01223 IF_PARSE_ASSERT(parent_tlv_value_len > 0); 01224 01225 if (request->request_type == SNMP_ASN1_CONTEXT_PDU_GET_BULK_REQ) { 01226 IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &request->non_repeaters)); 01227 if (request->non_repeaters < 0) { 01228 /* RFC 1905, 4.2.3 */ 01229 request->non_repeaters = 0; 01230 } 01231 } else { 01232 /* only check valid value, don't touch 'request->error_status', maybe a response error status was already set to above; */ 01233 IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &s32_value)); 01234 IF_PARSE_ASSERT(s32_value == SNMP_ERR_NOERROR); 01235 } 01236 01237 /* decode error index / max-repetitions */ 01238 IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); 01239 IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_INTEGER); 01240 parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); 01241 IF_PARSE_ASSERT(parent_tlv_value_len > 0); 01242 01243 if (request->request_type == SNMP_ASN1_CONTEXT_PDU_GET_BULK_REQ) { 01244 IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &request->max_repetitions)); 01245 if (request->max_repetitions < 0) { 01246 /* RFC 1905, 4.2.3 */ 01247 request->max_repetitions = 0; 01248 } 01249 } else { 01250 IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &request->error_index)); 01251 IF_PARSE_ASSERT(s32_value == 0); 01252 } 01253 01254 /* decode varbind-list type (next container level) */ 01255 IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); 01256 IF_PARSE_ASSERT((tlv.type == SNMP_ASN1_TYPE_SEQUENCE) && (tlv.value_len <= pbuf_stream.length)); 01257 01258 request->inbound_varbind_offset = pbuf_stream.offset; 01259 request->inbound_varbind_len = pbuf_stream.length - request->inbound_padding_len; 01260 snmp_vb_enumerator_init(&(request->inbound_varbind_enumerator), request->inbound_pbuf, request->inbound_varbind_offset, request->inbound_varbind_len); 01261 01262 return ERR_OK; 01263 } 01264 01265 #define OF_BUILD_EXEC(code) BUILD_EXEC(code, ERR_ARG) 01266 01267 static err_t 01268 snmp_prepare_outbound_frame(struct snmp_request *request) 01269 { 01270 struct snmp_asn1_tlv tlv; 01271 struct snmp_pbuf_stream *pbuf_stream = &(request->outbound_pbuf_stream); 01272 01273 /* try allocating pbuf(s) for maximum response size */ 01274 request->outbound_pbuf = pbuf_alloc(PBUF_TRANSPORT, 1472, PBUF_RAM); 01275 if (request->outbound_pbuf == NULL) { 01276 return ERR_MEM; 01277 } 01278 01279 snmp_pbuf_stream_init(pbuf_stream, request->outbound_pbuf, 0, request->outbound_pbuf->tot_len); 01280 01281 /* 'Message' sequence */ 01282 SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 3, 0); 01283 OF_BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) ); 01284 01285 /* version */ 01286 SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 0); 01287 snmp_asn1_enc_s32t_cnt(request->version, &tlv.value_len); 01288 OF_BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) ); 01289 OF_BUILD_EXEC( snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, request->version) ); 01290 01291 #if LWIP_SNMP_V3 01292 if (request->version < SNMP_VERSION_3) { 01293 #endif 01294 /* community */ 01295 SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 0, request->community_strlen); 01296 OF_BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) ); 01297 OF_BUILD_EXEC( snmp_asn1_enc_raw(pbuf_stream, request->community, request->community_strlen) ); 01298 #if LWIP_SNMP_V3 01299 } else { 01300 const char *id; 01301 01302 /* globalData */ 01303 request->outbound_msg_global_data_offset = pbuf_stream->offset; 01304 SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 1, 0); 01305 OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); 01306 01307 /* msgID */ 01308 SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 1); 01309 snmp_asn1_enc_s32t_cnt(request->msg_id, &tlv.value_len); 01310 OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); 01311 OF_BUILD_EXEC(snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, request->msg_id)); 01312 01313 /* msgMaxSize */ 01314 SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 1); 01315 snmp_asn1_enc_s32t_cnt(request->msg_max_size, &tlv.value_len); 01316 OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); 01317 OF_BUILD_EXEC(snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, request->msg_max_size)); 01318 01319 /* msgFlags */ 01320 SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 0, 1); 01321 OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); 01322 OF_BUILD_EXEC(snmp_asn1_enc_raw(pbuf_stream, &request->msg_flags, 1)); 01323 01324 /* msgSecurityModel */ 01325 SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 1); 01326 snmp_asn1_enc_s32t_cnt(request->msg_security_model, &tlv.value_len); 01327 OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); 01328 OF_BUILD_EXEC(snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, request->msg_security_model)); 01329 01330 /* end of msgGlobalData */ 01331 request->outbound_msg_global_data_end = pbuf_stream->offset; 01332 01333 /* msgSecurityParameters */ 01334 request->outbound_msg_security_parameters_str_offset = pbuf_stream->offset; 01335 SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 1, 0); 01336 OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); 01337 01338 request->outbound_msg_security_parameters_seq_offset = pbuf_stream->offset; 01339 SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 1, 0); 01340 OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); 01341 01342 /* msgAuthoritativeEngineID */ 01343 snmpv3_get_engine_id(&id, &request->msg_authoritative_engine_id_len); 01344 MEMCPY(request->msg_authoritative_engine_id, id, request->msg_authoritative_engine_id_len); 01345 SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 0, request->msg_authoritative_engine_id_len); 01346 OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); 01347 OF_BUILD_EXEC(snmp_asn1_enc_raw(pbuf_stream, request->msg_authoritative_engine_id, request->msg_authoritative_engine_id_len)); 01348 01349 request->msg_authoritative_engine_time = snmpv3_get_engine_time(); 01350 request->msg_authoritative_engine_boots = snmpv3_get_engine_boots(); 01351 01352 /* msgAuthoritativeEngineBoots */ 01353 SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 0); 01354 snmp_asn1_enc_s32t_cnt(request->msg_authoritative_engine_boots, &tlv.value_len); 01355 OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); 01356 OF_BUILD_EXEC(snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, request->msg_authoritative_engine_boots)); 01357 01358 /* msgAuthoritativeEngineTime */ 01359 SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 0); 01360 snmp_asn1_enc_s32t_cnt(request->msg_authoritative_engine_time, &tlv.value_len); 01361 OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); 01362 OF_BUILD_EXEC(snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, request->msg_authoritative_engine_time)); 01363 01364 /* msgUserName */ 01365 SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 0, request->msg_user_name_len); 01366 OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); 01367 OF_BUILD_EXEC(snmp_asn1_enc_raw(pbuf_stream, request->msg_user_name, request->msg_user_name_len)); 01368 01369 #if LWIP_SNMP_V3_CRYPTO 01370 /* msgAuthenticationParameters */ 01371 if (request->msg_flags & SNMP_V3_AUTH_FLAG) { 01372 memset(request->msg_authentication_parameters, 0, SNMP_V3_MAX_AUTH_PARAM_LENGTH); 01373 request->outbound_msg_authentication_parameters_offset = pbuf_stream->offset; 01374 SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 1, SNMP_V3_MAX_AUTH_PARAM_LENGTH); 01375 OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); 01376 OF_BUILD_EXEC(snmp_asn1_enc_raw(pbuf_stream, request->msg_authentication_parameters, SNMP_V3_MAX_AUTH_PARAM_LENGTH)); 01377 } else 01378 #endif 01379 { 01380 SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 0, 0); 01381 OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); 01382 } 01383 01384 #if LWIP_SNMP_V3_CRYPTO 01385 /* msgPrivacyParameters */ 01386 if (request->msg_flags & SNMP_V3_PRIV_FLAG) { 01387 snmpv3_build_priv_param(request->msg_privacy_parameters); 01388 01389 SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 0, SNMP_V3_MAX_PRIV_PARAM_LENGTH); 01390 OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); 01391 OF_BUILD_EXEC(snmp_asn1_enc_raw(pbuf_stream, request->msg_privacy_parameters, SNMP_V3_MAX_PRIV_PARAM_LENGTH)); 01392 } else 01393 #endif 01394 { 01395 SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 0, 0); 01396 OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv) ); 01397 } 01398 01399 /* End of msgSecurityParameters, so we can calculate the length of this sequence later */ 01400 request->outbound_msg_security_parameters_end = pbuf_stream->offset; 01401 01402 #if LWIP_SNMP_V3_CRYPTO 01403 /* For encryption we have to encapsulate the payload in an octet string */ 01404 if (request->msg_flags & SNMP_V3_PRIV_FLAG) { 01405 request->outbound_scoped_pdu_string_offset = pbuf_stream->offset; 01406 SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 3, 0); 01407 OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); 01408 } 01409 #endif 01410 /* Scoped PDU 01411 * Encryption context 01412 */ 01413 request->outbound_scoped_pdu_seq_offset = pbuf_stream->offset; 01414 SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 3, 0); 01415 OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); 01416 01417 /* contextEngineID */ 01418 snmpv3_get_engine_id(&id, &request->context_engine_id_len); 01419 MEMCPY(request->context_engine_id, id, request->context_engine_id_len); 01420 SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 0, request->context_engine_id_len); 01421 OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); 01422 OF_BUILD_EXEC(snmp_asn1_enc_raw(pbuf_stream, request->context_engine_id, request->context_engine_id_len)); 01423 01424 /* contextName */ 01425 SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 0, request->context_name_len); 01426 OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); 01427 OF_BUILD_EXEC(snmp_asn1_enc_raw(pbuf_stream, request->context_name, request->context_name_len)); 01428 } 01429 #endif 01430 01431 /* 'PDU' sequence */ 01432 request->outbound_pdu_offset = pbuf_stream->offset; 01433 SNMP_ASN1_SET_TLV_PARAMS(tlv, request->request_out_type, 3, 0); 01434 OF_BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) ); 01435 01436 /* request ID */ 01437 SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 0); 01438 snmp_asn1_enc_s32t_cnt(request->request_id, &tlv.value_len); 01439 OF_BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) ); 01440 OF_BUILD_EXEC( snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, request->request_id) ); 01441 01442 /* error status */ 01443 SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 1); 01444 OF_BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) ); 01445 request->outbound_error_status_offset = pbuf_stream->offset; 01446 OF_BUILD_EXEC( snmp_pbuf_stream_write(pbuf_stream, 0) ); 01447 01448 /* error index */ 01449 SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 1); 01450 OF_BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) ); 01451 request->outbound_error_index_offset = pbuf_stream->offset; 01452 OF_BUILD_EXEC( snmp_pbuf_stream_write(pbuf_stream, 0) ); 01453 01454 /* 'VarBindList' sequence */ 01455 SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 3, 0); 01456 OF_BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) ); 01457 01458 request->outbound_varbind_offset = pbuf_stream->offset; 01459 01460 return ERR_OK; 01461 } 01462 01463 /** Calculate the length of a varbind list */ 01464 err_t 01465 snmp_varbind_length(struct snmp_varbind *varbind, struct snmp_varbind_len *len) 01466 { 01467 /* calculate required lengths */ 01468 snmp_asn1_enc_oid_cnt(varbind->oid.id, varbind->oid.len, &len->oid_value_len); 01469 snmp_asn1_enc_length_cnt(len->oid_value_len, &len->oid_len_len); 01470 01471 if (varbind->value_len == 0) { 01472 len->value_value_len = 0; 01473 } else if (varbind->value_len & SNMP_GET_VALUE_RAW_DATA) { 01474 len->value_value_len = varbind->value_len & (~SNMP_GET_VALUE_RAW_DATA); 01475 } else { 01476 switch (varbind->type) { 01477 case SNMP_ASN1_TYPE_INTEGER: 01478 if (varbind->value_len != sizeof (s32_t)) { 01479 return ERR_VAL; 01480 } 01481 snmp_asn1_enc_s32t_cnt(*((s32_t *) varbind->value), &len->value_value_len); 01482 break; 01483 case SNMP_ASN1_TYPE_COUNTER: 01484 case SNMP_ASN1_TYPE_GAUGE: 01485 case SNMP_ASN1_TYPE_TIMETICKS: 01486 if (varbind->value_len != sizeof (u32_t)) { 01487 return ERR_VAL; 01488 } 01489 snmp_asn1_enc_u32t_cnt(*((u32_t *) varbind->value), &len->value_value_len); 01490 break; 01491 case SNMP_ASN1_TYPE_OCTET_STRING: 01492 case SNMP_ASN1_TYPE_IPADDR: 01493 case SNMP_ASN1_TYPE_OPAQUE: 01494 len->value_value_len = varbind->value_len; 01495 break; 01496 case SNMP_ASN1_TYPE_NULL: 01497 if (varbind->value_len != 0) { 01498 return ERR_VAL; 01499 } 01500 len->value_value_len = 0; 01501 break; 01502 case SNMP_ASN1_TYPE_OBJECT_ID: 01503 if ((varbind->value_len & 0x03) != 0) { 01504 return ERR_VAL; 01505 } 01506 snmp_asn1_enc_oid_cnt((u32_t *) varbind->value, varbind->value_len >> 2, &len->value_value_len); 01507 break; 01508 #if LWIP_HAVE_INT64 01509 case SNMP_ASN1_TYPE_COUNTER64: 01510 if (varbind->value_len != sizeof(u64_t)) { 01511 return ERR_VAL; 01512 } 01513 snmp_asn1_enc_u64t_cnt(*(u64_t *)varbind->value, &len->value_value_len); 01514 break; 01515 #endif 01516 default: 01517 /* unsupported type */ 01518 return ERR_VAL; 01519 } 01520 } 01521 snmp_asn1_enc_length_cnt(len->value_value_len, &len->value_len_len); 01522 01523 len->vb_value_len = 1 + len->oid_len_len + len->oid_value_len + 1 + len->value_len_len + len->value_value_len; 01524 snmp_asn1_enc_length_cnt(len->vb_value_len, &len->vb_len_len); 01525 01526 return ERR_OK; 01527 } 01528 01529 #define OVB_BUILD_EXEC(code) BUILD_EXEC(code, ERR_ARG) 01530 01531 err_t 01532 snmp_append_outbound_varbind(struct snmp_pbuf_stream *pbuf_stream, struct snmp_varbind *varbind) 01533 { 01534 struct snmp_asn1_tlv tlv; 01535 struct snmp_varbind_len len; 01536 err_t err; 01537 01538 err = snmp_varbind_length(varbind, &len); 01539 01540 if (err != ERR_OK) { 01541 return err; 01542 } 01543 01544 /* check length already before adding first data because in case of GetBulk, 01545 * data added so far is returned and therefore no partial data shall be added 01546 */ 01547 if ((1 + len.vb_len_len + len.vb_value_len) > pbuf_stream->length) { 01548 return ERR_BUF; 01549 } 01550 01551 /* 'VarBind' sequence */ 01552 SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, len.vb_len_len, len.vb_value_len); 01553 OVB_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); 01554 01555 /* VarBind OID */ 01556 SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OBJECT_ID, len.oid_len_len, len.oid_value_len); 01557 OVB_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); 01558 OVB_BUILD_EXEC(snmp_asn1_enc_oid(pbuf_stream, varbind->oid.id, varbind->oid.len)); 01559 01560 /* VarBind value */ 01561 SNMP_ASN1_SET_TLV_PARAMS(tlv, varbind->type, len.value_len_len, len.value_value_len); 01562 OVB_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); 01563 01564 if (len.value_value_len > 0) { 01565 if (varbind->value_len & SNMP_GET_VALUE_RAW_DATA) { 01566 OVB_BUILD_EXEC(snmp_asn1_enc_raw(pbuf_stream, (u8_t *) varbind->value, len.value_value_len)); 01567 } else { 01568 switch (varbind->type) { 01569 case SNMP_ASN1_TYPE_INTEGER: 01570 OVB_BUILD_EXEC(snmp_asn1_enc_s32t(pbuf_stream, len.value_value_len, *((s32_t *) varbind->value))); 01571 break; 01572 case SNMP_ASN1_TYPE_COUNTER: 01573 case SNMP_ASN1_TYPE_GAUGE: 01574 case SNMP_ASN1_TYPE_TIMETICKS: 01575 OVB_BUILD_EXEC(snmp_asn1_enc_u32t(pbuf_stream, len.value_value_len, *((u32_t *) varbind->value))); 01576 break; 01577 case SNMP_ASN1_TYPE_OCTET_STRING: 01578 case SNMP_ASN1_TYPE_IPADDR: 01579 case SNMP_ASN1_TYPE_OPAQUE: 01580 OVB_BUILD_EXEC(snmp_asn1_enc_raw(pbuf_stream, (u8_t *) varbind->value, len.value_value_len)); 01581 len.value_value_len = varbind->value_len; 01582 break; 01583 case SNMP_ASN1_TYPE_OBJECT_ID: 01584 OVB_BUILD_EXEC(snmp_asn1_enc_oid(pbuf_stream, (u32_t *) varbind->value, varbind->value_len / sizeof (u32_t))); 01585 break; 01586 #if LWIP_HAVE_INT64 01587 case SNMP_ASN1_TYPE_COUNTER64: 01588 OVB_BUILD_EXEC(snmp_asn1_enc_u64t(pbuf_stream, len.value_value_len, *(u64_t *) varbind->value)); 01589 break; 01590 #endif 01591 default: 01592 LWIP_ASSERT("Unknown variable type", 0); 01593 break; 01594 } 01595 } 01596 } 01597 01598 return ERR_OK; 01599 } 01600 01601 static err_t 01602 snmp_complete_outbound_frame(struct snmp_request *request) 01603 { 01604 struct snmp_asn1_tlv tlv; 01605 u16_t frame_size; 01606 u8_t outbound_padding = 0; 01607 01608 if (request->version == SNMP_VERSION_1) { 01609 if (request->error_status != SNMP_ERR_NOERROR) { 01610 /* map v2c error codes to v1 compliant error code (according to RFC 2089) */ 01611 switch (request->error_status) { 01612 /* mapping of implementation specific "virtual" error codes 01613 * (during processing of frame we already stored them in error_status field, 01614 * so no need to check all varbinds here for those exceptions as suggested by RFC) */ 01615 case SNMP_ERR_NOSUCHINSTANCE: 01616 case SNMP_ERR_NOSUCHOBJECT: 01617 case SNMP_ERR_ENDOFMIBVIEW: 01618 request->error_status = SNMP_ERR_NOSUCHNAME; 01619 break; 01620 /* mapping according to RFC */ 01621 case SNMP_ERR_WRONGVALUE: 01622 case SNMP_ERR_WRONGENCODING: 01623 case SNMP_ERR_WRONGTYPE: 01624 case SNMP_ERR_WRONGLENGTH: 01625 case SNMP_ERR_INCONSISTENTVALUE: 01626 request->error_status = SNMP_ERR_BADVALUE; 01627 break; 01628 case SNMP_ERR_NOACCESS: 01629 case SNMP_ERR_NOTWRITABLE: 01630 case SNMP_ERR_NOCREATION: 01631 case SNMP_ERR_INCONSISTENTNAME: 01632 case SNMP_ERR_AUTHORIZATIONERROR: 01633 request->error_status = SNMP_ERR_NOSUCHNAME; 01634 break; 01635 case SNMP_ERR_RESOURCEUNAVAILABLE: 01636 case SNMP_ERR_COMMITFAILED: 01637 case SNMP_ERR_UNDOFAILED: 01638 default: 01639 request->error_status = SNMP_ERR_GENERROR; 01640 break; 01641 } 01642 } 01643 } else { 01644 if (request->request_type == SNMP_ASN1_CONTEXT_PDU_SET_REQ) { 01645 /* map error codes to according to RFC 1905 (4.2.5. The SetRequest-PDU) return 'NotWritable' for unknown OIDs) */ 01646 switch (request->error_status) { 01647 case SNMP_ERR_NOSUCHINSTANCE: 01648 case SNMP_ERR_NOSUCHOBJECT: 01649 case SNMP_ERR_ENDOFMIBVIEW: 01650 request->error_status = SNMP_ERR_NOTWRITABLE; 01651 break; 01652 default: 01653 break; 01654 } 01655 } 01656 01657 if (request->error_status >= SNMP_VARBIND_EXCEPTION_OFFSET) { 01658 /* should never occur because v2 frames store exceptions directly inside varbinds and not as frame error_status */ 01659 LWIP_DEBUGF(SNMP_DEBUG, ("snmp_complete_outbound_frame() > Found v2 request with varbind exception code stored as error status!\n")); 01660 return ERR_ARG; 01661 } 01662 } 01663 01664 if ((request->error_status != SNMP_ERR_NOERROR) || (request->request_type == SNMP_ASN1_CONTEXT_PDU_SET_REQ)) { 01665 /* all inbound vars are returned in response without any modification for error responses and successful set requests*/ 01666 struct snmp_pbuf_stream inbound_stream; 01667 OF_BUILD_EXEC( snmp_pbuf_stream_init(&inbound_stream, request->inbound_pbuf, request->inbound_varbind_offset, request->inbound_varbind_len) ); 01668 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) ); 01669 OF_BUILD_EXEC( snmp_pbuf_stream_writeto(&inbound_stream, &(request->outbound_pbuf_stream), 0) ); 01670 } 01671 01672 frame_size = request->outbound_pbuf_stream.offset; 01673 01674 #if LWIP_SNMP_V3 && LWIP_SNMP_V3_CRYPTO 01675 /* Calculate padding for encryption */ 01676 if (request->version == SNMP_VERSION_3 && (request->msg_flags & SNMP_V3_PRIV_FLAG)) { 01677 u8_t i; 01678 outbound_padding = (8 - (u8_t)((frame_size - request->outbound_scoped_pdu_seq_offset) & 0x07)) & 0x07; 01679 for (i = 0; i < outbound_padding; i++) { 01680 OF_BUILD_EXEC( snmp_pbuf_stream_write(&request->outbound_pbuf_stream, 0) ); 01681 } 01682 } 01683 #endif 01684 01685 /* complete missing length in 'Message' sequence ; 'Message' tlv is located at the beginning (offset 0) */ 01686 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()) */ 01687 OF_BUILD_EXEC( snmp_pbuf_stream_init(&(request->outbound_pbuf_stream), request->outbound_pbuf, 0, request->outbound_pbuf->tot_len) ); 01688 OF_BUILD_EXEC( snmp_ans1_enc_tlv(&(request->outbound_pbuf_stream), &tlv) ); 01689 01690 #if LWIP_SNMP_V3 01691 if (request->version == SNMP_VERSION_3) { 01692 /* complete missing length in 'globalData' sequence */ 01693 /* - type - length_len(fixed, see snmp_prepare_outbound_frame()) */ 01694 SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 1, request->outbound_msg_global_data_end 01695 - request->outbound_msg_global_data_offset - 1 - 1); 01696 OF_BUILD_EXEC(snmp_pbuf_stream_seek_abs(&(request->outbound_pbuf_stream), request->outbound_msg_global_data_offset)); 01697 OF_BUILD_EXEC(snmp_ans1_enc_tlv(&(request->outbound_pbuf_stream), &tlv)); 01698 01699 /* complete missing length in 'msgSecurityParameters' sequence */ 01700 SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 1, request->outbound_msg_security_parameters_end 01701 - request->outbound_msg_security_parameters_str_offset - 1 - 1); 01702 OF_BUILD_EXEC(snmp_pbuf_stream_seek_abs(&(request->outbound_pbuf_stream), request->outbound_msg_security_parameters_str_offset)); 01703 OF_BUILD_EXEC(snmp_ans1_enc_tlv(&(request->outbound_pbuf_stream), &tlv)); 01704 01705 SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 1, request->outbound_msg_security_parameters_end 01706 - request->outbound_msg_security_parameters_seq_offset - 1 - 1); 01707 OF_BUILD_EXEC(snmp_pbuf_stream_seek_abs(&(request->outbound_pbuf_stream), request->outbound_msg_security_parameters_seq_offset)); 01708 OF_BUILD_EXEC(snmp_ans1_enc_tlv(&(request->outbound_pbuf_stream), &tlv)); 01709 01710 /* complete missing length in scoped PDU sequence */ 01711 SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 3, frame_size - request->outbound_scoped_pdu_seq_offset - 1 - 3); 01712 OF_BUILD_EXEC(snmp_pbuf_stream_seek_abs(&(request->outbound_pbuf_stream), request->outbound_scoped_pdu_seq_offset)); 01713 OF_BUILD_EXEC(snmp_ans1_enc_tlv(&(request->outbound_pbuf_stream), &tlv)); 01714 } 01715 #endif 01716 01717 /* complete missing length in 'PDU' sequence */ 01718 SNMP_ASN1_SET_TLV_PARAMS(tlv, request->request_out_type, 3, 01719 frame_size - request->outbound_pdu_offset - 1 - 3); /* - type - length_len(fixed, see snmp_prepare_outbound_frame()) */ 01720 OF_BUILD_EXEC( snmp_pbuf_stream_seek_abs(&(request->outbound_pbuf_stream), request->outbound_pdu_offset) ); 01721 OF_BUILD_EXEC( snmp_ans1_enc_tlv(&(request->outbound_pbuf_stream), &tlv) ); 01722 01723 /* process and encode final error status */ 01724 if (request->error_status != 0) { 01725 u16_t len; 01726 snmp_asn1_enc_s32t_cnt(request->error_status, &len); 01727 if (len != 1) { 01728 /* error, we only reserved one byte for it */ 01729 return ERR_ARG; 01730 } 01731 OF_BUILD_EXEC( snmp_pbuf_stream_seek_abs(&(request->outbound_pbuf_stream), request->outbound_error_status_offset) ); 01732 OF_BUILD_EXEC( snmp_asn1_enc_s32t(&(request->outbound_pbuf_stream), len, request->error_status) ); 01733 01734 /* for compatibility to v1, log statistics; in v2 (RFC 1907) these statistics are obsoleted */ 01735 switch (request->error_status) { 01736 case SNMP_ERR_TOOBIG: 01737 snmp_stats.outtoobigs++; 01738 break; 01739 case SNMP_ERR_NOSUCHNAME: 01740 snmp_stats.outnosuchnames++; 01741 break; 01742 case SNMP_ERR_BADVALUE: 01743 snmp_stats.outbadvalues++; 01744 break; 01745 case SNMP_ERR_GENERROR: 01746 default: 01747 snmp_stats.outgenerrs++; 01748 break; 01749 } 01750 01751 if (request->error_status == SNMP_ERR_TOOBIG) { 01752 request->error_index = 0; /* defined by RFC 1157 */ 01753 } else if (request->error_index == 0) { 01754 /* set index to varbind where error occured (if not already set before, e.g. during GetBulk processing) */ 01755 request->error_index = request->inbound_varbind_enumerator.varbind_count; 01756 } 01757 } else { 01758 if (request->request_type == SNMP_ASN1_CONTEXT_PDU_SET_REQ) { 01759 snmp_stats.intotalsetvars += request->inbound_varbind_enumerator.varbind_count; 01760 } else { 01761 snmp_stats.intotalreqvars += request->inbound_varbind_enumerator.varbind_count; 01762 } 01763 } 01764 01765 /* encode final error index*/ 01766 if (request->error_index != 0) { 01767 u16_t len; 01768 snmp_asn1_enc_s32t_cnt(request->error_index, &len); 01769 if (len != 1) { 01770 /* error, we only reserved one byte for it */ 01771 return ERR_VAL; 01772 } 01773 OF_BUILD_EXEC( snmp_pbuf_stream_seek_abs(&(request->outbound_pbuf_stream), request->outbound_error_index_offset) ); 01774 OF_BUILD_EXEC( snmp_asn1_enc_s32t(&(request->outbound_pbuf_stream), len, request->error_index) ); 01775 } 01776 01777 /* complete missing length in 'VarBindList' sequence ; 'VarBindList' tlv is located directly before varbind offset */ 01778 SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 3, frame_size - request->outbound_varbind_offset); 01779 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()) */ 01780 OF_BUILD_EXEC( snmp_ans1_enc_tlv(&(request->outbound_pbuf_stream), &tlv) ); 01781 01782 /* Authenticate response */ 01783 #if LWIP_SNMP_V3 && LWIP_SNMP_V3_CRYPTO 01784 /* Encrypt response */ 01785 if (request->version == SNMP_VERSION_3 && (request->msg_flags & SNMP_V3_PRIV_FLAG)) { 01786 u8_t key[20]; 01787 snmpv3_priv_algo_t algo; 01788 01789 /* complete missing length in PDU sequence */ 01790 OF_BUILD_EXEC(snmp_pbuf_stream_init(&request->outbound_pbuf_stream, request->outbound_pbuf, 0, request->outbound_pbuf->tot_len)); 01791 OF_BUILD_EXEC(snmp_pbuf_stream_seek_abs(&(request->outbound_pbuf_stream), request->outbound_scoped_pdu_string_offset)); 01792 SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 3, frame_size + outbound_padding 01793 - request->outbound_scoped_pdu_string_offset - 1 - 3); 01794 OF_BUILD_EXEC(snmp_ans1_enc_tlv(&(request->outbound_pbuf_stream), &tlv)); 01795 01796 OF_BUILD_EXEC(snmpv3_get_user((char *)request->msg_user_name, NULL, NULL, &algo, key)); 01797 01798 OF_BUILD_EXEC(snmpv3_crypt(&request->outbound_pbuf_stream, tlv.value_len, key, 01799 request->msg_privacy_parameters, request->msg_authoritative_engine_boots, 01800 request->msg_authoritative_engine_time, algo, SNMP_V3_PRIV_MODE_ENCRYPT)); 01801 } 01802 01803 if (request->version == SNMP_VERSION_3 && (request->msg_flags & SNMP_V3_AUTH_FLAG)) { 01804 u8_t key[20]; 01805 snmpv3_auth_algo_t algo; 01806 u8_t hmac[20]; 01807 01808 OF_BUILD_EXEC(snmpv3_get_user((char *)request->msg_user_name, &algo, key, NULL, NULL)); 01809 OF_BUILD_EXEC(snmp_pbuf_stream_init(&(request->outbound_pbuf_stream), 01810 request->outbound_pbuf, 0, request->outbound_pbuf->tot_len)); 01811 OF_BUILD_EXEC(snmpv3_auth(&request->outbound_pbuf_stream, frame_size + outbound_padding, key, algo, hmac)); 01812 01813 MEMCPY(request->msg_authentication_parameters, hmac, SNMP_V3_MAX_AUTH_PARAM_LENGTH); 01814 OF_BUILD_EXEC(snmp_pbuf_stream_init(&request->outbound_pbuf_stream, 01815 request->outbound_pbuf, 0, request->outbound_pbuf->tot_len)); 01816 OF_BUILD_EXEC(snmp_pbuf_stream_seek_abs(&request->outbound_pbuf_stream, 01817 request->outbound_msg_authentication_parameters_offset)); 01818 01819 SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 1, SNMP_V3_MAX_AUTH_PARAM_LENGTH); 01820 OF_BUILD_EXEC(snmp_ans1_enc_tlv(&request->outbound_pbuf_stream, &tlv)); 01821 OF_BUILD_EXEC(snmp_asn1_enc_raw(&request->outbound_pbuf_stream, 01822 request->msg_authentication_parameters, SNMP_V3_MAX_AUTH_PARAM_LENGTH)); 01823 } 01824 #endif 01825 01826 pbuf_realloc(request->outbound_pbuf, frame_size + outbound_padding); 01827 01828 snmp_stats.outgetresponses++; 01829 snmp_stats.outpkts++; 01830 01831 return ERR_OK; 01832 } 01833 01834 static void 01835 snmp_execute_write_callbacks(struct snmp_request *request) 01836 { 01837 struct snmp_varbind_enumerator inbound_varbind_enumerator; 01838 struct snmp_varbind vb; 01839 01840 snmp_vb_enumerator_init(&inbound_varbind_enumerator, request->inbound_pbuf, request->inbound_varbind_offset, request->inbound_varbind_len); 01841 vb.value = NULL; /* do NOT decode value (we enumerate outbound buffer here, so all varbinds have values assigned, which we don't need here) */ 01842 01843 while (snmp_vb_enumerator_get_next(&inbound_varbind_enumerator, &vb) == SNMP_VB_ENUMERATOR_ERR_OK) { 01844 snmp_write_callback(vb.oid.id, vb.oid.len, snmp_write_callback_arg); 01845 } 01846 } 01847 01848 01849 /* ----------------------------------------------------------------------- */ 01850 /* VarBind enumerator methods */ 01851 /* ----------------------------------------------------------------------- */ 01852 01853 void 01854 snmp_vb_enumerator_init(struct snmp_varbind_enumerator *enumerator, struct pbuf *p, u16_t offset, u16_t length) 01855 { 01856 snmp_pbuf_stream_init(&(enumerator->pbuf_stream), p, offset, length); 01857 enumerator->varbind_count = 0; 01858 } 01859 01860 #define VB_PARSE_EXEC(code) PARSE_EXEC(code, SNMP_VB_ENUMERATOR_ERR_ASN1ERROR) 01861 #define VB_PARSE_ASSERT(code) PARSE_ASSERT(code, SNMP_VB_ENUMERATOR_ERR_ASN1ERROR) 01862 01863 snmp_vb_enumerator_err_t 01864 snmp_vb_enumerator_get_next(struct snmp_varbind_enumerator *enumerator, struct snmp_varbind *varbind) 01865 { 01866 struct snmp_asn1_tlv tlv; 01867 u16_t varbind_len; 01868 err_t err; 01869 01870 if (enumerator->pbuf_stream.length == 0) { 01871 return SNMP_VB_ENUMERATOR_ERR_EOVB; 01872 } 01873 enumerator->varbind_count++; 01874 01875 /* decode varbind itself (parent container of a varbind) */ 01876 VB_PARSE_EXEC(snmp_asn1_dec_tlv(&(enumerator->pbuf_stream), &tlv)); 01877 VB_PARSE_ASSERT((tlv.type == SNMP_ASN1_TYPE_SEQUENCE) && (tlv.value_len <= enumerator->pbuf_stream.length)); 01878 varbind_len = tlv.value_len; 01879 01880 /* decode varbind name (object id) */ 01881 VB_PARSE_EXEC(snmp_asn1_dec_tlv(&(enumerator->pbuf_stream), &tlv)); 01882 VB_PARSE_ASSERT((tlv.type == SNMP_ASN1_TYPE_OBJECT_ID) && (SNMP_ASN1_TLV_LENGTH(tlv) < varbind_len) && (tlv.value_len < enumerator->pbuf_stream.length)); 01883 01884 VB_PARSE_EXEC(snmp_asn1_dec_oid(&(enumerator->pbuf_stream), tlv.value_len, varbind->oid.id, &(varbind->oid.len), SNMP_MAX_OBJ_ID_LEN)); 01885 varbind_len -= SNMP_ASN1_TLV_LENGTH(tlv); 01886 01887 /* decode varbind value (object id) */ 01888 VB_PARSE_EXEC(snmp_asn1_dec_tlv(&(enumerator->pbuf_stream), &tlv)); 01889 VB_PARSE_ASSERT((SNMP_ASN1_TLV_LENGTH(tlv) == varbind_len) && (tlv.value_len <= enumerator->pbuf_stream.length)); 01890 varbind->type = tlv.type; 01891 01892 /* shall the value be decoded ? */ 01893 if (varbind->value != NULL) { 01894 switch (varbind->type) { 01895 case SNMP_ASN1_TYPE_INTEGER: 01896 VB_PARSE_EXEC(snmp_asn1_dec_s32t(&(enumerator->pbuf_stream), tlv.value_len, (s32_t *)varbind->value)); 01897 varbind->value_len = sizeof(s32_t); 01898 break; 01899 case SNMP_ASN1_TYPE_COUNTER: 01900 case SNMP_ASN1_TYPE_GAUGE: 01901 case SNMP_ASN1_TYPE_TIMETICKS: 01902 VB_PARSE_EXEC(snmp_asn1_dec_u32t(&(enumerator->pbuf_stream), tlv.value_len, (u32_t *)varbind->value)); 01903 varbind->value_len = sizeof(u32_t); 01904 break; 01905 case SNMP_ASN1_TYPE_OCTET_STRING: 01906 case SNMP_ASN1_TYPE_OPAQUE: 01907 err = snmp_asn1_dec_raw(&(enumerator->pbuf_stream), tlv.value_len, (u8_t *)varbind->value, &varbind->value_len, SNMP_MAX_VALUE_SIZE); 01908 if (err == ERR_MEM) { 01909 return SNMP_VB_ENUMERATOR_ERR_INVALIDLENGTH; 01910 } 01911 VB_PARSE_ASSERT(err == ERR_OK); 01912 break; 01913 case SNMP_ASN1_TYPE_NULL: 01914 varbind->value_len = 0; 01915 break; 01916 case SNMP_ASN1_TYPE_OBJECT_ID: 01917 /* misuse tlv.length_len as OID_length transporter */ 01918 err = snmp_asn1_dec_oid(&(enumerator->pbuf_stream), tlv.value_len, (u32_t *)varbind->value, &tlv.length_len, SNMP_MAX_OBJ_ID_LEN); 01919 if (err == ERR_MEM) { 01920 return SNMP_VB_ENUMERATOR_ERR_INVALIDLENGTH; 01921 } 01922 VB_PARSE_ASSERT(err == ERR_OK); 01923 varbind->value_len = tlv.length_len * sizeof(u32_t); 01924 break; 01925 case SNMP_ASN1_TYPE_IPADDR: 01926 if (tlv.value_len == 4) { 01927 /* must be exactly 4 octets! */ 01928 VB_PARSE_EXEC(snmp_asn1_dec_raw(&(enumerator->pbuf_stream), tlv.value_len, (u8_t *)varbind->value, &varbind->value_len, SNMP_MAX_VALUE_SIZE)); 01929 } else { 01930 VB_PARSE_ASSERT(0); 01931 } 01932 break; 01933 #if LWIP_HAVE_INT64 01934 case SNMP_ASN1_TYPE_COUNTER64: 01935 VB_PARSE_EXEC(snmp_asn1_dec_u64t(&(enumerator->pbuf_stream), tlv.value_len, (u64_t *)varbind->value)); 01936 varbind->value_len = sizeof(u64_t); 01937 break; 01938 #endif 01939 default: 01940 VB_PARSE_ASSERT(0); 01941 break; 01942 } 01943 } else { 01944 snmp_pbuf_stream_seek(&(enumerator->pbuf_stream), tlv.value_len); 01945 varbind->value_len = tlv.value_len; 01946 } 01947 01948 return SNMP_VB_ENUMERATOR_ERR_OK; 01949 } 01950 01951 #endif /* LWIP_SNMP */
Generated on Tue Jul 12 2022 13:54:30 by
