blob: b5f80614f6fdf01f519f4a8e958c8f9a906b3915 [file] [log] [blame]
Harald Weltec8a0b932012-08-24 21:27:26 +02001/*
2 * (C) 2012 by Harald Welte <laforge@gnumonks.org>
3 * All Rights Reserved
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 */
20
21#include <string.h>
22#include <stdio.h>
Holger Hans Peter Freythercd252e32013-07-03 09:56:53 +020023#include <stdlib.h>
Harald Weltec8a0b932012-08-24 21:27:26 +020024
25#include <osmocom/gsm/protocol/gsm_04_08.h>
26#include <osmocom/gsm/gsm48_ie.h>
Holger Hans Peter Freythercd252e32013-07-03 09:56:53 +020027#include <osmocom/gsm/gsm48.h>
Stefan Sperlingfdf8b7b2018-07-27 12:19:15 +020028#include <osmocom/gsm/gsm48_arfcn_range_encode.h>
Harald Weltec8a0b932012-08-24 21:27:26 +020029#include <osmocom/gsm/mncc.h>
Holger Hans Peter Freythercd252e32013-07-03 09:56:53 +020030#include <osmocom/core/backtrace.h>
Harald Weltec8a0b932012-08-24 21:27:26 +020031#include <osmocom/core/utils.h>
32#include <osmocom/core/msgb.h>
33
34
35static const uint8_t csd_9600_v110_lv[] = { 0x07, 0xa1, 0xb8, 0x89, 0x21, 0x15, 0x63, 0x80 };
36
37static const struct gsm_mncc_bearer_cap bcap_csd_9600_v110 = {
38 .transfer = GSM48_BCAP_ITCAP_UNR_DIG_INF,
39 .mode = GSM48_BCAP_TMOD_CIRCUIT,
40 .coding = GSM48_BCAP_CODING_GSM_STD,
41 .radio = GSM48_BCAP_RRQ_FR_ONLY,
42 .speech_ver[0]= -1,
43 .data = {
44 .rate_adaption = GSM48_BCAP_RA_V110_X30,
45 .sig_access = GSM48_BCAP_SA_I440_I450,
46 .async = 1,
47 .nr_stop_bits = 1,
48 .nr_data_bits = 8,
49 .user_rate = GSM48_BCAP_UR_9600,
50 .parity = GSM48_BCAP_PAR_NONE,
51 .interm_rate = GSM48_BCAP_IR_16k,
52 .transp = GSM48_BCAP_TR_TRANSP,
53 .modem_type = GSM48_BCAP_MT_NONE,
54 },
55};
56
57static const uint8_t speech_all_lv[] = { 0x06, 0x60, 0x04, 0x02, 0x00, 0x05, 0x81 };
58
59static const struct gsm_mncc_bearer_cap bcap_speech_all = {
60 .transfer = GSM48_BCAP_ITCAP_SPEECH,
61 .mode = GSM48_BCAP_TMOD_CIRCUIT,
62 .coding = GSM48_BCAP_CODING_GSM_STD,
63 .radio = GSM48_BCAP_RRQ_DUAL_FR,
64 .speech_ver = {
65 4, 2, 0, 5, 1, -1,
66 },
67};
68
69
70struct bcap_test {
71 const uint8_t *lv;
72 const struct gsm_mncc_bearer_cap *bc;
73 const char *name;
74};
75
76static const struct bcap_test bcap_tests[] = {
77 { csd_9600_v110_lv, &bcap_csd_9600_v110, "CSD 9600/V.110/transparent" },
78 { speech_all_lv, &bcap_speech_all, "Speech, all codecs" },
79};
80
81static int test_bearer_cap()
82{
83 struct gsm_mncc_bearer_cap bc;
84 int i, rc;
85
86 for (i = 0; i < ARRAY_SIZE(bcap_tests); i++) {
87 struct msgb *msg = msgb_alloc(100, "test");
88 int lv_len;
89
90 memset(&bc, 0, sizeof(bc));
91
92 /* test decoding */
93 rc = gsm48_decode_bearer_cap(&bc, bcap_tests[i].lv);
94 if (rc < 0) {
95 fprintf(stderr, "Error decoding %s\n",
96 bcap_tests[i].name);
97 return rc;
98 }
99 if (memcmp(&bc, bcap_tests[i].bc, sizeof(bc))) {
100 fprintf(stderr, "Incorrect decoded result of %s:\n",
101 bcap_tests[i].name);
102 fprintf(stderr, " should: %s\n",
103 osmo_hexdump((uint8_t *) bcap_tests[i].bc, sizeof(bc)));
104 fprintf(stderr, " is: %s\n",
105 osmo_hexdump((uint8_t *) &bc, sizeof(bc)));
106 return -1;
107 }
108
109 /* also test re-encode? */
110 rc = gsm48_encode_bearer_cap(msg, 1, &bc);
111 if (rc < 0) {
112 fprintf(stderr, "Error encoding %s\n",
113 bcap_tests[i].name);
114 return rc;
115 }
116 lv_len = bcap_tests[i].lv[0]+1;
117 if (memcmp(msg->data, bcap_tests[i].lv, lv_len)) {
118 fprintf(stderr, "Incorrect encoded result of %s:\n",
119 bcap_tests[i].name);
120 fprintf(stderr, " should: %s\n",
121 osmo_hexdump(bcap_tests[i].lv, lv_len));
122 fprintf(stderr, " is: %s\n",
123 osmo_hexdump(msg->data, msg->len));
124 return -1;
125 }
126
127 printf("Test `%s' passed\n", bcap_tests[i].name);
128 msgb_free(msg);
129 }
130
131 return 0;
132}
133
Max99377c22017-08-30 19:17:50 +0200134static inline void dump_ra(const struct gprs_ra_id *raid)
135{
Neels Hofmeyrdbb25132018-02-20 15:12:23 +0100136 printf("%s%s\n", osmo_rai_name(raid), raid->mnc_3_digits ? " (3-digit MNC)" : "");
Max99377c22017-08-30 19:17:50 +0200137}
138
139static inline void check_ra(const struct gprs_ra_id *raid)
140{
Maxf1ad60e2018-01-05 14:19:33 +0100141 struct gsm48_ra_id ra;
Max99377c22017-08-30 19:17:50 +0200142 struct gprs_ra_id raid0 = {
143 .mnc = 0,
144 .mcc = 0,
145 .lac = 0,
146 .rac = 0,
147 };
148
Maxf1ad60e2018-01-05 14:19:33 +0100149 gsm48_encode_ra(&ra, raid);
150 printf("Constructed RA:\n");
Max99377c22017-08-30 19:17:50 +0200151
Maxf1ad60e2018-01-05 14:19:33 +0100152 gsm48_parse_ra(&raid0, (const uint8_t *)&ra);
Max99377c22017-08-30 19:17:50 +0200153 dump_ra(raid);
Neels Hofmeyrc38b32d2018-02-20 15:13:18 +0100154 printf("MCC+MNC in BCD: %s\n", osmo_hexdump(ra.digits, sizeof(ra.digits)));
Max99377c22017-08-30 19:17:50 +0200155 dump_ra(&raid0);
156 printf("RA test...");
Neels Hofmeyrdbb25132018-02-20 15:12:23 +0100157 if (raid->mnc != raid0.mnc || raid->mcc != raid0.mcc || raid->lac != raid0.lac || raid->rac != raid0.rac
158 || (raid->mnc_3_digits || raid->mnc > 99) != raid0.mnc_3_digits)
Max99377c22017-08-30 19:17:50 +0200159 printf("FAIL\n");
160 else
161 printf("passed\n");
162}
163
Neels Hofmeyrd5a577b2018-02-20 21:48:07 +0100164static inline void check_lai(const struct gprs_ra_id *raid)
165{
166 int rc;
167 struct gsm48_loc_area_id lai = {};
168 struct gprs_ra_id decoded = {};
169 struct gprs_ra_id _laid = *raid;
170 struct gprs_ra_id *laid = &_laid;
171 laid->rac = 0;
172
173 printf("- gsm48_generate_lai() from "); dump_ra(laid);
174
175 gsm48_generate_lai(&lai, laid->mcc, laid->mnc, laid->lac);
176 printf(" Encoded %s\n", osmo_hexdump((unsigned char*)&lai, sizeof(lai)));
177 rc = gsm48_decode_lai(&lai, &decoded.mcc, &decoded.mnc, &decoded.lac);
178 if (rc) {
179 printf(" gsm48_decode_lai() returned %d --> FAIL\n", rc);
180 return;
181 }
182 printf(" gsm48_decode_lai() gives "); dump_ra(&decoded);
183 if (decoded.mcc == laid->mcc
184 && decoded.mnc == laid->mnc
185 && decoded.lac == laid->lac)
186 printf(" passed\n");
187 else
188 printf(" FAIL\n");
189}
190
Neels Hofmeyr4566f4e2018-02-20 22:19:56 +0100191static inline void dump_lai(const struct osmo_location_area_id *lai)
192{
193 printf("%s%s\n", osmo_lai_name(lai), lai->plmn.mnc_3_digits ? " (3-digit MNC)" : "");
194}
195
196static inline void check_lai2(const struct gprs_ra_id *raid)
197{
198 struct gsm48_loc_area_id lai = {};
199 struct osmo_location_area_id decoded = {};
200 struct osmo_location_area_id laid = {
201 .plmn = {
202 .mcc = raid->mcc,
203 .mnc = raid->mnc,
204 .mnc_3_digits = raid->mnc_3_digits,
205 },
206 .lac = raid->lac,
207 };
208
209 printf("- gsm48_generate_lai2() from "); dump_lai(&laid);
210
211 gsm48_generate_lai2(&lai, &laid);
212 printf(" Encoded %s\n", osmo_hexdump((unsigned char*)&lai, sizeof(lai)));
213 gsm48_decode_lai2(&lai, &decoded);
214 printf(" gsm48_decode_lai2() gives "); dump_lai(&decoded);
215 if (decoded.plmn.mcc == laid.plmn.mcc
216 && decoded.plmn.mnc == laid.plmn.mnc
217 && decoded.lac == laid.lac
218 && decoded.plmn.mnc_3_digits == (laid.plmn.mnc_3_digits || laid.plmn.mnc > 99))
219 printf(" passed\n");
220 else
221 printf(" FAIL\n");
222}
223
Neels Hofmeyr22da1452018-02-20 15:11:25 +0100224static struct gprs_ra_id test_ra_cap_items[] = {
225 {
Max99377c22017-08-30 19:17:50 +0200226 .mcc = 77,
Neels Hofmeyr0bf93a62018-02-20 22:06:56 +0100227 .mnc = 121,
Max99377c22017-08-30 19:17:50 +0200228 .lac = 666,
229 .rac = 5,
Neels Hofmeyr22da1452018-02-20 15:11:25 +0100230 },
231 {
Max99377c22017-08-30 19:17:50 +0200232 .mcc = 84,
Neels Hofmeyr0bf93a62018-02-20 22:06:56 +0100233 .mnc = 98,
Max99377c22017-08-30 19:17:50 +0200234 .lac = 11,
235 .rac = 89,
Neels Hofmeyr22da1452018-02-20 15:11:25 +0100236 },
Neels Hofmeyrb9fd7eb2018-02-20 15:14:03 +0100237 {
238 .mcc = 0,
239 .mnc = 0,
240 .lac = 0,
241 .rac = 0,
Neels Hofmeyr6c7b3e22018-02-20 22:20:42 +0100242 .mnc_3_digits = false,
243 /* expecting 000-00, BCD = 00 f0 00 */
244 },
245 {
246 .mcc = 0,
247 .mnc = 0,
248 .lac = 0,
249 .rac = 0,
250 .mnc_3_digits = true,
251 /* expecting 000-000, BCD = 00 00 00 */
Neels Hofmeyrb9fd7eb2018-02-20 15:14:03 +0100252 },
253 {
254 .mcc = 999,
255 .mnc = 999,
256 .lac = 65535,
257 .rac = 255,
258 },
Neels Hofmeyr6c7b3e22018-02-20 22:20:42 +0100259 {
260 .mcc = 1,
261 .mnc = 2,
262 .lac = 23,
263 .rac = 42,
264 .mnc_3_digits = false,
265 /* expecting 001-02, BCD = 00 f1 20 */
266 },
267 {
268 .mcc = 1,
269 .mnc = 2,
270 .lac = 23,
271 .rac = 42,
272 .mnc_3_digits = true,
273 /* expecting 001-002, BCD = 00 21 00 */
274 },
275 {
276 .mcc = 12,
277 .mnc = 34,
278 .lac = 56,
279 .rac = 78,
280 .mnc_3_digits = false,
281 /* expecting 012-34, BCD = 10 f2 43 */
282 },
283 {
284 .mcc = 12,
285 .mnc = 34,
286 .lac = 23,
287 .rac = 42,
288 .mnc_3_digits = true,
289 /* expecting 012-034, BCD = 10 42 30 */
290 },
291 {
292 .mcc = 123,
293 .mnc = 456,
294 .lac = 23,
295 .rac = 42,
296 .mnc_3_digits = false,
297 /* expecting 123-456, BCD = 21 63 54 (false flag has no effect) */
298 },
299 {
300 .mcc = 123,
301 .mnc = 456,
302 .lac = 23,
303 .rac = 42,
304 .mnc_3_digits = true,
305 /* expecting 123-456, BCD = 21 63 54 (same) */
306 },
Neels Hofmeyr22da1452018-02-20 15:11:25 +0100307};
Max99377c22017-08-30 19:17:50 +0200308
Neels Hofmeyr22da1452018-02-20 15:11:25 +0100309static void test_ra_cap(void)
310{
311 int i;
312
313 for (i = 0; i < ARRAY_SIZE(test_ra_cap_items); i++)
314 check_ra(&test_ra_cap_items[i]);
Max99377c22017-08-30 19:17:50 +0200315}
316
Neels Hofmeyrd5a577b2018-02-20 21:48:07 +0100317static void test_lai_encode_decode(void)
318{
319 int i;
320
321 for (i = 0; i < ARRAY_SIZE(test_ra_cap_items); i++) {
322 check_lai(&test_ra_cap_items[i]);
Neels Hofmeyr4566f4e2018-02-20 22:19:56 +0100323 check_lai2(&test_ra_cap_items[i]);
Neels Hofmeyrd5a577b2018-02-20 21:48:07 +0100324 }
325}
326
Holger Hans Peter Freythercd252e32013-07-03 09:56:53 +0200327static void test_mid_from_tmsi(void)
328{
329 static const uint8_t res[] = { 0x17, 0x05, 0xf4, 0xaa, 0xbb, 0xcc, 0xdd };
330
331
332 uint32_t tmsi = 0xAABBCCDD;
333 uint8_t buf[3 + sizeof(uint32_t)];
334
335 printf("Simple TMSI encoding test....");
336
337 memset(&buf, 0xFE, sizeof(buf));
338 gsm48_generate_mid_from_tmsi(buf, tmsi);
339
340 OSMO_ASSERT(memcmp(buf, res, sizeof(res)) == 0);
341 printf("passed\n");
342}
343
Maxd55d7d42018-02-15 11:27:18 +0100344static void test_mid_from_imsi(void)
345{
346 char *imsi = "901700000004620";
347 uint8_t buf[10], len;
348
349 printf("Simple IMSI encoding test....");
350
351 len = gsm48_generate_mid_from_imsi(buf, imsi);
352
353 printf("passed: [%u] %s\n", len, osmo_hexdump(buf, len));
354}
355
Neels Hofmeyr49686282018-12-05 21:32:21 +0100356struct test_mid_encode_decode_test {
357 uint8_t mi_type;
358 const char *mi_str;
Neels Hofmeyr02fd83d2019-01-05 00:38:54 +0100359 const char *mi_name;
Neels Hofmeyr49686282018-12-05 21:32:21 +0100360 size_t str_size;
361 const char *expect_mi_tlv_hex;
362 const char *expect_str;
363 int expect_rc;
364};
365
366static const struct test_mid_encode_decode_test test_mid_encode_decode_tests[] = {
367 {
368 .mi_type = GSM_MI_TYPE_IMSI,
369 .mi_str = "123456789012345",
Neels Hofmeyr02fd83d2019-01-05 00:38:54 +0100370 .mi_name = "IMSI-123456789012345",
Neels Hofmeyr49686282018-12-05 21:32:21 +0100371 .expect_mi_tlv_hex = "17081932547698103254",
372 },
373 {
374 .mi_type = GSM_MI_TYPE_IMSI,
375 .mi_str = "12345678901234",
Neels Hofmeyr02fd83d2019-01-05 00:38:54 +0100376 .mi_name = "IMSI-12345678901234",
Neels Hofmeyr49686282018-12-05 21:32:21 +0100377 .expect_mi_tlv_hex = "170811325476981032f4",
378 },
379 {
380 .mi_type = GSM_MI_TYPE_IMSI,
381 .mi_str = "423423",
Neels Hofmeyr02fd83d2019-01-05 00:38:54 +0100382 .mi_name = "IMSI-423423",
Neels Hofmeyr49686282018-12-05 21:32:21 +0100383 .expect_mi_tlv_hex = "1704413224f3",
384 },
385 {
386 .mi_type = GSM_MI_TYPE_IMSI | GSM_MI_ODD,
387 .mi_str = "423423",
Neels Hofmeyr02fd83d2019-01-05 00:38:54 +0100388 .mi_name = "IMSI-423423",
Neels Hofmeyr23187fa2018-12-05 23:24:50 +0100389 .expect_mi_tlv_hex = "1704413224f3",
Neels Hofmeyr49686282018-12-05 21:32:21 +0100390 },
391 {
392 .mi_type = GSM_MI_TYPE_IMSI,
393 .mi_str = "4234235",
Neels Hofmeyr02fd83d2019-01-05 00:38:54 +0100394 .mi_name = "IMSI-4234235",
Neels Hofmeyr49686282018-12-05 21:32:21 +0100395 .expect_mi_tlv_hex = "170449322453",
396 },
397 {
398 .mi_type = GSM_MI_TYPE_IMSI,
399 .mi_str = "4234235",
Neels Hofmeyr02fd83d2019-01-05 00:38:54 +0100400 .mi_name = "IMSI-4234235",
Neels Hofmeyr49686282018-12-05 21:32:21 +0100401 .expect_mi_tlv_hex = "170449322453",
402 .str_size = 4,
403 .expect_str = "423",
Neels Hofmeyr49686282018-12-05 21:32:21 +0100404 },
405 {
406 .mi_type = GSM_MI_TYPE_IMEI,
407 .mi_str = "123456789012345",
Neels Hofmeyr02fd83d2019-01-05 00:38:54 +0100408 .mi_name = "IMEI-123456789012345",
Neels Hofmeyr49686282018-12-05 21:32:21 +0100409 .expect_mi_tlv_hex = "17081a32547698103254",
410 },
411 {
412 .mi_type = GSM_MI_TYPE_IMEI,
413 .mi_str = "98765432109876",
Neels Hofmeyr02fd83d2019-01-05 00:38:54 +0100414 .mi_name = "IMEI-98765432109876",
Neels Hofmeyr49686282018-12-05 21:32:21 +0100415 .expect_mi_tlv_hex = "170892785634129078f6",
416 },
417 {
418 .mi_type = GSM_MI_TYPE_IMEI,
419 .mi_str = "987654321098765",
Neels Hofmeyr02fd83d2019-01-05 00:38:54 +0100420 .mi_name = "IMEI-987654321098765",
Neels Hofmeyr49686282018-12-05 21:32:21 +0100421 .expect_mi_tlv_hex = "17089a78563412907856",
422 },
423 {
424 .mi_type = GSM_MI_TYPE_IMEISV,
Harald Welte13177712019-01-20 13:41:26 +0100425 .mi_str = "9876543210987654",
426 .mi_name = "IMEI-SV-9876543210987654",
427 .expect_mi_tlv_hex = "17099378563412907856f4",
Neels Hofmeyr49686282018-12-05 21:32:21 +0100428 },
429 {
430 .mi_type = GSM_MI_TYPE_IMEISV,
Harald Welte13177712019-01-20 13:41:26 +0100431 .mi_str = "9876543210987654",
432 .mi_name = "IMEI-SV-9876543210987654",
433 .expect_mi_tlv_hex = "17099378563412907856f4",
434 .str_size = 17,
435 .expect_str = "9876543210987654",
Neels Hofmeyr49686282018-12-05 21:32:21 +0100436 },
437 {
438 /* gsm48 treats TMSI as decimal string */
439 .mi_type = GSM_MI_TYPE_TMSI,
440 .mi_str = "305419896", /* 0x12345678 as decimal */
Neels Hofmeyr02fd83d2019-01-05 00:38:54 +0100441 .mi_name = "TMSI-0x12345678",
Neels Hofmeyr49686282018-12-05 21:32:21 +0100442 .expect_mi_tlv_hex = "1705f412345678",
443 .expect_rc = 9, /* exception: gsm48_mi_to_string() for TMSI returns strlen(), not bytes! */
444 },
445 {
446 .mi_type = GSM_MI_TYPE_TMSI,
447 .mi_str = "12648430", /* 0xc0ffee as decimal */
Neels Hofmeyr02fd83d2019-01-05 00:38:54 +0100448 .mi_name = "TMSI-0x00C0FFEE",
Neels Hofmeyr49686282018-12-05 21:32:21 +0100449 .expect_mi_tlv_hex = "1705f400c0ffee",
450 .expect_rc = 8, /* exception: gsm48_mi_to_string() for TMSI returns strlen(), not bytes! */
451 },
452 {
453 .mi_type = GSM_MI_TYPE_TMSI,
454 .mi_str = "0",
Neels Hofmeyr02fd83d2019-01-05 00:38:54 +0100455 .mi_name = "TMSI-0x00000000",
Neels Hofmeyr49686282018-12-05 21:32:21 +0100456 .expect_mi_tlv_hex = "1705f400000000",
457 .expect_rc = 1, /* exception: gsm48_mi_to_string() for TMSI returns strlen(), not bytes! */
458 },
459 {
460 /* gsm48 treats TMSI as decimal string */
461 .mi_type = GSM_MI_TYPE_TMSI,
462 .mi_str = "305419896", /* 0x12345678 as decimal */
Neels Hofmeyr02fd83d2019-01-05 00:38:54 +0100463 .mi_name = "TMSI-0x12345678",
Neels Hofmeyr49686282018-12-05 21:32:21 +0100464 .expect_mi_tlv_hex = "1705f412345678",
465 .str_size = 5,
466 .expect_str = "3054",
467 .expect_rc = 9, /* exception: gsm48_mi_to_string() for TMSI returns would-be strlen() like snprintf()! */
468 },
469 {
470 .mi_type = GSM_MI_TYPE_NONE,
471 .mi_str = "123",
Neels Hofmeyr02fd83d2019-01-05 00:38:54 +0100472 .mi_name = "unknown",
Neels Hofmeyr49686282018-12-05 21:32:21 +0100473 .expect_mi_tlv_hex = "17021832", /* encoding invalid MI type */
474 .expect_str = "",
475 },
476 {
477 .mi_type = GSM_MI_TYPE_NONE,
478 .mi_str = "1234",
Neels Hofmeyr02fd83d2019-01-05 00:38:54 +0100479 .mi_name = "unknown",
Neels Hofmeyr49686282018-12-05 21:32:21 +0100480 .expect_mi_tlv_hex = "17031032f4", /* encoding invalid MI type */
481 .expect_str = "",
482 },
483 {
484 .mi_type = GSM_MI_ODD,
485 .mi_str = "1234",
Neels Hofmeyr02fd83d2019-01-05 00:38:54 +0100486 .mi_name = "unknown",
Neels Hofmeyr23187fa2018-12-05 23:24:50 +0100487 .expect_mi_tlv_hex = "17031032f4", /* encoding invalid MI type */
Neels Hofmeyr49686282018-12-05 21:32:21 +0100488 .expect_str = "",
489 },
490};
491
492static void test_mid_encode_decode(void)
493{
494 int i;
495
496 printf("\nTesting Mobile Identity conversions\n");
497
498 for (i = 0; i < ARRAY_SIZE(test_mid_encode_decode_tests); i++) {
499 const struct test_mid_encode_decode_test *t = &test_mid_encode_decode_tests[i];
500 uint8_t tlv_buf[64];
501 uint8_t *mi_buf;
502 int tlv_len;
503 int mi_len;
504 const char *tlv_hex;
505 char str[64] = {};
506 size_t str_size = t->str_size ? : sizeof(str);
507 const char *expect_str = t->expect_str ? : t->mi_str;
508 int expect_rc = t->expect_rc ? : strlen(expect_str)+1;
509 int rc;
510 int str_len;
511
512 printf("- %s %s\n", gsm48_mi_type_name(t->mi_type), t->mi_str);
513 if (t->mi_type == GSM_MI_TYPE_TMSI)
514 tlv_len = gsm48_generate_mid_from_tmsi(tlv_buf, (uint32_t)atoll(t->mi_str));
515 else
516 tlv_len = gsm48_generate_mid(tlv_buf, t->mi_str, t->mi_type);
517 tlv_hex = osmo_hexdump_nospc(tlv_buf, tlv_len);
518
519 printf(" -> MI-TLV-hex='%s'\n", tlv_hex);
520 if (t->expect_mi_tlv_hex && strcmp(tlv_hex, t->expect_mi_tlv_hex)) {
521 printf(" ERROR: expected '%s'\n", t->expect_mi_tlv_hex);
522 }
523
524 /* skip the GSM48_IE_MOBILE_ID tag and length */
525 mi_buf = tlv_buf + 2;
526 mi_len = tlv_len - 2;
527
528 rc = gsm48_mi_to_string(str, str_size, mi_buf, mi_len);
529 printf(" -> MI-str=%s rc=%d\n", osmo_quote_str(str, -1), rc);
530 if (strcmp(str, expect_str))
531 printf(" ERROR: expected MI-str=%s\n", osmo_quote_str(expect_str, -1));
532 if (rc != expect_rc)
533 printf(" ERROR: expected rc=%d\n", expect_rc);
534
Neels Hofmeyr02fd83d2019-01-05 00:38:54 +0100535 if (t->mi_name) {
536 const char *mi_name = osmo_mi_name(mi_buf, mi_len);
537 printf(" -> MI-name=%s\n", osmo_quote_str(mi_name, -1));
538 if (strcmp(mi_name, t->mi_name))
539 printf(" ERROR: expected MI-name=%s\n", osmo_quote_str(t->mi_name, -1));
540 }
541
Neels Hofmeyr49686282018-12-05 21:32:21 +0100542 /* Now make sure the resulting string is always '\0' terminated.
543 * The above started out with a zeroed buffer, now repeat with a tainted one. */
544 str_len = strlen(str);
545 str[str_len] = '!';
546 gsm48_mi_to_string(str, str_size, mi_buf, mi_len);
547 if (strlen(str) != str_len)
548 printf(" ERROR: resulting string is not explicitly nul terminated\n");
549 }
550}
551
552static const uint8_t test_mid_decode_zero_length_types[] = { GSM_MI_TYPE_IMSI, GSM_MI_TYPE_TMSI, GSM_MI_TYPE_NONE };
553
554static void test_mid_decode_zero_length(void)
555{
556 int odd;
557 uint8_t valid_mi[64];
558 int valid_mi_len;
559
560 printf("\nDecoding zero length Mobile Identities\n");
561
562 /* IMSI = 123456789012345 */
563 valid_mi_len = osmo_hexparse("1932547698103254", valid_mi, sizeof(valid_mi));
564
565 for (odd = 0; odd <= 1; odd++) {
566 int i;
567 for (i = 0; i < ARRAY_SIZE(test_mid_decode_zero_length_types); i++) {
568 uint8_t mi_type = test_mid_decode_zero_length_types[i] | (odd ? GSM_MI_ODD : 0);
569 char str[8] = {};
570 int rc;
571
572 printf("- MI type: %s%s\n", gsm48_mi_type_name(mi_type & GSM_MI_TYPE_MASK),
573 odd ? " | GSM_MI_ODD":"");
574 valid_mi[0] = (valid_mi[0] & 0xf0) | mi_type;
575
576 printf(" - writing to zero-length string:\n");
577 memset(str, '!', sizeof(str) - 1);
578 rc = gsm48_mi_to_string(str, 0, valid_mi, valid_mi_len);
579 printf(" rc=%d\n", rc);
580 if (str[0] == '!')
581 printf(" nothing written\n");
582 else
583 printf(" ERROR: Wrote to invalid memory!\n");
584
585 printf(" - writing to 1-byte-length string:\n");
586 memset(str, '!', sizeof(str) - 1);
587 rc = gsm48_mi_to_string(str, 1, valid_mi, valid_mi_len);
588 printf(" rc=%d\n", rc);
589 if (str[0] == '\0')
590 printf(" returned empty string\n");
591 else if (str[0] == '!')
592 printf(" ERROR: nothing written, expected nul-terminated empty string\n");
593 else
594 printf(" ERROR: Wrote unexpected string %s\n", osmo_quote_str(str, 5));
595 if (str[1] != '!')
596 printf(" ERROR: Wrote to invalid memory!\n");
597
598 printf(" - decode zero-length mi:\n");
599 memset(str, '!', sizeof(str) - 1);
600 rc = gsm48_mi_to_string(str, sizeof(str), valid_mi, 0);
601 printf(" rc=%d\n", rc);
602 if (str[0] == '\0')
603 printf(" returned empty string\n");
604 else if (str[0] == '!')
605 printf(" ERROR: nothing written, expected nul-terminated empty string\n");
606 else
607 printf(" ERROR: expected empty string, got output string: %s\n", osmo_quote_str(str, -1));
608 }
609 }
610 printf("\n");
611}
612
Vadim Yanitskiyaa0683d2019-05-25 23:14:00 +0700613static const struct bcd_number_test {
614 /* Human-readable test name */
615 const char *test_name;
616
617 /* To be encoded number in ASCII */
618 const char *enc_ascii;
619 /* Expected encoding result in HEX */
620 const char *enc_hex;
621 /* Optional header length (LHV) */
622 uint8_t enc_h_len;
623 /* Expected return code */
624 int enc_rc;
625
626 /* To be decoded buffer in HEX */
627 const char *dec_hex;
628 /* Expected decoding result in ASCII */
629 const char *dec_ascii;
630 /* Optional header length (LHV) */
631 uint8_t dec_h_len;
632 /* Expected return code */
633 int dec_rc;
634
635 /* Encoding buffer limit (0 means unlimited) */
636 size_t enc_buf_lim;
637 /* Decoding buffer limit (0 means unlimited) */
638 size_t dec_buf_lim;
639} bcd_number_test_set[] = {
640 {
641 .test_name = "regular 9-digit MSISDN",
642
643 /* Encoding test */
644 .enc_ascii = "123456789",
645 .enc_hex = "0521436587f9",
646 .enc_rc = 6,
647
648 /* Decoding test */
649 .dec_hex = "0521436587f9",
650 .dec_ascii = "123456789",
651 },
652 {
653 .test_name = "regular 6-digit MSISDN with optional header (LHV)",
654
655 /* Encoding test */
656 .enc_ascii = "123456",
Vadim Yanitskiy1dc82642019-05-27 00:53:54 +0700657 .enc_hex = "07ffffffff214365",
Vadim Yanitskiyaa0683d2019-05-25 23:14:00 +0700658 .enc_h_len = 4, /* LHV */
659 .enc_rc = 4 + 4,
660
661 /* Decoding test */
662 .dec_hex = "07deadbeef214365",
663 .dec_ascii = "123456",
664 .dec_h_len = 4, /* LHV */
665 },
666 {
667 .test_name = "long 15-digit (maximum) MSISDN",
668
669 /* Encoding test */
670 .enc_ascii = "123456789012345",
671 .enc_hex = "0821436587092143f5",
672 .enc_rc = 9,
673
674 /* Decoding test */
675 .dec_hex = "0821436587092143f5",
676 .dec_ascii = "123456789012345",
677 },
678 {
679 .test_name = "long 15-digit (maximum) MSISDN, limited buffer",
680
681 /* Encoding test */
682 .enc_ascii = "123456789012345",
683 .enc_hex = "0821436587092143f5",
684 .enc_rc = 9,
685
686 /* Decoding test */
687 .dec_hex = "0821436587092143f5",
688 .dec_ascii = "123456789012345",
689
690 /* Buffer length limitations */
691 .dec_buf_lim = 15 + 1,
692 .enc_buf_lim = 9,
693 },
694 {
695 .test_name = "to be truncated 20-digit MSISDN",
696
697 /* Encoding test (not enough room in buffer) */
698 .enc_ascii = "12345678901234567890",
699 .enc_hex = "", /* nothing */
700 .enc_rc = -EIO,
701
702 /* Decoding test (one 5 digits do not fit) */
703 .dec_hex = "0a21436587092143658709",
704 .dec_ascii = "123456789012345",
Vadim Yanitskiy71940872019-05-26 00:49:57 +0700705 .dec_rc = -ENOSPC,
Vadim Yanitskiyaa0683d2019-05-25 23:14:00 +0700706
707 /* Buffer length limitations */
708 .dec_buf_lim = 15 + 1, /* 5 digits less */
709 .enc_buf_lim = 9,
710 },
711 {
712 .test_name = "LV incorrect length",
713 .dec_hex = "05214365", /* should be 0x03 */
714 .dec_ascii = "(none)",
Vadim Yanitskiye4799f52019-05-26 00:55:20 +0700715 .dec_rc = -EINVAL,
Vadim Yanitskiyaa0683d2019-05-25 23:14:00 +0700716 },
717 {
718 .test_name = "empty input buffer",
719
720 /* Encoding test */
721 .enc_ascii = "",
722 .enc_hex = "00",
723 .enc_rc = 1,
724
725 /* Decoding test */
726 .dec_hex = "",
727 .dec_ascii = "(none)",
728 .dec_rc = -EIO,
729 },
730};
731
732static void test_bcd_number_encode_decode()
733{
734 const struct bcd_number_test *test;
Vadim Yanitskiy1dc82642019-05-27 00:53:54 +0700735 uint8_t buf_enc[0xff] = { 0xff };
736 char buf_dec[0xff] = { 0xff };
Vadim Yanitskiyaa0683d2019-05-25 23:14:00 +0700737 size_t buf_len, i;
738 int rc;
739
740 printf("BSD number encoding / decoding test\n");
741
742 for (i = 0; i < ARRAY_SIZE(bcd_number_test_set); i++) {
743 test = &bcd_number_test_set[i];
744 printf("- Running test: %s\n", test->test_name);
745
746 if (test->enc_ascii) {
747 if (test->enc_buf_lim)
748 buf_len = test->enc_buf_lim;
749 else
750 buf_len = sizeof(buf_enc);
751
752 printf(" - Encoding ASCII (buffer limit=%zu) '%s'...\n",
753 test->enc_buf_lim, test->enc_ascii);
754
755 rc = gsm48_encode_bcd_number(buf_enc, buf_len,
756 test->enc_h_len, test->enc_ascii);
757 printf(" - Expected: (rc=%d) '%s'\n",
758 test->enc_rc, test->enc_hex);
759 printf(" - Actual: (rc=%d) '%s'\n",
760 rc, osmo_hexdump_nospc(buf_enc, rc >= 0 ? rc : 0));
761 }
762
763 if (test->dec_hex) {
764 /* Parse a HEX string */
765 rc = osmo_hexparse(test->dec_hex, buf_enc, sizeof(buf_enc));
766 OSMO_ASSERT(rc >= 0);
767
768 if (test->dec_buf_lim)
769 buf_len = test->dec_buf_lim;
770 else
771 buf_len = sizeof(buf_dec);
772
773 printf(" - Decoding HEX (buffer limit=%zu) '%s'...\n",
774 test->dec_buf_lim, test->dec_hex);
775
776 rc = gsm48_decode_bcd_number2(buf_dec, buf_len,
777 buf_enc, rc, test->dec_h_len);
778 printf(" - Expected: (rc=%d) '%s'\n",
779 test->dec_rc, test->dec_ascii);
780 printf(" - Actual: (rc=%d) '%s'\n",
Vadim Yanitskiy71940872019-05-26 00:49:57 +0700781 rc, (rc == 0 || rc == -ENOSPC) ? buf_dec : "(none)");
Vadim Yanitskiyaa0683d2019-05-25 23:14:00 +0700782 }
Vadim Yanitskiy1dc82642019-05-27 00:53:54 +0700783
784 /* Poison buffers between the test iterations */
785 memset(buf_enc, 0xff, sizeof(buf_enc));
786 memset(buf_dec, 0xff, sizeof(buf_dec));
Vadim Yanitskiyaa0683d2019-05-25 23:14:00 +0700787 }
788
789 printf("\n");
790}
791
Stefan Sperlingfdf8b7b2018-07-27 12:19:15 +0200792struct {
793 int range;
794 int arfcns_num;
795 int arfcns[OSMO_GSM48_RANGE_ENC_MAX_ARFCNS];
796} arfcn_test_ranges[] = {
797 {OSMO_GSM48_ARFCN_RANGE_512, 12,
798 { 1, 12, 31, 51, 57, 91, 97, 98, 113, 117, 120, 125 }},
799 {OSMO_GSM48_ARFCN_RANGE_512, 17,
800 { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17 }},
801 {OSMO_GSM48_ARFCN_RANGE_512, 18,
802 { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18 }},
803 {OSMO_GSM48_ARFCN_RANGE_512, 18,
804 { 1, 17, 31, 45, 58, 79, 81, 97,
805 113, 127, 213, 277, 287, 311, 331, 391,
806 417, 511 }},
807 {OSMO_GSM48_ARFCN_RANGE_512, 6,
808 { 1, 17, 31, 45, 58, 79 }},
809 {OSMO_GSM48_ARFCN_RANGE_512, 6,
810 { 10, 17, 31, 45, 58, 79 }},
811 {OSMO_GSM48_ARFCN_RANGE_1024, 17,
812 { 0, 17, 31, 45, 58, 79, 81, 97,
813 113, 127, 213, 277, 287, 311, 331, 391,
814 1023 }},
815 {OSMO_GSM48_ARFCN_RANGE_1024, 16,
816 { 17, 31, 45, 58, 79, 81, 97, 113,
817 127, 213, 277, 287, 311, 331, 391, 1023 }},
818 {-1}
819};
820
821static int test_single_range_encoding(int range, const int *orig_arfcns, int arfcns_num, int silent)
822{
823 int arfcns[OSMO_GSM48_RANGE_ENC_MAX_ARFCNS];
824 int w[OSMO_GSM48_RANGE_ENC_MAX_ARFCNS];
825 int f0_included = 0;
826 int rc, f0;
827 uint8_t chan_list[16] = {0};
828 struct gsm_sysinfo_freq dec_freq[1024] = {{0}};
829 int dec_arfcns[OSMO_GSM48_RANGE_ENC_MAX_ARFCNS] = {0};
830 int dec_arfcns_count = 0;
831 int arfcns_used = 0;
832 int i;
833
834 arfcns_used = arfcns_num;
835 memmove(arfcns, orig_arfcns, sizeof(arfcns));
836
837 f0 = range == OSMO_GSM48_ARFCN_RANGE_1024 ? 0 : arfcns[0];
838 /*
839 * Manipulate the ARFCN list according to the rules in J4 depending
840 * on the selected range.
841 */
842 arfcns_used = osmo_gsm48_range_enc_filter_arfcns(arfcns, arfcns_used, f0, &f0_included);
843
844 memset(w, 0, sizeof(w));
845 osmo_gsm48_range_enc_arfcns(range, arfcns, arfcns_used, w, 0);
846
847 if (!silent)
848 printf("range=%d, arfcns_used=%d, f0=%d, f0_included=%d\n", range, arfcns_used, f0, f0_included);
849
850 /* Select the range and the amount of bits needed */
851 switch (range) {
852 case OSMO_GSM48_ARFCN_RANGE_128:
853 osmo_gsm48_range_enc_128(chan_list, f0, w);
854 break;
855 case OSMO_GSM48_ARFCN_RANGE_256:
856 osmo_gsm48_range_enc_256(chan_list, f0, w);
857 break;
858 case OSMO_GSM48_ARFCN_RANGE_512:
859 osmo_gsm48_range_enc_512(chan_list, f0, w);
860 break;
861 case OSMO_GSM48_ARFCN_RANGE_1024:
862 osmo_gsm48_range_enc_1024(chan_list, f0, f0_included, w);
863 break;
864 default:
865 return 1;
866 };
867
868 if (!silent)
869 printf("chan_list = %s\n",
870 osmo_hexdump(chan_list, sizeof(chan_list)));
871
872 rc = gsm48_decode_freq_list(dec_freq, chan_list, sizeof(chan_list),
873 0xfe, 1);
874 if (rc != 0) {
875 printf("Cannot decode freq list, rc = %d\n", rc);
876 return 1;
877 }
878
879 for (i = 0; i < ARRAY_SIZE(dec_freq); i++) {
880 if (dec_freq[i].mask &&
881 dec_arfcns_count < ARRAY_SIZE(dec_arfcns))
882 dec_arfcns[dec_arfcns_count++] = i;
883 }
884
885 if (!silent) {
886 printf("Decoded freqs %d (expected %d)\n",
887 dec_arfcns_count, arfcns_num);
888 printf("Decoded: ");
889 for (i = 0; i < dec_arfcns_count; i++) {
890 printf("%d ", dec_arfcns[i]);
891 if (dec_arfcns[i] != orig_arfcns[i])
892 printf("(!= %d) ", orig_arfcns[i]);
893 }
894 printf("\n");
895 }
896
897 if (dec_arfcns_count != arfcns_num) {
898 printf("Wrong number of arfcns\n");
899 return 1;
900 }
901
902 if (memcmp(dec_arfcns, orig_arfcns, sizeof(dec_arfcns)) != 0) {
903 printf("Decoding error, got wrong freqs\n");
904 printf(" w = ");
905 for (i = 0; i < ARRAY_SIZE(w); i++)
906 printf("%d ", w[i]);
907 printf("\n");
908 return 1;
909 }
910
911 return 0;
912}
913
914static void test_random_range_encoding(int range, int max_arfcn_num)
915{
916 int arfcns_num = 0;
917 int test_idx;
918 int rc, max_count;
919 int num_tests = 1024;
920
921 printf("Random range test: range %d, max num ARFCNs %d\n",
922 range, max_arfcn_num);
923
924 srandom(1);
925
926 for (max_count = 1; max_count < max_arfcn_num; max_count++) {
927 for (test_idx = 0; test_idx < num_tests; test_idx++) {
928 int count;
929 int i;
930 int min_freq = 0;
931
932 int rnd_arfcns[OSMO_GSM48_RANGE_ENC_MAX_ARFCNS] = {0};
933 char rnd_arfcns_set[1024] = {0};
934
935 if (range < OSMO_GSM48_ARFCN_RANGE_1024)
936 min_freq = random() % (1023 - range);
937
938 for (count = max_count; count; ) {
939 int arfcn = min_freq + random() % (range + 1);
940 OSMO_ASSERT(arfcn < ARRAY_SIZE(rnd_arfcns_set));
941
942 if (!rnd_arfcns_set[arfcn]) {
943 rnd_arfcns_set[arfcn] = 1;
944 count -= 1;
945 }
946 }
947
948 arfcns_num = 0;
949 for (i = 0; i < ARRAY_SIZE(rnd_arfcns_set); i++)
950 if (rnd_arfcns_set[i])
951 rnd_arfcns[arfcns_num++] = i;
952
953 rc = test_single_range_encoding(range, rnd_arfcns,
954 arfcns_num, 1);
955 if (rc != 0) {
956 printf("Failed on test %d, range %d, num ARFCNs %d\n",
957 test_idx, range, max_count);
958 test_single_range_encoding(range, rnd_arfcns,
959 arfcns_num, 0);
960 return;
961 }
962 }
963 }
964}
965
966static void test_range_encoding()
967{
968 int *arfcns;
969 int arfcns_num = 0;
970 int test_idx;
971 int range;
972
973 for (test_idx = 0; arfcn_test_ranges[test_idx].arfcns_num > 0; test_idx++)
974 {
975 arfcns_num = arfcn_test_ranges[test_idx].arfcns_num;
976 arfcns = &arfcn_test_ranges[test_idx].arfcns[0];
977 range = arfcn_test_ranges[test_idx].range;
978
979 printf("Range test %d: range %d, num ARFCNs %d\n",
980 test_idx, range, arfcns_num);
981
982 test_single_range_encoding(range, arfcns, arfcns_num, 0);
983 }
984
985 test_random_range_encoding(OSMO_GSM48_ARFCN_RANGE_128, 29);
986 test_random_range_encoding(OSMO_GSM48_ARFCN_RANGE_256, 22);
987 test_random_range_encoding(OSMO_GSM48_ARFCN_RANGE_512, 18);
988 test_random_range_encoding(OSMO_GSM48_ARFCN_RANGE_1024, 16);
989}
990
991static int freqs1[] = {
992 12, 70, 121, 190, 250, 320, 401, 475, 520, 574, 634, 700, 764, 830, 905, 980
993};
994
995static int freqs2[] = {
996 402, 460, 1, 67, 131, 197, 272, 347,
997};
998
999static int freqs3[] = {
1000 68, 128, 198, 279, 353, 398, 452,
1001
1002};
1003
1004static int w_out[] = {
1005 122, 2, 69, 204, 75, 66, 60, 70, 83, 3, 24, 67, 54, 64, 70, 9,
1006};
1007
1008static int range128[] = {
1009 1, 1 + 127,
1010};
1011
1012static int range256[] = {
1013 1, 1 + 128,
1014};
1015
1016static int range512[] = {
1017 1, 1+ 511,
1018};
1019
1020
1021#define VERIFY(res, cmp, wanted) \
1022 if (!(res cmp wanted)) { \
1023 printf("ASSERT failed: %s:%d Wanted: %d %s %d\n", \
1024 __FILE__, __LINE__, (int) res, # cmp, (int) wanted); \
1025 }
1026
1027static void test_arfcn_filter()
1028{
1029 int arfcns[50], i, res, f0_included;
1030 for (i = 0; i < ARRAY_SIZE(arfcns); ++i)
1031 arfcns[i] = (i + 1) * 2;
1032
1033 /* check that the arfcn is taken out. f0_included is only set for Range1024 */
1034 f0_included = 24;
1035 res = osmo_gsm48_range_enc_filter_arfcns(arfcns, ARRAY_SIZE(arfcns), arfcns[0], &f0_included);
1036 VERIFY(res, ==, ARRAY_SIZE(arfcns) - 1);
1037 VERIFY(f0_included, ==, 1);
1038 for (i = 0; i < res; ++i)
1039 VERIFY(arfcns[i], ==, ((i+2) * 2) - (2+1));
1040
1041 /* check with range1024, ARFCN 0 is included */
1042 for (i = 0; i < ARRAY_SIZE(arfcns); ++i)
1043 arfcns[i] = i * 2;
1044 res = osmo_gsm48_range_enc_filter_arfcns(arfcns, ARRAY_SIZE(arfcns), 0, &f0_included);
1045 VERIFY(res, ==, ARRAY_SIZE(arfcns) - 1);
1046 VERIFY(f0_included, ==, 1);
1047 for (i = 0; i < res; ++i)
1048 VERIFY(arfcns[i], ==, (i + 1) * 2 - 1);
1049
1050 /* check with range1024, ARFCN 0 not included */
1051 for (i = 0; i < ARRAY_SIZE(arfcns); ++i)
1052 arfcns[i] = (i + 1) * 2;
1053 res = osmo_gsm48_range_enc_filter_arfcns(arfcns, ARRAY_SIZE(arfcns), 0, &f0_included);
1054 VERIFY(res, ==, ARRAY_SIZE(arfcns));
1055 VERIFY(f0_included, ==, 0);
1056 for (i = 0; i < res; ++i)
1057 VERIFY(arfcns[i], ==, ((i + 1) * 2) - 1);
1058}
1059
1060static void test_print_encoding()
1061{
1062 int rc;
1063 int w[17];
1064 uint8_t chan_list[16];
1065 memset(chan_list, 0x23, sizeof(chan_list));
1066
1067 for (rc = 0; rc < ARRAY_SIZE(w); ++rc)
1068 switch (rc % 3) {
1069 case 0:
1070 w[rc] = 0xAAAA;
1071 break;
1072 case 1:
1073 w[rc] = 0x5555;
1074 break;
1075 case 2:
1076 w[rc] = 0x9696;
1077 break;
1078 }
1079
1080 osmo_gsm48_range_enc_512(chan_list, (1 << 9) | 0x96, w);
1081
1082 printf("Range512: %s\n", osmo_hexdump(chan_list, ARRAY_SIZE(chan_list)));
1083}
1084
1085static void test_si_range_helpers()
1086{
1087 int ws[(sizeof(freqs1)/sizeof(freqs1[0]))];
1088 int i, f0 = 0xFFFFFF;
1089
1090 memset(&ws[0], 0x23, sizeof(ws));
1091
1092 i = osmo_gsm48_range_enc_find_index(1023, freqs1, ARRAY_SIZE(freqs1));
1093 printf("Element is: %d => freqs[i] = %d\n", i, i >= 0 ? freqs1[i] : -1);
1094 VERIFY(i, ==, 2);
1095
1096 i = osmo_gsm48_range_enc_find_index(511, freqs2, ARRAY_SIZE(freqs2));
1097 printf("Element is: %d => freqs[i] = %d\n", i, i >= 0 ? freqs2[i] : -1);
1098 VERIFY(i, ==, 2);
1099
1100 i = osmo_gsm48_range_enc_find_index(511, freqs3, ARRAY_SIZE(freqs3));
1101 printf("Element is: %d => freqs[i] = %d\n", i, i >= 0 ? freqs3[i] : -1);
1102 VERIFY(i, ==, 0);
1103
1104 osmo_gsm48_range_enc_arfcns(1023, freqs1, ARRAY_SIZE(freqs1), ws, 0);
1105
1106 for (i = 0; i < sizeof(freqs1)/sizeof(freqs1[0]); ++i) {
1107 printf("w[%d]=%d\n", i, ws[i]);
1108 VERIFY(ws[i], ==, w_out[i]);
1109 }
1110
1111 i = osmo_gsm48_range_enc_determine_range(range128, ARRAY_SIZE(range128), &f0);
1112 VERIFY(i, ==, OSMO_GSM48_ARFCN_RANGE_128);
1113 VERIFY(f0, ==, 1);
1114
1115 i = osmo_gsm48_range_enc_determine_range(range256, ARRAY_SIZE(range256), &f0);
1116 VERIFY(i, ==, OSMO_GSM48_ARFCN_RANGE_256);
1117 VERIFY(f0, ==, 1);
1118
1119 i = osmo_gsm48_range_enc_determine_range(range512, ARRAY_SIZE(range512), &f0);
1120 VERIFY(i, ==, OSMO_GSM48_ARFCN_RANGE_512);
1121 VERIFY(f0, ==, 1);
1122}
1123
Harald Weltec8a0b932012-08-24 21:27:26 +02001124int main(int argc, char **argv)
1125{
1126 test_bearer_cap();
Holger Hans Peter Freythercd252e32013-07-03 09:56:53 +02001127 test_mid_from_tmsi();
Maxd55d7d42018-02-15 11:27:18 +01001128 test_mid_from_imsi();
Neels Hofmeyr49686282018-12-05 21:32:21 +01001129 test_mid_encode_decode();
1130 test_mid_decode_zero_length();
Vadim Yanitskiyaa0683d2019-05-25 23:14:00 +07001131 test_bcd_number_encode_decode();
Max99377c22017-08-30 19:17:50 +02001132 test_ra_cap();
Neels Hofmeyrd5a577b2018-02-20 21:48:07 +01001133 test_lai_encode_decode();
Holger Hans Peter Freythercd252e32013-07-03 09:56:53 +02001134
Stefan Sperlingfdf8b7b2018-07-27 12:19:15 +02001135 test_si_range_helpers();
1136 test_arfcn_filter();
1137 test_print_encoding();
1138 test_range_encoding();
1139
Holger Hans Peter Freythercd252e32013-07-03 09:56:53 +02001140 return EXIT_SUCCESS;
Harald Weltec8a0b932012-08-24 21:27:26 +02001141}