blob: ae88e6ed39412535066e604396d9cdc16869b1fe [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 Weltea4d49e92009-05-23 06:39:58 +00009#define LV_GROSS_LEN(x) (x+1)
Harald Welte52b1f982008-12-23 20:25:15 +000010#define TLV_GROSS_LEN(x) (x+2)
11#define TLV16_GROSS_LEN(x) ((2*x)+2)
Harald Welte702d8702008-12-26 20:25:35 +000012#define TL16V_GROSS_LEN(x) (x+3)
Harald Welte52b1f982008-12-23 20:25:15 +000013
Harald Welte91b5b0d2009-02-06 12:51:39 +000014/* TLV generation */
15
Harald Weltea4d49e92009-05-23 06:39:58 +000016static inline u_int8_t *lv_put(u_int8_t *buf, u_int8_t len,
17 const u_int8_t *val)
18{
19 *buf++ = len;
20 memcpy(buf, val, len);
21 return buf + len;
22}
23
Harald Welte52b1f982008-12-23 20:25:15 +000024static inline u_int8_t *tlv_put(u_int8_t *buf, u_int8_t tag, u_int8_t len,
25 const u_int8_t *val)
26{
27 *buf++ = tag;
28 *buf++ = len;
29 memcpy(buf, val, len);
30 return buf + len;
31}
32
33static inline u_int8_t *tlv16_put(u_int8_t *buf, u_int8_t tag, u_int8_t len,
34 const u_int16_t *val)
35{
36 *buf++ = tag;
37 *buf++ = len;
38 memcpy(buf, val, len*2);
39 return buf + len*2;
40}
41
Harald Welte702d8702008-12-26 20:25:35 +000042static inline u_int8_t *tl16v_put(u_int8_t *buf, u_int8_t tag, u_int16_t len,
43 const u_int8_t *val)
44{
45 *buf++ = tag;
46 *buf++ = len >> 8;
47 *buf++ = len & 0xff;
48 memcpy(buf, val, len);
49 return buf + len*2;
50}
51
Harald Welte52b1f982008-12-23 20:25:15 +000052static inline u_int8_t *msgb_tlv16_put(struct msgb *msg, u_int8_t tag, u_int8_t len, const u_int16_t *val)
53{
54 u_int8_t *buf = msgb_put(msg, TLV16_GROSS_LEN(len));
55 return tlv16_put(buf, tag, len, val);
56}
57
Harald Welte702d8702008-12-26 20:25:35 +000058static inline u_int8_t *msgb_tl16v_put(struct msgb *msg, u_int8_t tag, u_int16_t len,
59 const u_int8_t *val)
60{
61 u_int8_t *buf = msgb_put(msg, TL16V_GROSS_LEN(len));
62 return tl16v_put(buf, tag, len, val);
63}
64
Harald Weltea4d49e92009-05-23 06:39:58 +000065static inline u_int8_t *v_put(u_int8_t *buf, u_int8_t val)
66{
67 *buf++ = val;
68 return buf;
69}
70
Harald Welte52b1f982008-12-23 20:25:15 +000071static inline u_int8_t *tv_put(u_int8_t *buf, u_int8_t tag,
72 u_int8_t val)
73{
74 *buf++ = tag;
75 *buf++ = val;
76 return buf;
77}
78
Harald Welte4b634542008-12-27 01:55:51 +000079static inline u_int8_t *tv16_put(u_int8_t *buf, u_int8_t tag,
80 u_int16_t val)
81{
82 *buf++ = tag;
83 *buf++ = val >> 8;
84 *buf++ = val & 0xff;
85 return buf;
86}
87
Harald Weltea4d49e92009-05-23 06:39:58 +000088static inline u_int8_t *msgb_lv_put(struct msgb *msg, u_int8_t len, const u_int8_t *val)
89{
90 u_int8_t *buf = msgb_put(msg, LV_GROSS_LEN(len));
91 return lv_put(buf, len, val);
92}
93
Harald Welte52b1f982008-12-23 20:25:15 +000094static inline u_int8_t *msgb_tlv_put(struct msgb *msg, u_int8_t tag, u_int8_t len, const u_int8_t *val)
95{
96 u_int8_t *buf = msgb_put(msg, TLV_GROSS_LEN(len));
97 return tlv_put(buf, tag, len, val);
98}
99
100static inline u_int8_t *msgb_tv_put(struct msgb *msg, u_int8_t tag, u_int8_t val)
101{
102 u_int8_t *buf = msgb_put(msg, 2);
103 return tv_put(buf, tag, val);
104}
105
Harald Weltea4d49e92009-05-23 06:39:58 +0000106static inline u_int8_t *msgb_v_put(struct msgb *msg, u_int8_t val)
107{
108 u_int8_t *buf = msgb_put(msg, 1);
109 return v_put(buf, val);
110}
111
Harald Welte4b634542008-12-27 01:55:51 +0000112static inline u_int8_t *msgb_tv16_put(struct msgb *msg, u_int8_t tag, u_int16_t val)
113{
114 u_int8_t *buf = msgb_put(msg, 3);
115 return tv16_put(buf, tag, val);
116}
117
Harald Welte52b1f982008-12-23 20:25:15 +0000118static inline u_int8_t *msgb_tlv_push(struct msgb *msg, u_int8_t tag, u_int8_t len, const u_int8_t *val)
119{
120 u_int8_t *buf = msgb_push(msg, TLV_GROSS_LEN(len));
121 return tlv_put(buf, tag, len, val);
122}
123
124static inline u_int8_t *msgb_tv_push(struct msgb *msg, u_int8_t tag, u_int8_t val)
125{
126 u_int8_t *buf = msgb_push(msg, 2);
127 return tv_put(buf, tag, val);
128}
129
Harald Welte4b634542008-12-27 01:55:51 +0000130static inline u_int8_t *msgb_tv16_push(struct msgb *msg, u_int8_t tag, u_int16_t val)
131{
132 u_int8_t *buf = msgb_push(msg, 3);
133 return tv16_put(buf, tag, val);
134}
135
Harald Welte91b5b0d2009-02-06 12:51:39 +0000136/* TLV parsing */
137
138struct tlv_p_entry {
Harald Weltee0590df2009-02-15 03:34:15 +0000139 u_int16_t len;
Harald Welte7bc4cbc2009-02-21 12:59:22 +0000140 const u_int8_t *val;
Harald Welte91b5b0d2009-02-06 12:51:39 +0000141};
142
Harald Weltee0590df2009-02-15 03:34:15 +0000143enum tlv_type {
144 TLV_TYPE_FIXED,
145 TLV_TYPE_T,
146 TLV_TYPE_TV,
147 TLV_TYPE_TLV,
148 TLV_TYPE_TL16V,
149};
150
151struct tlv_def {
152 enum tlv_type type;
153 u_int8_t fixed_len;
154};
155
156struct tlv_definition {
157 struct tlv_def def[0xff];
158};
159
Harald Welte2fa79342009-02-14 19:07:10 +0000160struct tlv_parsed {
Harald Welte91b5b0d2009-02-06 12:51:39 +0000161 struct tlv_p_entry lv[0xff];
162};
163
Harald Welte7bc4cbc2009-02-21 12:59:22 +0000164int tlv_parse(struct tlv_parsed *dec, const struct tlv_definition *def,
Harald Weltea4d49e92009-05-23 06:39:58 +0000165 const u_int8_t *buf, int buf_len, u_int8_t lv_tag, u_int8_t lv_tag2);
Harald Welte2fa79342009-02-14 19:07:10 +0000166
167#define TLVP_PRESENT(x, y) ((x)->lv[y].val)
168#define TLVP_LEN(x, y) (x)->lv[y].len
169#define TLVP_VAL(x, y) (x)->lv[y].val
Harald Welte4b634542008-12-27 01:55:51 +0000170
Harald Welte52b1f982008-12-23 20:25:15 +0000171#endif /* _TLV_H */