Example program with HTTPServer and sensor data streaming over TCPSockets, using Donatien Garnier's Net APIs and services code on top of LWIP. Files StreamServer.h and .cpp encapsulate streaming over TCPSockets. Broadcast is done by sendToAll(), and all incoming data is echoed back to the client. Echo code can be replaced with some remote control of the streaming interface. See main() that shows how to periodically send some data to all subscribed clients. To subscribe, a client should open a socket at <mbed_ip> port 123. I used few lines in TCL code to set up a quick sink for the data. HTTP files are served on port 80 concurrently to the streaming.

Dependencies:   mbed

Committer:
iva2k
Date:
Sat Jun 12 06:01:50 2010 +0000
Revision:
0:e614f7875b60

        

Who changed what in which revision?

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