aboutsummaryrefslogtreecommitdiffstats
path: root/src/tlv_parser.c
diff options
context:
space:
mode:
authorHarald Welte <laforge@gnumonks.org>2009-02-15 03:34:15 +0000
committerHarald Welte <laforge@gnumonks.org>2009-02-15 03:34:15 +0000
commite0590df5242af3178dbf75d527536634be0b890b (patch)
treedbd35075876c1976b944f4a273a9b4148b7483fe /src/tlv_parser.c
parent49314f60802dac6950479fc5ee6cdb190a943d41 (diff)
* extend TLV parser to use a list of TLV type descriptions
* implement TLV type descriptions for NM * add operational/administrative/availability state keeping logic to abis_nm * explicitly print all NACK's in abis_nm * make sure we produce [not just for BS-11] valid channel attributes
Diffstat (limited to 'src/tlv_parser.c')
-rw-r--r--src/tlv_parser.c46
1 files changed, 43 insertions, 3 deletions
diff --git a/src/tlv_parser.c b/src/tlv_parser.c
index b790d3cd8..f047d0bbc 100644
--- a/src/tlv_parser.c
+++ b/src/tlv_parser.c
@@ -1,6 +1,19 @@
+#include <stdio.h>
#include <openbsc/tlv.h>
-int tlv_parse(struct tlv_parsed *dec, u_int8_t *buf, int buf_len)
+int tlv_dump(struct tlv_parsed *dec)
+{
+ int i;
+
+ for (i = 0; i <= 0xff; i++) {
+ if (!dec->lv[i].val)
+ continue;
+ printf("T=%02x L=%d\n", i, dec->lv[i].len);
+ }
+ return 0;
+}
+
+int tlv_parse(struct tlv_parsed *dec, const struct tlv_definition *def, u_int8_t *buf, int buf_len)
{
u_int8_t tag, len = 1;
u_int8_t *pos;
@@ -11,13 +24,27 @@ int tlv_parse(struct tlv_parsed *dec, u_int8_t *buf, int buf_len)
for (pos = buf; pos < buf+buf_len; pos += len) {
tag = *pos;
/* FIXME: use tables for knwon IEI */
- if (tag & 0x80) {
+ switch (def->def[tag].type) {
+ case TLV_TYPE_T:
/* GSM TS 04.07 11.2.4: Type 1 TV or Type 2 T */
dec->lv[tag].val = pos;
dec->lv[tag].len = 0;
len = 1;
num_parsed++;
- } else {
+ break;
+ case TLV_TYPE_TV:
+ dec->lv[tag].val = pos+1;
+ dec->lv[tag].len = 1;
+ len = 2;
+ num_parsed++;
+ break;
+ case TLV_TYPE_FIXED:
+ dec->lv[tag].val = pos+1;
+ dec->lv[tag].len = def->def[tag].fixed_len;
+ len = def->def[tag].fixed_len + 1;
+ num_parsed++;
+ break;
+ case TLV_TYPE_TLV:
/* GSM TS 04.07 11.2.4: Type 4 TLV */
if (pos + 1 > buf + buf_len)
return -1;
@@ -27,7 +54,20 @@ int tlv_parse(struct tlv_parsed *dec, u_int8_t *buf, int buf_len)
if (pos + len > buf + buf_len)
return -2;
num_parsed++;
+ break;
+ case TLV_TYPE_TL16V:
+ if (pos + 2 > buf + buf_len)
+ return -1;
+ dec->lv[tag].val = pos+3;
+ dec->lv[tag].len = *(pos+1) << 8 | *(pos+2);
+ len = dec->lv[tag].len + 3;
+ if (pos + len > buf + buf_len)
+ return -2;
+ num_parsed++;
+ break;
}
}
+ //tlv_dump(dec);
return num_parsed;
}
+