Used in Live Traffic Update Nokia LCD Display Project

Fork of NetServices by Segundo Equipo

Committer:
rrajan8
Date:
Wed Mar 06 19:07:23 2013 +0000
Revision:
8:92b57208ab99
Parent:
0:ac1725ba162c
This project utilizes mbed's networking features to display live traffic updates on the Nokia LCD using the MapQuest API's Traffic Web Service.

Who changed what in which revision?

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