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