blob: 397327567e9e18e92bf60ceab95b91ac5ceef624 [file] [log] [blame]
Harald Weltefbd02fa2016-04-25 15:19:35 +02001#include <osmocom/gsm/tlv.h>
2
3static void check_tlv_parse(uint8_t **data, size_t *data_len,
4 uint8_t exp_tag, size_t exp_len, const uint8_t *exp_val)
5{
6 uint8_t *value;
7 size_t value_len;
8 uint8_t tag;
9 int rc;
10 uint8_t *saved_data = *data;
11 size_t saved_data_len = *data_len;
12
13 rc = osmo_match_shift_tlv(data, data_len, exp_tag ^ 1, NULL, NULL);
14 OSMO_ASSERT(rc == 0);
15
16 rc = osmo_match_shift_tlv(data, data_len, exp_tag, &value, &value_len);
17 OSMO_ASSERT(rc == (int)value_len + 2);
18 OSMO_ASSERT(value_len == exp_len);
19 OSMO_ASSERT(memcmp(value, exp_val, exp_len) == 0);
20
21 /* restore data/data_len */
22 *data = saved_data;
23 *data_len = saved_data_len;
24
25 rc = osmo_shift_tlv(data, data_len, &tag, &value, &value_len);
26 OSMO_ASSERT(rc == (int)value_len + 2);
27 OSMO_ASSERT(tag == exp_tag);
28 OSMO_ASSERT(value_len == exp_len);
29 OSMO_ASSERT(memcmp(value, exp_val, exp_len) == 0);
30}
31
32static void check_tv_fixed_match(uint8_t **data, size_t *data_len,
33 uint8_t tag, size_t len, const uint8_t *exp_val)
34{
35 uint8_t *value;
36 int rc;
37
38 rc = osmo_match_shift_tv_fixed(data, data_len, tag ^ 1, len, NULL);
39 OSMO_ASSERT(rc == 0);
40
41 rc = osmo_match_shift_tv_fixed(data, data_len, tag, len, &value);
42 OSMO_ASSERT(rc == (int)len + 1);
43 OSMO_ASSERT(memcmp(value, exp_val, len) == 0);
44}
45
46static void check_v_fixed_shift(uint8_t **data, size_t *data_len,
47 size_t len, const uint8_t *exp_val)
48{
49 uint8_t *value;
50 int rc;
51
52 rc = osmo_shift_v_fixed(data, data_len, len, &value);
53 OSMO_ASSERT(rc == (int)len);
54 OSMO_ASSERT(memcmp(value, exp_val, len) == 0);
55}
56
57static void check_lv_shift(uint8_t **data, size_t *data_len,
58 size_t exp_len, const uint8_t *exp_val)
59{
60 uint8_t *value;
61 size_t value_len;
62 int rc;
63
64 rc = osmo_shift_lv(data, data_len, &value, &value_len);
65 OSMO_ASSERT(rc == (int)value_len + 1);
66 OSMO_ASSERT(value_len == exp_len);
67 OSMO_ASSERT(memcmp(value, exp_val, exp_len) == 0);
68}
69
70static void check_tlv_match_data_len(size_t data_len, uint8_t tag, size_t len,
71 const uint8_t *test_data)
72{
Pau Espin Pedrol21be8372017-06-18 00:52:56 +020073 uint8_t buf[301] = {0};
74 *buf = 0xfe;
Harald Weltefbd02fa2016-04-25 15:19:35 +020075
Pau Espin Pedrol21be8372017-06-18 00:52:56 +020076 uint8_t *unchanged_ptr = buf;
Harald Weltefbd02fa2016-04-25 15:19:35 +020077 size_t unchanged_len = 0xdead;
78 size_t tmp_data_len = data_len;
79 uint8_t *value = unchanged_ptr;
80 size_t value_len = unchanged_len;
Pau Espin Pedrol21be8372017-06-18 00:52:56 +020081 uint8_t *data = buf + 1;
Harald Weltefbd02fa2016-04-25 15:19:35 +020082
Pau Espin Pedrol21be8372017-06-18 00:52:56 +020083 OSMO_ASSERT(data_len <= sizeof(buf) - 1);
Harald Weltefbd02fa2016-04-25 15:19:35 +020084
85 tlv_put(data, tag, len, test_data);
86 if (data_len < len + 2) {
87 OSMO_ASSERT(-1 == osmo_match_shift_tlv(&data, &tmp_data_len,
88 tag, &value, &value_len));
89 OSMO_ASSERT(tmp_data_len == 0);
Pau Espin Pedrol21be8372017-06-18 00:52:56 +020090 OSMO_ASSERT(data == buf + 1 + data_len);
Harald Weltefbd02fa2016-04-25 15:19:35 +020091 OSMO_ASSERT(value == unchanged_ptr);
92 OSMO_ASSERT(value_len == unchanged_len);
93 } else {
94 OSMO_ASSERT(0 <= osmo_match_shift_tlv(&data, &tmp_data_len,
95 tag, &value, &value_len));
96 OSMO_ASSERT(value != unchanged_ptr);
97 OSMO_ASSERT(value_len != unchanged_len);
98 }
99}
100
101static void check_tv_fixed_match_data_len(size_t data_len,
102 uint8_t tag, size_t len,
103 const uint8_t *test_data)
104{
Pau Espin Pedrol21be8372017-06-18 00:52:56 +0200105 uint8_t buf[301] = {0};
106 *buf = 0xfe;
Harald Weltefbd02fa2016-04-25 15:19:35 +0200107
Pau Espin Pedrol21be8372017-06-18 00:52:56 +0200108 uint8_t *unchanged_ptr = buf;
Harald Weltefbd02fa2016-04-25 15:19:35 +0200109 size_t tmp_data_len = data_len;
110 uint8_t *value = unchanged_ptr;
Pau Espin Pedrol21be8372017-06-18 00:52:56 +0200111 uint8_t *data = buf + 1;
Harald Weltefbd02fa2016-04-25 15:19:35 +0200112
Pau Espin Pedrol21be8372017-06-18 00:52:56 +0200113 OSMO_ASSERT(data_len <= sizeof(buf) - 1);
Harald Weltefbd02fa2016-04-25 15:19:35 +0200114
115 tv_fixed_put(data, tag, len, test_data);
116
117 if (data_len < len + 1) {
118 OSMO_ASSERT(-1 == osmo_match_shift_tv_fixed(&data, &tmp_data_len,
119 tag, len, &value));
120 OSMO_ASSERT(tmp_data_len == 0);
Pau Espin Pedrol21be8372017-06-18 00:52:56 +0200121 OSMO_ASSERT(data == buf + 1 + data_len);
Harald Weltefbd02fa2016-04-25 15:19:35 +0200122 OSMO_ASSERT(value == unchanged_ptr);
123 } else {
124 OSMO_ASSERT(0 <= osmo_match_shift_tv_fixed(&data, &tmp_data_len,
125 tag, len, &value));
126 OSMO_ASSERT(value != unchanged_ptr);
127 }
128}
129
130static void check_v_fixed_shift_data_len(size_t data_len,
131 size_t len, const uint8_t *test_data)
132{
Pau Espin Pedrol21be8372017-06-18 00:52:56 +0200133 uint8_t buf[301] = {0};
134 *buf = 0xfe;
Harald Weltefbd02fa2016-04-25 15:19:35 +0200135
Pau Espin Pedrol21be8372017-06-18 00:52:56 +0200136 uint8_t *unchanged_ptr = buf;
Harald Weltefbd02fa2016-04-25 15:19:35 +0200137 size_t tmp_data_len = data_len;
138 uint8_t *value = unchanged_ptr;
Pau Espin Pedrol21be8372017-06-18 00:52:56 +0200139 uint8_t *data = buf + 1;
Harald Weltefbd02fa2016-04-25 15:19:35 +0200140
Pau Espin Pedrol21be8372017-06-18 00:52:56 +0200141 OSMO_ASSERT(data_len <= sizeof(buf) - 1);
Harald Weltefbd02fa2016-04-25 15:19:35 +0200142
143 memcpy(data, test_data, len);
144
145 if (data_len < len) {
146 OSMO_ASSERT(-1 == osmo_shift_v_fixed(&data, &tmp_data_len,
147 len, &value));
148 OSMO_ASSERT(tmp_data_len == 0);
Pau Espin Pedrol21be8372017-06-18 00:52:56 +0200149 OSMO_ASSERT(data == buf + 1 + data_len);
Harald Weltefbd02fa2016-04-25 15:19:35 +0200150 OSMO_ASSERT(value == unchanged_ptr);
151 } else {
152 OSMO_ASSERT(0 <= osmo_shift_v_fixed(&data, &tmp_data_len,
153 len, &value));
154 OSMO_ASSERT(value != unchanged_ptr);
155 }
156}
157
158static void check_lv_shift_data_len(size_t data_len,
159 size_t len, const uint8_t *test_data)
160{
Pau Espin Pedrol21be8372017-06-18 00:52:56 +0200161 uint8_t buf[301] = {0};
162 *buf = 0xfe;
Harald Weltefbd02fa2016-04-25 15:19:35 +0200163
Pau Espin Pedrol21be8372017-06-18 00:52:56 +0200164 uint8_t *unchanged_ptr = buf;
Harald Weltefbd02fa2016-04-25 15:19:35 +0200165 size_t unchanged_len = 0xdead;
166 size_t tmp_data_len = data_len;
167 uint8_t *value = unchanged_ptr;
168 size_t value_len = unchanged_len;
Pau Espin Pedrol21be8372017-06-18 00:52:56 +0200169 uint8_t *data = buf + 1;
170
171 OSMO_ASSERT(data_len <= sizeof(buf) - 1);
Harald Weltefbd02fa2016-04-25 15:19:35 +0200172
173 lv_put(data, len, test_data);
174 if (data_len < len + 1) {
175 OSMO_ASSERT(-1 == osmo_shift_lv(&data, &tmp_data_len,
176 &value, &value_len));
177 OSMO_ASSERT(tmp_data_len == 0);
Pau Espin Pedrol21be8372017-06-18 00:52:56 +0200178 OSMO_ASSERT(data == buf + 1 + data_len);
Harald Weltefbd02fa2016-04-25 15:19:35 +0200179 OSMO_ASSERT(value == unchanged_ptr);
180 OSMO_ASSERT(value_len == unchanged_len);
181 } else {
182 OSMO_ASSERT(0 <= osmo_shift_lv(&data, &tmp_data_len,
183 &value, &value_len));
184 OSMO_ASSERT(value != unchanged_ptr);
185 OSMO_ASSERT(value_len != unchanged_len);
186 }
187}
188
189static void test_tlv_shift_functions()
190{
191 uint8_t test_data[1024];
192 uint8_t buf[1024];
193 uint8_t *data_end;
194 unsigned i, len;
195 uint8_t *data;
196 size_t data_len;
197 const uint8_t tag = 0x1a;
198
199 printf("Test shift functions\n");
200
201 for (i = 0; i < ARRAY_SIZE(test_data); i++)
202 test_data[i] = (uint8_t)i;
203
204 for (len = 0; len < 256; len++) {
205 const unsigned iterations = sizeof(buf) / (len + 2) / 4;
206
207 memset(buf, 0xee, sizeof(buf));
208 data_end = data = buf;
209
210 for (i = 0; i < iterations; i++) {
211 data_end = tlv_put(data_end, tag, len, test_data);
212 data_end = tv_fixed_put(data_end, tag, len, test_data);
213 /* v_fixed_put */
214 memcpy(data_end, test_data, len);
215 data_end += len;
216 data_end = lv_put(data_end, len, test_data);
217 }
218
219 data_len = data_end - data;
220 OSMO_ASSERT(data_len <= sizeof(buf));
221
222 for (i = 0; i < iterations; i++) {
223 check_tlv_parse(&data, &data_len, tag, len, test_data);
224 check_tv_fixed_match(&data, &data_len, tag, len, test_data);
225 check_v_fixed_shift(&data, &data_len, len, test_data);
226 check_lv_shift(&data, &data_len, len, test_data);
227 }
228
229 OSMO_ASSERT(data == data_end);
230
231 /* Test at end of data */
232
233 OSMO_ASSERT(-1 == osmo_match_shift_tlv(&data, &data_len, tag, NULL, NULL));
234 OSMO_ASSERT(-1 == osmo_match_shift_tv_fixed(&data, &data_len, tag, len, NULL));
235 OSMO_ASSERT((len ? -1 : 0) == osmo_shift_v_fixed(&data, &data_len, len, NULL));
236 OSMO_ASSERT(-1 == osmo_shift_lv(&data, &data_len, NULL, NULL));
237
238 /* Test invalid data_len */
239 for (data_len = 0; data_len <= len + 2 + 1; data_len += 1) {
240 check_tlv_match_data_len(data_len, tag, len, test_data);
241 check_tv_fixed_match_data_len(data_len, tag, len, test_data);
242 check_v_fixed_shift_data_len(data_len, len, test_data);
243 check_lv_shift_data_len(data_len, len, test_data);
244 }
245 }
246}
247
Stefan Sperlingc9bebbd2018-03-16 15:59:01 +0100248/* Most GSM related protocols clearly indicate that in case of duplicate
249 * IEs, only the first occurrence shall be used, while any further occurrences
250 * shall be ignored. See e.g. 3GPP TS 24.008 Section 8.6.3 */
251static void test_tlv_repeated_ie()
252{
253 uint8_t test_data[768];
254 int i, rc;
255 const uint8_t tag = 0x1a;
256 struct tlv_parsed dec;
257 struct tlv_definition def;
258
259 memset(&def, 0, sizeof(def));
260
261 /* tag:1:255, tag:1:254, tag:1:253, ..., tag:1:3, tag:1:2, tag:1:1, tag:1:0 */
262 for (i = 0; i < ARRAY_SIZE(test_data) - 1; i += 3) {
263 test_data[i] = tag;
264 test_data[i + 1] = 1;
265 test_data[i + 2] = (uint8_t)(0xff - i/2);
266 }
267
268 def.def[tag].type = TLV_TYPE_TLV;
269
270 rc = tlv_parse(&dec, &def, &test_data[1], sizeof(test_data) - 1, tag, 0);
271 OSMO_ASSERT(rc == i/3);
272 OSMO_ASSERT(dec.lv[tag].len == 1);
273 /* Value pointer should point at first value in test data array. */
274 OSMO_ASSERT(dec.lv[tag].val == &test_data[2]);
275 OSMO_ASSERT(*dec.lv[tag].val == test_data[2]);
276}
277
Harald Weltefbd02fa2016-04-25 15:19:35 +0200278int main(int argc, char **argv)
279{
Neels Hofmeyra829b452018-04-05 03:02:35 +0200280 //osmo_init_logging2(ctx, &info);
Harald Weltefbd02fa2016-04-25 15:19:35 +0200281
282 test_tlv_shift_functions();
Stefan Sperlingc9bebbd2018-03-16 15:59:01 +0100283 test_tlv_repeated_ie();
Harald Weltefbd02fa2016-04-25 15:19:35 +0200284
285 printf("Done.\n");
286 return EXIT_SUCCESS;
287}