blob: 453f1d0a09f70f396cd5e9d542a33d6f2c977d73 [file] [log] [blame]
Harald Welte52b1f982008-12-23 20:25:15 +00001#ifndef _TLV_H
2#define _TLV_H
3
4#include <sys/types.h>
5#include <string.h>
6
Harald Welte91b5b0d2009-02-06 12:51:39 +00007#include <openbsc/msgb.h>
8
Harald Welte52b1f982008-12-23 20:25:15 +00009#define TLV_GROSS_LEN(x) (x+2)
10#define TLV16_GROSS_LEN(x) ((2*x)+2)
Harald Welte702d8702008-12-26 20:25:35 +000011#define TL16V_GROSS_LEN(x) (x+3)
Harald Welte52b1f982008-12-23 20:25:15 +000012
Harald Welte91b5b0d2009-02-06 12:51:39 +000013/* TLV generation */
14
Harald Welte52b1f982008-12-23 20:25:15 +000015static inline u_int8_t *tlv_put(u_int8_t *buf, u_int8_t tag, u_int8_t len,
16 const u_int8_t *val)
17{
18 *buf++ = tag;
19 *buf++ = len;
20 memcpy(buf, val, len);
21 return buf + len;
22}
23
24static inline u_int8_t *tlv16_put(u_int8_t *buf, u_int8_t tag, u_int8_t len,
25 const u_int16_t *val)
26{
27 *buf++ = tag;
28 *buf++ = len;
29 memcpy(buf, val, len*2);
30 return buf + len*2;
31}
32
Harald Welte702d8702008-12-26 20:25:35 +000033static inline u_int8_t *tl16v_put(u_int8_t *buf, u_int8_t tag, u_int16_t len,
34 const u_int8_t *val)
35{
36 *buf++ = tag;
37 *buf++ = len >> 8;
38 *buf++ = len & 0xff;
39 memcpy(buf, val, len);
40 return buf + len*2;
41}
42
Harald Welte52b1f982008-12-23 20:25:15 +000043static inline u_int8_t *msgb_tlv16_put(struct msgb *msg, u_int8_t tag, u_int8_t len, const u_int16_t *val)
44{
45 u_int8_t *buf = msgb_put(msg, TLV16_GROSS_LEN(len));
46 return tlv16_put(buf, tag, len, val);
47}
48
Harald Welte702d8702008-12-26 20:25:35 +000049static inline u_int8_t *msgb_tl16v_put(struct msgb *msg, u_int8_t tag, u_int16_t len,
50 const u_int8_t *val)
51{
52 u_int8_t *buf = msgb_put(msg, TL16V_GROSS_LEN(len));
53 return tl16v_put(buf, tag, len, val);
54}
55
Harald Welte52b1f982008-12-23 20:25:15 +000056static inline u_int8_t *tv_put(u_int8_t *buf, u_int8_t tag,
57 u_int8_t val)
58{
59 *buf++ = tag;
60 *buf++ = val;
61 return buf;
62}
63
Harald Welte4b634542008-12-27 01:55:51 +000064static inline u_int8_t *tv16_put(u_int8_t *buf, u_int8_t tag,
65 u_int16_t val)
66{
67 *buf++ = tag;
68 *buf++ = val >> 8;
69 *buf++ = val & 0xff;
70 return buf;
71}
72
Harald Welte52b1f982008-12-23 20:25:15 +000073static inline u_int8_t *msgb_tlv_put(struct msgb *msg, u_int8_t tag, u_int8_t len, const u_int8_t *val)
74{
75 u_int8_t *buf = msgb_put(msg, TLV_GROSS_LEN(len));
76 return tlv_put(buf, tag, len, val);
77}
78
79static inline u_int8_t *msgb_tv_put(struct msgb *msg, u_int8_t tag, u_int8_t val)
80{
81 u_int8_t *buf = msgb_put(msg, 2);
82 return tv_put(buf, tag, val);
83}
84
Harald Welte4b634542008-12-27 01:55:51 +000085static inline u_int8_t *msgb_tv16_put(struct msgb *msg, u_int8_t tag, u_int16_t val)
86{
87 u_int8_t *buf = msgb_put(msg, 3);
88 return tv16_put(buf, tag, val);
89}
90
Harald Welte52b1f982008-12-23 20:25:15 +000091static inline u_int8_t *msgb_tlv_push(struct msgb *msg, u_int8_t tag, u_int8_t len, const u_int8_t *val)
92{
93 u_int8_t *buf = msgb_push(msg, TLV_GROSS_LEN(len));
94 return tlv_put(buf, tag, len, val);
95}
96
97static inline u_int8_t *msgb_tv_push(struct msgb *msg, u_int8_t tag, u_int8_t val)
98{
99 u_int8_t *buf = msgb_push(msg, 2);
100 return tv_put(buf, tag, val);
101}
102
Harald Welte4b634542008-12-27 01:55:51 +0000103static inline u_int8_t *msgb_tv16_push(struct msgb *msg, u_int8_t tag, u_int16_t val)
104{
105 u_int8_t *buf = msgb_push(msg, 3);
106 return tv16_put(buf, tag, val);
107}
108
Harald Welte91b5b0d2009-02-06 12:51:39 +0000109/* TLV parsing */
110
111struct tlv_p_entry {
Harald Weltee0590df2009-02-15 03:34:15 +0000112 u_int16_t len;
Harald Welte7bc4cbc2009-02-21 12:59:22 +0000113 const u_int8_t *val;
Harald Welte91b5b0d2009-02-06 12:51:39 +0000114};
115
Harald Weltee0590df2009-02-15 03:34:15 +0000116enum tlv_type {
117 TLV_TYPE_FIXED,
118 TLV_TYPE_T,
119 TLV_TYPE_TV,
120 TLV_TYPE_TLV,
121 TLV_TYPE_TL16V,
122};
123
124struct tlv_def {
125 enum tlv_type type;
126 u_int8_t fixed_len;
127};
128
129struct tlv_definition {
130 struct tlv_def def[0xff];
131};
132
Harald Welte2fa79342009-02-14 19:07:10 +0000133struct tlv_parsed {
Harald Welte91b5b0d2009-02-06 12:51:39 +0000134 struct tlv_p_entry lv[0xff];
135};
136
Harald Welte7bc4cbc2009-02-21 12:59:22 +0000137int tlv_parse(struct tlv_parsed *dec, const struct tlv_definition *def,
138 const u_int8_t *buf, int buf_len);
Harald Welte2fa79342009-02-14 19:07:10 +0000139
140#define TLVP_PRESENT(x, y) ((x)->lv[y].val)
141#define TLVP_LEN(x, y) (x)->lv[y].len
142#define TLVP_VAL(x, y) (x)->lv[y].val
Harald Welte4b634542008-12-27 01:55:51 +0000143
Harald Welte52b1f982008-12-23 20:25:15 +0000144#endif /* _TLV_H */