Netservices modded to read fragmented HTTP respsonse/payload from special purpose server - 180 bytes only

Committer:
RodColeman
Date:
Thu Sep 08 10:41:36 2011 +0000
Revision:
0:8f5825f330b0
setDataLen hacked to 180bytes

Who changed what in which revision?

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