3 #include <osmocore/utils.h>
4 #include <osmocore/tlv.h>
6 struct tlv_definition tvlv_att_def;
8 int tlv_dump(struct tlv_parsed *dec)
12 for (i = 0; i <= 0xff; i++) {
15 printf("T=%02x L=%d\n", i, dec->lv[i].len);
20 /* o_tag: output: tag found
21 * o_len: output: length of the data
22 * o_val: output: pointer to the data
23 * def: input: a structure defining the valid TLV tags / configurations
24 * buf: input: the input data buffer to be parsed
25 * buf_len: input: the length of the input data buffer
27 * Also, returns the number of bytes consumed by the TLV entry
29 int tlv_parse_one(uint8_t *o_tag, uint16_t *o_len, const uint8_t **o_val,
30 const struct tlv_definition *def,
31 const uint8_t *buf, int buf_len)
39 /* single octet TV IE */
40 if (def->def[tag & 0xf0].type == TLV_TYPE_SINGLE_TV) {
47 /* FIXME: use tables for knwon IEI */
48 switch (def->def[tag].type) {
50 /* GSM TS 04.07 11.2.4: Type 1 TV or Type 2 T */
62 *o_len = def->def[tag].fixed_len;
63 len = def->def[tag].fixed_len + 1;
66 /* GSM TS 04.07 11.2.4: Type 4 TLV */
67 if (buf + 1 > buf + buf_len)
76 if (*(buf+1) & 0x80) {
77 /* like TLV, but without highest bit of len */
78 if (buf + 1 > buf + buf_len)
81 *o_len = *(buf+1) & 0x7f;
87 /* like TL16V, fallthrough */
92 *o_len = *(buf+1) << 8 | *(buf+2);
104 /* dec: output: a caller-allocated pointer to a struct tlv_parsed,
105 * def: input: a structure defining the valid TLV tags / configurations
106 * buf: input: the input data buffer to be parsed
107 * buf_len: input: the length of the input data buffer
108 * lv_tag: input: an initial LV tag at the start of the buffer
109 * lv_tag2: input: a second initial LV tag following lv_tag
111 int tlv_parse(struct tlv_parsed *dec, const struct tlv_definition *def,
112 const uint8_t *buf, int buf_len, uint8_t lv_tag,
115 int ofs = 0, num_parsed = 0;
118 memset(dec, 0, sizeof(*dec));
123 dec->lv[lv_tag].val = &buf[ofs+1];
124 dec->lv[lv_tag].len = buf[ofs];
125 len = dec->lv[lv_tag].len + 1;
126 if (ofs + len > buf_len)
134 dec->lv[lv_tag2].val = &buf[ofs+1];
135 dec->lv[lv_tag2].len = buf[ofs];
136 len = dec->lv[lv_tag2].len + 1;
137 if (ofs + len > buf_len)
143 while (ofs < buf_len) {
148 rv = tlv_parse_one(&tag, &len, &val, def,
149 &buf[ofs], buf_len-ofs);
152 dec->lv[tag].val = val;
153 dec->lv[tag].len = len;
161 /* take a master (src) tlvdev and fill up all empty slots in 'dst' */
162 void tlv_def_patch(struct tlv_definition *dst, const struct tlv_definition *src)
166 for (i = 0; i < ARRAY_SIZE(dst->def); i++) {
167 if (src->def[i].type == TLV_TYPE_NONE)
169 if (dst->def[i].type == TLV_TYPE_NONE)
170 dst->def[i] = src->def[i];
174 static __attribute__((constructor)) void on_dso_load_tlv(void)
177 for (i = 0; i < ARRAY_SIZE(tvlv_att_def.def); i++)
178 tvlv_att_def.def[i].type = TLV_TYPE_TvLV;