ON Semiconductor / mbed-os

Dependents:   mbed-TFT-example-NCS36510 mbed-Accelerometer-example-NCS36510 mbed-Accelerometer-example-NCS36510

Committer:
jacobjohnson
Date:
Mon Feb 27 17:45:05 2017 +0000
Revision:
1:f30bdcd2b33b
Parent:
0:098463de4c5d
changed the inputscale from 1 to 7 in analogin_api.c.  This will need to be changed later, and accessed from the main level, but for now this allows the  adc to read a value from 0 to 3.7V, instead of just up to 1V.;

Who changed what in which revision?

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