blob: f047d0bbc732060de258460d1ef43d6bb2943990 [file] [log] [blame]
Harald Weltee0590df2009-02-15 03:34:15 +00001#include <stdio.h>
Harald Welte91b5b0d2009-02-06 12:51:39 +00002#include <openbsc/tlv.h>
3
Harald Weltee0590df2009-02-15 03:34:15 +00004int tlv_dump(struct tlv_parsed *dec)
5{
6 int i;
7
8 for (i = 0; i <= 0xff; i++) {
9 if (!dec->lv[i].val)
10 continue;
11 printf("T=%02x L=%d\n", i, dec->lv[i].len);
12 }
13 return 0;
14}
15
16int tlv_parse(struct tlv_parsed *dec, const struct tlv_definition *def, u_int8_t *buf, int buf_len)
Harald Welte91b5b0d2009-02-06 12:51:39 +000017{
Harald Welte2fa79342009-02-14 19:07:10 +000018 u_int8_t tag, len = 1;
19 u_int8_t *pos;
20 int num_parsed = 0;
Harald Welte91b5b0d2009-02-06 12:51:39 +000021
Harald Welte2fa79342009-02-14 19:07:10 +000022 memset(dec, 0, sizeof(*dec));
Harald Welte91b5b0d2009-02-06 12:51:39 +000023
Harald Welte2fa79342009-02-14 19:07:10 +000024 for (pos = buf; pos < buf+buf_len; pos += len) {
25 tag = *pos;
26 /* FIXME: use tables for knwon IEI */
Harald Weltee0590df2009-02-15 03:34:15 +000027 switch (def->def[tag].type) {
28 case TLV_TYPE_T:
Harald Welte2fa79342009-02-14 19:07:10 +000029 /* GSM TS 04.07 11.2.4: Type 1 TV or Type 2 T */
30 dec->lv[tag].val = pos;
31 dec->lv[tag].len = 0;
32 len = 1;
33 num_parsed++;
Harald Weltee0590df2009-02-15 03:34:15 +000034 break;
35 case TLV_TYPE_TV:
36 dec->lv[tag].val = pos+1;
37 dec->lv[tag].len = 1;
38 len = 2;
39 num_parsed++;
40 break;
41 case TLV_TYPE_FIXED:
42 dec->lv[tag].val = pos+1;
43 dec->lv[tag].len = def->def[tag].fixed_len;
44 len = def->def[tag].fixed_len + 1;
45 num_parsed++;
46 break;
47 case TLV_TYPE_TLV:
Harald Welte2fa79342009-02-14 19:07:10 +000048 /* GSM TS 04.07 11.2.4: Type 4 TLV */
49 if (pos + 1 > buf + buf_len)
50 return -1;
51 dec->lv[tag].val = pos+2;
52 dec->lv[tag].len = *(pos+1);
53 len = dec->lv[tag].len + 2;
54 if (pos + len > buf + buf_len)
55 return -2;
56 num_parsed++;
Harald Weltee0590df2009-02-15 03:34:15 +000057 break;
58 case TLV_TYPE_TL16V:
59 if (pos + 2 > buf + buf_len)
60 return -1;
61 dec->lv[tag].val = pos+3;
62 dec->lv[tag].len = *(pos+1) << 8 | *(pos+2);
63 len = dec->lv[tag].len + 3;
64 if (pos + len > buf + buf_len)
65 return -2;
66 num_parsed++;
67 break;
Harald Welte2fa79342009-02-14 19:07:10 +000068 }
Harald Welte91b5b0d2009-02-06 12:51:39 +000069 }
Harald Weltee0590df2009-02-15 03:34:15 +000070 //tlv_dump(dec);
Harald Welte2fa79342009-02-14 19:07:10 +000071 return num_parsed;
Harald Welte91b5b0d2009-02-06 12:51:39 +000072}
Harald Weltee0590df2009-02-15 03:34:15 +000073