Dependents:   TimeZoneDemo EthernetJackTestCode MMEx_Challenge ntp_mem ... more

Committer:
segundo
Date:
Tue Nov 09 20:54:15 2010 +0000
Revision:
0:ac1725ba162c

        

Who changed what in which revision?

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