SNMP agent attached to SPI slave

Dependencies:   mbed

Committer:
lorcansmith
Date:
Mon Aug 13 15:07:40 2012 +0000
Revision:
0:2a53a4c3238c
v1.1 release includes ioAlarm traps

Who changed what in which revision?

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