Dependents:   TimeZoneDemo EthernetJackTestCode MMEx_Challenge ntp_mem ... more

Committer:
segundo
Date:
Tue Nov 09 20:54:15 2010 +0000
Revision:
0:ac1725ba162c

        

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 */