libosmogsm  0.9.6-12.20170220git32ee5af8.fc32
Osmocom GSM library
tlv.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include <stdint.h>
4 #include <string.h>
5 
6 #include <osmocom/core/msgb.h>
7 
13 /* Terminology / wording
14  tag length value (in bits)
15 
16  V - - 8
17  LV - 8 N * 8
18  TLV 8 8 N * 8
19  TL16V 8 16 N * 8
20  TLV16 8 8 N * 16
21  TvLV 8 8/16 N * 8
22  vTvLV 8/16 8/16 N * 8
23 
24 */
25 
27 #define LV_GROSS_LEN(x) (x+1)
28 
29 #define TLV_GROSS_LEN(x) (x+2)
30 
31 #define TLV16_GROSS_LEN(x) ((2*x)+2)
32 
33 #define TL16V_GROSS_LEN(x) (x+3)
34 
35 #define L16TV_GROSS_LEN(x) (x+3)
36 
38 #define TVLV_MAX_ONEBYTE 0x7f
39 
41 static inline uint16_t TVLV_GROSS_LEN(uint16_t len)
42 {
43  if (len <= TVLV_MAX_ONEBYTE)
44  return TLV_GROSS_LEN(len);
45  else
46  return TL16V_GROSS_LEN(len);
47 }
48 
50 static inline uint16_t VTVL_GAN_GROSS_LEN(uint16_t tag, uint16_t len)
51 {
52  uint16_t ret = 2;
53 
54  if (tag > TVLV_MAX_ONEBYTE)
55  ret++;
56 
57  if (len > TVLV_MAX_ONEBYTE)
58  ret++;
59 
60  return ret;
61 }
62 
64 static inline uint16_t VTVLV_GAN_GROSS_LEN(uint16_t tag, uint16_t len)
65 {
66  uint16_t ret;
67 
68  if (len <= TVLV_MAX_ONEBYTE)
69  return TLV_GROSS_LEN(len);
70  else
71  return TL16V_GROSS_LEN(len);
72 
73  if (tag > TVLV_MAX_ONEBYTE)
74  ret += 1;
75 
76  return ret;
77 }
78 
79 /* TLV generation */
80 
82 static inline uint8_t *lv_put(uint8_t *buf, uint8_t len,
83  const uint8_t *val)
84 {
85  *buf++ = len;
86  memcpy(buf, val, len);
87  return buf + len;
88 }
89 
91 static inline uint8_t *tlv_put(uint8_t *buf, uint8_t tag, uint8_t len,
92  const uint8_t *val)
93 {
94  *buf++ = tag;
95  *buf++ = len;
96  memcpy(buf, val, len);
97  return buf + len;
98 }
99 
101 static inline uint8_t *tlv16_put(uint8_t *buf, uint8_t tag, uint8_t len,
102  const uint16_t *val)
103 {
104  *buf++ = tag;
105  *buf++ = len;
106  memcpy(buf, val, len*2);
107  return buf + len*2;
108 }
109 
111 static inline uint8_t *tl16v_put(uint8_t *buf, uint8_t tag, uint16_t len,
112  const uint8_t *val)
113 {
114  *buf++ = tag;
115  *buf++ = len >> 8;
116  *buf++ = len & 0xff;
117  memcpy(buf, val, len);
118  return buf + len*2;
119 }
120 
122 static inline uint8_t *tvlv_put(uint8_t *buf, uint8_t tag, uint16_t len,
123  const uint8_t *val)
124 {
125  uint8_t *ret;
126 
127  if (len <= TVLV_MAX_ONEBYTE) {
128  ret = tlv_put(buf, tag, len, val);
129  buf[1] |= 0x80;
130  } else
131  ret = tl16v_put(buf, tag, len, val);
132 
133  return ret;
134 }
135 
137 static inline uint8_t *vt_gan_put(uint8_t *buf, uint16_t tag)
138 {
139  if (tag > TVLV_MAX_ONEBYTE) {
140  /* two-byte TAG */
141  *buf++ = 0x80 | (tag >> 8);
142  *buf++ = (tag & 0xff);
143  } else
144  *buf++ = tag;
145 
146  return buf;
147 }
148 
149 /* \brief put (append) vTvL (GAN) field (tag + length)*/
150 static inline uint8_t *vtvl_gan_put(uint8_t *buf, uint16_t tag, uint16_t len)
151 {
152  uint8_t *ret;
153 
154  ret = vt_gan_put(buf, tag);
155  return vt_gan_put(ret, len);
156 }
157 
158 /* \brief put (append) vTvLV (GAN) field (tag + length + val) */
159 static inline uint8_t *vtvlv_gan_put(uint8_t *buf, uint16_t tag, uint16_t len,
160  const uint8_t *val)
161 {
162  uint8_t *ret;
163 
164  ret = vtvl_gan_put(buf, tag, len );
165 
166  memcpy(ret, val, len);
167  ret = buf + len;
168 
169  return ret;
170 }
171 
173 static inline uint8_t *msgb_tlv16_put(struct msgb *msg, uint8_t tag, uint8_t len, const uint16_t *val)
174 {
175  uint8_t *buf = msgb_put(msg, TLV16_GROSS_LEN(len));
176  return tlv16_put(buf, tag, len, val);
177 }
178 
180 static inline uint8_t *msgb_tl16v_put(struct msgb *msg, uint8_t tag, uint16_t len,
181  const uint8_t *val)
182 {
183  uint8_t *buf = msgb_put(msg, TL16V_GROSS_LEN(len));
184  return tl16v_put(buf, tag, len, val);
185 }
186 
188 static inline uint8_t *msgb_tvlv_put(struct msgb *msg, uint8_t tag, uint16_t len,
189  const uint8_t *val)
190 {
191  uint8_t *buf = msgb_put(msg, TVLV_GROSS_LEN(len));
192  return tvlv_put(buf, tag, len, val);
193 }
194 
196 static inline uint8_t *msgb_vtvlv_gan_put(struct msgb *msg, uint16_t tag,
197  uint16_t len, const uint8_t *val)
198 {
199  uint8_t *buf = msgb_put(msg, VTVLV_GAN_GROSS_LEN(tag, len));
200  return vtvlv_gan_put(buf, tag, len, val);
201 }
202 
204 static inline uint8_t *msgb_l16tv_put(struct msgb *msg, uint16_t len, uint8_t tag,
205  const uint8_t *val)
206 {
207  uint8_t *buf = msgb_put(msg, L16TV_GROSS_LEN(len));
208 
209  *buf++ = len >> 8;
210  *buf++ = len & 0xff;
211  *buf++ = tag;
212  memcpy(buf, val, len);
213  return buf + len;
214 }
215 
217 static inline uint8_t *v_put(uint8_t *buf, uint8_t val)
218 {
219  *buf++ = val;
220  return buf;
221 }
222 
224 static inline uint8_t *tv_put(uint8_t *buf, uint8_t tag,
225  uint8_t val)
226 {
227  *buf++ = tag;
228  *buf++ = val;
229  return buf;
230 }
231 
233 static inline uint8_t *tv_fixed_put(uint8_t *buf, uint8_t tag,
234  unsigned int len, const uint8_t *val)
235 {
236  *buf++ = tag;
237  memcpy(buf, val, len);
238  return buf + len;
239 }
240 
246 static inline uint8_t *tv16_put(uint8_t *buf, uint8_t tag,
247  uint16_t val)
248 {
249  *buf++ = tag;
250  *buf++ = val >> 8;
251  *buf++ = val & 0xff;
252  return buf;
253 }
254 
257 static inline uint8_t *msgb_lv_put(struct msgb *msg, uint8_t len, const uint8_t *val)
258 {
259  uint8_t *buf = msgb_put(msg, LV_GROSS_LEN(len));
260  return lv_put(buf, len, val);
261 }
262 
265 static inline uint8_t *msgb_tlv_put(struct msgb *msg, uint8_t tag, uint8_t len, const uint8_t *val)
266 {
267  uint8_t *buf = msgb_put(msg, TLV_GROSS_LEN(len));
268  return tlv_put(buf, tag, len, val);
269 }
270 
273 static inline uint8_t *msgb_tv_put(struct msgb *msg, uint8_t tag, uint8_t val)
274 {
275  uint8_t *buf = msgb_put(msg, 2);
276  return tv_put(buf, tag, val);
277 }
278 
281 static inline uint8_t *msgb_tv_fixed_put(struct msgb *msg, uint8_t tag,
282  unsigned int len, const uint8_t *val)
283 {
284  uint8_t *buf = msgb_put(msg, 1+len);
285  return tv_fixed_put(buf, tag, len, val);
286 }
287 
290 static inline uint8_t *msgb_v_put(struct msgb *msg, uint8_t val)
291 {
292  uint8_t *buf = msgb_put(msg, 1);
293  return v_put(buf, val);
294 }
295 
298 static inline uint8_t *msgb_tv16_put(struct msgb *msg, uint8_t tag, uint16_t val)
299 {
300  uint8_t *buf = msgb_put(msg, 3);
301  return tv16_put(buf, tag, val);
302 }
303 
306 static inline uint8_t *msgb_tlv_push(struct msgb *msg, uint8_t tag, uint8_t len, const uint8_t *val)
307 {
308  uint8_t *buf = msgb_push(msg, TLV_GROSS_LEN(len));
309  tlv_put(buf, tag, len, val);
310  return buf;
311 }
312 
315 static inline uint8_t *msgb_tv_push(struct msgb *msg, uint8_t tag, uint8_t val)
316 {
317  uint8_t *buf = msgb_push(msg, 2);
318  tv_put(buf, tag, val);
319  return buf;
320 }
321 
324 static inline uint8_t *msgb_tv16_push(struct msgb *msg, uint8_t tag, uint16_t val)
325 {
326  uint8_t *buf = msgb_push(msg, 3);
327  tv16_put(buf, tag, val);
328  return buf;
329 }
330 
333 static inline uint8_t *msgb_tvlv_push(struct msgb *msg, uint8_t tag, uint16_t len,
334  const uint8_t *val)
335 {
336  uint8_t *buf = msgb_push(msg, TVLV_GROSS_LEN(len));
337  tvlv_put(buf, tag, len, val);
338  return buf;
339 }
340 
341 /* \brief push (prepend) a vTvL header to a \ref msgb
342  */
343 static inline uint8_t *msgb_vtvl_gan_push(struct msgb *msg, uint16_t tag,
344  uint16_t len)
345 {
346  uint8_t *buf = msgb_push(msg, VTVL_GAN_GROSS_LEN(tag, len));
347  vtvl_gan_put(buf, tag, len);
348  return buf;
349 }
350 
351 
352 static inline uint8_t *msgb_vtvlv_gan_push(struct msgb *msg, uint16_t tag,
353  uint16_t len, const uint8_t *val)
354 {
355  uint8_t *buf = msgb_push(msg, VTVLV_GAN_GROSS_LEN(tag, len));
356  vtvlv_gan_put(buf, tag, len, val);
357  return buf;
358 }
359 
360 /* TLV parsing */
361 
363 struct tlv_p_entry {
364  uint16_t len;
365  const uint8_t *val;
366 };
367 
369 enum tlv_type {
379 };
380 
382 struct tlv_def {
383  enum tlv_type type;
384  uint8_t fixed_len;
385 };
386 
389  struct tlv_def def[256];
390 };
391 
393 struct tlv_parsed {
394  struct tlv_p_entry lv[256];
395 };
396 
397 extern struct tlv_definition tvlv_att_def;
398 extern struct tlv_definition vtvlv_gan_att_def;
399 
400 int tlv_parse_one(uint8_t *o_tag, uint16_t *o_len, const uint8_t **o_val,
401  const struct tlv_definition *def,
402  const uint8_t *buf, int buf_len);
403 int tlv_parse(struct tlv_parsed *dec, const struct tlv_definition *def,
404  const uint8_t *buf, int buf_len, uint8_t lv_tag, uint8_t lv_tag2);
405 /* take a master (src) tlv def and fill up all empty slots in 'dst' */
406 void tlv_def_patch(struct tlv_definition *dst, const struct tlv_definition *src);
407 
408 #define TLVP_PRESENT(x, y) ((x)->lv[y].val)
409 #define TLVP_LEN(x, y) (x)->lv[y].len
410 #define TLVP_VAL(x, y) (x)->lv[y].val
411 
412 #define TLVP_PRES_LEN(tp, tag, min_len) \
413  (TLVP_PRESENT(tp, tag) && TLVP_LEN(tp, tag) >= min_len)
414 
420 static inline uint16_t tlvp_val16_unal(const struct tlv_parsed *tp, int pos)
421 {
422  uint16_t res;
423  memcpy(&res, TLVP_VAL(tp, pos), sizeof(res));
424  return res;
425 }
426 
432 static inline uint32_t tlvp_val32_unal(const struct tlv_parsed *tp, int pos)
433 {
434  uint32_t res;
435  memcpy(&res, TLVP_VAL(tp, pos), sizeof(res));
436  return res;
437 }
438 
439 struct tlv_parsed *osmo_tlvp_copy(const struct tlv_parsed *tp_orig, void *ctx);
440 int osmo_tlvp_merge(struct tlv_parsed *dst, const struct tlv_parsed *src);
441 int osmo_shift_v_fixed(uint8_t **data, size_t *data_len,
442  size_t len, uint8_t **value);
443 int osmo_match_shift_tv_fixed(uint8_t **data, size_t *data_len,
444  uint8_t tag, size_t len, uint8_t **value);
445 int osmo_shift_tlv(uint8_t **data, size_t *data_len,
446  uint8_t *tag, uint8_t **value, size_t *value_len);
447 int osmo_match_shift_tlv(uint8_t **data, size_t *data_len,
448  uint8_t tag, uint8_t **value, size_t *value_len);
449 int osmo_shift_lv(uint8_t **data, size_t *data_len,
450  uint8_t **value, size_t *value_len);
451 
tlv_parse_one
int tlv_parse_one(uint8_t *o_tag, uint16_t *o_len, const uint8_t **o_val, const struct tlv_definition *def, const uint8_t *buf, int buf_len)
Parse a single TLV encoded IE.
Definition: tlv_parser.c:115
msgb_l16tv_put
static uint8_t * msgb_l16tv_put(struct msgb *msg, uint16_t len, uint8_t tag, const uint8_t *val)
put (append) a L16TV field to msgb
Definition: tlv.h:204
osmo_match_shift_tlv
int osmo_match_shift_tlv(uint8_t **data, size_t *data_len, uint8_t tag, uint8_t **value, size_t *value_len)
Definition: tlv_parser.c:361
osmo_tlvp_copy
struct tlv_parsed * osmo_tlvp_copy(const struct tlv_parsed *tp_orig, void *ctx)
Copy tlv_parsed using given talloc context.
Definition: tlv_parser.c:52
tlv_p_entry::val
const uint8_t * val
pointer to value
Definition: tlv.h:365
osmo_tlvp_merge
int osmo_tlvp_merge(struct tlv_parsed *dst, const struct tlv_parsed *src)
Merge all tlv_parsed attributes of 'src' into 'dst'.
Definition: tlv_parser.c:87
tlv_def_patch
void tlv_def_patch(struct tlv_definition *dst, const struct tlv_definition *src)
take a master (src) tlvdev and fill up all empty slots in 'dst'
Definition: tlv_parser.c:266
TLV16_GROSS_LEN
#define TLV16_GROSS_LEN(x)
gross length of a TLV16 type field
Definition: tlv.h:31
tlv_parse
int tlv_parse(struct tlv_parsed *dec, const struct tlv_definition *def, const uint8_t *buf, int buf_len, uint8_t lv_tag, uint8_t lv_tag2)
Parse an entire buffer of TLV encoded Information Elements.
Definition: tlv_parser.c:215
osmo_shift_tlv
int osmo_shift_tlv(uint8_t **data, size_t *data_len, uint8_t *tag, uint8_t **value, size_t *value_len)
Definition: tlv_parser.c:389
TLV_TYPE_FIXED
@ TLV_TYPE_FIXED
fixed-length value-only
Definition: tlv.h:371
tlv_p_entry::len
uint16_t len
length
Definition: tlv.h:364
msgb_v_put
static uint8_t * msgb_v_put(struct msgb *msg, uint8_t val)
put (append) a V field to a msgb
Definition: tlv.h:290
msgb_tv16_put
static uint8_t * msgb_tv16_put(struct msgb *msg, uint8_t tag, uint16_t val)
put (append) a TV16 field to a msgb
Definition: tlv.h:298
LV_GROSS_LEN
#define LV_GROSS_LEN(x)
gross length of a LV type field
Definition: tlv.h:27
TLV_TYPE_T
@ TLV_TYPE_T
tag-only
Definition: tlv.h:372
vt_gan_put
static uint8_t * vt_gan_put(uint8_t *buf, uint16_t tag)
put (append) a variable-length tag or variable-length length *
Definition: tlv.h:137
VTVLV_GAN_GROSS_LEN
static uint16_t VTVLV_GAN_GROSS_LEN(uint16_t tag, uint16_t len)
gross length of vTvLV (tag+len+val)
Definition: tlv.h:64
msgb_tv16_push
static uint8_t * msgb_tv16_push(struct msgb *msg, uint8_t tag, uint16_t val)
push (prepend) a TV16 field to a msgb
Definition: tlv.h:324
TL16V_GROSS_LEN
#define TL16V_GROSS_LEN(x)
gross length of a TL16V type field
Definition: tlv.h:33
msgb_lv_put
static uint8_t * msgb_lv_put(struct msgb *msg, uint8_t len, const uint8_t *val)
put (append) a LV field to a msgb
Definition: tlv.h:257
tlv_p_entry
Entry in a TLV parser array.
Definition: tlv.h:363
TLV_TYPE_TLV
@ TLV_TYPE_TLV
tag-length-value
Definition: tlv.h:374
tv_fixed_put
static uint8_t * tv_fixed_put(uint8_t *buf, uint8_t tag, unsigned int len, const uint8_t *val)
put (append) a TVfixed field
Definition: tlv.h:233
TVLV_GROSS_LEN
static uint16_t TVLV_GROSS_LEN(uint16_t len)
gross length of a TVLV type field
Definition: tlv.h:41
TLV_TYPE_TvLV
@ TLV_TYPE_TvLV
tag, variable length, value
Definition: tlv.h:376
tlvp_val16_unal
static uint16_t tlvp_val16_unal(const struct tlv_parsed *tp, int pos)
Align given TLV element with 16 bit value to an even address.
Definition: tlv.h:420
tlv_definition
Definition of All 256 IE / TLV.
Definition: tlv.h:388
tlv_put
static uint8_t * tlv_put(uint8_t *buf, uint8_t tag, uint8_t len, const uint8_t *val)
put (append) a TLV field
Definition: tlv.h:91
tlv_def::type
enum tlv_type type
TLV type.
Definition: tlv.h:383
msgb_vtvlv_gan_put
static uint8_t * msgb_vtvlv_gan_put(struct msgb *msg, uint16_t tag, uint16_t len, const uint8_t *val)
put (append) a vTvLV field to msgb
Definition: tlv.h:196
v_put
static uint8_t * v_put(uint8_t *buf, uint8_t val)
put (append) a V field
Definition: tlv.h:217
tlv_def
Definition of a single IE (Information Element)
Definition: tlv.h:382
VTVL_GAN_GROSS_LEN
static uint16_t VTVL_GAN_GROSS_LEN(uint16_t tag, uint16_t len)
gross length of vTvL header (tag+len)
Definition: tlv.h:50
tlv_type
tlv_type
TLV type.
Definition: tlv.h:369
TLV_TYPE_TL16V
@ TLV_TYPE_TL16V
tag, 16 bit length, value
Definition: tlv.h:375
msgb_tlv16_put
static uint8_t * msgb_tlv16_put(struct msgb *msg, uint8_t tag, uint8_t len, const uint16_t *val)
put (append) a TLV16 field to msgb
Definition: tlv.h:173
L16TV_GROSS_LEN
#define L16TV_GROSS_LEN(x)
gross length of a L16TV type field
Definition: tlv.h:35
TVLV_MAX_ONEBYTE
#define TVLV_MAX_ONEBYTE
maximum length of TLV of one byte length
Definition: tlv.h:38
tlvp_val32_unal
static uint32_t tlvp_val32_unal(const struct tlv_parsed *tp, int pos)
Align given TLV element with 32 bit value to an address that is a multiple of 4.
Definition: tlv.h:432
osmo_match_shift_tv_fixed
int osmo_match_shift_tv_fixed(uint8_t **data, size_t *data_len, uint8_t tag, size_t len, uint8_t **value)
Definition: tlv_parser.c:323
msgb_tlv_put
static uint8_t * msgb_tlv_put(struct msgb *msg, uint8_t tag, uint8_t len, const uint8_t *val)
put (append) a TLV field to a msgb
Definition: tlv.h:265
TLV_TYPE_SINGLE_TV
@ TLV_TYPE_SINGLE_TV
tag and value (both 4 bit) in 1 byte
Definition: tlv.h:377
msgb_tl16v_put
static uint8_t * msgb_tl16v_put(struct msgb *msg, uint8_t tag, uint16_t len, const uint8_t *val)
put (append) a TL16V field to msgb
Definition: tlv.h:180
tlv_def::fixed_len
uint8_t fixed_len
length in case of TLV_TYPE_FIXED
Definition: tlv.h:384
msgb_tlv_push
static uint8_t * msgb_tlv_push(struct msgb *msg, uint8_t tag, uint8_t len, const uint8_t *val)
push (prepend) a TLV field to a msgb
Definition: tlv.h:306
tl16v_put
static uint8_t * tl16v_put(uint8_t *buf, uint8_t tag, uint16_t len, const uint8_t *val)
put (append) a TL16V field
Definition: tlv.h:111
data
uint8_t data[0]
actual payload data
Definition: gsm_08_58.h:4
tlv16_put
static uint8_t * tlv16_put(uint8_t *buf, uint8_t tag, uint8_t len, const uint16_t *val)
put (append) a TLV16 field
Definition: tlv.h:101
tv16_put
static uint8_t * tv16_put(uint8_t *buf, uint8_t tag, uint16_t val)
put (append) a TV16 field
Definition: tlv.h:246
TLV_TYPE_NONE
@ TLV_TYPE_NONE
no type
Definition: tlv.h:370
osmo_shift_v_fixed
int osmo_shift_v_fixed(uint8_t **data, size_t *data_len, size_t len, uint8_t **value)
Definition: tlv_parser.c:295
msgb_tvlv_put
static uint8_t * msgb_tvlv_put(struct msgb *msg, uint8_t tag, uint16_t len, const uint8_t *val)
put (append) a TvLV field to msgb
Definition: tlv.h:188
msgb_tv_push
static uint8_t * msgb_tv_push(struct msgb *msg, uint8_t tag, uint8_t val)
push (prepend) a TV field to a msgb
Definition: tlv.h:315
lv_put
static uint8_t * lv_put(uint8_t *buf, uint8_t len, const uint8_t *val)
put (append) a LV field
Definition: tlv.h:82
osmo_shift_lv
int osmo_shift_lv(uint8_t **data, size_t *data_len, uint8_t **value, size_t *value_len)
Definition: tlv_parser.c:429
tv_put
static uint8_t * tv_put(uint8_t *buf, uint8_t tag, uint8_t val)
put (append) a TV field
Definition: tlv.h:224
msgb_tv_fixed_put
static uint8_t * msgb_tv_fixed_put(struct msgb *msg, uint8_t tag, unsigned int len, const uint8_t *val)
put (append) a TVfixed field to a msgb
Definition: tlv.h:281
tvlv_put
static uint8_t * tvlv_put(uint8_t *buf, uint8_t tag, uint16_t len, const uint8_t *val)
put (append) a TvLV field
Definition: tlv.h:122
tlv_parsed
result of the TLV parser
Definition: tlv.h:393
TLV_GROSS_LEN
#define TLV_GROSS_LEN(x)
gross length of a TLV type field
Definition: tlv.h:29
msgb_tv_put
static uint8_t * msgb_tv_put(struct msgb *msg, uint8_t tag, uint8_t val)
put (append) a TV field to a msgb
Definition: tlv.h:273
msgb_tvlv_push
static uint8_t * msgb_tvlv_push(struct msgb *msg, uint8_t tag, uint16_t len, const uint8_t *val)
push (prepend) a TvLV field to a msgb
Definition: tlv.h:333
TLV_TYPE_vTvLV_GAN
@ TLV_TYPE_vTvLV_GAN
variable-length tag, variable-length length
Definition: tlv.h:378
TLV_TYPE_TV
@ TLV_TYPE_TV
tag-value (8bit)
Definition: tlv.h:373