libosmogsm  0.9.6.277-11f2
Osmocom GSM library
 All Data Structures Files Functions Variables Enumerations Enumerator Modules Pages
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 #include <osmocom/core/bit16gen.h>
8 #include <osmocom/core/bit32gen.h>
9 
15 /* Terminology / wording
16  tag length value (in bits)
17 
18  V - - 8
19  LV - 8 N * 8
20  TLV 8 8 N * 8
21  TL16V 8 16 N * 8
22  TLV16 8 8 N * 16
23  TvLV 8 8/16 N * 8
24  vTvLV 8/16 8/16 N * 8
25 
26 */
27 
29 #define LV_GROSS_LEN(x) (x+1)
30 
31 #define TLV_GROSS_LEN(x) (x+2)
32 
33 #define TLV16_GROSS_LEN(x) ((2*x)+2)
34 
35 #define TL16V_GROSS_LEN(x) (x+3)
36 
37 #define L16TV_GROSS_LEN(x) (x+3)
38 
40 #define TVLV_MAX_ONEBYTE 0x7f
41 
43 static inline uint16_t TVLV_GROSS_LEN(uint16_t len)
44 {
45  if (len <= TVLV_MAX_ONEBYTE)
46  return TLV_GROSS_LEN(len);
47  else
48  return TL16V_GROSS_LEN(len);
49 }
50 
52 static inline uint16_t VTVL_GAN_GROSS_LEN(uint16_t tag, uint16_t len)
53 {
54  uint16_t ret = 2;
55 
56  if (tag > TVLV_MAX_ONEBYTE)
57  ret++;
58 
59  if (len > TVLV_MAX_ONEBYTE)
60  ret++;
61 
62  return ret;
63 }
64 
66 static inline uint16_t VTVLV_GAN_GROSS_LEN(uint16_t tag, uint16_t len)
67 {
68  uint16_t ret;
69 
70  if (len <= TVLV_MAX_ONEBYTE)
71  ret = TLV_GROSS_LEN(len);
72  else
73  ret = TL16V_GROSS_LEN(len);
74 
75  if (tag > TVLV_MAX_ONEBYTE)
76  ret += 1;
77 
78  return ret;
79 }
80 
81 /* TLV generation */
82 
84 static inline uint8_t *lv_put(uint8_t *buf, uint8_t len,
85  const uint8_t *val)
86 {
87  *buf++ = len;
88  memcpy(buf, val, len);
89  return buf + len;
90 }
91 
93 static inline uint8_t *tlv_put(uint8_t *buf, uint8_t tag, uint8_t len,
94  const uint8_t *val)
95 {
96  *buf++ = tag;
97  *buf++ = len;
98  memcpy(buf, val, len);
99  return buf + len;
100 }
101 
103 static inline uint8_t *tlv16_put(uint8_t *buf, uint8_t tag, uint8_t len,
104  const uint16_t *val)
105 {
106  *buf++ = tag;
107  *buf++ = len;
108  memcpy(buf, val, len*2);
109  return buf + len*2;
110 }
111 
113 static inline uint8_t *tl16v_put(uint8_t *buf, uint8_t tag, uint16_t len,
114  const uint8_t *val)
115 {
116  *buf++ = tag;
117  *buf++ = len >> 8;
118  *buf++ = len & 0xff;
119  memcpy(buf, val, len);
120  return buf + len*2;
121 }
122 
124 static inline uint8_t *tvlv_put(uint8_t *buf, uint8_t tag, uint16_t len,
125  const uint8_t *val)
126 {
127  uint8_t *ret;
128 
129  if (len <= TVLV_MAX_ONEBYTE) {
130  ret = tlv_put(buf, tag, len, val);
131  buf[1] |= 0x80;
132  } else
133  ret = tl16v_put(buf, tag, len, val);
134 
135  return ret;
136 }
137 
139 static inline uint8_t *vt_gan_put(uint8_t *buf, uint16_t tag)
140 {
141  if (tag > TVLV_MAX_ONEBYTE) {
142  /* two-byte TAG */
143  *buf++ = 0x80 | (tag >> 8);
144  *buf++ = (tag & 0xff);
145  } else
146  *buf++ = tag;
147 
148  return buf;
149 }
150 
151 /* \brief put (append) vTvL (GAN) field (tag + length)*/
152 static inline uint8_t *vtvl_gan_put(uint8_t *buf, uint16_t tag, uint16_t len)
153 {
154  uint8_t *ret;
155 
156  ret = vt_gan_put(buf, tag);
157  return vt_gan_put(ret, len);
158 }
159 
160 /* \brief put (append) vTvLV (GAN) field (tag + length + val) */
161 static inline uint8_t *vtvlv_gan_put(uint8_t *buf, uint16_t tag, uint16_t len,
162  const uint8_t *val)
163 {
164  uint8_t *ret;
165 
166  ret = vtvl_gan_put(buf, tag, len );
167 
168  memcpy(ret, val, len);
169  ret = buf + len;
170 
171  return ret;
172 }
173 
175 static inline uint8_t *msgb_tlv16_put(struct msgb *msg, uint8_t tag, uint8_t len, const uint16_t *val)
176 {
177  uint8_t *buf = msgb_put(msg, TLV16_GROSS_LEN(len));
178  return tlv16_put(buf, tag, len, val);
179 }
180 
182 static inline uint8_t *msgb_tl16v_put(struct msgb *msg, uint8_t tag, uint16_t len,
183  const uint8_t *val)
184 {
185  uint8_t *buf = msgb_put(msg, TL16V_GROSS_LEN(len));
186  return tl16v_put(buf, tag, len, val);
187 }
188 
190 static inline uint8_t *msgb_tvlv_put(struct msgb *msg, uint8_t tag, uint16_t len,
191  const uint8_t *val)
192 {
193  uint8_t *buf = msgb_put(msg, TVLV_GROSS_LEN(len));
194  return tvlv_put(buf, tag, len, val);
195 }
196 
198 static inline uint8_t *msgb_vtvlv_gan_put(struct msgb *msg, uint16_t tag,
199  uint16_t len, const uint8_t *val)
200 {
201  uint8_t *buf = msgb_put(msg, VTVLV_GAN_GROSS_LEN(tag, len));
202  return vtvlv_gan_put(buf, tag, len, val);
203 }
204 
206 static inline uint8_t *msgb_l16tv_put(struct msgb *msg, uint16_t len, uint8_t tag,
207  const uint8_t *val)
208 {
209  uint8_t *buf = msgb_put(msg, L16TV_GROSS_LEN(len));
210 
211  *buf++ = len >> 8;
212  *buf++ = len & 0xff;
213  *buf++ = tag;
214  memcpy(buf, val, len);
215  return buf + len;
216 }
217 
219 static inline uint8_t *v_put(uint8_t *buf, uint8_t val)
220 {
221  *buf++ = val;
222  return buf;
223 }
224 
226 static inline uint8_t *tv_put(uint8_t *buf, uint8_t tag,
227  uint8_t val)
228 {
229  *buf++ = tag;
230  *buf++ = val;
231  return buf;
232 }
233 
235 static inline uint8_t *tv_fixed_put(uint8_t *buf, uint8_t tag,
236  unsigned int len, const uint8_t *val)
237 {
238  *buf++ = tag;
239  memcpy(buf, val, len);
240  return buf + len;
241 }
242 
248 static inline uint8_t *tv16_put(uint8_t *buf, uint8_t tag,
249  uint16_t val)
250 {
251  *buf++ = tag;
252  *buf++ = val >> 8;
253  *buf++ = val & 0xff;
254  return buf;
255 }
256 
259 static inline uint8_t *msgb_lv_put(struct msgb *msg, uint8_t len, const uint8_t *val)
260 {
261  uint8_t *buf = msgb_put(msg, LV_GROSS_LEN(len));
262  return lv_put(buf, len, val);
263 }
264 
267 static inline uint8_t *msgb_tlv_put(struct msgb *msg, uint8_t tag, uint8_t len, const uint8_t *val)
268 {
269  uint8_t *buf = msgb_put(msg, TLV_GROSS_LEN(len));
270  return tlv_put(buf, tag, len, val);
271 }
272 
275 static inline uint8_t *msgb_tv_put(struct msgb *msg, uint8_t tag, uint8_t val)
276 {
277  uint8_t *buf = msgb_put(msg, 2);
278  return tv_put(buf, tag, val);
279 }
280 
283 static inline uint8_t *msgb_tv_fixed_put(struct msgb *msg, uint8_t tag,
284  unsigned int len, const uint8_t *val)
285 {
286  uint8_t *buf = msgb_put(msg, 1+len);
287  return tv_fixed_put(buf, tag, len, val);
288 }
289 
292 static inline uint8_t *msgb_v_put(struct msgb *msg, uint8_t val)
293 {
294  uint8_t *buf = msgb_put(msg, 1);
295  return v_put(buf, val);
296 }
297 
300 static inline uint8_t *msgb_tv16_put(struct msgb *msg, uint8_t tag, uint16_t val)
301 {
302  uint8_t *buf = msgb_put(msg, 3);
303  return tv16_put(buf, tag, val);
304 }
305 
308 static inline uint8_t *msgb_tlv_push(struct msgb *msg, uint8_t tag, uint8_t len, const uint8_t *val)
309 {
310  uint8_t *buf = msgb_push(msg, TLV_GROSS_LEN(len));
311  tlv_put(buf, tag, len, val);
312  return buf;
313 }
314 
317 static inline uint8_t *msgb_tv_push(struct msgb *msg, uint8_t tag, uint8_t val)
318 {
319  uint8_t *buf = msgb_push(msg, 2);
320  tv_put(buf, tag, val);
321  return buf;
322 }
323 
326 static inline uint8_t *msgb_tv16_push(struct msgb *msg, uint8_t tag, uint16_t val)
327 {
328  uint8_t *buf = msgb_push(msg, 3);
329  tv16_put(buf, tag, val);
330  return buf;
331 }
332 
335 static inline uint8_t *msgb_tvlv_push(struct msgb *msg, uint8_t tag, uint16_t len,
336  const uint8_t *val)
337 {
338  uint8_t *buf = msgb_push(msg, TVLV_GROSS_LEN(len));
339  tvlv_put(buf, tag, len, val);
340  return buf;
341 }
342 
343 /* \brief push (prepend) a vTvL header to a \ref msgb
344  */
345 static inline uint8_t *msgb_vtvl_gan_push(struct msgb *msg, uint16_t tag,
346  uint16_t len)
347 {
348  uint8_t *buf = msgb_push(msg, VTVL_GAN_GROSS_LEN(tag, len));
349  vtvl_gan_put(buf, tag, len);
350  return buf;
351 }
352 
353 
354 static inline uint8_t *msgb_vtvlv_gan_push(struct msgb *msg, uint16_t tag,
355  uint16_t len, const uint8_t *val)
356 {
357  uint8_t *buf = msgb_push(msg, VTVLV_GAN_GROSS_LEN(tag, len));
358  vtvlv_gan_put(buf, tag, len, val);
359  return buf;
360 }
361 
362 /* TLV parsing */
363 
365 struct tlv_p_entry {
366  uint16_t len;
367  const uint8_t *val;
368 };
369 
371 enum tlv_type {
381 };
382 
384 struct tlv_def {
385  enum tlv_type type;
386  uint8_t fixed_len;
387 };
388 
391  struct tlv_def def[256];
392 };
393 
395 struct tlv_parsed {
396  struct tlv_p_entry lv[256];
397 };
398 
399 extern struct tlv_definition tvlv_att_def;
400 extern struct tlv_definition vtvlv_gan_att_def;
401 
402 int tlv_parse_one(uint8_t *o_tag, uint16_t *o_len, const uint8_t **o_val,
403  const struct tlv_definition *def,
404  const uint8_t *buf, int buf_len);
405 int tlv_parse(struct tlv_parsed *dec, const struct tlv_definition *def,
406  const uint8_t *buf, int buf_len, uint8_t lv_tag, uint8_t lv_tag2);
407 /* take a master (src) tlv def and fill up all empty slots in 'dst' */
408 void tlv_def_patch(struct tlv_definition *dst, const struct tlv_definition *src);
409 
410 #define TLVP_PRESENT(x, y) ((x)->lv[y].val)
411 #define TLVP_LEN(x, y) (x)->lv[y].len
412 #define TLVP_VAL(x, y) (x)->lv[y].val
413 
414 #define TLVP_PRES_LEN(tp, tag, min_len) \
415  (TLVP_PRESENT(tp, tag) && TLVP_LEN(tp, tag) >= min_len)
416 
422 static inline uint16_t tlvp_val16_unal(const struct tlv_parsed *tp, int pos)
423 {
424  uint16_t res;
425  memcpy(&res, TLVP_VAL(tp, pos), sizeof(res));
426  return res;
427 }
428 
434 static inline uint32_t tlvp_val32_unal(const struct tlv_parsed *tp, int pos)
435 {
436  uint32_t res;
437  memcpy(&res, TLVP_VAL(tp, pos), sizeof(res));
438  return res;
439 }
440 
446 static inline uint16_t tlvp_val16be(const struct tlv_parsed *tp, int pos)
447 {
448  return osmo_load16be(TLVP_VAL(tp, pos));
449 }
450 
456 static inline uint32_t tlvp_val32be(const struct tlv_parsed *tp, int pos)
457 {
458  return osmo_load32be(TLVP_VAL(tp, pos));
459 }
460 
461 
462 struct tlv_parsed *osmo_tlvp_copy(const struct tlv_parsed *tp_orig, void *ctx);
463 int osmo_tlvp_merge(struct tlv_parsed *dst, const struct tlv_parsed *src);
464 int osmo_shift_v_fixed(uint8_t **data, size_t *data_len,
465  size_t len, uint8_t **value);
466 int osmo_match_shift_tv_fixed(uint8_t **data, size_t *data_len,
467  uint8_t tag, size_t len, uint8_t **value);
468 int osmo_shift_tlv(uint8_t **data, size_t *data_len,
469  uint8_t *tag, uint8_t **value, size_t *value_len);
470 int osmo_match_shift_tlv(uint8_t **data, size_t *data_len,
471  uint8_t tag, uint8_t **value, size_t *value_len);
472 int osmo_shift_lv(uint8_t **data, size_t *data_len,
473  uint8_t **value, size_t *value_len);
474 
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:317
static uint16_t VTVLV_GAN_GROSS_LEN(uint16_t tag, uint16_t len)
gross length of vTvLV (tag+len+val)
Definition: tlv.h:66
static uint16_t tlvp_val16be(const struct tlv_parsed *tp, int pos)
Retrieve (possibly unaligned) TLV element and convert to host byte order.
Definition: tlv.h:446
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:326
static uint8_t * tv_put(uint8_t *buf, uint8_t tag, uint8_t val)
put (append) a TV field
Definition: tlv.h:226
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:206
uint16_t len
length
Definition: tlv.h:366
int osmo_shift_v_fixed(uint8_t **data, size_t *data_len, size_t len, uint8_t **value)
Definition: tlv_parser.c:312
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:175
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:275
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:130
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:335
static uint32_t tlvp_val32be(const struct tlv_parsed *tp, int pos)
Retrieve (possibly unaligned) TLV element and convert to host byte order.
Definition: tlv.h:456
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:340
static uint16_t TVLV_GROSS_LEN(uint16_t len)
gross length of a TVLV type field
Definition: tlv.h:43
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:139
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:124
static uint8_t * lv_put(uint8_t *buf, uint8_t len, const uint8_t *val)
put (append) a LV field
Definition: tlv.h:84
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:406
Entry in a TLV parser array.
Definition: tlv.h:365
#define TLV_GROSS_LEN(x)
gross length of a TLV type field
Definition: tlv.h:31
tag-value (8bit)
Definition: tlv.h:375
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:235
#define TL16V_GROSS_LEN(x)
gross length of a TL16V type field
Definition: tlv.h:35
no type
Definition: tlv.h:372
#define TVLV_MAX_ONEBYTE
maximum length of TLV of one byte length
Definition: tlv.h:40
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:378
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:198
static uint16_t VTVL_GAN_GROSS_LEN(uint16_t tag, uint16_t len)
gross length of vTvL header (tag+len)
Definition: tlv.h:52
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:300
#define TLV16_GROSS_LEN(x)
gross length of a TLV16 type field
Definition: tlv.h:33
Definition of a single IE (Information Element)
Definition: tlv.h:384
#define L16TV_GROSS_LEN(x)
gross length of a L16TV type field
Definition: tlv.h:37
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:113
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:267
enum tlv_type type
TLV type.
Definition: tlv.h:385
static uint8_t * tv16_put(uint8_t *buf, uint8_t tag, uint16_t val)
put (append) a TV16 field
Definition: tlv.h:248
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:422
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:103
int osmo_shift_lv(uint8_t **data, size_t *data_len, uint8_t **value, size_t *value_len)
Definition: tlv_parser.c:446
tag-length-value
Definition: tlv.h:376
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:283
tlv_type
TLV type.
Definition: tlv.h:371
static uint8_t * v_put(uint8_t *buf, uint8_t val)
put (append) a V field
Definition: tlv.h:219
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:182
variable-length tag, variable-length length
Definition: tlv.h:380
tag, 16 bit length, value
Definition: tlv.h:377
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:67
result of the TLV parser
Definition: tlv.h:395
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:93
uint8_t fixed_len
length in case of TLV_TYPE_FIXED
Definition: tlv.h:386
fixed-length value-only
Definition: tlv.h:373
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:283
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:434
Definition of All 256 IE / TLV.
Definition: tlv.h:390
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:102
static uint8_t * msgb_v_put(struct msgb *msg, uint8_t val)
put (append) a V field to a msgb
Definition: tlv.h:292
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:230
#define LV_GROSS_LEN(x)
gross length of a LV type field
Definition: tlv.h:29
tag-only
Definition: tlv.h:374
tag, variable length, value
Definition: tlv.h:378
const uint8_t * val
pointer to value
Definition: tlv.h:367
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:308
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:259
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:190
tag and value (both 4 bit) in 1 byte
Definition: tlv.h:379