blob: e445ae7c836e5c26c9cef7cfb3cfae2d80f69dbb [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,
446 0x04, 0x00, /* PDP info complete */
447 0x05, 0x12,
448 0x10, 0x01, 0x01,
449 0x11, 0x02, 0xf1, 0x21, /* IPv4 */
450 0x12, 0x09, 0x04, 't', 'e', 's', 't', 0x03, 'a', 'p', 'n',
451 0x05, 0x11,
452 0x10, 0x01, 0x02,
453 0x11, 0x02, 0xf1, 0x21, /* IPv4 */
454 0x12, 0x08, 0x03, 'f', 'o', 'o', 0x03, 'a', 'p', 'n',
455 };
456
457 static const uint8_t location_cancellation_req[] = {
458 0x1c,
459 TEST_IMSI_IE,
460 0x06, 0x01, 0x00,
461 };
462
463 static const uint8_t location_cancellation_err[] = {
464 0x1d,
465 TEST_IMSI_IE,
466 0x02, 0x01, 0x03 /* Illegal MS */
467 };
468
469 static const uint8_t location_cancellation_res[] = {
470 0x1e,
471 TEST_IMSI_IE,
472 };
473
Jacob Erlbeck69d27132015-01-15 11:50:08 +0100474 static const uint8_t purge_ms_req[] = {
475 0x0c,
476 TEST_IMSI_IE,
477 };
478
479 static const uint8_t purge_ms_err[] = {
480 0x0c,
481 TEST_IMSI_IE,
482 0x02, 0x01, 0x03, /* Illegal MS */
483 };
484
485 static const uint8_t purge_ms_res[] = {
486 0x0c,
487 TEST_IMSI_IE,
488 0x07, 0x00,
489 };
490
Jacob Erlbeckf3a271f2014-12-11 16:54:14 +0100491 static const struct test {
492 char *name;
493 const uint8_t *data;
494 size_t data_len;
495 } test_messages[] = {
496 {"Send Authentication Info Request",
497 send_auth_info_req, sizeof(send_auth_info_req)},
498 {"Send Authentication Info Error",
499 send_auth_info_err, sizeof(send_auth_info_err)},
500 {"Send Authentication Info Result",
501 send_auth_info_res, sizeof(send_auth_info_res)},
502 {"Update Location Request",
503 update_location_req, sizeof(update_location_req)},
504 {"Update Location Error",
505 update_location_err, sizeof(update_location_err)},
506 {"Update Location Result",
507 update_location_res, sizeof(update_location_res)},
508 {"Location Cancellation Request",
509 location_cancellation_req, sizeof(location_cancellation_req)},
510 {"Location Cancellation Error",
511 location_cancellation_err, sizeof(location_cancellation_err)},
512 {"Location Cancellation Result",
513 location_cancellation_res, sizeof(location_cancellation_res)},
Jacob Erlbeck69d27132015-01-15 11:50:08 +0100514 {"Purge MS Request",
515 purge_ms_req, sizeof(purge_ms_req)},
516 {"Purge MS Error",
517 purge_ms_err, sizeof(purge_ms_err)},
518 {"Purge MS Result",
519 purge_ms_res, sizeof(purge_ms_res)},
Jacob Erlbeckf3a271f2014-12-11 16:54:14 +0100520 };
521
522 printf("Test GSUP message decoding/encoding\n");
523
524 for (test_idx = 0; test_idx < ARRAY_SIZE(test_messages); test_idx++) {
525 const struct test *t = &test_messages[test_idx];
526 struct gprs_gsup_message gm = {0};
527 struct msgb *msg = msgb_alloc(4096, "gsup_test");
528
529 printf(" Testing %s\n", t->name);
530
531 rc = gprs_gsup_decode(t->data, t->data_len, &gm);
532 OSMO_ASSERT(rc >= 0);
533
534 gprs_gsup_encode(msg, &gm);
535
536 fprintf(stderr, " generated message: %s\n", msgb_hexdump(msg));
537 fprintf(stderr, " original message: %s\n", osmo_hexdump(t->data, t->data_len));
538 fprintf(stderr, " IMSI: %s\n", gm.imsi);
539 OSMO_ASSERT(strcmp(gm.imsi, TEST_IMSI_STR) == 0);
540 OSMO_ASSERT(msgb_length(msg) == t->data_len);
541 OSMO_ASSERT(memcmp(msgb_data(msg), t->data, t->data_len) == 0);
542
543 msgb_free(msg);
544 }
Jacob Erlbeck0572ee02015-01-12 11:14:18 +0100545
546 /* simple truncation test */
547 for (test_idx = 0; test_idx < ARRAY_SIZE(test_messages); test_idx++) {
548 int j;
549 const struct test *t = &test_messages[test_idx];
550 int ie_end = t->data_len;
551 struct gprs_gsup_message gm = {0};
552 int counter = 0;
553 int parse_err = 0;
554
555 for (j = t->data_len - 1; j >= 0; --j) {
556 rc = gprs_gsup_decode(t->data, j, &gm);
557 counter += 1;
558
559 VERBOSE_FPRINTF(stderr,
560 " partial message decoding: "
561 "orig_len = %d, trunc = %d, rc = %d, ie_end = %d\n",
562 t->data_len, j, rc, ie_end);
563 if (rc >= 0) {
564 VERBOSE_FPRINTF(stderr,
565 " remaing partial message: %s\n",
566 osmo_hexdump(t->data + j, ie_end - j));
567
568 OSMO_ASSERT(j <= ie_end - 2);
569 OSMO_ASSERT(t->data[j+0] <= GPRS_GSUP_KC_IE);
570 OSMO_ASSERT(t->data[j+1] <= ie_end - j - 2);
571
572 ie_end = j;
573 } else {
574 parse_err += 1;
575 }
576 }
577
578 fprintf(stderr,
579 " message %d: tested %d truncations, %d parse failures\n",
580 test_idx, counter, parse_err);
581 }
582
583 /* message modification test (relies on ASAN or valgrind being used) */
584 for (test_idx = 0; test_idx < ARRAY_SIZE(test_messages); test_idx++) {
585 int j;
586 const struct test *t = &test_messages[test_idx];
587 struct gprs_gsup_message gm = {0};
588 uint8_t val;
589 int counter = 0;
590 int parse_err = 0;
591
592 OSMO_ASSERT(sizeof(buf) >= t->data_len);
593
594 for (j = t->data_len - 1; j >= 0; --j) {
595 memcpy(buf, t->data, t->data_len);
596 val = 0;
597 do {
598 VERBOSE_FPRINTF(stderr,
599 "t = %d, len = %d, val = %d\n",
600 test_idx, j, val);
601 buf[j] = val;
602 rc = gprs_gsup_decode(buf, t->data_len, &gm);
603 counter += 1;
604 if (rc < 0)
605 parse_err += 1;
606
607 val += 1;
608 } while (val != (uint8_t)256);
609 }
610
611 fprintf(stderr,
612 " message %d: tested %d modifications, %d parse failures\n",
613 test_idx, counter, parse_err);
614 }
Jacob Erlbeckf3a271f2014-12-11 16:54:14 +0100615}
616
Jacob Erlbeck79af67d2015-01-19 08:27:34 +0100617static void test_gprs_timer_enc_dec(void)
618{
619 int i, u, secs, tmr;
620 const int upper_secs_test_limit = 12000;
621 int dec_secs, last_dec_secs = -1;
622
623 printf("Test GPRS timer decoding/encoding\n");
624
625 /* Check gprs_tmr_to_secs with all 256 encoded values */
626 for (u = 0; u <= GPRS_TMR_DEACTIVATED; u += 32) {
627 fprintf(stderr, "Testing decoding with timer value unit %u\n",
628 u / 32);
629 for (i = 0; i < 32; i++) {
630 switch (u) {
631 case GPRS_TMR_2SECONDS:
632 OSMO_ASSERT(gprs_tmr_to_secs(u + i) == 2 * i);
633 break;
634
635 default:
636 case GPRS_TMR_MINUTE:
637 OSMO_ASSERT(gprs_tmr_to_secs(u + i) == 60 * i);
638 break;
639
640 case GPRS_TMR_6MINUTE:
641 OSMO_ASSERT(gprs_tmr_to_secs(u + i) == 360 * i);
642 break;
643
644 case GPRS_TMR_DEACTIVATED:
645 OSMO_ASSERT(gprs_tmr_to_secs(u + i) == -1);
646 break;
647 }
648
649 OSMO_ASSERT(gprs_tmr_to_secs(u + i) < upper_secs_test_limit);
650 }
651 }
652
653 /* Check gprs_secs_to_tmr_floor for secs that can exactly be
654 * represented as GPRS timer values */
655 for (i = 0; i < GPRS_TMR_DEACTIVATED; i++) {
656 int j;
657 secs = gprs_tmr_to_secs(i);
658 tmr = gprs_secs_to_tmr_floor(secs);
659 OSMO_ASSERT(secs == gprs_tmr_to_secs(tmr));
660
661 /* Check that the highest resolution is used */
662 for (j = 0; j < tmr; j++)
663 OSMO_ASSERT(secs != gprs_tmr_to_secs(j));
664 }
665 OSMO_ASSERT(GPRS_TMR_DEACTIVATED == gprs_secs_to_tmr_floor(-1));
666
667 /* Check properties of gprs_secs_to_tmr_floor */
668 for (secs = 0; secs <= upper_secs_test_limit; secs++) {
669 int tmr = gprs_secs_to_tmr_floor(secs);
670 int delta_secs = gprs_tmr_to_secs((tmr & ~0x1f) | 1);
671 dec_secs = gprs_tmr_to_secs(tmr);
672
673 /* Check floor */
674 OSMO_ASSERT(dec_secs <= secs);
675 /* Check monotonicity */
676 OSMO_ASSERT(dec_secs >= last_dec_secs);
677 /* Check max distance (<= resolution) */
678 OSMO_ASSERT(dec_secs - last_dec_secs <= delta_secs);
679
680 last_dec_secs = dec_secs;
681 }
682}
683
Jacob Erlbeck0572ee02015-01-12 11:14:18 +0100684const struct log_info_cat default_categories[] = {
685 [DGPRS] = {
686 .name = "DGPRS",
687 .description = "GPRS Packet Service",
688 .enabled = 0, .loglevel = LOGL_DEBUG,
689 },
690};
691
692static struct log_info info = {
693 .cat = default_categories,
694 .num_cat = ARRAY_SIZE(default_categories),
695};
696
Holger Hans Peter Freytherfaf1f642011-06-23 17:53:27 -0400697int main(int argc, char **argv)
698{
Jacob Erlbeck0572ee02015-01-12 11:14:18 +0100699 osmo_init_logging(&info);
700
Holger Hans Peter Freytherfaf1f642011-06-23 17:53:27 -0400701 test_8_4_2();
Holger Hans Peter Freytherce1b22e2014-08-04 14:22:13 +0200702 test_gsm_03_03_apn();
Jacob Erlbeckdcfd4562014-12-11 11:01:46 +0100703 test_tlv_shift_functions();
Jacob Erlbeckf3a271f2014-12-11 16:54:14 +0100704 test_gsup_messages_dec_enc();
Jacob Erlbeck79af67d2015-01-19 08:27:34 +0100705 test_gprs_timer_enc_dec();
Holger Hans Peter Freytherfaf1f642011-06-23 17:53:27 -0400706
707 printf("Done.\n");
708 return EXIT_SUCCESS;
709}