Ethernet test for ECE 4180 and others to find your IP address and do a simple HTTP GET request over port 80.

Dependencies:   mbed Socket lwip-eth lwip-sys lwip

Committer:
mkersh3
Date:
Thu Apr 04 05:26:09 2013 +0000
Revision:
0:e7ca326e76ee
Ethernet Test for ECE4180 and others to find their IP Address and do a simple HTTP GET request over port 80.

Who changed what in which revision?

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