Committer:
mbed714
Date:
Sat Sep 18 23:05:49 2010 +0000
Revision:
0:d616ece2d859

        

Who changed what in which revision?

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