blob: 488cd198cdfa1ed8681cffce72871d875b7eff0b [file] [log] [blame]
Neels Hofmeyr6a29d322017-01-25 15:04:16 +01001/* Osmocom MSC+VLR end-to-end tests */
2
3/* (C) 2017 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
4 *
5 * All Rights Reserved
6 *
7 * Author: Neels Hofmeyr <nhofmeyr@sysmocom.de>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU Affero General Public License as published by
11 * the Free Software Foundation; either version 3 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU Affero General Public License for more details.
18 *
19 * You should have received a copy of the GNU Affero General Public License
20 * along with this program. If not, see <http://www.gnu.org/licenses/>.
21 *
22 */
23
24#include <getopt.h>
25#include <stdlib.h>
26
27#include <osmocom/core/logging.h>
28#include <osmocom/core/utils.h>
29#include <osmocom/core/msgb.h>
30#include <osmocom/core/application.h>
31#include <osmocom/gsm/protocol/gsm_04_11.h>
32#include <osmocom/gsm/gsup.h>
Neels Hofmeyrc4628a32018-12-07 14:47:34 +010033#include <osmocom/msc/gsup_client_mux.h>
Neels Hofmeyr90843962017-09-04 15:04:35 +020034#include <osmocom/msc/gsm_04_11.h>
35#include <osmocom/msc/debug.h>
Max43b01b02017-09-15 11:22:30 +020036#include <osmocom/msc/gsm_04_08.h>
Neels Hofmeyra99b4272017-11-21 17:13:23 +010037#include <osmocom/msc/transaction.h>
Neels Hofmeyrc4628a32018-12-07 14:47:34 +010038#include <osmocom/msc/ran_msg.h>
39#include <osmocom/msc/msc_a.h>
40#include <osmocom/msc/msc_i.h>
41#include <osmocom/msc/msc_t.h>
42#include <osmocom/msc/call_leg.h>
43#include <osmocom/msc/rtp_stream.h>
Neels Hofmeyr6a29d322017-01-25 15:04:16 +010044
45#include "msc_vlr_tests.h"
46
Neels Hofmeyrc01e9092018-03-22 15:56:49 +010047void *msc_vlr_tests_ctx = NULL;
48
Neels Hofmeyr6a29d322017-01-25 15:04:16 +010049bool _log_lines = false;
50
51struct gsm_network *net = NULL;
52
Neels Hofmeyr6a29d322017-01-25 15:04:16 +010053const char *gsup_tx_expected = NULL;
54bool gsup_tx_confirmed;
55
56struct msgb *dtap_tx_expected = NULL;
57bool dtap_tx_confirmed;
58
59enum result_sent lu_result_sent;
60enum result_sent cm_service_result_sent;
61bool auth_request_sent;
62const char *auth_request_expect_rand;
63const char *auth_request_expect_autn;
64bool cipher_mode_cmd_sent;
65bool cipher_mode_cmd_sent_with_imeisv;
Neels Hofmeyrdbabfd32018-03-10 02:06:47 +010066const char *cipher_mode_expect_kc;
67bool security_mode_ctrl_sent;
68const char *security_mode_expect_ck;
69const char *security_mode_expect_ik;
Neels Hofmeyr6a29d322017-01-25 15:04:16 +010070
Philipp Maierfbf66102017-04-09 12:32:51 +020071bool iu_release_expected = false;
72bool iu_release_sent = false;
73bool bssap_clear_expected = false;
74bool bssap_clear_sent = false;
75
Neels Hofmeyra99b4272017-11-21 17:13:23 +010076uint32_t cc_to_mncc_tx_expected_msg_type = 0;
77const char *cc_to_mncc_tx_expected_imsi = NULL;
78bool cc_to_mncc_tx_confirmed = false;
79uint32_t cc_to_mncc_tx_got_callref = 0;
80
Neels Hofmeyrc4628a32018-12-07 14:47:34 +010081extern int ran_dec_dtap_undup_pdisc_ctr_bin(uint8_t pdisc);
Harald Weltec2007852018-02-03 21:08:26 +010082
83/* static state variables for the L3 send sequence numbers */
84static uint8_t n_sd[4];
85
86/* patch a correct send sequence number into the given message */
87static void patch_l3_seq_nr(struct msgb *msg)
88{
89 struct gsm48_hdr *gh = msgb_l3(msg);
90 uint8_t pdisc = gsm48_hdr_pdisc(gh);
91 uint8_t *msg_type_oct = &msg->l3h[1];
Neels Hofmeyrc4628a32018-12-07 14:47:34 +010092 int bin = ran_dec_dtap_undup_pdisc_ctr_bin(pdisc);
Harald Weltec2007852018-02-03 21:08:26 +010093
94 if (bin >= 0 && bin < ARRAY_SIZE(n_sd)) {
95 /* patch in n_sd into the msg_type octet */
96 *msg_type_oct = (*msg_type_oct & 0x3f) | ((n_sd[bin] & 0x3) << 6);
97 //fprintf(stderr, "pdisc=0x%02x bin=%d, patched n_sd=%u\n\n", pdisc, bin, n_sd[bin] & 3);
98 /* increment N(SD) */
99 n_sd[bin] = (n_sd[bin] + 1) % 4;
100 } else {
101 //fprintf(stderr, "pdisc=0x%02x NO SEQ\n\n", pdisc);
102 }
103}
104
105/* reset L3 sequence numbers (e.g. new RR connection) */
106static void reset_l3_seq_nr()
107{
108 memset(n_sd, 0, sizeof(n_sd));
109}
110
Neels Hofmeyr6a29d322017-01-25 15:04:16 +0100111struct msgb *msgb_from_hex(const char *label, uint16_t size, const char *hex)
112{
Neels Hofmeyr3117b702018-09-13 03:23:07 +0200113 struct msgb *msg = msgb_alloc_headroom(size, 4, label);
Neels Hofmeyr6a29d322017-01-25 15:04:16 +0100114 unsigned char *rc;
Neels Hofmeyr3117b702018-09-13 03:23:07 +0200115 msg->l2h = msg->data;
116 rc = msgb_put(msg, osmo_hexparse(hex, msg->data, msgb_tailroom(msg)));
Neels Hofmeyr6a29d322017-01-25 15:04:16 +0100117 OSMO_ASSERT(rc == msg->l2h);
118 return msg;
119}
120
Maxd8d1a9e2018-02-06 15:50:20 +0100121static const char *gh_type_name(struct gsm48_hdr *gh)
Neels Hofmeyr78ada642017-03-10 02:15:20 +0100122{
123 return gsm48_pdisc_msgtype_name(gsm48_hdr_pdisc(gh),
124 gsm48_hdr_msg_type(gh));
125}
126
Neels Hofmeyr6a29d322017-01-25 15:04:16 +0100127void gsup_rx(const char *rx_hex, const char *expect_tx_hex)
128{
129 int rc;
130 struct msgb *msg;
131 const char *label;
132
133 gsup_expect_tx(expect_tx_hex);
134
135 msg = msgb_from_hex("gsup", 1024, rx_hex);
136 label = osmo_gsup_message_type_name(msg->l2h[0]);
137 fprintf(stderr, "<-- GSUP rx %s: %s\n", label,
138 osmo_hexdump_nospc(msgb_l2(msg), msgb_l2len(msg)));
Neels Hofmeyr834f94a2017-09-28 03:07:16 +0200139 /* GSUP read cb takes ownership of msgb */
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100140 rc = gsup_client_mux_rx(net->gcm->gsup_client, msg);
Neels Hofmeyr6a29d322017-01-25 15:04:16 +0100141 fprintf(stderr, "<-- GSUP rx %s: vlr_gsupc_read_cb() returns %d\n",
142 label, rc);
143 if (expect_tx_hex)
144 OSMO_ASSERT(gsup_tx_confirmed);
Neels Hofmeyr6a29d322017-01-25 15:04:16 +0100145}
146
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100147bool conn_exists(const struct msub *msub)
Neels Hofmeyr6a29d322017-01-25 15:04:16 +0100148{
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100149 struct msub *i;
Maxba8a0072018-10-25 17:58:43 +0200150
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100151 if (!msub)
Maxba8a0072018-10-25 17:58:43 +0200152 return false;
153
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100154 llist_for_each_entry(i, &msub_list, entry) {
155 if (i == msub)
Neels Hofmeyr6a29d322017-01-25 15:04:16 +0100156 return true;
157 }
Maxba8a0072018-10-25 17:58:43 +0200158
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100159 btw("msub gone");
Neels Hofmeyr6a29d322017-01-25 15:04:16 +0100160 return false;
161}
162
Vadim Yanitskiy27605852018-06-15 23:57:30 +0700163/* Simplified version of the cm_service_request_concludes() */
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100164void conn_conclude_cm_service_req(struct msub *msub, const char *cm_service_use)
Vadim Yanitskiy27605852018-06-15 23:57:30 +0700165{
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100166 int32_t count;
167 struct msc_a *msc_a = msub_msc_a(msub);
Vadim Yanitskiy27605852018-06-15 23:57:30 +0700168 btw("Concluding CM Service Request");
169
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100170 OSMO_ASSERT(conn_exists(msub));
171 count = osmo_use_count_by(&msc_a->use_count, cm_service_use);
172 OSMO_ASSERT(count > 0);
Vadim Yanitskiy27605852018-06-15 23:57:30 +0700173
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100174 OSMO_ASSERT(osmo_use_count_get_put(&msc_a->use_count, cm_service_use, -count) == 0)
Vadim Yanitskiy27605852018-06-15 23:57:30 +0700175
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100176 ASSERT_RELEASE_CLEAR(msc_a->c.ran->type);
177}
178
179void dummy_msc_i_action(struct osmo_fsm_inst *fi, uint32_t event, void *data)
180{
181}
182
183static const struct osmo_fsm_state dummy_msc_i_states[] = {
184 {
185 .name = "0",
186 .in_event_mask = 0xffffffff,
187 .action = dummy_msc_i_action,
188 },
189};
190
191struct osmo_fsm dummy_msc_i_fsm = {
192 .name = "dummy_msc_i",
193 .states = dummy_msc_i_states,
194 .num_states = ARRAY_SIZE(dummy_msc_i_states),
195 .log_subsys = DMSC,
196 .event_names = msc_i_fsm_event_names,
197};
198
199struct msc_i *dummy_msc_i_alloc(struct msub *msub, struct ran_infra *ran)
200{
201 return msub_role_alloc(g_msub, MSC_ROLE_I, &dummy_msc_i_fsm, struct msc_i, ran);
Vadim Yanitskiy27605852018-06-15 23:57:30 +0700202}
203
Neels Hofmeyr7814a832018-12-26 00:40:18 +0100204enum osmo_rat_type rx_from_ran = OSMO_RAT_GERAN_A;
Neels Hofmeyr6a29d322017-01-25 15:04:16 +0100205
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100206struct msub *g_msub = NULL;
Harald Welte977b5482019-02-18 12:23:43 +0100207
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100208void dtap_expect_tx(const char *hex)
Neels Hofmeyr6a29d322017-01-25 15:04:16 +0100209{
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100210 /* Has the previously expected dtap been received? */
211 OSMO_ASSERT(!dtap_tx_expected);
212 if (!hex)
213 return;
214 dtap_tx_expected = msgb_from_hex("dtap_tx_expected", 1024, hex);
215 /* Mask the sequence number out */
216 if (msgb_length(dtap_tx_expected) >= 2)
217 dtap_tx_expected->data[1] &= 0x3f;
218 dtap_tx_confirmed = false;
Neels Hofmeyr6a29d322017-01-25 15:04:16 +0100219}
220
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100221static int _validate_dtap(struct msgb *msg, enum osmo_rat_type to_ran)
222{
223 struct gsm48_hdr *gh = (void*)msg->data;
224 uint8_t pdisc = gsm48_hdr_pdisc(gh);
225 uint8_t msgt = gsm48_hdr_msg_type(gh);
226
227 btw("DTAP --%s--> MS: %s: %s",
228 osmo_rat_type_name(to_ran), gh_type_name((void*)msg->data),
229 osmo_hexdump_nospc(msg->data, msg->len));
230
231 if (pdisc == GSM48_PDISC_MM
232 && msgt == GSM48_MT_MM_CM_SERV_ACC) {
233 cm_service_result_sent |= RES_ACCEPT;
234 talloc_free(msg);
235 return 0;
236 }
237
238 if (pdisc == GSM48_PDISC_MM
239 && msgt == GSM48_MT_MM_CM_SERV_REJ) {
240 cm_service_result_sent |= RES_REJECT;
241 talloc_free(msg);
242 return 0;
243 }
244
245 OSMO_ASSERT(dtap_tx_expected);
246
247 /* Mask the sequence number out before comparing */
248 msg->data[1] &= 0x3f;
249 if (!msgb_eq_data_print(msg, dtap_tx_expected->data, dtap_tx_expected->len))
250 abort();
251
252 btw("DTAP matches expected message");
253
254 talloc_free(msg);
255 dtap_tx_confirmed = true;
256 talloc_free(dtap_tx_expected);
257 dtap_tx_expected = NULL;
258
259 return 0;
260}
261
262static void bssap_validate_clear_cmd()
263{
264 OSMO_ASSERT(bssap_clear_expected);
265 bssap_clear_expected = false;
266 bssap_clear_sent = true;
267}
268
269static void iucs_validate_clear_cmd()
270{
271 OSMO_ASSERT(iu_release_expected);
272 iu_release_expected = false;
273 iu_release_sent = true;
274}
275
276static int bssap_validate_cipher_mode_cmd(const struct ran_cipher_mode_command *cmd)
277{
278 int i;
279 const char *got_key;
280 cipher_mode_cmd_sent = true;
281 cipher_mode_cmd_sent_with_imeisv = cmd->geran.retrieve_imeisv;
282 btw("sending Ciphering Mode Command: retrieve_imeisv=%d", cipher_mode_cmd_sent_with_imeisv);
283 for (i = 0; i < 7; i++) {
284 if (!(cmd->geran.a5_encryption_mask & (1 << i)))
285 continue;
286 btw("...perm algo: A5/%d", i);
287 }
288 got_key = osmo_hexdump_nospc(cmd->vec->kc, sizeof(cmd->vec->kc));
289 btw("...key: %s", got_key);
290
291 if (!cipher_mode_expect_kc
292 || strcmp(cipher_mode_expect_kc, got_key)) {
293 log("FAILURE: expected kc=%s", cipher_mode_expect_kc ? : "NULL");
294 OSMO_ASSERT(false);
295 }
296 return 0;
297}
298
299static int iucs_validate_security_mode_ctrl(const struct ran_cipher_mode_command *cmd)
300{
301 const char *got_ik;
302 got_ik = osmo_hexdump_nospc(cmd->vec->ik, sizeof(cmd->vec->ik));
303 btw("sending SecurityModeControl: ik=%s", got_ik);
304 security_mode_ctrl_sent = true;
305 if (!security_mode_expect_ik
306 || strcmp(security_mode_expect_ik, got_ik)) {
307 log("FAILURE: expected ik=%s", security_mode_expect_ik ? : "NULL");
308 OSMO_ASSERT(false);
309 }
310 return 0;
311}
312
313struct msgb *dont_ran_encode(struct osmo_fsm_inst *caller_fi, const struct ran_msg *ran_enc_msg)
314{
315 struct msc_role_common *c = caller_fi->priv;
316 enum osmo_rat_type ran_type = c->ran->type;
317 const char *ran_name = osmo_rat_type_name(ran_type);
318 LOG_RAN_ENC(caller_fi, DMSC, LOGL_INFO, "%s on %s\n", ran_msg_type_name(ran_enc_msg->msg_type),
319 ran_name);
320
321 switch (ran_enc_msg->msg_type) {
322 case RAN_MSG_DTAP:
323 _validate_dtap(ran_enc_msg->dtap, ran_type);
324 break;
325 case RAN_MSG_CLEAR_COMMAND:
326 switch (ran_type) {
327 case OSMO_RAT_GERAN_A:
328 bssap_validate_clear_cmd();
329 break;
330 case OSMO_RAT_UTRAN_IU:
331 iucs_validate_clear_cmd();
332 break;
333 default:
334 OSMO_ASSERT(false);
335 }
336 break;
337 case RAN_MSG_CIPHER_MODE_COMMAND:
338 switch (ran_type) {
339 case OSMO_RAT_GERAN_A:
340 bssap_validate_cipher_mode_cmd(&ran_enc_msg->cipher_mode_command);
341 break;
342 case OSMO_RAT_UTRAN_IU:
343 iucs_validate_security_mode_ctrl(&ran_enc_msg->cipher_mode_command);
344 break;
345 default:
346 OSMO_ASSERT(false);
347 }
348 break;
349 default:
350 break;
351 }
352
353 /* We're testing MSC and VLR interaction, not message encoding.
354 * Return whatever. The test msc_i instance is a dummy and drops these.
355 * But it must be msg_free()-able.
356 */
357 return msgb_alloc(1, "unused dummy msg");
358}
359
360struct ran_infra test_ran_infra[] = {
361 [OSMO_RAT_GERAN_A] = {
362 .type = OSMO_RAT_GERAN_A,
363 .an_proto = OSMO_GSUP_ACCESS_NETWORK_PROTOCOL_TS3G_48006,
364 .log_subsys = DBSSAP,
365 .tdefs = msc_tdefs_geran,
366 .ran_encode = dont_ran_encode,
367 },
368 [OSMO_RAT_UTRAN_IU] = {
369 .type = OSMO_RAT_UTRAN_IU,
370 .an_proto = OSMO_GSUP_ACCESS_NETWORK_PROTOCOL_TS3G_25413,
371 .log_subsys = DIUCS,
372 .tdefs = msc_tdefs_utran,
373 .ran_encode = dont_ran_encode,
374 },
375};
376
377static int fake_msc_a_ran_dec(const struct ran_msg *ran_dec_msg)
378{
379 struct msc_a_ran_dec_data d = {
380 .from_role = MSC_ROLE_I,
381 };
382 return msc_a_ran_decode_cb(g_msub->role[MSC_ROLE_A], &d, ran_dec_msg);
383}
Neels Hofmeyr6a29d322017-01-25 15:04:16 +0100384
385void rx_from_ms(struct msgb *msg)
386{
Neels Hofmeyr6a29d322017-01-25 15:04:16 +0100387 struct gsm48_hdr *gh = msgb_l3(msg);
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100388 struct ran_msg ran_dec_msg;
389 struct gsm0808_cell_id cell_id = {
390 .id_discr = CELL_IDENT_LAI_AND_LAC,
391 .id.lai_and_lac = {
392 .plmn = {
393 .mcc = 1,
394 .mnc = 2,
395 },
396 .lac = 23,
397 },
398 };
399 struct msc_a *msc_a;
Neels Hofmeyr78ada642017-03-10 02:15:20 +0100400
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100401 log("MSC <--%s-- MS: %s", osmo_rat_type_name(rx_from_ran), gh_type_name(gh));
Neels Hofmeyr6a29d322017-01-25 15:04:16 +0100402
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100403 if (!conn_exists(g_msub))
404 g_msub = NULL;
Neels Hofmeyr6a29d322017-01-25 15:04:16 +0100405
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100406 if (!g_msub) {
Neels Hofmeyr6a29d322017-01-25 15:04:16 +0100407 log("new conn");
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100408 g_msub = msub_alloc(net);
409 msc_a_alloc(g_msub, &test_ran_infra[rx_from_ran]);
410 dummy_msc_i_alloc(g_msub, &test_ran_infra[rx_from_ran]);
411
Harald Weltec2007852018-02-03 21:08:26 +0100412 reset_l3_seq_nr();
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100413 ran_dec_msg = (struct ran_msg){
414 .msg_type = RAN_MSG_COMPL_L3,
415 .compl_l3 = {
416 .cell_id = &cell_id,
417 .msg = msg,
418 },
419 };
Neels Hofmeyr6a29d322017-01-25 15:04:16 +0100420 } else {
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100421 ran_dec_msg = (struct ran_msg){
422 .msg_type = RAN_MSG_DTAP,
423 .dtap = msg,
424 };
Neels Hofmeyr6a29d322017-01-25 15:04:16 +0100425 }
426
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100427 msc_a = msub_msc_a(g_msub);
428 msc_a_get(msc_a, __func__);
429
430 patch_l3_seq_nr(msg);
431 fake_msc_a_ran_dec(&ran_dec_msg);
432
433 msc_a_put(msc_a, __func__);
434
435 if (!conn_exists(g_msub))
436 g_msub = NULL;
Neels Hofmeyr6a29d322017-01-25 15:04:16 +0100437}
438
439void ms_sends_msg(const char *hex)
440{
441 struct msgb *msg;
442
443 msg = msgb_from_hex("ms_sends_msg", 1024, hex);
444 msg->l1h = msg->l2h = msg->l3h = msg->data;
445 rx_from_ms(msg);
Neels Hofmeyr3117b702018-09-13 03:23:07 +0200446 msgb_free(msg);
447}
448
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100449void ms_sends_classmark_update(const struct osmo_gsm48_classmark *classmark)
Neels Hofmeyr3117b702018-09-13 03:23:07 +0200450{
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100451 struct ran_msg ran_dec = {
452 .msg_type = RAN_MSG_CLASSMARK_UPDATE,
453 .classmark_update = {
454 .classmark = classmark,
455 },
456 };
457 fake_msc_a_ran_dec(&ran_dec);
Neels Hofmeyr6a29d322017-01-25 15:04:16 +0100458}
459
Maxd8d1a9e2018-02-06 15:50:20 +0100460static int ms_sends_msg_fake(uint8_t pdisc, uint8_t msg_type)
Neels Hofmeyr6a29d322017-01-25 15:04:16 +0100461{
462 int rc;
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100463 struct ran_msg ran_dec;
Neels Hofmeyr6a29d322017-01-25 15:04:16 +0100464 struct msgb *msg;
465 struct gsm48_hdr *gh;
466
467 msg = msgb_alloc(1024, "ms_sends_msg_fake");
468 msg->l1h = msg->l2h = msg->l3h = msg->data;
469
470 gh = (struct gsm48_hdr*)msgb_put(msg, sizeof(*gh));
471 gh->proto_discr = pdisc;
472 gh->msg_type = msg_type;
473 /* some amount of data, whatever */
474 msgb_put(msg, 123);
475
Harald Weltec2007852018-02-03 21:08:26 +0100476 patch_l3_seq_nr(msg);
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100477
478 ran_dec = (struct ran_msg){
479 .msg_type = RAN_MSG_DTAP,
480 .dtap = msg,
481 };
482 rc = fake_msc_a_ran_dec(&ran_dec);
Neels Hofmeyr6a29d322017-01-25 15:04:16 +0100483
484 talloc_free(msg);
485 return rc;
486}
487
Max68171902018-02-06 17:55:19 +0100488static inline void ms_msg_log_err(uint8_t val, uint8_t msgtype)
489{
490 int rc = ms_sends_msg_fake(val, msgtype);
491 if (rc != -EACCES)
492 log("Unexpected return value %u != %u for %s/%s",
493 -rc, -EACCES, gsm48_pdisc_name(val), gsm48_cc_msg_name(msgtype));
494}
495
Neels Hofmeyr6a29d322017-01-25 15:04:16 +0100496void thwart_rx_non_initial_requests()
497{
498 log("requests shall be thwarted");
Max68171902018-02-06 17:55:19 +0100499
500 ms_msg_log_err(GSM48_PDISC_CC, GSM48_MT_CC_SETUP);
501 ms_msg_log_err(GSM48_PDISC_MM, 0x33); /* nonexistent */
502 ms_msg_log_err(GSM48_PDISC_RR, GSM48_MT_RR_SYSINFO_1);
503 ms_msg_log_err(GSM48_PDISC_SMS, GSM411_MT_CP_DATA);
Neels Hofmeyr6a29d322017-01-25 15:04:16 +0100504}
505
506void send_sms(struct vlr_subscr *receiver,
507 struct vlr_subscr *sender,
508 char *str)
509{
Harald Welte39b55482018-04-09 19:19:33 +0200510 struct gsm_sms *sms = sms_from_text(receiver, sender->msisdn, 0, str);
Vadim Yanitskiy24e025e2018-11-22 15:42:39 +0700511 gsm411_send_sms(net, receiver, sms);
Neels Hofmeyr6a29d322017-01-25 15:04:16 +0100512}
513
514unsigned char next_rand_byte = 0;
Max753c15d2017-12-21 14:50:44 +0100515/* override, requires '-Wl,--wrap=osmo_get_rand_id' */
516int __real_osmo_get_rand_id(uint8_t *buf, size_t num);
517int __wrap_osmo_get_rand_id(uint8_t *buf, size_t num)
Neels Hofmeyr6a29d322017-01-25 15:04:16 +0100518{
Max753c15d2017-12-21 14:50:44 +0100519 size_t i;
Neels Hofmeyr6a29d322017-01-25 15:04:16 +0100520 for (i = 0; i < num; i++)
521 buf[i] = next_rand_byte++;
522 return 1;
523}
524
525/* override, requires '-Wl,--wrap=gsm340_gen_scts' */
526void __real_gsm340_gen_scts(uint8_t *scts, time_t time);
527void __wrap_gsm340_gen_scts(uint8_t *scts, time_t time)
528{
Neels Hofmeyr05230ea2017-08-22 18:06:42 +0200529 /* Write fixed time bytes for deterministic test results */
530 osmo_hexparse("07101000000000", scts, 7);
Neels Hofmeyr6a29d322017-01-25 15:04:16 +0100531}
532
533const char *paging_expecting_imsi = NULL;
534uint32_t paging_expecting_tmsi;
535bool paging_sent;
Neels Hofmeyr6a29d322017-01-25 15:04:16 +0100536
537void paging_expect_imsi(const char *imsi)
538{
539 paging_expecting_imsi = imsi;
540 paging_expecting_tmsi = GSM_RESERVED_TMSI;
541}
542
543void paging_expect_tmsi(uint32_t tmsi)
544{
545 paging_expecting_tmsi = tmsi;
546 paging_expecting_imsi = NULL;
547}
548
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100549/* override, requires '-Wl,--wrap=ran_peers_down_paging' */
550int __real_ran_peers_down_paging(struct sccp_ran_inst *sri, enum CELL_IDENT page_where, struct vlr_subscr *vsub,
551 enum paging_cause cause);
552int __wrap_ran_peers_down_paging(struct sccp_ran_inst *sri, enum CELL_IDENT page_where, struct vlr_subscr *vsub,
553 enum paging_cause cause)
Neels Hofmeyr6a29d322017-01-25 15:04:16 +0100554{
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100555 log("paging request (%s) to %s on %s", paging_cause_name(cause), vlr_subscr_name(vsub),
556 osmo_rat_type_name(sri->ran->type));
557
Neels Hofmeyr6a29d322017-01-25 15:04:16 +0100558 OSMO_ASSERT(paging_expecting_imsi || (paging_expecting_tmsi != GSM_RESERVED_TMSI));
559 if (paging_expecting_imsi)
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100560 VERBOSE_ASSERT(strcmp(paging_expecting_imsi, vsub->imsi), == 0, "%d");
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200561 if (paging_expecting_tmsi != GSM_RESERVED_TMSI) {
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100562 VERBOSE_ASSERT(paging_expecting_tmsi, == vsub->tmsi, "0x%08x");
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200563 }
Neels Hofmeyr6a29d322017-01-25 15:04:16 +0100564 paging_sent = true;
Neels Hofmeyr6a29d322017-01-25 15:04:16 +0100565 return 1;
566}
567
Neels Hofmeyr6a29d322017-01-25 15:04:16 +0100568void clear_vlr()
569{
570 struct vlr_subscr *vsub, *n;
571 llist_for_each_entry_safe(vsub, n, &net->vlr->subscribers, list) {
572 vlr_subscr_free(vsub);
573 }
574
575 net->authentication_required = false;
Harald Welte7b222aa2017-12-23 19:30:32 +0100576 net->a5_encryption_mask = (1 << 0);
Neels Hofmeyr6a29d322017-01-25 15:04:16 +0100577 net->vlr->cfg.check_imei_rqd = false;
578 net->vlr->cfg.assign_tmsi = false;
Neels Hofmeyr54a706c2017-07-18 15:39:27 +0200579 net->vlr->cfg.retrieve_imeisv_early = false;
580 net->vlr->cfg.retrieve_imeisv_ciphered = false;
Neels Hofmeyr7b1418e2017-10-29 02:12:16 +0100581 net->vlr->cfg.auth_tuple_max_reuse_count = 0;
582 net->vlr->cfg.auth_reuse_old_sets_on_error = false;
Neels Hofmeyr6a29d322017-01-25 15:04:16 +0100583
Neels Hofmeyr7814a832018-12-26 00:40:18 +0100584 rx_from_ran = OSMO_RAT_GERAN_A;
Neels Hofmeyr6a29d322017-01-25 15:04:16 +0100585 auth_request_sent = false;
586 auth_request_expect_rand = NULL;
587 auth_request_expect_autn = NULL;
588
Neels Hofmeyrdbabfd32018-03-10 02:06:47 +0100589 cipher_mode_cmd_sent = false;
590 cipher_mode_cmd_sent_with_imeisv = false;
591 cipher_mode_expect_kc = NULL;
592
593 security_mode_ctrl_sent = false;
594 security_mode_expect_ck = NULL;
595 security_mode_expect_ik = NULL;
596
Neels Hofmeyr6a29d322017-01-25 15:04:16 +0100597 next_rand_byte = 0;
598
Philipp Maierfbf66102017-04-09 12:32:51 +0200599 iu_release_expected = false;
600 iu_release_sent = false;
601 bssap_clear_expected = false;
602 bssap_clear_sent = false;
603
Neels Hofmeyr6a29d322017-01-25 15:04:16 +0100604 osmo_gettimeofday_override = false;
605}
606
607static struct log_info_cat test_categories[] = {
608 [DMSC] = {
609 .name = "DMSC",
610 .description = "Mobile Switching Center",
611 .enabled = 1, .loglevel = LOGL_DEBUG,
612 },
613 [DRLL] = {
614 .name = "DRLL",
615 .description = "A-bis Radio Link Layer (RLL)",
616 .enabled = 1, .loglevel = LOGL_DEBUG,
617 },
618 [DMM] = {
619 .name = "DMM",
620 .description = "Layer3 Mobility Management (MM)",
621 .enabled = 1, .loglevel = LOGL_DEBUG,
622 },
623 [DRR] = {
624 .name = "DRR",
625 .description = "Layer3 Radio Resource (RR)",
626 .enabled = 1, .loglevel = LOGL_DEBUG,
627 },
628 [DCC] = {
629 .name = "DCC",
630 .description = "Layer3 Call Control (CC)",
Neels Hofmeyr12e17be2018-03-12 23:59:37 +0100631 .enabled = 1, .loglevel = LOGL_DEBUG,
Neels Hofmeyr6a29d322017-01-25 15:04:16 +0100632 },
Neels Hofmeyr6a29d322017-01-25 15:04:16 +0100633 [DVLR] = {
634 .name = "DVLR",
635 .description = "Visitor Location Register",
636 .enabled = 1, .loglevel = LOGL_DEBUG,
637 },
638 [DREF] = {
639 .name = "DREF",
640 .description = "Reference Counting",
641 .enabled = 1, .loglevel = LOGL_DEBUG,
642 },
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200643 [DPAG] = {
644 .name = "DPAG",
645 .description = "Paging Subsystem",
646 .enabled = 1, .loglevel = LOGL_DEBUG,
647 },
648 [DIUCS] = {
649 .name = "DIUCS",
650 .description = "Iu-CS Protocol",
651 .enabled = 1, .loglevel = LOGL_DEBUG,
652 },
Neels Hofmeyra99b4272017-11-21 17:13:23 +0100653 [DMNCC] = {
654 .name = "DMNCC",
655 .description = "MNCC API for Call Control application",
656 .enabled = 1, .loglevel = LOGL_DEBUG,
657 },
Neels Hofmeyr46c06e22019-01-04 17:42:05 +0100658 [DBSSAP] = {
659 .name = "DBSSAP",
660 .description = "BSSAP Protocol (A Interface)",
661 .enabled = 1, .loglevel = LOGL_DEBUG,
662 },
Neels Hofmeyr979b0572019-05-09 15:24:49 +0200663 [DSS] = {
664 .name = "DSS",
665 .description = "Supplementary Services",
666 .enabled = 1, .loglevel = LOGL_DEBUG,
667 },
Neels Hofmeyr6a29d322017-01-25 15:04:16 +0100668};
669
670static struct log_info info = {
671 .cat = test_categories,
672 .num_cat = ARRAY_SIZE(test_categories),
673};
674
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100675struct gsm_mncc *on_call_release_mncc_sends_to_cc_data = NULL;
676
Neels Hofmeyra99b4272017-11-21 17:13:23 +0100677int mncc_recv(struct gsm_network *net, struct msgb *msg)
Neels Hofmeyr6a29d322017-01-25 15:04:16 +0100678{
Neels Hofmeyra99b4272017-11-21 17:13:23 +0100679 struct gsm_mncc *mncc = (void*)msg->data;
680 log("MSC --> MNCC: callref 0x%x: %s", mncc->callref,
681 get_mncc_name(mncc->msg_type));
682
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100683 if (mncc->msg_type == MNCC_REL_IND && on_call_release_mncc_sends_to_cc_data) {
684
685 log("MNCC: callref 0x%x: Call Release triggering %s", mncc->callref,
686 get_mncc_name(on_call_release_mncc_sends_to_cc_data->msg_type));
687
Neels Hofmeyr52558742019-05-09 01:23:09 +0200688 mncc_tx_to_cc(net,
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100689 on_call_release_mncc_sends_to_cc_data);
690
691 on_call_release_mncc_sends_to_cc_data = NULL;
692 return 0;
693 }
694
Neels Hofmeyra99b4272017-11-21 17:13:23 +0100695 OSMO_ASSERT(cc_to_mncc_tx_expected_msg_type);
696 if (cc_to_mncc_tx_expected_msg_type != mncc->msg_type) {
697 log("Mismatch! Expected MNCC msg type: %s",
698 get_mncc_name(cc_to_mncc_tx_expected_msg_type));
699 abort();
700 }
701
702 if (strcmp(cc_to_mncc_tx_expected_imsi, mncc->imsi)) {
703 log("Mismatch! Expected MNCC msg IMSI: '%s', got '%s'",
704 cc_to_mncc_tx_expected_imsi,
705 mncc->imsi);
706 abort();
707 }
708
709 cc_to_mncc_tx_confirmed = true;
710 cc_to_mncc_tx_got_callref = mncc->callref;
711 cc_to_mncc_tx_expected_imsi = NULL;
712 cc_to_mncc_tx_expected_msg_type = 0;
713 talloc_free(msg);
Neels Hofmeyr6a29d322017-01-25 15:04:16 +0100714 return 0;
715}
716
Harald Welte1ea6baf2018-07-31 19:40:52 +0200717struct osmo_gsup_client *
Stefan Sperlingafa030d2018-12-06 12:06:59 +0100718__real_osmo_gsup_client_create2(struct ipaccess_unit *ipa_dev, const char *ip_addr,
719 unsigned int tcp_port, osmo_gsup_client_read_cb_t read_cb,
720 struct osmo_oap_client_config *oap_config);
Harald Welte1ea6baf2018-07-31 19:40:52 +0200721struct osmo_gsup_client *
Stefan Sperlingafa030d2018-12-06 12:06:59 +0100722__wrap_osmo_gsup_client_create2(struct ipaccess_unit *ipa_dev, const char *ip_addr,
723 unsigned int tcp_port, osmo_gsup_client_read_cb_t read_cb,
724 struct osmo_oap_client_config *oap_config)
Neels Hofmeyr6a29d322017-01-25 15:04:16 +0100725{
Harald Welte1ea6baf2018-07-31 19:40:52 +0200726 struct osmo_gsup_client *gsupc;
727 gsupc = talloc_zero(msc_vlr_tests_ctx, struct osmo_gsup_client);
Neels Hofmeyr6a29d322017-01-25 15:04:16 +0100728 OSMO_ASSERT(gsupc);
729 return gsupc;
730}
731
732/* override, requires '-Wl,--wrap=gsup_client_send' */
Harald Welte1ea6baf2018-07-31 19:40:52 +0200733int __real_osmo_gsup_client_send(struct osmo_gsup_client *gsupc, struct msgb *msg);
734int __wrap_osmo_gsup_client_send(struct osmo_gsup_client *gsupc, struct msgb *msg)
Neels Hofmeyr6a29d322017-01-25 15:04:16 +0100735{
Max34d306b2019-01-15 18:37:31 +0100736 uint8_t buf[512];
737 int len;
738
Neels Hofmeyr6a29d322017-01-25 15:04:16 +0100739 fprintf(stderr, "GSUP --> HLR: %s: %s\n",
Max34d306b2019-01-15 18:37:31 +0100740 osmo_gsup_message_type_name(msg->data[0]), osmo_hexdump_nospc(msg->data, msg->len));
Neels Hofmeyr6a29d322017-01-25 15:04:16 +0100741
742 OSMO_ASSERT(gsup_tx_expected);
Max34d306b2019-01-15 18:37:31 +0100743 OSMO_ASSERT(strlen(gsup_tx_expected) <= (sizeof(buf) * 2));
744
745 len = osmo_hexparse(gsup_tx_expected, buf, sizeof(buf));
746 if (len < 1)
Neels Hofmeyr6a29d322017-01-25 15:04:16 +0100747 abort();
Max34d306b2019-01-15 18:37:31 +0100748
749 if (!msgb_eq_data_print(msg, buf, len))
750 abort();
Neels Hofmeyr6a29d322017-01-25 15:04:16 +0100751
752 talloc_free(msg);
753 gsup_tx_confirmed = true;
754 gsup_tx_expected = NULL;
755 return 0;
756}
757
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100758/* override, requires '-Wl,--wrap=call_leg_ensure_ci' */
759int __real_call_leg_ensure_ci(struct call_leg *cl, enum rtp_direction dir, uint32_t call_id, struct gsm_trans *for_trans);
760int __wrap_call_leg_ensure_ci(struct call_leg *cl, enum rtp_direction dir, uint32_t call_id, struct gsm_trans *for_trans)
Neels Hofmeyr6a29d322017-01-25 15:04:16 +0100761{
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100762 log("MS <--Call Assignment-- MSC: callref=0x%x", call_id);
Neels Hofmeyr6a29d322017-01-25 15:04:16 +0100763 return 0;
764}
765
766static int fake_vlr_tx_lu_acc(void *msc_conn_ref, uint32_t send_tmsi)
767{
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100768 struct msc_a *msc_a = msc_conn_ref;
Neels Hofmeyr6a29d322017-01-25 15:04:16 +0100769 if (send_tmsi == GSM_RESERVED_TMSI)
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100770 btw("sending LU Accept for %s", msc_a->c.fi->id);
Neels Hofmeyr6a29d322017-01-25 15:04:16 +0100771 else
772 btw("sending LU Accept for %s, with TMSI 0x%08x",
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100773 msc_a->c.fi->id, send_tmsi);
Neels Hofmeyr6a29d322017-01-25 15:04:16 +0100774 lu_result_sent |= RES_ACCEPT;
775 return 0;
776}
777
Neels Hofmeyr15809592018-04-06 02:57:51 +0200778static int fake_vlr_tx_lu_rej(void *msc_conn_ref, enum gsm48_reject_value cause)
Neels Hofmeyr6a29d322017-01-25 15:04:16 +0100779{
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100780 struct msc_a *msc_a = msc_conn_ref;
781 btw("sending LU Reject for %s, cause %u", msc_a->c.fi->id, cause);
Neels Hofmeyr6a29d322017-01-25 15:04:16 +0100782 lu_result_sent |= RES_REJECT;
783 return 0;
784}
785
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100786static int fake_vlr_tx_cm_serv_rej(void *msc_conn_ref, enum osmo_cm_service_type cm_service_type,
787 enum gsm48_reject_value cause)
Neels Hofmeyr6a29d322017-01-25 15:04:16 +0100788{
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100789 struct msc_a *msc_a = msc_conn_ref;
790 btw("sending CM Service Reject (%s) for %s, cause: %s",
791 osmo_cm_service_type_name(cm_service_type), msc_a->c.fi->id, gsm48_reject_value_name(cause));
Neels Hofmeyr6a29d322017-01-25 15:04:16 +0100792 cm_service_result_sent |= RES_REJECT;
793 return 0;
794}
795
Neels Hofmeyr8b6e5362018-11-30 02:57:33 +0100796static int fake_vlr_tx_auth_req(void *msc_conn_ref, struct vlr_auth_tuple *at,
Neels Hofmeyr6a29d322017-01-25 15:04:16 +0100797 bool send_autn)
798{
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100799 struct msc_a *msc_a = msc_conn_ref;
Neels Hofmeyr6a29d322017-01-25 15:04:16 +0100800 char *hex;
801 bool ok = true;
802 btw("sending %s Auth Request for %s: tuple use_count=%d key_seq=%d auth_types=0x%x and...",
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100803 send_autn? "UMTS" : "GSM", msc_a->c.fi->id,
Neels Hofmeyr6a29d322017-01-25 15:04:16 +0100804 at->use_count, at->key_seq, at->vec.auth_types);
805
806 hex = osmo_hexdump_nospc((void*)&at->vec.rand, sizeof(at->vec.rand));
807 btw("...rand=%s", hex);
808 if (!auth_request_expect_rand
809 || strcmp(hex, auth_request_expect_rand) != 0) {
810 ok = false;
811 log("FAILURE: expected rand=%s",
812 auth_request_expect_rand ? auth_request_expect_rand : "-");
813 }
814
815 if (send_autn) {
816 hex = osmo_hexdump_nospc((void*)&at->vec.autn, sizeof(at->vec.autn));
817 btw("...autn=%s", hex);
818 if (!auth_request_expect_autn
819 || strcmp(hex, auth_request_expect_autn) != 0) {
820 ok = false;
821 log("FAILURE: expected autn=%s",
822 auth_request_expect_autn ? auth_request_expect_autn : "-");
823 }
824 } else if (auth_request_expect_autn) {
825 ok = false;
826 log("FAILURE: no AUTN sent, expected AUTN = %s",
827 auth_request_expect_autn);
828 }
829
830 if (send_autn)
831 btw("...expecting res=%s",
832 osmo_hexdump_nospc((void*)&at->vec.res, at->vec.res_len));
833 else
834 btw("...expecting sres=%s",
835 osmo_hexdump_nospc((void*)&at->vec.sres, sizeof(at->vec.sres)));
836
837 auth_request_sent = ok;
838 return 0;
839}
840
841static int fake_vlr_tx_auth_rej(void *msc_conn_ref)
842{
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100843 struct msc_a *msc_a = msc_conn_ref;
844 btw("sending Auth Reject for %s", msc_a->c.fi->id);
Neels Hofmeyr6a29d322017-01-25 15:04:16 +0100845 return 0;
846}
847
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100848void ms_sends_ciphering_mode_complete(const char *inner_ran_msg)
Neels Hofmeyrda21a522018-03-02 01:50:09 +0100849{
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100850 struct ran_msg ran_dec;
Neels Hofmeyrdbabfd32018-03-10 02:06:47 +0100851
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100852 msc_a_get(msub_msc_a(g_msub), __func__);
853
854 ran_dec = (struct ran_msg){
855 .msg_type = RAN_MSG_CIPHER_MODE_COMPLETE,
856 };
857 fake_msc_a_ran_dec(&ran_dec);
858
859 if (inner_ran_msg) {
860 struct msgb *msg = msgb_from_hex("cipher_mode_complete_ran", 1024, inner_ran_msg);
861 msg->l1h = msg->l2h = msg->l3h = msg->data;
862 ran_dec = (struct ran_msg){
863 .msg_type = RAN_MSG_DTAP,
864 .dtap = msg,
865 };
866 patch_l3_seq_nr(msg);
867 fake_msc_a_ran_dec(&ran_dec);
868 msgb_free(msg);
Neels Hofmeyrdbabfd32018-03-10 02:06:47 +0100869 }
Neels Hofmeyrda21a522018-03-02 01:50:09 +0100870
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100871 msc_a_put(msub_msc_a(g_msub), __func__);
Neels Hofmeyrda21a522018-03-02 01:50:09 +0100872
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100873 if (!conn_exists(g_msub))
874 g_msub = NULL;
Neels Hofmeyr6a29d322017-01-25 15:04:16 +0100875}
876
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200877void ms_sends_security_mode_complete()
878{
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100879 struct ran_msg ran_dec;
880
881 ran_dec = (struct ran_msg){
882 .msg_type = RAN_MSG_CIPHER_MODE_COMPLETE,
883 };
884 fake_msc_a_ran_dec(&ran_dec);
885
886 if (!conn_exists(g_msub))
887 g_msub = NULL;
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200888}
889
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100890void ran_sends_clear_complete()
Neels Hofmeyr4068ab22018-04-01 20:55:54 +0200891{
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100892 struct ran_msg ran_dec;
Neels Hofmeyr4068ab22018-04-01 20:55:54 +0200893
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100894 ran_dec = (struct ran_msg){
895 .msg_type = RAN_MSG_CLEAR_COMPLETE,
896 };
897 fake_msc_a_ran_dec(&ran_dec);
898
899 if (!conn_exists(g_msub))
900 g_msub = NULL;
Neels Hofmeyr4068ab22018-04-01 20:55:54 +0200901}
902
Neels Hofmeyr6a29d322017-01-25 15:04:16 +0100903const struct timeval fake_time_start_time = { 123, 456 };
904
905void fake_time_start()
906{
Stefan Sperlingdefc3c82018-05-15 14:48:04 +0200907 struct timespec *clock_override;
908
Neels Hofmeyr6a29d322017-01-25 15:04:16 +0100909 osmo_gettimeofday_override_time = fake_time_start_time;
910 osmo_gettimeofday_override = true;
Stefan Sperlingdefc3c82018-05-15 14:48:04 +0200911 clock_override = osmo_clock_override_gettimespec(CLOCK_MONOTONIC);
912 OSMO_ASSERT(clock_override);
913 clock_override->tv_sec = fake_time_start_time.tv_sec;
914 clock_override->tv_nsec = fake_time_start_time.tv_usec * 1000;
915 osmo_clock_override_enable(CLOCK_MONOTONIC, true);
Neels Hofmeyr6a29d322017-01-25 15:04:16 +0100916 fake_time_passes(0, 0);
917}
918
Neels Hofmeyr08b38282018-03-30 23:04:04 +0200919static void check_talloc(void *msgb_ctx, void *msc_vlr_tests_ctx)
Neels Hofmeyr6a29d322017-01-25 15:04:16 +0100920{
Neels Hofmeyr08b38282018-03-30 23:04:04 +0200921 /* Verifying that the msgb context is empty */
Neels Hofmeyr6a29d322017-01-25 15:04:16 +0100922 talloc_report_full(msgb_ctx, stderr);
Neels Hofmeyrc01e9092018-03-22 15:56:49 +0100923 /* Expecting these to stick around in msc_vlr_tests_ctx:
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100924 * full talloc report on 'msgb' (total 0 bytes in 1 blocks)
925 * talloc_total_blocks(tall_bsc_ctx) == 17
926 * full talloc report on 'msc_vlr_tests_ctx' (total 6336 bytes in 17 blocks)
927 * struct osmo_gsup_client contains 256 bytes in 1 blocks (ref 0) 0x613000000260
928 * struct gsm_network contains 4647 bytes in 9 blocks (ref 0) 0x6190000000e0
929 * struct mgcp_client contains 688 bytes in 1 blocks (ref 0) 0x6180000000e0
930 * struct sccp_ran_inst contains 152 bytes in 1 blocks (ref 0) 0x611000000460
931 * struct sccp_ran_inst contains 152 bytes in 1 blocks (ref 0) 0x611000000320
932 * struct gsup_client_mux contains 200 bytes in 2 blocks (ref 0) 0x6110000001e0
933 * struct ipaccess_unit contains 64 bytes in 1 blocks (ref 0) 0x60e000023180
934 * struct vlr_instance contains 248 bytes in 1 blocks (ref 0) 0x6130000000a0
935 * no_gsup_server contains 15 bytes in 1 blocks (ref 0) 0x60b000000150
936 * ../../../src/libosmocore/src/rate_ctr.c:234 contains 2352 bytes in 1 blocks (ref 0) 0x61e0000000e0
937 * logging contains 1433 bytes in 5 blocks (ref 0) 0x60b0000000a0
938 * struct log_target contains 240 bytes in 2 blocks (ref 0) 0x6120000000a0
939 * struct log_category contains 72 bytes in 1 blocks (ref 0) 0x60f0000000a0
940 * struct log_info contains 1192 bytes in 2 blocks (ref 0) 0x60d0000000a0
941 * struct log_info_cat contains 1152 bytes in 1 blocks (ref 0) 0x61a0000000e0
942 * msgb contains 0 bytes in 1 blocks (ref 0) 0x608000000100
Neels Hofmeyr08b38282018-03-30 23:04:04 +0200943 */
Neels Hofmeyr6a29d322017-01-25 15:04:16 +0100944 fprintf(stderr, "talloc_total_blocks(tall_bsc_ctx) == %zu\n",
Neels Hofmeyrc01e9092018-03-22 15:56:49 +0100945 talloc_total_blocks(msc_vlr_tests_ctx));
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100946 if (talloc_total_blocks(msc_vlr_tests_ctx) != 17)
Neels Hofmeyrc01e9092018-03-22 15:56:49 +0100947 talloc_report_full(msc_vlr_tests_ctx, stderr);
Neels Hofmeyr6a29d322017-01-25 15:04:16 +0100948 fprintf(stderr, "\n");
949}
950
951static struct {
952 bool verbose;
953 int run_test_nr;
954} cmdline_opts = {
955 .verbose = false,
956 .run_test_nr = -1,
957};
958
959static void print_help(const char *program)
960{
961 printf("Usage:\n"
962 " %s [-v] [N [N...]]\n"
963 "Options:\n"
964 " -h --help show this text.\n"
965 " -v --verbose print source file and line numbers\n"
966 " N run only the Nth test (first test is N=1)\n",
967 program
968 );
969}
970
971static void handle_options(int argc, char **argv)
972{
973 while (1) {
974 int option_index = 0, c;
975 static struct option long_options[] = {
976 {"help", 0, 0, 'h'},
977 {"verbose", 1, 0, 'v'},
978 {0, 0, 0, 0}
979 };
980
981 c = getopt_long(argc, argv, "hv",
982 long_options, &option_index);
983 if (c == -1)
984 break;
985
986 switch (c) {
987 case 'h':
988 print_help(argv[0]);
989 exit(0);
990 case 'v':
991 cmdline_opts.verbose = true;
992 break;
993 default:
994 /* catch unknown options *as well as* missing arguments. */
995 fprintf(stderr, "Error in command line options. Exiting.\n");
996 exit(-1);
997 break;
998 }
999 }
1000}
1001
1002void *msgb_ctx = NULL;
1003
Neels Hofmeyrdfdc61d2018-03-02 00:40:58 +01001004static void run_tests(int nr)
Neels Hofmeyr6a29d322017-01-25 15:04:16 +01001005{
Neels Hofmeyrdfdc61d2018-03-02 00:40:58 +01001006 int test_nr;
Neels Hofmeyr08b38282018-03-30 23:04:04 +02001007
1008 check_talloc(msgb_ctx, msc_vlr_tests_ctx);
1009
Max5e2e9bd2018-02-06 19:31:08 +01001010 nr--; /* arg's first test is 1, in here it's 0 */
1011 for (test_nr = 0; msc_vlr_tests[test_nr]; test_nr++) {
Neels Hofmeyr6a29d322017-01-25 15:04:16 +01001012 if (nr >= 0 && test_nr != nr)
1013 continue;
1014
Neels Hofmeyrdfdc61d2018-03-02 00:40:58 +01001015 if (cmdline_opts.verbose)
1016 fprintf(stderr, "(test nr %d)\n", test_nr + 1);
1017
1018 msc_vlr_tests[test_nr]();
1019
1020 if (cmdline_opts.verbose)
1021 fprintf(stderr, "(test nr %d)\n", test_nr + 1);
Neels Hofmeyr6a29d322017-01-25 15:04:16 +01001022
Neels Hofmeyr08b38282018-03-30 23:04:04 +02001023 check_talloc(msgb_ctx, msc_vlr_tests_ctx);
Max29ce08a2018-02-06 18:46:57 +01001024 }
Neels Hofmeyr6a29d322017-01-25 15:04:16 +01001025}
1026
Max5e60de62018-02-07 12:56:09 +01001027struct gsm_network *test_net(void *ctx)
1028{
Neels Hofmeyr7f484202018-02-27 12:59:45 +01001029 struct gsm_network *net = gsm_network_init(ctx, mncc_recv);
Max5e60de62018-02-07 12:56:09 +01001030
1031 net->gsup_server_addr_str = talloc_strdup(net, "no_gsup_server");
1032 net->gsup_server_port = 0;
1033
1034 OSMO_ASSERT(msc_vlr_alloc(net) == 0);
Max5e60de62018-02-07 12:56:09 +01001035 OSMO_ASSERT(net->vlr);
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001036 OSMO_ASSERT(msc_gsup_client_start(net) == 0);
1037 OSMO_ASSERT(net->gcm);
1038 OSMO_ASSERT(msc_vlr_start(net) == 0);
Max5e60de62018-02-07 12:56:09 +01001039
1040 net->vlr->ops.tx_lu_acc = fake_vlr_tx_lu_acc;
1041 net->vlr->ops.tx_lu_rej = fake_vlr_tx_lu_rej;
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001042 net->vlr->ops.tx_cm_serv_acc = msc_vlr_tx_cm_serv_acc;
Max5e60de62018-02-07 12:56:09 +01001043 net->vlr->ops.tx_cm_serv_rej = fake_vlr_tx_cm_serv_rej;
1044 net->vlr->ops.tx_auth_req = fake_vlr_tx_auth_req;
1045 net->vlr->ops.tx_auth_rej = fake_vlr_tx_auth_rej;
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001046 net->vlr->ops.set_ciph_mode = msc_a_vlr_set_cipher_mode;
1047
1048 /* Allocate fake SCCP Ran Instances */
1049 net->a.sri = talloc_zero(net, struct sccp_ran_inst);
1050 *net->a.sri = (struct sccp_ran_inst){
1051 .ran = &test_ran_infra[OSMO_RAT_GERAN_A],
1052 };
1053 INIT_LLIST_HEAD(&net->a.sri->ran_peers);
1054 INIT_LLIST_HEAD(&net->a.sri->ran_conns);
1055
1056 net->iu.sri = talloc_zero(net, struct sccp_ran_inst);
1057 *net->iu.sri = (struct sccp_ran_inst){
1058 .ran = &test_ran_infra[OSMO_RAT_UTRAN_IU],
1059 };
1060 INIT_LLIST_HEAD(&net->iu.sri->ran_peers);
1061 INIT_LLIST_HEAD(&net->iu.sri->ran_conns);
1062
1063 net->mgw.tdefs = g_mgw_tdefs;
1064 mgcp_client_conf_init(&net->mgw.conf);
1065 net->mgw.tdefs = g_mgw_tdefs;
1066 net->mgw.client = mgcp_client_init(net, &net->mgw.conf);
Max5e60de62018-02-07 12:56:09 +01001067
1068 return net;
1069}
1070
Neels Hofmeyr6a29d322017-01-25 15:04:16 +01001071int main(int argc, char **argv)
1072{
1073 handle_options(argc, argv);
1074
Neels Hofmeyre4f7e712019-03-24 21:07:33 +01001075 osmo_fsm_term_safely(true);
1076
Neels Hofmeyrc01e9092018-03-22 15:56:49 +01001077 msc_vlr_tests_ctx = talloc_named_const(NULL, 0, "msc_vlr_tests_ctx");
1078 msgb_ctx = msgb_talloc_ctx_init(msc_vlr_tests_ctx, 0);
Neels Hofmeyr08b38282018-03-30 23:04:04 +02001079 osmo_init_logging2(msc_vlr_tests_ctx, &info);
Neels Hofmeyr6a29d322017-01-25 15:04:16 +01001080
1081 _log_lines = cmdline_opts.verbose;
1082
1083 OSMO_ASSERT(osmo_stderr_target);
1084 log_set_use_color(osmo_stderr_target, 0);
1085 log_set_print_timestamp(osmo_stderr_target, 0);
Neels Hofmeyr39cb0dd2018-12-18 02:30:18 +01001086 log_set_print_filename(osmo_stderr_target, 0);
Neels Hofmeyr6a29d322017-01-25 15:04:16 +01001087 log_set_print_category(osmo_stderr_target, 1);
Max48131522019-01-16 12:47:39 +01001088 log_set_category_filter(osmo_stderr_target, DLSMS, 1, LOGL_DEBUG);
Neels Hofmeyr6a29d322017-01-25 15:04:16 +01001089
Neels Hofmeyr39cb0dd2018-12-18 02:30:18 +01001090 if (cmdline_opts.verbose) {
Neels Hofmeyr39cb0dd2018-12-18 02:30:18 +01001091 log_set_print_filename2(osmo_stderr_target, LOG_FILENAME_BASENAME);
1092 log_set_print_filename_pos(osmo_stderr_target, LOG_FILENAME_POS_LINE_END);
1093 log_set_use_color(osmo_stderr_target, 1);
1094 log_set_print_level(osmo_stderr_target, 1);
1095 }
Neels Hofmeyr3f5b7802017-12-15 03:49:55 +01001096
Neels Hofmeyrc01e9092018-03-22 15:56:49 +01001097 net = test_net(msc_vlr_tests_ctx);
Neels Hofmeyr6a29d322017-01-25 15:04:16 +01001098
1099 osmo_fsm_log_addr(false);
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001100 osmo_fsm_log_timeouts(cmdline_opts.verbose);
Neels Hofmeyr6a29d322017-01-25 15:04:16 +01001101
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001102 call_leg_init(net);
1103
1104 OSMO_ASSERT(osmo_fsm_register(&dummy_msc_i_fsm) == 0);
Neels Hofmeyr6a29d322017-01-25 15:04:16 +01001105
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001106 clear_vlr();
1107
Neels Hofmeyrdfdc61d2018-03-02 00:40:58 +01001108 if (optind >= argc)
1109 run_tests(-1);
1110 else {
Neels Hofmeyr6a29d322017-01-25 15:04:16 +01001111 int arg;
1112 long int nr;
1113 for (arg = optind; arg < argc; arg++) {
Neels Hofmeyr9c848b52017-11-22 01:59:36 +01001114 errno = 0;
Neels Hofmeyr6a29d322017-01-25 15:04:16 +01001115 nr = strtol(argv[arg], NULL, 10);
1116 if (errno) {
1117 fprintf(stderr, "Invalid argument: %s\n",
1118 argv[arg]);
1119 exit(1);
1120 }
1121
Neels Hofmeyrdfdc61d2018-03-02 00:40:58 +01001122 run_tests(nr);
Neels Hofmeyr6a29d322017-01-25 15:04:16 +01001123 }
1124 }
1125
1126 printf("Done\n");
1127
Neels Hofmeyr08b38282018-03-30 23:04:04 +02001128 check_talloc(msgb_ctx, msc_vlr_tests_ctx);
Neels Hofmeyr6a29d322017-01-25 15:04:16 +01001129 return 0;
1130}