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