SNMP agent attached to SPI slave

Dependencies:   mbed

Committer:
lorcansmith
Date:
Mon Aug 13 15:07:40 2012 +0000
Revision:
0:2a53a4c3238c
v1.1 release includes ioAlarm traps

Who changed what in which revision?

UserRevisionLine numberNew contents of line
lorcansmith 0:2a53a4c3238c 1 /**
lorcansmith 0:2a53a4c3238c 2 * @file
lorcansmith 0:2a53a4c3238c 3 * Abstract Syntax Notation One (ISO 8824, 8825) decoding
lorcansmith 0:2a53a4c3238c 4 *
lorcansmith 0:2a53a4c3238c 5 * @todo not optimised (yet), favor correctness over speed, favor speed over size
lorcansmith 0:2a53a4c3238c 6 */
lorcansmith 0:2a53a4c3238c 7
lorcansmith 0:2a53a4c3238c 8 /*
lorcansmith 0:2a53a4c3238c 9 * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands.
lorcansmith 0:2a53a4c3238c 10 * All rights reserved.
lorcansmith 0:2a53a4c3238c 11 *
lorcansmith 0:2a53a4c3238c 12 * Redistribution and use in source and binary forms, with or without modification,
lorcansmith 0:2a53a4c3238c 13 * are permitted provided that the following conditions are met:
lorcansmith 0:2a53a4c3238c 14 *
lorcansmith 0:2a53a4c3238c 15 * 1. Redistributions of source code must retain the above copyright notice,
lorcansmith 0:2a53a4c3238c 16 * this list of conditions and the following disclaimer.
lorcansmith 0:2a53a4c3238c 17 * 2. Redistributions in binary form must reproduce the above copyright notice,
lorcansmith 0:2a53a4c3238c 18 * this list of conditions and the following disclaimer in the documentation
lorcansmith 0:2a53a4c3238c 19 * and/or other materials provided with the distribution.
lorcansmith 0:2a53a4c3238c 20 * 3. The name of the author may not be used to endorse or promote products
lorcansmith 0:2a53a4c3238c 21 * derived from this software without specific prior written permission.
lorcansmith 0:2a53a4c3238c 22 *
lorcansmith 0:2a53a4c3238c 23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
lorcansmith 0:2a53a4c3238c 24 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
lorcansmith 0:2a53a4c3238c 25 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
lorcansmith 0:2a53a4c3238c 26 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
lorcansmith 0:2a53a4c3238c 27 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
lorcansmith 0:2a53a4c3238c 28 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
lorcansmith 0:2a53a4c3238c 29 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
lorcansmith 0:2a53a4c3238c 30 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
lorcansmith 0:2a53a4c3238c 31 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
lorcansmith 0:2a53a4c3238c 32 * OF SUCH DAMAGE.
lorcansmith 0:2a53a4c3238c 33 *
lorcansmith 0:2a53a4c3238c 34 * Author: Christiaan Simons <christiaan.simons@axon.tv>
lorcansmith 0:2a53a4c3238c 35 */
lorcansmith 0:2a53a4c3238c 36
lorcansmith 0:2a53a4c3238c 37 #include "lwip/opt.h"
lorcansmith 0:2a53a4c3238c 38
lorcansmith 0:2a53a4c3238c 39 #if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */
lorcansmith 0:2a53a4c3238c 40
lorcansmith 0:2a53a4c3238c 41 #include "lwip/snmp_asn1.h"
lorcansmith 0:2a53a4c3238c 42
lorcansmith 0:2a53a4c3238c 43 /**
lorcansmith 0:2a53a4c3238c 44 * Retrieves type field from incoming pbuf chain.
lorcansmith 0:2a53a4c3238c 45 *
lorcansmith 0:2a53a4c3238c 46 * @param p points to a pbuf holding an ASN1 coded type field
lorcansmith 0:2a53a4c3238c 47 * @param ofs points to the offset within the pbuf chain of the ASN1 coded type field
lorcansmith 0:2a53a4c3238c 48 * @param type return ASN1 type
lorcansmith 0:2a53a4c3238c 49 * @return ERR_OK if successfull, ERR_ARG if we can't (or won't) decode
lorcansmith 0:2a53a4c3238c 50 */
lorcansmith 0:2a53a4c3238c 51 err_t
lorcansmith 0:2a53a4c3238c 52 snmp_asn1_dec_type(struct pbuf *p, u16_t ofs, u8_t *type)
lorcansmith 0:2a53a4c3238c 53 {
lorcansmith 0:2a53a4c3238c 54 u16_t plen, base;
lorcansmith 0:2a53a4c3238c 55 u8_t *msg_ptr;
lorcansmith 0:2a53a4c3238c 56
lorcansmith 0:2a53a4c3238c 57 plen = 0;
lorcansmith 0:2a53a4c3238c 58 while (p != NULL)
lorcansmith 0:2a53a4c3238c 59 {
lorcansmith 0:2a53a4c3238c 60 base = plen;
lorcansmith 0:2a53a4c3238c 61 plen += p->len;
lorcansmith 0:2a53a4c3238c 62 if (ofs < plen)
lorcansmith 0:2a53a4c3238c 63 {
lorcansmith 0:2a53a4c3238c 64 msg_ptr = (u8_t*)p->payload;
lorcansmith 0:2a53a4c3238c 65 msg_ptr += ofs - base;
lorcansmith 0:2a53a4c3238c 66 *type = *msg_ptr;
lorcansmith 0:2a53a4c3238c 67 return ERR_OK;
lorcansmith 0:2a53a4c3238c 68 }
lorcansmith 0:2a53a4c3238c 69 p = p->next;
lorcansmith 0:2a53a4c3238c 70 }
lorcansmith 0:2a53a4c3238c 71 /* p == NULL, ofs >= plen */
lorcansmith 0:2a53a4c3238c 72 return ERR_ARG;
lorcansmith 0:2a53a4c3238c 73 }
lorcansmith 0:2a53a4c3238c 74
lorcansmith 0:2a53a4c3238c 75 /**
lorcansmith 0:2a53a4c3238c 76 * Decodes length field from incoming pbuf chain into host length.
lorcansmith 0:2a53a4c3238c 77 *
lorcansmith 0:2a53a4c3238c 78 * @param p points to a pbuf holding an ASN1 coded length
lorcansmith 0:2a53a4c3238c 79 * @param ofs points to the offset within the pbuf chain of the ASN1 coded length
lorcansmith 0:2a53a4c3238c 80 * @param octets_used returns number of octets used by the length code
lorcansmith 0:2a53a4c3238c 81 * @param length return host order length, upto 64k
lorcansmith 0:2a53a4c3238c 82 * @return ERR_OK if successfull, ERR_ARG if we can't (or won't) decode
lorcansmith 0:2a53a4c3238c 83 */
lorcansmith 0:2a53a4c3238c 84 err_t
lorcansmith 0:2a53a4c3238c 85 snmp_asn1_dec_length(struct pbuf *p, u16_t ofs, u8_t *octets_used, u16_t *length)
lorcansmith 0:2a53a4c3238c 86 {
lorcansmith 0:2a53a4c3238c 87 u16_t plen, base;
lorcansmith 0:2a53a4c3238c 88 u8_t *msg_ptr;
lorcansmith 0:2a53a4c3238c 89
lorcansmith 0:2a53a4c3238c 90 plen = 0;
lorcansmith 0:2a53a4c3238c 91 while (p != NULL)
lorcansmith 0:2a53a4c3238c 92 {
lorcansmith 0:2a53a4c3238c 93 base = plen;
lorcansmith 0:2a53a4c3238c 94 plen += p->len;
lorcansmith 0:2a53a4c3238c 95 if (ofs < plen)
lorcansmith 0:2a53a4c3238c 96 {
lorcansmith 0:2a53a4c3238c 97 msg_ptr = (u8_t*)p->payload;
lorcansmith 0:2a53a4c3238c 98 msg_ptr += ofs - base;
lorcansmith 0:2a53a4c3238c 99
lorcansmith 0:2a53a4c3238c 100 if (*msg_ptr < 0x80)
lorcansmith 0:2a53a4c3238c 101 {
lorcansmith 0:2a53a4c3238c 102 /* primitive definite length format */
lorcansmith 0:2a53a4c3238c 103 *octets_used = 1;
lorcansmith 0:2a53a4c3238c 104 *length = *msg_ptr;
lorcansmith 0:2a53a4c3238c 105 return ERR_OK;
lorcansmith 0:2a53a4c3238c 106 }
lorcansmith 0:2a53a4c3238c 107 else if (*msg_ptr == 0x80)
lorcansmith 0:2a53a4c3238c 108 {
lorcansmith 0:2a53a4c3238c 109 /* constructed indefinite length format, termination with two zero octets */
lorcansmith 0:2a53a4c3238c 110 u8_t zeros;
lorcansmith 0:2a53a4c3238c 111 u8_t i;
lorcansmith 0:2a53a4c3238c 112
lorcansmith 0:2a53a4c3238c 113 *length = 0;
lorcansmith 0:2a53a4c3238c 114 zeros = 0;
lorcansmith 0:2a53a4c3238c 115 while (zeros != 2)
lorcansmith 0:2a53a4c3238c 116 {
lorcansmith 0:2a53a4c3238c 117 i = 2;
lorcansmith 0:2a53a4c3238c 118 while (i > 0)
lorcansmith 0:2a53a4c3238c 119 {
lorcansmith 0:2a53a4c3238c 120 i--;
lorcansmith 0:2a53a4c3238c 121 (*length) += 1;
lorcansmith 0:2a53a4c3238c 122 ofs += 1;
lorcansmith 0:2a53a4c3238c 123 if (ofs >= plen)
lorcansmith 0:2a53a4c3238c 124 {
lorcansmith 0:2a53a4c3238c 125 /* next octet in next pbuf */
lorcansmith 0:2a53a4c3238c 126 p = p->next;
lorcansmith 0:2a53a4c3238c 127 if (p == NULL) { return ERR_ARG; }
lorcansmith 0:2a53a4c3238c 128 msg_ptr = (u8_t*)p->payload;
lorcansmith 0:2a53a4c3238c 129 plen += p->len;
lorcansmith 0:2a53a4c3238c 130 }
lorcansmith 0:2a53a4c3238c 131 else
lorcansmith 0:2a53a4c3238c 132 {
lorcansmith 0:2a53a4c3238c 133 /* next octet in same pbuf */
lorcansmith 0:2a53a4c3238c 134 msg_ptr++;
lorcansmith 0:2a53a4c3238c 135 }
lorcansmith 0:2a53a4c3238c 136 if (*msg_ptr == 0)
lorcansmith 0:2a53a4c3238c 137 {
lorcansmith 0:2a53a4c3238c 138 zeros++;
lorcansmith 0:2a53a4c3238c 139 if (zeros == 2)
lorcansmith 0:2a53a4c3238c 140 {
lorcansmith 0:2a53a4c3238c 141 /* stop while (i > 0) */
lorcansmith 0:2a53a4c3238c 142 i = 0;
lorcansmith 0:2a53a4c3238c 143 }
lorcansmith 0:2a53a4c3238c 144 }
lorcansmith 0:2a53a4c3238c 145 else
lorcansmith 0:2a53a4c3238c 146 {
lorcansmith 0:2a53a4c3238c 147 zeros = 0;
lorcansmith 0:2a53a4c3238c 148 }
lorcansmith 0:2a53a4c3238c 149 }
lorcansmith 0:2a53a4c3238c 150 }
lorcansmith 0:2a53a4c3238c 151 *octets_used = 1;
lorcansmith 0:2a53a4c3238c 152 return ERR_OK;
lorcansmith 0:2a53a4c3238c 153 }
lorcansmith 0:2a53a4c3238c 154 else if (*msg_ptr == 0x81)
lorcansmith 0:2a53a4c3238c 155 {
lorcansmith 0:2a53a4c3238c 156 /* constructed definite length format, one octet */
lorcansmith 0:2a53a4c3238c 157 ofs += 1;
lorcansmith 0:2a53a4c3238c 158 if (ofs >= plen)
lorcansmith 0:2a53a4c3238c 159 {
lorcansmith 0:2a53a4c3238c 160 /* next octet in next pbuf */
lorcansmith 0:2a53a4c3238c 161 p = p->next;
lorcansmith 0:2a53a4c3238c 162 if (p == NULL) { return ERR_ARG; }
lorcansmith 0:2a53a4c3238c 163 msg_ptr = (u8_t*)p->payload;
lorcansmith 0:2a53a4c3238c 164 }
lorcansmith 0:2a53a4c3238c 165 else
lorcansmith 0:2a53a4c3238c 166 {
lorcansmith 0:2a53a4c3238c 167 /* next octet in same pbuf */
lorcansmith 0:2a53a4c3238c 168 msg_ptr++;
lorcansmith 0:2a53a4c3238c 169 }
lorcansmith 0:2a53a4c3238c 170 *length = *msg_ptr;
lorcansmith 0:2a53a4c3238c 171 *octets_used = 2;
lorcansmith 0:2a53a4c3238c 172 return ERR_OK;
lorcansmith 0:2a53a4c3238c 173 }
lorcansmith 0:2a53a4c3238c 174 else if (*msg_ptr == 0x82)
lorcansmith 0:2a53a4c3238c 175 {
lorcansmith 0:2a53a4c3238c 176 u8_t i;
lorcansmith 0:2a53a4c3238c 177
lorcansmith 0:2a53a4c3238c 178 /* constructed definite length format, two octets */
lorcansmith 0:2a53a4c3238c 179 i = 2;
lorcansmith 0:2a53a4c3238c 180 while (i > 0)
lorcansmith 0:2a53a4c3238c 181 {
lorcansmith 0:2a53a4c3238c 182 i--;
lorcansmith 0:2a53a4c3238c 183 ofs += 1;
lorcansmith 0:2a53a4c3238c 184 if (ofs >= plen)
lorcansmith 0:2a53a4c3238c 185 {
lorcansmith 0:2a53a4c3238c 186 /* next octet in next pbuf */
lorcansmith 0:2a53a4c3238c 187 p = p->next;
lorcansmith 0:2a53a4c3238c 188 if (p == NULL) { return ERR_ARG; }
lorcansmith 0:2a53a4c3238c 189 msg_ptr = (u8_t*)p->payload;
lorcansmith 0:2a53a4c3238c 190 plen += p->len;
lorcansmith 0:2a53a4c3238c 191 }
lorcansmith 0:2a53a4c3238c 192 else
lorcansmith 0:2a53a4c3238c 193 {
lorcansmith 0:2a53a4c3238c 194 /* next octet in same pbuf */
lorcansmith 0:2a53a4c3238c 195 msg_ptr++;
lorcansmith 0:2a53a4c3238c 196 }
lorcansmith 0:2a53a4c3238c 197 if (i == 0)
lorcansmith 0:2a53a4c3238c 198 {
lorcansmith 0:2a53a4c3238c 199 /* least significant length octet */
lorcansmith 0:2a53a4c3238c 200 *length |= *msg_ptr;
lorcansmith 0:2a53a4c3238c 201 }
lorcansmith 0:2a53a4c3238c 202 else
lorcansmith 0:2a53a4c3238c 203 {
lorcansmith 0:2a53a4c3238c 204 /* most significant length octet */
lorcansmith 0:2a53a4c3238c 205 *length = (*msg_ptr) << 8;
lorcansmith 0:2a53a4c3238c 206 }
lorcansmith 0:2a53a4c3238c 207 }
lorcansmith 0:2a53a4c3238c 208 *octets_used = 3;
lorcansmith 0:2a53a4c3238c 209 return ERR_OK;
lorcansmith 0:2a53a4c3238c 210 }
lorcansmith 0:2a53a4c3238c 211 else
lorcansmith 0:2a53a4c3238c 212 {
lorcansmith 0:2a53a4c3238c 213 /* constructed definite length format 3..127 octets, this is too big (>64k) */
lorcansmith 0:2a53a4c3238c 214 /** @todo: do we need to accept inefficient codings with many leading zero's? */
lorcansmith 0:2a53a4c3238c 215 *octets_used = 1 + ((*msg_ptr) & 0x7f);
lorcansmith 0:2a53a4c3238c 216 return ERR_ARG;
lorcansmith 0:2a53a4c3238c 217 }
lorcansmith 0:2a53a4c3238c 218 }
lorcansmith 0:2a53a4c3238c 219 p = p->next;
lorcansmith 0:2a53a4c3238c 220 }
lorcansmith 0:2a53a4c3238c 221
lorcansmith 0:2a53a4c3238c 222 /* p == NULL, ofs >= plen */
lorcansmith 0:2a53a4c3238c 223 return ERR_ARG;
lorcansmith 0:2a53a4c3238c 224 }
lorcansmith 0:2a53a4c3238c 225
lorcansmith 0:2a53a4c3238c 226 /**
lorcansmith 0:2a53a4c3238c 227 * Decodes positive integer (counter, gauge, timeticks) into u32_t.
lorcansmith 0:2a53a4c3238c 228 *
lorcansmith 0:2a53a4c3238c 229 * @param p points to a pbuf holding an ASN1 coded integer
lorcansmith 0:2a53a4c3238c 230 * @param ofs points to the offset within the pbuf chain of the ASN1 coded integer
lorcansmith 0:2a53a4c3238c 231 * @param len length of the coded integer field
lorcansmith 0:2a53a4c3238c 232 * @param value return host order integer
lorcansmith 0:2a53a4c3238c 233 * @return ERR_OK if successfull, ERR_ARG if we can't (or won't) decode
lorcansmith 0:2a53a4c3238c 234 *
lorcansmith 0:2a53a4c3238c 235 * @note ASN coded integers are _always_ signed. E.g. +0xFFFF is coded
lorcansmith 0:2a53a4c3238c 236 * as 0x00,0xFF,0xFF. Note the leading sign octet. A positive value
lorcansmith 0:2a53a4c3238c 237 * of 0xFFFFFFFF is preceded with 0x00 and the length is 5 octets!!
lorcansmith 0:2a53a4c3238c 238 */
lorcansmith 0:2a53a4c3238c 239 err_t
lorcansmith 0:2a53a4c3238c 240 snmp_asn1_dec_u32t(struct pbuf *p, u16_t ofs, u16_t len, u32_t *value)
lorcansmith 0:2a53a4c3238c 241 {
lorcansmith 0:2a53a4c3238c 242 u16_t plen, base;
lorcansmith 0:2a53a4c3238c 243 u8_t *msg_ptr;
lorcansmith 0:2a53a4c3238c 244
lorcansmith 0:2a53a4c3238c 245 plen = 0;
lorcansmith 0:2a53a4c3238c 246 while (p != NULL)
lorcansmith 0:2a53a4c3238c 247 {
lorcansmith 0:2a53a4c3238c 248 base = plen;
lorcansmith 0:2a53a4c3238c 249 plen += p->len;
lorcansmith 0:2a53a4c3238c 250 if (ofs < plen)
lorcansmith 0:2a53a4c3238c 251 {
lorcansmith 0:2a53a4c3238c 252 msg_ptr = (u8_t*)p->payload;
lorcansmith 0:2a53a4c3238c 253 msg_ptr += ofs - base;
lorcansmith 0:2a53a4c3238c 254 if ((len > 0) && (len < 6))
lorcansmith 0:2a53a4c3238c 255 {
lorcansmith 0:2a53a4c3238c 256 /* start from zero */
lorcansmith 0:2a53a4c3238c 257 *value = 0;
lorcansmith 0:2a53a4c3238c 258 if (*msg_ptr & 0x80)
lorcansmith 0:2a53a4c3238c 259 {
lorcansmith 0:2a53a4c3238c 260 /* negative, expecting zero sign bit! */
lorcansmith 0:2a53a4c3238c 261 return ERR_ARG;
lorcansmith 0:2a53a4c3238c 262 }
lorcansmith 0:2a53a4c3238c 263 else
lorcansmith 0:2a53a4c3238c 264 {
lorcansmith 0:2a53a4c3238c 265 /* positive */
lorcansmith 0:2a53a4c3238c 266 if ((len > 1) && (*msg_ptr == 0))
lorcansmith 0:2a53a4c3238c 267 {
lorcansmith 0:2a53a4c3238c 268 /* skip leading "sign byte" octet 0x00 */
lorcansmith 0:2a53a4c3238c 269 len--;
lorcansmith 0:2a53a4c3238c 270 ofs += 1;
lorcansmith 0:2a53a4c3238c 271 if (ofs >= plen)
lorcansmith 0:2a53a4c3238c 272 {
lorcansmith 0:2a53a4c3238c 273 /* next octet in next pbuf */
lorcansmith 0:2a53a4c3238c 274 p = p->next;
lorcansmith 0:2a53a4c3238c 275 if (p == NULL) { return ERR_ARG; }
lorcansmith 0:2a53a4c3238c 276 msg_ptr = (u8_t*)p->payload;
lorcansmith 0:2a53a4c3238c 277 plen += p->len;
lorcansmith 0:2a53a4c3238c 278 }
lorcansmith 0:2a53a4c3238c 279 else
lorcansmith 0:2a53a4c3238c 280 {
lorcansmith 0:2a53a4c3238c 281 /* next octet in same pbuf */
lorcansmith 0:2a53a4c3238c 282 msg_ptr++;
lorcansmith 0:2a53a4c3238c 283 }
lorcansmith 0:2a53a4c3238c 284 }
lorcansmith 0:2a53a4c3238c 285 }
lorcansmith 0:2a53a4c3238c 286 /* OR octets with value */
lorcansmith 0:2a53a4c3238c 287 while (len > 1)
lorcansmith 0:2a53a4c3238c 288 {
lorcansmith 0:2a53a4c3238c 289 len--;
lorcansmith 0:2a53a4c3238c 290 *value |= *msg_ptr;
lorcansmith 0:2a53a4c3238c 291 *value <<= 8;
lorcansmith 0:2a53a4c3238c 292 ofs += 1;
lorcansmith 0:2a53a4c3238c 293 if (ofs >= plen)
lorcansmith 0:2a53a4c3238c 294 {
lorcansmith 0:2a53a4c3238c 295 /* next octet in next pbuf */
lorcansmith 0:2a53a4c3238c 296 p = p->next;
lorcansmith 0:2a53a4c3238c 297 if (p == NULL) { return ERR_ARG; }
lorcansmith 0:2a53a4c3238c 298 msg_ptr = (u8_t*)p->payload;
lorcansmith 0:2a53a4c3238c 299 plen += p->len;
lorcansmith 0:2a53a4c3238c 300 }
lorcansmith 0:2a53a4c3238c 301 else
lorcansmith 0:2a53a4c3238c 302 {
lorcansmith 0:2a53a4c3238c 303 /* next octet in same pbuf */
lorcansmith 0:2a53a4c3238c 304 msg_ptr++;
lorcansmith 0:2a53a4c3238c 305 }
lorcansmith 0:2a53a4c3238c 306 }
lorcansmith 0:2a53a4c3238c 307 *value |= *msg_ptr;
lorcansmith 0:2a53a4c3238c 308 return ERR_OK;
lorcansmith 0:2a53a4c3238c 309 }
lorcansmith 0:2a53a4c3238c 310 else
lorcansmith 0:2a53a4c3238c 311 {
lorcansmith 0:2a53a4c3238c 312 return ERR_ARG;
lorcansmith 0:2a53a4c3238c 313 }
lorcansmith 0:2a53a4c3238c 314 }
lorcansmith 0:2a53a4c3238c 315 p = p->next;
lorcansmith 0:2a53a4c3238c 316 }
lorcansmith 0:2a53a4c3238c 317 /* p == NULL, ofs >= plen */
lorcansmith 0:2a53a4c3238c 318 return ERR_ARG;
lorcansmith 0:2a53a4c3238c 319 }
lorcansmith 0:2a53a4c3238c 320
lorcansmith 0:2a53a4c3238c 321 /**
lorcansmith 0:2a53a4c3238c 322 * Decodes integer into s32_t.
lorcansmith 0:2a53a4c3238c 323 *
lorcansmith 0:2a53a4c3238c 324 * @param p points to a pbuf holding an ASN1 coded integer
lorcansmith 0:2a53a4c3238c 325 * @param ofs points to the offset within the pbuf chain of the ASN1 coded integer
lorcansmith 0:2a53a4c3238c 326 * @param len length of the coded integer field
lorcansmith 0:2a53a4c3238c 327 * @param value return host order integer
lorcansmith 0:2a53a4c3238c 328 * @return ERR_OK if successfull, ERR_ARG if we can't (or won't) decode
lorcansmith 0:2a53a4c3238c 329 *
lorcansmith 0:2a53a4c3238c 330 * @note ASN coded integers are _always_ signed!
lorcansmith 0:2a53a4c3238c 331 */
lorcansmith 0:2a53a4c3238c 332 err_t
lorcansmith 0:2a53a4c3238c 333 snmp_asn1_dec_s32t(struct pbuf *p, u16_t ofs, u16_t len, s32_t *value)
lorcansmith 0:2a53a4c3238c 334 {
lorcansmith 0:2a53a4c3238c 335 u16_t plen, base;
lorcansmith 0:2a53a4c3238c 336 u8_t *msg_ptr;
lorcansmith 0:2a53a4c3238c 337 #if BYTE_ORDER == LITTLE_ENDIAN
lorcansmith 0:2a53a4c3238c 338 u8_t *lsb_ptr = (u8_t*)value;
lorcansmith 0:2a53a4c3238c 339 #endif
lorcansmith 0:2a53a4c3238c 340 #if BYTE_ORDER == BIG_ENDIAN
lorcansmith 0:2a53a4c3238c 341 u8_t *lsb_ptr = (u8_t*)value + sizeof(s32_t) - 1;
lorcansmith 0:2a53a4c3238c 342 #endif
lorcansmith 0:2a53a4c3238c 343 u8_t sign;
lorcansmith 0:2a53a4c3238c 344
lorcansmith 0:2a53a4c3238c 345 plen = 0;
lorcansmith 0:2a53a4c3238c 346 while (p != NULL)
lorcansmith 0:2a53a4c3238c 347 {
lorcansmith 0:2a53a4c3238c 348 base = plen;
lorcansmith 0:2a53a4c3238c 349 plen += p->len;
lorcansmith 0:2a53a4c3238c 350 if (ofs < plen)
lorcansmith 0:2a53a4c3238c 351 {
lorcansmith 0:2a53a4c3238c 352 msg_ptr = (u8_t*)p->payload;
lorcansmith 0:2a53a4c3238c 353 msg_ptr += ofs - base;
lorcansmith 0:2a53a4c3238c 354 if ((len > 0) && (len < 5))
lorcansmith 0:2a53a4c3238c 355 {
lorcansmith 0:2a53a4c3238c 356 if (*msg_ptr & 0x80)
lorcansmith 0:2a53a4c3238c 357 {
lorcansmith 0:2a53a4c3238c 358 /* negative, start from -1 */
lorcansmith 0:2a53a4c3238c 359 *value = -1;
lorcansmith 0:2a53a4c3238c 360 sign = 1;
lorcansmith 0:2a53a4c3238c 361 }
lorcansmith 0:2a53a4c3238c 362 else
lorcansmith 0:2a53a4c3238c 363 {
lorcansmith 0:2a53a4c3238c 364 /* positive, start from 0 */
lorcansmith 0:2a53a4c3238c 365 *value = 0;
lorcansmith 0:2a53a4c3238c 366 sign = 0;
lorcansmith 0:2a53a4c3238c 367 }
lorcansmith 0:2a53a4c3238c 368 /* OR/AND octets with value */
lorcansmith 0:2a53a4c3238c 369 while (len > 1)
lorcansmith 0:2a53a4c3238c 370 {
lorcansmith 0:2a53a4c3238c 371 len--;
lorcansmith 0:2a53a4c3238c 372 if (sign)
lorcansmith 0:2a53a4c3238c 373 {
lorcansmith 0:2a53a4c3238c 374 *lsb_ptr &= *msg_ptr;
lorcansmith 0:2a53a4c3238c 375 *value <<= 8;
lorcansmith 0:2a53a4c3238c 376 *lsb_ptr |= 255;
lorcansmith 0:2a53a4c3238c 377 }
lorcansmith 0:2a53a4c3238c 378 else
lorcansmith 0:2a53a4c3238c 379 {
lorcansmith 0:2a53a4c3238c 380 *lsb_ptr |= *msg_ptr;
lorcansmith 0:2a53a4c3238c 381 *value <<= 8;
lorcansmith 0:2a53a4c3238c 382 }
lorcansmith 0:2a53a4c3238c 383 ofs += 1;
lorcansmith 0:2a53a4c3238c 384 if (ofs >= plen)
lorcansmith 0:2a53a4c3238c 385 {
lorcansmith 0:2a53a4c3238c 386 /* next octet in next pbuf */
lorcansmith 0:2a53a4c3238c 387 p = p->next;
lorcansmith 0:2a53a4c3238c 388 if (p == NULL) { return ERR_ARG; }
lorcansmith 0:2a53a4c3238c 389 msg_ptr = (u8_t*)p->payload;
lorcansmith 0:2a53a4c3238c 390 plen += p->len;
lorcansmith 0:2a53a4c3238c 391 }
lorcansmith 0:2a53a4c3238c 392 else
lorcansmith 0:2a53a4c3238c 393 {
lorcansmith 0:2a53a4c3238c 394 /* next octet in same pbuf */
lorcansmith 0:2a53a4c3238c 395 msg_ptr++;
lorcansmith 0:2a53a4c3238c 396 }
lorcansmith 0:2a53a4c3238c 397 }
lorcansmith 0:2a53a4c3238c 398 if (sign)
lorcansmith 0:2a53a4c3238c 399 {
lorcansmith 0:2a53a4c3238c 400 *lsb_ptr &= *msg_ptr;
lorcansmith 0:2a53a4c3238c 401 }
lorcansmith 0:2a53a4c3238c 402 else
lorcansmith 0:2a53a4c3238c 403 {
lorcansmith 0:2a53a4c3238c 404 *lsb_ptr |= *msg_ptr;
lorcansmith 0:2a53a4c3238c 405 }
lorcansmith 0:2a53a4c3238c 406 return ERR_OK;
lorcansmith 0:2a53a4c3238c 407 }
lorcansmith 0:2a53a4c3238c 408 else
lorcansmith 0:2a53a4c3238c 409 {
lorcansmith 0:2a53a4c3238c 410 return ERR_ARG;
lorcansmith 0:2a53a4c3238c 411 }
lorcansmith 0:2a53a4c3238c 412 }
lorcansmith 0:2a53a4c3238c 413 p = p->next;
lorcansmith 0:2a53a4c3238c 414 }
lorcansmith 0:2a53a4c3238c 415 /* p == NULL, ofs >= plen */
lorcansmith 0:2a53a4c3238c 416 return ERR_ARG;
lorcansmith 0:2a53a4c3238c 417 }
lorcansmith 0:2a53a4c3238c 418
lorcansmith 0:2a53a4c3238c 419 /**
lorcansmith 0:2a53a4c3238c 420 * Decodes object identifier from incoming message into array of s32_t.
lorcansmith 0:2a53a4c3238c 421 *
lorcansmith 0:2a53a4c3238c 422 * @param p points to a pbuf holding an ASN1 coded object identifier
lorcansmith 0:2a53a4c3238c 423 * @param ofs points to the offset within the pbuf chain of the ASN1 coded object identifier
lorcansmith 0:2a53a4c3238c 424 * @param len length of the coded object identifier
lorcansmith 0:2a53a4c3238c 425 * @param oid return object identifier struct
lorcansmith 0:2a53a4c3238c 426 * @return ERR_OK if successfull, ERR_ARG if we can't (or won't) decode
lorcansmith 0:2a53a4c3238c 427 */
lorcansmith 0:2a53a4c3238c 428 err_t
lorcansmith 0:2a53a4c3238c 429 snmp_asn1_dec_oid(struct pbuf *p, u16_t ofs, u16_t len, struct snmp_obj_id *oid)
lorcansmith 0:2a53a4c3238c 430 {
lorcansmith 0:2a53a4c3238c 431 u16_t plen, base;
lorcansmith 0:2a53a4c3238c 432 u8_t *msg_ptr;
lorcansmith 0:2a53a4c3238c 433 s32_t *oid_ptr;
lorcansmith 0:2a53a4c3238c 434
lorcansmith 0:2a53a4c3238c 435 plen = 0;
lorcansmith 0:2a53a4c3238c 436 while (p != NULL)
lorcansmith 0:2a53a4c3238c 437 {
lorcansmith 0:2a53a4c3238c 438 base = plen;
lorcansmith 0:2a53a4c3238c 439 plen += p->len;
lorcansmith 0:2a53a4c3238c 440 if (ofs < plen)
lorcansmith 0:2a53a4c3238c 441 {
lorcansmith 0:2a53a4c3238c 442 msg_ptr = (u8_t*)p->payload;
lorcansmith 0:2a53a4c3238c 443 msg_ptr += ofs - base;
lorcansmith 0:2a53a4c3238c 444
lorcansmith 0:2a53a4c3238c 445 oid->len = 0;
lorcansmith 0:2a53a4c3238c 446 oid_ptr = &oid->id[0];
lorcansmith 0:2a53a4c3238c 447 if (len > 0)
lorcansmith 0:2a53a4c3238c 448 {
lorcansmith 0:2a53a4c3238c 449 /* first compressed octet */
lorcansmith 0:2a53a4c3238c 450 if (*msg_ptr == 0x2B)
lorcansmith 0:2a53a4c3238c 451 {
lorcansmith 0:2a53a4c3238c 452 /* (most) common case 1.3 (iso.org) */
lorcansmith 0:2a53a4c3238c 453 *oid_ptr = 1;
lorcansmith 0:2a53a4c3238c 454 oid_ptr++;
lorcansmith 0:2a53a4c3238c 455 *oid_ptr = 3;
lorcansmith 0:2a53a4c3238c 456 oid_ptr++;
lorcansmith 0:2a53a4c3238c 457 }
lorcansmith 0:2a53a4c3238c 458 else if (*msg_ptr < 40)
lorcansmith 0:2a53a4c3238c 459 {
lorcansmith 0:2a53a4c3238c 460 *oid_ptr = 0;
lorcansmith 0:2a53a4c3238c 461 oid_ptr++;
lorcansmith 0:2a53a4c3238c 462 *oid_ptr = *msg_ptr;
lorcansmith 0:2a53a4c3238c 463 oid_ptr++;
lorcansmith 0:2a53a4c3238c 464 }
lorcansmith 0:2a53a4c3238c 465 else if (*msg_ptr < 80)
lorcansmith 0:2a53a4c3238c 466 {
lorcansmith 0:2a53a4c3238c 467 *oid_ptr = 1;
lorcansmith 0:2a53a4c3238c 468 oid_ptr++;
lorcansmith 0:2a53a4c3238c 469 *oid_ptr = (*msg_ptr) - 40;
lorcansmith 0:2a53a4c3238c 470 oid_ptr++;
lorcansmith 0:2a53a4c3238c 471 }
lorcansmith 0:2a53a4c3238c 472 else
lorcansmith 0:2a53a4c3238c 473 {
lorcansmith 0:2a53a4c3238c 474 *oid_ptr = 2;
lorcansmith 0:2a53a4c3238c 475 oid_ptr++;
lorcansmith 0:2a53a4c3238c 476 *oid_ptr = (*msg_ptr) - 80;
lorcansmith 0:2a53a4c3238c 477 oid_ptr++;
lorcansmith 0:2a53a4c3238c 478 }
lorcansmith 0:2a53a4c3238c 479 oid->len = 2;
lorcansmith 0:2a53a4c3238c 480 }
lorcansmith 0:2a53a4c3238c 481 else
lorcansmith 0:2a53a4c3238c 482 {
lorcansmith 0:2a53a4c3238c 483 /* accepting zero length identifiers e.g. for
lorcansmith 0:2a53a4c3238c 484 getnext operation. uncommon but valid */
lorcansmith 0:2a53a4c3238c 485 return ERR_OK;
lorcansmith 0:2a53a4c3238c 486 }
lorcansmith 0:2a53a4c3238c 487 len--;
lorcansmith 0:2a53a4c3238c 488 if (len > 0)
lorcansmith 0:2a53a4c3238c 489 {
lorcansmith 0:2a53a4c3238c 490 ofs += 1;
lorcansmith 0:2a53a4c3238c 491 if (ofs >= plen)
lorcansmith 0:2a53a4c3238c 492 {
lorcansmith 0:2a53a4c3238c 493 /* next octet in next pbuf */
lorcansmith 0:2a53a4c3238c 494 p = p->next;
lorcansmith 0:2a53a4c3238c 495 if (p == NULL) { return ERR_ARG; }
lorcansmith 0:2a53a4c3238c 496 msg_ptr = (u8_t*)p->payload;
lorcansmith 0:2a53a4c3238c 497 plen += p->len;
lorcansmith 0:2a53a4c3238c 498 }
lorcansmith 0:2a53a4c3238c 499 else
lorcansmith 0:2a53a4c3238c 500 {
lorcansmith 0:2a53a4c3238c 501 /* next octet in same pbuf */
lorcansmith 0:2a53a4c3238c 502 msg_ptr++;
lorcansmith 0:2a53a4c3238c 503 }
lorcansmith 0:2a53a4c3238c 504 }
lorcansmith 0:2a53a4c3238c 505 while ((len > 0) && (oid->len < LWIP_SNMP_OBJ_ID_LEN))
lorcansmith 0:2a53a4c3238c 506 {
lorcansmith 0:2a53a4c3238c 507 /* sub-identifier uses multiple octets */
lorcansmith 0:2a53a4c3238c 508 if (*msg_ptr & 0x80)
lorcansmith 0:2a53a4c3238c 509 {
lorcansmith 0:2a53a4c3238c 510 s32_t sub_id = 0;
lorcansmith 0:2a53a4c3238c 511
lorcansmith 0:2a53a4c3238c 512 while ((*msg_ptr & 0x80) && (len > 1))
lorcansmith 0:2a53a4c3238c 513 {
lorcansmith 0:2a53a4c3238c 514 len--;
lorcansmith 0:2a53a4c3238c 515 sub_id = (sub_id << 7) + (*msg_ptr & ~0x80);
lorcansmith 0:2a53a4c3238c 516 ofs += 1;
lorcansmith 0:2a53a4c3238c 517 if (ofs >= plen)
lorcansmith 0:2a53a4c3238c 518 {
lorcansmith 0:2a53a4c3238c 519 /* next octet in next pbuf */
lorcansmith 0:2a53a4c3238c 520 p = p->next;
lorcansmith 0:2a53a4c3238c 521 if (p == NULL) { return ERR_ARG; }
lorcansmith 0:2a53a4c3238c 522 msg_ptr = (u8_t*)p->payload;
lorcansmith 0:2a53a4c3238c 523 plen += p->len;
lorcansmith 0:2a53a4c3238c 524 }
lorcansmith 0:2a53a4c3238c 525 else
lorcansmith 0:2a53a4c3238c 526 {
lorcansmith 0:2a53a4c3238c 527 /* next octet in same pbuf */
lorcansmith 0:2a53a4c3238c 528 msg_ptr++;
lorcansmith 0:2a53a4c3238c 529 }
lorcansmith 0:2a53a4c3238c 530 }
lorcansmith 0:2a53a4c3238c 531 if (!(*msg_ptr & 0x80) && (len > 0))
lorcansmith 0:2a53a4c3238c 532 {
lorcansmith 0:2a53a4c3238c 533 /* last octet sub-identifier */
lorcansmith 0:2a53a4c3238c 534 len--;
lorcansmith 0:2a53a4c3238c 535 sub_id = (sub_id << 7) + *msg_ptr;
lorcansmith 0:2a53a4c3238c 536 *oid_ptr = sub_id;
lorcansmith 0:2a53a4c3238c 537 }
lorcansmith 0:2a53a4c3238c 538 }
lorcansmith 0:2a53a4c3238c 539 else
lorcansmith 0:2a53a4c3238c 540 {
lorcansmith 0:2a53a4c3238c 541 /* !(*msg_ptr & 0x80) sub-identifier uses single octet */
lorcansmith 0:2a53a4c3238c 542 len--;
lorcansmith 0:2a53a4c3238c 543 *oid_ptr = *msg_ptr;
lorcansmith 0:2a53a4c3238c 544 // LWIP_DEBUGF(SNMP_MSG_DEBUG, ("\r\nsnmp_asn1_dec_oid . %d length left %d\r\n", *oid_ptr, len));
lorcansmith 0:2a53a4c3238c 545 }
lorcansmith 0:2a53a4c3238c 546 if (len > 0)
lorcansmith 0:2a53a4c3238c 547 {
lorcansmith 0:2a53a4c3238c 548 /* remaining oid bytes available ... */
lorcansmith 0:2a53a4c3238c 549 ofs += 1;
lorcansmith 0:2a53a4c3238c 550 if (ofs >= plen)
lorcansmith 0:2a53a4c3238c 551 {
lorcansmith 0:2a53a4c3238c 552 /* next octet in next pbuf */
lorcansmith 0:2a53a4c3238c 553 p = p->next;
lorcansmith 0:2a53a4c3238c 554 if (p == NULL) { return ERR_ARG; }
lorcansmith 0:2a53a4c3238c 555 msg_ptr = (u8_t*)p->payload;
lorcansmith 0:2a53a4c3238c 556 plen += p->len;
lorcansmith 0:2a53a4c3238c 557 }
lorcansmith 0:2a53a4c3238c 558 else
lorcansmith 0:2a53a4c3238c 559 {
lorcansmith 0:2a53a4c3238c 560 /* next octet in same pbuf */
lorcansmith 0:2a53a4c3238c 561 msg_ptr++;
lorcansmith 0:2a53a4c3238c 562 }
lorcansmith 0:2a53a4c3238c 563 }
lorcansmith 0:2a53a4c3238c 564 oid_ptr++;
lorcansmith 0:2a53a4c3238c 565 oid->len++;
lorcansmith 0:2a53a4c3238c 566 }
lorcansmith 0:2a53a4c3238c 567 if (len == 0)
lorcansmith 0:2a53a4c3238c 568 {
lorcansmith 0:2a53a4c3238c 569 /* len == 0, end of oid */
lorcansmith 0:2a53a4c3238c 570 return ERR_OK;
lorcansmith 0:2a53a4c3238c 571 }
lorcansmith 0:2a53a4c3238c 572 else
lorcansmith 0:2a53a4c3238c 573 {
lorcansmith 0:2a53a4c3238c 574 /* len > 0, oid->len == LWIP_SNMP_OBJ_ID_LEN or malformed encoding */
lorcansmith 0:2a53a4c3238c 575 LWIP_DEBUGF(SNMP_MSG_DEBUG, ("\r\nsnmp_asn1_dec_oid end ERR\r\n"));
lorcansmith 0:2a53a4c3238c 576 return ERR_ARG;
lorcansmith 0:2a53a4c3238c 577 }
lorcansmith 0:2a53a4c3238c 578
lorcansmith 0:2a53a4c3238c 579 }
lorcansmith 0:2a53a4c3238c 580 p = p->next;
lorcansmith 0:2a53a4c3238c 581 }
lorcansmith 0:2a53a4c3238c 582 /* p == NULL, ofs >= plen */
lorcansmith 0:2a53a4c3238c 583 return ERR_ARG;
lorcansmith 0:2a53a4c3238c 584 }
lorcansmith 0:2a53a4c3238c 585
lorcansmith 0:2a53a4c3238c 586 /**
lorcansmith 0:2a53a4c3238c 587 * Decodes (copies) raw data (ip-addresses, octet strings, opaque encoding)
lorcansmith 0:2a53a4c3238c 588 * from incoming message into array.
lorcansmith 0:2a53a4c3238c 589 *
lorcansmith 0:2a53a4c3238c 590 * @param p points to a pbuf holding an ASN1 coded raw data
lorcansmith 0:2a53a4c3238c 591 * @param ofs points to the offset within the pbuf chain of the ASN1 coded raw data
lorcansmith 0:2a53a4c3238c 592 * @param len length of the coded raw data (zero is valid, e.g. empty string!)
lorcansmith 0:2a53a4c3238c 593 * @param raw_len length of the raw return value
lorcansmith 0:2a53a4c3238c 594 * @param raw return raw bytes
lorcansmith 0:2a53a4c3238c 595 * @return ERR_OK if successfull, ERR_ARG if we can't (or won't) decode
lorcansmith 0:2a53a4c3238c 596 */
lorcansmith 0:2a53a4c3238c 597 err_t
lorcansmith 0:2a53a4c3238c 598 snmp_asn1_dec_raw(struct pbuf *p, u16_t ofs, u16_t len, u16_t raw_len, u8_t *raw)
lorcansmith 0:2a53a4c3238c 599 {
lorcansmith 0:2a53a4c3238c 600 u16_t plen, base;
lorcansmith 0:2a53a4c3238c 601 u8_t *msg_ptr;
lorcansmith 0:2a53a4c3238c 602
lorcansmith 0:2a53a4c3238c 603 if (len > 0)
lorcansmith 0:2a53a4c3238c 604 {
lorcansmith 0:2a53a4c3238c 605 plen = 0;
lorcansmith 0:2a53a4c3238c 606 while (p != NULL)
lorcansmith 0:2a53a4c3238c 607 {
lorcansmith 0:2a53a4c3238c 608 base = plen;
lorcansmith 0:2a53a4c3238c 609 plen += p->len;
lorcansmith 0:2a53a4c3238c 610 if (ofs < plen)
lorcansmith 0:2a53a4c3238c 611 {
lorcansmith 0:2a53a4c3238c 612 msg_ptr = (u8_t*)p->payload;
lorcansmith 0:2a53a4c3238c 613 msg_ptr += ofs - base;
lorcansmith 0:2a53a4c3238c 614 if (raw_len >= len)
lorcansmith 0:2a53a4c3238c 615 {
lorcansmith 0:2a53a4c3238c 616 while (len > 1)
lorcansmith 0:2a53a4c3238c 617 {
lorcansmith 0:2a53a4c3238c 618 /* copy len - 1 octets */
lorcansmith 0:2a53a4c3238c 619 len--;
lorcansmith 0:2a53a4c3238c 620 *raw = *msg_ptr;
lorcansmith 0:2a53a4c3238c 621 raw++;
lorcansmith 0:2a53a4c3238c 622 ofs += 1;
lorcansmith 0:2a53a4c3238c 623 if (ofs >= plen)
lorcansmith 0:2a53a4c3238c 624 {
lorcansmith 0:2a53a4c3238c 625 /* next octet in next pbuf */
lorcansmith 0:2a53a4c3238c 626 p = p->next;
lorcansmith 0:2a53a4c3238c 627 if (p == NULL) { return ERR_ARG; }
lorcansmith 0:2a53a4c3238c 628 msg_ptr = (u8_t*)p->payload;
lorcansmith 0:2a53a4c3238c 629 plen += p->len;
lorcansmith 0:2a53a4c3238c 630 }
lorcansmith 0:2a53a4c3238c 631 else
lorcansmith 0:2a53a4c3238c 632 {
lorcansmith 0:2a53a4c3238c 633 /* next octet in same pbuf */
lorcansmith 0:2a53a4c3238c 634 msg_ptr++;
lorcansmith 0:2a53a4c3238c 635 }
lorcansmith 0:2a53a4c3238c 636 }
lorcansmith 0:2a53a4c3238c 637 /* copy last octet */
lorcansmith 0:2a53a4c3238c 638 *raw = *msg_ptr;
lorcansmith 0:2a53a4c3238c 639 return ERR_OK;
lorcansmith 0:2a53a4c3238c 640 }
lorcansmith 0:2a53a4c3238c 641 else
lorcansmith 0:2a53a4c3238c 642 {
lorcansmith 0:2a53a4c3238c 643 /* raw_len < len, not enough dst space */
lorcansmith 0:2a53a4c3238c 644 return ERR_ARG;
lorcansmith 0:2a53a4c3238c 645 }
lorcansmith 0:2a53a4c3238c 646 }
lorcansmith 0:2a53a4c3238c 647 p = p->next;
lorcansmith 0:2a53a4c3238c 648 }
lorcansmith 0:2a53a4c3238c 649 /* p == NULL, ofs >= plen */
lorcansmith 0:2a53a4c3238c 650 return ERR_ARG;
lorcansmith 0:2a53a4c3238c 651 }
lorcansmith 0:2a53a4c3238c 652 else
lorcansmith 0:2a53a4c3238c 653 {
lorcansmith 0:2a53a4c3238c 654 /* len == 0, empty string */
lorcansmith 0:2a53a4c3238c 655 return ERR_OK;
lorcansmith 0:2a53a4c3238c 656 }
lorcansmith 0:2a53a4c3238c 657 }
lorcansmith 0:2a53a4c3238c 658
lorcansmith 0:2a53a4c3238c 659 #endif /* LWIP_SNMP */