delta param

Dependents:   EthernetInterface

Fork of lwip by mbed official

Committer:
mbed_official
Date:
Fri Jun 22 09:25:39 2012 +0000
Revision:
0:51ac1d130fd4
Initial import from lwip-1.4.0: http://download.savannah.gnu.org/releases/lwip/lwip-1.4.0.zip

Who changed what in which revision?

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