Ethernet for Nucleo and Disco board STM32F746 works with gcc and arm. IAC is untested

Dependencies:   mbed-rtos

Dependents:   IMU_ethernet

Fork of F7_Ethernet by Dieter Graef

Committer:
rctaduio
Date:
Thu Oct 06 16:55:16 2016 +0000
Revision:
2:e0a4035b5cd1
Parent:
0:d26c1b55cfca
Ethernet library for F7

Who changed what in which revision?

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