ソースの整理中ですが、利用はできます。

Dependencies:   EthernetInterface HttpServer TextLCD mbed-rpc mbed-rtos mbed Socket lwip-eth lwip-sys lwip

Committer:
yueee_yt
Date:
Wed Mar 12 04:39:15 2014 +0000
Revision:
2:14b689a85306
Parent:
0:7766f6712673
bug fix

Who changed what in which revision?

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