I have a problem getting this to work. Server only recieves half of the data being sent. Whats wrong

Dependencies:   mbed

Committer:
tax
Date:
Tue Mar 29 13:20:15 2011 +0000
Revision:
0:66300c77c6e9

        

Who changed what in which revision?

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