A version of LWIP, provided for backwards compatibility.

Dependents:   AA_DemoBoard DemoBoard HelloServerDemo DemoBoard_RangeIndicator ... more

Committer:
root@mbed.org
Date:
Tue May 08 15:32:10 2012 +0100
Revision:
0:5e1631496985
initial commit

Who changed what in which revision?

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