Ethernet for Nucleo and Disco board STM32F746 works with gcc and arm. IAC is untested

Dependencies:   mbed-rtos

Dependents:   IMU_ethernet

Fork of F7_Ethernet by Dieter Graef

Committer:
rctaduio
Date:
Thu Oct 06 16:55:16 2016 +0000
Revision:
2:e0a4035b5cd1
Parent:
0:d26c1b55cfca
Ethernet library for F7

Who changed what in which revision?

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