blob: 5a59639743ba4bceddab1c6f1c09fefa8b1c04fa [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
Neels Hofmeyr30856ca2020-06-16 13:17:20 +020021#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
22
Harald Weltec8a0b932012-08-24 21:27:26 +020023#include <string.h>
24#include <stdio.h>
Holger Hans Peter Freythercd252e32013-07-03 09:56:53 +020025#include <stdlib.h>
Harald Weltec8a0b932012-08-24 21:27:26 +020026
27#include <osmocom/gsm/protocol/gsm_04_08.h>
28#include <osmocom/gsm/gsm48_ie.h>
Holger Hans Peter Freythercd252e32013-07-03 09:56:53 +020029#include <osmocom/gsm/gsm48.h>
Stefan Sperlingfdf8b7b2018-07-27 12:19:15 +020030#include <osmocom/gsm/gsm48_arfcn_range_encode.h>
Pau Espin Pedrolb99f4ca2019-10-31 13:35:22 +010031#include <osmocom/gsm/gsm_utils.h>
Harald Weltec8a0b932012-08-24 21:27:26 +020032#include <osmocom/gsm/mncc.h>
Holger Hans Peter Freythercd252e32013-07-03 09:56:53 +020033#include <osmocom/core/backtrace.h>
Harald Weltec8a0b932012-08-24 21:27:26 +020034#include <osmocom/core/utils.h>
35#include <osmocom/core/msgb.h>
36
37
38static const uint8_t csd_9600_v110_lv[] = { 0x07, 0xa1, 0xb8, 0x89, 0x21, 0x15, 0x63, 0x80 };
39
40static const struct gsm_mncc_bearer_cap bcap_csd_9600_v110 = {
41 .transfer = GSM48_BCAP_ITCAP_UNR_DIG_INF,
42 .mode = GSM48_BCAP_TMOD_CIRCUIT,
43 .coding = GSM48_BCAP_CODING_GSM_STD,
44 .radio = GSM48_BCAP_RRQ_FR_ONLY,
45 .speech_ver[0]= -1,
46 .data = {
47 .rate_adaption = GSM48_BCAP_RA_V110_X30,
48 .sig_access = GSM48_BCAP_SA_I440_I450,
49 .async = 1,
50 .nr_stop_bits = 1,
51 .nr_data_bits = 8,
52 .user_rate = GSM48_BCAP_UR_9600,
53 .parity = GSM48_BCAP_PAR_NONE,
54 .interm_rate = GSM48_BCAP_IR_16k,
55 .transp = GSM48_BCAP_TR_TRANSP,
56 .modem_type = GSM48_BCAP_MT_NONE,
57 },
58};
59
60static const uint8_t speech_all_lv[] = { 0x06, 0x60, 0x04, 0x02, 0x00, 0x05, 0x81 };
61
62static const struct gsm_mncc_bearer_cap bcap_speech_all = {
63 .transfer = GSM48_BCAP_ITCAP_SPEECH,
64 .mode = GSM48_BCAP_TMOD_CIRCUIT,
65 .coding = GSM48_BCAP_CODING_GSM_STD,
66 .radio = GSM48_BCAP_RRQ_DUAL_FR,
67 .speech_ver = {
68 4, 2, 0, 5, 1, -1,
69 },
70};
71
72
73struct bcap_test {
74 const uint8_t *lv;
75 const struct gsm_mncc_bearer_cap *bc;
76 const char *name;
77};
78
79static const struct bcap_test bcap_tests[] = {
80 { csd_9600_v110_lv, &bcap_csd_9600_v110, "CSD 9600/V.110/transparent" },
81 { speech_all_lv, &bcap_speech_all, "Speech, all codecs" },
82};
83
84static int test_bearer_cap()
85{
86 struct gsm_mncc_bearer_cap bc;
87 int i, rc;
88
89 for (i = 0; i < ARRAY_SIZE(bcap_tests); i++) {
90 struct msgb *msg = msgb_alloc(100, "test");
91 int lv_len;
92
93 memset(&bc, 0, sizeof(bc));
94
95 /* test decoding */
96 rc = gsm48_decode_bearer_cap(&bc, bcap_tests[i].lv);
97 if (rc < 0) {
98 fprintf(stderr, "Error decoding %s\n",
99 bcap_tests[i].name);
100 return rc;
101 }
102 if (memcmp(&bc, bcap_tests[i].bc, sizeof(bc))) {
103 fprintf(stderr, "Incorrect decoded result of %s:\n",
104 bcap_tests[i].name);
105 fprintf(stderr, " should: %s\n",
106 osmo_hexdump((uint8_t *) bcap_tests[i].bc, sizeof(bc)));
107 fprintf(stderr, " is: %s\n",
108 osmo_hexdump((uint8_t *) &bc, sizeof(bc)));
109 return -1;
110 }
111
112 /* also test re-encode? */
113 rc = gsm48_encode_bearer_cap(msg, 1, &bc);
114 if (rc < 0) {
115 fprintf(stderr, "Error encoding %s\n",
116 bcap_tests[i].name);
117 return rc;
118 }
119 lv_len = bcap_tests[i].lv[0]+1;
120 if (memcmp(msg->data, bcap_tests[i].lv, lv_len)) {
121 fprintf(stderr, "Incorrect encoded result of %s:\n",
122 bcap_tests[i].name);
123 fprintf(stderr, " should: %s\n",
124 osmo_hexdump(bcap_tests[i].lv, lv_len));
125 fprintf(stderr, " is: %s\n",
126 osmo_hexdump(msg->data, msg->len));
127 return -1;
128 }
129
130 printf("Test `%s' passed\n", bcap_tests[i].name);
131 msgb_free(msg);
132 }
133
134 return 0;
135}
136
Max99377c22017-08-30 19:17:50 +0200137static inline void dump_ra(const struct gprs_ra_id *raid)
138{
Neels Hofmeyrdbb25132018-02-20 15:12:23 +0100139 printf("%s%s\n", osmo_rai_name(raid), raid->mnc_3_digits ? " (3-digit MNC)" : "");
Max99377c22017-08-30 19:17:50 +0200140}
141
142static inline void check_ra(const struct gprs_ra_id *raid)
143{
Maxf1ad60e2018-01-05 14:19:33 +0100144 struct gsm48_ra_id ra;
Max99377c22017-08-30 19:17:50 +0200145 struct gprs_ra_id raid0 = {
146 .mnc = 0,
147 .mcc = 0,
148 .lac = 0,
149 .rac = 0,
150 };
151
Maxf1ad60e2018-01-05 14:19:33 +0100152 gsm48_encode_ra(&ra, raid);
153 printf("Constructed RA:\n");
Max99377c22017-08-30 19:17:50 +0200154
Maxf1ad60e2018-01-05 14:19:33 +0100155 gsm48_parse_ra(&raid0, (const uint8_t *)&ra);
Max99377c22017-08-30 19:17:50 +0200156 dump_ra(raid);
Neels Hofmeyrc38b32d2018-02-20 15:13:18 +0100157 printf("MCC+MNC in BCD: %s\n", osmo_hexdump(ra.digits, sizeof(ra.digits)));
Max99377c22017-08-30 19:17:50 +0200158 dump_ra(&raid0);
159 printf("RA test...");
Neels Hofmeyrdbb25132018-02-20 15:12:23 +0100160 if (raid->mnc != raid0.mnc || raid->mcc != raid0.mcc || raid->lac != raid0.lac || raid->rac != raid0.rac
161 || (raid->mnc_3_digits || raid->mnc > 99) != raid0.mnc_3_digits)
Max99377c22017-08-30 19:17:50 +0200162 printf("FAIL\n");
163 else
164 printf("passed\n");
165}
166
Neels Hofmeyrd5a577b2018-02-20 21:48:07 +0100167static inline void check_lai(const struct gprs_ra_id *raid)
168{
169 int rc;
170 struct gsm48_loc_area_id lai = {};
171 struct gprs_ra_id decoded = {};
172 struct gprs_ra_id _laid = *raid;
173 struct gprs_ra_id *laid = &_laid;
174 laid->rac = 0;
175
176 printf("- gsm48_generate_lai() from "); dump_ra(laid);
177
178 gsm48_generate_lai(&lai, laid->mcc, laid->mnc, laid->lac);
179 printf(" Encoded %s\n", osmo_hexdump((unsigned char*)&lai, sizeof(lai)));
180 rc = gsm48_decode_lai(&lai, &decoded.mcc, &decoded.mnc, &decoded.lac);
181 if (rc) {
182 printf(" gsm48_decode_lai() returned %d --> FAIL\n", rc);
183 return;
184 }
185 printf(" gsm48_decode_lai() gives "); dump_ra(&decoded);
186 if (decoded.mcc == laid->mcc
187 && decoded.mnc == laid->mnc
188 && decoded.lac == laid->lac)
189 printf(" passed\n");
190 else
191 printf(" FAIL\n");
192}
193
Neels Hofmeyr4566f4e2018-02-20 22:19:56 +0100194static inline void dump_lai(const struct osmo_location_area_id *lai)
195{
196 printf("%s%s\n", osmo_lai_name(lai), lai->plmn.mnc_3_digits ? " (3-digit MNC)" : "");
197}
198
199static inline void check_lai2(const struct gprs_ra_id *raid)
200{
201 struct gsm48_loc_area_id lai = {};
202 struct osmo_location_area_id decoded = {};
203 struct osmo_location_area_id laid = {
204 .plmn = {
205 .mcc = raid->mcc,
206 .mnc = raid->mnc,
207 .mnc_3_digits = raid->mnc_3_digits,
208 },
209 .lac = raid->lac,
210 };
211
212 printf("- gsm48_generate_lai2() from "); dump_lai(&laid);
213
214 gsm48_generate_lai2(&lai, &laid);
215 printf(" Encoded %s\n", osmo_hexdump((unsigned char*)&lai, sizeof(lai)));
216 gsm48_decode_lai2(&lai, &decoded);
217 printf(" gsm48_decode_lai2() gives "); dump_lai(&decoded);
218 if (decoded.plmn.mcc == laid.plmn.mcc
219 && decoded.plmn.mnc == laid.plmn.mnc
220 && decoded.lac == laid.lac
221 && decoded.plmn.mnc_3_digits == (laid.plmn.mnc_3_digits || laid.plmn.mnc > 99))
222 printf(" passed\n");
223 else
224 printf(" FAIL\n");
225}
226
Neels Hofmeyr22da1452018-02-20 15:11:25 +0100227static struct gprs_ra_id test_ra_cap_items[] = {
228 {
Max99377c22017-08-30 19:17:50 +0200229 .mcc = 77,
Neels Hofmeyr0bf93a62018-02-20 22:06:56 +0100230 .mnc = 121,
Max99377c22017-08-30 19:17:50 +0200231 .lac = 666,
232 .rac = 5,
Neels Hofmeyr22da1452018-02-20 15:11:25 +0100233 },
234 {
Max99377c22017-08-30 19:17:50 +0200235 .mcc = 84,
Neels Hofmeyr0bf93a62018-02-20 22:06:56 +0100236 .mnc = 98,
Max99377c22017-08-30 19:17:50 +0200237 .lac = 11,
238 .rac = 89,
Neels Hofmeyr22da1452018-02-20 15:11:25 +0100239 },
Neels Hofmeyrb9fd7eb2018-02-20 15:14:03 +0100240 {
241 .mcc = 0,
242 .mnc = 0,
243 .lac = 0,
244 .rac = 0,
Neels Hofmeyr6c7b3e22018-02-20 22:20:42 +0100245 .mnc_3_digits = false,
246 /* expecting 000-00, BCD = 00 f0 00 */
247 },
248 {
249 .mcc = 0,
250 .mnc = 0,
251 .lac = 0,
252 .rac = 0,
253 .mnc_3_digits = true,
254 /* expecting 000-000, BCD = 00 00 00 */
Neels Hofmeyrb9fd7eb2018-02-20 15:14:03 +0100255 },
256 {
257 .mcc = 999,
258 .mnc = 999,
259 .lac = 65535,
260 .rac = 255,
261 },
Neels Hofmeyr6c7b3e22018-02-20 22:20:42 +0100262 {
263 .mcc = 1,
264 .mnc = 2,
265 .lac = 23,
266 .rac = 42,
267 .mnc_3_digits = false,
268 /* expecting 001-02, BCD = 00 f1 20 */
269 },
270 {
271 .mcc = 1,
272 .mnc = 2,
273 .lac = 23,
274 .rac = 42,
275 .mnc_3_digits = true,
276 /* expecting 001-002, BCD = 00 21 00 */
277 },
278 {
279 .mcc = 12,
280 .mnc = 34,
281 .lac = 56,
282 .rac = 78,
283 .mnc_3_digits = false,
284 /* expecting 012-34, BCD = 10 f2 43 */
285 },
286 {
287 .mcc = 12,
288 .mnc = 34,
289 .lac = 23,
290 .rac = 42,
291 .mnc_3_digits = true,
292 /* expecting 012-034, BCD = 10 42 30 */
293 },
294 {
295 .mcc = 123,
296 .mnc = 456,
297 .lac = 23,
298 .rac = 42,
299 .mnc_3_digits = false,
300 /* expecting 123-456, BCD = 21 63 54 (false flag has no effect) */
301 },
302 {
303 .mcc = 123,
304 .mnc = 456,
305 .lac = 23,
306 .rac = 42,
307 .mnc_3_digits = true,
308 /* expecting 123-456, BCD = 21 63 54 (same) */
309 },
Neels Hofmeyr22da1452018-02-20 15:11:25 +0100310};
Max99377c22017-08-30 19:17:50 +0200311
Neels Hofmeyr22da1452018-02-20 15:11:25 +0100312static void test_ra_cap(void)
313{
314 int i;
315
316 for (i = 0; i < ARRAY_SIZE(test_ra_cap_items); i++)
317 check_ra(&test_ra_cap_items[i]);
Max99377c22017-08-30 19:17:50 +0200318}
319
Neels Hofmeyrd5a577b2018-02-20 21:48:07 +0100320static void test_lai_encode_decode(void)
321{
322 int i;
323
324 for (i = 0; i < ARRAY_SIZE(test_ra_cap_items); i++) {
325 check_lai(&test_ra_cap_items[i]);
Neels Hofmeyr4566f4e2018-02-20 22:19:56 +0100326 check_lai2(&test_ra_cap_items[i]);
Neels Hofmeyrd5a577b2018-02-20 21:48:07 +0100327 }
328}
329
Philipp Maiere36be562020-11-12 11:33:54 +0100330static void dump_cm3(struct gsm48_classmark3 *cm3)
331{
332 printf("mult_band_supp=%02x\n", cm3->mult_band_supp);
333 printf("a5_bits=%02x\n", cm3->a5_bits);
334 printf("assoc_radio_cap_1=%02x\n", cm3->assoc_radio_cap_1);
335 printf("assoc_radio_cap_2=%02x\n", cm3->assoc_radio_cap_2);
336 printf("\n");
337 printf("r_support.present=%u\n", cm3->r_support.present);
338 printf("r_support.r_gsm_assoc_radio_cap=%02x\n",
339 cm3->r_support.r_gsm_assoc_radio_cap);
340 printf("\n");
341 printf("hscsd_mult_slot_cap.present=%u\n",
342 cm3->hscsd_mult_slot_cap.present);
343 printf("hscsd_mult_slot_cap.mslot_class=%02x\n",
344 cm3->hscsd_mult_slot_cap.mslot_class);
345 printf("\n");
346 printf("ucs2_treatment=%u\n", cm3->ucs2_treatment);
347 printf("extended_meas_cap=%u\n", cm3->extended_meas_cap);
348 printf("\n");
349 printf("ms_meas_cap.present=%u\n", cm3->ms_meas_cap.present);
350 printf("ms_meas_cap.sms_value=%02x\n", cm3->ms_meas_cap.sms_value);
351 printf("ms_meas_cap.sm_value=%02x\n", cm3->ms_meas_cap.sm_value);
352 printf("\n");
353 printf("ms_pos_method_cap.present=%u\n",
354 cm3->ms_pos_method_cap.present);
355 printf("ms_pos_method_cap.method=%02x\n",
356 cm3->ms_pos_method_cap.method);
357 printf("\n");
358 printf("ecsd_multislot_cap.present=%u\n",
359 cm3->ecsd_multislot_cap.present);
360 printf("ecsd_multislot_cap.mslot_class=%02x\n",
361 cm3->ecsd_multislot_cap.mslot_class);
362 printf("\n");
363 printf("psk8_struct.present=%u\n", cm3->psk8_struct.present);
364 printf("psk8_struct.mod_cap=%u\n", cm3->psk8_struct.mod_cap);
365 printf("psk8_struct.rf_pwr_cap_1.present=%u\n",
366 cm3->psk8_struct.rf_pwr_cap_1.present);
367 printf("psk8_struct.rf_pwr_cap_1.value=%02x\n",
368 cm3->psk8_struct.rf_pwr_cap_1.value);
369 printf("psk8_struct.rf_pwr_cap_2.present=%u\n",
370 cm3->psk8_struct.rf_pwr_cap_2.present);
371 printf("psk8_struct.rf_pwr_cap_2.value=%02x\n",
372 cm3->psk8_struct.rf_pwr_cap_2.value);
373 printf("\n");
374 printf("gsm_400_bands_supp.present=%u\n",
375 cm3->gsm_400_bands_supp.present);
376 printf("gsm_400_bands_supp.value=%02x\n",
377 cm3->gsm_400_bands_supp.value);
378 printf("gsm_400_bands_supp.assoc_radio_cap=%02x\n",
379 cm3->gsm_400_bands_supp.assoc_radio_cap);
380 printf("\n");
381 printf("gsm_850_assoc_radio_cap.present=%u\n",
382 cm3->gsm_850_assoc_radio_cap.present);
383 printf("gsm_850_assoc_radio_cap.value=%02x\n",
384 cm3->gsm_850_assoc_radio_cap.value);
385 printf("\n");
386 printf("gsm_1900_assoc_radio_cap.present=%u\n",
387 cm3->gsm_1900_assoc_radio_cap.present);
388 printf("gsm_1900_assoc_radio_cap.value=%02x\n",
389 cm3->gsm_1900_assoc_radio_cap.value);
390 printf("\n");
391 printf("umts_fdd_rat_cap=%u\n", cm3->umts_fdd_rat_cap);
392 printf("umts_tdd_rat_cap=%u\n", cm3->umts_tdd_rat_cap);
393 printf("cdma200_rat_cap=%u\n", cm3->cdma200_rat_cap);
394 printf("\n");
395 printf("dtm_gprs_multislot_cap.present=%u\n",
396 cm3->dtm_gprs_multislot_cap.present);
397 printf("dtm_gprs_multislot_cap.mslot_class=%02x\n",
398 cm3->dtm_gprs_multislot_cap.mslot_class);
399 printf("dtm_gprs_multislot_cap.single_slot_dtm=%u\n",
400 cm3->dtm_gprs_multislot_cap.single_slot_dtm);
401 printf("dtm_gprs_multislot_cap.dtm_egprs_multislot_cap.present=%u\n",
402 cm3->dtm_gprs_multislot_cap.dtm_egprs_multislot_cap.present);
403 printf("dtm_gprs_multislot_cap.dtm_egprs_multislot_cap.mslot_class=%02x\n",
404 cm3->dtm_gprs_multislot_cap.dtm_egprs_multislot_cap.mslot_class);
405 printf("\n");
406 printf("single_band_supp.present=%u\n", cm3->single_band_supp.present);
407 printf("single_band_supp.value=%u\n", cm3->single_band_supp.value);
408 printf("\n");
409 printf("gsm_750_assoc_radio_cap.present=%u\n",
410 cm3->gsm_750_assoc_radio_cap.present);
411 printf("gsm_750_assoc_radio_cap.value=%02x\n",
412 cm3->gsm_750_assoc_radio_cap.value);
413 printf("\n");
414 printf("umts_1_28_mcps_tdd_rat_cap=%u\n",
415 cm3->umts_1_28_mcps_tdd_rat_cap);
416 printf("geran_feature_package=%u\n", cm3->geran_feature_package);
417 printf("\n");
418 printf("extended_dtm_gprs_multislot_cap.present=%u\n",
419 cm3->extended_dtm_gprs_multislot_cap.present);
420 printf("extended_dtm_gprs_multislot_cap.mslot_class=%02x\n",
421 cm3->extended_dtm_gprs_multislot_cap.mslot_class);
422 printf
423 ("extended_dtm_gprs_multislot_cap.dtm_egprs_multislot_cap.present=%u\n",
424 cm3->extended_dtm_gprs_multislot_cap.
425 extended_dtm_egprs_multislot_cap.present);
426 printf
427 ("extended_dtm_gprs_multislot_cap.dtm_egprs_multislot_cap.mslot_class=%02x\n",
428 cm3->extended_dtm_gprs_multislot_cap.
429 extended_dtm_egprs_multislot_cap.mslot_class);
430 printf("\n");
431 printf("high_multislot_cap.present=%u\n",
432 cm3->high_multislot_cap.present);
433 printf("high_multislot_cap.value=%02x\n",
434 cm3->high_multislot_cap.value);
435 printf("\n");
436 printf("geran_feature_package_2=%u\n", cm3->geran_feature_package_2);
437 printf("gmsk_multislot_power_prof=%02x\n",
438 cm3->gmsk_multislot_power_prof);
439 printf("psk8_multislot_power_prof=%02x\n",
440 cm3->psk8_multislot_power_prof);
441 printf("\n");
442 printf("t_gsm_400_bands_supp.present=%u\n",
443 cm3->t_gsm_400_bands_supp.present);
444 printf("t_gsm_400_bands_supp.value=%02x\n",
445 cm3->t_gsm_400_bands_supp.value);
446 printf("t_gsm_400_bands_supp.assoc_radio_cap=%02x\n",
447 cm3->t_gsm_400_bands_supp.assoc_radio_cap);
448 printf("\n");
449 printf("dl_advanced_rx_perf=%02x\n", cm3->dl_advanced_rx_perf);
450 printf("dtm_enhancements_cap=%u\n", cm3->dtm_enhancements_cap);
451 printf("\n");
452 printf("dtm_gprs_high_multislot_cap.present=%u\n",
453 cm3->dtm_gprs_high_multislot_cap.present);
454 printf("dtm_gprs_high_multislot_cap.mslot_class=%02x\n",
455 cm3->dtm_gprs_high_multislot_cap.mslot_class);
456 printf("dtm_gprs_high_multislot_cap.offset_required=%u\n",
457 cm3->dtm_gprs_high_multislot_cap.offset_required);
458 printf
459 ("dtm_gprs_high_multislot_cap.dtm_egprs_high_multislot_cap.present=%u\n",
460 cm3->dtm_gprs_high_multislot_cap.dtm_egprs_high_multislot_cap.
461 present);
462 printf
463 ("dtm_gprs_high_multislot_cap.dtm_egprs_high_multislot_cap.mslot_class=%02x\n",
464 cm3->dtm_gprs_high_multislot_cap.dtm_egprs_high_multislot_cap.
465 mslot_class);
466 printf("\n");
467 printf("repeated_acch_capability=%u\n", cm3->repeated_acch_capability);
468 printf("\n");
469 printf("gsm_710_assoc_radio_cap.present=%u\n",
470 cm3->gsm_710_assoc_radio_cap.present);
471 printf("gsm_710_assoc_radio_cap.value=%02x\n",
472 cm3->gsm_710_assoc_radio_cap.value);
473 printf("\n");
474 printf("t_gsm_810_assoc_radio_cap.present=%u\n",
475 cm3->t_gsm_810_assoc_radio_cap.present);
476 printf("t_gsm_810_assoc_radio_cap.value=%02x\n",
477 cm3->t_gsm_810_assoc_radio_cap.value);
478 printf("\n");
479 printf("ciphering_mode_setting_cap=%u\n",
480 cm3->ciphering_mode_setting_cap);
481 printf("add_pos_cap=%u\n", cm3->add_pos_cap);
482 printf("e_utra_fdd_supp=%u\n", cm3->e_utra_fdd_supp);
483 printf("e_utra_tdd_supp=%u\n", cm3->e_utra_tdd_supp);
484 printf("e_utra_meas_rep_supp=%u\n", cm3->e_utra_meas_rep_supp);
485 printf("prio_resel_supp=%u\n", cm3->prio_resel_supp);
486 printf("utra_csg_cells_rep=%u\n", cm3->utra_csg_cells_rep);
487 printf("vamos_level=%02x\n", cm3->vamos_level);
488 printf("tighter_capability=%02x\n", cm3->tighter_capability);
489 printf("sel_ciph_dl_sacch=%u\n", cm3->sel_ciph_dl_sacch);
490 printf("cs_ps_srvcc_geran_utra=%02x\n", cm3->cs_ps_srvcc_geran_utra);
491 printf("cs_ps_srvcc_geran_eutra=%02x\n", cm3->cs_ps_srvcc_geran_eutra);
492 printf("geran_net_sharing=%u\n", cm3->geran_net_sharing);
493 printf("e_utra_wb_rsrq_meas_supp=%u\n", cm3->e_utra_wb_rsrq_meas_supp);
494 printf("er_band_support=%u\n", cm3->er_band_support);
495 printf("utra_mult_band_ind_supp=%u\n", cm3->utra_mult_band_ind_supp);
496 printf("e_utra_mult_band_ind_supp=%u\n",
497 cm3->e_utra_mult_band_ind_supp);
498 printf("extended_tsc_set_cap_supp=%u\n",
499 cm3->extended_tsc_set_cap_supp);
500 printf("extended_earfcn_val_range=%u\n",
501 cm3->extended_earfcn_val_range);
502}
503
504static void test_decode_classmark3(void)
505{
506 struct gsm48_classmark3 cm3;
507 const uint8_t cm3_1[] = { 0x60, 0x14, 0x04, 0x2f, 0x65, 0x00, 0x20, 0x03, 0x40, 0x4a };
508 const uint8_t cm3_2[] = { 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55};
509 const uint8_t cm3_3[] = { 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa};
510
511 printf("=====cm3_1=====\n");
512 gsm48_decode_classmark3(&cm3, cm3_1, sizeof(cm3_1));
513 dump_cm3(&cm3);
514 printf("\n");
515
516 printf("=====cm3_2=====\n");
517 gsm48_decode_classmark3(&cm3, cm3_2, sizeof(cm3_2));
518 dump_cm3(&cm3);
519 printf("\n");
520
521 printf("=====cm3_3=====\n");
522 gsm48_decode_classmark3(&cm3, cm3_3, sizeof(cm3_3));
523 dump_cm3(&cm3);
524 printf("\n");
525}
526
Holger Hans Peter Freythercd252e32013-07-03 09:56:53 +0200527static void test_mid_from_tmsi(void)
528{
529 static const uint8_t res[] = { 0x17, 0x05, 0xf4, 0xaa, 0xbb, 0xcc, 0xdd };
530
531
532 uint32_t tmsi = 0xAABBCCDD;
533 uint8_t buf[3 + sizeof(uint32_t)];
534
535 printf("Simple TMSI encoding test....");
536
537 memset(&buf, 0xFE, sizeof(buf));
538 gsm48_generate_mid_from_tmsi(buf, tmsi);
539
540 OSMO_ASSERT(memcmp(buf, res, sizeof(res)) == 0);
541 printf("passed\n");
542}
543
Maxd55d7d42018-02-15 11:27:18 +0100544static void test_mid_from_imsi(void)
545{
546 char *imsi = "901700000004620";
547 uint8_t buf[10], len;
548
549 printf("Simple IMSI encoding test....");
550
551 len = gsm48_generate_mid_from_imsi(buf, imsi);
552
553 printf("passed: [%u] %s\n", len, osmo_hexdump(buf, len));
554}
555
Neels Hofmeyr49686282018-12-05 21:32:21 +0100556struct test_mid_encode_decode_test {
557 uint8_t mi_type;
558 const char *mi_str;
Neels Hofmeyr02fd83d2019-01-05 00:38:54 +0100559 const char *mi_name;
Neels Hofmeyr49686282018-12-05 21:32:21 +0100560 size_t str_size;
561 const char *expect_mi_tlv_hex;
562 const char *expect_str;
563 int expect_rc;
564};
565
566static const struct test_mid_encode_decode_test test_mid_encode_decode_tests[] = {
567 {
568 .mi_type = GSM_MI_TYPE_IMSI,
569 .mi_str = "123456789012345",
Neels Hofmeyr02fd83d2019-01-05 00:38:54 +0100570 .mi_name = "IMSI-123456789012345",
Neels Hofmeyr49686282018-12-05 21:32:21 +0100571 .expect_mi_tlv_hex = "17081932547698103254",
572 },
573 {
574 .mi_type = GSM_MI_TYPE_IMSI,
575 .mi_str = "12345678901234",
Neels Hofmeyr02fd83d2019-01-05 00:38:54 +0100576 .mi_name = "IMSI-12345678901234",
Neels Hofmeyr49686282018-12-05 21:32:21 +0100577 .expect_mi_tlv_hex = "170811325476981032f4",
578 },
579 {
580 .mi_type = GSM_MI_TYPE_IMSI,
581 .mi_str = "423423",
Neels Hofmeyr02fd83d2019-01-05 00:38:54 +0100582 .mi_name = "IMSI-423423",
Neels Hofmeyr49686282018-12-05 21:32:21 +0100583 .expect_mi_tlv_hex = "1704413224f3",
584 },
585 {
586 .mi_type = GSM_MI_TYPE_IMSI | GSM_MI_ODD,
587 .mi_str = "423423",
Harald Weltea13fb752020-06-16 08:44:42 +0200588 .mi_name = "IMSI-423423",
589 .expect_mi_tlv_hex = "1704413224f3",
Neels Hofmeyr49686282018-12-05 21:32:21 +0100590 },
591 {
592 .mi_type = GSM_MI_TYPE_IMSI,
593 .mi_str = "4234235",
Neels Hofmeyr02fd83d2019-01-05 00:38:54 +0100594 .mi_name = "IMSI-4234235",
Neels Hofmeyr49686282018-12-05 21:32:21 +0100595 .expect_mi_tlv_hex = "170449322453",
596 },
597 {
598 .mi_type = GSM_MI_TYPE_IMSI,
599 .mi_str = "4234235",
Neels Hofmeyr02fd83d2019-01-05 00:38:54 +0100600 .mi_name = "IMSI-4234235",
Neels Hofmeyr49686282018-12-05 21:32:21 +0100601 .expect_mi_tlv_hex = "170449322453",
602 .str_size = 4,
603 .expect_str = "423",
Neels Hofmeyr49686282018-12-05 21:32:21 +0100604 },
605 {
606 .mi_type = GSM_MI_TYPE_IMEI,
607 .mi_str = "123456789012345",
Neels Hofmeyr02fd83d2019-01-05 00:38:54 +0100608 .mi_name = "IMEI-123456789012345",
Neels Hofmeyr49686282018-12-05 21:32:21 +0100609 .expect_mi_tlv_hex = "17081a32547698103254",
610 },
611 {
612 .mi_type = GSM_MI_TYPE_IMEI,
613 .mi_str = "98765432109876",
Neels Hofmeyr02fd83d2019-01-05 00:38:54 +0100614 .mi_name = "IMEI-98765432109876",
Neels Hofmeyr49686282018-12-05 21:32:21 +0100615 .expect_mi_tlv_hex = "170892785634129078f6",
616 },
617 {
618 .mi_type = GSM_MI_TYPE_IMEI,
619 .mi_str = "987654321098765",
Neels Hofmeyr02fd83d2019-01-05 00:38:54 +0100620 .mi_name = "IMEI-987654321098765",
Neels Hofmeyr49686282018-12-05 21:32:21 +0100621 .expect_mi_tlv_hex = "17089a78563412907856",
622 },
623 {
624 .mi_type = GSM_MI_TYPE_IMEISV,
Harald Welte13177712019-01-20 13:41:26 +0100625 .mi_str = "9876543210987654",
626 .mi_name = "IMEI-SV-9876543210987654",
627 .expect_mi_tlv_hex = "17099378563412907856f4",
Neels Hofmeyr49686282018-12-05 21:32:21 +0100628 },
629 {
630 .mi_type = GSM_MI_TYPE_IMEISV,
Harald Welte13177712019-01-20 13:41:26 +0100631 .mi_str = "9876543210987654",
632 .mi_name = "IMEI-SV-9876543210987654",
633 .expect_mi_tlv_hex = "17099378563412907856f4",
634 .str_size = 17,
635 .expect_str = "9876543210987654",
Neels Hofmeyr49686282018-12-05 21:32:21 +0100636 },
637 {
638 /* gsm48 treats TMSI as decimal string */
639 .mi_type = GSM_MI_TYPE_TMSI,
640 .mi_str = "305419896", /* 0x12345678 as decimal */
Neels Hofmeyr02fd83d2019-01-05 00:38:54 +0100641 .mi_name = "TMSI-0x12345678",
Neels Hofmeyr49686282018-12-05 21:32:21 +0100642 .expect_mi_tlv_hex = "1705f412345678",
643 .expect_rc = 9, /* exception: gsm48_mi_to_string() for TMSI returns strlen(), not bytes! */
644 },
645 {
646 .mi_type = GSM_MI_TYPE_TMSI,
647 .mi_str = "12648430", /* 0xc0ffee as decimal */
Neels Hofmeyr02fd83d2019-01-05 00:38:54 +0100648 .mi_name = "TMSI-0x00C0FFEE",
Neels Hofmeyr49686282018-12-05 21:32:21 +0100649 .expect_mi_tlv_hex = "1705f400c0ffee",
650 .expect_rc = 8, /* exception: gsm48_mi_to_string() for TMSI returns strlen(), not bytes! */
651 },
652 {
653 .mi_type = GSM_MI_TYPE_TMSI,
654 .mi_str = "0",
Neels Hofmeyr02fd83d2019-01-05 00:38:54 +0100655 .mi_name = "TMSI-0x00000000",
Neels Hofmeyr49686282018-12-05 21:32:21 +0100656 .expect_mi_tlv_hex = "1705f400000000",
657 .expect_rc = 1, /* exception: gsm48_mi_to_string() for TMSI returns strlen(), not bytes! */
658 },
659 {
660 /* gsm48 treats TMSI as decimal string */
661 .mi_type = GSM_MI_TYPE_TMSI,
662 .mi_str = "305419896", /* 0x12345678 as decimal */
Neels Hofmeyr02fd83d2019-01-05 00:38:54 +0100663 .mi_name = "TMSI-0x12345678",
Neels Hofmeyr49686282018-12-05 21:32:21 +0100664 .expect_mi_tlv_hex = "1705f412345678",
665 .str_size = 5,
666 .expect_str = "3054",
667 .expect_rc = 9, /* exception: gsm48_mi_to_string() for TMSI returns would-be strlen() like snprintf()! */
668 },
669 {
670 .mi_type = GSM_MI_TYPE_NONE,
671 .mi_str = "123",
Neels Hofmeyr02fd83d2019-01-05 00:38:54 +0100672 .mi_name = "unknown",
Harald Weltea13fb752020-06-16 08:44:42 +0200673 .expect_mi_tlv_hex = "17021832", /* encoding invalid MI type */
Neels Hofmeyr49686282018-12-05 21:32:21 +0100674 .expect_str = "",
675 },
676 {
677 .mi_type = GSM_MI_TYPE_NONE,
678 .mi_str = "1234",
Neels Hofmeyr02fd83d2019-01-05 00:38:54 +0100679 .mi_name = "unknown",
Harald Weltea13fb752020-06-16 08:44:42 +0200680 .expect_mi_tlv_hex = "17031032f4", /* encoding invalid MI type */
Neels Hofmeyr49686282018-12-05 21:32:21 +0100681 .expect_str = "",
682 },
683 {
684 .mi_type = GSM_MI_ODD,
685 .mi_str = "1234",
Neels Hofmeyr02fd83d2019-01-05 00:38:54 +0100686 .mi_name = "unknown",
Harald Weltea13fb752020-06-16 08:44:42 +0200687 .expect_mi_tlv_hex = "17031032f4", /* encoding invalid MI type */
Neels Hofmeyr49686282018-12-05 21:32:21 +0100688 .expect_str = "",
689 },
690};
691
692static void test_mid_encode_decode(void)
693{
694 int i;
695
696 printf("\nTesting Mobile Identity conversions\n");
697
698 for (i = 0; i < ARRAY_SIZE(test_mid_encode_decode_tests); i++) {
699 const struct test_mid_encode_decode_test *t = &test_mid_encode_decode_tests[i];
700 uint8_t tlv_buf[64];
701 uint8_t *mi_buf;
702 int tlv_len;
703 int mi_len;
704 const char *tlv_hex;
705 char str[64] = {};
706 size_t str_size = t->str_size ? : sizeof(str);
707 const char *expect_str = t->expect_str ? : t->mi_str;
708 int expect_rc = t->expect_rc ? : strlen(expect_str)+1;
709 int rc;
710 int str_len;
711
712 printf("- %s %s\n", gsm48_mi_type_name(t->mi_type), t->mi_str);
713 if (t->mi_type == GSM_MI_TYPE_TMSI)
714 tlv_len = gsm48_generate_mid_from_tmsi(tlv_buf, (uint32_t)atoll(t->mi_str));
715 else
716 tlv_len = gsm48_generate_mid(tlv_buf, t->mi_str, t->mi_type);
717 tlv_hex = osmo_hexdump_nospc(tlv_buf, tlv_len);
718
719 printf(" -> MI-TLV-hex='%s'\n", tlv_hex);
720 if (t->expect_mi_tlv_hex && strcmp(tlv_hex, t->expect_mi_tlv_hex)) {
721 printf(" ERROR: expected '%s'\n", t->expect_mi_tlv_hex);
722 }
723
Harald Weltea13fb752020-06-16 08:44:42 +0200724 /* skip the GSM48_IE_MOBILE_ID tag and length */
725 mi_buf = tlv_buf + 2;
726 mi_len = tlv_len - 2;
Neels Hofmeyr49686282018-12-05 21:32:21 +0100727
728 rc = gsm48_mi_to_string(str, str_size, mi_buf, mi_len);
729 printf(" -> MI-str=%s rc=%d\n", osmo_quote_str(str, -1), rc);
730 if (strcmp(str, expect_str))
731 printf(" ERROR: expected MI-str=%s\n", osmo_quote_str(expect_str, -1));
732 if (rc != expect_rc)
733 printf(" ERROR: expected rc=%d\n", expect_rc);
734
Neels Hofmeyr02fd83d2019-01-05 00:38:54 +0100735 if (t->mi_name) {
736 const char *mi_name = osmo_mi_name(mi_buf, mi_len);
737 printf(" -> MI-name=%s\n", osmo_quote_str(mi_name, -1));
738 if (strcmp(mi_name, t->mi_name))
739 printf(" ERROR: expected MI-name=%s\n", osmo_quote_str(t->mi_name, -1));
740 }
741
Neels Hofmeyr49686282018-12-05 21:32:21 +0100742 /* Now make sure the resulting string is always '\0' terminated.
743 * The above started out with a zeroed buffer, now repeat with a tainted one. */
744 str_len = strlen(str);
745 str[str_len] = '!';
746 gsm48_mi_to_string(str, str_size, mi_buf, mi_len);
747 if (strlen(str) != str_len)
748 printf(" ERROR: resulting string is not explicitly nul terminated\n");
749 }
750}
751
752static const uint8_t test_mid_decode_zero_length_types[] = { GSM_MI_TYPE_IMSI, GSM_MI_TYPE_TMSI, GSM_MI_TYPE_NONE };
753
754static void test_mid_decode_zero_length(void)
755{
756 int odd;
757 uint8_t valid_mi[64];
758 int valid_mi_len;
759
760 printf("\nDecoding zero length Mobile Identities\n");
761
762 /* IMSI = 123456789012345 */
763 valid_mi_len = osmo_hexparse("1932547698103254", valid_mi, sizeof(valid_mi));
764
765 for (odd = 0; odd <= 1; odd++) {
766 int i;
767 for (i = 0; i < ARRAY_SIZE(test_mid_decode_zero_length_types); i++) {
768 uint8_t mi_type = test_mid_decode_zero_length_types[i] | (odd ? GSM_MI_ODD : 0);
769 char str[8] = {};
770 int rc;
771
772 printf("- MI type: %s%s\n", gsm48_mi_type_name(mi_type & GSM_MI_TYPE_MASK),
773 odd ? " | GSM_MI_ODD":"");
774 valid_mi[0] = (valid_mi[0] & 0xf0) | mi_type;
775
776 printf(" - writing to zero-length string:\n");
777 memset(str, '!', sizeof(str) - 1);
778 rc = gsm48_mi_to_string(str, 0, valid_mi, valid_mi_len);
779 printf(" rc=%d\n", rc);
780 if (str[0] == '!')
781 printf(" nothing written\n");
782 else
783 printf(" ERROR: Wrote to invalid memory!\n");
784
785 printf(" - writing to 1-byte-length string:\n");
786 memset(str, '!', sizeof(str) - 1);
787 rc = gsm48_mi_to_string(str, 1, valid_mi, valid_mi_len);
788 printf(" rc=%d\n", rc);
789 if (str[0] == '\0')
790 printf(" returned empty string\n");
791 else if (str[0] == '!')
792 printf(" ERROR: nothing written, expected nul-terminated empty string\n");
793 else
794 printf(" ERROR: Wrote unexpected string %s\n", osmo_quote_str(str, 5));
795 if (str[1] != '!')
796 printf(" ERROR: Wrote to invalid memory!\n");
797
798 printf(" - decode zero-length mi:\n");
799 memset(str, '!', sizeof(str) - 1);
800 rc = gsm48_mi_to_string(str, sizeof(str), valid_mi, 0);
801 printf(" rc=%d\n", rc);
802 if (str[0] == '\0')
803 printf(" returned empty string\n");
804 else if (str[0] == '!')
805 printf(" ERROR: nothing written, expected nul-terminated empty string\n");
806 else
807 printf(" ERROR: expected empty string, got output string: %s\n", osmo_quote_str(str, -1));
808 }
809 }
810 printf("\n");
811}
812
Neels Hofmeyr83025bf2020-05-26 02:45:23 +0200813struct msgb *msgb_from_hex(const char *label, uint16_t size, const char *hex)
814{
815 struct msgb *msg = msgb_alloc_headroom(size, 4, label);
816 OSMO_ASSERT(msg);
817 msg->l3h = msgb_put(msg, osmo_hexparse(hex, msg->data, msgb_tailroom(msg)));
818 return msg;
819}
820
821struct mobile_identity_tc {
822 const char *label;
823 const char *compl_l3_msg;
824 int expect_rc;
825 struct osmo_mobile_identity expect_mi;
826};
827
828/* Some Complete Layer 3 messages copied from real GSM network traces. */
829struct mobile_identity_tc mobile_identity_tests[] = {
830 {
831 .label = "LU with IMSI 901700000004620",
832 .compl_l3_msg = "050802008168000130" "089910070000006402",
833 .expect_mi = {
834 .type = GSM_MI_TYPE_IMSI,
835 .imsi = "901700000004620",
836 },
837 },
838 {
839 .label = "LU with TMSI 0x0980ad8a",
840 .compl_l3_msg = "05084262f224002a50" "05f40980ad8a",
841 .expect_mi = {
842 .type = GSM_MI_TYPE_TMSI,
843 .tmsi = 0x0980ad8a,
844 },
845 },
846 {
847 .label = "LU with invalid MI type",
848 .compl_l3_msg = "050802008168000130" "089d10070000006402",
849 .expect_rc = -EINVAL,
850 },
851 {
852 .label = "LU with truncated IMSI MI",
853 .compl_l3_msg = "050802008168000130" "0899100700000064",
854 .expect_rc = -EBADMSG,
855 },
856 {
857 .label = "LU with too short IMSI MI (12345)",
858 .compl_l3_msg = "050802008168000130" "03193254",
859 .expect_rc = -EBADMSG,
860 },
861 {
862 .label = "LU with just long enough IMSI MI 123456",
863 .compl_l3_msg = "050802008168000130" "04113254f6",
864 .expect_mi = {
865 .type = GSM_MI_TYPE_IMSI,
866 .imsi = "123456",
867 },
868 },
869 {
870 .label = "LU with max length IMSI MI 123456789012345",
871 .compl_l3_msg = "050802008168000130" "081932547698103254",
872 .expect_mi = {
873 .type = GSM_MI_TYPE_IMSI,
874 .imsi = "123456789012345",
875 },
876 },
877 {
878 .label = "LU with just too long IMSI MI 1234567890123456",
879 .compl_l3_msg = "050802008168000130" "091132547698103254f6",
880 .expect_rc = -EBADMSG,
881 },
882 {
883 .label = "LU with truncated TMSI MI",
884 .compl_l3_msg = "05084262f224002a50" "05f40980ad",
885 .expect_rc = -EBADMSG,
886 },
887 {
888 .label = "LU with odd length TMSI",
889 .compl_l3_msg = "05084262f224002a50" "05fc0980ad8a",
890 .expect_rc = -EBADMSG,
891 },
892 {
893 .label = "LU with too long TMSI MI",
894 .compl_l3_msg = "05084262f224002a50" "06f40980ad23",
895 .expect_rc = -EBADMSG,
896 },
897 {
898 .label = "LU with too short TMSI",
899 .compl_l3_msg = "05084262f224002a50" "04f480ad8a",
900 .expect_rc = -EBADMSG,
901 },
902 {
903 .label = "CM Service Request with IMSI 123456",
904 .compl_l3_msg = "052401035058a6" "04113254f6",
905 .expect_mi = {
906 .type = GSM_MI_TYPE_IMSI,
907 .imsi = "123456",
908 },
909 },
910 {
911 .label = "CM Service Request with TMSI 0x5a42e404",
912 .compl_l3_msg = "052401035058a6" "05f45a42e404",
913 .expect_mi = {
914 .type = GSM_MI_TYPE_TMSI,
915 .tmsi = 0x5a42e404,
916 },
917 },
918 {
919 .label = "CM Service Request with shorter CM2, with IMSI 123456",
920 .compl_l3_msg = "052401025058" "04113254f6",
921 .expect_mi = {
922 .type = GSM_MI_TYPE_IMSI,
923 .imsi = "123456",
924 },
925 },
926 {
927 .label = "CM Service Request with longer CM2, with IMSI 123456",
928 .compl_l3_msg = "052401055058a62342" "04113254f6",
929 .expect_mi = {
930 .type = GSM_MI_TYPE_IMSI,
931 .imsi = "123456",
932 },
933 },
934 {
935 .label = "CM Service Request with shorter CM2, with TMSI 0x00000000",
936 .compl_l3_msg = "052401025058" "05f400000000",
937 .expect_mi = {
938 .type = GSM_MI_TYPE_TMSI,
939 .tmsi = 0,
940 },
941 },
942 {
943 .label = "CM Service Request with invalid MI type",
944 .compl_l3_msg = "052401035058a6" "089d10070000006402",
945 .expect_rc = -EINVAL,
946 },
947 {
948 .label = "CM Service Request with truncated IMSI MI",
949 .compl_l3_msg = "052401035058a6" "0899100700000064",
950 .expect_rc = -EBADMSG,
951 },
952 {
953 .label = "CM Service Request with truncated TMSI MI",
954 .compl_l3_msg = "0524010150" "05f40980ad",
955 .expect_rc = -EBADMSG,
956 },
957 {
958 .label = "CM Service Request with odd length TMSI",
959 .compl_l3_msg = "052401045058a623" "05fc0980ad8a",
960 .expect_rc = -EBADMSG,
961 },
962 {
963 .label = "CM Service Request with too long TMSI MI",
964 .compl_l3_msg = "052401035058a6" "06f40980ad23",
965 .expect_rc = -EBADMSG,
966 },
967 {
968 .label = "CM Service Request with too short TMSI",
969 .compl_l3_msg = "052401035058a6" "04f480ad8a",
970 .expect_rc = -EBADMSG,
971 },
972 {
973 .label = "CM Service Reestablish Request with TMSI 0x5a42e404",
974 .compl_l3_msg = "052801035058a6" "05f45a42e404",
975 .expect_mi = {
976 .type = GSM_MI_TYPE_TMSI,
977 .tmsi = 0x5a42e404,
978 },
979 },
980 {
981 .label = "Paging Response with IMSI 1234567",
982 .compl_l3_msg = "06270003505886" "0419325476",
983 .expect_mi = {
984 .type = GSM_MI_TYPE_IMSI,
985 .imsi = "1234567",
986 },
987 },
988 {
989 .label = "Paging Response with TMSI 0xb48883de",
990 .compl_l3_msg = "06270003505886" "05f4b48883de",
991 .expect_mi = {
992 .type = GSM_MI_TYPE_TMSI,
993 .tmsi = 0xb48883de,
994 },
995 },
996 {
997 .label = "Paging Response with TMSI, with unused nibble not 0xf",
998 .compl_l3_msg = "06270003505886" "0504b48883de",
999 .expect_rc = -EBADMSG,
1000 },
1001 {
1002 .label = "Paging Response with too short IMEI (1234567)",
1003 .compl_l3_msg = "06270003505886" "041a325476",
1004 .expect_rc = -EBADMSG,
1005 },
1006 {
1007 .label = "Paging Response with IMEI 123456789012345",
1008 .compl_l3_msg = "06270003505886" "081a32547698103254",
1009 .expect_mi = {
1010 .type = GSM_MI_TYPE_IMEI,
1011 .imei = "123456789012345",
1012 },
1013 },
1014 {
1015 .label = "Paging Response with IMEI 12345678901234 (no Luhn checksum)",
1016 .compl_l3_msg = "06270003505886" "0812325476981032f4",
1017 .expect_mi = {
1018 .type = GSM_MI_TYPE_IMEI,
1019 .imei = "12345678901234",
1020 },
1021 },
1022 {
1023 .label = "Paging Response with IMEISV 1234567890123456",
1024 .compl_l3_msg = "06270003505886" "091332547698103254f6",
1025 .expect_mi = {
1026 .type = GSM_MI_TYPE_IMEISV,
1027 .imeisv = "1234567890123456",
1028 },
1029 },
1030 {
1031 .label = "Paging Response with too short IMEISV 123456789012345",
1032 .compl_l3_msg = "06270003505886" "081b32547698103254",
1033 .expect_rc = -EBADMSG,
1034 },
1035 {
1036 .label = "Paging Response with too long IMEISV 12345678901234567",
1037 .compl_l3_msg = "06270003505886" "091b3254769810325476",
1038 .expect_rc = -EBADMSG,
1039 },
1040 {
1041 .label = "Paging Response with IMSI 123456789012345 and flipped ODD bit",
1042 .compl_l3_msg = "06270003505886" "081132547698103254",
1043 .expect_rc = -EBADMSG,
1044 },
1045 {
1046 .label = "IMSI-Detach with IMSI 901700000004620",
1047 .compl_l3_msg = "050130" "089910070000006402",
1048 .expect_mi = {
1049 .type = GSM_MI_TYPE_IMSI,
1050 .imsi = "901700000004620",
1051 },
1052 },
1053 {
1054 .label = "IMSI-Detach with TMSI 0x0980ad8a",
1055 .compl_l3_msg = "050130" "05f40980ad8a",
1056 .expect_mi = {
1057 .type = GSM_MI_TYPE_TMSI,
1058 .tmsi = 0x0980ad8a,
1059 },
1060 },
1061 {
1062 .label = "IMSI-Detach with invalid MI type",
1063 .compl_l3_msg = "050130" "089d10070000006402",
1064 .expect_rc = -EINVAL,
1065 },
1066 {
1067 .label = "IMSI-Detach with truncated IMSI MI",
1068 .compl_l3_msg = "050130" "0899100700000064",
1069 .expect_rc = -EBADMSG,
1070 },
1071 {
1072 .label = "IMSI-Detach with too short IMSI MI (12345)",
1073 .compl_l3_msg = "050130" "03193254",
1074 .expect_rc = -EBADMSG,
1075 },
1076 {
1077 .label = "IMSI-Detach with just long enough IMSI MI 123456",
1078 .compl_l3_msg = "050130" "04113254f6",
1079 .expect_mi = {
1080 .type = GSM_MI_TYPE_IMSI,
1081 .imsi = "123456",
1082 },
1083 },
1084 {
1085 .label = "IMSI-Detach with max length IMSI MI 123456789012345",
1086 .compl_l3_msg = "050130" "081932547698103254",
1087 .expect_mi = {
1088 .type = GSM_MI_TYPE_IMSI,
1089 .imsi = "123456789012345",
1090 },
1091 },
1092 {
1093 .label = "IMSI-Detach with just too long IMSI MI 1234567890123456",
1094 .compl_l3_msg = "050130" "091132547698103254f6",
1095 .expect_rc = -EBADMSG,
1096 },
1097 {
1098 .label = "IMSI-Detach with truncated TMSI MI",
1099 .compl_l3_msg = "050130" "05f40980ad",
1100 .expect_rc = -EBADMSG,
1101 },
1102 {
1103 .label = "IMSI-Detach with odd length TMSI",
1104 .compl_l3_msg = "050130" "05fc0980ad8a",
1105 .expect_rc = -EBADMSG,
1106 },
1107 {
1108 .label = "IMSI-Detach with too long TMSI MI",
1109 .compl_l3_msg = "050130" "06f40980ad23",
1110 .expect_rc = -EBADMSG,
1111 },
1112 {
1113 .label = "IMSI-Detach with too short TMSI",
1114 .compl_l3_msg = "050130" "04f480ad8a",
1115 .expect_rc = -EBADMSG,
1116 },
1117 {
1118 .label = "Identity Response with IMSI 901700000004620",
1119 .compl_l3_msg = "0519" "089910070000006402",
1120 .expect_mi = {
1121 .type = GSM_MI_TYPE_IMSI,
1122 .imsi = "901700000004620",
1123 },
1124 },
1125 {
1126 .label = "Identity Response with IMEI 123456789012345",
1127 .compl_l3_msg = "0519" "081a32547698103254",
1128 .expect_mi = {
1129 .type = GSM_MI_TYPE_IMEI,
1130 .imei = "123456789012345",
1131 },
1132 },
1133 {
1134 .label = "Identity Response with IMEISV 9876543210987654",
1135 .compl_l3_msg = "0519" "099378563412907856f4",
1136 .expect_mi = {
1137 .type = GSM_MI_TYPE_IMEISV,
1138 .imeisv = "9876543210987654",
1139 },
1140 },
1141};
1142
1143void test_struct_mobile_identity()
1144{
1145 struct mobile_identity_tc *t;
1146 printf("%s()\n", __func__);
1147 for (t = mobile_identity_tests; (t - mobile_identity_tests) < ARRAY_SIZE(mobile_identity_tests); t++) {
1148 struct osmo_mobile_identity mi;
1149 struct msgb *msg;
1150 int rc;
1151 memset(&mi, 0xff, sizeof(mi));
1152
1153 msg = msgb_from_hex(t->label, 1024, t->compl_l3_msg);
1154 rc = osmo_mobile_identity_decode_from_l3(&mi, msg, false);
1155 msgb_free(msg);
1156
1157 printf("%s: rc = %d", t->label, rc);
1158 if (!rc) {
1159 printf(", mi = %s", osmo_mobile_identity_to_str_c(OTC_SELECT, &mi));
1160 }
1161
1162 if (rc == t->expect_rc
1163 && ((rc != 0) || !osmo_mobile_identity_cmp(&mi, &t->expect_mi))) {
1164 printf(" ok");
1165 } else {
1166 printf(" ERROR: Expected rc = %d", t->expect_rc);
1167 if (!t->expect_rc)
1168 printf(", mi = %s", osmo_mobile_identity_to_str_c(OTC_SELECT, &t->expect_mi));
1169 }
1170 printf("\n");
1171 }
1172 printf("\n");
1173}
1174
Vadim Yanitskiyaa0683d2019-05-25 23:14:00 +07001175static const struct bcd_number_test {
1176 /* Human-readable test name */
1177 const char *test_name;
1178
1179 /* To be encoded number in ASCII */
1180 const char *enc_ascii;
1181 /* Expected encoding result in HEX */
1182 const char *enc_hex;
1183 /* Optional header length (LHV) */
1184 uint8_t enc_h_len;
1185 /* Expected return code */
1186 int enc_rc;
1187
1188 /* To be decoded buffer in HEX */
1189 const char *dec_hex;
1190 /* Expected decoding result in ASCII */
1191 const char *dec_ascii;
1192 /* Optional header length (LHV) */
1193 uint8_t dec_h_len;
1194 /* Expected return code */
1195 int dec_rc;
1196
1197 /* Encoding buffer limit (0 means unlimited) */
1198 size_t enc_buf_lim;
1199 /* Decoding buffer limit (0 means unlimited) */
1200 size_t dec_buf_lim;
1201} bcd_number_test_set[] = {
1202 {
1203 .test_name = "regular 9-digit MSISDN",
1204
1205 /* Encoding test */
1206 .enc_ascii = "123456789",
1207 .enc_hex = "0521436587f9",
1208 .enc_rc = 6,
1209
1210 /* Decoding test */
1211 .dec_hex = "0521436587f9",
1212 .dec_ascii = "123456789",
1213 },
1214 {
1215 .test_name = "regular 6-digit MSISDN with optional header (LHV)",
1216
1217 /* Encoding test */
1218 .enc_ascii = "123456",
Vadim Yanitskiy1dc82642019-05-27 00:53:54 +07001219 .enc_hex = "07ffffffff214365",
Vadim Yanitskiyaa0683d2019-05-25 23:14:00 +07001220 .enc_h_len = 4, /* LHV */
1221 .enc_rc = 4 + 4,
1222
1223 /* Decoding test */
1224 .dec_hex = "07deadbeef214365",
1225 .dec_ascii = "123456",
1226 .dec_h_len = 4, /* LHV */
1227 },
1228 {
1229 .test_name = "long 15-digit (maximum) MSISDN",
1230
1231 /* Encoding test */
1232 .enc_ascii = "123456789012345",
1233 .enc_hex = "0821436587092143f5",
1234 .enc_rc = 9,
1235
1236 /* Decoding test */
1237 .dec_hex = "0821436587092143f5",
1238 .dec_ascii = "123456789012345",
1239 },
1240 {
1241 .test_name = "long 15-digit (maximum) MSISDN, limited buffer",
1242
1243 /* Encoding test */
1244 .enc_ascii = "123456789012345",
1245 .enc_hex = "0821436587092143f5",
1246 .enc_rc = 9,
1247
1248 /* Decoding test */
1249 .dec_hex = "0821436587092143f5",
1250 .dec_ascii = "123456789012345",
1251
1252 /* Buffer length limitations */
1253 .dec_buf_lim = 15 + 1,
1254 .enc_buf_lim = 9,
1255 },
1256 {
1257 .test_name = "to be truncated 20-digit MSISDN",
1258
1259 /* Encoding test (not enough room in buffer) */
1260 .enc_ascii = "12345678901234567890",
1261 .enc_hex = "", /* nothing */
1262 .enc_rc = -EIO,
1263
1264 /* Decoding test (one 5 digits do not fit) */
1265 .dec_hex = "0a21436587092143658709",
1266 .dec_ascii = "123456789012345",
Vadim Yanitskiy71940872019-05-26 00:49:57 +07001267 .dec_rc = -ENOSPC,
Vadim Yanitskiyaa0683d2019-05-25 23:14:00 +07001268
1269 /* Buffer length limitations */
1270 .dec_buf_lim = 15 + 1, /* 5 digits less */
1271 .enc_buf_lim = 9,
1272 },
1273 {
1274 .test_name = "LV incorrect length",
1275 .dec_hex = "05214365", /* should be 0x03 */
1276 .dec_ascii = "(none)",
Vadim Yanitskiye4799f52019-05-26 00:55:20 +07001277 .dec_rc = -EINVAL,
Vadim Yanitskiyaa0683d2019-05-25 23:14:00 +07001278 },
1279 {
1280 .test_name = "empty input buffer",
1281
1282 /* Encoding test */
1283 .enc_ascii = "",
1284 .enc_hex = "00",
1285 .enc_rc = 1,
1286
1287 /* Decoding test */
1288 .dec_hex = "",
1289 .dec_ascii = "(none)",
1290 .dec_rc = -EIO,
1291 },
Oliver Smith186f8782019-06-06 16:11:32 +02001292 {
1293 .test_name = "decoding buffer is one byte too small (OS#4049)",
1294
1295 /* Decoding test */
1296 .dec_hex = "022143", /* "1234" */
1297 .dec_ascii = "123", /* '4' was truncated */
1298 .dec_rc = -ENOSPC,
1299
1300 /* Buffer length limitations */
1301 .dec_buf_lim = 4,
1302 },
Vadim Yanitskiyaa0683d2019-05-25 23:14:00 +07001303};
1304
1305static void test_bcd_number_encode_decode()
1306{
1307 const struct bcd_number_test *test;
Vadim Yanitskiy1dc82642019-05-27 00:53:54 +07001308 uint8_t buf_enc[0xff] = { 0xff };
1309 char buf_dec[0xff] = { 0xff };
Vadim Yanitskiyaa0683d2019-05-25 23:14:00 +07001310 size_t buf_len, i;
1311 int rc;
1312
1313 printf("BSD number encoding / decoding test\n");
1314
1315 for (i = 0; i < ARRAY_SIZE(bcd_number_test_set); i++) {
1316 test = &bcd_number_test_set[i];
1317 printf("- Running test: %s\n", test->test_name);
1318
1319 if (test->enc_ascii) {
1320 if (test->enc_buf_lim)
1321 buf_len = test->enc_buf_lim;
1322 else
1323 buf_len = sizeof(buf_enc);
1324
1325 printf(" - Encoding ASCII (buffer limit=%zu) '%s'...\n",
1326 test->enc_buf_lim, test->enc_ascii);
1327
1328 rc = gsm48_encode_bcd_number(buf_enc, buf_len,
1329 test->enc_h_len, test->enc_ascii);
1330 printf(" - Expected: (rc=%d) '%s'\n",
1331 test->enc_rc, test->enc_hex);
1332 printf(" - Actual: (rc=%d) '%s'\n",
1333 rc, osmo_hexdump_nospc(buf_enc, rc >= 0 ? rc : 0));
1334 }
1335
1336 if (test->dec_hex) {
1337 /* Parse a HEX string */
1338 rc = osmo_hexparse(test->dec_hex, buf_enc, sizeof(buf_enc));
1339 OSMO_ASSERT(rc >= 0);
1340
1341 if (test->dec_buf_lim)
1342 buf_len = test->dec_buf_lim;
1343 else
1344 buf_len = sizeof(buf_dec);
1345
1346 printf(" - Decoding HEX (buffer limit=%zu) '%s'...\n",
1347 test->dec_buf_lim, test->dec_hex);
1348
1349 rc = gsm48_decode_bcd_number2(buf_dec, buf_len,
1350 buf_enc, rc, test->dec_h_len);
1351 printf(" - Expected: (rc=%d) '%s'\n",
1352 test->dec_rc, test->dec_ascii);
1353 printf(" - Actual: (rc=%d) '%s'\n",
Vadim Yanitskiy71940872019-05-26 00:49:57 +07001354 rc, (rc == 0 || rc == -ENOSPC) ? buf_dec : "(none)");
Vadim Yanitskiyaa0683d2019-05-25 23:14:00 +07001355 }
Vadim Yanitskiy1dc82642019-05-27 00:53:54 +07001356
1357 /* Poison buffers between the test iterations */
1358 memset(buf_enc, 0xff, sizeof(buf_enc));
1359 memset(buf_dec, 0xff, sizeof(buf_dec));
Vadim Yanitskiyaa0683d2019-05-25 23:14:00 +07001360 }
1361
1362 printf("\n");
1363}
1364
Stefan Sperlingfdf8b7b2018-07-27 12:19:15 +02001365struct {
1366 int range;
1367 int arfcns_num;
1368 int arfcns[OSMO_GSM48_RANGE_ENC_MAX_ARFCNS];
1369} arfcn_test_ranges[] = {
1370 {OSMO_GSM48_ARFCN_RANGE_512, 12,
1371 { 1, 12, 31, 51, 57, 91, 97, 98, 113, 117, 120, 125 }},
1372 {OSMO_GSM48_ARFCN_RANGE_512, 17,
1373 { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17 }},
1374 {OSMO_GSM48_ARFCN_RANGE_512, 18,
1375 { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18 }},
1376 {OSMO_GSM48_ARFCN_RANGE_512, 18,
1377 { 1, 17, 31, 45, 58, 79, 81, 97,
1378 113, 127, 213, 277, 287, 311, 331, 391,
1379 417, 511 }},
1380 {OSMO_GSM48_ARFCN_RANGE_512, 6,
1381 { 1, 17, 31, 45, 58, 79 }},
1382 {OSMO_GSM48_ARFCN_RANGE_512, 6,
1383 { 10, 17, 31, 45, 58, 79 }},
1384 {OSMO_GSM48_ARFCN_RANGE_1024, 17,
1385 { 0, 17, 31, 45, 58, 79, 81, 97,
1386 113, 127, 213, 277, 287, 311, 331, 391,
1387 1023 }},
1388 {OSMO_GSM48_ARFCN_RANGE_1024, 16,
1389 { 17, 31, 45, 58, 79, 81, 97, 113,
1390 127, 213, 277, 287, 311, 331, 391, 1023 }},
1391 {-1}
1392};
1393
1394static int test_single_range_encoding(int range, const int *orig_arfcns, int arfcns_num, int silent)
1395{
1396 int arfcns[OSMO_GSM48_RANGE_ENC_MAX_ARFCNS];
1397 int w[OSMO_GSM48_RANGE_ENC_MAX_ARFCNS];
1398 int f0_included = 0;
1399 int rc, f0;
1400 uint8_t chan_list[16] = {0};
1401 struct gsm_sysinfo_freq dec_freq[1024] = {{0}};
1402 int dec_arfcns[OSMO_GSM48_RANGE_ENC_MAX_ARFCNS] = {0};
1403 int dec_arfcns_count = 0;
1404 int arfcns_used = 0;
1405 int i;
1406
1407 arfcns_used = arfcns_num;
1408 memmove(arfcns, orig_arfcns, sizeof(arfcns));
1409
1410 f0 = range == OSMO_GSM48_ARFCN_RANGE_1024 ? 0 : arfcns[0];
1411 /*
1412 * Manipulate the ARFCN list according to the rules in J4 depending
1413 * on the selected range.
1414 */
1415 arfcns_used = osmo_gsm48_range_enc_filter_arfcns(arfcns, arfcns_used, f0, &f0_included);
1416
1417 memset(w, 0, sizeof(w));
1418 osmo_gsm48_range_enc_arfcns(range, arfcns, arfcns_used, w, 0);
1419
1420 if (!silent)
1421 printf("range=%d, arfcns_used=%d, f0=%d, f0_included=%d\n", range, arfcns_used, f0, f0_included);
1422
1423 /* Select the range and the amount of bits needed */
1424 switch (range) {
1425 case OSMO_GSM48_ARFCN_RANGE_128:
1426 osmo_gsm48_range_enc_128(chan_list, f0, w);
1427 break;
1428 case OSMO_GSM48_ARFCN_RANGE_256:
1429 osmo_gsm48_range_enc_256(chan_list, f0, w);
1430 break;
1431 case OSMO_GSM48_ARFCN_RANGE_512:
1432 osmo_gsm48_range_enc_512(chan_list, f0, w);
1433 break;
1434 case OSMO_GSM48_ARFCN_RANGE_1024:
1435 osmo_gsm48_range_enc_1024(chan_list, f0, f0_included, w);
1436 break;
1437 default:
1438 return 1;
1439 };
1440
1441 if (!silent)
1442 printf("chan_list = %s\n",
1443 osmo_hexdump(chan_list, sizeof(chan_list)));
1444
1445 rc = gsm48_decode_freq_list(dec_freq, chan_list, sizeof(chan_list),
1446 0xfe, 1);
1447 if (rc != 0) {
1448 printf("Cannot decode freq list, rc = %d\n", rc);
1449 return 1;
1450 }
1451
1452 for (i = 0; i < ARRAY_SIZE(dec_freq); i++) {
1453 if (dec_freq[i].mask &&
1454 dec_arfcns_count < ARRAY_SIZE(dec_arfcns))
1455 dec_arfcns[dec_arfcns_count++] = i;
1456 }
1457
1458 if (!silent) {
1459 printf("Decoded freqs %d (expected %d)\n",
1460 dec_arfcns_count, arfcns_num);
1461 printf("Decoded: ");
1462 for (i = 0; i < dec_arfcns_count; i++) {
1463 printf("%d ", dec_arfcns[i]);
1464 if (dec_arfcns[i] != orig_arfcns[i])
1465 printf("(!= %d) ", orig_arfcns[i]);
1466 }
1467 printf("\n");
1468 }
1469
1470 if (dec_arfcns_count != arfcns_num) {
1471 printf("Wrong number of arfcns\n");
1472 return 1;
1473 }
1474
1475 if (memcmp(dec_arfcns, orig_arfcns, sizeof(dec_arfcns)) != 0) {
1476 printf("Decoding error, got wrong freqs\n");
1477 printf(" w = ");
1478 for (i = 0; i < ARRAY_SIZE(w); i++)
1479 printf("%d ", w[i]);
1480 printf("\n");
1481 return 1;
1482 }
1483
1484 return 0;
1485}
1486
1487static void test_random_range_encoding(int range, int max_arfcn_num)
1488{
1489 int arfcns_num = 0;
1490 int test_idx;
1491 int rc, max_count;
1492 int num_tests = 1024;
1493
1494 printf("Random range test: range %d, max num ARFCNs %d\n",
1495 range, max_arfcn_num);
1496
1497 srandom(1);
1498
1499 for (max_count = 1; max_count < max_arfcn_num; max_count++) {
1500 for (test_idx = 0; test_idx < num_tests; test_idx++) {
1501 int count;
1502 int i;
1503 int min_freq = 0;
1504
1505 int rnd_arfcns[OSMO_GSM48_RANGE_ENC_MAX_ARFCNS] = {0};
1506 char rnd_arfcns_set[1024] = {0};
1507
1508 if (range < OSMO_GSM48_ARFCN_RANGE_1024)
1509 min_freq = random() % (1023 - range);
1510
1511 for (count = max_count; count; ) {
1512 int arfcn = min_freq + random() % (range + 1);
1513 OSMO_ASSERT(arfcn < ARRAY_SIZE(rnd_arfcns_set));
1514
1515 if (!rnd_arfcns_set[arfcn]) {
1516 rnd_arfcns_set[arfcn] = 1;
1517 count -= 1;
1518 }
1519 }
1520
1521 arfcns_num = 0;
1522 for (i = 0; i < ARRAY_SIZE(rnd_arfcns_set); i++)
1523 if (rnd_arfcns_set[i])
1524 rnd_arfcns[arfcns_num++] = i;
1525
1526 rc = test_single_range_encoding(range, rnd_arfcns,
1527 arfcns_num, 1);
1528 if (rc != 0) {
1529 printf("Failed on test %d, range %d, num ARFCNs %d\n",
1530 test_idx, range, max_count);
1531 test_single_range_encoding(range, rnd_arfcns,
1532 arfcns_num, 0);
1533 return;
1534 }
1535 }
1536 }
1537}
1538
1539static void test_range_encoding()
1540{
1541 int *arfcns;
1542 int arfcns_num = 0;
1543 int test_idx;
1544 int range;
1545
1546 for (test_idx = 0; arfcn_test_ranges[test_idx].arfcns_num > 0; test_idx++)
1547 {
1548 arfcns_num = arfcn_test_ranges[test_idx].arfcns_num;
1549 arfcns = &arfcn_test_ranges[test_idx].arfcns[0];
1550 range = arfcn_test_ranges[test_idx].range;
1551
1552 printf("Range test %d: range %d, num ARFCNs %d\n",
1553 test_idx, range, arfcns_num);
1554
1555 test_single_range_encoding(range, arfcns, arfcns_num, 0);
1556 }
1557
1558 test_random_range_encoding(OSMO_GSM48_ARFCN_RANGE_128, 29);
1559 test_random_range_encoding(OSMO_GSM48_ARFCN_RANGE_256, 22);
1560 test_random_range_encoding(OSMO_GSM48_ARFCN_RANGE_512, 18);
1561 test_random_range_encoding(OSMO_GSM48_ARFCN_RANGE_1024, 16);
1562}
1563
1564static int freqs1[] = {
1565 12, 70, 121, 190, 250, 320, 401, 475, 520, 574, 634, 700, 764, 830, 905, 980
1566};
1567
1568static int freqs2[] = {
1569 402, 460, 1, 67, 131, 197, 272, 347,
1570};
1571
1572static int freqs3[] = {
1573 68, 128, 198, 279, 353, 398, 452,
1574
1575};
1576
1577static int w_out[] = {
1578 122, 2, 69, 204, 75, 66, 60, 70, 83, 3, 24, 67, 54, 64, 70, 9,
1579};
1580
1581static int range128[] = {
1582 1, 1 + 127,
1583};
1584
1585static int range256[] = {
1586 1, 1 + 128,
1587};
1588
1589static int range512[] = {
1590 1, 1+ 511,
1591};
1592
1593
1594#define VERIFY(res, cmp, wanted) \
1595 if (!(res cmp wanted)) { \
1596 printf("ASSERT failed: %s:%d Wanted: %d %s %d\n", \
1597 __FILE__, __LINE__, (int) res, # cmp, (int) wanted); \
1598 }
1599
1600static void test_arfcn_filter()
1601{
1602 int arfcns[50], i, res, f0_included;
1603 for (i = 0; i < ARRAY_SIZE(arfcns); ++i)
1604 arfcns[i] = (i + 1) * 2;
1605
1606 /* check that the arfcn is taken out. f0_included is only set for Range1024 */
1607 f0_included = 24;
1608 res = osmo_gsm48_range_enc_filter_arfcns(arfcns, ARRAY_SIZE(arfcns), arfcns[0], &f0_included);
1609 VERIFY(res, ==, ARRAY_SIZE(arfcns) - 1);
1610 VERIFY(f0_included, ==, 1);
1611 for (i = 0; i < res; ++i)
1612 VERIFY(arfcns[i], ==, ((i+2) * 2) - (2+1));
1613
1614 /* check with range1024, ARFCN 0 is included */
1615 for (i = 0; i < ARRAY_SIZE(arfcns); ++i)
1616 arfcns[i] = i * 2;
1617 res = osmo_gsm48_range_enc_filter_arfcns(arfcns, ARRAY_SIZE(arfcns), 0, &f0_included);
1618 VERIFY(res, ==, ARRAY_SIZE(arfcns) - 1);
1619 VERIFY(f0_included, ==, 1);
1620 for (i = 0; i < res; ++i)
1621 VERIFY(arfcns[i], ==, (i + 1) * 2 - 1);
1622
1623 /* check with range1024, ARFCN 0 not included */
1624 for (i = 0; i < ARRAY_SIZE(arfcns); ++i)
1625 arfcns[i] = (i + 1) * 2;
1626 res = osmo_gsm48_range_enc_filter_arfcns(arfcns, ARRAY_SIZE(arfcns), 0, &f0_included);
1627 VERIFY(res, ==, ARRAY_SIZE(arfcns));
1628 VERIFY(f0_included, ==, 0);
1629 for (i = 0; i < res; ++i)
1630 VERIFY(arfcns[i], ==, ((i + 1) * 2) - 1);
1631}
1632
1633static void test_print_encoding()
1634{
1635 int rc;
1636 int w[17];
1637 uint8_t chan_list[16];
1638 memset(chan_list, 0x23, sizeof(chan_list));
1639
1640 for (rc = 0; rc < ARRAY_SIZE(w); ++rc)
1641 switch (rc % 3) {
1642 case 0:
1643 w[rc] = 0xAAAA;
1644 break;
1645 case 1:
1646 w[rc] = 0x5555;
1647 break;
1648 case 2:
1649 w[rc] = 0x9696;
1650 break;
1651 }
1652
1653 osmo_gsm48_range_enc_512(chan_list, (1 << 9) | 0x96, w);
1654
1655 printf("Range512: %s\n", osmo_hexdump(chan_list, ARRAY_SIZE(chan_list)));
1656}
1657
1658static void test_si_range_helpers()
1659{
1660 int ws[(sizeof(freqs1)/sizeof(freqs1[0]))];
1661 int i, f0 = 0xFFFFFF;
1662
1663 memset(&ws[0], 0x23, sizeof(ws));
1664
1665 i = osmo_gsm48_range_enc_find_index(1023, freqs1, ARRAY_SIZE(freqs1));
1666 printf("Element is: %d => freqs[i] = %d\n", i, i >= 0 ? freqs1[i] : -1);
1667 VERIFY(i, ==, 2);
1668
1669 i = osmo_gsm48_range_enc_find_index(511, freqs2, ARRAY_SIZE(freqs2));
1670 printf("Element is: %d => freqs[i] = %d\n", i, i >= 0 ? freqs2[i] : -1);
1671 VERIFY(i, ==, 2);
1672
1673 i = osmo_gsm48_range_enc_find_index(511, freqs3, ARRAY_SIZE(freqs3));
1674 printf("Element is: %d => freqs[i] = %d\n", i, i >= 0 ? freqs3[i] : -1);
1675 VERIFY(i, ==, 0);
1676
1677 osmo_gsm48_range_enc_arfcns(1023, freqs1, ARRAY_SIZE(freqs1), ws, 0);
1678
1679 for (i = 0; i < sizeof(freqs1)/sizeof(freqs1[0]); ++i) {
1680 printf("w[%d]=%d\n", i, ws[i]);
1681 VERIFY(ws[i], ==, w_out[i]);
1682 }
1683
1684 i = osmo_gsm48_range_enc_determine_range(range128, ARRAY_SIZE(range128), &f0);
1685 VERIFY(i, ==, OSMO_GSM48_ARFCN_RANGE_128);
1686 VERIFY(f0, ==, 1);
1687
1688 i = osmo_gsm48_range_enc_determine_range(range256, ARRAY_SIZE(range256), &f0);
1689 VERIFY(i, ==, OSMO_GSM48_ARFCN_RANGE_256);
1690 VERIFY(f0, ==, 1);
1691
1692 i = osmo_gsm48_range_enc_determine_range(range512, ARRAY_SIZE(range512), &f0);
1693 VERIFY(i, ==, OSMO_GSM48_ARFCN_RANGE_512);
1694 VERIFY(f0, ==, 1);
1695}
1696
Pau Espin Pedrolb99f4ca2019-10-31 13:35:22 +01001697static void test_power_ctrl()
1698{
1699 int8_t rc8;
Pau Espin Pedrole40b9632019-10-31 15:38:30 +01001700 int rc;
Pau Espin Pedrolb99f4ca2019-10-31 13:35:22 +01001701
1702 rc8 = osmo_gsm48_rfpowercap2powerclass(GSM_BAND_850, 0x00);
1703 VERIFY(rc8, ==, 1);
1704 rc8 = osmo_gsm48_rfpowercap2powerclass(GSM_BAND_900, 0x02);
1705 VERIFY(rc8, ==, 3);
1706 rc8 = osmo_gsm48_rfpowercap2powerclass(GSM_BAND_1800, 0x02);
1707 VERIFY(rc8, ==, 3);
1708 rc8 = osmo_gsm48_rfpowercap2powerclass(GSM_BAND_1900, 0x02);
1709 VERIFY(rc8, ==, 3);
1710 rc8 = osmo_gsm48_rfpowercap2powerclass(GSM_BAND_1900, 0x04);
1711 VERIFY(rc8, <, 0);
1712 rc8 = osmo_gsm48_rfpowercap2powerclass(GSM_BAND_900, 0x04);
1713 VERIFY(rc8, ==, 5);
1714 rc8 = osmo_gsm48_rfpowercap2powerclass(GSM_BAND_900, 0x05);
1715 VERIFY(rc8, <, 0);
1716 rc8 = osmo_gsm48_rfpowercap2powerclass(GSM_BAND_900, 0xf2);
1717 VERIFY(rc8, <, 0);
Pau Espin Pedrole40b9632019-10-31 15:38:30 +01001718
1719 rc = ms_class_gmsk_dbm(GSM_BAND_850, 0);
1720 VERIFY(rc, <, 0);
1721 rc = ms_class_gmsk_dbm(GSM_BAND_850, 1);
1722 VERIFY(rc, ==, 43);
1723 rc = ms_class_gmsk_dbm(GSM_BAND_900, 3);
1724 VERIFY(rc, ==, 37);
1725 rc = ms_class_gmsk_dbm(GSM_BAND_1800, 2);
1726 VERIFY(rc, ==, 24);
1727 rc = ms_class_gmsk_dbm(GSM_BAND_1800, 3);
1728 VERIFY(rc, ==, 36);
1729 rc = ms_class_gmsk_dbm(GSM_BAND_1900, 3);
1730 VERIFY(rc, ==, 33);
1731 rc = ms_class_gmsk_dbm(GSM_BAND_1900, 4);
1732 VERIFY(rc, <, 0);
1733 rc = ms_class_gmsk_dbm(GSM_BAND_900, 5);
1734 VERIFY(rc, ==, 29);
1735 rc = ms_class_gmsk_dbm(GSM_BAND_900, 6);
1736 VERIFY(rc, <, 0);
Pau Espin Pedrolb99f4ca2019-10-31 13:35:22 +01001737}
1738
Harald Weltec8a0b932012-08-24 21:27:26 +02001739int main(int argc, char **argv)
1740{
1741 test_bearer_cap();
Holger Hans Peter Freythercd252e32013-07-03 09:56:53 +02001742 test_mid_from_tmsi();
Maxd55d7d42018-02-15 11:27:18 +01001743 test_mid_from_imsi();
Neels Hofmeyr49686282018-12-05 21:32:21 +01001744 test_mid_encode_decode();
1745 test_mid_decode_zero_length();
Neels Hofmeyr83025bf2020-05-26 02:45:23 +02001746 test_struct_mobile_identity();
Vadim Yanitskiyaa0683d2019-05-25 23:14:00 +07001747 test_bcd_number_encode_decode();
Max99377c22017-08-30 19:17:50 +02001748 test_ra_cap();
Neels Hofmeyrd5a577b2018-02-20 21:48:07 +01001749 test_lai_encode_decode();
Philipp Maiere36be562020-11-12 11:33:54 +01001750 test_decode_classmark3();
Holger Hans Peter Freythercd252e32013-07-03 09:56:53 +02001751
Stefan Sperlingfdf8b7b2018-07-27 12:19:15 +02001752 test_si_range_helpers();
1753 test_arfcn_filter();
1754 test_print_encoding();
1755 test_range_encoding();
Pau Espin Pedrolb99f4ca2019-10-31 13:35:22 +01001756 test_power_ctrl();
Stefan Sperlingfdf8b7b2018-07-27 12:19:15 +02001757
Holger Hans Peter Freythercd252e32013-07-03 09:56:53 +02001758 return EXIT_SUCCESS;
Harald Weltec8a0b932012-08-24 21:27:26 +02001759}