Some quick code to use UDP-only (no TCP) with mBed. Echos received packets and sends packets when a button is pressed

Dependencies:   mbed

Committer:
pehrhovey
Date:
Sun Mar 14 00:54:12 2010 +0000
Revision:
0:a548a085de55

        

Who changed what in which revision?

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