NetTribute library with debug turned on in FShandler Donatien Garner -> Segundo Equipo -> this version

Committer:
hexley
Date:
Fri Nov 19 01:54:45 2010 +0000
Revision:
0:281d6ff68967

        

Who changed what in which revision?

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