blob: bbd1d8ab3a4a2cd3f7a08d790898a8e5ee4551fa [file] [log] [blame]
Holger Hans Peter Freytherfaf1f642011-06-23 17:53:27 -04001#include <stdio.h>
2#include <stdlib.h>
3#include <inttypes.h>
4
5#include <openbsc/gprs_llc.h>
Holger Hans Peter Freytherce1b22e2014-08-04 14:22:13 +02006#include <openbsc/gprs_utils.h>
Holger Hans Peter Freytherfaf1f642011-06-23 17:53:27 -04007
Jacob Erlbeckf3a271f2014-12-11 16:54:14 +01008#include <openbsc/gprs_gsup_messages.h>
9
Jacob Erlbeck0572ee02015-01-12 11:14:18 +010010#include <openbsc/debug.h>
11
12#include <osmocom/core/application.h>
13
Holger Hans Peter Freytherfaf1f642011-06-23 17:53:27 -040014#define ASSERT_FALSE(x) if (x) { printf("Should have returned false.\n"); abort(); }
15#define ASSERT_TRUE(x) if (!x) { printf("Should have returned true.\n"); abort(); }
16
Jacob Erlbeck0572ee02015-01-12 11:14:18 +010017#define VERBOSE_FPRINTF(...)
18
Holger Hans Peter Freytherfaf1f642011-06-23 17:53:27 -040019/**
20 * GSM 04.64 8.4.2 Receipt of unacknowledged information
21 */
22static int nu_is_retransmission(uint16_t nu, uint16_t vur)
23{
24 int ret = gprs_llc_is_retransmit(nu, vur);
25 printf("N(U) = %d, V(UR) = %d => %s\n", nu, vur,
26 ret == 1 ? "retransmit" : "new");
27 return ret;
28}
29
30static void test_8_4_2()
31{
32 printf("Testing gprs_llc_is_retransmit.\n");
33
34 ASSERT_FALSE(nu_is_retransmission(0, 0));
35 ASSERT_TRUE (nu_is_retransmission(0, 1));
36
37 /* expect 1... check for retransmissions */
38 ASSERT_TRUE (nu_is_retransmission(0, 1));
39 ASSERT_TRUE (nu_is_retransmission(511, 1));
40 ASSERT_TRUE (nu_is_retransmission(483, 1));
41 ASSERT_TRUE (nu_is_retransmission(482, 1));
42 ASSERT_FALSE(nu_is_retransmission(481, 1));
43
44 /* expect 511... check for retransmissions */
45 ASSERT_FALSE(nu_is_retransmission(0, 240)); // ahead
46 ASSERT_FALSE(nu_is_retransmission(0, 511)); // ahead
47 ASSERT_FALSE(nu_is_retransmission(1, 511)); // ahead
48 ASSERT_FALSE(nu_is_retransmission(511, 511)); // same
49 ASSERT_TRUE (nu_is_retransmission(510, 511)); // behind
50 ASSERT_TRUE (nu_is_retransmission(481, 511)); // behind
51 ASSERT_FALSE(nu_is_retransmission(479, 511)); // wrapped
52}
53
Holger Hans Peter Freytherce1b22e2014-08-04 14:22:13 +020054static void apn_round_trip(const uint8_t *input, size_t len, const char *wanted_output)
55{
56 char output[len ? len : 1];
57 uint8_t encoded[len + 50];
58 char *out_str;
59 int enc_len;
60
61 /* decode and verify we have what we want */
62 out_str = gprs_apn_to_str(output, input, len);
63 OSMO_ASSERT(out_str);
64 OSMO_ASSERT(out_str == &output[0]);
65 OSMO_ASSERT(strlen(out_str) == strlen(wanted_output));
66 OSMO_ASSERT(strcmp(out_str, wanted_output) == 0);
67
68 /* encode and verify it */
69 if (len != 0) {
70 enc_len = gprs_str_to_apn(encoded, ARRAY_SIZE(encoded), wanted_output);
71 OSMO_ASSERT(enc_len == len);
72 OSMO_ASSERT(memcmp(encoded, input, enc_len) == 0);
73 } else {
74 enc_len = gprs_str_to_apn(encoded, 0, wanted_output);
75 OSMO_ASSERT(enc_len == -1);
76 }
77}
78
79static void test_gsm_03_03_apn(void)
80{
81
82 {
83 /* test invalid writes */
84 const uint8_t ref[10] = { 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF };
85 uint8_t output[10];
86 int enc_len;
87
88 memcpy(output, ref, ARRAY_SIZE(output));
89 enc_len = gprs_str_to_apn(output, 0, "");
90 OSMO_ASSERT(enc_len == -1);
91 OSMO_ASSERT(memcmp(ref, output, ARRAY_SIZE(ref)) == 0);
92
93 memcpy(output, ref, ARRAY_SIZE(output));
94 enc_len = gprs_str_to_apn(output, 0, "foo");
95 OSMO_ASSERT(enc_len == -1);
96 OSMO_ASSERT(memcmp(ref, output, ARRAY_SIZE(ref)) == 0);
97
98 memcpy(output, ref, ARRAY_SIZE(output));
99 enc_len = gprs_str_to_apn(output, 1, "foo");
100 OSMO_ASSERT(enc_len == -1);
101 OSMO_ASSERT(memcmp(ref + 1, output + 1, ARRAY_SIZE(ref) - 1) == 0);
102
103 memcpy(output, ref, ARRAY_SIZE(output));
104 enc_len = gprs_str_to_apn(output, 2, "foo");
105 OSMO_ASSERT(enc_len == -1);
106 OSMO_ASSERT(memcmp(ref + 2, output + 2, ARRAY_SIZE(ref) - 2) == 0);
107
108 memcpy(output, ref, ARRAY_SIZE(output));
109 enc_len = gprs_str_to_apn(output, 3, "foo");
110 OSMO_ASSERT(enc_len == -1);
111 OSMO_ASSERT(memcmp(ref + 3, output + 3, ARRAY_SIZE(ref) - 3) == 0);
112 }
113
114 {
115 /* single empty label */
116 uint8_t input[] = { 0x0 };
117 const char *output = "";
118 apn_round_trip(input, ARRAY_SIZE(input), output);
119 }
120
121 {
122 /* no label */
123 uint8_t input[] = { };
124 const char *output = "";
125 apn_round_trip(input, ARRAY_SIZE(input), output);
126 }
127
128 {
129 /* single label with A */
130 uint8_t input[] = { 0x1, 65 };
131 const char *output = "A";
132 apn_round_trip(input, ARRAY_SIZE(input), output);
133 OSMO_ASSERT(gprs_apn_to_str(NULL, input, ARRAY_SIZE(input) - 1) == NULL);
134 }
135
136 {
137 uint8_t input[] = { 0x3, 65, 66, 67, 0x2, 90, 122 };
138 const char *output = "ABC.Zz";
139 char tmp[strlen(output) + 1];
140 apn_round_trip(input, ARRAY_SIZE(input), output);
141 OSMO_ASSERT(gprs_apn_to_str(tmp, input, ARRAY_SIZE(input) - 1) == NULL);
142 OSMO_ASSERT(gprs_apn_to_str(tmp, input, ARRAY_SIZE(input) - 2) == NULL);
143 OSMO_ASSERT(gprs_apn_to_str(tmp, input, ARRAY_SIZE(input) - 4) == NULL);
144 OSMO_ASSERT(gprs_apn_to_str(tmp, input, ARRAY_SIZE(input) - 5) == NULL);
145 OSMO_ASSERT(gprs_apn_to_str(tmp, input, ARRAY_SIZE(input) - 6) == NULL);
146 }
147}
148
Jacob Erlbeckdcfd4562014-12-11 11:01:46 +0100149/* TODO: Move tlv testing to libosmocore */
Jacob Erlbeck697a5342014-12-11 12:05:29 +0100150static void check_tlv_parse(uint8_t **data, size_t *data_len,
151 uint8_t exp_tag, size_t exp_len, const uint8_t *exp_val)
Jacob Erlbeckdcfd4562014-12-11 11:01:46 +0100152{
153 uint8_t *value;
154 size_t value_len;
Jacob Erlbeck697a5342014-12-11 12:05:29 +0100155 uint8_t tag;
Jacob Erlbeckdcfd4562014-12-11 11:01:46 +0100156 int rc;
Jacob Erlbeck697a5342014-12-11 12:05:29 +0100157 uint8_t *saved_data = *data;
158 size_t saved_data_len = *data_len;
Jacob Erlbeckdcfd4562014-12-11 11:01:46 +0100159
Jacob Erlbeck697a5342014-12-11 12:05:29 +0100160 rc = gprs_match_tlv(data, data_len, exp_tag ^ 1, NULL, NULL);
Jacob Erlbeckdcfd4562014-12-11 11:01:46 +0100161 OSMO_ASSERT(rc == 0);
162
Jacob Erlbeck697a5342014-12-11 12:05:29 +0100163 rc = gprs_match_tlv(data, data_len, exp_tag, &value, &value_len);
Jacob Erlbeckdcfd4562014-12-11 11:01:46 +0100164 OSMO_ASSERT(rc == (int)value_len + 2);
165 OSMO_ASSERT(value_len == exp_len);
166 OSMO_ASSERT(memcmp(value, exp_val, exp_len) == 0);
Jacob Erlbeck697a5342014-12-11 12:05:29 +0100167
168 /* restore data/data_len */
169 *data = saved_data;
170 *data_len = saved_data_len;
171
172 rc = gprs_shift_tlv(data, data_len, &tag, &value, &value_len);
173 OSMO_ASSERT(rc == (int)value_len + 2);
174 OSMO_ASSERT(tag == exp_tag);
175 OSMO_ASSERT(value_len == exp_len);
176 OSMO_ASSERT(memcmp(value, exp_val, exp_len) == 0);
Jacob Erlbeckdcfd4562014-12-11 11:01:46 +0100177}
178
179static void check_tv_fixed_match(uint8_t **data, size_t *data_len,
180 uint8_t tag, size_t len, const uint8_t *exp_val)
181{
182 uint8_t *value;
183 int rc;
184
185 rc = gprs_match_tv_fixed(data, data_len, tag ^ 1, len, NULL);
186 OSMO_ASSERT(rc == 0);
187
188 rc = gprs_match_tv_fixed(data, data_len, tag, len, &value);
189 OSMO_ASSERT(rc == (int)len + 1);
190 OSMO_ASSERT(memcmp(value, exp_val, len) == 0);
191}
192
193static void check_v_fixed_shift(uint8_t **data, size_t *data_len,
194 size_t len, const uint8_t *exp_val)
195{
196 uint8_t *value;
197 int rc;
198
199 rc = gprs_shift_v_fixed(data, data_len, len, &value);
200 OSMO_ASSERT(rc == (int)len);
201 OSMO_ASSERT(memcmp(value, exp_val, len) == 0);
202}
203
204static void check_lv_shift(uint8_t **data, size_t *data_len,
205 size_t exp_len, const uint8_t *exp_val)
206{
207 uint8_t *value;
208 size_t value_len;
209 int rc;
210
211 rc = gprs_shift_lv(data, data_len, &value, &value_len);
212 OSMO_ASSERT(rc == (int)value_len + 1);
213 OSMO_ASSERT(value_len == exp_len);
214 OSMO_ASSERT(memcmp(value, exp_val, exp_len) == 0);
215}
216
217static void check_tlv_match_data_len(size_t data_len, uint8_t tag, size_t len,
218 const uint8_t *test_data)
219{
220 uint8_t buf[300] = {0};
221
222 uint8_t *unchanged_ptr = buf - 1;
223 size_t unchanged_len = 0xdead;
224 size_t tmp_data_len = data_len;
225 uint8_t *value = unchanged_ptr;
226 size_t value_len = unchanged_len;
227 uint8_t *data = buf;
228
229 OSMO_ASSERT(data_len <= sizeof(buf));
230
231 tlv_put(data, tag, len, test_data);
232 if (data_len < len + 2) {
233 OSMO_ASSERT(-1 == gprs_match_tlv(&data, &tmp_data_len,
234 tag, &value, &value_len));
235 OSMO_ASSERT(tmp_data_len == 0);
236 OSMO_ASSERT(data == buf + data_len);
237 OSMO_ASSERT(value == unchanged_ptr);
238 OSMO_ASSERT(value_len == unchanged_len);
239 } else {
240 OSMO_ASSERT(0 <= gprs_match_tlv(&data, &tmp_data_len,
241 tag, &value, &value_len));
242 OSMO_ASSERT(value != unchanged_ptr);
243 OSMO_ASSERT(value_len != unchanged_len);
244 }
245}
246
247static void check_tv_fixed_match_data_len(size_t data_len,
248 uint8_t tag, size_t len,
249 const uint8_t *test_data)
250{
251 uint8_t buf[300] = {0};
252
253 uint8_t *unchanged_ptr = buf - 1;
254 size_t tmp_data_len = data_len;
255 uint8_t *value = unchanged_ptr;
256 uint8_t *data = buf;
257
258 OSMO_ASSERT(data_len <= sizeof(buf));
259
260 tv_fixed_put(data, tag, len, test_data);
261
262 if (data_len < len + 1) {
263 OSMO_ASSERT(-1 == gprs_match_tv_fixed(&data, &tmp_data_len,
264 tag, len, &value));
265 OSMO_ASSERT(tmp_data_len == 0);
266 OSMO_ASSERT(data == buf + data_len);
267 OSMO_ASSERT(value == unchanged_ptr);
268 } else {
269 OSMO_ASSERT(0 <= gprs_match_tv_fixed(&data, &tmp_data_len,
270 tag, len, &value));
271 OSMO_ASSERT(value != unchanged_ptr);
272 }
273}
274
275static void check_v_fixed_shift_data_len(size_t data_len,
276 size_t len, const uint8_t *test_data)
277{
278 uint8_t buf[300] = {0};
279
280 uint8_t *unchanged_ptr = buf - 1;
281 size_t tmp_data_len = data_len;
282 uint8_t *value = unchanged_ptr;
283 uint8_t *data = buf;
284
285 OSMO_ASSERT(data_len <= sizeof(buf));
286
287 memcpy(data, test_data, len);
288
289 if (data_len < len) {
290 OSMO_ASSERT(-1 == gprs_shift_v_fixed(&data, &tmp_data_len,
291 len, &value));
292 OSMO_ASSERT(tmp_data_len == 0);
293 OSMO_ASSERT(data == buf + data_len);
294 OSMO_ASSERT(value == unchanged_ptr);
295 } else {
296 OSMO_ASSERT(0 <= gprs_shift_v_fixed(&data, &tmp_data_len,
297 len, &value));
298 OSMO_ASSERT(value != unchanged_ptr);
299 }
300}
301
302static void check_lv_shift_data_len(size_t data_len,
303 size_t len, const uint8_t *test_data)
304{
305 uint8_t buf[300] = {0};
306
307 uint8_t *unchanged_ptr = buf - 1;
308 size_t unchanged_len = 0xdead;
309 size_t tmp_data_len = data_len;
310 uint8_t *value = unchanged_ptr;
311 size_t value_len = unchanged_len;
312 uint8_t *data = buf;
313
314 lv_put(data, len, test_data);
315 if (data_len < len + 1) {
316 OSMO_ASSERT(-1 == gprs_shift_lv(&data, &tmp_data_len,
317 &value, &value_len));
318 OSMO_ASSERT(tmp_data_len == 0);
319 OSMO_ASSERT(data == buf + data_len);
320 OSMO_ASSERT(value == unchanged_ptr);
321 OSMO_ASSERT(value_len == unchanged_len);
322 } else {
323 OSMO_ASSERT(0 <= gprs_shift_lv(&data, &tmp_data_len,
324 &value, &value_len));
325 OSMO_ASSERT(value != unchanged_ptr);
326 OSMO_ASSERT(value_len != unchanged_len);
327 }
328}
329
330static void test_tlv_shift_functions()
331{
332 uint8_t test_data[1024];
333 uint8_t buf[1024];
334 uint8_t *data_end;
335 unsigned i, len;
336 uint8_t *data;
337 size_t data_len;
338 const uint8_t tag = 0x1a;
339
340 printf("Test shift functions\n");
341
342 for (i = 0; i < ARRAY_SIZE(test_data); i++)
343 test_data[i] = (uint8_t)i;
344
345 for (len = 0; len < 256; len++) {
346 const unsigned iterations = sizeof(buf) / (len + 2) / 4;
347
348 memset(buf, 0xee, sizeof(buf));
349 data_end = data = buf;
350
351 for (i = 0; i < iterations; i++) {
352 data_end = tlv_put(data_end, tag, len, test_data);
353 data_end = tv_fixed_put(data_end, tag, len, test_data);
354 /* v_fixed_put */
355 memcpy(data_end, test_data, len);
356 data_end += len;
357 data_end = lv_put(data_end, len, test_data);
358 }
359
360 data_len = data_end - data;
361 OSMO_ASSERT(data_len <= sizeof(buf));
362
363 for (i = 0; i < iterations; i++) {
Jacob Erlbeck697a5342014-12-11 12:05:29 +0100364 check_tlv_parse(&data, &data_len, tag, len, test_data);
Jacob Erlbeckdcfd4562014-12-11 11:01:46 +0100365 check_tv_fixed_match(&data, &data_len, tag, len, test_data);
366 check_v_fixed_shift(&data, &data_len, len, test_data);
367 check_lv_shift(&data, &data_len, len, test_data);
368 }
369
370 OSMO_ASSERT(data == data_end);
371
372 /* Test at end of data */
373
374 OSMO_ASSERT(-1 == gprs_match_tlv(&data, &data_len, tag, NULL, NULL));
375 OSMO_ASSERT(-1 == gprs_match_tv_fixed(&data, &data_len, tag, len, NULL));
376 OSMO_ASSERT((len ? -1 : 0) == gprs_shift_v_fixed(&data, &data_len, len, NULL));
377 OSMO_ASSERT(-1 == gprs_shift_lv(&data, &data_len, NULL, NULL));
378
379 /* Test invalid data_len */
380 for (data_len = 0; data_len <= len + 2 + 1; data_len += 1) {
381 check_tlv_match_data_len(data_len, tag, len, test_data);
382 check_tv_fixed_match_data_len(data_len, tag, len, test_data);
383 check_v_fixed_shift_data_len(data_len, len, test_data);
384 check_lv_shift_data_len(data_len, len, test_data);
385 }
386 }
387}
388
Jacob Erlbeckf3a271f2014-12-11 16:54:14 +0100389/* Tests for gprs_gsup_messages.c */
390
391#define TEST_IMSI_IE 0x01, 0x08, 0x21, 0x43, 0x65, 0x87, 0x09, 0x21, 0x43, 0xf5
392#define TEST_IMSI_STR "123456789012345"
393
394static void test_gsup_messages_dec_enc(void)
395{
396 int test_idx;
397 int rc;
Jacob Erlbeck0572ee02015-01-12 11:14:18 +0100398 uint8_t buf[1024];
Jacob Erlbeckf3a271f2014-12-11 16:54:14 +0100399
400 static const uint8_t send_auth_info_req[] = {
401 0x08,
402 TEST_IMSI_IE
403 };
404
405 static const uint8_t send_auth_info_err[] = {
406 0x09,
407 TEST_IMSI_IE,
408 0x02, 0x01, 0x07 /* GPRS no allowed */
409 };
410
411 static const uint8_t send_auth_info_res[] = {
412 0x0a,
413 TEST_IMSI_IE,
414 0x03, 0x22, /* Auth tuple */
415 0x20, 0x10,
416 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
417 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
418 0x21, 0x04,
419 0x21, 0x22, 0x23, 0x24,
420 0x22, 0x08,
421 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
422 0x03, 0x22, /* Auth tuple */
423 0x20, 0x10,
424 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88,
425 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90,
426 0x21, 0x04,
427 0xa1, 0xa2, 0xa3, 0xa4,
428 0x22, 0x08,
429 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8,
430 };
431
432 static const uint8_t update_location_req[] = {
433 0x04,
434 TEST_IMSI_IE,
435 };
436
437 static const uint8_t update_location_err[] = {
438 0x05,
439 TEST_IMSI_IE,
440 0x02, 0x01, 0x07 /* GPRS no allowed */
441 };
442
443 static const uint8_t update_location_res[] = {
444 0x06,
445 TEST_IMSI_IE,
Holger Hans Peter Freytherb927f1c2015-04-22 23:09:41 -0400446 0x08, 0x07, /* MSISDN of the subscriber */
447 0x91, 0x94, 0x61, 0x46, 0x32, 0x24, 0x43,
Jacob Erlbeckf3a271f2014-12-11 16:54:14 +0100448 0x04, 0x00, /* PDP info complete */
Holger Hans Peter Freyther49c1a712015-04-23 09:13:01 -0400449 0x05, 0x15,
Jacob Erlbeckf3a271f2014-12-11 16:54:14 +0100450 0x10, 0x01, 0x01,
451 0x11, 0x02, 0xf1, 0x21, /* IPv4 */
452 0x12, 0x09, 0x04, 't', 'e', 's', 't', 0x03, 'a', 'p', 'n',
Holger Hans Peter Freyther49c1a712015-04-23 09:13:01 -0400453 0x13, 0x01, 0x02,
Jacob Erlbeckf3a271f2014-12-11 16:54:14 +0100454 0x05, 0x11,
455 0x10, 0x01, 0x02,
456 0x11, 0x02, 0xf1, 0x21, /* IPv4 */
457 0x12, 0x08, 0x03, 'f', 'o', 'o', 0x03, 'a', 'p', 'n',
458 };
459
460 static const uint8_t location_cancellation_req[] = {
461 0x1c,
462 TEST_IMSI_IE,
463 0x06, 0x01, 0x00,
464 };
465
466 static const uint8_t location_cancellation_err[] = {
467 0x1d,
468 TEST_IMSI_IE,
469 0x02, 0x01, 0x03 /* Illegal MS */
470 };
471
472 static const uint8_t location_cancellation_res[] = {
473 0x1e,
474 TEST_IMSI_IE,
475 };
476
Jacob Erlbeck69d27132015-01-15 11:50:08 +0100477 static const uint8_t purge_ms_req[] = {
478 0x0c,
479 TEST_IMSI_IE,
480 };
481
482 static const uint8_t purge_ms_err[] = {
Jacob Erlbeck85ba6552015-01-29 14:15:54 +0100483 0x0d,
Jacob Erlbeck69d27132015-01-15 11:50:08 +0100484 TEST_IMSI_IE,
485 0x02, 0x01, 0x03, /* Illegal MS */
486 };
487
488 static const uint8_t purge_ms_res[] = {
Jacob Erlbeck85ba6552015-01-29 14:15:54 +0100489 0x0e,
Jacob Erlbeck69d27132015-01-15 11:50:08 +0100490 TEST_IMSI_IE,
491 0x07, 0x00,
492 };
493
Jacob Erlbeckf3a271f2014-12-11 16:54:14 +0100494 static const struct test {
495 char *name;
496 const uint8_t *data;
497 size_t data_len;
498 } test_messages[] = {
499 {"Send Authentication Info Request",
500 send_auth_info_req, sizeof(send_auth_info_req)},
501 {"Send Authentication Info Error",
502 send_auth_info_err, sizeof(send_auth_info_err)},
503 {"Send Authentication Info Result",
504 send_auth_info_res, sizeof(send_auth_info_res)},
505 {"Update Location Request",
506 update_location_req, sizeof(update_location_req)},
507 {"Update Location Error",
508 update_location_err, sizeof(update_location_err)},
509 {"Update Location Result",
510 update_location_res, sizeof(update_location_res)},
511 {"Location Cancellation Request",
512 location_cancellation_req, sizeof(location_cancellation_req)},
513 {"Location Cancellation Error",
514 location_cancellation_err, sizeof(location_cancellation_err)},
515 {"Location Cancellation Result",
516 location_cancellation_res, sizeof(location_cancellation_res)},
Jacob Erlbeck69d27132015-01-15 11:50:08 +0100517 {"Purge MS Request",
518 purge_ms_req, sizeof(purge_ms_req)},
519 {"Purge MS Error",
520 purge_ms_err, sizeof(purge_ms_err)},
521 {"Purge MS Result",
522 purge_ms_res, sizeof(purge_ms_res)},
Jacob Erlbeckf3a271f2014-12-11 16:54:14 +0100523 };
524
525 printf("Test GSUP message decoding/encoding\n");
526
527 for (test_idx = 0; test_idx < ARRAY_SIZE(test_messages); test_idx++) {
528 const struct test *t = &test_messages[test_idx];
529 struct gprs_gsup_message gm = {0};
530 struct msgb *msg = msgb_alloc(4096, "gsup_test");
531
532 printf(" Testing %s\n", t->name);
533
534 rc = gprs_gsup_decode(t->data, t->data_len, &gm);
535 OSMO_ASSERT(rc >= 0);
536
537 gprs_gsup_encode(msg, &gm);
538
539 fprintf(stderr, " generated message: %s\n", msgb_hexdump(msg));
540 fprintf(stderr, " original message: %s\n", osmo_hexdump(t->data, t->data_len));
541 fprintf(stderr, " IMSI: %s\n", gm.imsi);
542 OSMO_ASSERT(strcmp(gm.imsi, TEST_IMSI_STR) == 0);
543 OSMO_ASSERT(msgb_length(msg) == t->data_len);
544 OSMO_ASSERT(memcmp(msgb_data(msg), t->data, t->data_len) == 0);
545
546 msgb_free(msg);
547 }
Jacob Erlbeck0572ee02015-01-12 11:14:18 +0100548
549 /* simple truncation test */
550 for (test_idx = 0; test_idx < ARRAY_SIZE(test_messages); test_idx++) {
551 int j;
552 const struct test *t = &test_messages[test_idx];
553 int ie_end = t->data_len;
554 struct gprs_gsup_message gm = {0};
555 int counter = 0;
556 int parse_err = 0;
557
558 for (j = t->data_len - 1; j >= 0; --j) {
559 rc = gprs_gsup_decode(t->data, j, &gm);
560 counter += 1;
561
562 VERBOSE_FPRINTF(stderr,
563 " partial message decoding: "
564 "orig_len = %d, trunc = %d, rc = %d, ie_end = %d\n",
565 t->data_len, j, rc, ie_end);
566 if (rc >= 0) {
567 VERBOSE_FPRINTF(stderr,
568 " remaing partial message: %s\n",
569 osmo_hexdump(t->data + j, ie_end - j));
570
571 OSMO_ASSERT(j <= ie_end - 2);
572 OSMO_ASSERT(t->data[j+0] <= GPRS_GSUP_KC_IE);
573 OSMO_ASSERT(t->data[j+1] <= ie_end - j - 2);
574
575 ie_end = j;
576 } else {
577 parse_err += 1;
578 }
579 }
580
581 fprintf(stderr,
582 " message %d: tested %d truncations, %d parse failures\n",
583 test_idx, counter, parse_err);
584 }
585
586 /* message modification test (relies on ASAN or valgrind being used) */
587 for (test_idx = 0; test_idx < ARRAY_SIZE(test_messages); test_idx++) {
588 int j;
589 const struct test *t = &test_messages[test_idx];
590 struct gprs_gsup_message gm = {0};
591 uint8_t val;
592 int counter = 0;
593 int parse_err = 0;
594
595 OSMO_ASSERT(sizeof(buf) >= t->data_len);
596
597 for (j = t->data_len - 1; j >= 0; --j) {
598 memcpy(buf, t->data, t->data_len);
599 val = 0;
600 do {
601 VERBOSE_FPRINTF(stderr,
602 "t = %d, len = %d, val = %d\n",
603 test_idx, j, val);
604 buf[j] = val;
605 rc = gprs_gsup_decode(buf, t->data_len, &gm);
606 counter += 1;
607 if (rc < 0)
608 parse_err += 1;
609
610 val += 1;
611 } while (val != (uint8_t)256);
612 }
613
614 fprintf(stderr,
615 " message %d: tested %d modifications, %d parse failures\n",
616 test_idx, counter, parse_err);
617 }
Jacob Erlbeckf3a271f2014-12-11 16:54:14 +0100618}
619
Jacob Erlbeck79af67d2015-01-19 08:27:34 +0100620static void test_gprs_timer_enc_dec(void)
621{
622 int i, u, secs, tmr;
623 const int upper_secs_test_limit = 12000;
624 int dec_secs, last_dec_secs = -1;
625
626 printf("Test GPRS timer decoding/encoding\n");
627
628 /* Check gprs_tmr_to_secs with all 256 encoded values */
629 for (u = 0; u <= GPRS_TMR_DEACTIVATED; u += 32) {
630 fprintf(stderr, "Testing decoding with timer value unit %u\n",
631 u / 32);
632 for (i = 0; i < 32; i++) {
633 switch (u) {
634 case GPRS_TMR_2SECONDS:
635 OSMO_ASSERT(gprs_tmr_to_secs(u + i) == 2 * i);
636 break;
637
638 default:
639 case GPRS_TMR_MINUTE:
640 OSMO_ASSERT(gprs_tmr_to_secs(u + i) == 60 * i);
641 break;
642
643 case GPRS_TMR_6MINUTE:
644 OSMO_ASSERT(gprs_tmr_to_secs(u + i) == 360 * i);
645 break;
646
647 case GPRS_TMR_DEACTIVATED:
648 OSMO_ASSERT(gprs_tmr_to_secs(u + i) == -1);
649 break;
650 }
651
652 OSMO_ASSERT(gprs_tmr_to_secs(u + i) < upper_secs_test_limit);
653 }
654 }
655
656 /* Check gprs_secs_to_tmr_floor for secs that can exactly be
657 * represented as GPRS timer values */
658 for (i = 0; i < GPRS_TMR_DEACTIVATED; i++) {
659 int j;
660 secs = gprs_tmr_to_secs(i);
661 tmr = gprs_secs_to_tmr_floor(secs);
662 OSMO_ASSERT(secs == gprs_tmr_to_secs(tmr));
663
664 /* Check that the highest resolution is used */
665 for (j = 0; j < tmr; j++)
666 OSMO_ASSERT(secs != gprs_tmr_to_secs(j));
667 }
668 OSMO_ASSERT(GPRS_TMR_DEACTIVATED == gprs_secs_to_tmr_floor(-1));
669
670 /* Check properties of gprs_secs_to_tmr_floor */
671 for (secs = 0; secs <= upper_secs_test_limit; secs++) {
672 int tmr = gprs_secs_to_tmr_floor(secs);
673 int delta_secs = gprs_tmr_to_secs((tmr & ~0x1f) | 1);
674 dec_secs = gprs_tmr_to_secs(tmr);
675
676 /* Check floor */
677 OSMO_ASSERT(dec_secs <= secs);
678 /* Check monotonicity */
679 OSMO_ASSERT(dec_secs >= last_dec_secs);
680 /* Check max distance (<= resolution) */
681 OSMO_ASSERT(dec_secs - last_dec_secs <= delta_secs);
682
683 last_dec_secs = dec_secs;
684 }
685}
686
Jacob Erlbeck0572ee02015-01-12 11:14:18 +0100687const struct log_info_cat default_categories[] = {
688 [DGPRS] = {
689 .name = "DGPRS",
690 .description = "GPRS Packet Service",
691 .enabled = 0, .loglevel = LOGL_DEBUG,
692 },
693};
694
695static struct log_info info = {
696 .cat = default_categories,
697 .num_cat = ARRAY_SIZE(default_categories),
698};
699
Holger Hans Peter Freytherfaf1f642011-06-23 17:53:27 -0400700int main(int argc, char **argv)
701{
Jacob Erlbeck0572ee02015-01-12 11:14:18 +0100702 osmo_init_logging(&info);
703
Holger Hans Peter Freytherfaf1f642011-06-23 17:53:27 -0400704 test_8_4_2();
Holger Hans Peter Freytherce1b22e2014-08-04 14:22:13 +0200705 test_gsm_03_03_apn();
Jacob Erlbeckdcfd4562014-12-11 11:01:46 +0100706 test_tlv_shift_functions();
Jacob Erlbeckf3a271f2014-12-11 16:54:14 +0100707 test_gsup_messages_dec_enc();
Jacob Erlbeck79af67d2015-01-19 08:27:34 +0100708 test_gprs_timer_enc_dec();
Holger Hans Peter Freytherfaf1f642011-06-23 17:53:27 -0400709
710 printf("Done.\n");
711 return EXIT_SUCCESS;
712}