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

Subversion Repositories openrisc

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

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

powered by: WebSVN 2.1.0

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