HTTPClient using static IP

Dependencies:   mbed

Committer:
mr_q
Date:
Mon May 30 11:53:37 2011 +0000
Revision:
0:d8f2f7d5f31b
v0.01 Draft

Who changed what in which revision?

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