summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorHarald Welte <laforge@gnumonks.org>2012-07-14 01:50:33 +0200
committerHarald Welte <laforge@gnumonks.org>2012-07-14 01:50:33 +0200
commit2fe684755a3c8181a4dde0f5dcabac9c0c5a809c (patch)
tree2de721815a22e8c16eae2c9e7a1b2b695e8c44bd /src
parenta9250b9ebcdab7134e5d062e8ca37f9532eca5e8 (diff)
TLV: add new "vTvLV" type for GAN
This new TLV type is specific to TS 44.318. Contrary to the TvLV type of TS 08.16/08.18, it has an inverted meaning of the extension (0x80) bit: * if the extension bit is not set, 1-byte length * if the extension bit is set, 2-byte length Futhermore, it has support for variable-length tags, where the tag part can be optionally two bytes in length. As this esoteric option hasn't been seen in the wild yet, we only add encoding support but skip decoding for now.
Diffstat (limited to 'src')
-rw-r--r--src/gsm/libosmogsm.map1
-rw-r--r--src/gsm/tlv_parser.c22
2 files changed, 22 insertions, 1 deletions
diff --git a/src/gsm/libosmogsm.map b/src/gsm/libosmogsm.map
index 9ef5ccd4..33738881 100644
--- a/src/gsm/libosmogsm.map
+++ b/src/gsm/libosmogsm.map
@@ -227,6 +227,7 @@ tlv_dump;
tlv_parse;
tlv_parse_one;
tvlv_att_def;
+vtvlv_gan_att_def;
gan_msgt_vals;
gan_pdisc_vals;
diff --git a/src/gsm/tlv_parser.c b/src/gsm/tlv_parser.c
index 0ac90929..d18a6bfd 100644
--- a/src/gsm/tlv_parser.c
+++ b/src/gsm/tlv_parser.c
@@ -9,6 +9,7 @@
/*! \file tlv.c */
struct tlv_definition tvlv_att_def;
+struct tlv_definition vtvlv_gan_att_def;
/*! \brief Dump pasred TLV structure to stdout */
int tlv_dump(struct tlv_parsed *dec)
@@ -69,7 +70,7 @@ int tlv_parse_one(uint8_t *o_tag, uint16_t *o_len, const uint8_t **o_val,
len = def->def[tag].fixed_len + 1;
break;
case TLV_TYPE_TLV:
- /* GSM TS 04.07 11.2.4: Type 4 TLV */
+tlv: /* GSM TS 04.07 11.2.4: Type 4 TLV */
if (buf + 1 > buf + buf_len)
return -1;
*o_val = buf+2;
@@ -78,6 +79,22 @@ int tlv_parse_one(uint8_t *o_tag, uint16_t *o_len, const uint8_t **o_val,
if (len > buf_len)
return -2;
break;
+ case TLV_TYPE_vTvLV_GAN: /* 44.318 / 11.1.4 */
+ /* FIXME: variable-length TAG! */
+ if (*(buf+1) & 0x80) {
+ /* like TL16Vbut without highest bit of len */
+ if (2 > buf_len)
+ return -1;
+ *o_val = buf+3;
+ *o_len = (*(buf+1) & 0x7F) << 8 | *(buf+2);
+ len = *o_len + 3;
+ if (len > buf_len)
+ return -2;
+ } else {
+ /* like TLV */
+ goto tlv;
+ }
+ break;
case TLV_TYPE_TvLV:
if (*(buf+1) & 0x80) {
/* like TLV, but without highest bit of len */
@@ -184,6 +201,9 @@ static __attribute__((constructor)) void on_dso_load_tlv(void)
int i;
for (i = 0; i < ARRAY_SIZE(tvlv_att_def.def); i++)
tvlv_att_def.def[i].type = TLV_TYPE_TvLV;
+
+ for (i = 0; i < ARRAY_SIZE(vtvlv_gan_att_def.def); i++)
+ vtvlv_gan_att_def.def[i].type = TLV_TYPE_vTvLV_GAN;
}
/*! @} */