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