Web server based weather station using Sparkfun Weather Meters.

Dependencies:   FatFileSystem mbed WeatherMeters SDFileSystem

Committer:
AdamGreen
Date:
Thu Feb 23 21:38:39 2012 +0000
Revision:
0:616601bde9fb

        

Who changed what in which revision?

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