ZG2100 Network interface source

Committer:
donatien
Date:
Fri Jul 09 15:37:23 2010 +0000
Revision:
0:b802fc31f1db

        

Who changed what in which revision?

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