Used in Live Traffic Update Nokia LCD Display Project

Fork of NetServices by Segundo Equipo

Committer:
rrajan8
Date:
Wed Mar 06 19:07:23 2013 +0000
Revision:
8:92b57208ab99
Parent:
0:ac1725ba162c
This project utilizes mbed's networking features to display live traffic updates on the Nokia LCD using the MapQuest API's Traffic Web Service.

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 */