blob: fe6d289265dc6245decf8e608779ecadbc11a3f3 [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
Harald Welte7bc4cbc2009-02-21 12:59:22 +000016int tlv_parse(struct tlv_parsed *dec, const struct tlv_definition *def,
17 const u_int8_t *buf, int buf_len)
Harald Welte91b5b0d2009-02-06 12:51:39 +000018{
Harald Welte2fa79342009-02-14 19:07:10 +000019 u_int8_t tag, len = 1;
Harald Welte7bc4cbc2009-02-21 12:59:22 +000020 const u_int8_t *pos;
Harald Welte2fa79342009-02-14 19:07:10 +000021 int num_parsed = 0;
Harald Welte91b5b0d2009-02-06 12:51:39 +000022
Harald Welte2fa79342009-02-14 19:07:10 +000023 memset(dec, 0, sizeof(*dec));
Harald Welte91b5b0d2009-02-06 12:51:39 +000024
Harald Welte2fa79342009-02-14 19:07:10 +000025 for (pos = buf; pos < buf+buf_len; pos += len) {
26 tag = *pos;
27 /* FIXME: use tables for knwon IEI */
Harald Weltee0590df2009-02-15 03:34:15 +000028 switch (def->def[tag].type) {
29 case TLV_TYPE_T:
Harald Welte2fa79342009-02-14 19:07:10 +000030 /* GSM TS 04.07 11.2.4: Type 1 TV or Type 2 T */
31 dec->lv[tag].val = pos;
32 dec->lv[tag].len = 0;
33 len = 1;
34 num_parsed++;
Harald Weltee0590df2009-02-15 03:34:15 +000035 break;
36 case TLV_TYPE_TV:
37 dec->lv[tag].val = pos+1;
38 dec->lv[tag].len = 1;
39 len = 2;
40 num_parsed++;
41 break;
42 case TLV_TYPE_FIXED:
43 dec->lv[tag].val = pos+1;
44 dec->lv[tag].len = def->def[tag].fixed_len;
45 len = def->def[tag].fixed_len + 1;
46 num_parsed++;
47 break;
48 case TLV_TYPE_TLV:
Harald Welte2fa79342009-02-14 19:07:10 +000049 /* GSM TS 04.07 11.2.4: Type 4 TLV */
50 if (pos + 1 > buf + buf_len)
51 return -1;
52 dec->lv[tag].val = pos+2;
53 dec->lv[tag].len = *(pos+1);
54 len = dec->lv[tag].len + 2;
55 if (pos + len > buf + buf_len)
56 return -2;
57 num_parsed++;
Harald Weltee0590df2009-02-15 03:34:15 +000058 break;
59 case TLV_TYPE_TL16V:
60 if (pos + 2 > buf + buf_len)
61 return -1;
62 dec->lv[tag].val = pos+3;
63 dec->lv[tag].len = *(pos+1) << 8 | *(pos+2);
64 len = dec->lv[tag].len + 3;
65 if (pos + len > buf + buf_len)
66 return -2;
67 num_parsed++;
68 break;
Harald Welte2fa79342009-02-14 19:07:10 +000069 }
Harald Welte91b5b0d2009-02-06 12:51:39 +000070 }
Harald Weltee0590df2009-02-15 03:34:15 +000071 //tlv_dump(dec);
Harald Welte2fa79342009-02-14 19:07:10 +000072 return num_parsed;
Harald Welte91b5b0d2009-02-06 12:51:39 +000073}
Harald Weltee0590df2009-02-15 03:34:15 +000074