My fork of the HTTPServer (working)

Dependents:   DGWWebServer LAN2

Committer:
screamer
Date:
Mon Aug 06 09:23:14 2012 +0000
Revision:
0:7a64fbb4069d
[mbed] converted /DGWWebServer/HTTPServer

Who changed what in which revision?

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