ProjetoBB

Dependencies:   F7_Ethernet WebSocketClient mbed mcp3008

Fork of Nucleo_F746ZG_Ethernet by Dieter Graef

Committer:
DieterGraef
Date:
Sat Jun 18 10:49:12 2016 +0000
Revision:
0:f9b6112278fe
Ethernet for the NUCLEO STM32F746 Board Testprogram uses DHCP and NTP to set the clock

Who changed what in which revision?

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