Embedded WebSockets Experiment

Dependencies:   mbed MD5

Committer:
nandgate
Date:
Tue Jul 26 05:30:53 2011 +0000
Revision:
0:6dee052a3fa4

        

Who changed what in which revision?

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