Modified version of NetServices. Fixes an issue where connections failed should the HTTP response status line be received in a packet on its own prior to any further headers. Changes are made to the HTTPClient.cpp file's readHeaders method.

Committer:
andrewbonney
Date:
Fri Apr 08 14:39:41 2011 +0000
Revision:
0:ec559500a63f

        

Who changed what in which revision?

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