OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [freertos-6.1.1/] [Demo/] [Common/] [ethernet/] [lwIP_130/] [src/] [core/] [snmp/] [asn1_dec.c] - Blame information for rev 609

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.