diff options
author | Harald Welte <laforge@gnumonks.org> | 2012-07-14 01:50:33 +0200 |
---|---|---|
committer | Harald Welte <laforge@gnumonks.org> | 2012-07-14 01:50:33 +0200 |
commit | 2fe684755a3c8181a4dde0f5dcabac9c0c5a809c (patch) | |
tree | 2de721815a22e8c16eae2c9e7a1b2b695e8c44bd /src/gsm | |
parent | a9250b9ebcdab7134e5d062e8ca37f9532eca5e8 (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/gsm')
-rw-r--r-- | src/gsm/libosmogsm.map | 1 | ||||
-rw-r--r-- | src/gsm/tlv_parser.c | 22 |
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; } /*! @} */ |