Used in Live Traffic Update Nokia LCD Display Project

Fork of NetServices by Segundo Equipo

Committer:
rrajan8
Date:
Wed Mar 06 19:07:23 2013 +0000
Revision:
8:92b57208ab99
Parent:
0:ac1725ba162c
This project utilizes mbed's networking features to display live traffic updates on the Nokia LCD using the MapQuest API's Traffic Web Service.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
segundo 0:ac1725ba162c 1 /**
segundo 0:ac1725ba162c 2 * @file
segundo 0:ac1725ba162c 3 * SNMP input message processing (RFC1157).
segundo 0:ac1725ba162c 4 */
segundo 0:ac1725ba162c 5
segundo 0:ac1725ba162c 6 /*
segundo 0:ac1725ba162c 7 * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands.
segundo 0:ac1725ba162c 8 * All rights reserved.
segundo 0:ac1725ba162c 9 *
segundo 0:ac1725ba162c 10 * Redistribution and use in source and binary forms, with or without modification,
segundo 0:ac1725ba162c 11 * are permitted provided that the following conditions are met:
segundo 0:ac1725ba162c 12 *
segundo 0:ac1725ba162c 13 * 1. Redistributions of source code must retain the above copyright notice,
segundo 0:ac1725ba162c 14 * this list of conditions and the following disclaimer.
segundo 0:ac1725ba162c 15 * 2. Redistributions in binary form must reproduce the above copyright notice,
segundo 0:ac1725ba162c 16 * this list of conditions and the following disclaimer in the documentation
segundo 0:ac1725ba162c 17 * and/or other materials provided with the distribution.
segundo 0:ac1725ba162c 18 * 3. The name of the author may not be used to endorse or promote products
segundo 0:ac1725ba162c 19 * derived from this software without specific prior written permission.
segundo 0:ac1725ba162c 20 *
segundo 0:ac1725ba162c 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
segundo 0:ac1725ba162c 22 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
segundo 0:ac1725ba162c 23 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
segundo 0:ac1725ba162c 24 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
segundo 0:ac1725ba162c 25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
segundo 0:ac1725ba162c 26 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
segundo 0:ac1725ba162c 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
segundo 0:ac1725ba162c 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
segundo 0:ac1725ba162c 29 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
segundo 0:ac1725ba162c 30 * OF SUCH DAMAGE.
segundo 0:ac1725ba162c 31 *
segundo 0:ac1725ba162c 32 * Author: Christiaan Simons <christiaan.simons@axon.tv>
segundo 0:ac1725ba162c 33 */
segundo 0:ac1725ba162c 34
segundo 0:ac1725ba162c 35 #include "lwip/opt.h"
segundo 0:ac1725ba162c 36
segundo 0:ac1725ba162c 37 #if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */
segundo 0:ac1725ba162c 38
segundo 0:ac1725ba162c 39 #include "lwip/snmp.h"
segundo 0:ac1725ba162c 40 #include "lwip/snmp_asn1.h"
segundo 0:ac1725ba162c 41 #include "lwip/snmp_msg.h"
segundo 0:ac1725ba162c 42 #include "lwip/snmp_structs.h"
segundo 0:ac1725ba162c 43 #include "lwip/ip_addr.h"
segundo 0:ac1725ba162c 44 #include "lwip/memp.h"
segundo 0:ac1725ba162c 45 #include "lwip/udp.h"
segundo 0:ac1725ba162c 46 #include "lwip/stats.h"
segundo 0:ac1725ba162c 47
segundo 0:ac1725ba162c 48 #include <string.h>
segundo 0:ac1725ba162c 49
segundo 0:ac1725ba162c 50 /* public (non-static) constants */
segundo 0:ac1725ba162c 51 /** SNMP v1 == 0 */
segundo 0:ac1725ba162c 52 const s32_t snmp_version = 0;
segundo 0:ac1725ba162c 53 /** default SNMP community string */
segundo 0:ac1725ba162c 54 const char snmp_publiccommunity[7] = "public";
segundo 0:ac1725ba162c 55
segundo 0:ac1725ba162c 56 /* statically allocated buffers for SNMP_CONCURRENT_REQUESTS */
segundo 0:ac1725ba162c 57 struct snmp_msg_pstat msg_input_list[SNMP_CONCURRENT_REQUESTS];
segundo 0:ac1725ba162c 58 /* UDP Protocol Control Block */
segundo 0:ac1725ba162c 59 struct udp_pcb *snmp1_pcb;
segundo 0:ac1725ba162c 60
segundo 0:ac1725ba162c 61 static void snmp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *addr, u16_t port);
segundo 0:ac1725ba162c 62 static err_t snmp_pdu_header_check(struct pbuf *p, u16_t ofs, u16_t pdu_len, u16_t *ofs_ret, struct snmp_msg_pstat *m_stat);
segundo 0:ac1725ba162c 63 static err_t snmp_pdu_dec_varbindlist(struct pbuf *p, u16_t ofs, u16_t *ofs_ret, struct snmp_msg_pstat *m_stat);
segundo 0:ac1725ba162c 64
segundo 0:ac1725ba162c 65
segundo 0:ac1725ba162c 66 /**
segundo 0:ac1725ba162c 67 * Starts SNMP Agent.
segundo 0:ac1725ba162c 68 * Allocates UDP pcb and binds it to IP_ADDR_ANY port 161.
segundo 0:ac1725ba162c 69 */
segundo 0:ac1725ba162c 70 void
segundo 0:ac1725ba162c 71 snmp_init(void)
segundo 0:ac1725ba162c 72 {
segundo 0:ac1725ba162c 73 struct snmp_msg_pstat *msg_ps;
segundo 0:ac1725ba162c 74 u8_t i;
segundo 0:ac1725ba162c 75
segundo 0:ac1725ba162c 76 snmp1_pcb = udp_new();
segundo 0:ac1725ba162c 77 if (snmp1_pcb != NULL)
segundo 0:ac1725ba162c 78 {
segundo 0:ac1725ba162c 79 udp_recv(snmp1_pcb, snmp_recv, (void *)SNMP_IN_PORT);
segundo 0:ac1725ba162c 80 udp_bind(snmp1_pcb, IP_ADDR_ANY, SNMP_IN_PORT);
segundo 0:ac1725ba162c 81 }
segundo 0:ac1725ba162c 82 msg_ps = &msg_input_list[0];
segundo 0:ac1725ba162c 83 for (i=0; i<SNMP_CONCURRENT_REQUESTS; i++)
segundo 0:ac1725ba162c 84 {
segundo 0:ac1725ba162c 85 msg_ps->state = SNMP_MSG_EMPTY;
segundo 0:ac1725ba162c 86 msg_ps->error_index = 0;
segundo 0:ac1725ba162c 87 msg_ps->error_status = SNMP_ES_NOERROR;
segundo 0:ac1725ba162c 88 msg_ps++;
segundo 0:ac1725ba162c 89 }
segundo 0:ac1725ba162c 90 trap_msg.pcb = snmp1_pcb;
segundo 0:ac1725ba162c 91
segundo 0:ac1725ba162c 92 #ifdef SNMP_PRIVATE_MIB_INIT
segundo 0:ac1725ba162c 93 /* If defined, rhis must be a function-like define to initialize the
segundo 0:ac1725ba162c 94 * private MIB after the stack has been initialized.
segundo 0:ac1725ba162c 95 * The private MIB can also be initialized in tcpip_callback (or after
segundo 0:ac1725ba162c 96 * the stack is initialized), this define is only for convenience. */
segundo 0:ac1725ba162c 97 SNMP_PRIVATE_MIB_INIT();
segundo 0:ac1725ba162c 98 #endif /* SNMP_PRIVATE_MIB_INIT */
segundo 0:ac1725ba162c 99
segundo 0:ac1725ba162c 100 /* The coldstart trap will only be output
segundo 0:ac1725ba162c 101 if our outgoing interface is up & configured */
segundo 0:ac1725ba162c 102 snmp_coldstart_trap();
segundo 0:ac1725ba162c 103 }
segundo 0:ac1725ba162c 104
segundo 0:ac1725ba162c 105 static void
segundo 0:ac1725ba162c 106 snmp_error_response(struct snmp_msg_pstat *msg_ps, u8_t error)
segundo 0:ac1725ba162c 107 {
segundo 0:ac1725ba162c 108 snmp_varbind_list_free(&msg_ps->outvb);
segundo 0:ac1725ba162c 109 msg_ps->outvb = msg_ps->invb;
segundo 0:ac1725ba162c 110 msg_ps->invb.head = NULL;
segundo 0:ac1725ba162c 111 msg_ps->invb.tail = NULL;
segundo 0:ac1725ba162c 112 msg_ps->invb.count = 0;
segundo 0:ac1725ba162c 113 msg_ps->error_status = error;
segundo 0:ac1725ba162c 114 msg_ps->error_index = 1 + msg_ps->vb_idx;
segundo 0:ac1725ba162c 115 snmp_send_response(msg_ps);
segundo 0:ac1725ba162c 116 snmp_varbind_list_free(&msg_ps->outvb);
segundo 0:ac1725ba162c 117 msg_ps->state = SNMP_MSG_EMPTY;
segundo 0:ac1725ba162c 118 }
segundo 0:ac1725ba162c 119
segundo 0:ac1725ba162c 120 static void
segundo 0:ac1725ba162c 121 snmp_ok_response(struct snmp_msg_pstat *msg_ps)
segundo 0:ac1725ba162c 122 {
segundo 0:ac1725ba162c 123 err_t err_ret;
segundo 0:ac1725ba162c 124
segundo 0:ac1725ba162c 125 err_ret = snmp_send_response(msg_ps);
segundo 0:ac1725ba162c 126 if (err_ret == ERR_MEM)
segundo 0:ac1725ba162c 127 {
segundo 0:ac1725ba162c 128 /* serious memory problem, can't return tooBig */
segundo 0:ac1725ba162c 129 }
segundo 0:ac1725ba162c 130 else
segundo 0:ac1725ba162c 131 {
segundo 0:ac1725ba162c 132 LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_msg_event = %"S32_F"\n",msg_ps->error_status));
segundo 0:ac1725ba162c 133 }
segundo 0:ac1725ba162c 134 /* free varbinds (if available) */
segundo 0:ac1725ba162c 135 snmp_varbind_list_free(&msg_ps->invb);
segundo 0:ac1725ba162c 136 snmp_varbind_list_free(&msg_ps->outvb);
segundo 0:ac1725ba162c 137 msg_ps->state = SNMP_MSG_EMPTY;
segundo 0:ac1725ba162c 138 }
segundo 0:ac1725ba162c 139
segundo 0:ac1725ba162c 140 /**
segundo 0:ac1725ba162c 141 * Service an internal or external event for SNMP GET.
segundo 0:ac1725ba162c 142 *
segundo 0:ac1725ba162c 143 * @param request_id identifies requests from 0 to (SNMP_CONCURRENT_REQUESTS-1)
segundo 0:ac1725ba162c 144 * @param msg_ps points to the assosicated message process state
segundo 0:ac1725ba162c 145 */
segundo 0:ac1725ba162c 146 static void
segundo 0:ac1725ba162c 147 snmp_msg_get_event(u8_t request_id, struct snmp_msg_pstat *msg_ps)
segundo 0:ac1725ba162c 148 {
segundo 0:ac1725ba162c 149 LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_msg_get_event: msg_ps->state==%"U16_F"\n",(u16_t)msg_ps->state));
segundo 0:ac1725ba162c 150
segundo 0:ac1725ba162c 151 if (msg_ps->state == SNMP_MSG_EXTERNAL_GET_OBJDEF)
segundo 0:ac1725ba162c 152 {
segundo 0:ac1725ba162c 153 struct mib_external_node *en;
segundo 0:ac1725ba162c 154 struct snmp_name_ptr np;
segundo 0:ac1725ba162c 155
segundo 0:ac1725ba162c 156 /* get_object_def() answer*/
segundo 0:ac1725ba162c 157 en = msg_ps->ext_mib_node;
segundo 0:ac1725ba162c 158 np = msg_ps->ext_name_ptr;
segundo 0:ac1725ba162c 159
segundo 0:ac1725ba162c 160 /* translate answer into a known lifeform */
segundo 0:ac1725ba162c 161 en->get_object_def_a(request_id, np.ident_len, np.ident, &msg_ps->ext_object_def);
segundo 0:ac1725ba162c 162 if ((msg_ps->ext_object_def.instance != MIB_OBJECT_NONE) &&
segundo 0:ac1725ba162c 163 (msg_ps->ext_object_def.access & MIB_ACCESS_READ))
segundo 0:ac1725ba162c 164 {
segundo 0:ac1725ba162c 165 msg_ps->state = SNMP_MSG_EXTERNAL_GET_VALUE;
segundo 0:ac1725ba162c 166 en->get_value_q(request_id, &msg_ps->ext_object_def);
segundo 0:ac1725ba162c 167 }
segundo 0:ac1725ba162c 168 else
segundo 0:ac1725ba162c 169 {
segundo 0:ac1725ba162c 170 en->get_object_def_pc(request_id, np.ident_len, np.ident);
segundo 0:ac1725ba162c 171 /* search failed, object id points to unknown object (nosuchname) */
segundo 0:ac1725ba162c 172 snmp_error_response(msg_ps,SNMP_ES_NOSUCHNAME);
segundo 0:ac1725ba162c 173 }
segundo 0:ac1725ba162c 174 }
segundo 0:ac1725ba162c 175 else if (msg_ps->state == SNMP_MSG_EXTERNAL_GET_VALUE)
segundo 0:ac1725ba162c 176 {
segundo 0:ac1725ba162c 177 struct mib_external_node *en;
segundo 0:ac1725ba162c 178 struct snmp_varbind *vb;
segundo 0:ac1725ba162c 179
segundo 0:ac1725ba162c 180 /* get_value() answer */
segundo 0:ac1725ba162c 181 en = msg_ps->ext_mib_node;
segundo 0:ac1725ba162c 182
segundo 0:ac1725ba162c 183 /* allocate output varbind */
segundo 0:ac1725ba162c 184 vb = (struct snmp_varbind *)memp_malloc(MEMP_SNMP_VARBIND);
segundo 0:ac1725ba162c 185 LWIP_ASSERT("vb != NULL",vb != NULL);
segundo 0:ac1725ba162c 186 if (vb != NULL)
segundo 0:ac1725ba162c 187 {
segundo 0:ac1725ba162c 188 vb->next = NULL;
segundo 0:ac1725ba162c 189 vb->prev = NULL;
segundo 0:ac1725ba162c 190
segundo 0:ac1725ba162c 191 /* move name from invb to outvb */
segundo 0:ac1725ba162c 192 vb->ident = msg_ps->vb_ptr->ident;
segundo 0:ac1725ba162c 193 vb->ident_len = msg_ps->vb_ptr->ident_len;
segundo 0:ac1725ba162c 194 /* ensure this memory is refereced once only */
segundo 0:ac1725ba162c 195 msg_ps->vb_ptr->ident = NULL;
segundo 0:ac1725ba162c 196 msg_ps->vb_ptr->ident_len = 0;
segundo 0:ac1725ba162c 197
segundo 0:ac1725ba162c 198 vb->value_type = msg_ps->ext_object_def.asn_type;
segundo 0:ac1725ba162c 199 LWIP_ASSERT("invalid length", msg_ps->ext_object_def.v_len <= 0xff);
segundo 0:ac1725ba162c 200 vb->value_len = (u8_t)msg_ps->ext_object_def.v_len;
segundo 0:ac1725ba162c 201 if (vb->value_len > 0)
segundo 0:ac1725ba162c 202 {
segundo 0:ac1725ba162c 203 LWIP_ASSERT("SNMP_MAX_OCTET_STRING_LEN is configured too low", vb->value_len <= SNMP_MAX_VALUE_SIZE);
segundo 0:ac1725ba162c 204 vb->value = memp_malloc(MEMP_SNMP_VALUE);
segundo 0:ac1725ba162c 205 LWIP_ASSERT("vb->value != NULL",vb->value != NULL);
segundo 0:ac1725ba162c 206 if (vb->value != NULL)
segundo 0:ac1725ba162c 207 {
segundo 0:ac1725ba162c 208 en->get_value_a(request_id, &msg_ps->ext_object_def, vb->value_len, vb->value);
segundo 0:ac1725ba162c 209 snmp_varbind_tail_add(&msg_ps->outvb, vb);
segundo 0:ac1725ba162c 210 /* search again (if vb_idx < msg_ps->invb.count) */
segundo 0:ac1725ba162c 211 msg_ps->state = SNMP_MSG_SEARCH_OBJ;
segundo 0:ac1725ba162c 212 msg_ps->vb_idx += 1;
segundo 0:ac1725ba162c 213 }
segundo 0:ac1725ba162c 214 else
segundo 0:ac1725ba162c 215 {
segundo 0:ac1725ba162c 216 en->get_value_pc(request_id, &msg_ps->ext_object_def);
segundo 0:ac1725ba162c 217 LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_msg_event: no variable space\n"));
segundo 0:ac1725ba162c 218 msg_ps->vb_ptr->ident = vb->ident;
segundo 0:ac1725ba162c 219 msg_ps->vb_ptr->ident_len = vb->ident_len;
segundo 0:ac1725ba162c 220 memp_free(MEMP_SNMP_VARBIND, vb);
segundo 0:ac1725ba162c 221 snmp_error_response(msg_ps,SNMP_ES_TOOBIG);
segundo 0:ac1725ba162c 222 }
segundo 0:ac1725ba162c 223 }
segundo 0:ac1725ba162c 224 else
segundo 0:ac1725ba162c 225 {
segundo 0:ac1725ba162c 226 /* vb->value_len == 0, empty value (e.g. empty string) */
segundo 0:ac1725ba162c 227 en->get_value_a(request_id, &msg_ps->ext_object_def, 0, NULL);
segundo 0:ac1725ba162c 228 vb->value = NULL;
segundo 0:ac1725ba162c 229 snmp_varbind_tail_add(&msg_ps->outvb, vb);
segundo 0:ac1725ba162c 230 /* search again (if vb_idx < msg_ps->invb.count) */
segundo 0:ac1725ba162c 231 msg_ps->state = SNMP_MSG_SEARCH_OBJ;
segundo 0:ac1725ba162c 232 msg_ps->vb_idx += 1;
segundo 0:ac1725ba162c 233 }
segundo 0:ac1725ba162c 234 }
segundo 0:ac1725ba162c 235 else
segundo 0:ac1725ba162c 236 {
segundo 0:ac1725ba162c 237 en->get_value_pc(request_id, &msg_ps->ext_object_def);
segundo 0:ac1725ba162c 238 LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_msg_event: no outvb space\n"));
segundo 0:ac1725ba162c 239 snmp_error_response(msg_ps,SNMP_ES_TOOBIG);
segundo 0:ac1725ba162c 240 }
segundo 0:ac1725ba162c 241 }
segundo 0:ac1725ba162c 242
segundo 0:ac1725ba162c 243 while ((msg_ps->state == SNMP_MSG_SEARCH_OBJ) &&
segundo 0:ac1725ba162c 244 (msg_ps->vb_idx < msg_ps->invb.count))
segundo 0:ac1725ba162c 245 {
segundo 0:ac1725ba162c 246 struct mib_node *mn;
segundo 0:ac1725ba162c 247 struct snmp_name_ptr np;
segundo 0:ac1725ba162c 248
segundo 0:ac1725ba162c 249 if (msg_ps->vb_idx == 0)
segundo 0:ac1725ba162c 250 {
segundo 0:ac1725ba162c 251 msg_ps->vb_ptr = msg_ps->invb.head;
segundo 0:ac1725ba162c 252 }
segundo 0:ac1725ba162c 253 else
segundo 0:ac1725ba162c 254 {
segundo 0:ac1725ba162c 255 msg_ps->vb_ptr = msg_ps->vb_ptr->next;
segundo 0:ac1725ba162c 256 }
segundo 0:ac1725ba162c 257 /** test object identifier for .iso.org.dod.internet prefix */
segundo 0:ac1725ba162c 258 if (snmp_iso_prefix_tst(msg_ps->vb_ptr->ident_len, msg_ps->vb_ptr->ident))
segundo 0:ac1725ba162c 259 {
segundo 0:ac1725ba162c 260 mn = snmp_search_tree((struct mib_node*)&internet, msg_ps->vb_ptr->ident_len - 4,
segundo 0:ac1725ba162c 261 msg_ps->vb_ptr->ident + 4, &np);
segundo 0:ac1725ba162c 262 if (mn != NULL)
segundo 0:ac1725ba162c 263 {
segundo 0:ac1725ba162c 264 if (mn->node_type == MIB_NODE_EX)
segundo 0:ac1725ba162c 265 {
segundo 0:ac1725ba162c 266 /* external object */
segundo 0:ac1725ba162c 267 struct mib_external_node *en = (struct mib_external_node*)mn;
segundo 0:ac1725ba162c 268
segundo 0:ac1725ba162c 269 msg_ps->state = SNMP_MSG_EXTERNAL_GET_OBJDEF;
segundo 0:ac1725ba162c 270 /* save en && args in msg_ps!! */
segundo 0:ac1725ba162c 271 msg_ps->ext_mib_node = en;
segundo 0:ac1725ba162c 272 msg_ps->ext_name_ptr = np;
segundo 0:ac1725ba162c 273
segundo 0:ac1725ba162c 274 en->get_object_def_q(en->addr_inf, request_id, np.ident_len, np.ident);
segundo 0:ac1725ba162c 275 }
segundo 0:ac1725ba162c 276 else
segundo 0:ac1725ba162c 277 {
segundo 0:ac1725ba162c 278 /* internal object */
segundo 0:ac1725ba162c 279 struct obj_def object_def;
segundo 0:ac1725ba162c 280
segundo 0:ac1725ba162c 281 msg_ps->state = SNMP_MSG_INTERNAL_GET_OBJDEF;
segundo 0:ac1725ba162c 282 mn->get_object_def(np.ident_len, np.ident, &object_def);
segundo 0:ac1725ba162c 283 if ((object_def.instance != MIB_OBJECT_NONE) &&
segundo 0:ac1725ba162c 284 (object_def.access & MIB_ACCESS_READ))
segundo 0:ac1725ba162c 285 {
segundo 0:ac1725ba162c 286 mn = mn;
segundo 0:ac1725ba162c 287 }
segundo 0:ac1725ba162c 288 else
segundo 0:ac1725ba162c 289 {
segundo 0:ac1725ba162c 290 /* search failed, object id points to unknown object (nosuchname) */
segundo 0:ac1725ba162c 291 mn = NULL;
segundo 0:ac1725ba162c 292 }
segundo 0:ac1725ba162c 293 if (mn != NULL)
segundo 0:ac1725ba162c 294 {
segundo 0:ac1725ba162c 295 struct snmp_varbind *vb;
segundo 0:ac1725ba162c 296
segundo 0:ac1725ba162c 297 msg_ps->state = SNMP_MSG_INTERNAL_GET_VALUE;
segundo 0:ac1725ba162c 298 /* allocate output varbind */
segundo 0:ac1725ba162c 299 vb = (struct snmp_varbind *)memp_malloc(MEMP_SNMP_VARBIND);
segundo 0:ac1725ba162c 300 LWIP_ASSERT("vb != NULL",vb != NULL);
segundo 0:ac1725ba162c 301 if (vb != NULL)
segundo 0:ac1725ba162c 302 {
segundo 0:ac1725ba162c 303 vb->next = NULL;
segundo 0:ac1725ba162c 304 vb->prev = NULL;
segundo 0:ac1725ba162c 305
segundo 0:ac1725ba162c 306 /* move name from invb to outvb */
segundo 0:ac1725ba162c 307 vb->ident = msg_ps->vb_ptr->ident;
segundo 0:ac1725ba162c 308 vb->ident_len = msg_ps->vb_ptr->ident_len;
segundo 0:ac1725ba162c 309 /* ensure this memory is refereced once only */
segundo 0:ac1725ba162c 310 msg_ps->vb_ptr->ident = NULL;
segundo 0:ac1725ba162c 311 msg_ps->vb_ptr->ident_len = 0;
segundo 0:ac1725ba162c 312
segundo 0:ac1725ba162c 313 vb->value_type = object_def.asn_type;
segundo 0:ac1725ba162c 314 LWIP_ASSERT("invalid length", object_def.v_len <= 0xff);
segundo 0:ac1725ba162c 315 vb->value_len = (u8_t)object_def.v_len;
segundo 0:ac1725ba162c 316 if (vb->value_len > 0)
segundo 0:ac1725ba162c 317 {
segundo 0:ac1725ba162c 318 LWIP_ASSERT("SNMP_MAX_OCTET_STRING_LEN is configured too low",
segundo 0:ac1725ba162c 319 vb->value_len <= SNMP_MAX_VALUE_SIZE);
segundo 0:ac1725ba162c 320 vb->value = memp_malloc(MEMP_SNMP_VALUE);
segundo 0:ac1725ba162c 321 LWIP_ASSERT("vb->value != NULL",vb->value != NULL);
segundo 0:ac1725ba162c 322 if (vb->value != NULL)
segundo 0:ac1725ba162c 323 {
segundo 0:ac1725ba162c 324 mn->get_value(&object_def, vb->value_len, vb->value);
segundo 0:ac1725ba162c 325 snmp_varbind_tail_add(&msg_ps->outvb, vb);
segundo 0:ac1725ba162c 326 msg_ps->state = SNMP_MSG_SEARCH_OBJ;
segundo 0:ac1725ba162c 327 msg_ps->vb_idx += 1;
segundo 0:ac1725ba162c 328 }
segundo 0:ac1725ba162c 329 else
segundo 0:ac1725ba162c 330 {
segundo 0:ac1725ba162c 331 LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_msg_event: couldn't allocate variable space\n"));
segundo 0:ac1725ba162c 332 msg_ps->vb_ptr->ident = vb->ident;
segundo 0:ac1725ba162c 333 msg_ps->vb_ptr->ident_len = vb->ident_len;
segundo 0:ac1725ba162c 334 memp_free(MEMP_SNMP_VARBIND, vb);
segundo 0:ac1725ba162c 335 snmp_error_response(msg_ps,SNMP_ES_TOOBIG);
segundo 0:ac1725ba162c 336 }
segundo 0:ac1725ba162c 337 }
segundo 0:ac1725ba162c 338 else
segundo 0:ac1725ba162c 339 {
segundo 0:ac1725ba162c 340 /* vb->value_len == 0, empty value (e.g. empty string) */
segundo 0:ac1725ba162c 341 vb->value = NULL;
segundo 0:ac1725ba162c 342 snmp_varbind_tail_add(&msg_ps->outvb, vb);
segundo 0:ac1725ba162c 343 msg_ps->state = SNMP_MSG_SEARCH_OBJ;
segundo 0:ac1725ba162c 344 msg_ps->vb_idx += 1;
segundo 0:ac1725ba162c 345 }
segundo 0:ac1725ba162c 346 }
segundo 0:ac1725ba162c 347 else
segundo 0:ac1725ba162c 348 {
segundo 0:ac1725ba162c 349 LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_msg_event: couldn't allocate outvb space\n"));
segundo 0:ac1725ba162c 350 snmp_error_response(msg_ps,SNMP_ES_TOOBIG);
segundo 0:ac1725ba162c 351 }
segundo 0:ac1725ba162c 352 }
segundo 0:ac1725ba162c 353 }
segundo 0:ac1725ba162c 354 }
segundo 0:ac1725ba162c 355 }
segundo 0:ac1725ba162c 356 else
segundo 0:ac1725ba162c 357 {
segundo 0:ac1725ba162c 358 mn = NULL;
segundo 0:ac1725ba162c 359 }
segundo 0:ac1725ba162c 360 if (mn == NULL)
segundo 0:ac1725ba162c 361 {
segundo 0:ac1725ba162c 362 /* mn == NULL, noSuchName */
segundo 0:ac1725ba162c 363 snmp_error_response(msg_ps,SNMP_ES_NOSUCHNAME);
segundo 0:ac1725ba162c 364 }
segundo 0:ac1725ba162c 365 }
segundo 0:ac1725ba162c 366 if ((msg_ps->state == SNMP_MSG_SEARCH_OBJ) &&
segundo 0:ac1725ba162c 367 (msg_ps->vb_idx == msg_ps->invb.count))
segundo 0:ac1725ba162c 368 {
segundo 0:ac1725ba162c 369 snmp_ok_response(msg_ps);
segundo 0:ac1725ba162c 370 }
segundo 0:ac1725ba162c 371 }
segundo 0:ac1725ba162c 372
segundo 0:ac1725ba162c 373 /**
segundo 0:ac1725ba162c 374 * Service an internal or external event for SNMP GETNEXT.
segundo 0:ac1725ba162c 375 *
segundo 0:ac1725ba162c 376 * @param request_id identifies requests from 0 to (SNMP_CONCURRENT_REQUESTS-1)
segundo 0:ac1725ba162c 377 * @param msg_ps points to the assosicated message process state
segundo 0:ac1725ba162c 378 */
segundo 0:ac1725ba162c 379 static void
segundo 0:ac1725ba162c 380 snmp_msg_getnext_event(u8_t request_id, struct snmp_msg_pstat *msg_ps)
segundo 0:ac1725ba162c 381 {
segundo 0:ac1725ba162c 382 LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_msg_getnext_event: msg_ps->state==%"U16_F"\n",(u16_t)msg_ps->state));
segundo 0:ac1725ba162c 383
segundo 0:ac1725ba162c 384 if (msg_ps->state == SNMP_MSG_EXTERNAL_GET_OBJDEF)
segundo 0:ac1725ba162c 385 {
segundo 0:ac1725ba162c 386 struct mib_external_node *en;
segundo 0:ac1725ba162c 387
segundo 0:ac1725ba162c 388 /* get_object_def() answer*/
segundo 0:ac1725ba162c 389 en = msg_ps->ext_mib_node;
segundo 0:ac1725ba162c 390
segundo 0:ac1725ba162c 391 /* translate answer into a known lifeform */
segundo 0:ac1725ba162c 392 en->get_object_def_a(request_id, 1, &msg_ps->ext_oid.id[msg_ps->ext_oid.len - 1], &msg_ps->ext_object_def);
segundo 0:ac1725ba162c 393 if (msg_ps->ext_object_def.instance != MIB_OBJECT_NONE)
segundo 0:ac1725ba162c 394 {
segundo 0:ac1725ba162c 395 msg_ps->state = SNMP_MSG_EXTERNAL_GET_VALUE;
segundo 0:ac1725ba162c 396 en->get_value_q(request_id, &msg_ps->ext_object_def);
segundo 0:ac1725ba162c 397 }
segundo 0:ac1725ba162c 398 else
segundo 0:ac1725ba162c 399 {
segundo 0:ac1725ba162c 400 en->get_object_def_pc(request_id, 1, &msg_ps->ext_oid.id[msg_ps->ext_oid.len - 1]);
segundo 0:ac1725ba162c 401 /* search failed, object id points to unknown object (nosuchname) */
segundo 0:ac1725ba162c 402 snmp_error_response(msg_ps,SNMP_ES_NOSUCHNAME);
segundo 0:ac1725ba162c 403 }
segundo 0:ac1725ba162c 404 }
segundo 0:ac1725ba162c 405 else if (msg_ps->state == SNMP_MSG_EXTERNAL_GET_VALUE)
segundo 0:ac1725ba162c 406 {
segundo 0:ac1725ba162c 407 struct mib_external_node *en;
segundo 0:ac1725ba162c 408 struct snmp_varbind *vb;
segundo 0:ac1725ba162c 409
segundo 0:ac1725ba162c 410 /* get_value() answer */
segundo 0:ac1725ba162c 411 en = msg_ps->ext_mib_node;
segundo 0:ac1725ba162c 412
segundo 0:ac1725ba162c 413 LWIP_ASSERT("invalid length", msg_ps->ext_object_def.v_len <= 0xff);
segundo 0:ac1725ba162c 414 vb = snmp_varbind_alloc(&msg_ps->ext_oid,
segundo 0:ac1725ba162c 415 msg_ps->ext_object_def.asn_type,
segundo 0:ac1725ba162c 416 (u8_t)msg_ps->ext_object_def.v_len);
segundo 0:ac1725ba162c 417 if (vb != NULL)
segundo 0:ac1725ba162c 418 {
segundo 0:ac1725ba162c 419 en->get_value_a(request_id, &msg_ps->ext_object_def, vb->value_len, vb->value);
segundo 0:ac1725ba162c 420 snmp_varbind_tail_add(&msg_ps->outvb, vb);
segundo 0:ac1725ba162c 421 msg_ps->state = SNMP_MSG_SEARCH_OBJ;
segundo 0:ac1725ba162c 422 msg_ps->vb_idx += 1;
segundo 0:ac1725ba162c 423 }
segundo 0:ac1725ba162c 424 else
segundo 0:ac1725ba162c 425 {
segundo 0:ac1725ba162c 426 en->get_value_pc(request_id, &msg_ps->ext_object_def);
segundo 0:ac1725ba162c 427 LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_msg_getnext_event: couldn't allocate outvb space\n"));
segundo 0:ac1725ba162c 428 snmp_error_response(msg_ps,SNMP_ES_TOOBIG);
segundo 0:ac1725ba162c 429 }
segundo 0:ac1725ba162c 430 }
segundo 0:ac1725ba162c 431
segundo 0:ac1725ba162c 432 while ((msg_ps->state == SNMP_MSG_SEARCH_OBJ) &&
segundo 0:ac1725ba162c 433 (msg_ps->vb_idx < msg_ps->invb.count))
segundo 0:ac1725ba162c 434 {
segundo 0:ac1725ba162c 435 struct mib_node *mn;
segundo 0:ac1725ba162c 436 struct snmp_obj_id oid;
segundo 0:ac1725ba162c 437
segundo 0:ac1725ba162c 438 if (msg_ps->vb_idx == 0)
segundo 0:ac1725ba162c 439 {
segundo 0:ac1725ba162c 440 msg_ps->vb_ptr = msg_ps->invb.head;
segundo 0:ac1725ba162c 441 }
segundo 0:ac1725ba162c 442 else
segundo 0:ac1725ba162c 443 {
segundo 0:ac1725ba162c 444 msg_ps->vb_ptr = msg_ps->vb_ptr->next;
segundo 0:ac1725ba162c 445 }
segundo 0:ac1725ba162c 446 if (snmp_iso_prefix_expand(msg_ps->vb_ptr->ident_len, msg_ps->vb_ptr->ident, &oid))
segundo 0:ac1725ba162c 447 {
segundo 0:ac1725ba162c 448 if (msg_ps->vb_ptr->ident_len > 3)
segundo 0:ac1725ba162c 449 {
segundo 0:ac1725ba162c 450 /* can offset ident_len and ident */
segundo 0:ac1725ba162c 451 mn = snmp_expand_tree((struct mib_node*)&internet,
segundo 0:ac1725ba162c 452 msg_ps->vb_ptr->ident_len - 4,
segundo 0:ac1725ba162c 453 msg_ps->vb_ptr->ident + 4, &oid);
segundo 0:ac1725ba162c 454 }
segundo 0:ac1725ba162c 455 else
segundo 0:ac1725ba162c 456 {
segundo 0:ac1725ba162c 457 /* can't offset ident_len -4, ident + 4 */
segundo 0:ac1725ba162c 458 mn = snmp_expand_tree((struct mib_node*)&internet, 0, NULL, &oid);
segundo 0:ac1725ba162c 459 }
segundo 0:ac1725ba162c 460 }
segundo 0:ac1725ba162c 461 else
segundo 0:ac1725ba162c 462 {
segundo 0:ac1725ba162c 463 mn = NULL;
segundo 0:ac1725ba162c 464 }
segundo 0:ac1725ba162c 465 if (mn != NULL)
segundo 0:ac1725ba162c 466 {
segundo 0:ac1725ba162c 467 if (mn->node_type == MIB_NODE_EX)
segundo 0:ac1725ba162c 468 {
segundo 0:ac1725ba162c 469 /* external object */
segundo 0:ac1725ba162c 470 struct mib_external_node *en = (struct mib_external_node*)mn;
segundo 0:ac1725ba162c 471
segundo 0:ac1725ba162c 472 msg_ps->state = SNMP_MSG_EXTERNAL_GET_OBJDEF;
segundo 0:ac1725ba162c 473 /* save en && args in msg_ps!! */
segundo 0:ac1725ba162c 474 msg_ps->ext_mib_node = en;
segundo 0:ac1725ba162c 475 msg_ps->ext_oid = oid;
segundo 0:ac1725ba162c 476
segundo 0:ac1725ba162c 477 en->get_object_def_q(en->addr_inf, request_id, 1, &oid.id[oid.len - 1]);
segundo 0:ac1725ba162c 478 }
segundo 0:ac1725ba162c 479 else
segundo 0:ac1725ba162c 480 {
segundo 0:ac1725ba162c 481 /* internal object */
segundo 0:ac1725ba162c 482 struct obj_def object_def;
segundo 0:ac1725ba162c 483 struct snmp_varbind *vb;
segundo 0:ac1725ba162c 484
segundo 0:ac1725ba162c 485 msg_ps->state = SNMP_MSG_INTERNAL_GET_OBJDEF;
segundo 0:ac1725ba162c 486 mn->get_object_def(1, &oid.id[oid.len - 1], &object_def);
segundo 0:ac1725ba162c 487
segundo 0:ac1725ba162c 488 LWIP_ASSERT("invalid length", object_def.v_len <= 0xff);
segundo 0:ac1725ba162c 489 vb = snmp_varbind_alloc(&oid, object_def.asn_type, (u8_t)object_def.v_len);
segundo 0:ac1725ba162c 490 if (vb != NULL)
segundo 0:ac1725ba162c 491 {
segundo 0:ac1725ba162c 492 msg_ps->state = SNMP_MSG_INTERNAL_GET_VALUE;
segundo 0:ac1725ba162c 493 mn->get_value(&object_def, object_def.v_len, vb->value);
segundo 0:ac1725ba162c 494 snmp_varbind_tail_add(&msg_ps->outvb, vb);
segundo 0:ac1725ba162c 495 msg_ps->state = SNMP_MSG_SEARCH_OBJ;
segundo 0:ac1725ba162c 496 msg_ps->vb_idx += 1;
segundo 0:ac1725ba162c 497 }
segundo 0:ac1725ba162c 498 else
segundo 0:ac1725ba162c 499 {
segundo 0:ac1725ba162c 500 LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_recv couldn't allocate outvb space\n"));
segundo 0:ac1725ba162c 501 snmp_error_response(msg_ps,SNMP_ES_TOOBIG);
segundo 0:ac1725ba162c 502 }
segundo 0:ac1725ba162c 503 }
segundo 0:ac1725ba162c 504 }
segundo 0:ac1725ba162c 505 if (mn == NULL)
segundo 0:ac1725ba162c 506 {
segundo 0:ac1725ba162c 507 /* mn == NULL, noSuchName */
segundo 0:ac1725ba162c 508 snmp_error_response(msg_ps,SNMP_ES_NOSUCHNAME);
segundo 0:ac1725ba162c 509 }
segundo 0:ac1725ba162c 510 }
segundo 0:ac1725ba162c 511 if ((msg_ps->state == SNMP_MSG_SEARCH_OBJ) &&
segundo 0:ac1725ba162c 512 (msg_ps->vb_idx == msg_ps->invb.count))
segundo 0:ac1725ba162c 513 {
segundo 0:ac1725ba162c 514 snmp_ok_response(msg_ps);
segundo 0:ac1725ba162c 515 }
segundo 0:ac1725ba162c 516 }
segundo 0:ac1725ba162c 517
segundo 0:ac1725ba162c 518 /**
segundo 0:ac1725ba162c 519 * Service an internal or external event for SNMP SET.
segundo 0:ac1725ba162c 520 *
segundo 0:ac1725ba162c 521 * @param request_id identifies requests from 0 to (SNMP_CONCURRENT_REQUESTS-1)
segundo 0:ac1725ba162c 522 * @param msg_ps points to the assosicated message process state
segundo 0:ac1725ba162c 523 */
segundo 0:ac1725ba162c 524 static void
segundo 0:ac1725ba162c 525 snmp_msg_set_event(u8_t request_id, struct snmp_msg_pstat *msg_ps)
segundo 0:ac1725ba162c 526 {
segundo 0:ac1725ba162c 527 LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_msg_set_event: msg_ps->state==%"U16_F"\n",(u16_t)msg_ps->state));
segundo 0:ac1725ba162c 528
segundo 0:ac1725ba162c 529 if (msg_ps->state == SNMP_MSG_EXTERNAL_GET_OBJDEF)
segundo 0:ac1725ba162c 530 {
segundo 0:ac1725ba162c 531 struct mib_external_node *en;
segundo 0:ac1725ba162c 532 struct snmp_name_ptr np;
segundo 0:ac1725ba162c 533
segundo 0:ac1725ba162c 534 /* get_object_def() answer*/
segundo 0:ac1725ba162c 535 en = msg_ps->ext_mib_node;
segundo 0:ac1725ba162c 536 np = msg_ps->ext_name_ptr;
segundo 0:ac1725ba162c 537
segundo 0:ac1725ba162c 538 /* translate answer into a known lifeform */
segundo 0:ac1725ba162c 539 en->get_object_def_a(request_id, np.ident_len, np.ident, &msg_ps->ext_object_def);
segundo 0:ac1725ba162c 540 if (msg_ps->ext_object_def.instance != MIB_OBJECT_NONE)
segundo 0:ac1725ba162c 541 {
segundo 0:ac1725ba162c 542 msg_ps->state = SNMP_MSG_EXTERNAL_SET_TEST;
segundo 0:ac1725ba162c 543 en->set_test_q(request_id, &msg_ps->ext_object_def);
segundo 0:ac1725ba162c 544 }
segundo 0:ac1725ba162c 545 else
segundo 0:ac1725ba162c 546 {
segundo 0:ac1725ba162c 547 en->get_object_def_pc(request_id, np.ident_len, np.ident);
segundo 0:ac1725ba162c 548 /* search failed, object id points to unknown object (nosuchname) */
segundo 0:ac1725ba162c 549 snmp_error_response(msg_ps,SNMP_ES_NOSUCHNAME);
segundo 0:ac1725ba162c 550 }
segundo 0:ac1725ba162c 551 }
segundo 0:ac1725ba162c 552 else if (msg_ps->state == SNMP_MSG_EXTERNAL_SET_TEST)
segundo 0:ac1725ba162c 553 {
segundo 0:ac1725ba162c 554 struct mib_external_node *en;
segundo 0:ac1725ba162c 555
segundo 0:ac1725ba162c 556 /* set_test() answer*/
segundo 0:ac1725ba162c 557 en = msg_ps->ext_mib_node;
segundo 0:ac1725ba162c 558
segundo 0:ac1725ba162c 559 if (msg_ps->ext_object_def.access & MIB_ACCESS_WRITE)
segundo 0:ac1725ba162c 560 {
segundo 0:ac1725ba162c 561 if ((msg_ps->ext_object_def.asn_type == msg_ps->vb_ptr->value_type) &&
segundo 0:ac1725ba162c 562 (en->set_test_a(request_id,&msg_ps->ext_object_def,
segundo 0:ac1725ba162c 563 msg_ps->vb_ptr->value_len,msg_ps->vb_ptr->value) != 0))
segundo 0:ac1725ba162c 564 {
segundo 0:ac1725ba162c 565 msg_ps->state = SNMP_MSG_SEARCH_OBJ;
segundo 0:ac1725ba162c 566 msg_ps->vb_idx += 1;
segundo 0:ac1725ba162c 567 }
segundo 0:ac1725ba162c 568 else
segundo 0:ac1725ba162c 569 {
segundo 0:ac1725ba162c 570 en->set_test_pc(request_id,&msg_ps->ext_object_def);
segundo 0:ac1725ba162c 571 /* bad value */
segundo 0:ac1725ba162c 572 snmp_error_response(msg_ps,SNMP_ES_BADVALUE);
segundo 0:ac1725ba162c 573 }
segundo 0:ac1725ba162c 574 }
segundo 0:ac1725ba162c 575 else
segundo 0:ac1725ba162c 576 {
segundo 0:ac1725ba162c 577 en->set_test_pc(request_id,&msg_ps->ext_object_def);
segundo 0:ac1725ba162c 578 /* object not available for set */
segundo 0:ac1725ba162c 579 snmp_error_response(msg_ps,SNMP_ES_NOSUCHNAME);
segundo 0:ac1725ba162c 580 }
segundo 0:ac1725ba162c 581 }
segundo 0:ac1725ba162c 582 else if (msg_ps->state == SNMP_MSG_EXTERNAL_GET_OBJDEF_S)
segundo 0:ac1725ba162c 583 {
segundo 0:ac1725ba162c 584 struct mib_external_node *en;
segundo 0:ac1725ba162c 585 struct snmp_name_ptr np;
segundo 0:ac1725ba162c 586
segundo 0:ac1725ba162c 587 /* get_object_def() answer*/
segundo 0:ac1725ba162c 588 en = msg_ps->ext_mib_node;
segundo 0:ac1725ba162c 589 np = msg_ps->ext_name_ptr;
segundo 0:ac1725ba162c 590
segundo 0:ac1725ba162c 591 /* translate answer into a known lifeform */
segundo 0:ac1725ba162c 592 en->get_object_def_a(request_id, np.ident_len, np.ident, &msg_ps->ext_object_def);
segundo 0:ac1725ba162c 593 if (msg_ps->ext_object_def.instance != MIB_OBJECT_NONE)
segundo 0:ac1725ba162c 594 {
segundo 0:ac1725ba162c 595 msg_ps->state = SNMP_MSG_EXTERNAL_SET_VALUE;
segundo 0:ac1725ba162c 596 en->set_value_q(request_id, &msg_ps->ext_object_def,
segundo 0:ac1725ba162c 597 msg_ps->vb_ptr->value_len,msg_ps->vb_ptr->value);
segundo 0:ac1725ba162c 598 }
segundo 0:ac1725ba162c 599 else
segundo 0:ac1725ba162c 600 {
segundo 0:ac1725ba162c 601 en->get_object_def_pc(request_id, np.ident_len, np.ident);
segundo 0:ac1725ba162c 602 /* set_value failed, object has disappeared for some odd reason?? */
segundo 0:ac1725ba162c 603 snmp_error_response(msg_ps,SNMP_ES_GENERROR);
segundo 0:ac1725ba162c 604 }
segundo 0:ac1725ba162c 605 }
segundo 0:ac1725ba162c 606 else if (msg_ps->state == SNMP_MSG_EXTERNAL_SET_VALUE)
segundo 0:ac1725ba162c 607 {
segundo 0:ac1725ba162c 608 struct mib_external_node *en;
segundo 0:ac1725ba162c 609
segundo 0:ac1725ba162c 610 /** set_value_a() */
segundo 0:ac1725ba162c 611 en = msg_ps->ext_mib_node;
segundo 0:ac1725ba162c 612 en->set_value_a(request_id, &msg_ps->ext_object_def,
segundo 0:ac1725ba162c 613 msg_ps->vb_ptr->value_len, msg_ps->vb_ptr->value);
segundo 0:ac1725ba162c 614
segundo 0:ac1725ba162c 615 /** @todo use set_value_pc() if toobig */
segundo 0:ac1725ba162c 616 msg_ps->state = SNMP_MSG_INTERNAL_SET_VALUE;
segundo 0:ac1725ba162c 617 msg_ps->vb_idx += 1;
segundo 0:ac1725ba162c 618 }
segundo 0:ac1725ba162c 619
segundo 0:ac1725ba162c 620 /* test all values before setting */
segundo 0:ac1725ba162c 621 while ((msg_ps->state == SNMP_MSG_SEARCH_OBJ) &&
segundo 0:ac1725ba162c 622 (msg_ps->vb_idx < msg_ps->invb.count))
segundo 0:ac1725ba162c 623 {
segundo 0:ac1725ba162c 624 struct mib_node *mn;
segundo 0:ac1725ba162c 625 struct snmp_name_ptr np;
segundo 0:ac1725ba162c 626
segundo 0:ac1725ba162c 627 if (msg_ps->vb_idx == 0)
segundo 0:ac1725ba162c 628 {
segundo 0:ac1725ba162c 629 msg_ps->vb_ptr = msg_ps->invb.head;
segundo 0:ac1725ba162c 630 }
segundo 0:ac1725ba162c 631 else
segundo 0:ac1725ba162c 632 {
segundo 0:ac1725ba162c 633 msg_ps->vb_ptr = msg_ps->vb_ptr->next;
segundo 0:ac1725ba162c 634 }
segundo 0:ac1725ba162c 635 /** test object identifier for .iso.org.dod.internet prefix */
segundo 0:ac1725ba162c 636 if (snmp_iso_prefix_tst(msg_ps->vb_ptr->ident_len, msg_ps->vb_ptr->ident))
segundo 0:ac1725ba162c 637 {
segundo 0:ac1725ba162c 638 mn = snmp_search_tree((struct mib_node*)&internet, msg_ps->vb_ptr->ident_len - 4,
segundo 0:ac1725ba162c 639 msg_ps->vb_ptr->ident + 4, &np);
segundo 0:ac1725ba162c 640 if (mn != NULL)
segundo 0:ac1725ba162c 641 {
segundo 0:ac1725ba162c 642 if (mn->node_type == MIB_NODE_EX)
segundo 0:ac1725ba162c 643 {
segundo 0:ac1725ba162c 644 /* external object */
segundo 0:ac1725ba162c 645 struct mib_external_node *en = (struct mib_external_node*)mn;
segundo 0:ac1725ba162c 646
segundo 0:ac1725ba162c 647 msg_ps->state = SNMP_MSG_EXTERNAL_GET_OBJDEF;
segundo 0:ac1725ba162c 648 /* save en && args in msg_ps!! */
segundo 0:ac1725ba162c 649 msg_ps->ext_mib_node = en;
segundo 0:ac1725ba162c 650 msg_ps->ext_name_ptr = np;
segundo 0:ac1725ba162c 651
segundo 0:ac1725ba162c 652 en->get_object_def_q(en->addr_inf, request_id, np.ident_len, np.ident);
segundo 0:ac1725ba162c 653 }
segundo 0:ac1725ba162c 654 else
segundo 0:ac1725ba162c 655 {
segundo 0:ac1725ba162c 656 /* internal object */
segundo 0:ac1725ba162c 657 struct obj_def object_def;
segundo 0:ac1725ba162c 658
segundo 0:ac1725ba162c 659 msg_ps->state = SNMP_MSG_INTERNAL_GET_OBJDEF;
segundo 0:ac1725ba162c 660 mn->get_object_def(np.ident_len, np.ident, &object_def);
segundo 0:ac1725ba162c 661 if (object_def.instance != MIB_OBJECT_NONE)
segundo 0:ac1725ba162c 662 {
segundo 0:ac1725ba162c 663 mn = mn;
segundo 0:ac1725ba162c 664 }
segundo 0:ac1725ba162c 665 else
segundo 0:ac1725ba162c 666 {
segundo 0:ac1725ba162c 667 /* search failed, object id points to unknown object (nosuchname) */
segundo 0:ac1725ba162c 668 mn = NULL;
segundo 0:ac1725ba162c 669 }
segundo 0:ac1725ba162c 670 if (mn != NULL)
segundo 0:ac1725ba162c 671 {
segundo 0:ac1725ba162c 672 msg_ps->state = SNMP_MSG_INTERNAL_SET_TEST;
segundo 0:ac1725ba162c 673
segundo 0:ac1725ba162c 674 if (object_def.access & MIB_ACCESS_WRITE)
segundo 0:ac1725ba162c 675 {
segundo 0:ac1725ba162c 676 if ((object_def.asn_type == msg_ps->vb_ptr->value_type) &&
segundo 0:ac1725ba162c 677 (mn->set_test(&object_def,msg_ps->vb_ptr->value_len,msg_ps->vb_ptr->value) != 0))
segundo 0:ac1725ba162c 678 {
segundo 0:ac1725ba162c 679 msg_ps->state = SNMP_MSG_SEARCH_OBJ;
segundo 0:ac1725ba162c 680 msg_ps->vb_idx += 1;
segundo 0:ac1725ba162c 681 }
segundo 0:ac1725ba162c 682 else
segundo 0:ac1725ba162c 683 {
segundo 0:ac1725ba162c 684 /* bad value */
segundo 0:ac1725ba162c 685 snmp_error_response(msg_ps,SNMP_ES_BADVALUE);
segundo 0:ac1725ba162c 686 }
segundo 0:ac1725ba162c 687 }
segundo 0:ac1725ba162c 688 else
segundo 0:ac1725ba162c 689 {
segundo 0:ac1725ba162c 690 /* object not available for set */
segundo 0:ac1725ba162c 691 snmp_error_response(msg_ps,SNMP_ES_NOSUCHNAME);
segundo 0:ac1725ba162c 692 }
segundo 0:ac1725ba162c 693 }
segundo 0:ac1725ba162c 694 }
segundo 0:ac1725ba162c 695 }
segundo 0:ac1725ba162c 696 }
segundo 0:ac1725ba162c 697 else
segundo 0:ac1725ba162c 698 {
segundo 0:ac1725ba162c 699 mn = NULL;
segundo 0:ac1725ba162c 700 }
segundo 0:ac1725ba162c 701 if (mn == NULL)
segundo 0:ac1725ba162c 702 {
segundo 0:ac1725ba162c 703 /* mn == NULL, noSuchName */
segundo 0:ac1725ba162c 704 snmp_error_response(msg_ps,SNMP_ES_NOSUCHNAME);
segundo 0:ac1725ba162c 705 }
segundo 0:ac1725ba162c 706 }
segundo 0:ac1725ba162c 707
segundo 0:ac1725ba162c 708 if ((msg_ps->state == SNMP_MSG_SEARCH_OBJ) &&
segundo 0:ac1725ba162c 709 (msg_ps->vb_idx == msg_ps->invb.count))
segundo 0:ac1725ba162c 710 {
segundo 0:ac1725ba162c 711 msg_ps->vb_idx = 0;
segundo 0:ac1725ba162c 712 msg_ps->state = SNMP_MSG_INTERNAL_SET_VALUE;
segundo 0:ac1725ba162c 713 }
segundo 0:ac1725ba162c 714
segundo 0:ac1725ba162c 715 /* set all values "atomically" (be as "atomic" as possible) */
segundo 0:ac1725ba162c 716 while ((msg_ps->state == SNMP_MSG_INTERNAL_SET_VALUE) &&
segundo 0:ac1725ba162c 717 (msg_ps->vb_idx < msg_ps->invb.count))
segundo 0:ac1725ba162c 718 {
segundo 0:ac1725ba162c 719 struct mib_node *mn;
segundo 0:ac1725ba162c 720 struct snmp_name_ptr np;
segundo 0:ac1725ba162c 721
segundo 0:ac1725ba162c 722 if (msg_ps->vb_idx == 0)
segundo 0:ac1725ba162c 723 {
segundo 0:ac1725ba162c 724 msg_ps->vb_ptr = msg_ps->invb.head;
segundo 0:ac1725ba162c 725 }
segundo 0:ac1725ba162c 726 else
segundo 0:ac1725ba162c 727 {
segundo 0:ac1725ba162c 728 msg_ps->vb_ptr = msg_ps->vb_ptr->next;
segundo 0:ac1725ba162c 729 }
segundo 0:ac1725ba162c 730 /* skip iso prefix test, was done previously while settesting() */
segundo 0:ac1725ba162c 731 mn = snmp_search_tree((struct mib_node*)&internet, msg_ps->vb_ptr->ident_len - 4,
segundo 0:ac1725ba162c 732 msg_ps->vb_ptr->ident + 4, &np);
segundo 0:ac1725ba162c 733 /* check if object is still available
segundo 0:ac1725ba162c 734 (e.g. external hot-plug thingy present?) */
segundo 0:ac1725ba162c 735 if (mn != NULL)
segundo 0:ac1725ba162c 736 {
segundo 0:ac1725ba162c 737 if (mn->node_type == MIB_NODE_EX)
segundo 0:ac1725ba162c 738 {
segundo 0:ac1725ba162c 739 /* external object */
segundo 0:ac1725ba162c 740 struct mib_external_node *en = (struct mib_external_node*)mn;
segundo 0:ac1725ba162c 741
segundo 0:ac1725ba162c 742 msg_ps->state = SNMP_MSG_EXTERNAL_GET_OBJDEF_S;
segundo 0:ac1725ba162c 743 /* save en && args in msg_ps!! */
segundo 0:ac1725ba162c 744 msg_ps->ext_mib_node = en;
segundo 0:ac1725ba162c 745 msg_ps->ext_name_ptr = np;
segundo 0:ac1725ba162c 746
segundo 0:ac1725ba162c 747 en->get_object_def_q(en->addr_inf, request_id, np.ident_len, np.ident);
segundo 0:ac1725ba162c 748 }
segundo 0:ac1725ba162c 749 else
segundo 0:ac1725ba162c 750 {
segundo 0:ac1725ba162c 751 /* internal object */
segundo 0:ac1725ba162c 752 struct obj_def object_def;
segundo 0:ac1725ba162c 753
segundo 0:ac1725ba162c 754 msg_ps->state = SNMP_MSG_INTERNAL_GET_OBJDEF_S;
segundo 0:ac1725ba162c 755 mn->get_object_def(np.ident_len, np.ident, &object_def);
segundo 0:ac1725ba162c 756 msg_ps->state = SNMP_MSG_INTERNAL_SET_VALUE;
segundo 0:ac1725ba162c 757 mn->set_value(&object_def,msg_ps->vb_ptr->value_len,msg_ps->vb_ptr->value);
segundo 0:ac1725ba162c 758 msg_ps->vb_idx += 1;
segundo 0:ac1725ba162c 759 }
segundo 0:ac1725ba162c 760 }
segundo 0:ac1725ba162c 761 }
segundo 0:ac1725ba162c 762 if ((msg_ps->state == SNMP_MSG_INTERNAL_SET_VALUE) &&
segundo 0:ac1725ba162c 763 (msg_ps->vb_idx == msg_ps->invb.count))
segundo 0:ac1725ba162c 764 {
segundo 0:ac1725ba162c 765 /* simply echo the input if we can set it
segundo 0:ac1725ba162c 766 @todo do we need to return the actual value?
segundo 0:ac1725ba162c 767 e.g. if value is silently modified or behaves sticky? */
segundo 0:ac1725ba162c 768 msg_ps->outvb = msg_ps->invb;
segundo 0:ac1725ba162c 769 msg_ps->invb.head = NULL;
segundo 0:ac1725ba162c 770 msg_ps->invb.tail = NULL;
segundo 0:ac1725ba162c 771 msg_ps->invb.count = 0;
segundo 0:ac1725ba162c 772 snmp_ok_response(msg_ps);
segundo 0:ac1725ba162c 773 }
segundo 0:ac1725ba162c 774 }
segundo 0:ac1725ba162c 775
segundo 0:ac1725ba162c 776
segundo 0:ac1725ba162c 777 /**
segundo 0:ac1725ba162c 778 * Handle one internal or external event.
segundo 0:ac1725ba162c 779 * Called for one async event. (recv external/private answer)
segundo 0:ac1725ba162c 780 *
segundo 0:ac1725ba162c 781 * @param request_id identifies requests from 0 to (SNMP_CONCURRENT_REQUESTS-1)
segundo 0:ac1725ba162c 782 */
segundo 0:ac1725ba162c 783 void
segundo 0:ac1725ba162c 784 snmp_msg_event(u8_t request_id)
segundo 0:ac1725ba162c 785 {
segundo 0:ac1725ba162c 786 struct snmp_msg_pstat *msg_ps;
segundo 0:ac1725ba162c 787
segundo 0:ac1725ba162c 788 if (request_id < SNMP_CONCURRENT_REQUESTS)
segundo 0:ac1725ba162c 789 {
segundo 0:ac1725ba162c 790 msg_ps = &msg_input_list[request_id];
segundo 0:ac1725ba162c 791 if (msg_ps->rt == SNMP_ASN1_PDU_GET_NEXT_REQ)
segundo 0:ac1725ba162c 792 {
segundo 0:ac1725ba162c 793 snmp_msg_getnext_event(request_id, msg_ps);
segundo 0:ac1725ba162c 794 }
segundo 0:ac1725ba162c 795 else if (msg_ps->rt == SNMP_ASN1_PDU_GET_REQ)
segundo 0:ac1725ba162c 796 {
segundo 0:ac1725ba162c 797 snmp_msg_get_event(request_id, msg_ps);
segundo 0:ac1725ba162c 798 }
segundo 0:ac1725ba162c 799 else if(msg_ps->rt == SNMP_ASN1_PDU_SET_REQ)
segundo 0:ac1725ba162c 800 {
segundo 0:ac1725ba162c 801 snmp_msg_set_event(request_id, msg_ps);
segundo 0:ac1725ba162c 802 }
segundo 0:ac1725ba162c 803 }
segundo 0:ac1725ba162c 804 }
segundo 0:ac1725ba162c 805
segundo 0:ac1725ba162c 806
segundo 0:ac1725ba162c 807 /* lwIP UDP receive callback function */
segundo 0:ac1725ba162c 808 static void
segundo 0:ac1725ba162c 809 snmp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *addr, u16_t port)
segundo 0:ac1725ba162c 810 {
segundo 0:ac1725ba162c 811 struct snmp_msg_pstat *msg_ps;
segundo 0:ac1725ba162c 812 u8_t req_idx;
segundo 0:ac1725ba162c 813 err_t err_ret;
segundo 0:ac1725ba162c 814 u16_t payload_len = p->tot_len;
segundo 0:ac1725ba162c 815 u16_t payload_ofs = 0;
segundo 0:ac1725ba162c 816 u16_t varbind_ofs = 0;
segundo 0:ac1725ba162c 817
segundo 0:ac1725ba162c 818 /* suppress unused argument warning */
segundo 0:ac1725ba162c 819 LWIP_UNUSED_ARG(arg);
segundo 0:ac1725ba162c 820
segundo 0:ac1725ba162c 821 /* traverse input message process list, look for SNMP_MSG_EMPTY */
segundo 0:ac1725ba162c 822 msg_ps = &msg_input_list[0];
segundo 0:ac1725ba162c 823 req_idx = 0;
segundo 0:ac1725ba162c 824 while ((req_idx < SNMP_CONCURRENT_REQUESTS) && (msg_ps->state != SNMP_MSG_EMPTY))
segundo 0:ac1725ba162c 825 {
segundo 0:ac1725ba162c 826 req_idx++;
segundo 0:ac1725ba162c 827 msg_ps++;
segundo 0:ac1725ba162c 828 }
segundo 0:ac1725ba162c 829 if (req_idx == SNMP_CONCURRENT_REQUESTS)
segundo 0:ac1725ba162c 830 {
segundo 0:ac1725ba162c 831 /* exceeding number of concurrent requests */
segundo 0:ac1725ba162c 832 pbuf_free(p);
segundo 0:ac1725ba162c 833 return;
segundo 0:ac1725ba162c 834 }
segundo 0:ac1725ba162c 835
segundo 0:ac1725ba162c 836 /* accepting request */
segundo 0:ac1725ba162c 837 snmp_inc_snmpinpkts();
segundo 0:ac1725ba162c 838 /* record used 'protocol control block' */
segundo 0:ac1725ba162c 839 msg_ps->pcb = pcb;
segundo 0:ac1725ba162c 840 /* source address (network order) */
segundo 0:ac1725ba162c 841 msg_ps->sip = *addr;
segundo 0:ac1725ba162c 842 /* source port (host order (lwIP oddity)) */
segundo 0:ac1725ba162c 843 msg_ps->sp = port;
segundo 0:ac1725ba162c 844
segundo 0:ac1725ba162c 845 /* check total length, version, community, pdu type */
segundo 0:ac1725ba162c 846 err_ret = snmp_pdu_header_check(p, payload_ofs, payload_len, &varbind_ofs, msg_ps);
segundo 0:ac1725ba162c 847 /* Only accept requests and requests without error (be robust) */
segundo 0:ac1725ba162c 848 /* Reject response and trap headers or error requests as input! */
segundo 0:ac1725ba162c 849 if ((err_ret != ERR_OK) ||
segundo 0:ac1725ba162c 850 ((msg_ps->rt != SNMP_ASN1_PDU_GET_REQ) &&
segundo 0:ac1725ba162c 851 (msg_ps->rt != SNMP_ASN1_PDU_GET_NEXT_REQ) &&
segundo 0:ac1725ba162c 852 (msg_ps->rt != SNMP_ASN1_PDU_SET_REQ)) ||
segundo 0:ac1725ba162c 853 ((msg_ps->error_status != SNMP_ES_NOERROR) ||
segundo 0:ac1725ba162c 854 (msg_ps->error_index != 0)) )
segundo 0:ac1725ba162c 855 {
segundo 0:ac1725ba162c 856 /* header check failed drop request silently, do not return error! */
segundo 0:ac1725ba162c 857 pbuf_free(p);
segundo 0:ac1725ba162c 858 LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_pdu_header_check() failed\n"));
segundo 0:ac1725ba162c 859 return;
segundo 0:ac1725ba162c 860 }
segundo 0:ac1725ba162c 861 LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_recv ok, community %s\n", msg_ps->community));
segundo 0:ac1725ba162c 862
segundo 0:ac1725ba162c 863 /* Builds a list of variable bindings. Copy the varbinds from the pbuf
segundo 0:ac1725ba162c 864 chain to glue them when these are divided over two or more pbuf's. */
segundo 0:ac1725ba162c 865 err_ret = snmp_pdu_dec_varbindlist(p, varbind_ofs, &varbind_ofs, msg_ps);
segundo 0:ac1725ba162c 866 /* we've decoded the incoming message, release input msg now */
segundo 0:ac1725ba162c 867 pbuf_free(p);
segundo 0:ac1725ba162c 868 if ((err_ret != ERR_OK) || (msg_ps->invb.count == 0))
segundo 0:ac1725ba162c 869 {
segundo 0:ac1725ba162c 870 /* varbind-list decode failed, or varbind list empty.
segundo 0:ac1725ba162c 871 drop request silently, do not return error!
segundo 0:ac1725ba162c 872 (errors are only returned for a specific varbind failure) */
segundo 0:ac1725ba162c 873 LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_pdu_dec_varbindlist() failed\n"));
segundo 0:ac1725ba162c 874 return;
segundo 0:ac1725ba162c 875 }
segundo 0:ac1725ba162c 876
segundo 0:ac1725ba162c 877 msg_ps->error_status = SNMP_ES_NOERROR;
segundo 0:ac1725ba162c 878 msg_ps->error_index = 0;
segundo 0:ac1725ba162c 879 /* find object for each variable binding */
segundo 0:ac1725ba162c 880 msg_ps->state = SNMP_MSG_SEARCH_OBJ;
segundo 0:ac1725ba162c 881 /* first variable binding from list to inspect */
segundo 0:ac1725ba162c 882 msg_ps->vb_idx = 0;
segundo 0:ac1725ba162c 883
segundo 0:ac1725ba162c 884 LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_recv varbind cnt=%"U16_F"\n",(u16_t)msg_ps->invb.count));
segundo 0:ac1725ba162c 885
segundo 0:ac1725ba162c 886 /* handle input event and as much objects as possible in one go */
segundo 0:ac1725ba162c 887 snmp_msg_event(req_idx);
segundo 0:ac1725ba162c 888 }
segundo 0:ac1725ba162c 889
segundo 0:ac1725ba162c 890 /**
segundo 0:ac1725ba162c 891 * Checks and decodes incoming SNMP message header, logs header errors.
segundo 0:ac1725ba162c 892 *
segundo 0:ac1725ba162c 893 * @param p points to pbuf chain of SNMP message (UDP payload)
segundo 0:ac1725ba162c 894 * @param ofs points to first octet of SNMP message
segundo 0:ac1725ba162c 895 * @param pdu_len the length of the UDP payload
segundo 0:ac1725ba162c 896 * @param ofs_ret returns the ofset of the variable bindings
segundo 0:ac1725ba162c 897 * @param m_stat points to the current message request state return
segundo 0:ac1725ba162c 898 * @return
segundo 0:ac1725ba162c 899 * - ERR_OK SNMP header is sane and accepted
segundo 0:ac1725ba162c 900 * - ERR_ARG SNMP header is either malformed or rejected
segundo 0:ac1725ba162c 901 */
segundo 0:ac1725ba162c 902 static err_t
segundo 0:ac1725ba162c 903 snmp_pdu_header_check(struct pbuf *p, u16_t ofs, u16_t pdu_len, u16_t *ofs_ret, struct snmp_msg_pstat *m_stat)
segundo 0:ac1725ba162c 904 {
segundo 0:ac1725ba162c 905 err_t derr;
segundo 0:ac1725ba162c 906 u16_t len, ofs_base;
segundo 0:ac1725ba162c 907 u8_t len_octets;
segundo 0:ac1725ba162c 908 u8_t type;
segundo 0:ac1725ba162c 909 s32_t version;
segundo 0:ac1725ba162c 910
segundo 0:ac1725ba162c 911 ofs_base = ofs;
segundo 0:ac1725ba162c 912 snmp_asn1_dec_type(p, ofs, &type);
segundo 0:ac1725ba162c 913 derr = snmp_asn1_dec_length(p, ofs+1, &len_octets, &len);
segundo 0:ac1725ba162c 914 if ((derr != ERR_OK) ||
segundo 0:ac1725ba162c 915 (pdu_len != (1 + len_octets + len)) ||
segundo 0:ac1725ba162c 916 (type != (SNMP_ASN1_UNIV | SNMP_ASN1_CONSTR | SNMP_ASN1_SEQ)))
segundo 0:ac1725ba162c 917 {
segundo 0:ac1725ba162c 918 snmp_inc_snmpinasnparseerrs();
segundo 0:ac1725ba162c 919 return ERR_ARG;
segundo 0:ac1725ba162c 920 }
segundo 0:ac1725ba162c 921 ofs += (1 + len_octets);
segundo 0:ac1725ba162c 922 snmp_asn1_dec_type(p, ofs, &type);
segundo 0:ac1725ba162c 923 derr = snmp_asn1_dec_length(p, ofs+1, &len_octets, &len);
segundo 0:ac1725ba162c 924 if ((derr != ERR_OK) || (type != (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG)))
segundo 0:ac1725ba162c 925 {
segundo 0:ac1725ba162c 926 /* can't decode or no integer (version) */
segundo 0:ac1725ba162c 927 snmp_inc_snmpinasnparseerrs();
segundo 0:ac1725ba162c 928 return ERR_ARG;
segundo 0:ac1725ba162c 929 }
segundo 0:ac1725ba162c 930 derr = snmp_asn1_dec_s32t(p, ofs + 1 + len_octets, len, &version);
segundo 0:ac1725ba162c 931 if (derr != ERR_OK)
segundo 0:ac1725ba162c 932 {
segundo 0:ac1725ba162c 933 /* can't decode */
segundo 0:ac1725ba162c 934 snmp_inc_snmpinasnparseerrs();
segundo 0:ac1725ba162c 935 return ERR_ARG;
segundo 0:ac1725ba162c 936 }
segundo 0:ac1725ba162c 937 if (version != 0)
segundo 0:ac1725ba162c 938 {
segundo 0:ac1725ba162c 939 /* not version 1 */
segundo 0:ac1725ba162c 940 snmp_inc_snmpinbadversions();
segundo 0:ac1725ba162c 941 return ERR_ARG;
segundo 0:ac1725ba162c 942 }
segundo 0:ac1725ba162c 943 ofs += (1 + len_octets + len);
segundo 0:ac1725ba162c 944 snmp_asn1_dec_type(p, ofs, &type);
segundo 0:ac1725ba162c 945 derr = snmp_asn1_dec_length(p, ofs+1, &len_octets, &len);
segundo 0:ac1725ba162c 946 if ((derr != ERR_OK) || (type != (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR)))
segundo 0:ac1725ba162c 947 {
segundo 0:ac1725ba162c 948 /* can't decode or no octet string (community) */
segundo 0:ac1725ba162c 949 snmp_inc_snmpinasnparseerrs();
segundo 0:ac1725ba162c 950 return ERR_ARG;
segundo 0:ac1725ba162c 951 }
segundo 0:ac1725ba162c 952 derr = snmp_asn1_dec_raw(p, ofs + 1 + len_octets, len, SNMP_COMMUNITY_STR_LEN, m_stat->community);
segundo 0:ac1725ba162c 953 if (derr != ERR_OK)
segundo 0:ac1725ba162c 954 {
segundo 0:ac1725ba162c 955 snmp_inc_snmpinasnparseerrs();
segundo 0:ac1725ba162c 956 return ERR_ARG;
segundo 0:ac1725ba162c 957 }
segundo 0:ac1725ba162c 958 /* add zero terminator */
segundo 0:ac1725ba162c 959 len = ((len < (SNMP_COMMUNITY_STR_LEN))?(len):(SNMP_COMMUNITY_STR_LEN));
segundo 0:ac1725ba162c 960 m_stat->community[len] = 0;
segundo 0:ac1725ba162c 961 m_stat->com_strlen = (u8_t)len;
segundo 0:ac1725ba162c 962 if (strncmp(snmp_publiccommunity, (const char*)m_stat->community, SNMP_COMMUNITY_STR_LEN) != 0)
segundo 0:ac1725ba162c 963 {
segundo 0:ac1725ba162c 964 /** @todo: move this if we need to check more names */
segundo 0:ac1725ba162c 965 snmp_inc_snmpinbadcommunitynames();
segundo 0:ac1725ba162c 966 snmp_authfail_trap();
segundo 0:ac1725ba162c 967 return ERR_ARG;
segundo 0:ac1725ba162c 968 }
segundo 0:ac1725ba162c 969 ofs += (1 + len_octets + len);
segundo 0:ac1725ba162c 970 snmp_asn1_dec_type(p, ofs, &type);
segundo 0:ac1725ba162c 971 derr = snmp_asn1_dec_length(p, ofs+1, &len_octets, &len);
segundo 0:ac1725ba162c 972 if (derr != ERR_OK)
segundo 0:ac1725ba162c 973 {
segundo 0:ac1725ba162c 974 snmp_inc_snmpinasnparseerrs();
segundo 0:ac1725ba162c 975 return ERR_ARG;
segundo 0:ac1725ba162c 976 }
segundo 0:ac1725ba162c 977 switch(type)
segundo 0:ac1725ba162c 978 {
segundo 0:ac1725ba162c 979 case (SNMP_ASN1_CONTXT | SNMP_ASN1_CONSTR | SNMP_ASN1_PDU_GET_REQ):
segundo 0:ac1725ba162c 980 /* GetRequest PDU */
segundo 0:ac1725ba162c 981 snmp_inc_snmpingetrequests();
segundo 0:ac1725ba162c 982 derr = ERR_OK;
segundo 0:ac1725ba162c 983 break;
segundo 0:ac1725ba162c 984 case (SNMP_ASN1_CONTXT | SNMP_ASN1_CONSTR | SNMP_ASN1_PDU_GET_NEXT_REQ):
segundo 0:ac1725ba162c 985 /* GetNextRequest PDU */
segundo 0:ac1725ba162c 986 snmp_inc_snmpingetnexts();
segundo 0:ac1725ba162c 987 derr = ERR_OK;
segundo 0:ac1725ba162c 988 break;
segundo 0:ac1725ba162c 989 case (SNMP_ASN1_CONTXT | SNMP_ASN1_CONSTR | SNMP_ASN1_PDU_GET_RESP):
segundo 0:ac1725ba162c 990 /* GetResponse PDU */
segundo 0:ac1725ba162c 991 snmp_inc_snmpingetresponses();
segundo 0:ac1725ba162c 992 derr = ERR_ARG;
segundo 0:ac1725ba162c 993 break;
segundo 0:ac1725ba162c 994 case (SNMP_ASN1_CONTXT | SNMP_ASN1_CONSTR | SNMP_ASN1_PDU_SET_REQ):
segundo 0:ac1725ba162c 995 /* SetRequest PDU */
segundo 0:ac1725ba162c 996 snmp_inc_snmpinsetrequests();
segundo 0:ac1725ba162c 997 derr = ERR_OK;
segundo 0:ac1725ba162c 998 break;
segundo 0:ac1725ba162c 999 case (SNMP_ASN1_CONTXT | SNMP_ASN1_CONSTR | SNMP_ASN1_PDU_TRAP):
segundo 0:ac1725ba162c 1000 /* Trap PDU */
segundo 0:ac1725ba162c 1001 snmp_inc_snmpintraps();
segundo 0:ac1725ba162c 1002 derr = ERR_ARG;
segundo 0:ac1725ba162c 1003 break;
segundo 0:ac1725ba162c 1004 default:
segundo 0:ac1725ba162c 1005 snmp_inc_snmpinasnparseerrs();
segundo 0:ac1725ba162c 1006 derr = ERR_ARG;
segundo 0:ac1725ba162c 1007 break;
segundo 0:ac1725ba162c 1008 }
segundo 0:ac1725ba162c 1009 if (derr != ERR_OK)
segundo 0:ac1725ba162c 1010 {
segundo 0:ac1725ba162c 1011 /* unsupported input PDU for this agent (no parse error) */
segundo 0:ac1725ba162c 1012 return ERR_ARG;
segundo 0:ac1725ba162c 1013 }
segundo 0:ac1725ba162c 1014 m_stat->rt = type & 0x1F;
segundo 0:ac1725ba162c 1015 ofs += (1 + len_octets);
segundo 0:ac1725ba162c 1016 if (len != (pdu_len - (ofs - ofs_base)))
segundo 0:ac1725ba162c 1017 {
segundo 0:ac1725ba162c 1018 /* decoded PDU length does not equal actual payload length */
segundo 0:ac1725ba162c 1019 snmp_inc_snmpinasnparseerrs();
segundo 0:ac1725ba162c 1020 return ERR_ARG;
segundo 0:ac1725ba162c 1021 }
segundo 0:ac1725ba162c 1022 snmp_asn1_dec_type(p, ofs, &type);
segundo 0:ac1725ba162c 1023 derr = snmp_asn1_dec_length(p, ofs+1, &len_octets, &len);
segundo 0:ac1725ba162c 1024 if ((derr != ERR_OK) || (type != (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG)))
segundo 0:ac1725ba162c 1025 {
segundo 0:ac1725ba162c 1026 /* can't decode or no integer (request ID) */
segundo 0:ac1725ba162c 1027 snmp_inc_snmpinasnparseerrs();
segundo 0:ac1725ba162c 1028 return ERR_ARG;
segundo 0:ac1725ba162c 1029 }
segundo 0:ac1725ba162c 1030 derr = snmp_asn1_dec_s32t(p, ofs + 1 + len_octets, len, &m_stat->rid);
segundo 0:ac1725ba162c 1031 if (derr != ERR_OK)
segundo 0:ac1725ba162c 1032 {
segundo 0:ac1725ba162c 1033 /* can't decode */
segundo 0:ac1725ba162c 1034 snmp_inc_snmpinasnparseerrs();
segundo 0:ac1725ba162c 1035 return ERR_ARG;
segundo 0:ac1725ba162c 1036 }
segundo 0:ac1725ba162c 1037 ofs += (1 + len_octets + len);
segundo 0:ac1725ba162c 1038 snmp_asn1_dec_type(p, ofs, &type);
segundo 0:ac1725ba162c 1039 derr = snmp_asn1_dec_length(p, ofs+1, &len_octets, &len);
segundo 0:ac1725ba162c 1040 if ((derr != ERR_OK) || (type != (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG)))
segundo 0:ac1725ba162c 1041 {
segundo 0:ac1725ba162c 1042 /* can't decode or no integer (error-status) */
segundo 0:ac1725ba162c 1043 snmp_inc_snmpinasnparseerrs();
segundo 0:ac1725ba162c 1044 return ERR_ARG;
segundo 0:ac1725ba162c 1045 }
segundo 0:ac1725ba162c 1046 /* must be noError (0) for incoming requests.
segundo 0:ac1725ba162c 1047 log errors for mib-2 completeness and for debug purposes */
segundo 0:ac1725ba162c 1048 derr = snmp_asn1_dec_s32t(p, ofs + 1 + len_octets, len, &m_stat->error_status);
segundo 0:ac1725ba162c 1049 if (derr != ERR_OK)
segundo 0:ac1725ba162c 1050 {
segundo 0:ac1725ba162c 1051 /* can't decode */
segundo 0:ac1725ba162c 1052 snmp_inc_snmpinasnparseerrs();
segundo 0:ac1725ba162c 1053 return ERR_ARG;
segundo 0:ac1725ba162c 1054 }
segundo 0:ac1725ba162c 1055 switch (m_stat->error_status)
segundo 0:ac1725ba162c 1056 {
segundo 0:ac1725ba162c 1057 case SNMP_ES_TOOBIG:
segundo 0:ac1725ba162c 1058 snmp_inc_snmpintoobigs();
segundo 0:ac1725ba162c 1059 break;
segundo 0:ac1725ba162c 1060 case SNMP_ES_NOSUCHNAME:
segundo 0:ac1725ba162c 1061 snmp_inc_snmpinnosuchnames();
segundo 0:ac1725ba162c 1062 break;
segundo 0:ac1725ba162c 1063 case SNMP_ES_BADVALUE:
segundo 0:ac1725ba162c 1064 snmp_inc_snmpinbadvalues();
segundo 0:ac1725ba162c 1065 break;
segundo 0:ac1725ba162c 1066 case SNMP_ES_READONLY:
segundo 0:ac1725ba162c 1067 snmp_inc_snmpinreadonlys();
segundo 0:ac1725ba162c 1068 break;
segundo 0:ac1725ba162c 1069 case SNMP_ES_GENERROR:
segundo 0:ac1725ba162c 1070 snmp_inc_snmpingenerrs();
segundo 0:ac1725ba162c 1071 break;
segundo 0:ac1725ba162c 1072 }
segundo 0:ac1725ba162c 1073 ofs += (1 + len_octets + len);
segundo 0:ac1725ba162c 1074 snmp_asn1_dec_type(p, ofs, &type);
segundo 0:ac1725ba162c 1075 derr = snmp_asn1_dec_length(p, ofs+1, &len_octets, &len);
segundo 0:ac1725ba162c 1076 if ((derr != ERR_OK) || (type != (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG)))
segundo 0:ac1725ba162c 1077 {
segundo 0:ac1725ba162c 1078 /* can't decode or no integer (error-index) */
segundo 0:ac1725ba162c 1079 snmp_inc_snmpinasnparseerrs();
segundo 0:ac1725ba162c 1080 return ERR_ARG;
segundo 0:ac1725ba162c 1081 }
segundo 0:ac1725ba162c 1082 /* must be 0 for incoming requests.
segundo 0:ac1725ba162c 1083 decode anyway to catch bad integers (and dirty tricks) */
segundo 0:ac1725ba162c 1084 derr = snmp_asn1_dec_s32t(p, ofs + 1 + len_octets, len, &m_stat->error_index);
segundo 0:ac1725ba162c 1085 if (derr != ERR_OK)
segundo 0:ac1725ba162c 1086 {
segundo 0:ac1725ba162c 1087 /* can't decode */
segundo 0:ac1725ba162c 1088 snmp_inc_snmpinasnparseerrs();
segundo 0:ac1725ba162c 1089 return ERR_ARG;
segundo 0:ac1725ba162c 1090 }
segundo 0:ac1725ba162c 1091 ofs += (1 + len_octets + len);
segundo 0:ac1725ba162c 1092 *ofs_ret = ofs;
segundo 0:ac1725ba162c 1093 return ERR_OK;
segundo 0:ac1725ba162c 1094 }
segundo 0:ac1725ba162c 1095
segundo 0:ac1725ba162c 1096 static err_t
segundo 0:ac1725ba162c 1097 snmp_pdu_dec_varbindlist(struct pbuf *p, u16_t ofs, u16_t *ofs_ret, struct snmp_msg_pstat *m_stat)
segundo 0:ac1725ba162c 1098 {
segundo 0:ac1725ba162c 1099 err_t derr;
segundo 0:ac1725ba162c 1100 u16_t len, vb_len;
segundo 0:ac1725ba162c 1101 u8_t len_octets;
segundo 0:ac1725ba162c 1102 u8_t type;
segundo 0:ac1725ba162c 1103
segundo 0:ac1725ba162c 1104 /* variable binding list */
segundo 0:ac1725ba162c 1105 snmp_asn1_dec_type(p, ofs, &type);
segundo 0:ac1725ba162c 1106 derr = snmp_asn1_dec_length(p, ofs+1, &len_octets, &vb_len);
segundo 0:ac1725ba162c 1107 if ((derr != ERR_OK) ||
segundo 0:ac1725ba162c 1108 (type != (SNMP_ASN1_UNIV | SNMP_ASN1_CONSTR | SNMP_ASN1_SEQ)))
segundo 0:ac1725ba162c 1109 {
segundo 0:ac1725ba162c 1110 snmp_inc_snmpinasnparseerrs();
segundo 0:ac1725ba162c 1111 return ERR_ARG;
segundo 0:ac1725ba162c 1112 }
segundo 0:ac1725ba162c 1113 ofs += (1 + len_octets);
segundo 0:ac1725ba162c 1114
segundo 0:ac1725ba162c 1115 /* start with empty list */
segundo 0:ac1725ba162c 1116 m_stat->invb.count = 0;
segundo 0:ac1725ba162c 1117 m_stat->invb.head = NULL;
segundo 0:ac1725ba162c 1118 m_stat->invb.tail = NULL;
segundo 0:ac1725ba162c 1119
segundo 0:ac1725ba162c 1120 while (vb_len > 0)
segundo 0:ac1725ba162c 1121 {
segundo 0:ac1725ba162c 1122 struct snmp_obj_id oid, oid_value;
segundo 0:ac1725ba162c 1123 struct snmp_varbind *vb;
segundo 0:ac1725ba162c 1124
segundo 0:ac1725ba162c 1125 snmp_asn1_dec_type(p, ofs, &type);
segundo 0:ac1725ba162c 1126 derr = snmp_asn1_dec_length(p, ofs+1, &len_octets, &len);
segundo 0:ac1725ba162c 1127 if ((derr != ERR_OK) ||
segundo 0:ac1725ba162c 1128 (type != (SNMP_ASN1_UNIV | SNMP_ASN1_CONSTR | SNMP_ASN1_SEQ)) ||
segundo 0:ac1725ba162c 1129 (len == 0) || (len > vb_len))
segundo 0:ac1725ba162c 1130 {
segundo 0:ac1725ba162c 1131 snmp_inc_snmpinasnparseerrs();
segundo 0:ac1725ba162c 1132 /* free varbinds (if available) */
segundo 0:ac1725ba162c 1133 snmp_varbind_list_free(&m_stat->invb);
segundo 0:ac1725ba162c 1134 return ERR_ARG;
segundo 0:ac1725ba162c 1135 }
segundo 0:ac1725ba162c 1136 ofs += (1 + len_octets);
segundo 0:ac1725ba162c 1137 vb_len -= (1 + len_octets);
segundo 0:ac1725ba162c 1138
segundo 0:ac1725ba162c 1139 snmp_asn1_dec_type(p, ofs, &type);
segundo 0:ac1725ba162c 1140 derr = snmp_asn1_dec_length(p, ofs+1, &len_octets, &len);
segundo 0:ac1725ba162c 1141 if ((derr != ERR_OK) || (type != (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OBJ_ID)))
segundo 0:ac1725ba162c 1142 {
segundo 0:ac1725ba162c 1143 /* can't decode object name length */
segundo 0:ac1725ba162c 1144 snmp_inc_snmpinasnparseerrs();
segundo 0:ac1725ba162c 1145 /* free varbinds (if available) */
segundo 0:ac1725ba162c 1146 snmp_varbind_list_free(&m_stat->invb);
segundo 0:ac1725ba162c 1147 return ERR_ARG;
segundo 0:ac1725ba162c 1148 }
segundo 0:ac1725ba162c 1149 derr = snmp_asn1_dec_oid(p, ofs + 1 + len_octets, len, &oid);
segundo 0:ac1725ba162c 1150 if (derr != ERR_OK)
segundo 0:ac1725ba162c 1151 {
segundo 0:ac1725ba162c 1152 /* can't decode object name */
segundo 0:ac1725ba162c 1153 snmp_inc_snmpinasnparseerrs();
segundo 0:ac1725ba162c 1154 /* free varbinds (if available) */
segundo 0:ac1725ba162c 1155 snmp_varbind_list_free(&m_stat->invb);
segundo 0:ac1725ba162c 1156 return ERR_ARG;
segundo 0:ac1725ba162c 1157 }
segundo 0:ac1725ba162c 1158 ofs += (1 + len_octets + len);
segundo 0:ac1725ba162c 1159 vb_len -= (1 + len_octets + len);
segundo 0:ac1725ba162c 1160
segundo 0:ac1725ba162c 1161 snmp_asn1_dec_type(p, ofs, &type);
segundo 0:ac1725ba162c 1162 derr = snmp_asn1_dec_length(p, ofs+1, &len_octets, &len);
segundo 0:ac1725ba162c 1163 if (derr != ERR_OK)
segundo 0:ac1725ba162c 1164 {
segundo 0:ac1725ba162c 1165 /* can't decode object value length */
segundo 0:ac1725ba162c 1166 snmp_inc_snmpinasnparseerrs();
segundo 0:ac1725ba162c 1167 /* free varbinds (if available) */
segundo 0:ac1725ba162c 1168 snmp_varbind_list_free(&m_stat->invb);
segundo 0:ac1725ba162c 1169 return ERR_ARG;
segundo 0:ac1725ba162c 1170 }
segundo 0:ac1725ba162c 1171
segundo 0:ac1725ba162c 1172 switch (type)
segundo 0:ac1725ba162c 1173 {
segundo 0:ac1725ba162c 1174 case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG):
segundo 0:ac1725ba162c 1175 vb = snmp_varbind_alloc(&oid, type, sizeof(s32_t));
segundo 0:ac1725ba162c 1176 if (vb != NULL)
segundo 0:ac1725ba162c 1177 {
segundo 0:ac1725ba162c 1178 s32_t *vptr = (s32_t*)vb->value;
segundo 0:ac1725ba162c 1179
segundo 0:ac1725ba162c 1180 derr = snmp_asn1_dec_s32t(p, ofs + 1 + len_octets, len, vptr);
segundo 0:ac1725ba162c 1181 snmp_varbind_tail_add(&m_stat->invb, vb);
segundo 0:ac1725ba162c 1182 }
segundo 0:ac1725ba162c 1183 else
segundo 0:ac1725ba162c 1184 {
segundo 0:ac1725ba162c 1185 derr = ERR_ARG;
segundo 0:ac1725ba162c 1186 }
segundo 0:ac1725ba162c 1187 break;
segundo 0:ac1725ba162c 1188 case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_COUNTER):
segundo 0:ac1725ba162c 1189 case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_GAUGE):
segundo 0:ac1725ba162c 1190 case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_TIMETICKS):
segundo 0:ac1725ba162c 1191 vb = snmp_varbind_alloc(&oid, type, sizeof(u32_t));
segundo 0:ac1725ba162c 1192 if (vb != NULL)
segundo 0:ac1725ba162c 1193 {
segundo 0:ac1725ba162c 1194 u32_t *vptr = (u32_t*)vb->value;
segundo 0:ac1725ba162c 1195
segundo 0:ac1725ba162c 1196 derr = snmp_asn1_dec_u32t(p, ofs + 1 + len_octets, len, vptr);
segundo 0:ac1725ba162c 1197 snmp_varbind_tail_add(&m_stat->invb, vb);
segundo 0:ac1725ba162c 1198 }
segundo 0:ac1725ba162c 1199 else
segundo 0:ac1725ba162c 1200 {
segundo 0:ac1725ba162c 1201 derr = ERR_ARG;
segundo 0:ac1725ba162c 1202 }
segundo 0:ac1725ba162c 1203 break;
segundo 0:ac1725ba162c 1204 case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR):
segundo 0:ac1725ba162c 1205 case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_OPAQUE):
segundo 0:ac1725ba162c 1206 LWIP_ASSERT("invalid length", len <= 0xff);
segundo 0:ac1725ba162c 1207 vb = snmp_varbind_alloc(&oid, type, (u8_t)len);
segundo 0:ac1725ba162c 1208 if (vb != NULL)
segundo 0:ac1725ba162c 1209 {
segundo 0:ac1725ba162c 1210 derr = snmp_asn1_dec_raw(p, ofs + 1 + len_octets, len, vb->value_len, (u8_t*)vb->value);
segundo 0:ac1725ba162c 1211 snmp_varbind_tail_add(&m_stat->invb, vb);
segundo 0:ac1725ba162c 1212 }
segundo 0:ac1725ba162c 1213 else
segundo 0:ac1725ba162c 1214 {
segundo 0:ac1725ba162c 1215 derr = ERR_ARG;
segundo 0:ac1725ba162c 1216 }
segundo 0:ac1725ba162c 1217 break;
segundo 0:ac1725ba162c 1218 case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_NUL):
segundo 0:ac1725ba162c 1219 vb = snmp_varbind_alloc(&oid, type, 0);
segundo 0:ac1725ba162c 1220 if (vb != NULL)
segundo 0:ac1725ba162c 1221 {
segundo 0:ac1725ba162c 1222 snmp_varbind_tail_add(&m_stat->invb, vb);
segundo 0:ac1725ba162c 1223 derr = ERR_OK;
segundo 0:ac1725ba162c 1224 }
segundo 0:ac1725ba162c 1225 else
segundo 0:ac1725ba162c 1226 {
segundo 0:ac1725ba162c 1227 derr = ERR_ARG;
segundo 0:ac1725ba162c 1228 }
segundo 0:ac1725ba162c 1229 break;
segundo 0:ac1725ba162c 1230 case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OBJ_ID):
segundo 0:ac1725ba162c 1231 derr = snmp_asn1_dec_oid(p, ofs + 1 + len_octets, len, &oid_value);
segundo 0:ac1725ba162c 1232 if (derr == ERR_OK)
segundo 0:ac1725ba162c 1233 {
segundo 0:ac1725ba162c 1234 vb = snmp_varbind_alloc(&oid, type, oid_value.len * sizeof(s32_t));
segundo 0:ac1725ba162c 1235 if (vb != NULL)
segundo 0:ac1725ba162c 1236 {
segundo 0:ac1725ba162c 1237 u8_t i = oid_value.len;
segundo 0:ac1725ba162c 1238 s32_t *vptr = (s32_t*)vb->value;
segundo 0:ac1725ba162c 1239
segundo 0:ac1725ba162c 1240 while(i > 0)
segundo 0:ac1725ba162c 1241 {
segundo 0:ac1725ba162c 1242 i--;
segundo 0:ac1725ba162c 1243 vptr[i] = oid_value.id[i];
segundo 0:ac1725ba162c 1244 }
segundo 0:ac1725ba162c 1245 snmp_varbind_tail_add(&m_stat->invb, vb);
segundo 0:ac1725ba162c 1246 derr = ERR_OK;
segundo 0:ac1725ba162c 1247 }
segundo 0:ac1725ba162c 1248 else
segundo 0:ac1725ba162c 1249 {
segundo 0:ac1725ba162c 1250 derr = ERR_ARG;
segundo 0:ac1725ba162c 1251 }
segundo 0:ac1725ba162c 1252 }
segundo 0:ac1725ba162c 1253 break;
segundo 0:ac1725ba162c 1254 case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_IPADDR):
segundo 0:ac1725ba162c 1255 if (len == 4)
segundo 0:ac1725ba162c 1256 {
segundo 0:ac1725ba162c 1257 /* must be exactly 4 octets! */
segundo 0:ac1725ba162c 1258 vb = snmp_varbind_alloc(&oid, type, 4);
segundo 0:ac1725ba162c 1259 if (vb != NULL)
segundo 0:ac1725ba162c 1260 {
segundo 0:ac1725ba162c 1261 derr = snmp_asn1_dec_raw(p, ofs + 1 + len_octets, len, vb->value_len, (u8_t*)vb->value);
segundo 0:ac1725ba162c 1262 snmp_varbind_tail_add(&m_stat->invb, vb);
segundo 0:ac1725ba162c 1263 }
segundo 0:ac1725ba162c 1264 else
segundo 0:ac1725ba162c 1265 {
segundo 0:ac1725ba162c 1266 derr = ERR_ARG;
segundo 0:ac1725ba162c 1267 }
segundo 0:ac1725ba162c 1268 }
segundo 0:ac1725ba162c 1269 else
segundo 0:ac1725ba162c 1270 {
segundo 0:ac1725ba162c 1271 derr = ERR_ARG;
segundo 0:ac1725ba162c 1272 }
segundo 0:ac1725ba162c 1273 break;
segundo 0:ac1725ba162c 1274 default:
segundo 0:ac1725ba162c 1275 derr = ERR_ARG;
segundo 0:ac1725ba162c 1276 break;
segundo 0:ac1725ba162c 1277 }
segundo 0:ac1725ba162c 1278 if (derr != ERR_OK)
segundo 0:ac1725ba162c 1279 {
segundo 0:ac1725ba162c 1280 snmp_inc_snmpinasnparseerrs();
segundo 0:ac1725ba162c 1281 /* free varbinds (if available) */
segundo 0:ac1725ba162c 1282 snmp_varbind_list_free(&m_stat->invb);
segundo 0:ac1725ba162c 1283 return ERR_ARG;
segundo 0:ac1725ba162c 1284 }
segundo 0:ac1725ba162c 1285 ofs += (1 + len_octets + len);
segundo 0:ac1725ba162c 1286 vb_len -= (1 + len_octets + len);
segundo 0:ac1725ba162c 1287 }
segundo 0:ac1725ba162c 1288
segundo 0:ac1725ba162c 1289 if (m_stat->rt == SNMP_ASN1_PDU_SET_REQ)
segundo 0:ac1725ba162c 1290 {
segundo 0:ac1725ba162c 1291 snmp_add_snmpintotalsetvars(m_stat->invb.count);
segundo 0:ac1725ba162c 1292 }
segundo 0:ac1725ba162c 1293 else
segundo 0:ac1725ba162c 1294 {
segundo 0:ac1725ba162c 1295 snmp_add_snmpintotalreqvars(m_stat->invb.count);
segundo 0:ac1725ba162c 1296 }
segundo 0:ac1725ba162c 1297
segundo 0:ac1725ba162c 1298 *ofs_ret = ofs;
segundo 0:ac1725ba162c 1299 return ERR_OK;
segundo 0:ac1725ba162c 1300 }
segundo 0:ac1725ba162c 1301
segundo 0:ac1725ba162c 1302 struct snmp_varbind*
segundo 0:ac1725ba162c 1303 snmp_varbind_alloc(struct snmp_obj_id *oid, u8_t type, u8_t len)
segundo 0:ac1725ba162c 1304 {
segundo 0:ac1725ba162c 1305 struct snmp_varbind *vb;
segundo 0:ac1725ba162c 1306
segundo 0:ac1725ba162c 1307 vb = (struct snmp_varbind *)memp_malloc(MEMP_SNMP_VARBIND);
segundo 0:ac1725ba162c 1308 LWIP_ASSERT("vb != NULL",vb != NULL);
segundo 0:ac1725ba162c 1309 if (vb != NULL)
segundo 0:ac1725ba162c 1310 {
segundo 0:ac1725ba162c 1311 u8_t i;
segundo 0:ac1725ba162c 1312
segundo 0:ac1725ba162c 1313 vb->next = NULL;
segundo 0:ac1725ba162c 1314 vb->prev = NULL;
segundo 0:ac1725ba162c 1315 i = oid->len;
segundo 0:ac1725ba162c 1316 vb->ident_len = i;
segundo 0:ac1725ba162c 1317 if (i > 0)
segundo 0:ac1725ba162c 1318 {
segundo 0:ac1725ba162c 1319 LWIP_ASSERT("SNMP_MAX_TREE_DEPTH is configured too low", i <= SNMP_MAX_TREE_DEPTH);
segundo 0:ac1725ba162c 1320 /* allocate array of s32_t for our object identifier */
segundo 0:ac1725ba162c 1321 vb->ident = (s32_t*)memp_malloc(MEMP_SNMP_VALUE);
segundo 0:ac1725ba162c 1322 LWIP_ASSERT("vb->ident != NULL",vb->ident != NULL);
segundo 0:ac1725ba162c 1323 if (vb->ident == NULL)
segundo 0:ac1725ba162c 1324 {
segundo 0:ac1725ba162c 1325 memp_free(MEMP_SNMP_VARBIND, vb);
segundo 0:ac1725ba162c 1326 return NULL;
segundo 0:ac1725ba162c 1327 }
segundo 0:ac1725ba162c 1328 while(i > 0)
segundo 0:ac1725ba162c 1329 {
segundo 0:ac1725ba162c 1330 i--;
segundo 0:ac1725ba162c 1331 vb->ident[i] = oid->id[i];
segundo 0:ac1725ba162c 1332 }
segundo 0:ac1725ba162c 1333 }
segundo 0:ac1725ba162c 1334 else
segundo 0:ac1725ba162c 1335 {
segundo 0:ac1725ba162c 1336 /* i == 0, pass zero length object identifier */
segundo 0:ac1725ba162c 1337 vb->ident = NULL;
segundo 0:ac1725ba162c 1338 }
segundo 0:ac1725ba162c 1339 vb->value_type = type;
segundo 0:ac1725ba162c 1340 vb->value_len = len;
segundo 0:ac1725ba162c 1341 if (len > 0)
segundo 0:ac1725ba162c 1342 {
segundo 0:ac1725ba162c 1343 LWIP_ASSERT("SNMP_MAX_OCTET_STRING_LEN is configured too low", vb->value_len <= SNMP_MAX_VALUE_SIZE);
segundo 0:ac1725ba162c 1344 /* allocate raw bytes for our object value */
segundo 0:ac1725ba162c 1345 vb->value = memp_malloc(MEMP_SNMP_VALUE);
segundo 0:ac1725ba162c 1346 LWIP_ASSERT("vb->value != NULL",vb->value != NULL);
segundo 0:ac1725ba162c 1347 if (vb->value == NULL)
segundo 0:ac1725ba162c 1348 {
segundo 0:ac1725ba162c 1349 if (vb->ident != NULL)
segundo 0:ac1725ba162c 1350 {
segundo 0:ac1725ba162c 1351 memp_free(MEMP_SNMP_VALUE, vb->ident);
segundo 0:ac1725ba162c 1352 }
segundo 0:ac1725ba162c 1353 memp_free(MEMP_SNMP_VARBIND, vb);
segundo 0:ac1725ba162c 1354 return NULL;
segundo 0:ac1725ba162c 1355 }
segundo 0:ac1725ba162c 1356 }
segundo 0:ac1725ba162c 1357 else
segundo 0:ac1725ba162c 1358 {
segundo 0:ac1725ba162c 1359 /* ASN1_NUL type, or zero length ASN1_OC_STR */
segundo 0:ac1725ba162c 1360 vb->value = NULL;
segundo 0:ac1725ba162c 1361 }
segundo 0:ac1725ba162c 1362 }
segundo 0:ac1725ba162c 1363 return vb;
segundo 0:ac1725ba162c 1364 }
segundo 0:ac1725ba162c 1365
segundo 0:ac1725ba162c 1366 void
segundo 0:ac1725ba162c 1367 snmp_varbind_free(struct snmp_varbind *vb)
segundo 0:ac1725ba162c 1368 {
segundo 0:ac1725ba162c 1369 if (vb->value != NULL )
segundo 0:ac1725ba162c 1370 {
segundo 0:ac1725ba162c 1371 memp_free(MEMP_SNMP_VALUE, vb->value);
segundo 0:ac1725ba162c 1372 }
segundo 0:ac1725ba162c 1373 if (vb->ident != NULL )
segundo 0:ac1725ba162c 1374 {
segundo 0:ac1725ba162c 1375 memp_free(MEMP_SNMP_VALUE, vb->ident);
segundo 0:ac1725ba162c 1376 }
segundo 0:ac1725ba162c 1377 memp_free(MEMP_SNMP_VARBIND, vb);
segundo 0:ac1725ba162c 1378 }
segundo 0:ac1725ba162c 1379
segundo 0:ac1725ba162c 1380 void
segundo 0:ac1725ba162c 1381 snmp_varbind_list_free(struct snmp_varbind_root *root)
segundo 0:ac1725ba162c 1382 {
segundo 0:ac1725ba162c 1383 struct snmp_varbind *vb, *prev;
segundo 0:ac1725ba162c 1384
segundo 0:ac1725ba162c 1385 vb = root->tail;
segundo 0:ac1725ba162c 1386 while ( vb != NULL )
segundo 0:ac1725ba162c 1387 {
segundo 0:ac1725ba162c 1388 prev = vb->prev;
segundo 0:ac1725ba162c 1389 snmp_varbind_free(vb);
segundo 0:ac1725ba162c 1390 vb = prev;
segundo 0:ac1725ba162c 1391 }
segundo 0:ac1725ba162c 1392 root->count = 0;
segundo 0:ac1725ba162c 1393 root->head = NULL;
segundo 0:ac1725ba162c 1394 root->tail = NULL;
segundo 0:ac1725ba162c 1395 }
segundo 0:ac1725ba162c 1396
segundo 0:ac1725ba162c 1397 void
segundo 0:ac1725ba162c 1398 snmp_varbind_tail_add(struct snmp_varbind_root *root, struct snmp_varbind *vb)
segundo 0:ac1725ba162c 1399 {
segundo 0:ac1725ba162c 1400 if (root->count == 0)
segundo 0:ac1725ba162c 1401 {
segundo 0:ac1725ba162c 1402 /* add first varbind to list */
segundo 0:ac1725ba162c 1403 root->head = vb;
segundo 0:ac1725ba162c 1404 root->tail = vb;
segundo 0:ac1725ba162c 1405 }
segundo 0:ac1725ba162c 1406 else
segundo 0:ac1725ba162c 1407 {
segundo 0:ac1725ba162c 1408 /* add nth varbind to list tail */
segundo 0:ac1725ba162c 1409 root->tail->next = vb;
segundo 0:ac1725ba162c 1410 vb->prev = root->tail;
segundo 0:ac1725ba162c 1411 root->tail = vb;
segundo 0:ac1725ba162c 1412 }
segundo 0:ac1725ba162c 1413 root->count += 1;
segundo 0:ac1725ba162c 1414 }
segundo 0:ac1725ba162c 1415
segundo 0:ac1725ba162c 1416 struct snmp_varbind*
segundo 0:ac1725ba162c 1417 snmp_varbind_tail_remove(struct snmp_varbind_root *root)
segundo 0:ac1725ba162c 1418 {
segundo 0:ac1725ba162c 1419 struct snmp_varbind* vb;
segundo 0:ac1725ba162c 1420
segundo 0:ac1725ba162c 1421 if (root->count > 0)
segundo 0:ac1725ba162c 1422 {
segundo 0:ac1725ba162c 1423 /* remove tail varbind */
segundo 0:ac1725ba162c 1424 vb = root->tail;
segundo 0:ac1725ba162c 1425 root->tail = vb->prev;
segundo 0:ac1725ba162c 1426 vb->prev->next = NULL;
segundo 0:ac1725ba162c 1427 root->count -= 1;
segundo 0:ac1725ba162c 1428 }
segundo 0:ac1725ba162c 1429 else
segundo 0:ac1725ba162c 1430 {
segundo 0:ac1725ba162c 1431 /* nothing to remove */
segundo 0:ac1725ba162c 1432 vb = NULL;
segundo 0:ac1725ba162c 1433 }
segundo 0:ac1725ba162c 1434 return vb;
segundo 0:ac1725ba162c 1435 }
segundo 0:ac1725ba162c 1436
segundo 0:ac1725ba162c 1437 #endif /* LWIP_SNMP */