blob: 898aeef3e87a4512053ed2bc947cc71368d7c657 [file] [log] [blame]
Harald Weltef6dd64d2017-11-19 12:09:51 +01001module MSC_Tests {
2
Harald Welte34b5a952019-05-27 11:54:11 +02003/* Osmocom MSC test suite in in TTCN-3
4 * (C) 2017-2019 Harald Welte <laforge@gnumonks.org>
5 * (C) 2018-2019 sysmocom - s.f.m.c. GmbH
6 * (C) 2018-2019 Vadim Yanitskiy <axilirator@gmail.com>
7 * All rights reserved.
8 *
9 * Released under the terms of GNU General Public License, Version 2 or
10 * (at your option) any later version.
11 *
12 * SPDX-License-Identifier: GPL-2.0-or-later
13 */
14
Harald Weltee13cfb22019-04-23 16:52:02 +020015friend module MSC_Tests_Iu;
Andreas Eversberg1733de32023-07-27 16:27:05 +020016friend module MSC_Tests_ASCI;
Harald Weltee13cfb22019-04-23 16:52:02 +020017
Harald Weltef6dd64d2017-11-19 12:09:51 +010018import from General_Types all;
19import from Osmocom_Types all;
Vadim Yanitskiy74b2f4f2024-06-06 22:07:11 +070020import from Misc_Helpers all;
Pau Espin Pedrole979c402021-04-28 17:29:54 +020021import from GSM_Types all;
Harald Weltef6dd64d2017-11-19 12:09:51 +010022
23import from M3UA_Types all;
24import from M3UA_Emulation all;
25
26import from MTP3asp_Types all;
27import from MTP3asp_PortType all;
28
29import from SCCPasp_Types all;
30import from SCCP_Types all;
31import from SCCP_Emulation all;
32
33import from SCTPasp_Types all;
34import from SCTPasp_PortType all;
35
Harald Weltea49e36e2018-01-21 19:29:33 +010036import from Osmocom_CTRL_Functions all;
37import from Osmocom_CTRL_Types all;
38import from Osmocom_CTRL_Adapter all;
39
Harald Welte3ca1c902018-01-24 18:51:27 +010040import from TELNETasp_PortType all;
41import from Osmocom_VTY_Functions all;
42
Harald Weltea49e36e2018-01-21 19:29:33 +010043import from MNCC_Emulation all;
Harald Welte2bb825f2018-01-22 11:31:18 +010044import from MNCC_Types all;
Harald Weltea49e36e2018-01-21 19:29:33 +010045
Harald Welte4aa970c2018-01-26 10:38:09 +010046import from MGCP_Emulation all;
47import from MGCP_Types all;
48import from MGCP_Templates all;
49import from SDP_Types all;
Pau Espin Pedrol1158cc62024-03-21 17:21:35 +010050import from SDP_Templates all;
Harald Welte4aa970c2018-01-26 10:38:09 +010051
Harald Weltea49e36e2018-01-21 19:29:33 +010052import from GSUP_Types all;
Pau Espin Pedrol8f1403a2024-01-18 20:08:43 +010053import from GSUP_Templates all;
54import from GSUP_Emulation all;
Harald Weltea49e36e2018-01-21 19:29:33 +010055import from IPA_Emulation all;
56
Harald Weltef6dd64d2017-11-19 12:09:51 +010057import from BSSAP_Types all;
Harald Welte6811d102019-04-14 22:23:14 +020058import from RAN_Adapter all;
Harald Weltea49e36e2018-01-21 19:29:33 +010059import from BSSAP_CodecPort all;
60import from BSSMAP_Templates all;
Harald Welte6811d102019-04-14 22:23:14 +020061import from RAN_Emulation all;
Harald Weltea49e36e2018-01-21 19:29:33 +010062import from BSC_ConnectionHandler all;
Harald Weltee13cfb22019-04-23 16:52:02 +020063import from RANAP_Templates all;
Harald Weltef6dd64d2017-11-19 12:09:51 +010064
Harald Welte4263c522018-12-06 11:56:27 +010065import from SGsAP_Templates all;
66import from SGsAP_Types all;
67import from SGsAP_Emulation all;
68
Harald Weltea49e36e2018-01-21 19:29:33 +010069import from MobileL3_Types all;
70import from MobileL3_CommonIE_Types all;
Vadim Yanitskiy103d09f2018-11-12 02:50:23 +070071import from MobileL3_SMS_Types all;
Harald Weltea49e36e2018-01-21 19:29:33 +010072import from L3_Templates all;
Harald Welte158a7ca2018-02-16 18:11:31 +010073import from L3_Common all;
Harald Weltef6dd64d2017-11-19 12:09:51 +010074
Harald Weltef640a012018-04-14 17:49:21 +020075import from SMPP_Types all;
76import from SMPP_Templates all;
77import from SMPP_Emulation all;
78
Stefan Sperlingc307e682018-06-14 15:15:46 +020079import from SCCP_Templates all;
80
Vadim Yanitskiy7d1f9182018-05-28 16:21:42 +070081import from SS_Types all;
82import from SS_Templates all;
83import from USSD_Helpers all;
Harald Welte4263c522018-12-06 11:56:27 +010084import from DNS_Helpers all;
Vadim Yanitskiy7d1f9182018-05-28 16:21:42 +070085
Philipp Maier948747b2019-04-02 15:22:33 +020086import from TCCConversion_Functions all;
87
Harald Welte9b751a62019-04-14 17:39:29 +020088const integer NUM_BSC := 3;
Harald Weltef6dd64d2017-11-19 12:09:51 +010089
Harald Welte4263c522018-12-06 11:56:27 +010090/* Needed for SGsAP SMS */
91import from MobileL3_SMS_Types all;
92
Harald Weltea4ca4462018-02-09 00:17:14 +010093type component MTC_CT extends CTRL_Adapter_CT {
Harald Weltef6dd64d2017-11-19 12:09:51 +010094 var boolean g_initialized := false;
Harald Weltea49e36e2018-01-21 19:29:33 +010095
Harald Welte6811d102019-04-14 22:23:14 +020096 var RAN_Adapter g_bssap[NUM_BSC];
Harald Weltea4ca4462018-02-09 00:17:14 +010097
Harald Weltea49e36e2018-01-21 19:29:33 +010098 /* no 'adapter_CT' for MNCC or GSUP */
99 var MNCC_Emulation_CT vc_MNCC;
Harald Welte4aa970c2018-01-26 10:38:09 +0100100 var MGCP_Emulation_CT vc_MGCP;
Harald Weltea49e36e2018-01-21 19:29:33 +0100101 var GSUP_Emulation_CT vc_GSUP;
102 var IPA_Emulation_CT vc_GSUP_IPA;
Harald Weltef640a012018-04-14 17:49:21 +0200103 var SMPP_Emulation_CT vc_SMPP;
Harald Welte4263c522018-12-06 11:56:27 +0100104 var SGsAP_Emulation_CT vc_SGsAP;
Harald Weltea49e36e2018-01-21 19:29:33 +0100105
106 /* only to get events from IPA underneath GSUP */
107 port IPA_CTRL_PT GSUP_IPA_EVENT;
Harald Welte3ca1c902018-01-24 18:51:27 +0100108 /* VTY to MSC */
109 port TELNETasp_PT MSCVTY;
Philipp Maier328d1662018-03-07 10:40:27 +0100110
111 /* A port to directly send BSSAP messages. This port is used for
112 * tests that require low level access to sen arbitrary BSSAP
113 * messages. Run f_init_bssap_direct() to connect and initialize */
114 port BSSAP_CODEC_PT BSSAP_DIRECT;
115
116 /* When BSSAP messages are directly sent, then the connection
117 * handler is not active, which means that also no guard timer is
118 * set up. The following timer will serve as a replacement */
119 timer Tguard_direct := 60.0;
Pau Espin Pedrola42745c2020-01-10 18:03:28 +0100120
121 /* Configure T(tias) over VTY, seconds */
122 var integer g_msc_sccp_timer_ias := 7 * 60;
123 /* Configure T(tiar) over VTY, seconds */
124 var integer g_msc_sccp_timer_iar := 15 * 60;
Harald Weltef6dd64d2017-11-19 12:09:51 +0100125}
126
127modulepar {
Harald Weltea49e36e2018-01-21 19:29:33 +0100128 /* remote parameters of IUT */
129 charstring mp_msc_ip := "127.0.0.1";
130 integer mp_msc_ctrl_port := 4255;
131 integer mp_msc_vty_port := 4254;
Harald Weltef6dd64d2017-11-19 12:09:51 +0100132
Harald Weltea49e36e2018-01-21 19:29:33 +0100133 /* local parameters of emulated HLR */
Philipp Maier9b690e42018-12-21 11:50:03 +0100134 boolean mp_mm_info := false;
Harald Weltea49e36e2018-01-21 19:29:33 +0100135 charstring mp_hlr_ip := "127.0.0.1";
136 integer mp_hlr_port := 4222;
Harald Welte6126fb02018-01-27 20:08:24 +0100137 charstring mp_mgw_ip := "127.0.0.1";
138 integer mp_mgw_port := 2427;
Harald Weltef6dd64d2017-11-19 12:09:51 +0100139
Harald Weltea49e36e2018-01-21 19:29:33 +0100140 charstring mp_msc_mncc := "/tmp/mncc";
Harald Weltea4ca4462018-02-09 00:17:14 +0100141
Harald Weltef640a012018-04-14 17:49:21 +0200142 integer mp_msc_smpp_port := 2775;
143 charstring mp_smpp_system_id := "msc_tester";
144 charstring mp_smpp_password := "osmocom1";
Harald Welte4263c522018-12-06 11:56:27 +0100145 charstring mp_mme_name := "mmec01.mmegi0001.mme.epc.mnc070.mcc901.3gppnetwork.org";
146 charstring mp_vlr_name := "vlr.example.net";
Eric Wild49888a62022-03-30 03:16:11 +0200147 integer mp_bssap_reset_retries := 1;
Harald Weltef640a012018-04-14 17:49:21 +0200148
Harald Welte6811d102019-04-14 22:23:14 +0200149 RAN_Configurations mp_bssap_cfg := {
Philipp Maier75932982018-03-27 14:52:35 +0200150 {
151 sccp_service_type := "mtp3_itu",
152 sctp_addr := { 23905, "127.0.0.1", 2905, "127.0.0.1" },
153 own_pc := 185,
154 own_ssn := 254,
155 peer_pc := 187,
156 peer_ssn := 254,
157 sio := '83'O,
158 rctx := 0
159 },
160 {
161 sccp_service_type := "mtp3_itu",
162 sctp_addr := { 23906, "127.0.0.1", 2905, "127.0.0.1" },
163 own_pc := 186,
164 own_ssn := 254,
165 peer_pc := 187,
166 peer_ssn := 254,
167 sio := '83'O,
168 rctx := 1
169 }
Harald Weltea4ca4462018-02-09 00:17:14 +0100170 };
Harald Weltef6dd64d2017-11-19 12:09:51 +0100171}
172
Philipp Maier328d1662018-03-07 10:40:27 +0100173/* altstep for the global guard timer (only used when BSSAP_DIRECT
174 * is used for communication */
175private altstep as_Tguard_direct() runs on MTC_CT {
176 [] Tguard_direct.timeout {
177 setverdict(fail, "Tguard timeout");
Daniel Willmannafce8662018-07-06 23:11:32 +0200178 mtc.stop;
Philipp Maier328d1662018-03-07 10:40:27 +0100179 }
180}
Harald Weltef6dd64d2017-11-19 12:09:51 +0100181
Neels Hofmeyr2ca1ab42019-03-08 03:45:43 +0100182private altstep as_optional_cc_rel(CallParameters cpars, boolean respond := false) runs on BSC_ConnHdlr {
183 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_CC_RELEASE(cpars.transaction_id))) {
Vadim Yanitskiy42fae8a2024-03-27 02:06:55 +0700184 if (respond) {
185 var BIT1 tid_remote := '1'B;
186 if (cpars.mo_call) {
187 tid_remote := '0'B;
Neels Hofmeyr2ca1ab42019-03-08 03:45:43 +0100188 }
Vadim Yanitskiy42fae8a2024-03-27 02:06:55 +0700189 BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_CC_REL_COMPL(cpars.transaction_id, tid_remote)));
Neels Hofmeyr2ca1ab42019-03-08 03:45:43 +0100190 }
Vadim Yanitskiyd1a32e02024-03-27 14:48:41 +0700191 repeat;
Vadim Yanitskiy42fae8a2024-03-27 02:06:55 +0700192 }
Neels Hofmeyrde76f052019-02-26 05:02:46 +0100193}
194
Harald Weltef640a012018-04-14 17:49:21 +0200195function f_init_smpp(charstring id) runs on MTC_CT {
196 id := id & "-SMPP";
197 var EsmePars pars := {
198 mode := MODE_TRANSCEIVER,
199 bind := {
200 system_id := mp_smpp_system_id,
201 password := mp_smpp_password,
202 system_type := "MSC_Tests",
203 interface_version := hex2int('34'H),
204 addr_ton := unknown,
205 addr_npi := unknown,
206 address_range := ""
207 },
208 esme_role := true
209 }
210
211 vc_SMPP := SMPP_Emulation_CT.create(id);
212 map(vc_SMPP:SMPP_PORT, system:SMPP_PORT);
Harald Welte4698a4c2020-08-18 22:57:52 +0200213 vc_SMPP.start(SMPP_Emulation.main_client(pars, mp_msc_ip, mp_msc_smpp_port, "", 0));
Harald Weltef640a012018-04-14 17:49:21 +0200214}
215
216
Harald Weltea49e36e2018-01-21 19:29:33 +0100217function f_init_mncc(charstring id) runs on MTC_CT {
218 id := id & "-MNCC";
219 var MnccOps ops := {
220 create_cb := refers(MNCC_Emulation.ExpectedCreateCallback),
221 unitdata_cb := refers(MNCC_Emulation.DummyUnitdataCallback)
222 }
223
224 vc_MNCC := MNCC_Emulation_CT.create(id);
225 map(vc_MNCC:MNCC, system:MNCC_CODEC_PT);
226 vc_MNCC.start(MNCC_Emulation.main(ops, id, mp_msc_mncc));
Harald Weltef6dd64d2017-11-19 12:09:51 +0100227}
228
Harald Welte4aa970c2018-01-26 10:38:09 +0100229function f_init_mgcp(charstring id) runs on MTC_CT {
230 id := id & "-MGCP";
231 var MGCPOps ops := {
232 create_cb := refers(MGCP_Emulation.ExpectedCreateCallback),
233 unitdata_cb := refers(MGCP_Emulation.DummyUnitdataCallback)
234 }
235 var MGCP_conn_parameters pars := {
Harald Welte6126fb02018-01-27 20:08:24 +0100236 callagent_ip := mp_msc_ip,
Harald Welte4aa970c2018-01-26 10:38:09 +0100237 callagent_udp_port := -1,
Harald Welte6126fb02018-01-27 20:08:24 +0100238 mgw_ip := mp_mgw_ip,
Pau Espin Pedrol1a026a52019-06-18 17:21:52 +0200239 mgw_udp_port := mp_mgw_port,
240 multi_conn_mode := false
Harald Welte4aa970c2018-01-26 10:38:09 +0100241 }
242
243 vc_MGCP := MGCP_Emulation_CT.create(id);
244 map(vc_MGCP:MGCP, system:MGCP_CODEC_PT);
245 vc_MGCP.start(MGCP_Emulation.main(ops, pars, id));
246}
247
Philipp Maierc09a1312019-04-09 16:05:26 +0200248function ForwardUnitdataCallback(PDU_SGsAP msg)
249runs on SGsAP_Emulation_CT return template PDU_SGsAP {
250 SGsAP_CLIENT.send(msg);
251 return omit;
252}
253
Harald Welte4263c522018-12-06 11:56:27 +0100254function f_init_sgsap(charstring id) runs on MTC_CT {
255 id := id & "-SGsAP";
256 var SGsAPOps ops := {
257 create_cb := refers(SGsAP_Emulation.ExpectedCreateCallback),
Philipp Maierc09a1312019-04-09 16:05:26 +0200258 unitdata_cb := refers(ForwardUnitdataCallback)
Harald Welte4263c522018-12-06 11:56:27 +0100259 }
260 var SGsAP_conn_parameters pars := {
261 remote_ip := mp_msc_ip,
262 remote_sctp_port := 29118,
263 local_ip := "",
264 local_sctp_port := -1
265 }
266
267 vc_SGsAP := SGsAP_Emulation_CT.create(id);
268 map(vc_SGsAP:SGsAP, system:SGsAP_CODEC_PT);
269 vc_SGsAP.start(SGsAP_Emulation.main(ops, pars, id));
270}
271
272
Harald Weltea49e36e2018-01-21 19:29:33 +0100273function f_init_gsup(charstring id) runs on MTC_CT {
274 id := id & "-GSUP";
275 var GsupOps ops := {
276 create_cb := refers(GSUP_Emulation.ExpectedCreateCallback)
277 }
278
279 vc_GSUP_IPA := IPA_Emulation_CT.create(id & "-IPA");
280 vc_GSUP := GSUP_Emulation_CT.create(id);
281
282 map(vc_GSUP_IPA:IPA_PORT, system:IPA_CODEC_PT);
283 connect(vc_GSUP:GSUP, vc_GSUP_IPA:IPA_GSUP_PORT);
284 /* we use this hack to get events like ASP_IPA_EVENT_UP */
285 connect(vc_GSUP_IPA:IPA_CTRL_PORT, self:GSUP_IPA_EVENT);
286
287 vc_GSUP.start(GSUP_Emulation.main(ops, id));
288 vc_GSUP_IPA.start(IPA_Emulation.main_server(mp_hlr_ip, mp_hlr_port));
289
290 /* wait for incoming connection to GSUP port before proceeding */
291 timer T := 10.0;
292 T.start;
293 alt {
Vadim Yanitskiy61564be2020-05-18 20:44:14 +0700294 [] GSUP_IPA_EVENT.receive(tr_ASP_IPA_EV(ASP_IPA_EVENT_UP)) { }
Harald Weltea49e36e2018-01-21 19:29:33 +0100295 [] T.timeout {
Harald Welte458fd372018-03-21 11:26:23 +0100296 setverdict(fail, "No connection to GSUP Port");
Daniel Willmannafce8662018-07-06 23:11:32 +0200297 mtc.stop
Harald Weltea49e36e2018-01-21 19:29:33 +0100298 }
299 }
Harald Weltef6dd64d2017-11-19 12:09:51 +0100300}
301
Pau Espin Pedrola65697d2019-05-21 12:54:39 +0200302function f_init(integer num_bsc := 1, boolean sgsap := false, boolean gsup := true, boolean osmux := false) runs on MTC_CT {
Harald Weltef6dd64d2017-11-19 12:09:51 +0100303
304 if (g_initialized == true) {
305 return;
306 }
307 g_initialized := true;
308
Philipp Maier75932982018-03-27 14:52:35 +0200309 if (num_bsc > NUM_BSC) {
Daniel Willmannafce8662018-07-06 23:11:32 +0200310 testcase.stop("excess number of BSC instances requested");
Philipp Maier75932982018-03-27 14:52:35 +0200311 }
312
Pau Espin Pedrol9a5b8ff2021-01-04 19:01:31 +0100313 f_ipa_ctrl_start_client(mp_msc_ip, mp_msc_ctrl_port);
Harald Welte3ca1c902018-01-24 18:51:27 +0100314
315 map(self:MSCVTY, system:MSCVTY);
316 f_vty_set_prompts(MSCVTY);
317 f_vty_transceive(MSCVTY, "enable");
Harald Welteb14c77a2018-01-25 17:25:44 +0100318
319 /* set some defaults */
320 f_vty_config(MSCVTY, "network", "authentication optional");
321 f_vty_config(MSCVTY, "msc", "assign-tmsi");
Oliver Smith1d118ff2019-07-03 10:57:35 +0200322 f_vty_config(MSCVTY, "msc", "check-imei-rqd 0");
Harald Welteb14c77a2018-01-25 17:25:44 +0100323 f_vty_config(MSCVTY, "network", "encryption a5 0");
Pau Espin Pedrola42745c2020-01-10 18:03:28 +0100324 f_vty_config(MSCVTY, "cs7 instance 0", "sccp-timer ias " & int2str(g_msc_sccp_timer_ias));
325 f_vty_config(MSCVTY, "cs7 instance 0", "sccp-timer iar " & int2str(g_msc_sccp_timer_iar));
Pau Espin Pedrol9a732a42020-09-15 15:56:33 +0200326 if (osmux) {
327 f_vty_config(MSCVTY, "msc", "osmux on");
328 } else {
329 f_vty_config(MSCVTY, "msc", "osmux off");
Pau Espin Pedrol3dd33bc2019-05-31 17:51:20 +0200330 }
Daniel Willmann08862152022-02-22 13:21:49 +0100331
Neels Hofmeyrc47ce852023-03-06 17:16:50 +0100332 /* Configure the MGCP timeout so that a failure to set up all RTP streams triggers within the time that we keep
333 * an otherwise established call open. */
334 f_vty_config(MSCVTY, "msc", "timer mgw X2 3");
335
Daniel Willmann08862152022-02-22 13:21:49 +0100336 for (var integer i := 0; i < num_bsc; i := i + 1) {
337 if (isbound(mp_bssap_cfg[i])) {
338 var RanOps ranops := BSC_RanOps;
339 ranops.use_osmux := osmux;
Eric Wild49888a62022-03-30 03:16:11 +0200340 ranops.bssap_reset_retries := mp_bssap_reset_retries;
Daniel Willmann08862152022-02-22 13:21:49 +0100341 f_ran_adapter_init(g_bssap[i], mp_bssap_cfg[i], "MSC_Test_" & int2str(i), ranops);
342 f_ran_adapter_start(g_bssap[i]);
343 } else {
344 testcase.stop("missing BSSAP configuration");
345 }
346 }
347
348 f_init_mncc("MSC_Test");
349 f_init_mgcp("MSC_Test");
350
351 if (gsup == true) {
352 f_init_gsup("MSC_Test");
353 }
354 f_init_smpp("MSC_Test");
355
356 if (sgsap == true) {
357 f_init_sgsap("MSC_Test");
358 }
359
Harald Weltef6dd64d2017-11-19 12:09:51 +0100360}
361
Philipp Maier328d1662018-03-07 10:40:27 +0100362/* Initialize for a direct connection to BSSAP. This function is an alternative
363 * to f_init() when the high level functions of the BSC_ConnectionHandler are
364 * not needed. */
365function f_init_bssap_direct() runs on MTC_CT {
Harald Welte3ca0ce12019-04-23 17:18:48 +0200366 f_ran_adapter_init(g_bssap[0], mp_bssap_cfg[0], "MSC_Test", omit);
Philipp Maier75932982018-03-27 14:52:35 +0200367 connect(g_bssap[0].vc_SCCP:SCCP_SP_PORT, self:BSSAP_DIRECT);
Philipp Maier328d1662018-03-07 10:40:27 +0100368
369 /* Start guard timer and activate it as default */
370 Tguard_direct.start
371 activate(as_Tguard_direct());
372}
373
Harald Weltea49e36e2018-01-21 19:29:33 +0100374type function void_fn(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr;
Harald Weltef6dd64d2017-11-19 12:09:51 +0100375
Harald Weltea49e36e2018-01-21 19:29:33 +0100376/* FIXME: move into BSC_ConnectionHandler? */
Harald Welte9b751a62019-04-14 17:39:29 +0200377function f_init_pars(integer imsi_suffix, boolean sgsap := false, boolean gsup := true, integer ran_idx := 0,
Neels Hofmeyr4e18ccc2020-06-24 19:08:17 +0200378 boolean ran_is_geran := true, boolean use_osmux := false, OCT4 gsup_sid := '20000101'O,
379 boolean verify_cell_id := true)
Harald Weltef9abf8d2019-04-21 13:07:17 +0200380runs on MTC_CT return BSC_ConnHdlrPars {
Harald Weltede371492018-01-27 23:44:41 +0100381 var BSC_ConnHdlrNetworkPars net_pars := {
382 kc_support := '0A'O, /* A5/1 and A5/3 enabled */
Neels Hofmeyre860fc42022-10-05 01:15:54 +0200383 net_config := { "authentication optional", "encryption a5 0" },
384 expect_attach_success := true,
Harald Weltede371492018-01-27 23:44:41 +0100385 expect_tmsi := true,
Neels Hofmeyre860fc42022-10-05 01:15:54 +0200386 expect_auth_attempt := false,
387 hlr_has_auth_info := true,
Harald Weltede371492018-01-27 23:44:41 +0100388 expect_auth := false,
Oliver Smith1d118ff2019-07-03 10:57:35 +0200389 expect_ciph := false,
390 expect_imei := false,
391 expect_imei_early := false,
392 check_imei_result := OSMO_GSUP_IMEI_RESULT_ACK,
393 check_imei_error := false
Harald Weltede371492018-01-27 23:44:41 +0100394 };
Harald Weltea49e36e2018-01-21 19:29:33 +0100395 var BSC_ConnHdlrPars pars := {
Harald Weltef9abf8d2019-04-21 13:07:17 +0200396 sccp_addr_own := g_bssap[ran_idx].sccp_addr_own,
397 sccp_addr_peer := g_bssap[ran_idx].sccp_addr_peer,
Harald Welteedbab812018-03-18 16:02:25 +0100398 cell_id := valueof(ts_CellId_CGI('262'H, '42'H, 23, 42)),
Harald Welte81b7f9d2018-01-24 19:06:24 +0100399 imei := f_gen_imei(imsi_suffix),
400 imsi := f_gen_imsi(imsi_suffix),
401 msisdn := f_gen_msisdn(imsi_suffix),
Harald Welte256571e2018-01-24 18:47:19 +0100402 tmsi := omit,
Harald Welte9de84792018-01-28 01:06:35 +0100403 cm1 := valueof(ts_CM1),
Harald Welte82600572018-01-21 20:54:08 +0100404 cm2 := valueof(ts_CM2_default),
Harald Welte16114282018-01-24 22:41:21 +0100405 cm3 := omit,
Harald Weltede371492018-01-27 23:44:41 +0100406 vec := omit,
Neels Hofmeyrb00c5b02021-06-23 20:05:25 +0200407 vec_keep := false,
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +0100408 net := net_pars,
Philipp Maieraeb29a82018-11-08 17:40:53 +0100409 send_early_cm := true,
410 ipa_ctrl_ip := mp_msc_ip,
411 ipa_ctrl_port := mp_msc_ctrl_port,
Philipp Maier9b690e42018-12-21 11:50:03 +0100412 ipa_ctrl_enable := true,
Philipp Maier57865482019-01-07 18:33:13 +0100413 mm_info := mp_mm_info,
Philipp Maierc09a1312019-04-09 16:05:26 +0200414 sgsap_enable := sgsap,
Harald Weltef9abf8d2019-04-21 13:07:17 +0200415 gsup_enable := gsup,
Vadim Yanitskiy2dd96612020-01-07 21:48:29 +0100416 gsup_sid := gsup_sid,
Harald Weltec1f937a2019-04-21 21:19:23 +0200417 ran_idx := ran_idx,
Harald Welte9b751a62019-04-14 17:39:29 +0200418 use_umts_aka := false,
Pau Espin Pedrola65697d2019-05-21 12:54:39 +0200419 ran_is_geran := ran_is_geran,
Neels Hofmeyr4e18ccc2020-06-24 19:08:17 +0200420 use_osmux := use_osmux,
Pau Espin Pedrol833174e2020-09-03 16:46:02 +0200421 use_ipv6 := false,
Oliver Smith44424db2023-08-22 13:54:09 +0200422 use_csd := false,
Pau Espin Pedrole979c402021-04-28 17:29:54 +0200423 verify_cell_id := verify_cell_id,
424 common_id_last_eutran_plmn := omit
Harald Weltea49e36e2018-01-21 19:29:33 +0100425 };
Harald Weltee13cfb22019-04-23 16:52:02 +0200426 if (not ran_is_geran) {
427 pars.use_umts_aka := true;
428 pars.net.expect_auth := true;
429 }
Neels Hofmeyr9adaa702018-03-01 20:23:19 +0100430 return pars;
431}
432
Neels Hofmeyre1a1b632021-07-28 18:05:43 +0200433function f_start_handler_create(BSC_ConnHdlrPars pars) runs on MTC_CT return BSC_ConnHdlr {
Neels Hofmeyr9adaa702018-03-01 20:23:19 +0100434 var BSC_ConnHdlr vc_conn;
Neels Hofmeyr60122f82021-07-28 17:59:38 +0200435 var charstring id := testcasename() & int2str(pars.ran_idx);
Harald Weltea49e36e2018-01-21 19:29:33 +0100436
437 vc_conn := BSC_ConnHdlr.create(id);
Neels Hofmeyr60122f82021-07-28 17:59:38 +0200438
Harald Weltea49e36e2018-01-21 19:29:33 +0100439 /* BSSMAP part / A interface */
Neels Hofmeyr60122f82021-07-28 17:59:38 +0200440 connect(vc_conn:BSSAP, g_bssap[pars.ran_idx].vc_RAN:CLIENT);
441 connect(vc_conn:BSSAP_PROC, g_bssap[pars.ran_idx].vc_RAN:PROC);
Harald Weltea49e36e2018-01-21 19:29:33 +0100442 /* MNCC part */
443 connect(vc_conn:MNCC, vc_MNCC:MNCC_CLIENT);
444 connect(vc_conn:MNCC_PROC, vc_MNCC:MNCC_PROC);
Harald Welte4aa970c2018-01-26 10:38:09 +0100445 /* MGCP part */
446 connect(vc_conn:MGCP, vc_MGCP:MGCP_CLIENT);
447 connect(vc_conn:MGCP_PROC, vc_MGCP:MGCP_PROC);
Harald Weltea49e36e2018-01-21 19:29:33 +0100448 /* GSUP part */
Philipp Maierc09a1312019-04-09 16:05:26 +0200449 if (pars.gsup_enable == true) {
450 connect(vc_conn:GSUP, vc_GSUP:GSUP_CLIENT);
451 connect(vc_conn:GSUP_PROC, vc_GSUP:GSUP_PROC);
452 }
Harald Weltef640a012018-04-14 17:49:21 +0200453 /* SMPP part */
454 connect(vc_conn:SMPP, vc_SMPP:SMPP_CLIENT);
455 connect(vc_conn:SMPP_PROC, vc_SMPP:SMPP_PROC);
Harald Welte4263c522018-12-06 11:56:27 +0100456 /* SGs part */
Philipp Maier8e07a4a2019-02-14 18:23:28 +0100457 if (pars.sgsap_enable == true) {
Philipp Maier57865482019-01-07 18:33:13 +0100458 connect(vc_conn:SGsAP, vc_SGsAP:SGsAP_CLIENT);
459 connect(vc_conn:SGsAP_PROC, vc_SGsAP:SGsAP_PROC);
460 }
Neels Hofmeyre1a1b632021-07-28 18:05:43 +0200461 return vc_conn;
462}
Harald Weltea49e36e2018-01-21 19:29:33 +0100463
Neels Hofmeyre1a1b632021-07-28 18:05:43 +0200464function f_start_handler_run(BSC_ConnHdlr vc_conn, void_fn fn, BSC_ConnHdlrPars pars) runs on MTC_CT {
465 var charstring id := testcasename() & int2str(pars.ran_idx);
Harald Weltea10db902018-01-27 12:44:49 +0100466 /* We cannot use vc_conn.start(f_init_handler(fn, id, pars)); as we cannot have
467 * a stand-alone 'derefers()' call, see https://www.eclipse.org/forums/index.php/t/1091364/ */
Harald Weltea49e36e2018-01-21 19:29:33 +0100468 vc_conn.start(derefers(fn)(id, pars));
Neels Hofmeyre1a1b632021-07-28 18:05:43 +0200469}
470
471function f_start_handler_with_pars(void_fn fn, BSC_ConnHdlrPars pars) runs on MTC_CT return BSC_ConnHdlr {
472 var BSC_ConnHdlr vc_conn;
473 vc_conn := f_start_handler_create(pars);
474 f_start_handler_run(vc_conn, fn, pars);
Harald Weltea49e36e2018-01-21 19:29:33 +0100475 return vc_conn;
476}
477
Neels Hofmeyr4e18ccc2020-06-24 19:08:17 +0200478function f_start_handler(void_fn fn, integer imsi_suffix, integer ran_idx := 0, boolean ran_is_geran := true, boolean use_osmux := false,
479 boolean verify_cell_id := true)
Harald Welte9b751a62019-04-14 17:39:29 +0200480runs on MTC_CT return BSC_ConnHdlr {
Neels Hofmeyr4e18ccc2020-06-24 19:08:17 +0200481 return f_start_handler_with_pars(fn, f_init_pars(imsi_suffix, ran_idx := ran_idx, ran_is_geran := ran_is_geran, use_osmux := use_osmux, verify_cell_id := verify_cell_id));
Neels Hofmeyr9adaa702018-03-01 20:23:19 +0100482}
483
Harald Weltea49e36e2018-01-21 19:29:33 +0100484private function f_tc_lu_imsi_noauth_tmsi(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +0100485 f_init_handler(pars);
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +0100486 f_perform_lu();
Harald Weltea49e36e2018-01-21 19:29:33 +0100487}
Harald Weltea49e36e2018-01-21 19:29:33 +0100488testcase TC_lu_imsi_noauth_tmsi() runs on MTC_CT {
489 var BSC_ConnHdlr vc_conn;
490 f_init();
491
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +0100492 vc_conn := f_start_handler(refers(f_tc_lu_imsi_noauth_tmsi), 1);
Harald Weltea49e36e2018-01-21 19:29:33 +0100493 vc_conn.done;
494}
495
496private function f_tc_lu_imsi_noauth_notmsi(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltede371492018-01-27 23:44:41 +0100497 pars.net.expect_tmsi := false;
Harald Weltea10db902018-01-27 12:44:49 +0100498 f_init_handler(pars);
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +0100499 f_perform_lu();
Harald Weltea49e36e2018-01-21 19:29:33 +0100500}
Harald Weltea49e36e2018-01-21 19:29:33 +0100501testcase TC_lu_imsi_noauth_notmsi() runs on MTC_CT {
502 var BSC_ConnHdlr vc_conn;
503 f_init();
Harald Welte3ca1c902018-01-24 18:51:27 +0100504 f_vty_config(MSCVTY, "msc", "no assign-tmsi");
Harald Weltea49e36e2018-01-21 19:29:33 +0100505
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +0100506 vc_conn := f_start_handler(refers(f_tc_lu_imsi_noauth_notmsi), 2);
Harald Weltea49e36e2018-01-21 19:29:33 +0100507 vc_conn.done;
508}
509
510/* Do LU by IMSI, refuse it on GSUP and expect LU REJ back to MS */
Harald Weltee13cfb22019-04-23 16:52:02 +0200511friend function f_tc_lu_imsi_reject(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +0100512 f_init_handler(pars);
Harald Weltea49e36e2018-01-21 19:29:33 +0100513 var PDU_ML3_MS_NW l3_lu := f_build_lu_imsi(g_pars.imsi);
514
515 f_create_gsup_expect(hex2str(g_pars.imsi));
Harald Weltedceacc72019-04-21 20:58:35 +0200516 f_cl3_or_initial_ue(l3_lu);
Neels Hofmeyrd076c522019-11-28 01:00:52 +0100517 f_mm_common();
Harald Weltea49e36e2018-01-21 19:29:33 +0100518 GSUP.receive(tr_GSUP_UL_REQ(g_pars.imsi));
519 GSUP.send(ts_GSUP_UL_ERR(g_pars.imsi, 23));
520 alt {
Harald Welte5946b332018-03-18 23:32:21 +0100521 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Rej(int2oct(23,1)))) {
522 f_expect_clear();
523 }
Harald Weltea49e36e2018-01-21 19:29:33 +0100524 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Acc)) {
525 setverdict(fail, "Expecting LU REJ, but got ACCEPT");
Daniel Willmannafce8662018-07-06 23:11:32 +0200526 mtc.stop;
Harald Weltea49e36e2018-01-21 19:29:33 +0100527 }
528 }
Harald Weltea49e36e2018-01-21 19:29:33 +0100529}
530testcase TC_lu_imsi_reject() runs on MTC_CT {
531 var BSC_ConnHdlr vc_conn;
532 f_init();
533
Neels Hofmeyr4e18ccc2020-06-24 19:08:17 +0200534 vc_conn := f_start_handler(refers(f_tc_lu_imsi_reject), 3, verify_cell_id := false);
Harald Weltea49e36e2018-01-21 19:29:33 +0100535 vc_conn.done;
536}
537
Harald Weltee13cfb22019-04-23 16:52:02 +0200538
539
Harald Weltea49e36e2018-01-21 19:29:33 +0100540/* Do LU by IMSI, timeout on GSUP */
Harald Weltee13cfb22019-04-23 16:52:02 +0200541friend function f_tc_lu_imsi_timeout_gsup(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +0100542 f_init_handler(pars);
Harald Weltea49e36e2018-01-21 19:29:33 +0100543 var PDU_ML3_MS_NW l3_lu := f_build_lu_imsi(g_pars.imsi);
544
545 f_create_gsup_expect(hex2str(g_pars.imsi));
Harald Weltedceacc72019-04-21 20:58:35 +0200546 f_cl3_or_initial_ue(l3_lu);
Neels Hofmeyrd076c522019-11-28 01:00:52 +0100547 f_mm_common();
Harald Weltea49e36e2018-01-21 19:29:33 +0100548 GSUP.receive(tr_GSUP_UL_REQ(g_pars.imsi));
549 /* Normally the HLR would need to respond here, but we decide to force a timeout here */
550 alt {
551 /* FIXME: Expect specific reject cause */
Harald Welte5946b332018-03-18 23:32:21 +0100552 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Rej)) {
553 f_expect_clear();
554 }
Harald Weltea49e36e2018-01-21 19:29:33 +0100555 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Acc)) {
556 setverdict(fail, "Expecting LU REJ, but got ACCEPT");
Daniel Willmannafce8662018-07-06 23:11:32 +0200557 mtc.stop;
Harald Weltea49e36e2018-01-21 19:29:33 +0100558 }
559 }
Harald Weltea49e36e2018-01-21 19:29:33 +0100560}
561testcase TC_lu_imsi_timeout_gsup() runs on MTC_CT {
562 var BSC_ConnHdlr vc_conn;
563 f_init();
564
Neels Hofmeyr4e18ccc2020-06-24 19:08:17 +0200565 vc_conn := f_start_handler(refers(f_tc_lu_imsi_timeout_gsup), 4, verify_cell_id := false);
Harald Weltea49e36e2018-01-21 19:29:33 +0100566 vc_conn.done;
567}
568
Harald Weltee13cfb22019-04-23 16:52:02 +0200569
Harald Welte7b1b2812018-01-22 21:23:06 +0100570private function f_tc_lu_imsi_auth_tmsi(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltede371492018-01-27 23:44:41 +0100571 pars.net.expect_auth := true;
Harald Weltea10db902018-01-27 12:44:49 +0100572 f_init_handler(pars);
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +0100573 f_perform_lu();
Harald Welte7b1b2812018-01-22 21:23:06 +0100574}
575testcase TC_lu_imsi_auth_tmsi() runs on MTC_CT {
576 var BSC_ConnHdlr vc_conn;
577 f_init();
Harald Welte3ca1c902018-01-24 18:51:27 +0100578 f_vty_config(MSCVTY, "network", "authentication required");
Harald Welte7b1b2812018-01-22 21:23:06 +0100579
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +0100580 vc_conn := f_start_handler(refers(f_tc_lu_imsi_auth_tmsi), 5);
Harald Welte7b1b2812018-01-22 21:23:06 +0100581 vc_conn.done;
582}
583
Harald Weltee13cfb22019-04-23 16:52:02 +0200584
585friend function f_tc_lu_imsi_auth3g_tmsi(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Welte8a397ae2019-04-21 22:03:37 +0200586 pars.net.expect_auth := true;
587 pars.use_umts_aka := true;
588 f_init_handler(pars);
589 f_perform_lu();
590}
591testcase TC_lu_imsi_auth3g_tmsi() runs on MTC_CT {
592 var BSC_ConnHdlr vc_conn;
593 f_init();
594 f_vty_config(MSCVTY, "network", "authentication required");
595
596 vc_conn := f_start_handler(refers(f_tc_lu_imsi_auth3g_tmsi), 1005);
597 vc_conn.done;
598}
Harald Weltea49e36e2018-01-21 19:29:33 +0100599
Pau Espin Pedrold3d54a92019-12-17 17:02:54 +0100600/* Proceed with LU but never receive an TMSI Realloc from MS after LU Accept (OS#4337).
601 * TS 24.008 sec 4.3.1.5 states MSC should simply release all MM connections.
602 */
603friend function f_tc_lu_imsi_timeout_tmsi_realloc(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
604
605 f_init_handler(pars);
606
607 var PDU_ML3_MS_NW l3_lu := f_build_lu_imsi(g_pars.imsi);
608 var PDU_DTAP_MT dtap_mt;
609
610 /* tell GSUP dispatcher to send this IMSI to us */
611 f_create_gsup_expect(hex2str(g_pars.imsi));
612
613 /* Send BSSAP_Conn_Req with COMPL L3 INFO to MSC */
614 if (g_pars.ran_is_geran) {
615 f_bssap_compl_l3(l3_lu);
616 if (g_pars.send_early_cm) {
617 BSSAP.send(ts_BSSMAP_ClassmarkUpd(g_pars.cm2, g_pars.cm3));
618 }
619 } else {
620 f_ranap_initial_ue(l3_lu);
621 }
622
623 f_mm_imei_early();
624 f_mm_common();
625 f_msc_lu_hlr();
626 f_mm_imei();
627
628 alt {
629 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Acc)) -> value dtap_mt {}
630 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Rej)) {
631 setverdict(fail, "Expected LU ACK, but received LU REJ");
632 mtc.stop;
633 }
634 }
635
636 /* currently (due to bug OS#4337), an extra LU reject is received before
637 terminating the connection. Enabling following line makes the test
638 pass: */
639 //f_expect_lu_reject('16'O); /* Cause: congestion */
640
641 /* f_expect_lu_reject() already waits for T"-1" (X1, 5 seconds), but give some
642 extra time to avoid race conditons... */
Neels Hofmeyr4e18ccc2020-06-24 19:08:17 +0200643 f_expect_clear(7.0, verify_vlr_cell_id := false);
Pau Espin Pedrold3d54a92019-12-17 17:02:54 +0100644
645 setverdict(pass);
646}
647testcase TC_lu_imsi_timeout_tmsi_realloc() runs on MTC_CT {
648 var BSC_ConnHdlr vc_conn;
649 f_init();
650
651 vc_conn := f_start_handler(refers(f_tc_lu_imsi_timeout_tmsi_realloc), 5);
652 vc_conn.done;
653}
654
Harald Weltee13cfb22019-04-23 16:52:02 +0200655
Harald Weltea49e36e2018-01-21 19:29:33 +0100656/* Send CM SERVICE REQ for IMSI that has never performed LU before */
Harald Weltee13cfb22019-04-23 16:52:02 +0200657friend function f_tc_cmserv_imsi_unknown(charstring id, BSC_ConnHdlrPars pars)
Harald Weltea49e36e2018-01-21 19:29:33 +0100658runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +0100659 f_init_handler(pars);
Harald Weltea49e36e2018-01-21 19:29:33 +0100660
661 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
Harald Welteedbab812018-03-18 16:02:25 +0100662 var BSSMAP_IE_CellIdentifier cell_id := valueof(ts_CellId_CGI('262'H, '42'H, 23, 42));
Harald Welte6ed6bf92018-01-24 21:09:15 +0100663 var PDU_ML3_MS_NW l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, mi));
Harald Weltea49e36e2018-01-21 19:29:33 +0100664
665 f_create_gsup_expect(hex2str(g_pars.imsi));
666
667 /* Send BSSAP_Conn_Req with COMPL L3 INFO to MSC */
Harald Weltedceacc72019-04-21 20:58:35 +0200668 f_cl3_or_initial_ue(l3_info);
Harald Welteb7817992019-05-09 13:15:39 +0200669 f_mm_auth();
Harald Weltea49e36e2018-01-21 19:29:33 +0100670
671 timer T := 10.0;
Harald Weltef6dd64d2017-11-19 12:09:51 +0100672 T.start;
673 alt {
Harald Weltea49e36e2018-01-21 19:29:33 +0100674 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_CM_SERV_REJ)) { }
675 //[] BSSAP.receive(tr_PDU_DTAP_MT(tr_CM_SERV_ACC)) { }
Daniel Willmannafce8662018-07-06 23:11:32 +0200676 [] BSSAP.receive {
677 setverdict(fail, "Received unexpected BSSAP");
678 mtc.stop;
679 }
Harald Weltea49e36e2018-01-21 19:29:33 +0100680 [] GSUP.receive(tr_GSUP_UL_REQ(g_pars.imsi)) {
681 setverdict(fail, "Unexpected GSUP UL REQ");
Daniel Willmannafce8662018-07-06 23:11:32 +0200682 mtc.stop;
Harald Weltea49e36e2018-01-21 19:29:33 +0100683 }
Daniel Willmannafce8662018-07-06 23:11:32 +0200684 [] T.timeout {
Neels Hofmeyrf1c3c212020-08-19 13:15:32 +0000685 setverdict(fail, "Timeout waiting for CM SERV REJ");
Daniel Willmannafce8662018-07-06 23:11:32 +0200686 mtc.stop;
687 }
Harald Weltef6dd64d2017-11-19 12:09:51 +0100688 }
689
Harald Welte1ddc7162018-01-27 14:25:46 +0100690 f_expect_clear();
Harald Weltef6dd64d2017-11-19 12:09:51 +0100691}
Harald Weltea49e36e2018-01-21 19:29:33 +0100692testcase TC_cmserv_imsi_unknown() runs on MTC_CT {
693 var BSC_ConnHdlr vc_conn;
694 f_init();
Neels Hofmeyr4e18ccc2020-06-24 19:08:17 +0200695 vc_conn := f_start_handler(refers(f_tc_cmserv_imsi_unknown), 6, verify_cell_id := false);
Harald Weltea49e36e2018-01-21 19:29:33 +0100696 vc_conn.done;
697}
698
Harald Weltee13cfb22019-04-23 16:52:02 +0200699
Neels Hofmeyr13737fb2020-08-19 13:16:14 +0000700/* Send CM SERVICE REQ for TMSI that has never performed LU before */
701friend function f_tc_cmserv_tmsi_unknown(charstring id, BSC_ConnHdlrPars pars)
702runs on BSC_ConnHdlr {
703 f_init_handler(pars);
704
705 var MobileIdentityLV mi := valueof(ts_MI_TMSI_LV('57111111'O));
706 var BSSMAP_IE_CellIdentifier cell_id := valueof(ts_CellId_CGI('262'H, '42'H, 23, 42));
707 var PDU_ML3_MS_NW l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, mi));
708
709 /* Send BSSAP_Conn_Req with COMPL L3 INFO to MSC */
710 f_cl3_or_initial_ue(l3_info);
711 f_mm_auth();
712
713 timer T := 10.0;
714 T.start;
715 alt {
716 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_CM_SERV_REJ)) { }
717 [] BSSAP.receive {
718 setverdict(fail, "Received unexpected BSSAP");
719 mtc.stop;
720 }
721 [] T.timeout {
722 setverdict(fail, "Timeout waiting for CM SERV REJ");
723 mtc.stop;
724 }
725 }
726
727 f_expect_clear();
728}
729testcase TC_cmserv_tmsi_unknown() runs on MTC_CT {
730 var BSC_ConnHdlr vc_conn;
731 f_init();
732 vc_conn := f_start_handler(refers(f_tc_cmserv_tmsi_unknown), 57, verify_cell_id := false);
733 vc_conn.done;
734}
735
Neels Hofmeyr14d0b132020-08-19 13:49:05 +0000736/* Send Paging Response for IMSI that has never performed LU before */
737friend function f_tc_paging_response_imsi_unknown(charstring id, BSC_ConnHdlrPars pars)
738runs on BSC_ConnHdlr {
739 f_init_handler(pars);
740
741 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
742 var BSSMAP_IE_CellIdentifier cell_id := valueof(ts_CellId_CGI('262'H, '42'H, 23, 42));
743 var PDU_ML3_MS_NW l3_info := valueof(ts_PAG_RESP(mi));
744
745 /* Send BSSAP_Conn_Req with COMPL L3 INFO to MSC */
746 f_cl3_or_initial_ue(l3_info);
747
748 /* The Paging Response gets rejected by a direct Clear Command */
749 f_expect_clear();
750}
751testcase TC_paging_response_imsi_unknown() runs on MTC_CT {
752 var BSC_ConnHdlr vc_conn;
753 f_init();
754 vc_conn := f_start_handler(refers(f_tc_paging_response_imsi_unknown), 58, verify_cell_id := false);
755 vc_conn.done;
756}
757
758/* Send Paging Response for TMSI that has never performed LU before */
759friend function f_tc_paging_response_tmsi_unknown(charstring id, BSC_ConnHdlrPars pars)
760runs on BSC_ConnHdlr {
761 f_init_handler(pars);
762
763 var MobileIdentityLV mi := valueof(ts_MI_TMSI_LV('59111111'O));
764 var BSSMAP_IE_CellIdentifier cell_id := valueof(ts_CellId_CGI('262'H, '42'H, 23, 42));
765 var PDU_ML3_MS_NW l3_info := valueof(ts_PAG_RESP(mi));
766
767 /* Send BSSAP_Conn_Req with COMPL L3 INFO to MSC */
768 f_cl3_or_initial_ue(l3_info);
769
770 /* The Paging Response gets rejected by a direct Clear Command */
771 f_expect_clear();
772}
773testcase TC_paging_response_tmsi_unknown() runs on MTC_CT {
774 var BSC_ConnHdlr vc_conn;
775 f_init();
776 vc_conn := f_start_handler(refers(f_tc_paging_response_tmsi_unknown), 59, verify_cell_id := false);
777 vc_conn.done;
778}
779
Neels Hofmeyr13737fb2020-08-19 13:16:14 +0000780
Harald Weltee13cfb22019-04-23 16:52:02 +0200781friend function f_tc_lu_and_mo_call(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +0100782 f_init_handler(pars);
Neels Hofmeyr3c89a6b2019-10-15 16:54:37 +0200783 var CallParameters cpars := valueof(t_CallParams);
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +0100784 f_perform_lu();
Harald Welteb71901a2018-01-26 19:16:05 +0100785 f_mo_call(cpars);
Harald Welte2bb825f2018-01-22 11:31:18 +0100786}
787testcase TC_lu_and_mo_call() runs on MTC_CT {
788 var BSC_ConnHdlr vc_conn;
789 f_init();
790
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +0100791 vc_conn := f_start_handler(refers(f_tc_lu_and_mo_call), 7);
Harald Welte071ed732018-01-23 19:53:52 +0100792 vc_conn.done;
793}
Pau Espin Pedrol833174e2020-09-03 16:46:02 +0200794friend function f_tc_lu_and_mo_call_ipv6(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
795 f_init_handler(pars);
796 var CallParameters cpars := valueof(t_CallParams);
797 cpars.mgw_conn_1.mgw_rtp_ip := "::1";
798 cpars.mgw_conn_2.mgw_rtp_ip := "::2";
799 cpars.bss_rtp_ip := "::3";
800 f_perform_lu();
801 f_mo_call(cpars);
802}
803testcase TC_lu_and_mo_call_ipv6() runs on MTC_CT {
804 var BSC_ConnHdlr vc_conn;
805 f_init();
806
807 vc_conn := f_start_handler(refers(f_tc_lu_and_mo_call_ipv6), 7);
808 vc_conn.done;
809}
Harald Welte071ed732018-01-23 19:53:52 +0100810
Pau Espin Pedrola42745c2020-01-10 18:03:28 +0100811/* Verify T(iar) triggers and releases the channel */
812friend function f_lu_and_mo_call_sccp_tiar_timeout(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
813 timer T_wait_iar := int2float(5 + 1); /* g_msc_sccp_timer_iar + Give extra time (+1 sec) */
814 f_init_handler(pars);
815 var CallParameters cpars := valueof(t_CallParams);
816 f_perform_lu();
817 f_mo_call_establish(cpars);
818
819 /* Expect the channel cleared upon T(iar) triggered: */
820 T_wait_iar.start;
821 alt {
822 [] BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_IND) {
823 T_wait_iar.stop
824 setverdict(pass);
825 }
Pau Espin Pedrola42745c2020-01-10 18:03:28 +0100826 [] T_wait_iar.timeout {
827 setverdict(fail, "Timeout waiting for T(iar) triggered SCCP RSLD");
828 mtc.stop;
829 }
830 }
Harald Welte4a3fa712020-08-19 08:57:33 +0200831 /* DLCX for both directions; if we don't do this, we might receive either of the two during
832 * shutdown causing race conditions */
833 MGCP.receive(tr_DLCX(?));
834 MGCP.receive(tr_DLCX(?));
Pau Espin Pedrola42745c2020-01-10 18:03:28 +0100835
836 setverdict(pass);
837}
838testcase TC_lu_and_mo_call_sccp_tiar_timeout() runs on MTC_CT {
839 var BSC_ConnHdlr vc_conn;
840
841 /* Set T(iar) in MSC low enough that it will trigger before other side
842 has time to keep alive with a T(ias). Keep recommended ratio of
843 T(iar) >= T(ias)*2 */
844 g_msc_sccp_timer_ias := 2;
845 g_msc_sccp_timer_iar := 5;
846
847 f_init();
848
849 vc_conn := f_start_handler(refers(f_lu_and_mo_call_sccp_tiar_timeout), 89);
850 vc_conn.done;
851}
852
Harald Weltee13cfb22019-04-23 16:52:02 +0200853
Harald Welte071ed732018-01-23 19:53:52 +0100854/* Test LU (with authentication enabled), where HLR times out sending SAI response */
Harald Weltee13cfb22019-04-23 16:52:02 +0200855friend function f_tc_lu_auth_sai_timeout(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +0100856 f_init_handler(pars);
Harald Welte071ed732018-01-23 19:53:52 +0100857
858 var PDU_ML3_MS_NW l3_lu := f_build_lu_imsi(g_pars.imsi)
859 var PDU_DTAP_MT dtap_mt;
860
861 /* tell GSUP dispatcher to send this IMSI to us */
862 f_create_gsup_expect(hex2str(g_pars.imsi));
863
864 /* Send BSSAP_Conn_Req with COMPL L3 INFO to MSC */
Harald Weltedceacc72019-04-21 20:58:35 +0200865 f_cl3_or_initial_ue(l3_lu);
Harald Welte071ed732018-01-23 19:53:52 +0100866
867 /* Send Early Classmark, just for the fun of it */
Harald Weltee13cfb22019-04-23 16:52:02 +0200868 if (pars.ran_is_geran) {
869 BSSAP.send(ts_BSSMAP_ClassmarkUpd(g_pars.cm2, g_pars.cm3));
870 }
Harald Welte071ed732018-01-23 19:53:52 +0100871
872 GSUP.receive(tr_GSUP_SAI_REQ(g_pars.imsi));
873 /* The HLR would normally return an auth vector here, but we fail to do so. */
874
875 BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Rej));
Harald Welte1ddc7162018-01-27 14:25:46 +0100876 f_expect_clear();
Harald Welte071ed732018-01-23 19:53:52 +0100877}
878testcase TC_lu_auth_sai_timeout() runs on MTC_CT {
879 var BSC_ConnHdlr vc_conn;
880 f_init();
Harald Welte3ca1c902018-01-24 18:51:27 +0100881 f_vty_config(MSCVTY, "network", "authentication required");
Harald Welte071ed732018-01-23 19:53:52 +0100882
Neels Hofmeyr4e18ccc2020-06-24 19:08:17 +0200883 vc_conn := f_start_handler(refers(f_tc_lu_auth_sai_timeout), 8, verify_cell_id := false);
Harald Welte071ed732018-01-23 19:53:52 +0100884 vc_conn.done;
885}
886
Harald Weltee13cfb22019-04-23 16:52:02 +0200887
Harald Welte071ed732018-01-23 19:53:52 +0100888/* Test LU (with authentication enabled), where HLR rejects sending SAI error */
Harald Weltee13cfb22019-04-23 16:52:02 +0200889friend function f_tc_lu_auth_sai_err(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +0100890 f_init_handler(pars);
Harald Welte071ed732018-01-23 19:53:52 +0100891
892 var PDU_ML3_MS_NW l3_lu := f_build_lu_imsi(g_pars.imsi)
893 var PDU_DTAP_MT dtap_mt;
894
895 /* tell GSUP dispatcher to send this IMSI to us */
896 f_create_gsup_expect(hex2str(g_pars.imsi));
897
898 /* Send BSSAP_Conn_Req with COMPL L3 INFO to MSC */
Harald Weltedceacc72019-04-21 20:58:35 +0200899 f_cl3_or_initial_ue(l3_lu);
Harald Welte071ed732018-01-23 19:53:52 +0100900
901 /* Send Early Classmark, just for the fun of it */
Harald Weltee13cfb22019-04-23 16:52:02 +0200902 if (pars.ran_is_geran) {
903 BSSAP.send(ts_BSSMAP_ClassmarkUpd(g_pars.cm2, g_pars.cm3));
904 }
Harald Welte071ed732018-01-23 19:53:52 +0100905
906 GSUP.receive(tr_GSUP_SAI_REQ(g_pars.imsi));
907 GSUP.send(ts_GSUP_SAI_ERR(g_pars.imsi, 13));
908
909 BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Rej));
Harald Welte1ddc7162018-01-27 14:25:46 +0100910 f_expect_clear();
Harald Welte071ed732018-01-23 19:53:52 +0100911}
912testcase TC_lu_auth_sai_err() runs on MTC_CT {
913 var BSC_ConnHdlr vc_conn;
914 f_init();
Harald Welte3ca1c902018-01-24 18:51:27 +0100915 f_vty_config(MSCVTY, "network", "authentication required");
Harald Welte071ed732018-01-23 19:53:52 +0100916
Neels Hofmeyr4e18ccc2020-06-24 19:08:17 +0200917 vc_conn := f_start_handler(refers(f_tc_lu_auth_sai_err), 9, verify_cell_id := false);
Harald Welte2bb825f2018-01-22 11:31:18 +0100918 vc_conn.done;
919}
Harald Weltea49e36e2018-01-21 19:29:33 +0100920
Harald Weltee13cfb22019-04-23 16:52:02 +0200921
Harald Weltebc881782018-01-23 20:09:15 +0100922/* Test LU but BSC will send a clear request in the middle */
923private function f_tc_lu_clear_request(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +0100924 f_init_handler(pars);
Harald Weltebc881782018-01-23 20:09:15 +0100925
926 var PDU_ML3_MS_NW l3_lu := f_build_lu_imsi(g_pars.imsi)
927 var PDU_DTAP_MT dtap_mt;
928
929 /* tell GSUP dispatcher to send this IMSI to us */
930 f_create_gsup_expect(hex2str(g_pars.imsi));
931
932 /* Send BSSAP_Conn_Req with COMPL L3 INFO to MSC */
Harald Weltedceacc72019-04-21 20:58:35 +0200933 f_cl3_or_initial_ue(l3_lu);
Harald Welte79f1e452020-08-18 22:55:02 +0200934 f_expect_common_id();
Harald Weltebc881782018-01-23 20:09:15 +0100935
936 /* Send Early Classmark, just for the fun of it */
937 BSSAP.send(ts_BSSMAP_ClassmarkUpd(g_pars.cm2, g_pars.cm3));
938
939 f_sleep(1.0);
940 /* send clear request in the middle of the LU */
941 BSSAP.send(ts_BSSMAP_ClearRequest(0));
Neels Hofmeyr2b326fa2018-04-06 00:59:36 +0200942 alt {
943 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Rej)) { repeat; }
944 [] BSSAP.receive(tr_BSSMAP_ClearCommand) {}
945 }
Harald Weltebc881782018-01-23 20:09:15 +0100946 BSSAP.send(ts_BSSMAP_ClearComplete);
Harald Welte89a32492018-01-27 19:07:28 +0100947 alt {
948 /* See https://osmocom.org/issues/2862 */
Neels Hofmeyr2b326fa2018-04-06 00:59:36 +0200949 [] BSSAP.receive(tr_BSSMAP_ClearCommand) {
950 setverdict(fail, "Got a second Clear Command, only one expected");
Daniel Willmannafce8662018-07-06 23:11:32 +0200951 mtc.stop;
Neels Hofmeyr2b326fa2018-04-06 00:59:36 +0200952 repeat;
953 }
Harald Welte6811d102019-04-14 22:23:14 +0200954 [] BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_IND) {}
Harald Welte89a32492018-01-27 19:07:28 +0100955 }
Harald Weltebc881782018-01-23 20:09:15 +0100956 setverdict(pass);
957}
958testcase TC_lu_clear_request() runs on MTC_CT {
959 var BSC_ConnHdlr vc_conn;
960 f_init();
961
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +0100962 vc_conn := f_start_handler(refers(f_tc_lu_clear_request), 10);
Harald Weltebc881782018-01-23 20:09:15 +0100963 vc_conn.done;
964}
965
Vadim Yanitskiy109e7552021-02-05 05:36:02 +0100966/* Test reaction on Clear Request during a MO Call */
967friend function f_TC_mo_mt_call_clear_request(charstring id, BSC_ConnHdlrPars pars)
968runs on BSC_ConnHdlr {
969 var CallParameters cpars := valueof(t_CallParams);
970 var MNCC_PDU mncc_pdu;
971 timer T := 2.0;
972
973 f_init_handler(pars);
974
975 f_perform_lu();
976
977 /* HACK: reducing code duplication ('66'H - MO, '68'H - MT) */
978 if (pars.imsi == '262420002532766'H)
979 { f_mo_call_establish(cpars); }
980 else
981 { f_mt_call_establish(cpars); }
982
983 /* Hold the line for a while... */
984 f_sleep(2.0);
985
986 /* BSC sends BSSMAP Clear Request (e.g. due to RR failure) */
987 BSSAP.send(ts_BSSMAP_ClearRequest(1));
988
989 /* Expect (optional) CC RELEASE and Clear Command */
990 var default ccrel := activate(as_optional_cc_rel(cpars));
991 f_expect_clear();
992 deactivate(ccrel);
993
994 /* Expect RELease indication on the MNCC socket */
995 T.start;
996 alt {
997 [] MNCC.receive(tr_MNCC_REL_ind(cpars.mncc_callref)) -> value mncc_pdu {
998 log("Rx MNCC REL.ind, cause := ", mncc_pdu.u.signal.cause);
999 setverdict(pass);
1000 }
1001 [] MNCC.receive(MNCC_PDU:?) -> value mncc_pdu {
1002 setverdict(fail, "Rx unexpected MNCC PDU: ", mncc_pdu);
1003 }
1004 [] T.timeout {
1005 setverdict(fail, "Timeout waiting for MNCC REL.ind");
1006 }
1007 }
1008}
1009testcase TC_mo_call_clear_request() runs on MTC_CT {
1010 var BSC_ConnHdlr vc_conn;
1011
1012 f_init();
1013
1014 vc_conn := f_start_handler(refers(f_TC_mo_mt_call_clear_request), 2532766); // '66'H - MO
1015 vc_conn.done;
1016}
1017testcase TC_mt_call_clear_request() runs on MTC_CT {
1018 var BSC_ConnHdlr vc_conn;
1019
1020 f_init();
1021
1022 vc_conn := f_start_handler(refers(f_TC_mo_mt_call_clear_request), 2532768); // '68'H - MT
1023 vc_conn.done;
1024}
1025
Harald Welte66af9e62018-01-24 17:28:21 +01001026/* Test LU but BSC will send a clear request in the middle */
Harald Weltee13cfb22019-04-23 16:52:02 +02001027friend function f_tc_lu_disconnect(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +01001028 f_init_handler(pars);
Harald Welte66af9e62018-01-24 17:28:21 +01001029
1030 var PDU_ML3_MS_NW l3_lu := f_build_lu_imsi(g_pars.imsi)
1031 var PDU_DTAP_MT dtap_mt;
1032
1033 /* tell GSUP dispatcher to send this IMSI to us */
1034 f_create_gsup_expect(hex2str(g_pars.imsi));
1035
1036 /* Send BSSAP_Conn_Req with COMPL L3 INFO to MSC */
Harald Weltedceacc72019-04-21 20:58:35 +02001037 f_cl3_or_initial_ue(l3_lu);
Harald Welte66af9e62018-01-24 17:28:21 +01001038
1039 /* Send Early Classmark, just for the fun of it */
Harald Weltee13cfb22019-04-23 16:52:02 +02001040 if (pars.ran_is_geran) {
1041 BSSAP.send(ts_BSSMAP_ClassmarkUpd(g_pars.cm2, g_pars.cm3));
1042 }
Harald Welte66af9e62018-01-24 17:28:21 +01001043
1044 f_sleep(1.0);
1045 /* send clear request in the middle of the LU */
Harald Welte6811d102019-04-14 22:23:14 +02001046 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
Harald Welte66af9e62018-01-24 17:28:21 +01001047 setverdict(pass);
Neels Hofmeyrbb825c92019-03-06 15:35:50 +01001048 f_sleep(1.0);
Harald Welte66af9e62018-01-24 17:28:21 +01001049}
1050testcase TC_lu_disconnect() runs on MTC_CT {
1051 var BSC_ConnHdlr vc_conn;
1052 f_init();
1053
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001054 vc_conn := f_start_handler(refers(f_tc_lu_disconnect), 11);
Harald Welte66af9e62018-01-24 17:28:21 +01001055 vc_conn.done;
1056}
1057
Harald Welteba7b6d92018-01-23 21:32:34 +01001058/* Test LU but with illegal mobile identity type = IMEI */
Harald Weltee13cfb22019-04-23 16:52:02 +02001059friend function f_tc_lu_by_imei(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +01001060 f_init_handler(pars);
Harald Welteba7b6d92018-01-23 21:32:34 +01001061
Harald Welte256571e2018-01-24 18:47:19 +01001062 var PDU_ML3_MS_NW l3_lu := f_build_lu_imei(g_pars.imei)
Harald Welteba7b6d92018-01-23 21:32:34 +01001063 var PDU_DTAP_MT dtap_mt;
1064
1065 /* tell GSUP dispatcher to send this IMSI to us */
1066 f_create_gsup_expect(hex2str(g_pars.imsi));
1067
1068 /* Send BSSAP_Conn_Req with COMPL L3 INFO to MSC */
Harald Weltedceacc72019-04-21 20:58:35 +02001069 f_cl3_or_initial_ue(l3_lu);
Harald Welteba7b6d92018-01-23 21:32:34 +01001070
1071 /* Send Early Classmark, just for the fun of it */
Harald Weltee13cfb22019-04-23 16:52:02 +02001072 if (pars.ran_is_geran) {
1073 BSSAP.send(ts_BSSMAP_ClassmarkUpd(g_pars.cm2, g_pars.cm3));
1074 }
Harald Welteba7b6d92018-01-23 21:32:34 +01001075 /* wait for LU reject, ignore any ID REQ */
1076 alt {
1077 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Rej)) { }
1078 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_MM_ID_Req)) { repeat; }
1079 }
1080 /* wait for normal teardown */
Harald Welte1ddc7162018-01-27 14:25:46 +01001081 f_expect_clear();
Harald Welteba7b6d92018-01-23 21:32:34 +01001082}
1083testcase TC_lu_by_imei() runs on MTC_CT {
1084 var BSC_ConnHdlr vc_conn;
1085 f_init();
1086
Neels Hofmeyr4e18ccc2020-06-24 19:08:17 +02001087 vc_conn := f_start_handler(refers(f_tc_lu_by_imei), 12, verify_cell_id := false);
Harald Welteba7b6d92018-01-23 21:32:34 +01001088 vc_conn.done;
1089}
1090
Harald Weltee13cfb22019-04-23 16:52:02 +02001091
Harald Welteba7b6d92018-01-23 21:32:34 +01001092/* Test LU by TMSI with unknown TMSI, expect (and answer) ID REQ. */
1093private function f_tc_lu_tmsi_noauth_unknown(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Stefan Sperling04fc4bc2018-06-25 17:44:57 +02001094 /* We piggyback a test for an MSC crash on overlong IMSI (OS#2864) onto this test. */
1095 var hexstring overlong_imsi := '012345789ABCDEF0123456789ABCDEF'H;
Harald Weltea10db902018-01-27 12:44:49 +01001096 f_init_handler(pars);
Harald Welteba7b6d92018-01-23 21:32:34 +01001097
1098 var PDU_ML3_MS_NW l3_lu := f_build_lu_tmsi('01020304'O); /* FIXME: Random */
1099 var PDU_DTAP_MT dtap_mt;
1100
1101 /* tell GSUP dispatcher to send this IMSI to us */
1102 f_create_gsup_expect(hex2str(g_pars.imsi));
1103
1104 /* Send BSSAP_Conn_Req with COMPL L3 INFO to MSC */
Harald Weltedceacc72019-04-21 20:58:35 +02001105 f_cl3_or_initial_ue(l3_lu);
Harald Welteba7b6d92018-01-23 21:32:34 +01001106
1107 /* Send Early Classmark, just for the fun of it */
1108 BSSAP.send(ts_BSSMAP_ClassmarkUpd(g_pars.cm2, g_pars.cm3));
1109
1110 /* Wait for + respond to ID REQ (IMSI) */
Oliver Smith32898452019-07-09 12:32:35 +02001111 BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_MM_ID_Req(CM_ID_TYPE_IMSI)));
Stefan Sperling04fc4bc2018-06-25 17:44:57 +02001112 BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_MM_ID_Rsp_IMSI(overlong_imsi))); /* test for OS#2864 */
Harald Welteba7b6d92018-01-23 21:32:34 +01001113 BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_MM_ID_Rsp_IMSI(g_pars.imsi)));
Harald Welte79f1e452020-08-18 22:55:02 +02001114 f_expect_common_id();
Harald Welteba7b6d92018-01-23 21:32:34 +01001115
1116 /* Expect MSC to do UpdateLocation to HLR; respond to it */
1117 GSUP.receive(tr_GSUP_UL_REQ(g_pars.imsi));
1118 GSUP.send(ts_GSUP_ISD_REQ(g_pars.imsi, g_pars.msisdn));
1119 GSUP.receive(tr_GSUP_ISD_RES(g_pars.imsi));
1120 GSUP.send(ts_GSUP_UL_RES(g_pars.imsi));
1121
1122 alt {
Harald Welte7ec4fa82018-01-27 10:57:40 +01001123 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Acc)) {
1124 BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_TmsiRealloc_Cmpl));
1125 }
Harald Welteba7b6d92018-01-23 21:32:34 +01001126 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Rej)) {
1127 setverdict(fail, "Expected LU ACK, but received REJ");
Daniel Willmannafce8662018-07-06 23:11:32 +02001128 mtc.stop;
Harald Welteba7b6d92018-01-23 21:32:34 +01001129 }
1130 }
1131
Philipp Maier9b690e42018-12-21 11:50:03 +01001132 /* Wait for MM-Information (if enabled) */
1133 f_expect_mm_info();
1134
Harald Welteba7b6d92018-01-23 21:32:34 +01001135 /* wait for normal teardown */
Harald Welte1ddc7162018-01-27 14:25:46 +01001136 f_expect_clear();
Harald Welteba7b6d92018-01-23 21:32:34 +01001137}
1138testcase TC_lu_by_tmsi_noauth_unknown() runs on MTC_CT {
1139 var BSC_ConnHdlr vc_conn;
1140 f_init();
1141
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001142 vc_conn := f_start_handler(refers(f_tc_lu_tmsi_noauth_unknown), 13);
Harald Welteba7b6d92018-01-23 21:32:34 +01001143 vc_conn.done;
1144}
1145
Neels Hofmeyrfc06c732020-08-19 12:52:28 +00001146/* Test LU by unknown TMSI, while the IMSI is already attached: osmo-msc should switch to the attached vlr_subscr. */
1147private function f_tc_attached_imsi_lu_unknown_tmsi(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
1148 f_init_handler(pars);
1149
1150 var PDU_ML3_MS_NW l3_lu := f_build_lu_tmsi('56111111'O);
1151 var PDU_DTAP_MT dtap_mt;
1152
1153 /* tell GSUP dispatcher to send this IMSI to us */
1154 f_create_gsup_expect(hex2str(g_pars.imsi));
1155
1156 /* Send BSSAP_Conn_Req with COMPL L3 INFO to MSC */
1157 f_cl3_or_initial_ue(l3_lu);
1158
1159 /* Send Early Classmark, just for the fun of it */
1160 BSSAP.send(ts_BSSMAP_ClassmarkUpd(g_pars.cm2, g_pars.cm3));
1161
1162 /* Wait for + respond to ID REQ (IMSI) */
1163 BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_MM_ID_Req(CM_ID_TYPE_IMSI)));
1164 BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_MM_ID_Rsp_IMSI(g_pars.imsi)));
1165 f_expect_common_id();
1166
1167 /* Expect MSC to do UpdateLocation to HLR; respond to it */
1168 GSUP.receive(tr_GSUP_UL_REQ(g_pars.imsi));
1169 GSUP.send(ts_GSUP_ISD_REQ(g_pars.imsi, g_pars.msisdn));
1170 GSUP.receive(tr_GSUP_ISD_RES(g_pars.imsi));
1171 GSUP.send(ts_GSUP_UL_RES(g_pars.imsi));
1172
1173 alt {
1174 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Acc)) {
1175 BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_TmsiRealloc_Cmpl));
1176 }
1177 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Rej)) {
1178 setverdict(fail, "Expected LU ACK, but received REJ");
1179 mtc.stop;
1180 }
1181 }
1182
1183 /* Wait for MM-Information (if enabled) */
1184 f_expect_mm_info();
1185
1186 /* wait for normal teardown */
Eric Wild85cc1612022-03-30 01:44:29 +02001187 f_expect_clear(verify_vlr_cell_id := false);
Neels Hofmeyrfc06c732020-08-19 12:52:28 +00001188
1189 /* Now the same IMSI is still attached in the VLR, and a LU with an unknown TMSI reveals the same IMSI only
1190 * later during ID Response. osmo-msc first creates a new vlr_subscr for the unknown TMSI, and as soon as the
1191 * IMSI becomes known, must notice that this IMSI is still regarded as attached, and must not create evil twins.
1192 */
1193
1194 /* (since the TMSI Reallocation happened, we could do this with exactly the same TMSI as above, but for test
1195 * readability just use a different one.) */
1196 l3_lu := f_build_lu_tmsi('56222222'O);
1197 f_cl3_or_initial_ue(l3_lu);
1198
1199 /* Wait for + respond to ID REQ (IMSI) */
1200 BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_MM_ID_Req(CM_ID_TYPE_IMSI)));
1201 BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_MM_ID_Rsp_IMSI(g_pars.imsi)));
1202 f_expect_common_id();
1203
1204 /* Expect MSC to do UpdateLocation to HLR; respond to it */
1205 GSUP.receive(tr_GSUP_UL_REQ(g_pars.imsi));
1206 GSUP.send(ts_GSUP_ISD_REQ(g_pars.imsi, g_pars.msisdn));
1207 GSUP.receive(tr_GSUP_ISD_RES(g_pars.imsi));
1208 GSUP.send(ts_GSUP_UL_RES(g_pars.imsi));
1209
1210 alt {
1211 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Acc)) {
1212 BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_TmsiRealloc_Cmpl));
1213 }
1214 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Rej)) {
1215 setverdict(fail, "Expected LU ACK, but received REJ");
1216 mtc.stop;
1217 }
1218 }
1219
1220 /* Wait for MM-Information (if enabled) */
1221 f_expect_mm_info();
1222
1223 /* wait for normal teardown */
Eric Wild85cc1612022-03-30 01:44:29 +02001224 f_expect_clear(verify_vlr_cell_id := false);
Neels Hofmeyrfc06c732020-08-19 12:52:28 +00001225}
1226testcase TC_attached_imsi_lu_unknown_tmsi() runs on MTC_CT {
1227 var BSC_ConnHdlr vc_conn;
1228 f_init();
1229
1230 vc_conn := f_start_handler(refers(f_tc_attached_imsi_lu_unknown_tmsi), 56);
1231 vc_conn.done;
1232}
1233
Harald Welte4d15fa72020-08-19 08:58:28 +02001234friend function f_imsi_detach_by_imsi() runs on BSC_ConnHdlr {
Harald Welte45164da2018-01-24 12:51:27 +01001235 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
1236
1237 /* Send BSSAP_Conn_Req with COMPL L3 INFO to MSC */
Harald Weltedceacc72019-04-21 20:58:35 +02001238 f_cl3_or_initial_ue(valueof(ts_ML3_MO_MM_IMSI_DET_Ind(mi)));
Harald Welte45164da2018-01-24 12:51:27 +01001239
1240 /* Send Early Classmark, just for the fun of it? */
Harald Welte4d15fa72020-08-19 08:58:28 +02001241 if (g_pars.ran_is_geran) {
Harald Weltee13cfb22019-04-23 16:52:02 +02001242 BSSAP.send(ts_BSSMAP_ClassmarkUpd(g_pars.cm2, g_pars.cm3));
1243 }
Harald Welte45164da2018-01-24 12:51:27 +01001244
1245 /* wait for normal teardown */
Harald Welte4d15fa72020-08-19 08:58:28 +02001246 f_expect_clear(verify_vlr_cell_id := false);
1247}
1248
1249
1250/* Test IMSI DETACH (MI=IMSI) */
1251friend function f_tc_imsi_detach_by_imsi(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
1252 f_init_handler(pars);
1253
1254 f_imsi_detach_by_imsi();
Harald Welte45164da2018-01-24 12:51:27 +01001255}
1256testcase TC_imsi_detach_by_imsi() runs on MTC_CT {
1257 var BSC_ConnHdlr vc_conn;
1258 f_init();
1259
Neels Hofmeyr4e18ccc2020-06-24 19:08:17 +02001260 vc_conn := f_start_handler(refers(f_tc_imsi_detach_by_imsi), 14, verify_cell_id := false);
Harald Welte45164da2018-01-24 12:51:27 +01001261 vc_conn.done;
1262}
1263
Harald Weltee13cfb22019-04-23 16:52:02 +02001264
Harald Welte45164da2018-01-24 12:51:27 +01001265/* Test IMSI DETACH (MI=TMSI) */
Harald Weltee13cfb22019-04-23 16:52:02 +02001266friend function f_tc_imsi_detach_by_tmsi(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +01001267 f_init_handler(pars);
Harald Welte45164da2018-01-24 12:51:27 +01001268
1269 var MobileIdentityLV mi := valueof(ts_MI_TMSI_LV('01020304'O));
1270
1271 /* Send BSSAP_Conn_Req with COMPL L3 INFO to MSC */
Harald Weltedceacc72019-04-21 20:58:35 +02001272 f_cl3_or_initial_ue(valueof(ts_ML3_MO_MM_IMSI_DET_Ind(mi)));
Harald Welte45164da2018-01-24 12:51:27 +01001273
1274 /* Send Early Classmark, just for the fun of it? */
Harald Weltee13cfb22019-04-23 16:52:02 +02001275 if (pars.ran_is_geran) {
1276 BSSAP.send(ts_BSSMAP_ClassmarkUpd(g_pars.cm2, g_pars.cm3));
1277 }
Harald Welte45164da2018-01-24 12:51:27 +01001278
1279 /* wait for normal teardown */
Harald Welte1ddc7162018-01-27 14:25:46 +01001280 f_expect_clear();
Harald Welte45164da2018-01-24 12:51:27 +01001281}
1282testcase TC_imsi_detach_by_tmsi() runs on MTC_CT {
1283 var BSC_ConnHdlr vc_conn;
1284 f_init();
1285
Neels Hofmeyr4e18ccc2020-06-24 19:08:17 +02001286 vc_conn := f_start_handler(refers(f_tc_imsi_detach_by_tmsi), 15, verify_cell_id := false);
Harald Welte45164da2018-01-24 12:51:27 +01001287 vc_conn.done;
1288}
1289
Harald Weltee13cfb22019-04-23 16:52:02 +02001290
Harald Welte45164da2018-01-24 12:51:27 +01001291/* Test IMSI DETACH (MI=IMEI), which is illegal */
Harald Weltee13cfb22019-04-23 16:52:02 +02001292friend function f_tc_imsi_detach_by_imei(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +01001293 f_init_handler(pars);
Harald Welte45164da2018-01-24 12:51:27 +01001294
Harald Welte256571e2018-01-24 18:47:19 +01001295 var MobileIdentityLV mi := valueof(ts_MI_IMEI_LV(g_pars.imei));
Harald Welte45164da2018-01-24 12:51:27 +01001296
1297 /* Send BSSAP_Conn_Req with COMPL L3 INFO to MSC */
Harald Weltedceacc72019-04-21 20:58:35 +02001298 f_cl3_or_initial_ue(valueof(ts_ML3_MO_MM_IMSI_DET_Ind(mi)));
Harald Welte45164da2018-01-24 12:51:27 +01001299
1300 /* Send Early Classmark, just for the fun of it? */
Harald Weltee13cfb22019-04-23 16:52:02 +02001301 if (pars.ran_is_geran) {
1302 BSSAP.send(ts_BSSMAP_ClassmarkUpd(g_pars.cm2, g_pars.cm3));
1303 }
Harald Welte45164da2018-01-24 12:51:27 +01001304
1305 /* wait for normal teardown */
Harald Welte1ddc7162018-01-27 14:25:46 +01001306 f_expect_clear();
Harald Welte45164da2018-01-24 12:51:27 +01001307}
1308testcase TC_imsi_detach_by_imei() runs on MTC_CT {
1309 var BSC_ConnHdlr vc_conn;
1310 f_init();
1311
Neels Hofmeyr4e18ccc2020-06-24 19:08:17 +02001312 vc_conn := f_start_handler(refers(f_tc_imsi_detach_by_imei), 16, verify_cell_id := false);
Harald Welte45164da2018-01-24 12:51:27 +01001313 vc_conn.done;
1314}
1315
1316
1317/* helper function for an emergency call. caller passes in mobile identity to use */
1318private function f_emerg_call(MobileIdentityLV mi) runs on BSC_ConnHdlr {
Harald Welte0bef21e2018-02-10 09:48:23 +01001319 var CallParameters cpars := valueof(t_CallParams('112'H, 0));
1320 cpars.emergency := true;
Harald Welte45164da2018-01-24 12:51:27 +01001321
Harald Welte0bef21e2018-02-10 09:48:23 +01001322 f_mo_call(cpars);
Harald Welte45164da2018-01-24 12:51:27 +01001323}
1324
1325/* establish an emergency call by IMEI, no SIM inserted (and hence no IMSI) */
Harald Weltee13cfb22019-04-23 16:52:02 +02001326friend function f_tc_emerg_call_imei_reject(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +01001327 f_init_handler(pars);
Harald Welte45164da2018-01-24 12:51:27 +01001328
Harald Welte256571e2018-01-24 18:47:19 +01001329 var MobileIdentityLV mi := valueof(ts_MI_IMEI_LV(g_pars.imei));
Harald Welte6ed6bf92018-01-24 21:09:15 +01001330 var PDU_ML3_MS_NW l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_EMERG_CALL, mi));
Harald Weltedceacc72019-04-21 20:58:35 +02001331 f_cl3_or_initial_ue(l3_info);
Harald Welte45164da2018-01-24 12:51:27 +01001332 BSSAP.receive(tr_PDU_DTAP_MT(tr_CM_SERV_REJ('05'O)));
Harald Welte1ddc7162018-01-27 14:25:46 +01001333 f_expect_clear();
Harald Welte45164da2018-01-24 12:51:27 +01001334}
1335testcase TC_emerg_call_imei_reject() runs on MTC_CT {
1336 var BSC_ConnHdlr vc_conn;
1337 f_init();
1338
Neels Hofmeyr4e18ccc2020-06-24 19:08:17 +02001339 vc_conn := f_start_handler(refers(f_tc_emerg_call_imei_reject), 17, verify_cell_id := false);
Harald Welte45164da2018-01-24 12:51:27 +01001340 vc_conn.done;
1341}
1342
Harald Weltee13cfb22019-04-23 16:52:02 +02001343
Harald Welted5b91402018-01-24 18:48:16 +01001344/* establish an emergency call by IMSI, SIM inserted (and hence IMSI) */
Harald Weltee13cfb22019-04-23 16:52:02 +02001345friend function f_tc_emerg_call_imsi(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +01001346 f_init_handler(pars);
Harald Welte45164da2018-01-24 12:51:27 +01001347 /* First perform location update to ensure subscriber is known */
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +01001348 f_perform_lu();
Harald Welte45164da2018-01-24 12:51:27 +01001349 /* Then issue emergency call identified by IMSI */
1350 f_emerg_call(valueof(ts_MI_IMSI_LV(g_pars.imsi)));
1351}
1352testcase TC_emerg_call_imsi() runs on MTC_CT {
1353 var BSC_ConnHdlr vc_conn;
1354 f_init();
1355
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001356 vc_conn := f_start_handler(refers(f_tc_emerg_call_imsi), 18);
Harald Welte45164da2018-01-24 12:51:27 +01001357 vc_conn.done;
1358}
1359
Harald Weltee13cfb22019-04-23 16:52:02 +02001360
Harald Welte45164da2018-01-24 12:51:27 +01001361/* CM Service Request for VGCS -> reject */
1362private function f_tc_cm_serv_req_vgcs_reject(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +01001363 f_init_handler(pars);
Harald Welte45164da2018-01-24 12:51:27 +01001364
1365 /* First perform location update to ensure subscriber is known */
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +01001366 f_perform_lu();
Harald Welte45164da2018-01-24 12:51:27 +01001367
1368 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
Harald Welte6ed6bf92018-01-24 21:09:15 +01001369 var PDU_ML3_MS_NW l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_VGCS, mi));
Harald Weltedceacc72019-04-21 20:58:35 +02001370 f_cl3_or_initial_ue(l3_info);
Harald Welte45164da2018-01-24 12:51:27 +01001371 BSSAP.receive(tr_PDU_DTAP_MT(tr_CM_SERV_REJ(int2oct(32,1))));
Harald Welte1ddc7162018-01-27 14:25:46 +01001372 f_expect_clear();
Harald Welte45164da2018-01-24 12:51:27 +01001373}
1374testcase TC_cm_serv_req_vgcs_reject() runs on MTC_CT {
1375 var BSC_ConnHdlr vc_conn;
1376 f_init();
1377
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001378 vc_conn := f_start_handler(refers(f_tc_cm_serv_req_vgcs_reject), 19);
Harald Welte45164da2018-01-24 12:51:27 +01001379 vc_conn.done;
1380}
1381
1382/* CM Service Request for VBS -> reject */
1383private function f_tc_cm_serv_req_vbs_reject(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +01001384 f_init_handler(pars);
Harald Welte45164da2018-01-24 12:51:27 +01001385
1386 /* First perform location update to ensure subscriber is known */
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +01001387 f_perform_lu();
Harald Welte45164da2018-01-24 12:51:27 +01001388
1389 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
Harald Welte6ed6bf92018-01-24 21:09:15 +01001390 var PDU_ML3_MS_NW l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_VBS, mi));
Harald Weltedceacc72019-04-21 20:58:35 +02001391 f_cl3_or_initial_ue(l3_info);
Harald Welte45164da2018-01-24 12:51:27 +01001392 BSSAP.receive(tr_PDU_DTAP_MT(tr_CM_SERV_REJ(int2oct(32,1))));
Harald Welte1ddc7162018-01-27 14:25:46 +01001393 f_expect_clear();
Harald Welte45164da2018-01-24 12:51:27 +01001394}
1395testcase TC_cm_serv_req_vbs_reject() runs on MTC_CT {
1396 var BSC_ConnHdlr vc_conn;
1397 f_init();
1398
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001399 vc_conn := f_start_handler(refers(f_tc_cm_serv_req_vbs_reject), 20);
Harald Welte45164da2018-01-24 12:51:27 +01001400 vc_conn.done;
1401}
1402
1403/* CM Service Request for LCS -> reject */
1404private function f_tc_cm_serv_req_lcs_reject(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +01001405 f_init_handler(pars);
Harald Welte45164da2018-01-24 12:51:27 +01001406
1407 /* First perform location update to ensure subscriber is known */
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +01001408 f_perform_lu();
Harald Welte45164da2018-01-24 12:51:27 +01001409
1410 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
Harald Welte6ed6bf92018-01-24 21:09:15 +01001411 var PDU_ML3_MS_NW l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_LCS, mi));
Harald Weltedceacc72019-04-21 20:58:35 +02001412 f_cl3_or_initial_ue(l3_info);
Harald Welte45164da2018-01-24 12:51:27 +01001413 BSSAP.receive(tr_PDU_DTAP_MT(tr_CM_SERV_REJ(int2oct(32,1))));
Harald Welte1ddc7162018-01-27 14:25:46 +01001414 f_expect_clear();
Harald Welte45164da2018-01-24 12:51:27 +01001415}
1416testcase TC_cm_serv_req_lcs_reject() runs on MTC_CT {
1417 var BSC_ConnHdlr vc_conn;
1418 f_init();
1419
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001420 vc_conn := f_start_handler(refers(f_tc_cm_serv_req_lcs_reject), 21);
Harald Welte45164da2018-01-24 12:51:27 +01001421 vc_conn.done;
1422}
1423
Harald Welte0195ab12018-01-24 21:50:20 +01001424/* CM Re-Establishment Request */
1425private function f_tc_cm_reest_req_reject(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +01001426 f_init_handler(pars);
Harald Welte0195ab12018-01-24 21:50:20 +01001427
1428 /* First perform location update to ensure subscriber is known */
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +01001429 f_perform_lu();
Harald Welte0195ab12018-01-24 21:50:20 +01001430
1431 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
1432 var PDU_ML3_MS_NW l3_info := valueof(ts_CM_REEST_REQ(0, mi));
Harald Weltedceacc72019-04-21 20:58:35 +02001433 f_cl3_or_initial_ue(l3_info);
Neels Hofmeyr49bbb512021-07-29 22:51:08 +02001434 /* Older osmo-msc returns: GSM48_REJECT_SRV_OPT_NOT_SUPPORTED = 32,
1435 * newer osmo-msc with CM Re-Establish support returns: GSM48_REJECT_CALL_CAN_NOT_BE_IDENTIFIED = 38 */
1436 BSSAP.receive(tr_PDU_DTAP_MT(tr_CM_SERV_REJ( (int2oct(32,1), int2oct(38,1)) )));
Harald Welte1ddc7162018-01-27 14:25:46 +01001437 f_expect_clear();
Harald Welte0195ab12018-01-24 21:50:20 +01001438}
1439testcase TC_cm_reest_req_reject() runs on MTC_CT {
1440 var BSC_ConnHdlr vc_conn;
1441 f_init();
Harald Welte0195ab12018-01-24 21:50:20 +01001442
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001443 vc_conn := f_start_handler(refers(f_tc_cm_reest_req_reject), 22);
Harald Welte0195ab12018-01-24 21:50:20 +01001444 vc_conn.done;
1445}
1446
Harald Weltec638f4d2018-01-24 22:00:36 +01001447/* Test LU (with authentication enabled), with wrong response from MS */
1448private function f_tc_lu_auth_2G_fail(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +01001449 f_init_handler(pars);
Harald Weltec638f4d2018-01-24 22:00:36 +01001450
1451 var PDU_ML3_MS_NW l3_lu := f_build_lu_imsi(g_pars.imsi)
1452
1453 /* tell GSUP dispatcher to send this IMSI to us */
1454 f_create_gsup_expect(hex2str(g_pars.imsi));
1455
1456 /* Send BSSAP_Conn_Req with COMPL L3 INFO to MSC */
Harald Weltedceacc72019-04-21 20:58:35 +02001457 f_cl3_or_initial_ue(l3_lu);
Harald Weltec638f4d2018-01-24 22:00:36 +01001458
1459 /* Send Early Classmark, just for the fun of it */
1460 BSSAP.send(ts_BSSMAP_ClassmarkUpd(g_pars.cm2, g_pars.cm3));
1461
1462 var AuthVector vec := f_gen_auth_vec_2g();
1463 var GSUP_IE auth_tuple := valueof(ts_GSUP_IE_AuthTuple2G(vec.rand, vec.sres, vec.kc));
1464 GSUP.receive(tr_GSUP_SAI_REQ(g_pars.imsi));
1465 GSUP.send(ts_GSUP_SAI_RES(g_pars.imsi, auth_tuple));
1466
1467 BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_MM_AUTH_REQ(vec.rand)));
1468 /* Send back wrong auth response */
1469 BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MT_MM_AUTH_RESP_2G('00000000'O)));
1470
1471 /* Expect GSUP AUTH FAIL REP to HLR */
1472 GSUP.receive(tr_GSUP_AUTH_FAIL_IND(g_pars.imsi));
1473
1474 /* Expect LU REJECT with Cause == Illegal MS */
1475 BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Rej('03'O)));
Harald Welte1ddc7162018-01-27 14:25:46 +01001476 f_expect_clear();
Harald Weltec638f4d2018-01-24 22:00:36 +01001477}
1478testcase TC_lu_auth_2G_fail() runs on MTC_CT {
1479 var BSC_ConnHdlr vc_conn;
1480 f_init();
1481 f_vty_config(MSCVTY, "network", "authentication required");
Harald Weltec638f4d2018-01-24 22:00:36 +01001482
Neels Hofmeyr4e18ccc2020-06-24 19:08:17 +02001483 vc_conn := f_start_handler(refers(f_tc_lu_auth_2G_fail), 23, verify_cell_id := false);
Harald Weltec638f4d2018-01-24 22:00:36 +01001484 vc_conn.done;
1485}
1486
Harald Weltede371492018-01-27 23:44:41 +01001487/* A5/1 + A5/3 permitted on network side, and MS capable to do it */
Harald Welte16114282018-01-24 22:41:21 +01001488private function f_tc_lu_imsi_auth_tmsi_encr_13_13(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltede371492018-01-27 23:44:41 +01001489 pars.net.expect_auth := true;
1490 pars.net.expect_ciph := true;
Harald Weltea10db902018-01-27 12:44:49 +01001491 f_init_handler(pars);
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +01001492 f_perform_lu();
Harald Welte16114282018-01-24 22:41:21 +01001493}
1494testcase TC_lu_imsi_auth_tmsi_encr_13_13() runs on MTC_CT {
1495 var BSC_ConnHdlr vc_conn;
1496 f_init();
1497 f_vty_config(MSCVTY, "network", "authentication required");
Harald Welte16114282018-01-24 22:41:21 +01001498 f_vty_config(MSCVTY, "network", "encryption a5 1 3");
1499
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001500 vc_conn := f_start_handler(refers(f_tc_lu_imsi_auth_tmsi_encr_13_13), 24);
Harald Welte16114282018-01-24 22:41:21 +01001501 vc_conn.done;
1502}
1503
Harald Welte1af6ea82018-01-25 18:33:15 +01001504/* Test Complete L3 without payload */
1505private function f_tc_cl3_no_payload(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +01001506 f_init_handler(pars);
Harald Welte1af6ea82018-01-25 18:33:15 +01001507
1508 /* Send Complete L3 Info with empty L3 frame */
1509 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_peer, g_pars.sccp_addr_own,
1510 valueof(ts_BSSMAP_ComplL3(g_pars.cell_id, ''O))));
1511
Harald Weltef466eb42018-01-27 14:26:54 +01001512 timer T := 5.0;
1513 T.start;
Harald Welte1af6ea82018-01-25 18:33:15 +01001514 alt {
Harald Welte6811d102019-04-14 22:23:14 +02001515 [] BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_IND) {}
Harald Welte1af6ea82018-01-25 18:33:15 +01001516 /* Expect LU REJECT with Cause == Illegal MS */
Harald Weltebdb3c452018-03-18 22:43:06 +01001517 [] BSSAP.receive(tr_PDU_DTAP_MT(?)) { repeat; }
Harald Welte6811d102019-04-14 22:23:14 +02001518 [] BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND) { repeat; }
Harald Welte5946b332018-03-18 23:32:21 +01001519 [] as_clear_cmd_compl_disc();
Harald Weltef466eb42018-01-27 14:26:54 +01001520 [] T.timeout {
Daniel Willmann90829d62018-02-15 17:45:14 +01001521 setverdict(fail, "Timeout waiting for ClearCommand or SCCP Release");
Daniel Willmannafce8662018-07-06 23:11:32 +02001522 mtc.stop;
Harald Weltef466eb42018-01-27 14:26:54 +01001523 }
Harald Welte1af6ea82018-01-25 18:33:15 +01001524 }
1525 setverdict(pass);
1526}
1527testcase TC_cl3_no_payload() runs on MTC_CT {
1528 var BSC_ConnHdlr vc_conn;
1529 f_init();
1530
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001531 vc_conn := f_start_handler(refers(f_tc_cl3_no_payload), 25);
Harald Welte1af6ea82018-01-25 18:33:15 +01001532 vc_conn.done;
1533}
1534
1535/* Test Complete L3 with random payload */
1536private function f_tc_cl3_rnd_payload(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +01001537 f_init_handler(pars);
Harald Welte1af6ea82018-01-25 18:33:15 +01001538
Daniel Willmannaa14a382018-07-26 08:29:45 +02001539 /* length is limited by PDU_BSSAP length field which includes some
1540 * other fields beside l3info payload. So payl can only be 240 bytes
1541 * Since rnd() returns values < 1 multiply with 241
1542 */
1543 var integer len := float2int(rnd() * 241.0);
Harald Welte1af6ea82018-01-25 18:33:15 +01001544 var octetstring payl := f_rnd_octstring(len);
1545
1546 /* Send Complete L3 Info with empty L3 frame */
1547 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_peer, g_pars.sccp_addr_own,
1548 valueof(ts_BSSMAP_ComplL3(g_pars.cell_id, payl))));
1549
Harald Weltef466eb42018-01-27 14:26:54 +01001550 timer T := 5.0;
1551 T.start;
Harald Welte1af6ea82018-01-25 18:33:15 +01001552 alt {
1553 /* Immediate disconnect */
Harald Welte6811d102019-04-14 22:23:14 +02001554 [] BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_IND) {}
Harald Welte1af6ea82018-01-25 18:33:15 +01001555 [] BSSAP.receive(tr_PDU_DTAP_MT(?)) { repeat; }
Harald Welte6811d102019-04-14 22:23:14 +02001556 [] BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND) { repeat; }
Harald Welte5946b332018-03-18 23:32:21 +01001557 [] as_clear_cmd_compl_disc();
Harald Weltef466eb42018-01-27 14:26:54 +01001558 [] T.timeout {
Daniel Willmann90829d62018-02-15 17:45:14 +01001559 setverdict(fail, "Timeout waiting for ClearCommand or SCCP Release");
Daniel Willmannafce8662018-07-06 23:11:32 +02001560 mtc.stop;
Harald Weltef466eb42018-01-27 14:26:54 +01001561 }
Harald Welte1af6ea82018-01-25 18:33:15 +01001562 }
1563 setverdict(pass);
1564}
1565testcase TC_cl3_rnd_payload() runs on MTC_CT {
1566 var BSC_ConnHdlr vc_conn;
1567 f_init();
1568
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001569 vc_conn := f_start_handler(refers(f_tc_cl3_rnd_payload), 26);
Harald Welte1af6ea82018-01-25 18:33:15 +01001570 vc_conn.done;
1571}
1572
Harald Welte116e4332018-01-26 22:17:48 +01001573/* Test Complete L3 with random payload */
Harald Weltee13cfb22019-04-23 16:52:02 +02001574friend function f_tc_establish_and_nothing(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +01001575 f_init_handler(pars);
Harald Welte116e4332018-01-26 22:17:48 +01001576
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +01001577 f_perform_lu();
Harald Welte116e4332018-01-26 22:17:48 +01001578
Harald Welteb9e86fa2018-04-09 18:18:31 +02001579 f_establish_fully();
Daniel Willmann898a7e02018-05-17 12:16:16 +02001580 f_expect_clear(10.0);
Harald Welte116e4332018-01-26 22:17:48 +01001581}
1582testcase TC_establish_and_nothing() runs on MTC_CT {
1583 var BSC_ConnHdlr vc_conn;
1584 f_init();
1585
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001586 vc_conn := f_start_handler(refers(f_tc_establish_and_nothing), 27);
Harald Welte116e4332018-01-26 22:17:48 +01001587 vc_conn.done;
1588}
1589
Harald Weltee13cfb22019-04-23 16:52:02 +02001590
Harald Welte12510c52018-01-26 22:26:24 +01001591/* Test MO Call SETUP with no response from MNCC */
Harald Weltee13cfb22019-04-23 16:52:02 +02001592friend function f_tc_mo_setup_and_nothing(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Philipp Maier109e6aa2018-10-17 10:53:32 +02001593 f_init_handler(pars, 190.0);
Harald Weltea10db902018-01-27 12:44:49 +01001594
Harald Welte12510c52018-01-26 22:26:24 +01001595 var CallParameters cpars := valueof(t_CallParams('12345'H, 0));
Neels Hofmeyr3c89a6b2019-10-15 16:54:37 +02001596 cpars.mgw_conn_2.resp := 0;
1597 cpars.stop_after_cc_setup := true;
1598
1599 f_vty_config(MSCVTY, "msc", "mncc guard-timeout 20");
Harald Welte12510c52018-01-26 22:26:24 +01001600
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +01001601 f_perform_lu();
Harald Welte12510c52018-01-26 22:26:24 +01001602
Neels Hofmeyr3c89a6b2019-10-15 16:54:37 +02001603 f_mo_call_establish(cpars);
Harald Welte12510c52018-01-26 22:26:24 +01001604
Neels Hofmeyrde76f052019-02-26 05:02:46 +01001605 var default ccrel := activate(as_optional_cc_rel(cpars));
1606
Philipp Maier109e6aa2018-10-17 10:53:32 +02001607 f_expect_clear(185.0);
Neels Hofmeyrde76f052019-02-26 05:02:46 +01001608
1609 deactivate(ccrel);
1610
1611 f_sleep(1.0);
Harald Welte12510c52018-01-26 22:26:24 +01001612}
1613testcase TC_mo_setup_and_nothing() runs on MTC_CT {
1614 var BSC_ConnHdlr vc_conn;
1615 f_init();
1616
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001617 vc_conn := f_start_handler(refers(f_tc_mo_setup_and_nothing), 28);
Harald Welte12510c52018-01-26 22:26:24 +01001618 vc_conn.done;
1619}
1620
Harald Weltee13cfb22019-04-23 16:52:02 +02001621
Harald Welte3ab88002018-01-26 22:37:25 +01001622/* Test MO Call with no response to RAN-side CRCX */
Harald Weltee13cfb22019-04-23 16:52:02 +02001623friend function f_tc_mo_crcx_ran_timeout(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +01001624 f_init_handler(pars);
Harald Welte3ab88002018-01-26 22:37:25 +01001625 var CallParameters cpars := valueof(t_CallParams('12345'H, 0));
1626 var MNCC_PDU mncc;
1627 var MgcpCommand mgcp_cmd;
1628
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +01001629 f_perform_lu();
Neels Hofmeyr3c89a6b2019-10-15 16:54:37 +02001630 /* Do not respond to the second CRCX */
1631 cpars.mgw_conn_2.resp := 0;
1632 f_mo_call_establish(cpars);
Harald Welte3ab88002018-01-26 22:37:25 +01001633
Neels Hofmeyr3c89a6b2019-10-15 16:54:37 +02001634 var default ccrel := activate(as_optional_cc_rel(cpars));
Harald Welte3ab88002018-01-26 22:37:25 +01001635
Neels Hofmeyr3c89a6b2019-10-15 16:54:37 +02001636 f_expect_clear(60.0);
Harald Welte3ab88002018-01-26 22:37:25 +01001637
Neels Hofmeyr3c89a6b2019-10-15 16:54:37 +02001638 deactivate(ccrel);
Harald Welte3ab88002018-01-26 22:37:25 +01001639}
1640testcase TC_mo_crcx_ran_timeout() runs on MTC_CT {
1641 var BSC_ConnHdlr vc_conn;
1642 f_init();
1643
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001644 vc_conn := f_start_handler(refers(f_tc_mo_crcx_ran_timeout), 29);
Harald Welte3ab88002018-01-26 22:37:25 +01001645 vc_conn.done;
1646}
1647
Harald Weltee13cfb22019-04-23 16:52:02 +02001648
Harald Welte0cc82d92018-01-26 22:52:34 +01001649/* Test MO Call with reject to RAN-side CRCX */
Harald Weltee13cfb22019-04-23 16:52:02 +02001650friend function f_tc_mo_crcx_ran_reject(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +01001651 f_init_handler(pars);
Neels Hofmeyr3c89a6b2019-10-15 16:54:37 +02001652
Harald Welte0cc82d92018-01-26 22:52:34 +01001653 var CallParameters cpars := valueof(t_CallParams('12345'H, 0));
Neels Hofmeyr3c89a6b2019-10-15 16:54:37 +02001654
1655 /* Respond with error for the first CRCX */
1656 cpars.mgw_conn_1.resp := -1;
Harald Welte0cc82d92018-01-26 22:52:34 +01001657
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +01001658 f_perform_lu();
Neels Hofmeyr3c89a6b2019-10-15 16:54:37 +02001659 f_mo_call_establish(cpars);
Harald Welte0cc82d92018-01-26 22:52:34 +01001660
Neels Hofmeyr3c89a6b2019-10-15 16:54:37 +02001661 var default ccrel := activate(as_optional_cc_rel(cpars));
1662 f_expect_clear(60.0);
1663 deactivate(ccrel);
Harald Welte0cc82d92018-01-26 22:52:34 +01001664}
1665testcase TC_mo_crcx_ran_reject() runs on MTC_CT {
1666 var BSC_ConnHdlr vc_conn;
1667 f_init();
1668
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001669 vc_conn := f_start_handler(refers(f_tc_mo_crcx_ran_reject), 30);
Harald Welte0cc82d92018-01-26 22:52:34 +01001670 vc_conn.done;
1671}
1672
Harald Welte3ab88002018-01-26 22:37:25 +01001673
Harald Welte812f7a42018-01-27 00:49:18 +01001674/* helper function to start a MT call: MNCC SETUP; Paging; DChan est.; DTAP SETUP */
1675private function f_mt_call_start(inout CallParameters cpars) runs on BSC_ConnHdlr {
1676 var MNCC_PDU mncc;
1677 var MgcpCommand mgcp_cmd;
Harald Welte812f7a42018-01-27 00:49:18 +01001678
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +01001679 f_perform_lu();
Vadim Yanitskiyae747742020-01-10 00:23:10 +01001680 f_ran_register_imsi(g_pars.imsi, g_pars.tmsi);
Harald Welte812f7a42018-01-27 00:49:18 +01001681
1682 /* Allocate call reference and send SETUP via MNCC to MSC */
1683 cpars.mncc_callref := f_rnd_int(2147483648);
1684 MNCC.send(ts_MNCC_SETUP_req(cpars.mncc_callref, hex2str(g_pars.msisdn),
1685 hex2str(cpars.called_party), hex2str(g_pars.imsi)));
1686
1687 /* MSC->BSC: expect PAGING from MSC */
Harald Weltee035e3e2019-04-21 17:32:05 +02001688 f_expect_paging();
1689
Harald Welte812f7a42018-01-27 00:49:18 +01001690 /* MS -> MSC: PAGING RESPONSE */
Harald Welteb9e86fa2018-04-09 18:18:31 +02001691 f_establish_fully(EST_TYPE_PAG_RESP);
Harald Welte812f7a42018-01-27 00:49:18 +01001692
1693 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
1694
1695 /* MSC->MS: SETUP */
1696 BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_CC_SETUP(cpars.transaction_id, *, cpars.called_party)));
1697}
1698
1699/* Test MT Call */
Harald Weltee13cfb22019-04-23 16:52:02 +02001700friend function f_tc_mt_crcx_ran_reject(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +01001701 f_init_handler(pars);
Harald Welte812f7a42018-01-27 00:49:18 +01001702 var CallParameters cpars := valueof(t_CallParams('123456'H, 0));
1703 var MNCC_PDU mncc;
1704 var MgcpCommand mgcp_cmd;
1705
1706 f_mt_call_start(cpars);
1707
1708 /* MS->MSC: CALL CONFIRMED */
1709 BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_CC_CALL_CONF(cpars.transaction_id)));
1710
1711 MNCC.receive(tr_MNCC_CALL_CONF_ind(cpars.mncc_callref));
1712
1713 MGCP.receive(tr_CRCX) -> value mgcp_cmd;
1714 cpars.mgcp_call_id := f_MgcpCmd_extract_call_id(mgcp_cmd);
Philipp Maierf1e02bb2018-03-15 16:30:00 +01001715
1716 /* Detect if the received CRCX is a wildcarded CRCX request. If yes,
1717 * set an endpoint name that fits the pattern. If not, just use the
1718 * endpoint name from the request */
1719 if (match(mgcp_cmd.line.ep, t_MGCP_EP_wildcard)) {
1720 cpars.mgcp_ep := "rtpbridge/1@mgw";
1721 } else {
1722 cpars.mgcp_ep := mgcp_cmd.line.ep;
1723 }
1724
Harald Welte812f7a42018-01-27 00:49:18 +01001725 /* Respond to CRCX with error */
1726 var MgcpResponse mgcp_rsp := {
1727 line := {
1728 code := "542",
1729 trans_id := mgcp_cmd.line.trans_id,
1730 string := "FORCED_FAIL"
1731 },
Harald Welte812f7a42018-01-27 00:49:18 +01001732 sdp := omit
1733 }
Philipp Maierf1e02bb2018-03-15 16:30:00 +01001734 var MgcpParameter mgcp_rsp_param := {
1735 code := "Z",
1736 val := cpars.mgcp_ep
1737 };
1738 mgcp_rsp.params[0] := mgcp_rsp_param;
Harald Welte812f7a42018-01-27 00:49:18 +01001739 MGCP.send(mgcp_rsp);
1740
1741 timer T := 30.0;
1742 T.start;
1743 alt {
Daniel Willmannafce8662018-07-06 23:11:32 +02001744 [] T.timeout {
1745 setverdict(fail, "Timeout waiting for channel release");
1746 mtc.stop;
1747 }
Harald Welte812f7a42018-01-27 00:49:18 +01001748 [] MNCC.receive { repeat; }
1749 [] GSUP.receive { repeat; }
1750 [] MGCP.receive(tr_DLCX(?)) -> value mgcp_cmd {
1751 MGCP.send(ts_DLCX_ACK2(mgcp_cmd.line.trans_id));
1752 f_create_mgcp_delete_ep(cpars.mgcp_ep);
1753 repeat;
1754 }
1755 [] MGCP.receive { repeat; }
Vadim Yanitskiyb3e42cf2024-03-27 16:23:30 +07001756 [] as_optional_cc_rel(cpars); /* repeats internally */
1757 [] as_expect_clear() { setverdict(pass); }
Harald Welte812f7a42018-01-27 00:49:18 +01001758 }
1759}
1760testcase TC_mt_crcx_ran_reject() runs on MTC_CT {
1761 var BSC_ConnHdlr vc_conn;
1762 f_init();
1763
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001764 vc_conn := f_start_handler(refers(f_tc_mt_crcx_ran_reject), 31);
Harald Welte812f7a42018-01-27 00:49:18 +01001765 vc_conn.done;
1766}
1767
1768
Harald Weltee13cfb22019-04-23 16:52:02 +02001769
Harald Welte812f7a42018-01-27 00:49:18 +01001770/* Test MT Call T310 timer */
Harald Weltee13cfb22019-04-23 16:52:02 +02001771friend function f_tc_mt_t310(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Welte812f7a42018-01-27 00:49:18 +01001772 var CallParameters cpars := valueof(t_CallParams('123456'H, 0));
Harald Welte812f7a42018-01-27 00:49:18 +01001773 var MgcpCommand mgcp_cmd;
Vadim Yanitskiyb56701e2021-02-05 01:54:07 +01001774 var PDU_BSSAP bssap;
1775 timer T310;
Harald Welte812f7a42018-01-27 00:49:18 +01001776
Vadim Yanitskiyb56701e2021-02-05 01:54:07 +01001777 f_init_handler(pars);
1778
Neels Hofmeyr05606152023-03-06 22:42:27 +01001779 /* Make sure X2 does not fire in this test. This test does not send a CN RTP port to osmo-msc, which will
1780 * trigger X2 timeout. We want to test T310, so make X2 significantly longer than T310=30s. */
1781 f_vty_config(MSCVTY, "msc", "timer mgw X2 40");
1782
Vadim Yanitskiyb56701e2021-02-05 01:54:07 +01001783 /* Initiate a MT call, establish connection */
Harald Welte812f7a42018-01-27 00:49:18 +01001784 f_mt_call_start(cpars);
1785
1786 /* MS->MSC: CALL CONFIRMED */
1787 BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_CC_CALL_CONF(cpars.transaction_id)));
1788 MNCC.receive(tr_MNCC_CALL_CONF_ind(cpars.mncc_callref));
1789
Vadim Yanitskiyb56701e2021-02-05 01:54:07 +01001790 /* NOTE: MSC is expected to start T310 here */
Harald Welte812f7a42018-01-27 00:49:18 +01001791
Neels Hofmeyrd8a4aee2022-07-25 22:07:24 +02001792 interleave {
Vadim Yanitskiyb56701e2021-02-05 01:54:07 +01001793 /* MSC->MGW: CRCX (first) */
Neels Hofmeyrd8a4aee2022-07-25 22:07:24 +02001794 [] MGCP.receive(tr_CRCX) -> value mgcp_cmd {
1795 f_handle_crcx(cpars, mgcp_cmd); /* MSC<-MGW: OK */
1796 }
Vadim Yanitskiyb56701e2021-02-05 01:54:07 +01001797
1798 /* BSC->BSC: BSSMAP ASSIGNMENT REQ */
Neels Hofmeyrd8a4aee2022-07-25 22:07:24 +02001799 [] BSSAP.receive(tr_BSSMAP_AssignmentReq(omit, ?)) -> value bssap {
1800 BSSAP.send(ts_BSSMAP_AssignmentComplete(omit,
1801 aoip := f_ts_BSSMAP_IE_AoIP_TLA(cpars.bss_rtp_ip, cpars.bss_rtp_port),
1802 speechCodec := ts_BSSMAP_IE_SpeechCodec({ ts_CodecFR })));
1803 }
Vadim Yanitskiyb56701e2021-02-05 01:54:07 +01001804
1805 /* MSC->MGW: MDCX */
Neels Hofmeyrd8a4aee2022-07-25 22:07:24 +02001806 [] MGCP.receive(tr_MDCX) -> value mgcp_cmd {
1807 MGCP.send(ts_MDCX_ACK(mgcp_cmd.line.trans_id, cpars.mgw_conn_1.mgcp_connection_id,
1808 sdp := omit));
1809 }
Vadim Yanitskiyb56701e2021-02-05 01:54:07 +01001810
1811 /* MSC->MGW: CRCX (second) */
Neels Hofmeyrd8a4aee2022-07-25 22:07:24 +02001812 [] MGCP.receive(tr_CRCX) -> value mgcp_cmd {
1813 f_handle_crcx(cpars, mgcp_cmd); /* MSC<-MGW: OK */
Neels Hofmeyrd8a4aee2022-07-25 22:07:24 +02001814 }
Neels Hofmeyrc29e6dc2022-08-09 02:38:10 +02001815
1816 [] MNCC.receive(tr_MNCC_RTP_CREATE(cpars.mncc_callref));
Neels Hofmeyrd8a4aee2022-07-25 22:07:24 +02001817 }
Vadim Yanitskiyb56701e2021-02-05 01:54:07 +01001818
1819 /* Reschedule the guard timeout */
1820 g_Tguard.start(30.0 + 10.0);
1821
1822 /* NOTE: the BSC is expected to respond with CC ALERTING at this state, so
1823 * the MSC would stop T310. However, the idea is to verify T310 expiration
1824 * here, so grab some popcorn and wait for MNCC DISC.ind. */
1825 T310.start(30.0 + 2.0);
Neels Hofmeyre81ef422022-08-07 14:33:06 +02001826 var MNCC_PDU mncc_rx;
Harald Welte812f7a42018-01-27 00:49:18 +01001827 alt {
Vadim Yanitskiyb56701e2021-02-05 01:54:07 +01001828 [] T310.timeout {
1829 setverdict(fail, "Timeout waiting for MNCC DISC.ind due to T310");
Daniel Willmannafce8662018-07-06 23:11:32 +02001830 mtc.stop;
1831 }
Harald Welte812f7a42018-01-27 00:49:18 +01001832 [] MNCC.receive(tr_MNCC_DISC_ind(cpars.mncc_callref)) {
1833 MNCC.send(ts_MNCC_REL_req(cpars.mncc_callref, valueof(ts_MNCC_cause(23))));
Neels Hofmeyr13eeb552022-08-07 14:33:37 +02001834 log("Rx MNCC DISC.ind, T310.read yields ", T310.read);
Vadim Yanitskiyb56701e2021-02-05 01:54:07 +01001835 setverdict(pass);
Harald Welte812f7a42018-01-27 00:49:18 +01001836 }
Neels Hofmeyre81ef422022-08-07 14:33:06 +02001837 [] MNCC.receive(MNCC_PDU:?) -> value mncc_rx {
1838 log("Rx ", mncc_rx);
1839 setverdict(fail, "Expected MNCC DISC.ind, got some other MNCC message instead");
1840 mtc.stop;
1841 }
Harald Welte812f7a42018-01-27 00:49:18 +01001842 }
Vadim Yanitskiyb56701e2021-02-05 01:54:07 +01001843
Harald Welte812f7a42018-01-27 00:49:18 +01001844 BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_CC_DISC(cpars.transaction_id)));
1845 BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_CC_RELEASE(cpars.transaction_id)));
Vadim Yanitskiyb56701e2021-02-05 01:54:07 +01001846 BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_CC_REL_COMPL(cpars.transaction_id, '1'B)));
Harald Welte812f7a42018-01-27 00:49:18 +01001847
1848 alt {
Harald Welte812f7a42018-01-27 00:49:18 +01001849 [] MGCP.receive(tr_DLCX(?)) -> value mgcp_cmd {
1850 MGCP.send(ts_DLCX_ACK2(mgcp_cmd.line.trans_id));
Vadim Yanitskiyb56701e2021-02-05 01:54:07 +01001851 // FIXME: f_create_mgcp_delete_ep(cpars.mgcp_ep);
Harald Welte812f7a42018-01-27 00:49:18 +01001852 repeat;
1853 }
Vadim Yanitskiy4a011fa2024-03-27 16:29:56 +07001854 [] as_expect_clear() { setverdict(pass); }
Harald Welte812f7a42018-01-27 00:49:18 +01001855 }
1856}
1857testcase TC_mt_t310() runs on MTC_CT {
1858 var BSC_ConnHdlr vc_conn;
1859 f_init();
1860
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001861 vc_conn := f_start_handler(refers(f_tc_mt_t310), 32);
Harald Welte812f7a42018-01-27 00:49:18 +01001862 vc_conn.done;
1863}
1864
Harald Weltee13cfb22019-04-23 16:52:02 +02001865
Harald Welte167458a2018-01-27 15:58:16 +01001866/* Perform successful LU + MO call, then GSUP LocationCancel. Subscriber must be denied CM SERV */
Harald Weltee13cfb22019-04-23 16:52:02 +02001867friend function f_tc_gsup_cancel(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Welte167458a2018-01-27 15:58:16 +01001868 f_init_handler(pars);
1869 var CallParameters cpars := valueof(t_CallParams('12345'H, 0));
Harald Welte167458a2018-01-27 15:58:16 +01001870
1871 /* Location Update to make subscriber known */
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +01001872 f_perform_lu();
Harald Welte167458a2018-01-27 15:58:16 +01001873
1874 /* First MO call should succeed */
1875 f_mo_call(cpars);
1876
1877 /* Cancel the subscriber in the VLR */
1878 GSUP.send(ts_GSUP_CL_REQ(g_pars.imsi, OSMO_GSUP_CANCEL_TYPE_WITHDRAW));
1879 alt {
1880 [] GSUP.receive(tr_GSUP_CL_RES(g_pars.imsi)) { }
1881 [] GSUP.receive(tr_GSUP_CL_ERR(g_pars.imsi)) {
1882 setverdict(fail, "Received GSUP Location Cancel Error");
Daniel Willmannafce8662018-07-06 23:11:32 +02001883 mtc.stop;
Harald Welte167458a2018-01-27 15:58:16 +01001884 }
1885 }
1886
1887 /* Follow-up transactions should fail */
1888 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
1889 var PDU_ML3_MS_NW l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, mi));
Harald Weltedceacc72019-04-21 20:58:35 +02001890 f_cl3_or_initial_ue(l3_info);
Harald Welte167458a2018-01-27 15:58:16 +01001891 alt {
1892 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_CM_SERV_REJ)) { }
1893 [] BSSAP.receive {
1894 setverdict(fail, "Received unexpected BSSAP instead of CM SERV REJ");
Daniel Willmannafce8662018-07-06 23:11:32 +02001895 mtc.stop;
Harald Welte167458a2018-01-27 15:58:16 +01001896 }
1897 }
Neels Hofmeyr0f7429a2019-03-07 22:28:41 +01001898
1899 f_expect_clear();
Harald Welte167458a2018-01-27 15:58:16 +01001900 setverdict(pass);
1901}
1902testcase TC_gsup_cancel() runs on MTC_CT {
1903 var BSC_ConnHdlr vc_conn;
1904 f_init();
1905
Neels Hofmeyr4e18ccc2020-06-24 19:08:17 +02001906 vc_conn := f_start_handler(refers(f_tc_gsup_cancel), 33, verify_cell_id := false);
Harald Welte167458a2018-01-27 15:58:16 +01001907 vc_conn.done;
1908}
1909
Harald Weltee13cfb22019-04-23 16:52:02 +02001910
Harald Welte9de84792018-01-28 01:06:35 +01001911/* A5/1 only permitted on network side, and MS capable to do it */
1912private function f_tc_lu_imsi_auth_tmsi_encr_1_13(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
1913 pars.net.expect_auth := true;
1914 pars.net.expect_ciph := true;
1915 pars.net.kc_support := '02'O; /* A5/1 only */
1916 f_init_handler(pars);
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +01001917 f_perform_lu();
Harald Welte9de84792018-01-28 01:06:35 +01001918}
1919testcase TC_lu_imsi_auth_tmsi_encr_1_13() runs on MTC_CT {
1920 var BSC_ConnHdlr vc_conn;
1921 f_init();
1922 f_vty_config(MSCVTY, "network", "authentication required");
1923 f_vty_config(MSCVTY, "network", "encryption a5 1");
1924
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001925 vc_conn := f_start_handler(refers(f_tc_lu_imsi_auth_tmsi_encr_1_13), 34);
Harald Welte9de84792018-01-28 01:06:35 +01001926 vc_conn.done;
1927}
1928
1929/* A5/3 only permitted on network side, and MS capable to do it */
1930private function f_tc_lu_imsi_auth_tmsi_encr_3_13(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
1931 pars.net.expect_auth := true;
1932 pars.net.expect_ciph := true;
1933 pars.net.kc_support := '08'O; /* A5/3 only */
1934 f_init_handler(pars);
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +01001935 f_perform_lu();
Harald Welte9de84792018-01-28 01:06:35 +01001936}
1937testcase TC_lu_imsi_auth_tmsi_encr_3_13() runs on MTC_CT {
1938 var BSC_ConnHdlr vc_conn;
1939 f_init();
1940 f_vty_config(MSCVTY, "network", "authentication required");
1941 f_vty_config(MSCVTY, "network", "encryption a5 3");
1942
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001943 vc_conn := f_start_handler(refers(f_tc_lu_imsi_auth_tmsi_encr_3_13), 35);
Harald Welte9de84792018-01-28 01:06:35 +01001944 vc_conn.done;
1945}
1946
1947/* A5/3 only permitted on network side, and MS with only A5/1 support */
1948private function f_tc_lu_imsi_auth_tmsi_encr_3_1(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
1949 pars.net.expect_auth := true;
1950 pars.net.expect_ciph := true;
1951 pars.net.kc_support := '08'O; /* A5/3 only */
1952 pars.cm2.classmarkInformationType2_oct5.a5_3 := '0'B;
1953 f_init_handler(pars, 15.0);
1954
1955 /* cannot use f_perform_lu() as we expect a reject */
1956 var PDU_ML3_MS_NW l3_lu := f_build_lu_imsi(g_pars.imsi);
1957 f_create_gsup_expect(hex2str(g_pars.imsi));
Harald Weltedceacc72019-04-21 20:58:35 +02001958 f_cl3_or_initial_ue(l3_lu);
Neels Hofmeyr29b8da02018-03-01 18:09:45 +01001959 if (pars.send_early_cm) {
1960 BSSAP.send(ts_BSSMAP_ClassmarkUpd(g_pars.cm2, g_pars.cm3));
1961 } else {
1962 pars.cm1.esind := '0'B;
1963 }
Harald Welte9de84792018-01-28 01:06:35 +01001964 f_mm_auth();
1965 alt {
Daniel Willmann52918e52018-09-20 14:39:09 +02001966 [] BSSAP.receive(tr_BSSMAP_ClassmarkReq) {
1967 BSSAP.send(ts_BSSMAP_ClassmarkUpd(g_pars.cm2, g_pars.cm3));
1968 repeat;
1969 }
Harald Welte5946b332018-03-18 23:32:21 +01001970 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Rej)) {
1971 f_expect_clear();
1972 }
Harald Welte9de84792018-01-28 01:06:35 +01001973 [] BSSAP.receive(tr_BSSMAP_CipherModeCmd(?,?)) {
1974 setverdict(fail, "CipherModeCommand despite no A5 intersection");
Daniel Willmannafce8662018-07-06 23:11:32 +02001975 mtc.stop;
Harald Welte9de84792018-01-28 01:06:35 +01001976 }
1977 [] BSSAP.receive {
Harald Welte458fd372018-03-21 11:26:23 +01001978 setverdict(fail, "Unknown/unexpected BSSAP received");
Daniel Willmannafce8662018-07-06 23:11:32 +02001979 mtc.stop;
Harald Welte9de84792018-01-28 01:06:35 +01001980 }
1981 }
1982 setverdict(pass);
1983}
1984testcase TC_lu_imsi_auth_tmsi_encr_3_1() runs on MTC_CT {
1985 var BSC_ConnHdlr vc_conn;
1986 f_init();
1987 f_vty_config(MSCVTY, "network", "authentication required");
1988 f_vty_config(MSCVTY, "network", "encryption a5 3");
1989
Neels Hofmeyr4e18ccc2020-06-24 19:08:17 +02001990 vc_conn := f_start_handler(refers(f_tc_lu_imsi_auth_tmsi_encr_3_1), 360, verify_cell_id := false);
Neels Hofmeyr29b8da02018-03-01 18:09:45 +01001991 vc_conn.done;
1992}
1993testcase TC_lu_imsi_auth_tmsi_encr_3_1_no_cm() runs on MTC_CT {
1994 var BSC_ConnHdlrPars pars;
1995 var BSC_ConnHdlr vc_conn;
1996 f_init();
1997 f_vty_config(MSCVTY, "network", "authentication required");
1998 f_vty_config(MSCVTY, "network", "encryption a5 3");
1999
Neels Hofmeyr4e18ccc2020-06-24 19:08:17 +02002000 pars := f_init_pars(361, verify_cell_id := false);
Neels Hofmeyr29b8da02018-03-01 18:09:45 +01002001 pars.send_early_cm := false;
2002 vc_conn := f_start_handler_with_pars(refers(f_tc_lu_imsi_auth_tmsi_encr_3_1), pars);
Harald Welte9de84792018-01-28 01:06:35 +01002003 vc_conn.done;
2004}
Neels Hofmeyr1b3c6e32018-03-01 17:52:21 +01002005testcase TC_lu_imsi_auth_tmsi_encr_3_1_log_msc_debug() runs on MTC_CT {
2006 var BSC_ConnHdlr vc_conn;
2007 f_init();
2008 f_vty_config(MSCVTY, "network", "authentication required");
2009 f_vty_config(MSCVTY, "network", "encryption a5 3");
2010
2011 /* Make sure the MSC category is on DEBUG level to trigger the log
2012 * message that is reported in OS#2947 to trigger the segfault */
2013 f_vty_config(MSCVTY, "log stderr", "logging level msc debug");
2014
Neels Hofmeyr4e18ccc2020-06-24 19:08:17 +02002015 vc_conn := f_start_handler(refers(f_tc_lu_imsi_auth_tmsi_encr_3_1), 362, verify_cell_id := false);
Neels Hofmeyr1b3c6e32018-03-01 17:52:21 +01002016 vc_conn.done;
2017}
Harald Welte9de84792018-01-28 01:06:35 +01002018
2019/* A5/1 + A5/3 only permitted on network side, and MS with only A5/2 support */
2020private function f_tc_lu_imsi_auth_tmsi_encr_13_2(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
2021 pars.net.expect_auth := true;
2022 pars.net.expect_ciph := true;
2023 pars.net.kc_support := '0A'O; /* A5/1 + A5/3 */
2024 pars.cm1.a5_1 := '1'B;
2025 pars.cm2.a5_1 := '1'B;
2026 pars.cm2.classmarkInformationType2_oct5.a5_3 := '0'B;
2027 pars.cm2.classmarkInformationType2_oct5.a5_2 := '1'B;
2028 f_init_handler(pars, 15.0);
2029
2030 /* cannot use f_perform_lu() as we expect a reject */
2031 var PDU_ML3_MS_NW l3_lu := f_build_lu_imsi(g_pars.imsi);
2032 f_create_gsup_expect(hex2str(g_pars.imsi));
Harald Weltedceacc72019-04-21 20:58:35 +02002033 f_cl3_or_initial_ue(l3_lu);
Harald Welte9de84792018-01-28 01:06:35 +01002034 BSSAP.send(ts_BSSMAP_ClassmarkUpd(g_pars.cm2, g_pars.cm3));
2035 f_mm_auth();
2036 alt {
Harald Welte5946b332018-03-18 23:32:21 +01002037 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Rej)) {
2038 f_expect_clear();
2039 }
Harald Welte9de84792018-01-28 01:06:35 +01002040 [] BSSAP.receive(tr_BSSMAP_CipherModeCmd(?,?)) {
2041 setverdict(fail, "CipherModeCommand despite no A5 intersection");
Daniel Willmannafce8662018-07-06 23:11:32 +02002042 mtc.stop;
Harald Welte9de84792018-01-28 01:06:35 +01002043 }
2044 [] BSSAP.receive {
Harald Welte458fd372018-03-21 11:26:23 +01002045 setverdict(fail, "Unknown/unexpected BSSAP received");
Daniel Willmannafce8662018-07-06 23:11:32 +02002046 mtc.stop;
Harald Welte9de84792018-01-28 01:06:35 +01002047 }
2048 }
2049 setverdict(pass);
2050}
2051testcase TC_lu_imsi_auth_tmsi_encr_13_2() runs on MTC_CT {
2052 var BSC_ConnHdlr vc_conn;
2053 f_init();
2054 f_vty_config(MSCVTY, "network", "authentication required");
2055 f_vty_config(MSCVTY, "network", "encryption a5 1 3");
2056
Neels Hofmeyr4e18ccc2020-06-24 19:08:17 +02002057 vc_conn := f_start_handler(refers(f_tc_lu_imsi_auth_tmsi_encr_13_2), 37, verify_cell_id := false);
Harald Welte9de84792018-01-28 01:06:35 +01002058 vc_conn.done;
2059}
2060
Eric Wild26f4a622021-05-17 15:27:05 +02002061/* A5/0 + A5/1 + A5/3 + a5/4 only permitted on network side, and MS with only A5/1 support */
2062private function f_tc_lu_imsi_auth_tmsi_encr_0134_1(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
2063 pars.net.expect_auth := true;
2064 pars.net.expect_ciph := true;
2065 pars.net.kc_support := '03'O; /* A5/0 + A5/1 */
2066 pars.cm1.a5_1 := '0'B;
2067 pars.cm2.a5_1 := '0'B;
2068 pars.cm2.classmarkInformationType2_oct5.a5_3 := '0'B;
2069 pars.cm2.classmarkInformationType2_oct5.a5_2 := '0'B;
2070 pars.cm2.classmarkInformationType2_oct5.cm3 := '0'B;
2071 pars.cm3 := omit;
2072 pars.use_umts_aka := true;
2073
2074 f_init_handler(pars, 15.0);
2075 f_perform_lu();
2076}
2077testcase TC_lu_imsi_auth_tmsi_encr_0134_1() runs on MTC_CT {
2078 var BSC_ConnHdlr vc_conn;
2079 f_init();
2080 f_vty_config(MSCVTY, "network", "authentication required");
2081 f_vty_config(MSCVTY, "network", "encryption a5 0 1 3 4");
2082
2083 vc_conn := f_start_handler(refers(f_tc_lu_imsi_auth_tmsi_encr_0134_1), 39);
2084 vc_conn.done;
2085}
2086
2087/* A5/0 + A5/1 + A5/3 + a5/4 only permitted on network side, and MS with A5/3 + A5/4 support */
2088private function f_tc_lu_imsi_auth_tmsi_encr_0134_34(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
2089 pars.net.expect_auth := true;
2090 pars.net.expect_ciph := true;
2091 pars.net.kc_support := '19'O; /* A5/3 + A5/4 */
2092 pars.cm1.a5_1 := '1'B;
2093 pars.cm2.a5_1 := '1'B;
2094 pars.cm2.classmarkInformationType2_oct5.a5_3 := '1'B;
2095 pars.cm2.classmarkInformationType2_oct5.a5_2 := '0'B;
2096 pars.cm2.classmarkInformationType2_oct5.cm3 := '1'B;
2097 pars.cm3 := valueof(ts_CM3_default);
2098 pars.use_umts_aka := true;
2099
2100 f_init_handler(pars, 15.0);
2101 f_perform_lu();
2102}
2103testcase TC_lu_imsi_auth_tmsi_encr_0134_34() runs on MTC_CT {
2104 var BSC_ConnHdlr vc_conn;
2105 f_init();
2106 f_vty_config(MSCVTY, "network", "authentication required");
2107 f_vty_config(MSCVTY, "network", "encryption a5 0 1 3 4");
2108
2109 vc_conn := f_start_handler(refers(f_tc_lu_imsi_auth_tmsi_encr_0134_34), 40);
2110 vc_conn.done;
2111}
2112
2113/* A5/0 + A5/1 + A5/3 + a5/4 only permitted on network side, and MS with A5/3 support but no CM3 */
2114private function f_tc_lu_imsi_auth_tmsi_encr_0134_34_no_cm3(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
2115 pars.net.expect_auth := true;
2116 pars.net.expect_ciph := true;
2117 pars.net.kc_support := '19'O; /* A5/3 + A5/4 */
2118 pars.cm1.a5_1 := '1'B;
2119 pars.cm2.a5_1 := '1'B;
2120 pars.cm2.classmarkInformationType2_oct5.a5_3 := '1'B;
2121 pars.cm2.classmarkInformationType2_oct5.a5_2 := '0'B;
2122 pars.cm2.classmarkInformationType2_oct5.cm3 := '0'B;
2123 pars.cm3 := omit;
2124 pars.use_umts_aka := true;
2125
2126 f_init_handler(pars, 15.0);
2127 f_perform_lu();
2128}
2129testcase TC_lu_imsi_auth_tmsi_encr_0134_34_no_cm3() runs on MTC_CT {
2130 var BSC_ConnHdlr vc_conn;
2131 f_init();
2132 f_vty_config(MSCVTY, "network", "authentication required");
2133 f_vty_config(MSCVTY, "network", "encryption a5 0 1 3 4");
2134
2135 vc_conn := f_start_handler(refers(f_tc_lu_imsi_auth_tmsi_encr_0134_34_no_cm3), 41);
2136 vc_conn.done;
2137}
2138
Harald Welte9de84792018-01-28 01:06:35 +01002139/* A5/0 + A5/1 + A5/3 only permitted on network side, and MS with only A5/2 support */
2140private function f_tc_lu_imsi_auth_tmsi_encr_013_2(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
2141 pars.net.expect_auth := true;
2142 pars.net.expect_ciph := true;
2143 pars.net.kc_support := '0B'O; /* A5/1 + A5/3 */
2144 pars.cm1.a5_1 := '1'B;
2145 pars.cm2.a5_1 := '1'B;
2146 pars.cm2.classmarkInformationType2_oct5.a5_3 := '0'B;
2147 pars.cm2.classmarkInformationType2_oct5.a5_2 := '1'B;
2148 f_init_handler(pars, 15.0);
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +01002149 f_perform_lu();
Harald Welte9de84792018-01-28 01:06:35 +01002150}
2151testcase TC_lu_imsi_auth_tmsi_encr_013_2() runs on MTC_CT {
2152 var BSC_ConnHdlr vc_conn;
2153 f_init();
2154 f_vty_config(MSCVTY, "network", "authentication required");
2155 f_vty_config(MSCVTY, "network", "encryption a5 0 1 3");
2156
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01002157 vc_conn := f_start_handler(refers(f_tc_lu_imsi_auth_tmsi_encr_013_2), 38);
Harald Welte9de84792018-01-28 01:06:35 +01002158 vc_conn.done;
2159}
2160
Harald Welte33ec09b2018-02-10 15:34:46 +01002161/* LU followed by MT call (including paging) */
Neels Hofmeyr8fe8a902019-11-03 05:51:03 +01002162friend function f_tc_lu_and_mt_call(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Welte33ec09b2018-02-10 15:34:46 +01002163 f_init_handler(pars);
Stefan Sperling26d57be2018-11-12 17:03:26 +01002164 var CallParameters cpars := valueof(t_CallParams('12345'H, 0));
Pau Espin Pedrola65697d2019-05-21 12:54:39 +02002165 cpars.use_osmux := pars.use_osmux;
Harald Welte33ec09b2018-02-10 15:34:46 +01002166
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +01002167 f_perform_lu();
Harald Welte33ec09b2018-02-10 15:34:46 +01002168 f_mt_call(cpars);
2169}
2170testcase TC_lu_and_mt_call() runs on MTC_CT {
2171 var BSC_ConnHdlr vc_conn;
2172 f_init();
2173
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01002174 vc_conn := f_start_handler(refers(f_tc_lu_and_mt_call), 39);
Harald Welte33ec09b2018-02-10 15:34:46 +01002175 vc_conn.done;
2176}
2177
Pau Espin Pedrola65697d2019-05-21 12:54:39 +02002178testcase TC_lu_and_mt_call_osmux() runs on MTC_CT {
2179 var BSC_ConnHdlr vc_conn;
2180 f_init(1, false, true, true);
Pau Espin Pedrola65697d2019-05-21 12:54:39 +02002181
2182 vc_conn := f_start_handler(refers(f_tc_lu_and_mt_call), 39, 0, true, true);
2183 vc_conn.done;
2184}
2185
Pau Espin Pedrol833174e2020-09-03 16:46:02 +02002186/* LU followed by MT call (including paging) */
2187friend function f_tc_lu_and_mt_call_ipv6(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
2188 f_init_handler(pars);
2189 var CallParameters cpars := valueof(t_CallParams('12345'H, 0));
2190 cpars.mgw_conn_1.mgw_rtp_ip := "::1";
2191 cpars.mgw_conn_2.mgw_rtp_ip := "::2";
2192 cpars.bss_rtp_ip := "::3";
Pau Espin Pedrol563b3d02020-09-09 20:19:52 +02002193 cpars.mncc_rtp_ip := "::9";
Pau Espin Pedrol833174e2020-09-03 16:46:02 +02002194 f_perform_lu();
2195 f_mt_call(cpars);
2196}
2197testcase TC_lu_and_mt_call_ipv6() runs on MTC_CT {
2198 var BSC_ConnHdlr vc_conn;
2199 f_init();
2200
2201 vc_conn := f_start_handler(refers(f_tc_lu_and_mt_call_ipv6), 39);
2202 vc_conn.done;
2203}
2204
Neels Hofmeyrb58d9742019-11-27 18:44:54 +01002205/* MT call while already Paging */
2206friend function f_tc_lu_and_mt_call_already_paging(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
2207 var CallParameters cpars := valueof(t_CallParams('123456'H, 0));
2208 var SmsParameters spars := valueof(t_SmsPars);
2209 var OCT4 tmsi;
2210
2211 f_init_handler(pars);
2212
2213 /* Perform location update */
2214 f_perform_lu();
2215
2216 /* register an 'expect' for given IMSI (+TMSI) */
2217 if (isvalue(g_pars.tmsi)) {
2218 tmsi := g_pars.tmsi;
2219 } else {
2220 tmsi := 'FFFFFFFF'O;
2221 }
2222 f_ran_register_imsi(g_pars.imsi, tmsi);
2223
2224 log("start Paging by an SMS");
2225 f_vty_sms_send(hex2str(pars.imsi), "2342", "Hello SMS");
2226
2227 /* MSC->BSC: expect PAGING from MSC */
2228 f_expect_paging();
2229
2230 log("MNCC signals MT call, before Paging Response");
Oliver Smith97dc91f2023-05-31 13:53:21 +02002231 f_mt_call_initiate(cpars);
Neels Hofmeyrb58d9742019-11-27 18:44:54 +01002232 f_ran_register_imsi(g_pars.imsi, g_pars.tmsi);
2233
2234 f_sleep(0.5);
2235 log("phone answers Paging, expecting both SMS and MT call to be established");
2236 f_establish_fully(EST_TYPE_PAG_RESP);
2237 spars.tp.ud := 'C8329BFD064D9B53'O;
2238 interleave {
2239 [] BSSAP.receive(f_mt_sms_deliver_pdu(spars)) {
2240 log("Got SMS-DELIVER");
2241 };
2242 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_CC_SETUP(cpars.transaction_id, *, cpars.called_party))) {
2243 log("Got CC Setup");
2244 };
2245 }
2246 setverdict(pass);
2247 log("success, tear down");
2248 var default ccrel := activate(as_optional_cc_rel(cpars));
2249 if (g_pars.ran_is_geran) {
2250 BSSAP.send(ts_BSSMAP_ClearRequest(0));
2251 } else {
2252 BSSAP.send(ts_RANAP_IuReleaseRequest(ts_RanapCause_om_intervention));
2253 }
2254 f_expect_clear();
2255 deactivate(ccrel);
2256 f_vty_sms_clear(hex2str(g_pars.imsi));
2257}
2258testcase TC_lu_and_mt_call_already_paging() runs on MTC_CT {
2259 var BSC_ConnHdlrPars pars;
2260 var BSC_ConnHdlr vc_conn;
2261 f_init();
2262 pars := f_init_pars(391);
2263 vc_conn := f_start_handler_with_pars(refers(f_tc_lu_and_mt_call_already_paging), pars);
2264 vc_conn.done;
2265}
2266
Daniel Willmann8b084372018-02-04 13:35:26 +01002267/* Test MO Call SETUP with DTMF */
2268private function f_tc_mo_setup_dtmf_dup(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
2269 f_init_handler(pars);
2270 var CallParameters cpars := valueof(t_CallParams('12345'H, 0));
Daniel Willmann8b084372018-02-04 13:35:26 +01002271
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +01002272 f_perform_lu();
Daniel Willmann8b084372018-02-04 13:35:26 +01002273 f_mo_seq_dtmf_dup(cpars);
2274}
2275testcase TC_mo_setup_and_dtmf_dup() runs on MTC_CT {
2276 var BSC_ConnHdlr vc_conn;
2277 f_init();
2278
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01002279 vc_conn := f_start_handler(refers(f_tc_mo_setup_dtmf_dup), 39);
Daniel Willmann8b084372018-02-04 13:35:26 +01002280 vc_conn.done;
2281}
Harald Welte9de84792018-01-28 01:06:35 +01002282
Philipp Maier328d1662018-03-07 10:40:27 +01002283testcase TC_cr_before_reset() runs on MTC_CT {
2284 timer T := 4.0;
2285 var boolean reset_ack_seen := false;
2286 f_init_bssap_direct();
2287
Harald Welte3ca0ce12019-04-23 17:18:48 +02002288 f_ran_adapter_start(g_bssap[0]);
Daniel Willmann42d1d5b2018-08-07 15:18:41 +02002289
Daniel Willmanne8018962018-08-21 14:18:00 +02002290 f_sleep(3.0);
2291
Philipp Maier328d1662018-03-07 10:40:27 +01002292 /* Make a blind connection attemt, to trigger the deadlock condition */
Philipp Maier75932982018-03-27 14:52:35 +02002293 BSSAP_DIRECT.send(ts_BSSAP_CONNECT_req(g_bssap[0].sccp_addr_peer, g_bssap[0].sccp_addr_own, 1, omit));
Philipp Maier328d1662018-03-07 10:40:27 +01002294
2295 /* Send a BSSMAP reset */
Philipp Maier75932982018-03-27 14:52:35 +02002296 BSSAP_DIRECT.send(ts_BSSAP_UNITDATA_req(g_bssap[0].sccp_addr_peer, g_bssap[0].sccp_addr_own, ts_BSSMAP_Reset(0)));
Philipp Maier328d1662018-03-07 10:40:27 +01002297 T.start
2298 alt {
2299 [] BSSAP_DIRECT.receive(tr_BSSAP_UNITDATA_ind(?, ?, tr_BSSMAP_ResetAck)) {
2300 reset_ack_seen := true;
2301 repeat;
2302 }
2303
2304 /* Acknowledge MSC sided reset requests */
2305 [] BSSAP_DIRECT.receive(tr_BSSAP_UNITDATA_ind(?, ?, tr_BSSMAP_Reset)) {
Philipp Maier75932982018-03-27 14:52:35 +02002306 BSSAP_DIRECT.send(ts_BSSAP_UNITDATA_req(g_bssap[0].sccp_addr_peer, g_bssap[0].sccp_addr_own, ts_BSSMAP_ResetAck));
Philipp Maier328d1662018-03-07 10:40:27 +01002307 repeat;
2308 }
2309
2310 /* Ignore all other messages (e.g CR from the connection request) */
2311 [] BSSAP_DIRECT.receive { repeat }
2312
2313 /* If we got no BSSMAP RESET ACK back, then the MSC entered the
2314 * deadlock situation. The MSC is then unable to respond to any
2315 * further BSSMAP RESET or any other sort of traffic. */
2316 [reset_ack_seen == true] T.timeout { setverdict(pass) }
2317 [reset_ack_seen == false] T.timeout {
2318 setverdict(fail, "no BSSMAP RESET ACK seen!");
Daniel Willmannafce8662018-07-06 23:11:32 +02002319 mtc.stop;
Philipp Maier328d1662018-03-07 10:40:27 +01002320 }
Pau Espin Pedrol7e9178d2019-12-17 17:52:17 +01002321 }
Philipp Maier328d1662018-03-07 10:40:27 +01002322}
Harald Welte9de84792018-01-28 01:06:35 +01002323
Philipp Maier94f3f1b2018-03-15 18:54:13 +01002324/* Test MO Call with no response to RAN-side CRCX or DTAP Release */
Harald Weltee13cfb22019-04-23 16:52:02 +02002325friend function f_tc_mo_release_timeout(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Philipp Maier94f3f1b2018-03-15 18:54:13 +01002326 f_init_handler(pars);
2327 var CallParameters cpars := valueof(t_CallParams('12345'H, 0));
2328 var MNCC_PDU mncc;
2329 var MgcpCommand mgcp_cmd;
2330
Neels Hofmeyr3c89a6b2019-10-15 16:54:37 +02002331 /* Do not respond to the second CRCX */
2332 cpars.mgw_conn_2.resp := 0;
2333
Philipp Maier94f3f1b2018-03-15 18:54:13 +01002334 f_perform_lu();
Neels Hofmeyr3c89a6b2019-10-15 16:54:37 +02002335 f_mo_call_establish(cpars);
Philipp Maier94f3f1b2018-03-15 18:54:13 +01002336
Neels Hofmeyrde76f052019-02-26 05:02:46 +01002337 var default ccrel := activate(as_optional_cc_rel(cpars));
Philipp Maier94f3f1b2018-03-15 18:54:13 +01002338
2339 f_expect_clear(60.0);
Neels Hofmeyrde76f052019-02-26 05:02:46 +01002340
2341 deactivate(ccrel);
Philipp Maier94f3f1b2018-03-15 18:54:13 +01002342}
2343testcase TC_mo_release_timeout() runs on MTC_CT {
2344 var BSC_ConnHdlr vc_conn;
2345 f_init();
2346
2347 vc_conn := f_start_handler(refers(f_tc_mo_release_timeout), 40);
2348 vc_conn.done;
2349}
2350
Harald Welte12510c52018-01-26 22:26:24 +01002351
Philipp Maier2a98a732018-03-19 16:06:12 +01002352/* LU followed by MT call (including paging) */
2353private function f_tc_lu_and_mt_call_no_dlcx_resp(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
2354 f_init_handler(pars);
Stefan Sperling26d57be2018-11-12 17:03:26 +01002355 var CallParameters cpars := valueof(t_CallParams('12345'H, 0));
Philipp Maier2a98a732018-03-19 16:06:12 +01002356
2357 /* Intentionally disable the CRCX response */
2358 cpars.mgw_drop_dlcx := true;
2359
2360 /* Perform location update and call */
2361 f_perform_lu();
2362 f_mt_call(cpars);
2363}
2364testcase TC_lu_and_mt_call_no_dlcx_resp() runs on MTC_CT {
2365 var BSC_ConnHdlr vc_conn;
2366 f_init();
2367
2368 /* Perform an almost normal looking locationupdate + mt-call, but do
2369 * not respond to the DLCX at the end of the call */
2370 vc_conn := f_start_handler(refers(f_tc_lu_and_mt_call_no_dlcx_resp), 41);
2371 vc_conn.done;
2372
2373 /* Wait a guard period until the MGCP layer in the MSC times out,
2374 * if the MSC is vulnerable to the use-after-free situation that is
2375 * fixed by I78f1b6a9149488a4ad3f120c1e190a83c07d4b89 then it should
2376 * segfault now */
2377 f_sleep(6.0);
2378
2379 /* Run the init procedures once more. If the MSC has crashed, this
2380 * this will fail */
2381 f_init();
2382}
Harald Welte45164da2018-01-24 12:51:27 +01002383
Philipp Maier75932982018-03-27 14:52:35 +02002384/* Two BSSMAP resets from two different BSCs */
2385testcase TC_reset_two() runs on MTC_CT {
2386 var BSC_ConnHdlr vc_conn;
2387 f_init(2);
2388 f_sleep(2.0);
2389 setverdict(pass);
2390}
2391
Harald Weltee13cfb22019-04-23 16:52:02 +02002392/* Two BSSMAP resets from two different BSCs plus one IuCS RANAP Reset */
2393testcase TC_reset_two_1iu() runs on MTC_CT {
2394 var BSC_ConnHdlr vc_conn;
2395 f_init(3);
2396 f_sleep(2.0);
2397 setverdict(pass);
2398}
2399
Harald Weltef640a012018-04-14 17:49:21 +02002400/***********************************************************************
2401 * SMS Testing
2402 ***********************************************************************/
2403
Harald Weltef45efeb2018-04-09 18:19:24 +02002404/* LU followed by MO SMS */
Harald Weltee13cfb22019-04-23 16:52:02 +02002405friend function f_tc_lu_and_mo_sms(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltef45efeb2018-04-09 18:19:24 +02002406 var SmsParameters spars := valueof(t_SmsPars);
2407
2408 f_init_handler(pars);
2409
2410 /* Perform location update and call */
2411 f_perform_lu();
2412
2413 f_establish_fully(EST_TYPE_MO_SMS);
2414
2415 //spars.exp_rp_err := 96; /* invalid mandatory information */
2416 f_mo_sms(spars);
2417
2418 f_expect_clear();
2419}
2420testcase TC_lu_and_mo_sms() runs on MTC_CT {
2421 var BSC_ConnHdlr vc_conn;
2422 f_init();
2423 vc_conn := f_start_handler(refers(f_tc_lu_and_mo_sms), 42);
2424 vc_conn.done;
2425}
2426
Harald Weltee13cfb22019-04-23 16:52:02 +02002427
Harald Weltef45efeb2018-04-09 18:19:24 +02002428private function f_vty_sms_send(charstring imsi, charstring msisdn, charstring text)
Neels Hofmeyr6aaeccf2019-03-06 15:32:26 +01002429runs on BSC_ConnHdlr {
Harald Weltef45efeb2018-04-09 18:19:24 +02002430 f_vty_transceive(MSCVTY, "subscriber imsi "&imsi&" sms sender msisdn "&msisdn&" send "&text);
2431}
2432
Neels Hofmeyr8256ed22019-03-06 15:34:01 +01002433/* Remove still pending SMS */
2434private function f_vty_sms_clear(charstring imsi)
2435runs on BSC_ConnHdlr {
2436 f_vty_transceive(MSCVTY, "subscriber imsi " & imsi & " sms delete-all");
2437 f_vty_transceive(MSCVTY, "sms-queue clear");
2438}
2439
Harald Weltef45efeb2018-04-09 18:19:24 +02002440/* LU followed by MT SMS */
Harald Weltee13cfb22019-04-23 16:52:02 +02002441friend function f_tc_lu_and_mt_sms(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltef45efeb2018-04-09 18:19:24 +02002442 var SmsParameters spars := valueof(t_SmsPars);
Harald Weltef45efeb2018-04-09 18:19:24 +02002443
2444 f_init_handler(pars);
2445
2446 /* Perform location update and call */
2447 f_perform_lu();
2448
2449 /* register an 'expect' for given IMSI (+TMSI) */
Vadim Yanitskiyae747742020-01-10 00:23:10 +01002450 f_ran_register_imsi(g_pars.imsi, g_pars.tmsi);
Harald Weltef45efeb2018-04-09 18:19:24 +02002451
Neels Hofmeyr6aaeccf2019-03-06 15:32:26 +01002452 f_vty_sms_send(hex2str(pars.imsi), "2342", "Hello SMS");
Harald Weltef45efeb2018-04-09 18:19:24 +02002453
2454 /* MSC->BSC: expect PAGING from MSC */
Harald Weltee035e3e2019-04-21 17:32:05 +02002455 f_expect_paging();
2456
Harald Weltef45efeb2018-04-09 18:19:24 +02002457 /* Establish DTAP / BSSAP / SCCP connection */
2458 f_establish_fully(EST_TYPE_PAG_RESP);
2459
2460 spars.tp.ud := 'C8329BFD064D9B53'O;
2461 f_mt_sms(spars);
2462
2463 f_expect_clear();
2464}
2465testcase TC_lu_and_mt_sms() runs on MTC_CT {
2466 var BSC_ConnHdlrPars pars;
2467 var BSC_ConnHdlr vc_conn;
2468 f_init();
2469 pars := f_init_pars(43);
2470 vc_conn := f_start_handler_with_pars(refers(f_tc_lu_and_mt_sms), pars);
Harald Weltef45efeb2018-04-09 18:19:24 +02002471 vc_conn.done;
2472}
2473
Neels Hofmeyrb58d9742019-11-27 18:44:54 +01002474/* SMS added while already Paging */
2475friend function f_tc_lu_and_mt_sms_already_paging(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
2476 var SmsParameters spars := valueof(t_SmsPars);
2477 var OCT4 tmsi;
2478
2479 f_init_handler(pars);
2480
2481 f_perform_lu();
2482
2483 /* register an 'expect' for given IMSI (+TMSI) */
2484 if (isvalue(g_pars.tmsi)) {
2485 tmsi := g_pars.tmsi;
2486 } else {
2487 tmsi := 'FFFFFFFF'O;
2488 }
2489 f_ran_register_imsi(g_pars.imsi, tmsi);
2490
2491 log("first SMS");
2492 f_vty_sms_send(hex2str(pars.imsi), "2342", "Hello SMS");
2493
2494 /* MSC->BSC: expect PAGING from MSC */
2495 f_expect_paging();
2496
2497 log("second SMS");
2498 /* Now osmo-msc is in state "Paging pending", make sure that another SMS to be sent at this time just joins in
2499 * with the pending paging. Another SMS: */
2500 f_vty_sms_send(hex2str(pars.imsi), "2342", "Another SMS");
2501
2502 /* Establish DTAP / BSSAP / SCCP connection */
2503 f_establish_fully(EST_TYPE_PAG_RESP);
2504
2505 spars.tp.ud := 'C8329BFD064D9B53'O;
2506 f_mt_sms(spars);
2507
2508 spars.tp.ud := '41F79B8E2ECB41D3E614'O;
2509 f_mt_sms(spars);
2510
2511 f_expect_clear();
2512}
2513testcase TC_lu_and_mt_sms_already_paging() runs on MTC_CT {
2514 var BSC_ConnHdlrPars pars;
2515 var BSC_ConnHdlr vc_conn;
2516 f_init();
2517 pars := f_init_pars(44);
2518 vc_conn := f_start_handler_with_pars(refers(f_tc_lu_and_mt_sms_already_paging), pars);
2519 vc_conn.done;
2520}
Harald Weltee13cfb22019-04-23 16:52:02 +02002521
Philipp Maier3983e702018-11-22 19:01:33 +01002522/* Paging for MT SMS but no response */
Harald Weltee13cfb22019-04-23 16:52:02 +02002523friend function f_tc_lu_and_mt_sms_paging_and_nothing(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Philipp Maier3983e702018-11-22 19:01:33 +01002524 var SmsParameters spars := valueof(t_SmsPars);
Vadim Yanitskiyae747742020-01-10 00:23:10 +01002525
Philipp Maier3983e702018-11-22 19:01:33 +01002526 f_init_handler(pars, 150.0);
2527
2528 /* Perform location update */
2529 f_perform_lu();
2530
2531 /* register an 'expect' for given IMSI (+TMSI) */
Vadim Yanitskiyae747742020-01-10 00:23:10 +01002532 f_ran_register_imsi(g_pars.imsi, g_pars.tmsi);
Philipp Maier3983e702018-11-22 19:01:33 +01002533
Neels Hofmeyr6aaeccf2019-03-06 15:32:26 +01002534 f_vty_sms_send(hex2str(pars.imsi), "2342", "Hello SMS");
2535
Neels Hofmeyr16237742019-03-06 15:34:01 +01002536 /* Expect the MSC to page exactly once */
Harald Weltee13cfb22019-04-23 16:52:02 +02002537 f_expect_paging();
Philipp Maier3983e702018-11-22 19:01:33 +01002538
2539 /* Wait some time to make sure the MSC is not delivering any further
2540 * paging messages or anything else that could be unexpected. */
2541 timer T := 20.0;
2542 T.start
2543 alt {
Vadim Yanitskiy53f2be62024-04-14 19:48:39 +07002544 [] as_paging_any() {
Vadim Yanitskiyda774592020-01-15 10:33:47 +07002545 setverdict(fail, "paging seems not to stop!");
2546 mtc.stop;
Harald Weltee13cfb22019-04-23 16:52:02 +02002547 }
Vadim Yanitskiyda774592020-01-15 10:33:47 +07002548 [] BSSAP.receive {
2549 setverdict(fail, "unexpected BSSAP message received");
2550 self.stop;
Philipp Maier3983e702018-11-22 19:01:33 +01002551 }
Vadim Yanitskiyda774592020-01-15 10:33:47 +07002552 [] T.timeout {
2553 setverdict(pass);
Philipp Maier3983e702018-11-22 19:01:33 +01002554 }
2555 }
2556
Neels Hofmeyr8256ed22019-03-06 15:34:01 +01002557 f_vty_sms_clear(hex2str(g_pars.imsi));
2558
Philipp Maier3983e702018-11-22 19:01:33 +01002559 setverdict(pass);
2560}
2561testcase TC_lu_and_mt_sms_paging_and_nothing() runs on MTC_CT {
2562 var BSC_ConnHdlrPars pars;
2563 var BSC_ConnHdlr vc_conn;
2564 f_init();
Philipp Maiera99ad262019-01-22 15:35:42 +01002565 pars := f_init_pars(1843);
Philipp Maier3983e702018-11-22 19:01:33 +01002566 vc_conn := f_start_handler_with_pars(refers(f_tc_lu_and_mt_sms_paging_and_nothing), pars);
Philipp Maier3983e702018-11-22 19:01:33 +01002567 vc_conn.done;
2568}
2569
Alexander Couzensfc02f242019-09-12 03:43:18 +02002570/* LU followed by MT SMS with repeated paging */
2571friend function f_tc_lu_and_mt_sms_paging_repeated(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
2572 var SmsParameters spars := valueof(t_SmsPars);
Alexander Couzensfc02f242019-09-12 03:43:18 +02002573
2574 f_init_handler(pars);
2575
2576 /* Perform location update and call */
2577 f_perform_lu();
2578
2579 /* register an 'expect' for given IMSI (+TMSI) */
Vadim Yanitskiyae747742020-01-10 00:23:10 +01002580 f_ran_register_imsi(g_pars.imsi, g_pars.tmsi);
Alexander Couzensfc02f242019-09-12 03:43:18 +02002581
2582 f_vty_sms_send(hex2str(pars.imsi), "2342", "Hello SMS");
2583
Neels Hofmeyrc3accec2019-11-28 01:09:47 +01002584 log("Expecting first Paging");
Alexander Couzensfc02f242019-09-12 03:43:18 +02002585 /* MSC->BSC: expect PAGING from MSC */
2586 f_expect_paging();
2587
Neels Hofmeyrc3accec2019-11-28 01:09:47 +01002588 if (g_pars.ran_is_geran) {
2589 log("GERAN: expect no further Paging");
2590 } else {
2591 log("UTRAN: expect more Paging");
2592 }
2593
2594 timer T := 5.0;
2595 T.start;
2596 alt {
Vadim Yanitskiy53f2be62024-04-14 19:48:39 +07002597 [] as_paging() {
2598 if (g_pars.ran_is_geran) {
2599 setverdict(fail, "GERAN should not repeat Paging, but received a second Paging");
2600 mtc.stop;
2601 } else {
2602 log("UTRAN: second Paging received, as expected");
2603 setverdict(pass);
Neels Hofmeyrc3accec2019-11-28 01:09:47 +01002604 }
Vadim Yanitskiy53f2be62024-04-14 19:48:39 +07002605 }
2606 [] as_paging_any() {
2607 setverdict(fail, "Rx unexpected BSSMAP/RANAP Paging");
2608 mtc.stop;
Neels Hofmeyrc3accec2019-11-28 01:09:47 +01002609 }
2610 [] T.timeout {
2611 if (g_pars.ran_is_geran) {
2612 log("GERAN: No further Paging received, as expected");
2613 setverdict(pass);
2614 } else {
2615 setverdict(fail, "UTRAN: Expected a second Paging");
2616 mtc.stop;
2617 }
2618 }
2619 }
Alexander Couzensfc02f242019-09-12 03:43:18 +02002620
2621 /* Establish DTAP / BSSAP / SCCP connection */
2622 f_establish_fully(EST_TYPE_PAG_RESP);
2623
2624 spars.tp.ud := 'C8329BFD064D9B53'O;
2625 f_mt_sms(spars);
2626
2627 f_expect_clear();
2628}
2629testcase TC_lu_and_mt_sms_paging_repeated() runs on MTC_CT {
2630 var BSC_ConnHdlrPars pars;
2631 var BSC_ConnHdlr vc_conn;
2632 f_init();
2633 pars := f_init_pars(1844);
2634 vc_conn := f_start_handler_with_pars(refers(f_tc_lu_and_mt_sms_paging_repeated), pars);
2635 vc_conn.done;
2636}
Harald Weltee13cfb22019-04-23 16:52:02 +02002637
Harald Weltef640a012018-04-14 17:49:21 +02002638/* mobile originated SMS from MS/BTS/BSC side to SMPP */
Harald Weltee13cfb22019-04-23 16:52:02 +02002639friend function f_tc_smpp_mo_sms(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltef640a012018-04-14 17:49:21 +02002640 var SmsParameters spars := valueof(t_SmsPars);
Harald Weltef45efeb2018-04-09 18:19:24 +02002641
Harald Weltef640a012018-04-14 17:49:21 +02002642 f_init_handler(pars);
Harald Weltef45efeb2018-04-09 18:19:24 +02002643
Harald Weltef640a012018-04-14 17:49:21 +02002644 /* Perform location update so IMSI is known + registered in MSC/VLR */
2645 f_perform_lu();
Harald Weltef640a012018-04-14 17:49:21 +02002646
Vadim Yanitskiy2d3f8462020-01-15 11:44:12 +07002647 /* MS/UE submits a MO SMS */
2648 f_establish_fully(EST_TYPE_MO_SMS);
2649 f_mo_sms_submit(spars);
Harald Weltef640a012018-04-14 17:49:21 +02002650
2651 var SMPP_PDU smpp;
2652 var template SMPP_PDU tr_smpp := tr_SMPP(c_SMPP_command_id_deliver_sm, ESME_ROK);
2653 tr_smpp.body.deliver_sm := {
2654 service_type := "CMT",
2655 source_addr_ton := network_specific,
2656 source_addr_npi := isdn,
2657 source_addr := hex2str(pars.msisdn),
2658 dest_addr_ton := f_sm_ton_from_gsm(spars.tp.da.tP_DA_NoPad.tP_TypeOfNumber),
2659 dest_addr_npi := f_sm_npi_from_gsm(spars.tp.da.tP_DA_NoPad.tP_NumberingPlanID),
2660 destination_addr := hex2str(spars.tp.da.tP_DA_NoPad.tP_DAValue),
2661 esm_class := '00000001'B,
2662 protocol_id := 0,
2663 priority_flag := 0,
2664 schedule_delivery_time := "",
2665 replace_if_present := 0,
2666 data_coding := '00000001'B,
2667 sm_default_msg_id := 0,
2668 sm_length := ?,
2669 short_message := spars.tp.ud,
2670 opt_pars := {
2671 {
2672 tag := user_message_reference,
2673 len := 2,
2674 opt_value := {
2675 int2_val := oct2int(spars.tp.msg_ref)
2676 }
2677 }
2678 }
2679 };
2680 alt {
2681 [] SMPP.receive(tr_smpp) -> value smpp {
2682 SMPP.send(ts_SMPP_DELIVER_SM_resp(ESME_ROK, smpp.header.seq_num));
2683 }
2684 [] SMPP.receive(tr_SMPP(c_SMPP_command_id_alert_notification, ESME_ROK)) { repeat; }
2685 }
2686
Vadim Yanitskiy2d3f8462020-01-15 11:44:12 +07002687 /* MSC terminates the SMS transaction with RP-ACK */
2688 f_mo_sms_wait_rp_ack(spars);
2689
Harald Weltef640a012018-04-14 17:49:21 +02002690 f_expect_clear();
2691}
2692testcase TC_smpp_mo_sms() runs on MTC_CT {
2693 var BSC_ConnHdlr vc_conn;
2694 f_init();
2695 f_vty_config2(MSCVTY, { "smpp", "esme msc_tester"}, "default-route");
2696 vc_conn := f_start_handler(refers(f_tc_smpp_mo_sms), 44);
2697 vc_conn.done;
2698 f_vty_config2(MSCVTY, { "smpp", "esme msc_tester"}, "no default-route");
2699}
2700
Vadim Yanitskiy33820762020-01-15 11:26:07 +07002701/* Test case for OS#4351: make sure that RP-ERROR from ESME is properly sent to the MS/UE */
2702friend function f_tc_smpp_mo_sms_rp_error(charstring id, BSC_ConnHdlrPars pars)
2703runs on BSC_ConnHdlr {
2704 var SmsParameters spars := valueof(t_SmsPars);
2705 var SMPP_PDU smpp_pdu;
2706 timer T := 3.0;
2707
2708 f_init_handler(pars);
2709
2710 /* Perform location update */
2711 f_perform_lu();
2712
2713 /* MS/UE submits a MO SMS */
2714 f_establish_fully(EST_TYPE_MO_SMS);
2715 f_mo_sms_submit(spars);
2716
2717 /* ESME responds with an error (Invalid Destination Address) */
2718 T.start;
2719 alt {
2720 [] SMPP.receive(tr_SMPP(c_SMPP_command_id_deliver_sm, ESME_ROK, body := ?)) -> value smpp_pdu {
2721 SMPP.send(ts_SMPP_DELIVER_SM_resp(ESME_RINVDSTADR, smpp_pdu.header.seq_num));
2722 }
2723 [] SMPP.receive(tr_SMPP(c_SMPP_command_id_alert_notification, ESME_ROK)) { repeat; }
2724 [] T.timeout {
2725 setverdict(fail, "Timeout waiting for SMPP DELIVER-SM");
2726 mtc.stop;
2727 }
2728 }
2729
2730 /* Expect RP-ERROR on BSSAP interface */
2731 spars.exp_rp_err := 1; /* FIXME: GSM411_RP_CAUSE_MO_NUM_UNASSIGNED */
2732 f_mo_sms_wait_rp_ack(spars);
2733
2734 f_expect_clear();
2735}
2736testcase TC_smpp_mo_sms_rp_error() runs on MTC_CT {
2737 var BSC_ConnHdlr vc_conn;
2738 f_init();
2739 f_vty_config2(MSCVTY, { "smpp", "esme msc_tester"}, "default-route");
2740 vc_conn := f_start_handler(refers(f_tc_smpp_mo_sms_rp_error), 45);
2741 vc_conn.done;
2742 f_vty_config2(MSCVTY, { "smpp", "esme msc_tester"}, "no default-route");
2743}
2744
Harald Weltee13cfb22019-04-23 16:52:02 +02002745
Vadim Yanitskiy103d09f2018-11-12 02:50:23 +07002746/* Test MO-SMS from MS/BTS/BSC towards HLR (via GSUP) */
Harald Weltee13cfb22019-04-23 16:52:02 +02002747friend function f_tc_gsup_mo_sms(charstring id, BSC_ConnHdlrPars pars)
Vadim Yanitskiy103d09f2018-11-12 02:50:23 +07002748runs on BSC_ConnHdlr {
2749 var SmsParameters spars := valueof(t_SmsPars);
2750 var GSUP_PDU gsup_msg_rx;
2751 var octetstring sm_tpdu;
2752
2753 f_init_handler(pars);
2754
2755 /* We need to inspect GSUP activity */
2756 f_create_gsup_expect(hex2str(g_pars.imsi));
2757
2758 /* Perform location update */
2759 f_perform_lu();
2760
2761 /* Send CM Service Request for SMS */
2762 f_establish_fully(EST_TYPE_MO_SMS);
2763
2764 /* Prepare expected SM-RP-UI (SM TPDU) */
2765 enc_TPDU_RP_DATA_MS_SGSN_fast(
2766 valueof(ts_SMS_SUBMIT(spars.tp.msg_ref,
2767 spars.tp.da, spars.tp.pid, spars.tp.dcs,
2768 spars.tp.udl, spars.tp.ud)),
2769 sm_tpdu);
2770
2771 var template GSUP_PDU mo_forwardSM := tr_GSUP_MO_FORWARD_SM_REQ(
2772 imsi := g_pars.imsi,
2773 sm_rp_mr := spars.rp.msg_ref,
Vadim Yanitskiy04dd5f72019-12-13 15:45:44 +09002774 /* SM-RP-DA: SMSC address */
2775 sm_rp_da := tr_GSUP_SM_RP_DA_SMSC_ADDR(t_GSUP_SM_RP_Addr(
2776 number := spars.rp.smsc_addr.rP_NumberDigits,
2777 npi := spars.rp.smsc_addr.rP_NumberingPlanIdentification,
2778 ton := spars.rp.smsc_addr.rP_TypeOfNumber,
2779 ext := spars.rp.smsc_addr.rP_Ext)),
2780 /* SM-RP-OA: subscriber's MSISDN (filled in by MSC) */
2781 sm_rp_oa := tr_GSUP_SM_RP_OA_MSISDN(t_GSUP_SM_RP_Addr(
2782 number := g_pars.msisdn,
2783 /* NOTE: MSISDN in g_pars lacks this info, assuming defaults */
2784 npi := '0001'B, ton := '001'B, ext := '1'B)),
Vadim Yanitskiy103d09f2018-11-12 02:50:23 +07002785 /* TODO: can we use decmatch here? */
2786 sm_rp_ui := sm_tpdu
2787 );
2788
2789 /* Submit an SMS on DTAP and expect MO-forwardSM-Req on GSUP */
2790 f_mo_sms_submit(spars);
2791 alt {
2792 [] GSUP.receive(mo_forwardSM) -> value gsup_msg_rx {
Vadim Yanitskiya358dd42020-01-15 10:42:47 +07002793 log("RX MO-forwardSM-Req: ", gsup_msg_rx);
Vadim Yanitskiy103d09f2018-11-12 02:50:23 +07002794 setverdict(pass);
2795 }
2796 [] GSUP.receive {
Vadim Yanitskiy286b0422024-01-09 18:11:04 +07002797 setverdict(fail, "Rx unexpected GSUP message");
Vadim Yanitskiy103d09f2018-11-12 02:50:23 +07002798 mtc.stop;
2799 }
2800 }
2801
2802 /* Trigger RP-ACK by sending MO-forwardSM-Res */
2803 GSUP.send(valueof(ts_GSUP_MO_FORWARD_SM_RES(
2804 imsi := g_pars.imsi,
2805 sm_rp_mr := spars.rp.msg_ref)));
2806 /* Expect RP-ACK on DTAP */
2807 f_mo_sms_wait_rp_ack(spars);
2808
2809 f_expect_clear();
2810}
2811testcase TC_gsup_mo_sms() runs on MTC_CT {
2812 var BSC_ConnHdlr vc_conn;
2813 f_init();
2814 f_vty_config(MSCVTY, "msc", "sms-over-gsup");
2815 vc_conn := f_start_handler(refers(f_tc_gsup_mo_sms), 88);
2816 vc_conn.done;
2817 f_vty_config(MSCVTY, "msc", "no sms-over-gsup");
2818}
2819
Harald Weltee13cfb22019-04-23 16:52:02 +02002820
Vadim Yanitskiy9cc019a2018-11-15 02:06:07 +07002821/* Test MO-SMMA from MS/BTS/BSC towards HLR (via GSUP) */
Harald Weltee13cfb22019-04-23 16:52:02 +02002822friend function f_tc_gsup_mo_smma(charstring id, BSC_ConnHdlrPars pars)
Vadim Yanitskiy9cc019a2018-11-15 02:06:07 +07002823runs on BSC_ConnHdlr {
2824 var SmsParameters spars := valueof(t_SmsPars);
2825 var GSUP_PDU gsup_msg_rx;
2826
2827 f_init_handler(pars);
2828
2829 /* We need to inspect GSUP activity */
2830 f_create_gsup_expect(hex2str(g_pars.imsi));
2831
2832 /* Perform location update */
2833 f_perform_lu();
2834
2835 /* Send CM Service Request for SMS */
2836 f_establish_fully(EST_TYPE_MO_SMS);
2837
2838 var template GSUP_PDU mo_ReadyForSM := tr_GSUP_MO_READY_FOR_SM_REQ(
2839 imsi := g_pars.imsi,
2840 sm_rp_mr := spars.rp.msg_ref,
2841 sm_alert_rsn := GSUP_SM_ALERT_RSN_TYPE_MEM_AVAIL
2842 );
2843
2844 /* Submit an SMS on DTAP and expect MO-forwardSM-Req on GSUP */
2845 f_mo_smma(spars);
2846 alt {
2847 [] GSUP.receive(mo_ReadyForSM) -> value gsup_msg_rx {
Vadim Yanitskiya358dd42020-01-15 10:42:47 +07002848 log("RX MO-ReadyForSM-Req: ", gsup_msg_rx);
Vadim Yanitskiy9cc019a2018-11-15 02:06:07 +07002849 setverdict(pass);
2850 }
2851 [] GSUP.receive {
Vadim Yanitskiy286b0422024-01-09 18:11:04 +07002852 setverdict(fail, "Rx unexpected GSUP message");
Vadim Yanitskiy9cc019a2018-11-15 02:06:07 +07002853 mtc.stop;
2854 }
2855 }
2856
2857 /* Trigger RP-ACK by sending MO-forwardSM-Res */
2858 GSUP.send(valueof(ts_GSUP_MO_READY_FOR_SM_RES(
2859 imsi := g_pars.imsi,
2860 sm_rp_mr := spars.rp.msg_ref)));
2861 /* Expect RP-ACK on DTAP */
2862 f_mo_sms_wait_rp_ack(spars);
2863
2864 f_expect_clear();
2865}
2866testcase TC_gsup_mo_smma() runs on MTC_CT {
2867 var BSC_ConnHdlr vc_conn;
2868 f_init();
2869 f_vty_config(MSCVTY, "msc", "sms-over-gsup");
2870 vc_conn := f_start_handler(refers(f_tc_gsup_mo_smma), 89);
2871 vc_conn.done;
2872 f_vty_config(MSCVTY, "msc", "no sms-over-gsup");
2873}
2874
Harald Weltee13cfb22019-04-23 16:52:02 +02002875
Vadim Yanitskiyd7b37ab2018-11-24 03:40:20 +07002876/* Helper for sending MT SMS over GSUP */
2877private function f_gsup_forwardSM_req(SmsParameters spars, OCT1 mms := '00'O)
2878runs on BSC_ConnHdlr {
Vadim Yanitskiya52347c2019-12-12 17:32:33 +09002879 var GSUP_SM_RP_Addr msisdn := valueof(t_GSUP_SM_RP_Addr(g_pars.msisdn));
Vadim Yanitskiy04dd5f72019-12-13 15:45:44 +09002880 var GSUP_SM_RP_Addr smsc := valueof(t_GSUP_SM_RP_Addr(
2881 number := spars.rp.smsc_addr.rP_NumberDigits,
2882 npi := spars.rp.smsc_addr.rP_NumberingPlanIdentification,
2883 ton := spars.rp.smsc_addr.rP_TypeOfNumber,
2884 ext := spars.rp.smsc_addr.rP_Ext));
Vadim Yanitskiya52347c2019-12-12 17:32:33 +09002885
Vadim Yanitskiyd7b37ab2018-11-24 03:40:20 +07002886 GSUP.send(ts_GSUP_MT_FORWARD_SM_REQ(
2887 imsi := g_pars.imsi,
2888 /* NOTE: MSC should assign RP-MR itself */
2889 sm_rp_mr := 'FF'O,
Vadim Yanitskiya52347c2019-12-12 17:32:33 +09002890 sm_rp_da := valueof(ts_GSUP_SM_RP_DA_MSISDN(msisdn)),
Vadim Yanitskiy04dd5f72019-12-13 15:45:44 +09002891 sm_rp_oa := valueof(ts_GSUP_SM_RP_OA_SMSC_ADDR(smsc)),
Vadim Yanitskiyd7b37ab2018-11-24 03:40:20 +07002892 /* Encoded SMS TPDU (taken from Wireshark)
2893 * FIXME: we should encode spars somehow */
2894 sm_rp_ui := '00068021436500008111328130858200'O,
2895 sm_rp_mms := mms
2896 ));
2897}
2898
2899/* Test successful MT-SMS (RP-ACK) over GSUP */
Harald Weltee13cfb22019-04-23 16:52:02 +02002900friend function f_tc_gsup_mt_sms_ack(charstring id, BSC_ConnHdlrPars pars)
Vadim Yanitskiyd7b37ab2018-11-24 03:40:20 +07002901runs on BSC_ConnHdlr {
2902 var SmsParameters spars := valueof(t_SmsPars);
2903
2904 f_init_handler(pars);
2905
2906 /* We need to inspect GSUP activity */
2907 f_create_gsup_expect(hex2str(g_pars.imsi));
2908
2909 /* Perform location update */
2910 f_perform_lu();
2911
2912 /* Register an 'expect' for given IMSI (+TMSI) */
Vadim Yanitskiyae747742020-01-10 00:23:10 +01002913 f_ran_register_imsi(g_pars.imsi, g_pars.tmsi);
Vadim Yanitskiyd7b37ab2018-11-24 03:40:20 +07002914
2915 var template GSUP_PDU mt_forwardSM_res := tr_GSUP_MT_FORWARD_SM_RES(
2916 imsi := g_pars.imsi,
2917 /* NOTE: MSC should assign RP-MR itself */
2918 sm_rp_mr := ?
2919 );
2920
2921 /* Submit a MT SMS on GSUP */
2922 f_gsup_forwardSM_req(spars);
2923
2924 /* Expect Paging Request and Establish DTAP / BSSAP / SCCP connection */
Harald Weltee035e3e2019-04-21 17:32:05 +02002925 f_expect_paging();
Vadim Yanitskiyd7b37ab2018-11-24 03:40:20 +07002926 f_establish_fully(EST_TYPE_PAG_RESP);
2927
2928 /* Wait for MT SMS on DTAP */
2929 f_mt_sms_expect(spars);
2930
2931 /* Send RP-ACK and expect MT-forwardSM-Res on GSUP */
2932 f_mt_sms_send_rp_ack(spars);
2933 alt {
2934 [] GSUP.receive(mt_forwardSM_res) {
2935 log("RX MT-forwardSM-Res (RP-ACK)");
2936 setverdict(pass);
2937 }
2938 [] GSUP.receive {
Vadim Yanitskiy286b0422024-01-09 18:11:04 +07002939 setverdict(fail, "Rx unexpected GSUP message");
Vadim Yanitskiyd7b37ab2018-11-24 03:40:20 +07002940 mtc.stop;
2941 }
2942 }
2943
2944 f_expect_clear();
2945}
2946testcase TC_gsup_mt_sms_ack() runs on MTC_CT {
2947 var BSC_ConnHdlrPars pars;
2948 var BSC_ConnHdlr vc_conn;
2949 f_init();
2950 pars := f_init_pars(90);
2951 f_vty_config(MSCVTY, "msc", "sms-over-gsup");
2952 vc_conn := f_start_handler_with_pars(refers(f_tc_gsup_mt_sms_ack), pars);
2953 vc_conn.done;
2954 f_vty_config(MSCVTY, "msc", "no sms-over-gsup");
2955}
2956
Harald Weltee13cfb22019-04-23 16:52:02 +02002957
Vadim Yanitskiyd7b37ab2018-11-24 03:40:20 +07002958/* Test rejected MT-SMS (RP-ERROR) over GSUP */
Harald Weltee13cfb22019-04-23 16:52:02 +02002959friend function f_tc_gsup_mt_sms_err(charstring id, BSC_ConnHdlrPars pars)
Vadim Yanitskiyd7b37ab2018-11-24 03:40:20 +07002960runs on BSC_ConnHdlr {
2961 var SmsParameters spars := valueof(t_SmsPars);
2962 var OCT1 sm_rp_cause := '78'O; /* dummy RP-Cause value */
2963
2964 f_init_handler(pars);
2965
2966 /* We need to inspect GSUP activity */
2967 f_create_gsup_expect(hex2str(g_pars.imsi));
2968
2969 /* Perform location update */
2970 f_perform_lu();
2971
2972 /* Register an 'expect' for given IMSI (+TMSI) */
Vadim Yanitskiyae747742020-01-10 00:23:10 +01002973 f_ran_register_imsi(g_pars.imsi, g_pars.tmsi);
Vadim Yanitskiyd7b37ab2018-11-24 03:40:20 +07002974
2975 var template GSUP_PDU mt_forwardSM_err := tr_GSUP_MT_FORWARD_SM_ERR(
2976 imsi := g_pars.imsi,
2977 /* NOTE: MSC should assign RP-MR itself */
2978 sm_rp_mr := ?,
2979 sm_rp_cause := sm_rp_cause
2980 );
2981
2982 /* Submit a MT SMS on GSUP */
2983 f_gsup_forwardSM_req(spars);
2984
2985 /* Expect Paging Request and Establish DTAP / BSSAP / SCCP connection */
Harald Weltee035e3e2019-04-21 17:32:05 +02002986 f_expect_paging();
Vadim Yanitskiyd7b37ab2018-11-24 03:40:20 +07002987 f_establish_fully(EST_TYPE_PAG_RESP);
2988
2989 /* Wait for MT SMS on DTAP */
2990 f_mt_sms_expect(spars);
2991
2992 /* Send RP-ERROR and expect MT-forwardSM-Err on GSUP */
2993 f_mt_sms_send_rp_error(spars, oct2int(sm_rp_cause));
2994 alt {
2995 [] GSUP.receive(mt_forwardSM_err) {
2996 log("RX MT-forwardSM-Err (RP-ERROR)");
2997 setverdict(pass);
2998 mtc.stop;
2999 }
3000 [] GSUP.receive {
Vadim Yanitskiy286b0422024-01-09 18:11:04 +07003001 setverdict(fail, "Rx unexpected GSUP message");
Vadim Yanitskiyd7b37ab2018-11-24 03:40:20 +07003002 mtc.stop;
3003 }
3004 }
3005
3006 f_expect_clear();
3007}
3008testcase TC_gsup_mt_sms_err() runs on MTC_CT {
3009 var BSC_ConnHdlrPars pars;
3010 var BSC_ConnHdlr vc_conn;
3011 f_init();
3012 pars := f_init_pars(91);
3013 f_vty_config(MSCVTY, "msc", "sms-over-gsup");
3014 vc_conn := f_start_handler_with_pars(refers(f_tc_gsup_mt_sms_err), pars);
3015 vc_conn.done;
3016 f_vty_config(MSCVTY, "msc", "no sms-over-gsup");
3017}
3018
Harald Weltee13cfb22019-04-23 16:52:02 +02003019
Vadim Yanitskiybe1ff4b2019-01-18 15:04:13 +07003020/* Test SM-RP-MR assignment for MT-SMS over GSUP */
Harald Weltee13cfb22019-04-23 16:52:02 +02003021friend function f_tc_gsup_mt_sms_rp_mr(charstring id, BSC_ConnHdlrPars pars)
Vadim Yanitskiybe1ff4b2019-01-18 15:04:13 +07003022runs on BSC_ConnHdlr {
3023 var SmsParameters spars1 := valueof(t_SmsPars); /* 1st SMS */
3024 var SmsParameters spars2 := valueof(t_SmsPars); /* 2nd SMS */
3025
3026 f_init_handler(pars);
3027
3028 /* We need to inspect GSUP activity */
3029 f_create_gsup_expect(hex2str(g_pars.imsi));
3030
3031 /* Perform location update */
3032 f_perform_lu();
3033
3034 /* Register an 'expect' for given IMSI (+TMSI) */
Vadim Yanitskiyae747742020-01-10 00:23:10 +01003035 f_ran_register_imsi(g_pars.imsi, g_pars.tmsi);
Vadim Yanitskiybe1ff4b2019-01-18 15:04:13 +07003036
3037 /* Submit the 1st MT SMS on GSUP */
3038 log("TX MT-forwardSM-Req for the 1st SMS");
3039 f_gsup_forwardSM_req(spars1);
3040
3041 /* Expect Paging Request and Establish DTAP / BSSAP / SCCP connection */
Harald Weltee035e3e2019-04-21 17:32:05 +02003042 f_expect_paging();
Vadim Yanitskiybe1ff4b2019-01-18 15:04:13 +07003043 f_establish_fully(EST_TYPE_PAG_RESP);
3044
3045 /* Wait for 1st MT SMS on DTAP */
3046 f_mt_sms_expect(spars1);
3047 log("RX the 1st SMS on DTAP, DTAP TID is ", spars1.tid,
3048 ", SM-RP-MR is ", spars1.rp.msg_ref);
3049
3050 /* Submit the 2nd MT SMS on GSUP */
3051 log("TX MT-forwardSM-Req for the 2nd SMS");
3052 f_gsup_forwardSM_req(spars2);
3053
3054 /* Wait for 2nd MT SMS on DTAP */
3055 f_mt_sms_expect(spars2);
3056 log("RX the 2nd SMS on DTAP, DTAP TID is ", spars2.tid,
3057 ", SM-RP-MR is ", spars2.rp.msg_ref);
3058
3059 /* Both transaction IDs shall be different */
3060 if (spars1.tid == spars2.tid) {
Vadim Yanitskiy286b0422024-01-09 18:11:04 +07003061 setverdict(fail, "Both DTAP transaction IDs shall be different");
Vadim Yanitskiybe1ff4b2019-01-18 15:04:13 +07003062 }
3063
3064 /* Both SM-RP-MR values shall be different */
3065 if (spars1.rp.msg_ref == spars2.rp.msg_ref) {
Vadim Yanitskiy286b0422024-01-09 18:11:04 +07003066 setverdict(fail, "Both SM-RP-MR values shall be different");
Vadim Yanitskiybe1ff4b2019-01-18 15:04:13 +07003067 }
3068
3069 /* Both SM-RP-MR values shall be assigned */
3070 if (spars1.rp.msg_ref == 'FF'O) {
Vadim Yanitskiy286b0422024-01-09 18:11:04 +07003071 setverdict(fail, "Unassigned SM-RP-MR value for the 1st SMS");
Vadim Yanitskiybe1ff4b2019-01-18 15:04:13 +07003072 }
3073 if (spars2.rp.msg_ref == 'FF'O) {
Vadim Yanitskiy286b0422024-01-09 18:11:04 +07003074 setverdict(fail, "Unassigned SM-RP-MR value for the 2nd SMS");
Vadim Yanitskiybe1ff4b2019-01-18 15:04:13 +07003075 }
3076
3077 /* Send the 1st RP-ACK and expect MT-forwardSM-Res on GSUP */
3078 f_mt_sms_send_rp_ack(spars1);
3079 alt {
3080 [] GSUP.receive(tr_GSUP_MT_FORWARD_SM_RES(
3081 imsi := g_pars.imsi,
3082 sm_rp_mr := spars1.rp.msg_ref
3083 )) {
3084 log("RX MT-forwardSM-Res (RP-ACK)");
3085 setverdict(pass);
3086 }
3087 [] GSUP.receive {
Vadim Yanitskiy286b0422024-01-09 18:11:04 +07003088 setverdict(fail, "Rx unexpected GSUP message");
Vadim Yanitskiybe1ff4b2019-01-18 15:04:13 +07003089 mtc.stop;
3090 }
3091 }
3092
3093 /* Send the 2nd RP-ACK and expect MT-forwardSM-Res on GSUP */
3094 f_mt_sms_send_rp_ack(spars2);
3095 alt {
3096 [] GSUP.receive(tr_GSUP_MT_FORWARD_SM_RES(
3097 imsi := g_pars.imsi,
3098 sm_rp_mr := spars2.rp.msg_ref
3099 )) {
3100 log("RX MT-forwardSM-Res (RP-ACK)");
3101 setverdict(pass);
3102 }
3103 [] GSUP.receive {
Vadim Yanitskiy286b0422024-01-09 18:11:04 +07003104 setverdict(fail, "Rx unexpected GSUP message");
Vadim Yanitskiybe1ff4b2019-01-18 15:04:13 +07003105 mtc.stop;
3106 }
3107 }
3108
3109 f_expect_clear();
3110}
3111testcase TC_gsup_mt_sms_rp_mr() runs on MTC_CT {
3112 var BSC_ConnHdlrPars pars;
3113 var BSC_ConnHdlr vc_conn;
3114 f_init();
3115 pars := f_init_pars(92);
3116 f_vty_config(MSCVTY, "msc", "sms-over-gsup");
3117 vc_conn := f_start_handler_with_pars(refers(f_tc_gsup_mt_sms_rp_mr), pars);
3118 vc_conn.done;
3119 f_vty_config(MSCVTY, "msc", "no sms-over-gsup");
3120}
3121
Harald Weltee13cfb22019-04-23 16:52:02 +02003122
Vadim Yanitskiy5ac49cc2019-01-24 16:57:31 +07003123/* Test SM-RP-MR assignment for MT-SMS over GSUP */
Harald Weltee13cfb22019-04-23 16:52:02 +02003124friend function f_tc_gsup_mo_mt_sms_rp_mr(charstring id, BSC_ConnHdlrPars pars)
Vadim Yanitskiy5ac49cc2019-01-24 16:57:31 +07003125runs on BSC_ConnHdlr {
3126 var SmsParameters spars_mo := valueof(t_SmsPars); /* MO SMMA */
3127 var SmsParameters spars_mt := valueof(t_SmsPars); /* MT SMS */
3128
3129 f_init_handler(pars);
3130
3131 /* We need to inspect GSUP activity */
3132 f_create_gsup_expect(hex2str(g_pars.imsi));
3133
3134 /* Perform location update */
3135 f_perform_lu();
3136
3137 /* Register an 'expect' for given IMSI (+TMSI) */
Vadim Yanitskiyae747742020-01-10 00:23:10 +01003138 f_ran_register_imsi(g_pars.imsi, g_pars.tmsi);
Vadim Yanitskiy5ac49cc2019-01-24 16:57:31 +07003139
3140 /* Send CM Service Request for MO SMMA */
3141 f_establish_fully(EST_TYPE_MO_SMS);
3142
3143 /* Submit MO SMMA on DTAP */
3144 log("Submit MO SMMA on DTAP, SM-RP-MR is '00'O");
3145 spars_mo.rp.msg_ref := '00'O;
3146 f_mo_smma(spars_mo);
3147
3148 /* Expect MO-forwardSM-Req for MO SMMA on GSUP */
3149 alt {
3150 [] GSUP.receive(tr_GSUP_MO_READY_FOR_SM_REQ(
3151 imsi := g_pars.imsi,
3152 sm_rp_mr := spars_mo.rp.msg_ref,
3153 sm_alert_rsn := GSUP_SM_ALERT_RSN_TYPE_MEM_AVAIL
3154 )) {
3155 log("RX MO-ReadyForSM-Req, SM-RP-MR is '00'O");
3156 setverdict(pass);
3157 }
3158 [] GSUP.receive {
Vadim Yanitskiy286b0422024-01-09 18:11:04 +07003159 setverdict(fail, "Rx unexpected GSUP message");
Vadim Yanitskiy5ac49cc2019-01-24 16:57:31 +07003160 mtc.stop;
3161 }
3162 }
3163
3164 /* Submit MT SMS on GSUP */
3165 log("TX MT-forwardSM-Req for the MT SMS");
3166 f_gsup_forwardSM_req(spars_mt);
3167
3168 /* Wait for MT SMS on DTAP */
3169 f_mt_sms_expect(spars_mt);
3170 log("RX MT SMS on DTAP, DTAP TID is ", spars_mt.tid,
3171 ", SM-RP-MR is ", spars_mt.rp.msg_ref);
3172
3173 /* Both SM-RP-MR values shall be different */
3174 if (spars_mo.rp.msg_ref == spars_mt.rp.msg_ref) {
Vadim Yanitskiy286b0422024-01-09 18:11:04 +07003175 setverdict(fail, "Both SM-RP-MR values shall be different");
Vadim Yanitskiy5ac49cc2019-01-24 16:57:31 +07003176 }
3177
3178 /* SM-RP-MR value for MT SMS shall be assigned */
3179 if (spars_mt.rp.msg_ref == 'FF'O) {
Vadim Yanitskiy286b0422024-01-09 18:11:04 +07003180 setverdict(fail, "Unassigned SM-RP-MR value for the MT SMS");
Vadim Yanitskiy5ac49cc2019-01-24 16:57:31 +07003181 }
3182
3183 /* Trigger RP-ACK for MO SMMA by sending MO-forwardSM-Res */
3184 GSUP.send(valueof(ts_GSUP_MO_READY_FOR_SM_RES(
3185 imsi := g_pars.imsi,
3186 sm_rp_mr := spars_mo.rp.msg_ref)));
3187 /* Expect RP-ACK for MO SMMA on DTAP */
3188 f_mo_sms_wait_rp_ack(spars_mo);
3189
3190 /* Send RP-ACK for MT SMS and expect MT-forwardSM-Res on GSUP */
3191 f_mt_sms_send_rp_ack(spars_mt);
3192 alt {
3193 [] GSUP.receive(tr_GSUP_MT_FORWARD_SM_RES(
3194 imsi := g_pars.imsi,
3195 sm_rp_mr := spars_mt.rp.msg_ref
3196 )) {
3197 log("RX MT-forwardSM-Res (RP-ACK)");
3198 setverdict(pass);
3199 }
3200 [] GSUP.receive {
Vadim Yanitskiy286b0422024-01-09 18:11:04 +07003201 setverdict(fail, "Rx unexpected GSUP message");
Vadim Yanitskiy5ac49cc2019-01-24 16:57:31 +07003202 mtc.stop;
3203 }
3204 }
3205
3206 f_expect_clear();
3207}
3208testcase TC_gsup_mo_mt_sms_rp_mr() runs on MTC_CT {
3209 var BSC_ConnHdlrPars pars;
3210 var BSC_ConnHdlr vc_conn;
3211 f_init();
3212 pars := f_init_pars(93);
3213 f_vty_config(MSCVTY, "msc", "sms-over-gsup");
3214 vc_conn := f_start_handler_with_pars(refers(f_tc_gsup_mo_mt_sms_rp_mr), pars);
3215 vc_conn.done;
3216 f_vty_config(MSCVTY, "msc", "no sms-over-gsup");
3217}
3218
Harald Weltee13cfb22019-04-23 16:52:02 +02003219
Vadim Yanitskiy1cd11a02018-12-03 02:43:35 +07003220/* Test multi-part MT-SMS over GSUP */
3221private function f_tc_gsup_mt_multi_part_sms(charstring id, BSC_ConnHdlrPars pars)
3222runs on BSC_ConnHdlr {
3223 var SmsParameters spars := valueof(t_SmsPars);
3224
3225 f_init_handler(pars);
3226
3227 /* We need to inspect GSUP activity */
3228 f_create_gsup_expect(hex2str(g_pars.imsi));
3229
3230 /* Perform location update */
3231 f_perform_lu();
3232
3233 /* Register an 'expect' for given IMSI (+TMSI) */
Vadim Yanitskiyae747742020-01-10 00:23:10 +01003234 f_ran_register_imsi(g_pars.imsi, g_pars.tmsi);
Vadim Yanitskiy1cd11a02018-12-03 02:43:35 +07003235
3236 var template GSUP_PDU mt_forwardSM_res := tr_GSUP_MT_FORWARD_SM_RES(
3237 imsi := g_pars.imsi,
3238 /* NOTE: MSC should assign RP-MR itself */
3239 sm_rp_mr := ?
3240 );
3241
3242 /* Send 4 messages (NOTE: SM-RP-UI remains unchanged) */
3243 for (var integer i := 3; i >= 0; i := i-1) {
3244 /* Submit a MT SMS on GSUP (MMS is decremented) */
3245 f_gsup_forwardSM_req(spars, int2oct(i, 1));
3246
3247 /* Expect Paging Request and Establish connection */
3248 if (i == 3) { /* ... only once! */
Harald Weltee13cfb22019-04-23 16:52:02 +02003249 f_expect_paging();
Vadim Yanitskiy1cd11a02018-12-03 02:43:35 +07003250 f_establish_fully(EST_TYPE_PAG_RESP);
3251 }
3252
3253 /* Wait for MT SMS on DTAP */
3254 f_mt_sms_expect(spars);
3255
3256 /* Send RP-ACK and expect MT-forwardSM-Res on GSUP */
3257 f_mt_sms_send_rp_ack(spars);
3258 alt {
3259 [] GSUP.receive(mt_forwardSM_res) {
3260 log("RX MT-forwardSM-Res (RP-ACK)");
3261 setverdict(pass);
3262 }
3263 [] GSUP.receive {
Vadim Yanitskiy286b0422024-01-09 18:11:04 +07003264 setverdict(fail, "Rx unexpected GSUP message");
Vadim Yanitskiy1cd11a02018-12-03 02:43:35 +07003265 mtc.stop;
3266 }
3267 }
3268
3269 /* Keep some 'distance' between transmissions */
3270 f_sleep(1.5);
3271 }
3272
3273 f_expect_clear();
3274}
3275testcase TC_gsup_mt_multi_part_sms() runs on MTC_CT {
3276 var BSC_ConnHdlrPars pars;
3277 var BSC_ConnHdlr vc_conn;
3278 f_init();
3279 pars := f_init_pars(91);
3280 f_vty_config(MSCVTY, "msc", "sms-over-gsup");
3281 vc_conn := f_start_handler_with_pars(refers(f_tc_gsup_mt_multi_part_sms), pars);
3282 vc_conn.done;
3283 f_vty_config(MSCVTY, "msc", "no sms-over-gsup");
3284}
3285
Vadim Yanitskiy8d0d7af2024-05-10 15:14:43 +02003286/* Test X36 (LU delay) timer allowing to deliver MT SMS over the same connection */
3287friend function f_TC_gsup_mt_sms_lu_delay(charstring id, BSC_ConnHdlrPars pars)
3288runs on BSC_ConnHdlr {
3289 var SmsParameters spars := valueof(t_SmsPars);
3290
3291 f_init_handler(pars);
3292
3293 /* We need to inspect GSUP activity */
3294 f_create_gsup_expect(hex2str(g_pars.imsi));
3295
3296 /* Perform location update */
3297 f_perform_lu(expect_clear := false);
3298
3299 /* Register an 'expect' for given IMSI (+TMSI) */
3300 f_ran_register_imsi(g_pars.imsi, g_pars.tmsi);
3301
3302 var template GSUP_PDU mt_forwardSM_res := tr_GSUP_MT_FORWARD_SM_RES(
3303 imsi := g_pars.imsi,
3304 /* NOTE: MSC should assign RP-MR itself */
3305 sm_rp_mr := ?
3306 );
3307
3308 /* Some delay to make sure the connection remains alive */
3309 f_sleep(0.5);
3310
3311 /* Submit a MT SMS on GSUP */
3312 f_gsup_forwardSM_req(spars);
3313
3314 /* Wait for MT SMS on DTAP */
3315 f_mt_sms_expect(spars);
3316
3317 /* Send RP-ACK and expect MT-forwardSM-Res on GSUP */
3318 f_mt_sms_send_rp_ack(spars);
3319 alt {
3320 [] GSUP.receive(mt_forwardSM_res) {
3321 log("RX MT-forwardSM-Res (RP-ACK)");
3322 setverdict(pass);
3323 }
3324 [] GSUP.receive {
3325 setverdict(fail, "Rx unexpected GSUP message");
3326 mtc.stop;
3327 }
3328 }
3329
3330 f_expect_clear();
3331}
3332testcase TC_gsup_mt_sms_lu_delay() runs on MTC_CT {
3333 var BSC_ConnHdlrPars pars;
3334 var BSC_ConnHdlr vc_conn;
3335 f_init();
3336 pars := f_init_pars(92);
3337 f_vty_config(MSCVTY, "msc", "sms-over-gsup");
3338 f_vty_config(MSCVTY, "msc", "timer geran X36 2500"); /* 2.5s */
3339 vc_conn := f_start_handler_with_pars(refers(f_TC_gsup_mt_sms_lu_delay), pars);
3340 vc_conn.done;
3341 f_vty_config(MSCVTY, "msc", "timer geran X36 0");
3342 f_vty_config(MSCVTY, "msc", "no sms-over-gsup");
3343}
3344
Harald Weltef640a012018-04-14 17:49:21 +02003345/* convert GSM L3 TON to SMPP_TON enum */
3346function f_sm_ton_from_gsm(BIT3 ton) return SMPP_TON {
3347 select (ton) {
3348 case ('000'B) { return unknown; }
3349 case ('001'B) { return international; }
3350 case ('010'B) { return national; }
3351 case ('011'B) { return network_specific; }
3352 case ('100'B) { return subscriber_number; }
3353 case ('101'B) { return alphanumeric; }
3354 case ('110'B) { return abbreviated; }
3355 }
3356 setverdict(fail, "Unknown TON ", ton);
Daniel Willmannafce8662018-07-06 23:11:32 +02003357 mtc.stop;
Harald Weltef640a012018-04-14 17:49:21 +02003358}
3359/* convert GSM L3 NPI to SMPP_NPI enum */
3360function f_sm_npi_from_gsm(BIT4 npi) return SMPP_NPI {
3361 select (npi) {
3362 case ('0000'B) { return unknown; }
3363 case ('0001'B) { return isdn; }
3364 case ('0011'B) { return data; }
3365 case ('0100'B) { return telex; }
3366 case ('0110'B) { return land_mobile; }
3367 case ('1000'B) { return national; }
3368 case ('1001'B) { return private_; }
3369 case ('1010'B) { return ermes; }
3370 }
3371 setverdict(fail, "Unknown NPI ", npi);
Daniel Willmannafce8662018-07-06 23:11:32 +02003372 mtc.stop;
Harald Weltef640a012018-04-14 17:49:21 +02003373}
3374
3375/* build a SMPP_SM from SmsParameters */
3376function f_mt_sm_from_spars(SmsParameters spars)
3377runs on BSC_ConnHdlr return SMPP_SM {
3378 var SMPP_SM sm := {
3379 service_type := "CMT",
3380 source_addr_ton := f_sm_ton_from_gsm(spars.tp.da.tP_DA_NoPad.tP_TypeOfNumber),
3381 source_addr_npi := f_sm_npi_from_gsm(spars.tp.da.tP_DA_NoPad.tP_NumberingPlanID),
3382 source_addr := hex2str(spars.tp.da.tP_DA_NoPad.tP_DAValue),
3383 dest_addr_ton := international,
3384 dest_addr_npi := isdn,
3385 destination_addr := hex2str(g_pars.msisdn),
3386 esm_class := '00000001'B,
3387 protocol_id := 0,
3388 priority_flag := 0,
3389 schedule_delivery_time := "",
3390 validity_period := "",
3391 registered_delivery := '00000000'B,
3392 replace_if_present := 0,
3393 data_coding := '00000001'B,
3394 sm_default_msg_id := 0,
3395 sm_length := spars.tp.udl,
3396 short_message := spars.tp.ud,
3397 opt_pars := {}
3398 };
3399 return sm;
3400}
3401
3402/* helper function to encode SMS from 'spars', send it via SMPP to MSC; receive it on MS side */
3403private function f_smpp_mt_sms(SmsParameters spars, boolean trans_mode) runs on BSC_ConnHdlr {
3404 var SMPP_SM sm := f_mt_sm_from_spars(spars);
3405 if (trans_mode) {
3406 sm.esm_class := '00000010'B;
3407 }
3408
3409 /* actually cause MSC to send a SMS via SUBMIT-SM from SMPP side */
3410 SMPP.send(ts_SMPP_SUBMIT_SM(sm));
3411 if (not match(sm.esm_class, tr_ESM_CLASS_TRANSACTION)) {
3412 /* if we're not in SMPP transaction mode, we expect the SMPP-level ACK
3413 * before we expect the SMS delivery on the BSC/radio side */
3414 SMPP.receive(tr_SMPP(c_SMPP_command_id_submit_sm_resp, ESME_ROK));
3415 }
3416
3417 /* MSC->BSC: expect PAGING from MSC */
Harald Weltee035e3e2019-04-21 17:32:05 +02003418 f_expect_paging();
Harald Weltef640a012018-04-14 17:49:21 +02003419 /* Establish DTAP / BSSAP / SCCP connection */
3420 f_establish_fully(EST_TYPE_PAG_RESP);
3421 SMPP.receive(tr_SMPP(c_SMPP_command_id_alert_notification, ESME_ROK));
3422
3423 f_mt_sms(spars);
3424
3425 if (match(sm.esm_class, tr_ESM_CLASS_TRANSACTION)) {
3426 SMPP.receive(tr_SMPP(c_SMPP_command_id_submit_sm_resp, ESME_ROK));
3427 }
3428 f_expect_clear();
3429}
3430
3431/* mobile terminated SMS, from SMPP to BSC/BTS/MS */
3432private function f_tc_smpp_mt_sms(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
3433 f_init_handler(pars);
3434
3435 /* Perform location update so IMSI is known + registered in MSC/VLR */
3436 f_perform_lu();
3437 SMPP.receive(tr_SMPP(c_SMPP_command_id_alert_notification, ESME_ROK));
3438
3439 /* register an 'expect' for given IMSI (+TMSI) */
Vadim Yanitskiyae747742020-01-10 00:23:10 +01003440 f_ran_register_imsi(g_pars.imsi, g_pars.tmsi);
Harald Weltef640a012018-04-14 17:49:21 +02003441
3442 var SmsParameters spars := valueof(t_SmsPars);
3443 /* TODO: test with more intelligent user data; test different coding schemes */
3444 spars.tp.ud := '00'O;
3445 spars.tp.udl := 1;
3446
3447 /* first test the non-transaction store+forward mode */
3448 f_smpp_mt_sms(spars, false);
3449
3450 /* then test the transaction mode */
3451 f_smpp_mt_sms(spars, true);
3452}
3453testcase TC_smpp_mt_sms() runs on MTC_CT {
3454 var BSC_ConnHdlr vc_conn;
3455 f_init();
3456 vc_conn := f_start_handler(refers(f_tc_smpp_mt_sms), 45);
3457 vc_conn.done;
3458}
3459
Vadim Yanitskiy7d1f9182018-05-28 16:21:42 +07003460/***********************************************************************
3461 * USSD Testing
3462 ***********************************************************************/
3463
Vadim Yanitskiyce8cc372018-06-21 01:46:33 +07003464private altstep as_unexp_gsup_or_bssap_msg()
3465runs on BSC_ConnHdlr {
3466 [] GSUP.receive {
3467 setverdict(fail, "Unknown/unexpected GSUP received");
3468 self.stop;
3469 }
3470 [] BSSAP.receive {
3471 setverdict(fail, "Unknown/unexpected BSSAP message received");
3472 self.stop;
3473 }
3474}
3475
Vadim Yanitskiye5f4ed92019-06-16 02:36:33 +07003476private function f_expect_gsup_msg(template GSUP_PDU msg,
3477 float T_val := 2.0)
Vadim Yanitskiyce8cc372018-06-21 01:46:33 +07003478runs on BSC_ConnHdlr return GSUP_PDU {
3479 var GSUP_PDU gsup_msg_complete;
Vadim Yanitskiye5f4ed92019-06-16 02:36:33 +07003480 timer T := T_val;
Vadim Yanitskiyce8cc372018-06-21 01:46:33 +07003481
Vadim Yanitskiyd1e1ce52019-06-15 03:40:59 +07003482 T.start;
Vadim Yanitskiyce8cc372018-06-21 01:46:33 +07003483 alt {
3484 [] GSUP.receive(msg) -> value gsup_msg_complete {
3485 setverdict(pass);
3486 }
3487 /* We don't expect anything else */
3488 [] as_unexp_gsup_or_bssap_msg();
Vadim Yanitskiyd1e1ce52019-06-15 03:40:59 +07003489 [] T.timeout {
3490 setverdict(fail, "Timeout waiting for GSUP message: ", msg);
3491 }
Vadim Yanitskiyce8cc372018-06-21 01:46:33 +07003492 }
3493
3494 return gsup_msg_complete;
3495}
3496
Vadim Yanitskiye5f4ed92019-06-16 02:36:33 +07003497private function f_expect_mt_dtap_msg(template PDU_ML3_NW_MS msg,
3498 float T_val := 2.0)
Vadim Yanitskiyce8cc372018-06-21 01:46:33 +07003499runs on BSC_ConnHdlr return PDU_ML3_NW_MS {
3500 var PDU_DTAP_MT bssap_msg_complete;
Vadim Yanitskiye5f4ed92019-06-16 02:36:33 +07003501 timer T := T_val;
Vadim Yanitskiyce8cc372018-06-21 01:46:33 +07003502
Vadim Yanitskiyd1e1ce52019-06-15 03:40:59 +07003503 T.start;
Vadim Yanitskiyce8cc372018-06-21 01:46:33 +07003504 alt {
3505 [] BSSAP.receive(tr_PDU_DTAP_MT(msg)) -> value bssap_msg_complete {
3506 setverdict(pass);
3507 }
3508 /* We don't expect anything else */
3509 [] as_unexp_gsup_or_bssap_msg();
Vadim Yanitskiyd1e1ce52019-06-15 03:40:59 +07003510 [] T.timeout {
3511 setverdict(fail, "Timeout waiting for BSSAP message: ", msg);
3512 }
Vadim Yanitskiyce8cc372018-06-21 01:46:33 +07003513 }
3514
3515 return bssap_msg_complete.dtap;
3516}
3517
Vadim Yanitskiy2a978b92018-06-19 17:51:20 +07003518/* LU followed by MO USSD request */
Harald Weltee13cfb22019-04-23 16:52:02 +02003519friend function f_tc_lu_and_mo_ussd_single_request(charstring id, BSC_ConnHdlrPars pars)
Vadim Yanitskiy7d1f9182018-05-28 16:21:42 +07003520runs on BSC_ConnHdlr {
3521 f_init_handler(pars);
3522
3523 /* Perform location update */
3524 f_perform_lu();
3525
3526 /* Send CM Service Request for SS/USSD */
3527 f_establish_fully(EST_TYPE_SS_ACT);
3528
Vadim Yanitskiy747689e2018-06-19 00:14:28 +07003529 /* We need to inspect GSUP activity */
3530 f_create_gsup_expect(hex2str(g_pars.imsi));
3531
3532 var template OCTN facility_req := f_USSD_FACILITY_IE_INVOKE(
3533 invoke_id := 5, /* Phone may not start from 0 or 1 */
3534 op_code := SS_OP_CODE_PROCESS_USS_REQ,
3535 ussd_string := "*#100#"
3536 );
3537
3538 var template OCTN facility_rsp := f_USSD_FACILITY_IE_RETURN_RESULT(
3539 invoke_id := 5, /* InvokeID shall be the same for both REQ and RSP */
3540 op_code := SS_OP_CODE_PROCESS_USS_REQ,
3541 ussd_string := "Your extension is " & hex2str(g_pars.msisdn) & "\r"
3542 )
3543
Vadim Yanitskiy7d1f9182018-05-28 16:21:42 +07003544 /* Compose a new SS/REGISTER message with request */
3545 var template (value) PDU_ML3_MS_NW ussd_req := ts_ML3_MO_SS_REGISTER(
3546 tid := 1, /* We just need a single transaction */
3547 ti_flag := c_TIF_ORIG, /* Sent from the side that originates the TI */
Vadim Yanitskiy747689e2018-06-19 00:14:28 +07003548 facility := valueof(facility_req)
Vadim Yanitskiy7d1f9182018-05-28 16:21:42 +07003549 );
3550
3551 /* Compose SS/RELEASE_COMPLETE template with expected response */
3552 var template PDU_ML3_NW_MS ussd_rsp := tr_ML3_MT_SS_RELEASE_COMPLETE(
3553 tid := 1, /* Response should arrive within the same transaction */
3554 ti_flag := c_TIF_REPL, /* Sent to the side that originates the TI */
Vadim Yanitskiy747689e2018-06-19 00:14:28 +07003555 facility := valueof(facility_rsp)
Vadim Yanitskiy7d1f9182018-05-28 16:21:42 +07003556 );
3557
Vadim Yanitskiy747689e2018-06-19 00:14:28 +07003558 /* Compose expected MSC -> HLR message */
3559 var template GSUP_PDU gsup_req := tr_GSUP_PROC_SS_REQ(
3560 imsi := g_pars.imsi,
3561 state := OSMO_GSUP_SESSION_STATE_BEGIN,
3562 ss := valueof(facility_req)
3563 );
3564
3565 /* To be used for sending response with correct session ID */
3566 var GSUP_PDU gsup_req_complete;
3567
3568 /* Request own number */
Vadim Yanitskiy7d1f9182018-05-28 16:21:42 +07003569 BSSAP.send(ts_PDU_DTAP_MO(ussd_req));
Vadim Yanitskiy747689e2018-06-19 00:14:28 +07003570 /* Expect GSUP message containing the SS payload */
3571 gsup_req_complete := f_expect_gsup_msg(gsup_req);
3572
3573 /* Compose the response from HLR using received session ID */
3574 var template GSUP_PDU gsup_rsp := ts_GSUP_PROC_SS_REQ(
3575 imsi := g_pars.imsi,
3576 sid := gsup_req_complete.ies[1].val.session_id,
3577 state := OSMO_GSUP_SESSION_STATE_END,
3578 ss := valueof(facility_rsp)
3579 );
3580
3581 /* Finally, HLR terminates the session */
3582 GSUP.send(gsup_rsp);
3583 /* Expect RELEASE_COMPLETE message with the response */
3584 f_expect_mt_dtap_msg(ussd_rsp);
Vadim Yanitskiy7d1f9182018-05-28 16:21:42 +07003585
3586 f_expect_clear();
3587}
Vadim Yanitskiy2a978b92018-06-19 17:51:20 +07003588testcase TC_lu_and_mo_ussd_single_request() runs on MTC_CT {
Vadim Yanitskiy7d1f9182018-05-28 16:21:42 +07003589 var BSC_ConnHdlr vc_conn;
3590 f_init();
Vadim Yanitskiy2a978b92018-06-19 17:51:20 +07003591 vc_conn := f_start_handler(refers(f_tc_lu_and_mo_ussd_single_request), 46);
Vadim Yanitskiy7d1f9182018-05-28 16:21:42 +07003592 vc_conn.done;
3593}
3594
Harald Weltee13cfb22019-04-23 16:52:02 +02003595
Vadim Yanitskiy13e4a272018-06-19 18:24:31 +07003596/* LU followed by MT USSD notification */
Harald Weltee13cfb22019-04-23 16:52:02 +02003597friend function f_tc_lu_and_mt_ussd_notification(charstring id, BSC_ConnHdlrPars pars)
Vadim Yanitskiy13e4a272018-06-19 18:24:31 +07003598runs on BSC_ConnHdlr {
Vadim Yanitskiyd1e1ce52019-06-15 03:40:59 +07003599 timer T := 5.0;
3600
Vadim Yanitskiy13e4a272018-06-19 18:24:31 +07003601 f_init_handler(pars);
3602
3603 /* Perform location update */
3604 f_perform_lu();
3605
Harald Welte6811d102019-04-14 22:23:14 +02003606 f_ran_register_imsi(g_pars.imsi, g_pars.tmsi);
Vadim Yanitskiy13e4a272018-06-19 18:24:31 +07003607
3608 /* We need to inspect GSUP activity */
3609 f_create_gsup_expect(hex2str(g_pars.imsi));
3610
3611 /* Facility IE with network-originated USSD notification */
3612 var template OCTN facility_req := f_USSD_FACILITY_IE_INVOKE(
3613 op_code := SS_OP_CODE_USS_NOTIFY,
3614 ussd_string := "Mahlzeit!"
3615 );
3616
3617 /* Facility IE with acknowledgment to the USSD notification */
3618 var template OCTN facility_rsp := enc_SS_FacilityInformation(
3619 /* In case of USSD notification, Return Result is empty */
3620 valueof(ts_SS_USSD_FACILITY_RETURN_RESULT_EMPTY())
3621 );
3622
3623 /* Compose a new MT SS/REGISTER message with USSD notification */
3624 var template PDU_ML3_NW_MS ussd_ntf := tr_ML3_MT_SS_REGISTER(
3625 tid := 0, /* FIXME: most likely, it should be 0 */
3626 ti_flag := c_TIF_ORIG, /* Sent from the side that originates the TI */
3627 facility := valueof(facility_req)
3628 );
3629
3630 /* Compose HLR -> MSC GSUP message */
3631 var template (value) GSUP_PDU gsup_req := ts_GSUP_PROC_SS_REQ(
3632 imsi := g_pars.imsi,
Vadim Yanitskiy2dd96612020-01-07 21:48:29 +01003633 sid := g_pars.gsup_sid,
Vadim Yanitskiy13e4a272018-06-19 18:24:31 +07003634 state := OSMO_GSUP_SESSION_STATE_BEGIN,
3635 ss := valueof(facility_req)
3636 );
3637
3638 /* Send it to MSC and expect Paging Request */
3639 GSUP.send(gsup_req);
Vadim Yanitskiyd1e1ce52019-06-15 03:40:59 +07003640 T.start;
Vadim Yanitskiy13e4a272018-06-19 18:24:31 +07003641 alt {
Vadim Yanitskiy53f2be62024-04-14 19:48:39 +07003642 [] as_paging() { setverdict(pass); }
3643 [] as_paging_any() {
3644 setverdict(fail, "Rx unexpected BSSMAP/RANAP Paging");
3645 mtc.stop;
Harald Weltee13cfb22019-04-23 16:52:02 +02003646 }
Vadim Yanitskiy13e4a272018-06-19 18:24:31 +07003647 [] as_unexp_gsup_or_bssap_msg();
Vadim Yanitskiyd1e1ce52019-06-15 03:40:59 +07003648 [] T.timeout {
3649 setverdict(fail, "Timeout waiting for Paging Request");
3650 }
Vadim Yanitskiy13e4a272018-06-19 18:24:31 +07003651 }
3652
3653 /* Send Paging Response and expect USSD notification */
3654 f_establish_fully(EST_TYPE_PAG_RESP);
3655 /* Expect MT REGISTER message with USSD notification */
3656 f_expect_mt_dtap_msg(ussd_ntf);
3657
3658 /* Compose a new MO SS/FACILITY message with empty response */
3659 var template (value) PDU_ML3_MS_NW ussd_rsp := ts_ML3_MO_SS_FACILITY(
3660 tid := 0, /* FIXME: it shall match the request tid */
3661 ti_flag := c_TIF_REPL, /* Sent to the side that originates the TI */
3662 facility := valueof(facility_rsp)
3663 );
3664
3665 /* Compose expected MSC -> HLR GSUP message */
3666 var template GSUP_PDU gsup_rsp := tr_GSUP_PROC_SS_REQ(
3667 imsi := g_pars.imsi,
Vadim Yanitskiy2dd96612020-01-07 21:48:29 +01003668 sid := g_pars.gsup_sid,
Vadim Yanitskiy13e4a272018-06-19 18:24:31 +07003669 state := OSMO_GSUP_SESSION_STATE_CONTINUE,
3670 ss := valueof(facility_rsp)
3671 );
3672
3673 /* MS sends response to the notification */
3674 BSSAP.send(ts_PDU_DTAP_MO(ussd_rsp));
3675 /* Expect GSUP message containing the SS payload */
3676 f_expect_gsup_msg(gsup_rsp);
3677
3678 /* Compose expected MT SS/RELEASE COMPLETE message */
3679 var template PDU_ML3_NW_MS ussd_term := tr_ML3_MT_SS_RELEASE_COMPLETE(
3680 tid := 0, /* FIXME: it shall match the request tid */
3681 ti_flag := c_TIF_ORIG, /* Sent from the side that originates the TI */
3682 facility := omit
3683 );
3684
3685 /* Compose MSC -> HLR GSUP message */
3686 var template GSUP_PDU gsup_term := ts_GSUP_PROC_SS_REQ(
3687 imsi := g_pars.imsi,
Vadim Yanitskiy2dd96612020-01-07 21:48:29 +01003688 sid := g_pars.gsup_sid,
Vadim Yanitskiy13e4a272018-06-19 18:24:31 +07003689 state := OSMO_GSUP_SESSION_STATE_END
3690 );
3691
3692 /* Finally, HLR terminates the session */
3693 GSUP.send(gsup_term)
3694 /* Expect MT RELEASE COMPLETE without Facility IE */
3695 f_expect_mt_dtap_msg(ussd_term);
3696
3697 f_expect_clear();
3698}
3699testcase TC_lu_and_mt_ussd_notification() runs on MTC_CT {
3700 var BSC_ConnHdlr vc_conn;
3701 f_init();
3702 vc_conn := f_start_handler(refers(f_tc_lu_and_mt_ussd_notification), 47);
3703 vc_conn.done;
3704}
3705
Harald Weltee13cfb22019-04-23 16:52:02 +02003706
Vadim Yanitskiy2a978b92018-06-19 17:51:20 +07003707/* LU followed by MT call and MO USSD request during this call */
Harald Weltee13cfb22019-04-23 16:52:02 +02003708friend function f_tc_lu_and_mo_ussd_during_mt_call(charstring id, BSC_ConnHdlrPars pars)
Vadim Yanitskiy0aaf48d2018-06-06 07:02:47 +07003709runs on BSC_ConnHdlr {
3710 f_init_handler(pars);
3711
3712 /* Call parameters taken from f_tc_lu_and_mt_call */
3713 var CallParameters cpars := valueof(t_CallParams('123456'H, 0));
Vadim Yanitskiy0aaf48d2018-06-06 07:02:47 +07003714
3715 /* Perform location update */
3716 f_perform_lu();
3717
3718 /* Establish a MT call */
3719 f_mt_call_establish(cpars);
3720
3721 /* Hold the call for some time */
3722 f_sleep(1.0);
3723
Vadim Yanitskiy747689e2018-06-19 00:14:28 +07003724 var template OCTN facility_req := f_USSD_FACILITY_IE_INVOKE(
3725 op_code := SS_OP_CODE_PROCESS_USS_REQ,
3726 ussd_string := "*#100#"
3727 );
3728
3729 var template OCTN facility_rsp := f_USSD_FACILITY_IE_RETURN_RESULT(
3730 op_code := SS_OP_CODE_PROCESS_USS_REQ,
3731 ussd_string := "Your extension is " & hex2str(g_pars.msisdn) & "\r"
3732 )
3733
Vadim Yanitskiy0aaf48d2018-06-06 07:02:47 +07003734 /* Compose a new SS/REGISTER message with request */
3735 var template (value) PDU_ML3_MS_NW ussd_req := ts_ML3_MO_SS_REGISTER(
3736 tid := 1, /* We just need a single transaction */
3737 ti_flag := c_TIF_ORIG, /* Sent from the side that originates the TI */
Vadim Yanitskiy747689e2018-06-19 00:14:28 +07003738 facility := valueof(facility_req)
Vadim Yanitskiy0aaf48d2018-06-06 07:02:47 +07003739 );
3740
3741 /* Compose SS/RELEASE_COMPLETE template with expected response */
3742 var template PDU_ML3_NW_MS ussd_rsp := tr_ML3_MT_SS_RELEASE_COMPLETE(
3743 tid := 1, /* Response should arrive within the same transaction */
3744 ti_flag := c_TIF_REPL, /* Sent to the side that originates the TI */
Vadim Yanitskiy747689e2018-06-19 00:14:28 +07003745 facility := valueof(facility_rsp)
Vadim Yanitskiy0aaf48d2018-06-06 07:02:47 +07003746 );
3747
Vadim Yanitskiy747689e2018-06-19 00:14:28 +07003748 /* Compose expected MSC -> HLR message */
3749 var template GSUP_PDU gsup_req := tr_GSUP_PROC_SS_REQ(
3750 imsi := g_pars.imsi,
3751 state := OSMO_GSUP_SESSION_STATE_BEGIN,
3752 ss := valueof(facility_req)
3753 );
3754
3755 /* To be used for sending response with correct session ID */
3756 var GSUP_PDU gsup_req_complete;
3757
3758 /* Request own number */
Vadim Yanitskiy0aaf48d2018-06-06 07:02:47 +07003759 BSSAP.send(ts_PDU_DTAP_MO(ussd_req));
Vadim Yanitskiy747689e2018-06-19 00:14:28 +07003760 /* Expect GSUP message containing the SS payload */
3761 gsup_req_complete := f_expect_gsup_msg(gsup_req);
3762
3763 /* Compose the response from HLR using received session ID */
3764 var template GSUP_PDU gsup_rsp := ts_GSUP_PROC_SS_REQ(
3765 imsi := g_pars.imsi,
3766 sid := gsup_req_complete.ies[1].val.session_id,
3767 state := OSMO_GSUP_SESSION_STATE_END,
3768 ss := valueof(facility_rsp)
3769 );
3770
3771 /* Finally, HLR terminates the session */
3772 GSUP.send(gsup_rsp);
3773 /* Expect RELEASE_COMPLETE message with the response */
3774 f_expect_mt_dtap_msg(ussd_rsp);
Vadim Yanitskiy0aaf48d2018-06-06 07:02:47 +07003775
3776 /* Hold the call for some time */
3777 f_sleep(1.0);
3778
3779 /* Release the call (does Clear Complete itself) */
3780 f_call_hangup(cpars, true);
3781}
Vadim Yanitskiy2a978b92018-06-19 17:51:20 +07003782testcase TC_lu_and_mo_ussd_during_mt_call() runs on MTC_CT {
Vadim Yanitskiy0aaf48d2018-06-06 07:02:47 +07003783 var BSC_ConnHdlr vc_conn;
3784 f_init();
Vadim Yanitskiy2a978b92018-06-19 17:51:20 +07003785 vc_conn := f_start_handler(refers(f_tc_lu_and_mo_ussd_during_mt_call), 48);
Vadim Yanitskiy0aaf48d2018-06-06 07:02:47 +07003786 vc_conn.done;
3787}
3788
Neels Hofmeyr692c9ee2018-04-10 02:07:13 +02003789/* BSSMAP Clear Request in the middle of a call, see OS#3062 */
Harald Weltee13cfb22019-04-23 16:52:02 +02003790friend function f_tc_mo_cc_bssmap_clear(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Neels Hofmeyr692c9ee2018-04-10 02:07:13 +02003791 f_init_handler(pars);
3792 var CallParameters cpars := valueof(t_CallParams('12345'H, 0));
Neels Hofmeyr3c89a6b2019-10-15 16:54:37 +02003793 cpars.ran_clear_when_alerting := true;
Neels Hofmeyr692c9ee2018-04-10 02:07:13 +02003794
3795 f_perform_lu();
3796
Neels Hofmeyrde76f052019-02-26 05:02:46 +01003797 var default ccrel := activate(as_optional_cc_rel(cpars));
Neels Hofmeyr3c89a6b2019-10-15 16:54:37 +02003798 f_mo_call_establish(cpars);
3799 f_expect_clear()
Neels Hofmeyrde76f052019-02-26 05:02:46 +01003800 deactivate(ccrel);
Neels Hofmeyr692c9ee2018-04-10 02:07:13 +02003801
3802 f_sleep(1.0);
3803}
3804testcase TC_mo_cc_bssmap_clear() runs on MTC_CT {
3805 var BSC_ConnHdlr vc_conn;
3806 f_init();
3807
3808 vc_conn := f_start_handler(refers(f_tc_mo_cc_bssmap_clear), 43);
3809 vc_conn.done;
3810}
3811
Harald Weltee13cfb22019-04-23 16:52:02 +02003812
Vadim Yanitskiy13e4a272018-06-19 18:24:31 +07003813/* LU followed by MT call and MT USSD request during this call */
Harald Weltee13cfb22019-04-23 16:52:02 +02003814friend function f_tc_lu_and_mt_ussd_during_mt_call(charstring id, BSC_ConnHdlrPars pars)
Vadim Yanitskiy13e4a272018-06-19 18:24:31 +07003815runs on BSC_ConnHdlr {
3816 f_init_handler(pars);
3817
3818 /* Call parameters taken from f_tc_lu_and_mt_call */
3819 var CallParameters cpars := valueof(t_CallParams('123456'H, 0));
Vadim Yanitskiy13e4a272018-06-19 18:24:31 +07003820
3821 /* Perform location update */
3822 f_perform_lu();
3823
3824 /* Establish a MT call */
3825 f_mt_call_establish(cpars);
3826
3827 /* Hold the call for some time */
3828 f_sleep(1.0);
3829
3830 var template OCTN facility_req := f_USSD_FACILITY_IE_INVOKE(
3831 op_code := SS_OP_CODE_USS_REQUEST,
3832 ussd_string := "Please type anything..."
3833 );
3834
3835 var template OCTN facility_rsp := f_USSD_FACILITY_IE_RETURN_RESULT(
3836 op_code := SS_OP_CODE_USS_REQUEST,
3837 ussd_string := "Nope."
3838 )
3839
3840 /* Compose MT SS/REGISTER message with network-originated request */
3841 var template (value) PDU_ML3_NW_MS ussd_req := ts_ML3_MT_SS_REGISTER(
3842 tid := 0, /* FIXME: most likely, it should be 0 */
3843 ti_flag := c_TIF_ORIG, /* Sent from the side that originates the TI */
3844 facility := valueof(facility_req)
3845 );
3846
3847 /* Compose HLR -> MSC GSUP message */
3848 var template (value) GSUP_PDU gsup_req := ts_GSUP_PROC_SS_REQ(
3849 imsi := g_pars.imsi,
Vadim Yanitskiy2dd96612020-01-07 21:48:29 +01003850 sid := g_pars.gsup_sid,
Vadim Yanitskiy13e4a272018-06-19 18:24:31 +07003851 state := OSMO_GSUP_SESSION_STATE_BEGIN,
3852 ss := valueof(facility_req)
3853 );
3854
3855 /* Send it to MSC */
3856 GSUP.send(gsup_req);
3857 /* Expect MT REGISTER message with USSD request */
3858 f_expect_mt_dtap_msg(ussd_req);
3859
3860 /* Compose a new MO SS/FACILITY message with response */
3861 var template (value) PDU_ML3_MS_NW ussd_rsp := ts_ML3_MO_SS_FACILITY(
3862 tid := 0, /* FIXME: it shall match the request tid */
3863 ti_flag := c_TIF_REPL, /* Sent to the side that originates the TI */
3864 facility := valueof(facility_rsp)
3865 );
3866
3867 /* Compose expected MSC -> HLR GSUP message */
3868 var template GSUP_PDU gsup_rsp := tr_GSUP_PROC_SS_REQ(
3869 imsi := g_pars.imsi,
Vadim Yanitskiy2dd96612020-01-07 21:48:29 +01003870 sid := g_pars.gsup_sid,
Vadim Yanitskiy13e4a272018-06-19 18:24:31 +07003871 state := OSMO_GSUP_SESSION_STATE_CONTINUE,
3872 ss := valueof(facility_rsp)
3873 );
3874
3875 /* MS sends response */
3876 BSSAP.send(ts_PDU_DTAP_MO(ussd_rsp));
3877 f_expect_gsup_msg(gsup_rsp);
3878
3879 /* Compose expected MT SS/RELEASE COMPLETE message */
3880 var template PDU_ML3_NW_MS ussd_term := tr_ML3_MT_SS_RELEASE_COMPLETE(
3881 tid := 0, /* FIXME: it shall match the request tid */
3882 ti_flag := c_TIF_ORIG, /* Sent from the side that originates the TI */
3883 facility := omit
3884 );
3885
3886 /* Compose MSC -> HLR GSUP message */
3887 var template GSUP_PDU gsup_term := ts_GSUP_PROC_SS_REQ(
3888 imsi := g_pars.imsi,
Vadim Yanitskiy2dd96612020-01-07 21:48:29 +01003889 sid := g_pars.gsup_sid,
Vadim Yanitskiy13e4a272018-06-19 18:24:31 +07003890 state := OSMO_GSUP_SESSION_STATE_END
3891 );
3892
3893 /* Finally, HLR terminates the session */
3894 GSUP.send(gsup_term);
3895 /* Expect MT RELEASE COMPLETE without Facility IE */
3896 f_expect_mt_dtap_msg(ussd_term);
3897
3898 /* Hold the call for some time */
3899 f_sleep(1.0);
3900
3901 /* Release the call (does Clear Complete itself) */
3902 f_call_hangup(cpars, true);
3903}
3904testcase TC_lu_and_mt_ussd_during_mt_call() runs on MTC_CT {
3905 var BSC_ConnHdlr vc_conn;
3906 f_init();
3907 vc_conn := f_start_handler(refers(f_tc_lu_and_mt_ussd_during_mt_call), 49);
3908 vc_conn.done;
3909}
3910
Harald Weltee13cfb22019-04-23 16:52:02 +02003911
Vadim Yanitskiy2daf52d2018-06-21 04:19:58 +07003912/* LU followed by MO USSD request and MO Release during transaction */
Harald Weltee13cfb22019-04-23 16:52:02 +02003913friend function f_tc_lu_and_mo_ussd_mo_release(charstring id, BSC_ConnHdlrPars pars)
Vadim Yanitskiy2daf52d2018-06-21 04:19:58 +07003914runs on BSC_ConnHdlr {
3915 f_init_handler(pars);
3916
3917 /* Perform location update */
3918 f_perform_lu();
3919
3920 /* Send CM Service Request for SS/USSD */
3921 f_establish_fully(EST_TYPE_SS_ACT);
3922
3923 /* We need to inspect GSUP activity */
3924 f_create_gsup_expect(hex2str(g_pars.imsi));
3925
3926 var template OCTN facility_ms_req := f_USSD_FACILITY_IE_INVOKE(
3927 invoke_id := 1, /* Initial request */
3928 op_code := SS_OP_CODE_PROCESS_USS_REQ,
3929 ussd_string := "*6766*266#"
3930 );
3931
3932 var template OCTN facility_net_req := f_USSD_FACILITY_IE_INVOKE(
3933 invoke_id := 2, /* Counter request */
3934 op_code := SS_OP_CODE_USS_REQUEST,
3935 ussd_string := "Password?!?"
3936 )
3937
3938 /* Compose MO SS/REGISTER message with request */
3939 var template (value) PDU_ML3_MS_NW ussd_ms_req := ts_ML3_MO_SS_REGISTER(
3940 tid := 1, /* We just need a single transaction */
3941 ti_flag := c_TIF_ORIG, /* Sent from the side that originates the TI */
3942 facility := valueof(facility_ms_req)
3943 );
3944
3945 /* Compose expected MSC -> HLR message */
3946 var template GSUP_PDU gsup_ms_req := tr_GSUP_PROC_SS_REQ(
3947 imsi := g_pars.imsi,
3948 state := OSMO_GSUP_SESSION_STATE_BEGIN,
3949 ss := valueof(facility_ms_req)
3950 );
3951
3952 /* To be used for sending response with correct session ID */
3953 var GSUP_PDU gsup_ms_req_complete;
3954
3955 /* Initiate a new transaction */
3956 BSSAP.send(ts_PDU_DTAP_MO(ussd_ms_req));
3957 /* Expect GSUP request with original Facility IE */
3958 gsup_ms_req_complete := f_expect_gsup_msg(gsup_ms_req);
3959
3960 /* Compose the response from HLR using received session ID */
3961 var template (value) GSUP_PDU gsup_net_req := ts_GSUP_PROC_SS_REQ(
3962 imsi := g_pars.imsi,
3963 sid := gsup_ms_req_complete.ies[1].val.session_id,
3964 state := OSMO_GSUP_SESSION_STATE_CONTINUE,
3965 ss := valueof(facility_net_req)
3966 );
3967
3968 /* Compose expected MT SS/FACILITY template with counter request */
3969 var template PDU_ML3_NW_MS ussd_net_req := tr_ML3_MT_SS_FACILITY(
3970 tid := 1, /* Response should arrive within the same transaction */
3971 ti_flag := c_TIF_REPL, /* Sent to the side that originates the TI */
3972 facility := valueof(facility_net_req)
3973 );
3974
3975 /* Send response over GSUP */
3976 GSUP.send(gsup_net_req);
3977 /* Expect MT SS/FACILITY message with counter request */
3978 f_expect_mt_dtap_msg(ussd_net_req);
3979
3980 /* Compose MO SS/RELEASE COMPLETE */
3981 var template (value) PDU_ML3_MS_NW ussd_abort := ts_ML3_MO_SS_RELEASE_COMPLETE(
3982 tid := 1, /* Response should arrive within the same transaction */
3983 ti_flag := c_TIF_ORIG, /* Sent from the side that originates the TI */
3984 facility := omit
3985 /* TODO: cause? */
3986 );
3987
3988 /* Compose expected HLR -> MSC abort message */
3989 var template GSUP_PDU gsup_abort := tr_GSUP_PROC_SS_REQ(
3990 imsi := g_pars.imsi,
3991 sid := gsup_ms_req_complete.ies[1].val.session_id,
3992 state := OSMO_GSUP_SESSION_STATE_END
3993 );
3994
3995 /* Abort transaction */
3996 BSSAP.send(ts_PDU_DTAP_MO(ussd_abort));
3997 /* Expect GSUP message indicating abort */
3998 f_expect_gsup_msg(gsup_abort);
3999
4000 f_expect_clear();
4001}
4002testcase TC_lu_and_mo_ussd_mo_release() runs on MTC_CT {
4003 var BSC_ConnHdlr vc_conn;
4004 f_init();
4005 vc_conn := f_start_handler(refers(f_tc_lu_and_mo_ussd_mo_release), 50);
4006 vc_conn.done;
4007}
4008
Harald Weltee13cfb22019-04-23 16:52:02 +02004009
Vadim Yanitskiy0e392dd2018-11-29 00:47:54 +07004010/* LU followed by MO USSD request and MT Release due to timeout */
Harald Weltee13cfb22019-04-23 16:52:02 +02004011friend function f_tc_lu_and_ss_session_timeout(charstring id, BSC_ConnHdlrPars pars)
Vadim Yanitskiy0e392dd2018-11-29 00:47:54 +07004012runs on BSC_ConnHdlr {
4013 f_init_handler(pars);
4014
4015 /* Perform location update */
4016 f_perform_lu();
4017
4018 /* Send CM Service Request for SS/USSD */
4019 f_establish_fully(EST_TYPE_SS_ACT);
4020
4021 /* We need to inspect GSUP activity */
4022 f_create_gsup_expect(hex2str(g_pars.imsi));
4023
4024 var template OCTN facility_ms_req := f_USSD_FACILITY_IE_INVOKE(
4025 invoke_id := 1,
4026 op_code := SS_OP_CODE_PROCESS_USS_REQ,
4027 ussd_string := "#release_me");
4028
4029 /* Compose MO SS/REGISTER message with request */
4030 var template (value) PDU_ML3_MS_NW ussd_ms_req := ts_ML3_MO_SS_REGISTER(
4031 tid := 1, /* An arbitrary transaction identifier */
4032 ti_flag := c_TIF_ORIG, /* Sent from the side that originates the TI */
4033 facility := valueof(facility_ms_req));
4034
4035 /* Compose expected MSC -> HLR message */
4036 var template GSUP_PDU gsup_ms_req := tr_GSUP_PROC_SS_REQ(
4037 imsi := g_pars.imsi,
4038 state := OSMO_GSUP_SESSION_STATE_BEGIN,
4039 ss := valueof(facility_ms_req));
4040
4041 /* To be used for sending response with correct session ID */
4042 var GSUP_PDU gsup_ms_req_complete;
4043
4044 /* Initiate a new SS transaction */
4045 BSSAP.send(ts_PDU_DTAP_MO(ussd_ms_req));
4046 /* Expect GSUP request with original Facility IE */
4047 gsup_ms_req_complete := f_expect_gsup_msg(gsup_ms_req);
4048
4049 /* Don't respond, wait for timeout */
4050 f_sleep(3.0);
4051
4052 var template PDU_ML3_NW_MS dtap_rel := tr_ML3_MT_SS_RELEASE_COMPLETE(
4053 tid := 1, /* Should match the request's tid */
4054 ti_flag := c_TIF_REPL, /* Sent to the side that originates the TI */
4055 cause := *, /* TODO: expect some specific value */
4056 facility := omit);
4057
4058 var template GSUP_PDU gsup_rel := tr_GSUP_PROC_SS_ERR(
4059 imsi := g_pars.imsi,
4060 sid := gsup_ms_req_complete.ies[1].val.session_id,
4061 state := OSMO_GSUP_SESSION_STATE_END,
4062 cause := ?); /* TODO: expect some specific value */
4063
4064 /* Expect release on both interfaces */
4065 interleave {
4066 [] BSSAP.receive(tr_PDU_DTAP_MT(dtap_rel)) { };
4067 [] GSUP.receive(gsup_rel) { };
4068 }
4069
4070 f_expect_clear();
4071 setverdict(pass);
4072}
4073testcase TC_lu_and_ss_session_timeout() runs on MTC_CT {
4074 var BSC_ConnHdlr vc_conn;
4075 f_init();
Vadim Yanitskiy36d28dd2018-12-03 02:45:45 +07004076 f_vty_config(MSCVTY, "msc", "ncss guard-timeout 3");
Vadim Yanitskiy0e392dd2018-11-29 00:47:54 +07004077 vc_conn := f_start_handler(refers(f_tc_lu_and_ss_session_timeout), 51);
4078 vc_conn.done;
Vadim Yanitskiy36d28dd2018-12-03 02:45:45 +07004079 f_vty_config(MSCVTY, "msc", "ncss guard-timeout 0");
Vadim Yanitskiy0e392dd2018-11-29 00:47:54 +07004080}
4081
Vadim Yanitskiy0e6c9f52019-06-15 01:01:28 +07004082/* MT (network-originated) USSD for unknown subscriber */
4083friend function f_tc_mt_ussd_for_unknown_subscr(charstring id, BSC_ConnHdlrPars pars)
4084runs on BSC_ConnHdlr {
4085 var hexstring imsi := '000000000000000'H; /* Some unknown IMSI */
4086 var OCT4 sid := '20000222'O;
Vadim Yanitskiy0e6c9f52019-06-15 01:01:28 +07004087
4088 f_init_handler(pars);
4089 f_ran_register_imsi(imsi, 'FFFFFFFF'O);
4090 f_create_gsup_expect(hex2str(imsi));
4091
4092 var template (value) GSUP_PDU gsup_req := ts_GSUP_PROC_SS_REQ(
4093 imsi := imsi,
4094 sid := sid,
4095 state := OSMO_GSUP_SESSION_STATE_BEGIN,
4096 ss := f_rnd_octstring(23)
4097 );
4098
4099 /* Error with cause GMM_CAUSE_IMSI_UNKNOWN */
4100 var template GSUP_PDU gsup_rsp := tr_GSUP_PROC_SS_ERR(
4101 imsi := imsi,
4102 sid := sid,
4103 state := OSMO_GSUP_SESSION_STATE_END,
4104 cause := 2 /* FIXME: introduce an enumerated type! */
4105 );
4106
4107 /* Initiate a MT USSD notification */
4108 GSUP.send(gsup_req);
4109
4110 /* Expect GSUP PROC_SS_ERROR message */
Vadim Yanitskiy851798c2019-06-15 14:22:28 +07004111 f_expect_gsup_msg(gsup_rsp);
Vadim Yanitskiy0e6c9f52019-06-15 01:01:28 +07004112}
4113testcase TC_mt_ussd_for_unknown_subscr() runs on MTC_CT {
4114 var BSC_ConnHdlr vc_conn;
4115 f_init();
4116 vc_conn := f_start_handler(refers(f_tc_mt_ussd_for_unknown_subscr), 0);
4117 vc_conn.done;
4118}
4119
Vadim Yanitskiyc3c07d42019-06-17 23:00:44 +07004120/* MO (mobile-originated) SS/USSD for unknown transaction */
4121friend function f_tc_mo_ussd_for_unknown_trans(charstring id, BSC_ConnHdlrPars pars)
4122runs on BSC_ConnHdlr {
4123 f_init_handler(pars);
4124
Vadim Yanitskiy70d15bf2020-01-09 22:51:01 +01004125 f_ran_register_imsi(g_pars.imsi, g_pars.tmsi);
Vadim Yanitskiyc3c07d42019-06-17 23:00:44 +07004126 f_create_gsup_expect(hex2str(g_pars.imsi));
4127
4128 /* Perform location update */
4129 f_perform_lu();
4130
4131 /* Send CM Service Request for SS/USSD */
4132 f_establish_fully(EST_TYPE_SS_ACT);
4133
4134 /* GSM 04.80 FACILITY message for a non-existing transaction */
4135 var template (value) PDU_ML3_MS_NW mo_ss_fac := ts_ML3_MO_SS_FACILITY(
4136 tid := 1, /* An arbitrary transaction identifier */
4137 ti_flag := c_TIF_ORIG, /* Sent from the side that originates the TI */
4138 facility := f_rnd_octstring(23) /* We don't care about the Facility IE */
4139 );
4140
4141 /* GSM 04.80 RELEASE COMPLETE message for a non-existing transaction */
4142 var template (value) PDU_ML3_MS_NW mo_ss_rel := ts_ML3_MO_SS_RELEASE_COMPLETE(
4143 tid := 1, /* An arbitrary transaction identifier */
4144 ti_flag := c_TIF_ORIG, /* Sent from the side that originates the TI */
4145 facility := f_rnd_octstring(23) /* We don't care about the Facility IE */
4146 );
4147
4148 /* Expected response from the network */
4149 var template PDU_ML3_NW_MS mt_ss_rel := tr_ML3_MT_SS_RELEASE_COMPLETE(
4150 tid := 1, /* Same as in the FACILITY message */
4151 ti_flag := c_TIF_REPL, /* Sent to the side that originates the TI */
4152 facility := omit
4153 );
4154
4155 /* Send GSM 04.80 FACILITY for non-existing transaction */
4156 BSSAP.send(ts_PDU_DTAP_MO(mo_ss_fac));
4157
4158 /* Expect GSM 04.80 RELEASE COMPLETE message */
4159 f_expect_mt_dtap_msg(mt_ss_rel);
4160 f_expect_clear();
4161
4162 /* Send another CM Service Request for SS/USSD */
4163 f_establish_fully(EST_TYPE_SS_ACT);
4164
4165 /* Send GSM 04.80 RELEASE COMPLETE for non-existing transaction */
4166 BSSAP.send(ts_PDU_DTAP_MO(mo_ss_rel));
4167
4168 /* Expect GSM 04.80 RELEASE COMPLETE message */
4169 f_expect_mt_dtap_msg(mt_ss_rel);
4170 f_expect_clear();
4171}
4172testcase TC_mo_ussd_for_unknown_trans() runs on MTC_CT {
4173 var BSC_ConnHdlr vc_conn;
4174 f_init();
4175 vc_conn := f_start_handler(refers(f_tc_mo_ussd_for_unknown_trans), 111);
4176 vc_conn.done;
4177}
4178
Vadim Yanitskiyd612d282019-06-15 14:46:03 +07004179/* MT (network-originated) USSD for unknown session */
4180friend function f_tc_proc_ss_for_unknown_session(charstring id, BSC_ConnHdlrPars pars)
4181runs on BSC_ConnHdlr {
4182 var OCT4 sid := '20000333'O;
4183
4184 f_init_handler(pars);
4185
4186 /* Perform location update */
4187 f_perform_lu();
4188
Vadim Yanitskiy70d15bf2020-01-09 22:51:01 +01004189 f_ran_register_imsi(g_pars.imsi, g_pars.tmsi);
Vadim Yanitskiyd612d282019-06-15 14:46:03 +07004190 f_create_gsup_expect(hex2str(g_pars.imsi));
4191
4192 /* Request referencing a non-existing SS session */
4193 var template (value) GSUP_PDU gsup_req := ts_GSUP_PROC_SS_REQ(
4194 imsi := g_pars.imsi,
4195 sid := sid,
4196 state := OSMO_GSUP_SESSION_STATE_CONTINUE,
4197 ss := f_rnd_octstring(23)
4198 );
4199
4200 /* Error with some cause value */
4201 var template GSUP_PDU gsup_rsp := tr_GSUP_PROC_SS_ERR(
4202 imsi := g_pars.imsi,
4203 sid := sid,
4204 state := OSMO_GSUP_SESSION_STATE_END,
4205 cause := ? /* FIXME: introduce an enumerated type! */
4206 );
4207
4208 /* Initiate a MT USSD notification */
4209 GSUP.send(gsup_req);
4210
4211 /* Expect GSUP PROC_SS_ERROR message */
4212 f_expect_gsup_msg(gsup_rsp);
4213}
4214testcase TC_proc_ss_for_unknown_session() runs on MTC_CT {
4215 var BSC_ConnHdlr vc_conn;
4216 f_init();
4217 vc_conn := f_start_handler(refers(f_tc_proc_ss_for_unknown_session), 110);
4218 vc_conn.done;
4219}
4220
Vadim Yanitskiye5f4ed92019-06-16 02:36:33 +07004221/* MT (network-originated) USSD and no response to Paging Request */
4222friend function f_tc_proc_ss_paging_fail(charstring id, BSC_ConnHdlrPars pars)
4223runs on BSC_ConnHdlr {
4224 timer TP := 2.0; /* Paging timer */
4225
4226 f_init_handler(pars);
4227
4228 /* Perform location update */
4229 f_perform_lu();
4230
Vadim Yanitskiy70d15bf2020-01-09 22:51:01 +01004231 f_ran_register_imsi(g_pars.imsi, g_pars.tmsi);
Vadim Yanitskiye5f4ed92019-06-16 02:36:33 +07004232 f_create_gsup_expect(hex2str(g_pars.imsi));
4233
4234 var template (value) GSUP_PDU gsup_req := ts_GSUP_PROC_SS_REQ(
4235 imsi := g_pars.imsi,
4236 sid := '20000444'O,
4237 state := OSMO_GSUP_SESSION_STATE_BEGIN,
4238 ss := f_rnd_octstring(23)
4239 );
4240
4241 /* Error with some cause value */
4242 var template GSUP_PDU gsup_rsp := tr_GSUP_PROC_SS_ERR(
4243 imsi := g_pars.imsi,
4244 sid := '20000444'O,
4245 state := OSMO_GSUP_SESSION_STATE_END,
4246 cause := ? /* FIXME: introduce an enumerated type! */
4247 );
4248
4249 /* Initiate a MT USSD notification */
4250 GSUP.send(gsup_req);
4251
4252 /* Send it to MSC and expect Paging Request */
4253 TP.start;
4254 alt {
Vadim Yanitskiy53f2be62024-04-14 19:48:39 +07004255 [] as_paging() { setverdict(pass); }
4256 [] as_paging_any() {
4257 setverdict(fail, "Rx unexpected BSSMAP/RANAP Paging");
4258 mtc.stop;
Vadim Yanitskiye5f4ed92019-06-16 02:36:33 +07004259 }
Vadim Yanitskiye5f4ed92019-06-16 02:36:33 +07004260 [] as_unexp_gsup_or_bssap_msg();
4261 [] TP.timeout {
4262 setverdict(fail, "Timeout waiting for Paging Request");
4263 }
4264 }
4265
Vadim Yanitskiyd24b5252019-10-02 00:04:51 +07004266 /* Wait up to 20 seconds for GSUP PROC_SS_ERROR message.
4267 * OsmoMSC waits for Paging Response 10 seconds by default. */
4268 f_expect_gsup_msg(gsup_rsp, T_val := 20.0);
Vadim Yanitskiye5f4ed92019-06-16 02:36:33 +07004269}
4270testcase TC_proc_ss_paging_fail() runs on MTC_CT {
4271 var BSC_ConnHdlr vc_conn;
4272 f_init();
4273 vc_conn := f_start_handler(refers(f_tc_proc_ss_paging_fail), 101);
4274 vc_conn.done;
4275}
4276
Vadim Yanitskiy29ba8d62019-06-16 15:19:41 +07004277/* MT (network-originated) USSD followed by immediate abort */
4278friend function f_tc_proc_ss_abort(charstring id, BSC_ConnHdlrPars pars)
4279runs on BSC_ConnHdlr {
4280 var octetstring facility := f_rnd_octstring(23);
4281 var OCT4 sid := '20000555'O;
4282 timer TP := 2.0;
4283
4284 f_init_handler(pars);
4285
4286 /* Perform location update */
4287 f_perform_lu();
4288
Vadim Yanitskiy70d15bf2020-01-09 22:51:01 +01004289 f_ran_register_imsi(g_pars.imsi, g_pars.tmsi);
Vadim Yanitskiy29ba8d62019-06-16 15:19:41 +07004290 f_create_gsup_expect(hex2str(g_pars.imsi));
4291
4292 /* PROC_SS_REQ initiates a mobile-originated SS/USSD session */
4293 var template (value) GSUP_PDU gsup_req := ts_GSUP_PROC_SS_REQ(
4294 imsi := g_pars.imsi, sid := sid,
4295 state := OSMO_GSUP_SESSION_STATE_BEGIN,
4296 ss := facility
4297 );
4298
4299 /* On the MS side, we expect GSM 04.80 REGISTER message */
4300 var template PDU_ML3_NW_MS dtap_reg := tr_ML3_MT_SS_REGISTER(
4301 tid := 0, /* Most likely, it should be 0 */
4302 ti_flag := c_TIF_ORIG, /* Sent from the side that originates the TI */
4303 facility := facility
4304 );
4305
4306 /* PROC_SS_ERR with SESSION_STATE_END terminates the SS/USSD session */
4307 var template (value) GSUP_PDU gsup_abort := ts_GSUP_PROC_SS_ERR(
4308 imsi := g_pars.imsi, sid := sid,
4309 state := OSMO_GSUP_SESSION_STATE_END,
4310 cause := 0 /* FIXME: introduce an enumerated type! */
4311 );
4312
4313 /* On the MS side, we expect GSM 04.80 REGISTER message */
4314 var template PDU_ML3_NW_MS dtap_rel := tr_ML3_MT_SS_RELEASE_COMPLETE(
4315 tid := 0, /* Most likely, it should be 0 */
4316 ti_flag := c_TIF_ORIG, /* Sent from the side that originates the TI */
4317 cause := *, /* FIXME: expect some specific cause value */
4318 facility := omit
4319 );
4320
4321 /* Initiate a MT USSD with random payload */
4322 GSUP.send(gsup_req);
4323
4324 /* Expect Paging Request */
4325 TP.start;
4326 alt {
Vadim Yanitskiy53f2be62024-04-14 19:48:39 +07004327 [] as_paging() { setverdict(pass); }
4328 [] as_paging_any() {
4329 setverdict(fail, "Rx unexpected BSSMAP/RANAP Paging");
4330 mtc.stop;
Vadim Yanitskiy29ba8d62019-06-16 15:19:41 +07004331 }
Vadim Yanitskiy29ba8d62019-06-16 15:19:41 +07004332 [] as_unexp_gsup_or_bssap_msg();
4333 [] TP.timeout {
4334 setverdict(fail, "Timeout waiting for Paging Request");
4335 }
4336 }
4337
4338 /* Send Paging Response and establish connection */
4339 f_establish_fully(EST_TYPE_PAG_RESP);
4340 /* Expect MT REGISTER message with random facility */
4341 f_expect_mt_dtap_msg(dtap_reg);
4342
4343 /* HLR/EUSE decides to abort the session even
4344 * before getting any response from the MS */
4345 /* Initiate a MT USSD with random payload */
4346 GSUP.send(gsup_abort);
4347
4348 /* Expect RELEASE COMPLETE on ths MS side */
4349 f_expect_mt_dtap_msg(dtap_rel);
4350
4351 f_expect_clear();
4352}
4353testcase TC_proc_ss_abort() runs on MTC_CT {
4354 var BSC_ConnHdlr vc_conn;
4355 f_init();
4356 vc_conn := f_start_handler(refers(f_tc_proc_ss_abort), 102);
4357 vc_conn.done;
4358}
4359
Harald Weltee13cfb22019-04-23 16:52:02 +02004360
Vadim Yanitskiy1c9754d2020-01-07 21:56:55 +01004361/* Verify multiple concurrent MO SS/USSD transactions
4362 * (one subscriber - one transaction) */
4363testcase TC_multi_lu_and_mo_ussd() runs on MTC_CT {
4364 var BSC_ConnHdlr vc_conn[16];
4365 var integer i;
4366
4367 f_init();
4368
4369 for (i := 0; i < sizeof(vc_conn); i := i + 1) {
4370 vc_conn[i] := f_start_handler(refers(f_tc_lu_and_mo_ussd_single_request), 210 + i);
4371 }
4372
4373 for (i := 0; i < sizeof(vc_conn); i := i + 1) {
4374 vc_conn[i].done;
4375 }
4376}
4377
4378/* Verify multiple concurrent MT SS/USSD transactions
4379 * (one subscriber - one transaction) */
4380testcase TC_multi_lu_and_mt_ussd() runs on MTC_CT {
4381 var BSC_ConnHdlr vc_conn[16];
4382 var integer i;
4383 var OCT4 sid;
4384
4385 f_init();
4386
4387 for (i := 0; i < sizeof(vc_conn); i := i + 1) {
4388 sid := '200001'O & int2oct(i, 1); /* All transactions must use different session ID */
4389 vc_conn[i] := f_start_handler_with_pars(refers(f_tc_lu_and_mt_ussd_notification),
4390 f_init_pars(226 + i, gsup_sid := sid));
4391 }
4392
4393 for (i := 0; i < sizeof(vc_conn); i := i + 1) {
4394 vc_conn[i].done;
4395 }
4396}
4397
4398
Stefan Sperling89eb1f32018-12-17 15:06:20 +01004399/* A5/1 only permitted on network side; attempt an invalid CIPHER MODE COMPLETE with A5/3 which MSC should reject. */
4400private function f_tc_cipher_complete_with_invalid_cipher(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
4401 pars.net.expect_auth := true;
4402 pars.net.expect_ciph := true;
4403 pars.net.kc_support := '02'O; /* A5/1 only */
4404 f_init_handler(pars);
4405
4406 g_pars.vec := f_gen_auth_vec_2g();
4407
4408 /* Can't use f_perform_lu() directly. Code below is based on it. */
4409
4410 /* tell GSUP dispatcher to send this IMSI to us */
4411 f_create_gsup_expect(hex2str(g_pars.imsi));
4412
4413 /* Send BSSAP_Conn_Req with COMPL L3 INFO to MSC */
4414 var PDU_ML3_MS_NW l3_lu := f_build_lu_imsi(g_pars.imsi)
Harald Weltedceacc72019-04-21 20:58:35 +02004415 f_cl3_or_initial_ue(l3_lu);
Stefan Sperling89eb1f32018-12-17 15:06:20 +01004416
4417 f_mm_auth();
4418
4419 var OCT1 a5_net := f_alg_mask_from_cm(g_pars.cm2);
4420 var OCT1 a5_intersect := g_pars.net.kc_support and4b a5_net;
4421 alt {
4422 [] BSSAP.receive(tr_BSSMAP_CipherModeCmd(a5_intersect, g_pars.vec.kc)) {
4423 BSSAP.send(ts_BSSMAP_CipherModeCompl(int2oct(4 /* "accept" A5/3 */, 1)));
4424 }
4425 [] BSSAP.receive(tr_BSSMAP_CipherModeCmd(?, g_pars.vec.kc)) {
4426 setverdict(fail, "Wrong ciphering algorithm mask in CiphModCmd");
4427 mtc.stop;
4428 }
4429 [] BSSAP.receive {
4430 setverdict(fail, "Unknown/unexpected BSSAP received");
4431 mtc.stop;
4432 }
4433 }
Harald Welte79f1e452020-08-18 22:55:02 +02004434 f_expect_common_id();
Stefan Sperling89eb1f32018-12-17 15:06:20 +01004435
4436 /* Expect LU reject from MSC. */
4437 alt {
4438 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Rej)) {
4439 setverdict(pass);
4440 }
4441 [] BSSAP.receive {
4442 setverdict(fail, "Unknown/unexpected BSSAP received");
4443 mtc.stop;
4444 }
4445 }
Stefan Sperlingc620b352018-12-18 17:23:36 +01004446 f_expect_clear();
Stefan Sperling89eb1f32018-12-17 15:06:20 +01004447}
4448
4449testcase TC_cipher_complete_with_invalid_cipher() runs on MTC_CT {
4450 var BSC_ConnHdlr vc_conn;
4451 f_init();
4452 f_vty_config(MSCVTY, "network", "encryption a5 1");
4453
Neels Hofmeyr4e18ccc2020-06-24 19:08:17 +02004454 vc_conn := f_start_handler(refers(f_tc_cipher_complete_with_invalid_cipher), 52, verify_cell_id := false);
Stefan Sperling89eb1f32018-12-17 15:06:20 +01004455 vc_conn.done;
4456}
4457
Harald Welteb2284bd2019-05-10 11:30:43 +02004458/* Location Update with invalid (non-matching) MCC/MNC reported on BSSMAP level from BSC */
4459friend function f_tc_lu_with_invalid_mcc_mnc(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
4460 f_init_handler(pars);
4461
4462 /* tell GSUP dispatcher to send this IMSI to us */
4463 f_create_gsup_expect(hex2str(g_pars.imsi));
4464
4465 /* modify the cell ID which will be used to construct the COMPLELTE L3 or InitialUE */
4466 g_pars.cell_id := valueof(ts_CellId_CGI('333'H, '22'H, 23, 42));
4467
4468 /* Send BSSAP_Conn_Req with COMPL L3 INFO to MSC */
4469 var PDU_ML3_MS_NW l3_lu := f_build_lu_imsi(g_pars.imsi)
4470 f_cl3_or_initial_ue(l3_lu);
Harald Welte79f1e452020-08-18 22:55:02 +02004471 f_expect_common_id();
Harald Welteb2284bd2019-05-10 11:30:43 +02004472
4473 /* Expect LU reject from MSC. */
4474 alt {
4475 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Rej)) {
4476 setverdict(pass);
4477 }
4478 [] BSSAP.receive {
4479 setverdict(fail, "Unknown/unexpected BSSAP received");
4480 mtc.stop;
4481 }
4482 }
Eric Wild85cc1612022-03-30 01:44:29 +02004483 f_expect_clear(verify_vlr_cell_id:=false);
Harald Welteb2284bd2019-05-10 11:30:43 +02004484}
4485testcase TC_lu_with_invalid_mcc_mnc() runs on MTC_CT {
4486 var BSC_ConnHdlr vc_conn;
4487 f_init();
4488 vc_conn := f_start_handler(refers(f_tc_lu_with_invalid_mcc_mnc), 54);
4489 vc_conn.done;
4490}
4491
Stefan Sperlinga2d59c62018-12-18 16:32:44 +01004492private function f_tc_cipher_complete_without_alg(charstring id, BSC_ConnHdlrPars pars, octetstring kc_support) runs on BSC_ConnHdlr {
4493 pars.net.expect_auth := true;
4494 pars.net.expect_ciph := true;
4495 pars.net.kc_support := kc_support;
4496 f_init_handler(pars);
4497
4498 g_pars.vec := f_gen_auth_vec_2g();
4499
4500 /* Can't use f_perform_lu() directly. Code below is based on it. */
4501
4502 /* tell GSUP dispatcher to send this IMSI to us */
4503 f_create_gsup_expect(hex2str(g_pars.imsi));
4504
4505 /* Send BSSAP_Conn_Req with COMPL L3 INFO to MSC */
4506 var PDU_ML3_MS_NW l3_lu := f_build_lu_imsi(g_pars.imsi)
4507 f_cl3_or_initial_ue(l3_lu);
4508
4509 f_mm_auth();
4510
4511 var OCT1 a5_net := f_alg_mask_from_cm(g_pars.cm2);
4512 var OCT1 a5_intersect := g_pars.net.kc_support and4b a5_net;
4513 alt {
4514 [] BSSAP.receive(tr_BSSMAP_CipherModeCmd(a5_intersect, g_pars.vec.kc)) {
4515 BSSAP.send(ts_BSSMAP_CipherModeComplAlg(omit));
4516 }
4517 [] BSSAP.receive(tr_BSSMAP_ClassmarkReq) {
4518 BSSAP.send(ts_BSSMAP_ClassmarkUpd(g_pars.cm2, g_pars.cm3));
4519 repeat;
4520 }
4521 [] BSSAP.receive(tr_BSSMAP_CipherModeCmd(?, g_pars.vec.kc)) {
4522 setverdict(fail, "Wrong ciphering algorithm mask in CiphModCmd");
4523 mtc.stop;
4524 }
4525 [] BSSAP.receive {
4526 setverdict(fail, "Unknown/unexpected BSSAP received");
4527 mtc.stop;
4528 }
4529 }
Harald Welte79f1e452020-08-18 22:55:02 +02004530 f_expect_common_id();
Stefan Sperlinga2d59c62018-12-18 16:32:44 +01004531
4532 /* TODO: Verify MSC is using the best cipher available! How? */
4533
4534 f_msc_lu_hlr();
Neels Hofmeyre860fc42022-10-05 01:15:54 +02004535 as_accept_reject_lu();
Stefan Sperlinga2d59c62018-12-18 16:32:44 +01004536 f_expect_clear();
4537 setverdict(pass);
4538}
4539
4540/* A5/1 only permitted on network side; attempt CIPHER MODE COMPLETE without specifying the accepted algorithm. */
4541private function f_tc_cipher_complete_1_without_cipher(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
4542 f_tc_cipher_complete_without_alg(id, pars, '02'O /* A5/1 only */);
4543}
4544
4545/* A5/3 only permitted on network side; attempt CIPHER MODE COMPLETE without specifying the accepted algorithm. */
4546private function f_tc_cipher_complete_3_without_cipher(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
4547 f_tc_cipher_complete_without_alg(id, pars, '08'O /* A5/3 only */);
4548}
4549
4550/* A5/1 + A5/3 permitted on network side; attempt CIPHER MODE COMPLETE without specifying the accepted algorithm. */
4551private function f_tc_cipher_complete_13_without_cipher(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
4552 f_tc_cipher_complete_without_alg(id, pars, '0A'O /* A5/1 and A5/3 enabled */);
4553}
4554
4555testcase TC_cipher_complete_1_without_cipher() runs on MTC_CT {
4556 var BSC_ConnHdlr vc_conn;
4557 f_init();
4558 f_vty_config(MSCVTY, "network", "encryption a5 1");
4559
4560 vc_conn := f_start_handler(refers(f_tc_cipher_complete_1_without_cipher), 53);
4561 vc_conn.done;
4562}
4563
4564testcase TC_cipher_complete_3_without_cipher() runs on MTC_CT {
4565 var BSC_ConnHdlr vc_conn;
4566 f_init();
4567 f_vty_config(MSCVTY, "network", "encryption a5 3");
4568
4569 vc_conn := f_start_handler(refers(f_tc_cipher_complete_3_without_cipher), 54);
4570 vc_conn.done;
4571}
4572
4573testcase TC_cipher_complete_13_without_cipher() runs on MTC_CT {
4574 var BSC_ConnHdlr vc_conn;
4575 f_init();
4576 f_vty_config(MSCVTY, "network", "encryption a5 1 3");
4577
4578 vc_conn := f_start_handler(refers(f_tc_cipher_complete_13_without_cipher), 55);
4579 vc_conn.done;
4580}
Harald Welteb2284bd2019-05-10 11:30:43 +02004581
Harald Weltef640a012018-04-14 17:49:21 +02004582/* TODO (SMS):
4583 * different user data lengths
4584 * SMPP transaction mode with unsuccessful delivery
4585 * queued MT-SMS with no paging response + later delivery
4586 * different data coding schemes
4587 * multi-part SMS
4588 * user-data headers
4589 * TP-PID for SMS to SIM
4590 * behavior if SMS memory is full + RP-SMMA
4591 * delivery reports
4592 * SMPP osmocom extensions
4593 * more-messages-to-send
4594 * SMS during ongoing call (SACCH/SAPI3)
4595 */
4596
4597/* TODO (General):
Harald Welteba7b6d92018-01-23 21:32:34 +01004598 * continue to send repeated MO signalling messages to keep channel open: does MSC tmeout?
4599 * malformed messages (missing IE, invalid message type): properly rejected?
4600 * MT call while LU or is ongoing: Do we use existing lchan or page while lchan active?
4601 * 3G/2G auth permutations
4602 * encryption algorithms vs. classmark vs. vty config
Harald Welteba7b6d92018-01-23 21:32:34 +01004603 * send new transaction after/during clear (like SMS, ...)
Harald Welte45164da2018-01-24 12:51:27 +01004604 * too long L3 INFO in DTAP
4605 * too long / padded BSSAP
4606 * too long / short TLV values
Harald Welteba7b6d92018-01-23 21:32:34 +01004607 */
Harald Weltef6dd64d2017-11-19 12:09:51 +01004608
Harald Weltee13cfb22019-04-23 16:52:02 +02004609/***********************************************************************
4610 * SGsAP Testing
4611 ***********************************************************************/
4612
Philipp Maier948747b2019-04-02 15:22:33 +02004613/* Check if a subscriber exists in the VLR */
4614private function f_ctrl_subscr_in_vlr(charstring imsi_or_msisdn) runs on BSC_ConnHdlr return boolean {
4615
4616 var CtrlValue active_subsribers;
4617 var integer rc;
4618 active_subsribers := f_ctrl_get(IPA_CTRL, "subscriber-list-active-v1");
4619
4620 rc := f_strstr(active_subsribers, imsi_or_msisdn);
4621 if (rc < 0) {
4622 return false;
4623 }
4624
4625 return true;
4626}
4627
Pau Espin Pedrolcefe9da2021-07-02 18:38:27 +02004628/* Perform a Location Update at the A-Interface and run some checks to confirm
Harald Welte4263c522018-12-06 11:56:27 +01004629 * that everything is back to normal. */
4630private function f_sgsap_bssmap_screening() runs on BSC_ConnHdlr {
4631 var SmsParameters spars := valueof(t_SmsPars);
4632
Pau Espin Pedrol7593a8a2021-07-02 18:55:16 +02004633 /* From now on, since we initiated LU from A-Interface, we expect no
4634 * LastEutranPLMNId on Common Id, since the SGs interface should be gone
4635 */
4636 g_pars.common_id_last_eutran_plmn := omit;
4637
Harald Welte4263c522018-12-06 11:56:27 +01004638 /* Perform a location update, the SGs association is expected to fall
4639 * back to NULL */
4640 f_perform_lu();
4641 f_ctrl_get_exp(IPA_CTRL, "fsm.SGs-UE.id.imsi:" & hex2str(g_pars.imsi) & ".state", "SGs-NULL");
4642
4643 /* Trigger a paging request and expect the paging on BSSMAP, this is
4644 * to make sure that pagings are sent throught the A-Interface again
4645 * and not throught the SGs interface.*/
Harald Welte6811d102019-04-14 22:23:14 +02004646 f_ran_register_imsi(g_pars.imsi, g_pars.tmsi);
Harald Welte4263c522018-12-06 11:56:27 +01004647 f_vty_transceive(MSCVTY, "subscriber imsi " & hex2str(g_pars.imsi) & " paging");
4648
4649 alt {
Vadim Yanitskiy53f2be62024-04-14 19:48:39 +07004650 [] as_paging() { setverdict(pass); }
4651 [] as_paging_any() {
4652 setverdict(fail, "Rx unexpected BSSMAP/RANAP Paging");
4653 mtc.stop;
Harald Welte4263c522018-12-06 11:56:27 +01004654 }
4655 [] SGsAP.receive {
4656 setverdict(fail, "Received unexpected message on SGs");
4657 }
4658 }
4659
4660 /* Send an SMS to make sure that also payload messages are routed
4661 * throught the A-Interface again */
4662 f_establish_fully(EST_TYPE_MO_SMS);
4663 f_mo_sms(spars);
4664 f_expect_clear();
4665}
4666
4667private function f_tc_sgsap_reset(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
4668 var charstring vlr_name;
4669 f_init_handler(pars);
4670
4671 vlr_name := f_sgsap_reset_mme(mp_mme_name);
4672 log("VLR name: ", vlr_name);
4673 setverdict(pass);
Neels Hofmeyrc0b520d2019-03-06 15:35:50 +01004674 f_sleep(1.0);
Harald Welte4263c522018-12-06 11:56:27 +01004675}
4676
4677testcase TC_sgsap_reset() runs on MTC_CT {
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004678 var BSC_ConnHdlrPars pars;
Harald Welte4263c522018-12-06 11:56:27 +01004679 var BSC_ConnHdlr vc_conn;
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004680 f_init(1, true);
4681 pars := f_init_pars(11810, true);
4682 vc_conn := f_start_handler_with_pars(refers(f_tc_sgsap_reset), pars);
Harald Welte4263c522018-12-06 11:56:27 +01004683 vc_conn.done;
4684}
4685
4686/* like f_mm_auth() but for SGs */
4687function f_mm_auth_sgs() runs on BSC_ConnHdlr {
4688 if (g_pars.net.expect_auth) {
4689 g_pars.vec := f_gen_auth_vec_3g();
4690 var GSUP_IE auth_tuple := valueof(ts_GSUP_IE_AuthTuple2G3G(g_pars.vec.rand,
4691 g_pars.vec.sres,
4692 g_pars.vec.kc,
4693 g_pars.vec.ik,
4694 g_pars.vec.ck,
4695 g_pars.vec.autn,
4696 g_pars.vec.res));
4697 GSUP.receive(tr_GSUP_SAI_REQ(g_pars.imsi));
4698 GSUP.send(ts_GSUP_SAI_RES(g_pars.imsi, auth_tuple));
4699 SGsAP.receive(tr_ML3_MT_MM_AUTH_REQ_3G(g_pars.vec.rand, g_pars.vec.autn));
4700 SGsAP.send(ts_ML3_MT_MM_AUTH_RESP_3G(g_pars.vec.sres, g_pars.vec.res));
4701 }
4702}
4703
4704/* like f_perform_lu(), but on SGs rather than BSSAP */
4705function f_sgs_perform_lu() runs on BSC_ConnHdlr {
4706 var octetstring mme_name := f_enc_dns_hostname(mp_mme_name);
4707 var PDU_SGsAP lur;
4708 var PDU_SGsAP lua;
4709 var PDU_SGsAP mm_info;
4710 var octetstring mm_info_dtap;
Pau Espin Pedrole979c402021-04-28 17:29:54 +02004711 var GsmMcc mcc;
4712 var GsmMnc mnc;
4713 var template (omit) TrackingAreaIdentityValue tai := omit;
Harald Welte4263c522018-12-06 11:56:27 +01004714
4715 /* tell GSUP dispatcher to send this IMSI to us */
4716 f_create_gsup_expect(hex2str(g_pars.imsi));
Pau Espin Pedrole979c402021-04-28 17:29:54 +02004717 if (g_pars.common_id_last_eutran_plmn != omit) {
4718 f_dec_mcc_mnc(g_pars.common_id_last_eutran_plmn, mcc, mnc);
4719 tai := ts_SGsAP_TAI(mcc, mnc, 555);
4720 }
Harald Welte4263c522018-12-06 11:56:27 +01004721 lur := valueof(ts_SGsAP_LU_REQ(g_pars.imsi, mme_name, IMSI_attach,
Pau Espin Pedrol3768a6f2021-04-28 14:24:23 +02004722 ts_SGsAP_LAI('901'H, '70'H, 2342),
Pau Espin Pedrole979c402021-04-28 17:29:54 +02004723 tai));
Harald Welte4263c522018-12-06 11:56:27 +01004724 /* Old LAI, if MS sends it */
4725 /* TMSI status, if MS has no valid TMSI */
4726 /* IMEISV, if it supports "automatic device detection" */
4727 /* TAI, if available in MME */
4728 /* E-CGI, if available in MME */
4729 SGsAP.send(lur);
4730
4731 /* FIXME: is this really done over SGs? The Ue is already authenticated
4732 * via the MME ... */
4733 f_mm_auth_sgs();
4734
4735 /* Expect MSC to perform LU with HLR */
4736 GSUP.receive(tr_GSUP_UL_REQ(g_pars.imsi));
4737 GSUP.send(ts_GSUP_ISD_REQ(g_pars.imsi, g_pars.msisdn));
4738 GSUP.receive(tr_GSUP_ISD_RES(g_pars.imsi));
4739 GSUP.send(ts_GSUP_UL_RES(g_pars.imsi));
4740
4741 alt {
4742 [] SGsAP.receive(tr_SGsAP_LU_ACCEPT(g_pars.imsi, ?)) -> value lua {
4743 if (isvalue(lua.sGsAP_LOCATION_UPDATE_ACCEPT.newTMSIorIMSI.iD.iD.tmsi_ptmsi.octets)) {
4744 g_pars.tmsi :=lua.sGsAP_LOCATION_UPDATE_ACCEPT.newTMSIorIMSI.iD.iD.tmsi_ptmsi.octets
4745 SGsAP.send(ts_SGsAP_TMSI_REALL_CMPL(g_pars.imsi));
4746 }
4747 setverdict(pass);
4748 }
4749 [] SGsAP.receive(tr_SGsAP_LU_REJECT(g_pars.imsi, ?, ?)) {
4750 setverdict(fail, "Received LU-REJECT instead of ACCEPT");
4751 }
4752 [] SGsAP.receive {
4753 setverdict(fail, "Received unexpected message on SGs");
4754 }
4755 }
4756
4757 /* Check MM information */
4758 if (mp_mm_info == true) {
4759 SGsAP.receive(tr_SGsAP_MM_INFO_REQ(g_pars.imsi, ?)) -> value mm_info;
4760 mm_info_dtap := '0532'O & mm_info.sGsAP_MM_INFORMATION_REQUEST.mM_Information.information;
4761 if (not match(dec_PDU_ML3_NW_MS(mm_info_dtap), tr_ML3_MT_MM_Info)) {
4762 setverdict(fail, "Unexpected MM Information");
4763 }
4764 }
4765
4766 f_ctrl_get_exp(IPA_CTRL, "fsm.SGs-UE.id.imsi:" & hex2str(g_pars.imsi) & ".state", "SGs-ASSOCIATED");
4767}
4768
4769private function f_tc_sgsap_lu(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
4770 f_init_handler(pars);
4771 f_sgs_perform_lu();
4772 f_ctrl_get_exp(IPA_CTRL, "fsm.SGs-UE.id.imsi:" & hex2str(g_pars.imsi) & ".state", "SGs-ASSOCIATED");
4773
4774 f_sgsap_bssmap_screening();
4775
4776 setverdict(pass);
4777}
4778testcase TC_sgsap_lu() runs on MTC_CT {
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004779 var BSC_ConnHdlrPars pars;
Harald Welte4263c522018-12-06 11:56:27 +01004780 var BSC_ConnHdlr vc_conn;
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004781 f_init(1, true);
4782 pars := f_init_pars(11811, true);
Pau Espin Pedrole979c402021-04-28 17:29:54 +02004783 pars.common_id_last_eutran_plmn := f_enc_mcc_mnc('901'H, '70'H);
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004784 vc_conn := f_start_handler_with_pars(refers(f_tc_sgsap_lu), pars);
Harald Welte4263c522018-12-06 11:56:27 +01004785 vc_conn.done;
4786}
4787
4788/* Do LU by IMSI, refuse it on GSUP and expect LU REJ back to MS */
4789private function f_tc_sgsap_lu_imsi_reject(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
4790 f_init_handler(pars);
4791 var PDU_SGsAP lur;
4792
4793 f_create_gsup_expect(hex2str(g_pars.imsi));
4794 var octetstring mme_name := f_enc_dns_hostname(mp_mme_name);
4795 lur := valueof(ts_SGsAP_LU_REQ(g_pars.imsi, mme_name, IMSI_attach,
4796 ts_SGsAP_LAI('901'H, '70'H, 2342)));
4797 SGsAP.send(lur);
4798
4799 GSUP.receive(tr_GSUP_UL_REQ(g_pars.imsi));
4800 GSUP.send(ts_GSUP_UL_ERR(g_pars.imsi, 23));
4801 alt {
4802 [] SGsAP.receive(tr_SGsAP_LU_REJECT(g_pars.imsi, ?, ?)) {
4803 setverdict(pass);
4804 }
4805 [] SGsAP.receive(tr_SGsAP_LU_ACCEPT(g_pars.imsi, ?)) {
4806 setverdict(fail, "Expecting LU REJ, but got ACCEPT");
4807 mtc.stop;
4808 }
4809 [] SGsAP.receive {
4810 setverdict(fail, "Received unexpected message on SGs");
4811 }
4812 }
4813
4814 f_sgsap_bssmap_screening();
4815
4816 setverdict(pass);
4817}
4818testcase TC_sgsap_lu_imsi_reject() runs on MTC_CT {
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004819 var BSC_ConnHdlrPars pars;
Harald Welte4263c522018-12-06 11:56:27 +01004820 var BSC_ConnHdlr vc_conn;
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004821 f_init(1, true);
4822 pars := f_init_pars(11812, true);
Harald Welte4263c522018-12-06 11:56:27 +01004823
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004824 vc_conn := f_start_handler_with_pars(refers(f_tc_sgsap_lu_imsi_reject), pars);
Harald Welte4263c522018-12-06 11:56:27 +01004825 vc_conn.done;
4826}
4827
4828/* Do LU by IMSI, but then remain silent so that Ts6-1 times out */
4829private function f_tc_sgsap_lu_and_nothing(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
4830 var octetstring mme_name := f_enc_dns_hostname(mp_mme_name);
4831 var PDU_SGsAP lur;
4832
4833 f_init_handler(pars);
4834
4835 /* tell GSUP dispatcher to send this IMSI to us */
4836 f_create_gsup_expect(hex2str(g_pars.imsi));
4837
4838 lur := valueof(ts_SGsAP_LU_REQ(g_pars.imsi, mme_name, IMSI_attach,
4839 ts_SGsAP_LAI('901'H, '70'H, 2342)));
4840 /* Old LAI, if MS sends it */
4841 /* TMSI status, if MS has no valid TMSI */
4842 /* IMEISV, if it supports "automatic device detection" */
4843 /* TAI, if available in MME */
4844 /* E-CGI, if available in MME */
4845 SGsAP.send(lur);
4846
4847 /* FIXME: is this really done over SGs? The Ue is already authenticated
4848 * via the MME ... */
4849 f_mm_auth_sgs();
4850
4851 /* Expect MSC to perform LU with HLR */
4852 GSUP.receive(tr_GSUP_UL_REQ(g_pars.imsi));
4853 GSUP.send(ts_GSUP_ISD_REQ(g_pars.imsi, g_pars.msisdn));
4854 GSUP.receive(tr_GSUP_ISD_RES(g_pars.imsi));
4855 GSUP.send(ts_GSUP_UL_RES(g_pars.imsi));
4856
4857 alt {
4858 [] SGsAP.receive(tr_SGsAP_LU_ACCEPT(g_pars.imsi, ?)) {
4859 setverdict(pass);
4860 }
4861 [] SGsAP.receive(tr_SGsAP_LU_REJECT(g_pars.imsi, ?, ?)) {
4862 setverdict(fail, "Received LU-REJECT instead of ACCEPT");
4863 }
4864 [] SGsAP.receive {
4865 setverdict(fail, "Received unexpected message on SGs");
4866 }
4867 }
4868
4869 f_ctrl_get_exp(IPA_CTRL, "fsm.SGs-UE.id.imsi:" & hex2str(g_pars.imsi) & ".state", "SGs-ASSOCIATED");
4870
4871 /* Wait until the VLR has abort the TMSI reallocation procedure */
4872 f_sleep(45.0);
4873
4874 /* The outcome does not change the SGs state, see also 5.2.3.4 */
4875 f_ctrl_get_exp(IPA_CTRL, "fsm.SGs-UE.id.imsi:" & hex2str(g_pars.imsi) & ".state", "SGs-ASSOCIATED");
4876
4877 f_sgsap_bssmap_screening();
4878
4879 setverdict(pass);
4880}
4881testcase TC_sgsap_lu_and_nothing() runs on MTC_CT {
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004882 var BSC_ConnHdlrPars pars;
Harald Welte4263c522018-12-06 11:56:27 +01004883 var BSC_ConnHdlr vc_conn;
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004884 f_init(1, true);
4885 pars := f_init_pars(11813, true);
Harald Welte4263c522018-12-06 11:56:27 +01004886
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004887 vc_conn := f_start_handler_with_pars(refers(f_tc_sgsap_lu_and_nothing), pars);
Harald Welte4263c522018-12-06 11:56:27 +01004888 vc_conn.done;
4889}
4890
4891private function f_tc_sgsap_expl_imsi_det_eps(charstring id, BSC_ConnHdlrPars pars)
4892runs on BSC_ConnHdlr {
4893 f_init_handler(pars);
4894 f_sgs_perform_lu();
4895 f_sleep(3.0);
4896
4897 var octetstring mme_name := f_enc_dns_hostname(mp_mme_name);
4898 SGsAP.send(ts_SGsAP_EPS_DETACH_IND(g_pars.imsi, mme_name, UE_initiated));
4899 SGsAP.receive(tr_SGsAP_EPS_DETACH_ACK(g_pars.imsi));
4900 f_ctrl_get_exp(IPA_CTRL, "fsm.SGs-UE.id.imsi:" & hex2str(g_pars.imsi) & ".state", "SGs-NULL");
4901
4902 f_sgsap_bssmap_screening();
4903
4904 setverdict(pass);
4905}
4906testcase TC_sgsap_expl_imsi_det_eps() runs on MTC_CT {
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004907 var BSC_ConnHdlrPars pars;
Harald Welte4263c522018-12-06 11:56:27 +01004908 var BSC_ConnHdlr vc_conn;
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004909 f_init(1, true);
4910 pars := f_init_pars(11814, true);
Pau Espin Pedrole979c402021-04-28 17:29:54 +02004911 pars.common_id_last_eutran_plmn := f_enc_mcc_mnc('901'H, '70'H);
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004912 vc_conn := f_start_handler_with_pars(refers(f_tc_sgsap_expl_imsi_det_eps), pars);
Harald Welte4263c522018-12-06 11:56:27 +01004913 vc_conn.done;
4914}
4915
Philipp Maierfc19f172019-03-21 11:17:54 +01004916private function f_tc_sgsap_impl_imsi_det_eps(charstring id, BSC_ConnHdlrPars pars)
4917runs on BSC_ConnHdlr {
4918 f_init_handler(pars);
4919 f_sgs_perform_lu();
4920 f_sleep(3.0);
4921
4922 var octetstring mme_name := f_enc_dns_hostname(mp_mme_name);
4923 SGsAP.send(ts_SGsAP_EPS_DETACH_IND(g_pars.imsi, mme_name, network_initiated));
4924 SGsAP.receive(tr_SGsAP_EPS_DETACH_ACK(g_pars.imsi));
4925 f_ctrl_get_exp(IPA_CTRL, "fsm.SGs-UE.id.imsi:" & hex2str(g_pars.imsi) & ".state", "SGs-NULL");
4926
4927 f_sgsap_bssmap_screening();
4928
4929 setverdict(pass);
4930}
4931testcase TC_sgsap_impl_imsi_det_eps() runs on MTC_CT {
4932 var BSC_ConnHdlrPars pars;
4933 var BSC_ConnHdlr vc_conn;
4934 f_init(1, true);
4935 pars := f_init_pars(11814, true);
Pau Espin Pedrole979c402021-04-28 17:29:54 +02004936 pars.common_id_last_eutran_plmn := f_enc_mcc_mnc('901'H, '70'H);
Philipp Maierfc19f172019-03-21 11:17:54 +01004937 vc_conn := f_start_handler_with_pars(refers(f_tc_sgsap_impl_imsi_det_eps), pars);
4938 vc_conn.done;
4939}
4940
Harald Welte4263c522018-12-06 11:56:27 +01004941private function f_tc_sgsap_expl_imsi_det_noneps(charstring id, BSC_ConnHdlrPars pars)
4942runs on BSC_ConnHdlr {
4943 f_init_handler(pars);
4944 f_sgs_perform_lu();
4945 f_sleep(3.0);
4946
4947 var octetstring mme_name := f_enc_dns_hostname(mp_mme_name);
4948 SGsAP.send(ts_SGsAP_IMSI_DETACH_IND(g_pars.imsi, mme_name, combined_UE_initiated));
4949 SGsAP.receive(tr_SGsAP_IMSI_DETACH_ACK(g_pars.imsi));
Philipp Maierd08e7e72019-04-02 15:27:10 +02004950
4951 if (f_ctrl_subscr_in_vlr(hex2str(g_pars.imsi))) {
4952 setverdict(fail, "subscriber not removed from VLR");
4953 }
Harald Welte4263c522018-12-06 11:56:27 +01004954
4955 f_sgsap_bssmap_screening();
4956
4957 setverdict(pass);
4958}
4959testcase TC_sgsap_expl_imsi_det_noneps() runs on MTC_CT {
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004960 var BSC_ConnHdlrPars pars;
Harald Welte4263c522018-12-06 11:56:27 +01004961 var BSC_ConnHdlr vc_conn;
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004962 f_init(1, true);
4963 pars := f_init_pars(11815, true);
Pau Espin Pedrole979c402021-04-28 17:29:54 +02004964 pars.common_id_last_eutran_plmn := f_enc_mcc_mnc('901'H, '70'H);
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004965 vc_conn := f_start_handler_with_pars(refers(f_tc_sgsap_expl_imsi_det_noneps), pars);
Harald Welte4263c522018-12-06 11:56:27 +01004966 vc_conn.done;
4967}
4968
Philipp Maier5d812702019-03-21 10:51:26 +01004969private function f_tc_sgsap_impl_imsi_det_noneps(charstring id, BSC_ConnHdlrPars pars)
4970runs on BSC_ConnHdlr {
4971 f_init_handler(pars);
4972 f_sgs_perform_lu();
4973 f_sleep(3.0);
4974
4975 var octetstring mme_name := f_enc_dns_hostname(mp_mme_name);
4976 SGsAP.send(ts_SGsAP_IMSI_DETACH_IND(g_pars.imsi, mme_name, implicit_network_initiated));
4977 SGsAP.receive(tr_SGsAP_IMSI_DETACH_ACK(g_pars.imsi));
4978
4979 if (f_ctrl_subscr_in_vlr(hex2str(g_pars.imsi))) {
4980 setverdict(fail, "subscriber not removed from VLR");
4981 }
4982
4983 f_sgsap_bssmap_screening();
4984
4985 setverdict(pass);
4986}
4987testcase TC_sgsap_impl_imsi_det_noneps() runs on MTC_CT {
4988 var BSC_ConnHdlrPars pars;
4989 var BSC_ConnHdlr vc_conn;
4990 f_init(1, true);
4991 pars := f_init_pars(11815, true);
Pau Espin Pedrole979c402021-04-28 17:29:54 +02004992 pars.common_id_last_eutran_plmn := f_enc_mcc_mnc('901'H, '70'H);
Philipp Maier5d812702019-03-21 10:51:26 +01004993 vc_conn := f_start_handler_with_pars(refers(f_tc_sgsap_impl_imsi_det_noneps), pars);
4994 vc_conn.done;
4995}
4996
Harald Welte4263c522018-12-06 11:56:27 +01004997/* Trigger a paging request via VTY and send a paging reject in response */
4998private function f_tc_sgsap_paging_rej(charstring id, BSC_ConnHdlrPars pars)
4999runs on BSC_ConnHdlr {
5000 f_init_handler(pars);
5001 f_sgs_perform_lu();
5002 f_sleep(1.0);
5003
5004 var octetstring vlr_name := f_enc_dns_hostname(mp_vlr_name);
5005 var template PDU_SGsAP exp_resp := tr_SGsAP_PAGING_REQ(g_pars.imsi, vlr_name, CS_call_indicator, omit);
5006 var template LocationAreaId exp_lai := ts_SGsAP_IE_Lai(valueof(ts_SGsAP_LAI('901'H, '70'H, 2342)));
5007 exp_resp.sGsAP_PAGING_REQUEST.locationAreaId := exp_lai;
5008
5009 /* Initiate paging via VTY */
5010 f_vty_transceive(MSCVTY, "subscriber imsi " & hex2str(g_pars.imsi) & " paging");
5011 alt {
5012 [] SGsAP.receive(exp_resp) {
5013 setverdict(pass);
5014 }
5015 [] SGsAP.receive {
5016 setverdict(fail, "Received unexpected message on SGs");
5017 }
5018 }
5019
5020 /* Now reject the paging */
5021 SGsAP.send(ts_SGsAP_PAGING_REJ(g_pars.imsi, IMSI_unknown));
5022
5023 /* Wait for the states inside the MSC to settle and check the state
5024 * of the SGs Association */
5025 f_sleep(1.0);
5026 f_ctrl_get_exp(IPA_CTRL, "fsm.SGs-UE.id.imsi:" & hex2str(g_pars.imsi) & ".state", "SGs-NULL");
5027
5028 /* FIXME: At the moment we send an IMSI_unknown as cause code, which is fine,
5029 * but we also need to cover tha case where the cause code indicates an
5030 * "IMSI detached for EPS services". In those cases the VLR is expected to
5031 * try paging on tha A/Iu interface. This will be another testcase similar to
5032 * this one, but extended with checks for the presence of the A/Iu paging
5033 * messages. */
5034
5035 f_sgsap_bssmap_screening();
5036
5037 setverdict(pass);
5038}
5039testcase TC_sgsap_paging_rej() runs on MTC_CT {
Philipp Maier8e07a4a2019-02-14 18:23:28 +01005040 var BSC_ConnHdlrPars pars;
Harald Welte4263c522018-12-06 11:56:27 +01005041 var BSC_ConnHdlr vc_conn;
Philipp Maier8e07a4a2019-02-14 18:23:28 +01005042 f_init(1, true);
5043 pars := f_init_pars(11816, true);
Pau Espin Pedrole979c402021-04-28 17:29:54 +02005044 pars.common_id_last_eutran_plmn := f_enc_mcc_mnc('901'H, '70'H);
Philipp Maier8e07a4a2019-02-14 18:23:28 +01005045 vc_conn := f_start_handler_with_pars(refers(f_tc_sgsap_paging_rej), pars);
Harald Welte4263c522018-12-06 11:56:27 +01005046 vc_conn.done;
5047}
5048
5049/* Trigger a paging request via VTY and send a paging reject that indicates
5050 * that the subscriber intentionally rejected the call. */
5051private function f_tc_sgsap_paging_subscr_rej(charstring id, BSC_ConnHdlrPars pars)
5052runs on BSC_ConnHdlr {
5053 f_init_handler(pars);
5054 f_sgs_perform_lu();
5055 f_sleep(1.0);
5056
5057 var octetstring vlr_name := f_enc_dns_hostname(mp_vlr_name);
5058 var template PDU_SGsAP exp_resp := tr_SGsAP_PAGING_REQ(g_pars.imsi, vlr_name, CS_call_indicator, omit);
5059 var template LocationAreaId exp_lai := ts_SGsAP_IE_Lai(valueof(ts_SGsAP_LAI('901'H, '70'H, 2342)));
5060 exp_resp.sGsAP_PAGING_REQUEST.locationAreaId := exp_lai;
5061
5062 /* Initiate paging via VTY */
5063 f_vty_transceive(MSCVTY, "subscriber imsi " & hex2str(g_pars.imsi) & " paging");
5064 alt {
5065 [] SGsAP.receive(exp_resp) {
5066 setverdict(pass);
5067 }
5068 [] SGsAP.receive {
5069 setverdict(fail, "Received unexpected message on SGs");
5070 }
5071 }
5072
5073 /* Now reject the paging */
5074 SGsAP.send(ts_SGsAP_PAGING_REJ(g_pars.imsi, user_rejected_mobile_terminating_CS_fallback_call));
5075
5076 /* Wait for the states inside the MSC to settle and check the state
5077 * of the SGs Association */
5078 f_sleep(1.0);
5079 f_ctrl_get_exp(IPA_CTRL, "fsm.SGs-UE.id.imsi:" & hex2str(g_pars.imsi) & ".state", "SGs-ASSOCIATED");
5080
5081 /* FIXME: The VLR is supposed to trigger an User Determined User Busy (UDUB) as specified
5082 * in 3GPP TS 24.082, this is not yet implemented in the MSC or in this tests, we need
5083 * to check back how this works and how it can be tested */
5084
5085 f_sgsap_bssmap_screening();
5086
5087 setverdict(pass);
5088}
5089testcase TC_sgsap_paging_subscr_rej() runs on MTC_CT {
Philipp Maier8e07a4a2019-02-14 18:23:28 +01005090 var BSC_ConnHdlrPars pars;
Harald Welte4263c522018-12-06 11:56:27 +01005091 var BSC_ConnHdlr vc_conn;
Philipp Maier8e07a4a2019-02-14 18:23:28 +01005092 f_init(1, true);
5093 pars := f_init_pars(11817, true);
Pau Espin Pedrole979c402021-04-28 17:29:54 +02005094 pars.common_id_last_eutran_plmn := f_enc_mcc_mnc('901'H, '70'H);
Philipp Maier8e07a4a2019-02-14 18:23:28 +01005095 vc_conn := f_start_handler_with_pars(refers(f_tc_sgsap_paging_subscr_rej), pars);
Harald Welte4263c522018-12-06 11:56:27 +01005096 vc_conn.done;
5097}
5098
5099/* Trigger a paging request via VTY and send an UE unreacable messge in response */
5100private function f_tc_sgsap_paging_ue_unr(charstring id, BSC_ConnHdlrPars pars)
5101runs on BSC_ConnHdlr {
5102 f_init_handler(pars);
5103 f_sgs_perform_lu();
5104 f_sleep(1.0);
5105
5106 var octetstring vlr_name := f_enc_dns_hostname(mp_vlr_name);
5107 var template PDU_SGsAP exp_resp := tr_SGsAP_PAGING_REQ(g_pars.imsi, vlr_name, CS_call_indicator, omit);
5108 var template LocationAreaId exp_lai := ts_SGsAP_IE_Lai(valueof(ts_SGsAP_LAI('901'H, '70'H, 2342)));
5109 exp_resp.sGsAP_PAGING_REQUEST.locationAreaId := exp_lai;
5110
5111 /* Initiate paging via VTY */
5112 f_vty_transceive(MSCVTY, "subscriber imsi " & hex2str(g_pars.imsi) & " paging");
5113 alt {
5114 [] SGsAP.receive(exp_resp) {
5115 setverdict(pass);
5116 }
5117 [] SGsAP.receive {
5118 setverdict(fail, "Received unexpected message on SGs");
5119 }
5120 }
5121
5122 /* Now pretend that the UE is unreachable */
5123 SGsAP.send(ts_SGsAP_UE_UNREACHABLE(g_pars.imsi, UE_unreachable));
5124
5125 /* Wait for the states inside the MSC to settle and check the state
5126 * of the SGs Association. */
5127 f_sleep(1.0);
5128 f_ctrl_get_exp(IPA_CTRL, "fsm.SGs-UE.id.imsi:" & hex2str(g_pars.imsi) & ".state", "SGs-ASSOCIATED");
5129
5130 f_sgsap_bssmap_screening();
5131
5132 setverdict(pass);
5133}
5134testcase TC_sgsap_paging_ue_unr() runs on MTC_CT {
Philipp Maier8e07a4a2019-02-14 18:23:28 +01005135 var BSC_ConnHdlrPars pars;
Harald Welte4263c522018-12-06 11:56:27 +01005136 var BSC_ConnHdlr vc_conn;
Philipp Maier8e07a4a2019-02-14 18:23:28 +01005137 f_init(1, true);
5138 pars := f_init_pars(11818, true);
Pau Espin Pedrole979c402021-04-28 17:29:54 +02005139 pars.common_id_last_eutran_plmn := f_enc_mcc_mnc('901'H, '70'H);
Philipp Maier8e07a4a2019-02-14 18:23:28 +01005140 vc_conn := f_start_handler_with_pars(refers(f_tc_sgsap_paging_ue_unr), pars);
Harald Welte4263c522018-12-06 11:56:27 +01005141 vc_conn.done;
5142}
5143
5144/* Trigger a paging request via VTY but don't respond to it */
5145private function f_tc_sgsap_paging_and_nothing(charstring id, BSC_ConnHdlrPars pars)
5146runs on BSC_ConnHdlr {
5147 f_init_handler(pars);
5148 f_sgs_perform_lu();
5149 f_sleep(1.0);
5150
5151 var octetstring vlr_name := f_enc_dns_hostname(mp_vlr_name);
5152 var template PDU_SGsAP exp_resp := tr_SGsAP_PAGING_REQ(g_pars.imsi, vlr_name, CS_call_indicator, omit);
Philipp Maier34218102019-09-24 09:15:49 +02005153 var template PDU_SGsAP exp_serv_abrt := ts_SGsAP_SERVICE_ABORT_REQ(g_pars.imsi);
Harald Welte4263c522018-12-06 11:56:27 +01005154 var template LocationAreaId exp_lai := ts_SGsAP_IE_Lai(valueof(ts_SGsAP_LAI('901'H, '70'H, 2342)));
5155 exp_resp.sGsAP_PAGING_REQUEST.locationAreaId := exp_lai;
5156
5157 /* Initiate paging via VTY */
5158 f_vty_transceive(MSCVTY, "subscriber imsi " & hex2str(g_pars.imsi) & " paging");
5159 alt {
5160 [] SGsAP.receive(exp_resp) {
5161 setverdict(pass);
5162 }
5163 [] SGsAP.receive {
5164 setverdict(fail, "Received unexpected message on SGs");
5165 }
5166 }
5167
Philipp Maier34218102019-09-24 09:15:49 +02005168 /* While we are doing nothing, expect an SGsAP-SERVICE-ABORT-REQUEST
5169 * after some time */
5170 timer T := 10.0;
5171 T.start
5172 alt {
5173 [] SGsAP.receive(exp_serv_abrt)
5174 {
5175 setverdict(pass);
5176 }
5177 [] SGsAP.receive {
5178 setverdict(fail, "unexpected SGsAP message received");
5179 self.stop;
5180 }
5181 [] T.timeout {
5182 setverdict(fail, "MSC did not send SGsAP-SERVICE-ABORT-REQUEST");
5183 self.stop;
5184 }
5185 }
5186
5187 /* The SGs association must remain unchanged. */
Harald Welte4263c522018-12-06 11:56:27 +01005188 f_ctrl_get_exp(IPA_CTRL, "fsm.SGs-UE.id.imsi:" & hex2str(g_pars.imsi) & ".state", "SGs-ASSOCIATED");
5189
5190 f_sgsap_bssmap_screening();
5191
5192 setverdict(pass);
5193}
5194testcase TC_sgsap_paging_and_nothing() runs on MTC_CT {
Philipp Maier8e07a4a2019-02-14 18:23:28 +01005195 var BSC_ConnHdlrPars pars;
Harald Welte4263c522018-12-06 11:56:27 +01005196 var BSC_ConnHdlr vc_conn;
Philipp Maier8e07a4a2019-02-14 18:23:28 +01005197 f_init(1, true);
5198 pars := f_init_pars(11819, true);
Pau Espin Pedrole979c402021-04-28 17:29:54 +02005199 pars.common_id_last_eutran_plmn := f_enc_mcc_mnc('901'H, '70'H);
Philipp Maier8e07a4a2019-02-14 18:23:28 +01005200 vc_conn := f_start_handler_with_pars(refers(f_tc_sgsap_paging_and_nothing), pars);
Harald Welte4263c522018-12-06 11:56:27 +01005201 vc_conn.done;
5202}
5203
5204/* Trigger a paging request via VTY and slip in an LU */
5205private function f_tc_sgsap_paging_and_lu(charstring id, BSC_ConnHdlrPars pars)
5206runs on BSC_ConnHdlr {
5207 var octetstring vlr_name := f_enc_dns_hostname(mp_vlr_name);
5208 f_init_handler(pars);
5209
5210 /* First we prepar the situation, where the SGs association is in state
5211 * NULL and the confirmed by radio contact indicator is set to false
5212 * as well. This can be archived by performing an SGs LU and then
5213 * resetting the VLR */
5214 f_sgs_perform_lu();
5215 f_sgsap_reset_mme(mp_mme_name);
5216 f_sleep(1.0);
5217 f_ctrl_get_exp(IPA_CTRL, "fsm.SGs-UE.id.imsi:" & hex2str(g_pars.imsi) & ".state", "SGs-NULL");
5218
5219 /* Perform a paging, expect the paging messages on the SGs interface */
5220 f_vty_transceive(MSCVTY, "subscriber imsi " & hex2str(g_pars.imsi) & " paging");
5221 alt {
5222 [] SGsAP.receive(tr_SGsAP_PAGING_REQ(pars.imsi, vlr_name, CS_call_indicator, omit)) {
5223 setverdict(pass);
5224 }
5225 [] SGsAP.receive {
5226 setverdict(fail, "Received unexpected message on SGs");
5227 }
5228 }
5229
5230 /* Perform the LU as normal */
5231 f_sgs_perform_lu();
5232 f_ctrl_get_exp(IPA_CTRL, "fsm.SGs-UE.id.imsi:" & hex2str(g_pars.imsi) & ".state", "SGs-ASSOCIATED");
5233
5234 /* Expect a new paging request right after the LU */
5235 alt {
5236 [] SGsAP.receive(tr_SGsAP_PAGING_REQ(pars.imsi, vlr_name, CS_call_indicator, omit)) {
5237 setverdict(pass);
5238 }
5239 [] SGsAP.receive {
5240 setverdict(fail, "Received unexpected message on SGs");
5241 }
5242 }
5243
5244 /* Test is done now, lets round everything up by rejecting the paging
5245 * cleanly. */
5246 SGsAP.send(ts_SGsAP_PAGING_REJ(g_pars.imsi, user_rejected_mobile_terminating_CS_fallback_call));
5247 f_ctrl_get_exp(IPA_CTRL, "fsm.SGs-UE.id.imsi:" & hex2str(g_pars.imsi) & ".state", "SGs-ASSOCIATED");
5248
5249 f_sgsap_bssmap_screening();
5250
5251 setverdict(pass);
5252}
5253testcase TC_sgsap_paging_and_lu() runs on MTC_CT {
Philipp Maier8e07a4a2019-02-14 18:23:28 +01005254 var BSC_ConnHdlrPars pars;
Harald Welte4263c522018-12-06 11:56:27 +01005255 var BSC_ConnHdlr vc_conn;
Philipp Maier8e07a4a2019-02-14 18:23:28 +01005256 f_init(1, true);
5257 pars := f_init_pars(11820, true);
Pau Espin Pedrole979c402021-04-28 17:29:54 +02005258 pars.common_id_last_eutran_plmn := f_enc_mcc_mnc('901'H, '70'H);
Philipp Maier8e07a4a2019-02-14 18:23:28 +01005259 vc_conn := f_start_handler_with_pars(refers(f_tc_sgsap_paging_and_lu), pars);
Harald Welte4263c522018-12-06 11:56:27 +01005260 vc_conn.done;
5261}
5262
5263/* Send unexpected unit-data through the SGs interface */
5264private function f_tc_sgsap_unexp_ud(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
5265 f_init_handler(pars);
5266 f_sleep(1.0);
5267
5268 /* This simulates what happens when a subscriber without SGs
5269 * association gets unitdata via the SGs interface. */
5270
5271 /* Make sure the subscriber exists and the SGs association
5272 * is in NULL state */
5273 f_perform_lu();
5274 f_ctrl_get_exp(IPA_CTRL, "fsm.SGs-UE.id.imsi:" & hex2str(g_pars.imsi) & ".state", "SGs-NULL");
5275
5276 /* Send some random unit data, the MSC/VLR should send a release
5277 * immediately. */
5278 SGsAP.send(ts_SGsAP_UL_UD(pars.imsi,'1234'O));
5279 SGsAP.receive(tr_SGsAP_RELEASE_REQ(pars.imsi, IMSI_detached_for_EPS_nonEPS_services));
5280
5281 f_sgsap_bssmap_screening();
5282
5283 setverdict(pass);
5284}
5285testcase TC_sgsap_unexp_ud() runs on MTC_CT {
Philipp Maier8e07a4a2019-02-14 18:23:28 +01005286 var BSC_ConnHdlrPars pars;
Harald Welte4263c522018-12-06 11:56:27 +01005287 var BSC_ConnHdlr vc_conn;
Philipp Maier8e07a4a2019-02-14 18:23:28 +01005288 f_init(1, true);
5289 pars := f_init_pars(11821, true);
5290 vc_conn := f_start_handler_with_pars(refers(f_tc_sgsap_unexp_ud), pars);
Harald Welte4263c522018-12-06 11:56:27 +01005291 vc_conn.done;
5292}
5293
5294/* Send unsolicited unit-data through the SGs interface */
5295private function f_tc_sgsap_unsol_ud(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
5296 f_init_handler(pars);
5297 f_sleep(1.0);
5298
5299 /* This simulates what happens when the MME attempts to send unitdata
5300 * to a subscriber that is completely unknown to the VLR */
5301
5302 /* Send some random unit data, the MSC/VLR should send a release
5303 * immediately. */
5304 SGsAP.send(ts_SGsAP_UL_UD(pars.imsi,'1234'O));
5305 SGsAP.receive(tr_SGsAP_RELEASE_REQ(pars.imsi, IMSI_unknown));
5306
5307 f_sgsap_bssmap_screening();
5308
Harald Welte4d15fa72020-08-19 08:58:28 +02005309 /* clean-up VLR state about this subscriber */
5310 f_imsi_detach_by_imsi();
5311
Harald Welte4263c522018-12-06 11:56:27 +01005312 setverdict(pass);
5313}
5314testcase TC_sgsap_unsol_ud() runs on MTC_CT {
Philipp Maier8e07a4a2019-02-14 18:23:28 +01005315 var BSC_ConnHdlrPars pars;
Harald Welte4263c522018-12-06 11:56:27 +01005316 var BSC_ConnHdlr vc_conn;
Philipp Maier8e07a4a2019-02-14 18:23:28 +01005317 f_init(1, true);
5318 pars := f_init_pars(11822, true);
5319 vc_conn := f_start_handler_with_pars(refers(f_tc_sgsap_unsol_ud), pars);
Harald Welte4263c522018-12-06 11:56:27 +01005320 vc_conn.done;
5321}
5322
5323private altstep as_other_sms_sgs() runs on BSC_ConnHdlr {
5324 /* FIXME: Match an actual payload (second questionmark), the type is
5325 * octetstring, how do we use a tr_PDU_DTAP_MT here? */
5326 [] SGsAP.receive(tr_SGsAP_DL_UD(?,?)) {
5327 setverdict(fail, "Unexpected SMS related PDU from MSC");
5328 mtc.stop;
5329 }
5330}
5331
5332/* receive a MT-SMS delivered from the MSC/SMSC over an already existing SGsAP connection */
5333function f_mt_sms_sgs(inout SmsParameters spars)
5334runs on BSC_ConnHdlr {
5335 var template (value) TPDU_RP_DATA_MS_SGSN tp_mo;
5336 var template (value) RPDU_MS_SGSN rp_mo;
5337 var template (value) PDU_ML3_MS_NW l3_mo;
5338
5339 var template TPDU_RP_DATA_SGSN_MS tp_mt;
5340 var template RPDU_SGSN_MS rp_mt;
5341 var template PDU_ML3_NW_MS l3_mt;
5342
5343 var PDU_ML3_NW_MS sgsap_l3_mt;
5344
5345 var default d := activate(as_other_sms_sgs());
5346
5347 /* Expect CP-DATA(RP-DATA(SMS-DELIVER)) */
5348 tp_mt := tr_SMS_DELIVER(?, spars.tp.ud, spars.tp.pid, spars.tp.dcs, ?);
Vadim Yanitskiy04dd5f72019-12-13 15:45:44 +09005349 rp_mt := tr_RP_DATA_MT(?, spars.rp.smsc_addr, omit, tp_mt);
Harald Welte4263c522018-12-06 11:56:27 +01005350 l3_mt := tr_ML3_MT_SMS(?, c_TIF_ORIG, tr_CP_DATA_MT(rp_mt));
5351
5352 SGsAP.receive(l3_mt) -> value sgsap_l3_mt;
5353
5354 /* Extract relevant identifiers */
5355 spars.tid := bit2int(sgsap_l3_mt.tiOrSkip.transactionId.tio);
5356 spars.rp.msg_ref := sgsap_l3_mt.msgs.sms.cP_DATA.cP_User_Data.cP_RPDU.rP_DATA_SGSN_MS.rP_MessageReference;
5357
5358 /* send CP-ACK for CP-DATA just received */
5359 l3_mo := ts_ML3_MO_SMS(spars.tid, c_TIF_REPL, ts_CP_ACK_MO);
5360
5361 SGsAP.send(l3_mo);
5362
5363 /* send RP-ACK for RP-DATA */
5364 rp_mo := ts_RP_ACK_MO(spars.rp.msg_ref);
5365 l3_mo := ts_ML3_MO_SMS(spars.tid, c_TIF_REPL, ts_CP_DATA_MO(rp_mo));
5366
5367 SGsAP.send(l3_mo);
5368
5369 /* expect CP-ACK for CP-DATA(RP-ACK) just sent */
5370 l3_mt := tr_ML3_MT_SMS(spars.tid, c_TIF_ORIG, tr_CP_ACK_MT);
5371
5372 SGsAP.receive(l3_mt);
5373
5374 deactivate(d);
5375
5376 setverdict(pass);
5377}
5378
5379/* submit a MO-SMS to MSC/SMSC over an already existing SGsAP connection */
5380function f_mo_sms_sgs(inout SmsParameters spars)
5381runs on BSC_ConnHdlr {
5382 var template (value) TPDU_RP_DATA_MS_SGSN tp_mo;
5383 var template (value) RPDU_MS_SGSN rp_mo;
5384 var template (value) PDU_ML3_MS_NW l3_mo;
5385
5386 var template TPDU_RP_DATA_SGSN_MS tp_mt;
5387 var template RPDU_SGSN_MS rp_mt;
5388 var template PDU_ML3_NW_MS l3_mt;
5389
5390 var default d := activate(as_other_sms_sgs());
5391
5392 /* just in case this is routed to SMPP.. */
5393 f_create_smpp_expect(hex2str(spars.tp.da.tP_DA_NoPad.tP_DAValue));
5394
5395 tp_mo := ts_SMS_SUBMIT(spars.tp.msg_ref, spars.tp.da, spars.tp.pid, spars.tp.dcs,
5396 spars.tp.udl, spars.tp.ud);
Vadim Yanitskiy437b5a62019-12-15 14:13:39 +09005397 rp_mo := ts_RP_DATA_MO(spars.rp.msg_ref, omit, spars.rp.smsc_addr, tp_mo);
Harald Welte4263c522018-12-06 11:56:27 +01005398 l3_mo := ts_ML3_MO_SMS(spars.tid, c_TIF_ORIG, ts_CP_DATA_MO(rp_mo));
5399
5400 SGsAP.send(l3_mo);
5401
5402 /* receive CP-ACK for CP-DATA above */
5403 SGsAP.receive(tr_ML3_MT_SMS(spars.tid, c_TIF_REPL, tr_CP_ACK_MT));
5404
5405 if (ispresent(spars.exp_rp_err)) {
5406 /* expect an RP-ERROR message from MSC with given cause */
5407 rp_mt := tr_RP_ERROR_MT(spars.rp.msg_ref, spars.exp_rp_err);
5408 l3_mt := tr_ML3_MT_SMS(spars.tid, c_TIF_REPL, tr_CP_DATA_MT(rp_mt));
5409 SGsAP.receive(l3_mt);
5410 /* send CP-ACK for CP-DATA just received */
5411 l3_mo := ts_ML3_MO_SMS(spars.tid, c_TIF_ORIG, ts_CP_ACK_MO);
5412 SGsAP.send(l3_mo);
5413 } else {
5414 /* expect RP-ACK for RP-DATA */
5415 rp_mt := tr_RP_ACK_MT(spars.rp.msg_ref);
5416 l3_mt := tr_ML3_MT_SMS(spars.tid, c_TIF_REPL, tr_CP_DATA_MT(rp_mt));
5417 SGsAP.receive(l3_mt);
5418 /* send CP-ACO for CP-DATA just received */
5419 l3_mo := ts_ML3_MO_SMS(spars.tid, c_TIF_ORIG, ts_CP_ACK_MO);
5420 SGsAP.send(l3_mo);
5421 }
5422
5423 deactivate(d);
5424
5425 setverdict(pass);
5426}
5427
5428private function f_vty_sms_send_conn_hdlr(charstring imsi, charstring msisdn, charstring text)
5429runs on BSC_ConnHdlr {
5430 f_vty_transceive(MSCVTY, "subscriber imsi "&imsi&" sms sender msisdn "&msisdn&" send "&text);
5431}
5432
5433/* Send a MT SMS via SGs interface */
5434private function f_tc_sgsap_mt_sms(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
5435 f_init_handler(pars);
5436 f_sgs_perform_lu();
5437 f_sleep(1.0);
5438 var SmsParameters spars := valueof(t_SmsPars);
5439 spars.tp.ud := 'C8329BFD064D9B53'O;
5440
5441 /* Trigger SMS via VTY */
5442 f_vty_sms_send_conn_hdlr(hex2str(pars.imsi), "2342", "Hello SMS");
5443 var octetstring vlr_name := f_enc_dns_hostname(mp_vlr_name);
5444
5445 /* Expect a paging request and respond accordingly with a service request */
5446 SGsAP.receive(tr_SGsAP_PAGING_REQ(pars.imsi, vlr_name, SMS_indicator, omit));
5447 SGsAP.send(ts_SGsAP_SERVICE_REQ(pars.imsi, SMS_indicator, EMM_CONNECTED));
5448
5449 /* Connection is now live, receive the MT-SMS */
5450 f_mt_sms_sgs(spars);
5451
5452 /* Expect a concluding release from the MSC */
5453 SGsAP.receive(tr_SGsAP_RELEASE_REQ(pars.imsi, omit));
5454
5455 /* Make sure that subscriber is still present and the SGs association is in tact (ref-counting) */
5456 f_ctrl_get_exp(IPA_CTRL, "fsm.SGs-UE.id.imsi:" & hex2str(g_pars.imsi) & ".state", "SGs-ASSOCIATED");
5457
5458 f_sgsap_bssmap_screening();
5459
5460 setverdict(pass);
5461}
5462testcase TC_sgsap_mt_sms() runs on MTC_CT {
Philipp Maier8e07a4a2019-02-14 18:23:28 +01005463 var BSC_ConnHdlrPars pars;
Harald Welte4263c522018-12-06 11:56:27 +01005464 var BSC_ConnHdlr vc_conn;
Philipp Maier8e07a4a2019-02-14 18:23:28 +01005465 f_init(1, true);
5466 pars := f_init_pars(11823, true);
Pau Espin Pedrole979c402021-04-28 17:29:54 +02005467 pars.common_id_last_eutran_plmn := f_enc_mcc_mnc('901'H, '70'H);
Philipp Maier8e07a4a2019-02-14 18:23:28 +01005468 vc_conn := f_start_handler_with_pars(refers(f_tc_sgsap_mt_sms), pars);
Harald Welte4263c522018-12-06 11:56:27 +01005469 vc_conn.done;
5470}
5471
5472/* Send a MO SMS via SGs interface */
5473private function f_tc_sgsap_mo_sms(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
5474 f_init_handler(pars);
5475 f_sgs_perform_lu();
5476 f_sleep(1.0);
5477 var SmsParameters spars := valueof(t_SmsPars);
5478 spars.tp.ud := 'C8329BFD064D9B53'O;
5479
5480 /* Send the MO-SMS */
5481 f_mo_sms_sgs(spars);
5482
5483 /* Expect a concluding release from the MSC/VLR */
5484 SGsAP.receive(tr_SGsAP_RELEASE_REQ(pars.imsi, omit));
5485
5486 /* Make sure that subscriber is still present and the SGs association is in tact (ref-counting) */
5487 f_ctrl_get_exp(IPA_CTRL, "fsm.SGs-UE.id.imsi:" & hex2str(g_pars.imsi) & ".state", "SGs-ASSOCIATED");
5488
5489 setverdict(pass);
5490
5491 f_sgsap_bssmap_screening()
5492}
5493testcase TC_sgsap_mo_sms() runs on MTC_CT {
Philipp Maier8e07a4a2019-02-14 18:23:28 +01005494 var BSC_ConnHdlrPars pars;
Harald Welte4263c522018-12-06 11:56:27 +01005495 var BSC_ConnHdlr vc_conn;
Philipp Maier8e07a4a2019-02-14 18:23:28 +01005496 f_init(1, true);
5497 pars := f_init_pars(11824, true);
Pau Espin Pedrole979c402021-04-28 17:29:54 +02005498 pars.common_id_last_eutran_plmn := f_enc_mcc_mnc('901'H, '70'H);
Philipp Maier8e07a4a2019-02-14 18:23:28 +01005499 vc_conn := f_start_handler_with_pars(refers(f_tc_sgsap_mo_sms), pars);
Harald Welte4263c522018-12-06 11:56:27 +01005500 vc_conn.done;
5501}
5502
5503/* Trigger sending of an MT sms via VTY but never respond to anything */
5504private function f_tc_sgsap_mt_sms_and_nothing(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
5505 f_init_handler(pars, 170.0);
5506 f_sgs_perform_lu();
5507 f_sleep(1.0);
5508
5509 var SmsParameters spars := valueof(t_SmsPars);
5510 spars.tp.ud := 'C8329BFD064D9B53'O;
5511 var integer page_count := 0;
5512 var octetstring vlr_name := f_enc_dns_hostname(mp_vlr_name);
5513 var template PDU_SGsAP exp_pag_req := tr_SGsAP_PAGING_REQ(g_pars.imsi, vlr_name, SMS_indicator, omit);
5514 var template LocationAreaId exp_lai := ts_SGsAP_IE_Lai(valueof(ts_SGsAP_LAI('901'H, '70'H, 2342)));
5515 exp_pag_req.sGsAP_PAGING_REQUEST.locationAreaId := exp_lai;
5516
5517 /* Trigger SMS via VTY */
5518 f_vty_sms_send_conn_hdlr(hex2str(pars.imsi), "2342", "Hello SMS");
5519
Neels Hofmeyr16237742019-03-06 15:34:01 +01005520 /* Expect the MSC/VLR to page exactly once */
5521 SGsAP.receive(exp_pag_req);
Harald Welte4263c522018-12-06 11:56:27 +01005522
5523 /* Wait some time to make sure the MSC is not delivering any further
5524 * paging messages or anything else that could be unexpected. */
5525 timer T := 20.0;
5526 T.start
5527 alt {
5528 [] SGsAP.receive(exp_pag_req)
5529 {
5530 setverdict(fail, "paging seems not to stop!");
5531 mtc.stop;
5532 }
5533 [] SGsAP.receive {
5534 setverdict(fail, "unexpected SGsAP message received");
5535 self.stop;
5536 }
5537 [] T.timeout {
5538 setverdict(pass);
5539 }
5540 }
5541
5542 /* Even on a failed paging the SGs Association should stay intact */
5543 f_ctrl_get_exp(IPA_CTRL, "fsm.SGs-UE.id.imsi:" & hex2str(g_pars.imsi) & ".state", "SGs-ASSOCIATED");
5544
Philipp Maier26bdb8c2019-09-24 09:21:12 +02005545 /* Make sure that the SMS we just inserted is cleared and the
5546 * subscriber is expired. This is necessary because otherwise the MSC
5547 * might re-try the SMS delivery and disturb the following tests. */
Harald Welte4263c522018-12-06 11:56:27 +01005548
Neels Hofmeyr8256ed22019-03-06 15:34:01 +01005549 f_vty_sms_clear(hex2str(g_pars.imsi));
5550
Harald Welte4263c522018-12-06 11:56:27 +01005551 f_vty_transceive(MSCVTY, "subscriber imsi " & hex2str(g_pars.imsi) & " expire");
5552
5553 setverdict(pass);
Neels Hofmeyrb0f82342019-03-06 15:36:51 +01005554
5555 f_sgsap_bssmap_screening();
Harald Welte4263c522018-12-06 11:56:27 +01005556}
5557testcase TC_sgsap_mt_sms_and_nothing() runs on MTC_CT {
Philipp Maier8e07a4a2019-02-14 18:23:28 +01005558 var BSC_ConnHdlrPars pars;
Harald Welte4263c522018-12-06 11:56:27 +01005559 var BSC_ConnHdlr vc_conn;
Philipp Maier8e07a4a2019-02-14 18:23:28 +01005560 f_init(1, true);
5561 pars := f_init_pars(11825, true);
Pau Espin Pedrole979c402021-04-28 17:29:54 +02005562 pars.common_id_last_eutran_plmn := f_enc_mcc_mnc('901'H, '70'H);
Philipp Maier8e07a4a2019-02-14 18:23:28 +01005563 vc_conn := f_start_handler_with_pars(refers(f_tc_sgsap_mt_sms_and_nothing), pars);
Harald Welte4263c522018-12-06 11:56:27 +01005564 vc_conn.done;
5565}
5566
5567/* Trigger sending of an MT sms via VTY but reject the paging immediately */
5568private function f_tc_sgsap_mt_sms_and_reject(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
5569 f_init_handler(pars, 150.0);
5570 f_sgs_perform_lu();
5571 f_sleep(1.0);
5572
5573 var SmsParameters spars := valueof(t_SmsPars);
5574 spars.tp.ud := 'C8329BFD064D9B53'O;
5575 var integer page_count := 0;
5576 var octetstring vlr_name := f_enc_dns_hostname(mp_vlr_name);
5577 var template PDU_SGsAP exp_pag_req := tr_SGsAP_PAGING_REQ(g_pars.imsi, vlr_name, SMS_indicator, omit);
5578 var template LocationAreaId exp_lai := ts_SGsAP_IE_Lai(valueof(ts_SGsAP_LAI('901'H, '70'H, 2342)));
5579 exp_pag_req.sGsAP_PAGING_REQUEST.locationAreaId := exp_lai;
5580
5581 /* Trigger SMS via VTY */
5582 f_vty_sms_send_conn_hdlr(hex2str(pars.imsi), "2342", "Hello SMS");
5583
5584 /* Expect a paging request and reject it immediately */
5585 SGsAP.receive(exp_pag_req);
5586 SGsAP.send(ts_SGsAP_PAGING_REJ(g_pars.imsi, IMSI_unknown));
5587
5588 /* The MSC/VLR should no longer try to page once the paging has been
5589 * rejected. Wait some time and check if there are no unexpected
5590 * messages on the SGs interface. */
5591 timer T := 20.0;
5592 T.start
5593 alt {
5594 [] SGsAP.receive(exp_pag_req)
5595 {
5596 setverdict(fail, "paging seems not to stop!");
5597 mtc.stop;
5598 }
5599 [] SGsAP.receive {
5600 setverdict(fail, "unexpected SGsAP message received");
5601 self.stop;
5602 }
5603 [] T.timeout {
5604 setverdict(pass);
5605 }
5606 }
5607
Neels Hofmeyr8256ed22019-03-06 15:34:01 +01005608 f_vty_sms_clear(hex2str(g_pars.imsi));
5609
Harald Welte4263c522018-12-06 11:56:27 +01005610 /* A rejected paging with IMSI_unknown (see above) should always send
5611 * the SGs association to NULL. */
5612 f_ctrl_get_exp(IPA_CTRL, "fsm.SGs-UE.id.imsi:" & hex2str(g_pars.imsi) & ".state", "SGs-NULL");
5613
5614 f_sgsap_bssmap_screening();
5615
Harald Welte4263c522018-12-06 11:56:27 +01005616 setverdict(pass);
5617}
5618testcase TC_sgsap_mt_sms_and_reject() runs on MTC_CT {
Philipp Maier8e07a4a2019-02-14 18:23:28 +01005619 var BSC_ConnHdlrPars pars;
Harald Welte4263c522018-12-06 11:56:27 +01005620 var BSC_ConnHdlr vc_conn;
Philipp Maier8e07a4a2019-02-14 18:23:28 +01005621 f_init(1, true);
5622 pars := f_init_pars(11826, true);
Pau Espin Pedrole979c402021-04-28 17:29:54 +02005623 pars.common_id_last_eutran_plmn := f_enc_mcc_mnc('901'H, '70'H);
Philipp Maier8e07a4a2019-02-14 18:23:28 +01005624 vc_conn := f_start_handler_with_pars(refers(f_tc_sgsap_mt_sms_and_reject), pars);
Harald Welte4263c522018-12-06 11:56:27 +01005625 vc_conn.done;
5626}
5627
Pau Espin Pedrol3acd19e2021-04-28 12:59:52 +02005628/* Perform an MT CSFB call including LU */
Harald Welte4263c522018-12-06 11:56:27 +01005629private function f_mt_lu_and_csfb_call(charstring id, BSC_ConnHdlrPars pars, boolean bssmap_lu) runs on BSC_ConnHdlr {
5630 f_init_handler(pars);
5631
5632 /* Be sure that the BSSMAP reset is done before we begin. */
5633 f_sleep(2.0);
5634
5635 /* Testcase variation: See what happens when we do a regular BSSMAP
5636 * LU first (this should not hurt in any way!) */
5637 if (bssmap_lu) {
5638 f_perform_lu();
5639 }
Pau Espin Pedrole979c402021-04-28 17:29:54 +02005640 pars.common_id_last_eutran_plmn := f_enc_mcc_mnc('901'H, '70'H);
Harald Welte4263c522018-12-06 11:56:27 +01005641
5642 f_sgs_perform_lu();
5643 f_sleep(1.0);
5644
5645 var octetstring vlr_name := f_enc_dns_hostname(mp_vlr_name);
5646 var CallParameters cpars := valueof(t_CallParams('12345'H, 0));
Harald Welte4263c522018-12-06 11:56:27 +01005647
5648 /* Initiate a call via MNCC interface */
Oliver Smith97dc91f2023-05-31 13:53:21 +02005649 f_mt_call_initiate(cpars);
Harald Welte4263c522018-12-06 11:56:27 +01005650
5651 /* Expect a paging request and respond accordingly with a service request */
5652 SGsAP.receive(tr_SGsAP_PAGING_REQ(pars.imsi, vlr_name, CS_call_indicator, omit));
5653 SGsAP.send(ts_SGsAP_SERVICE_REQ(pars.imsi, CS_call_indicator, EMM_CONNECTED));
5654
5655 /* Complete the call, hold it for some time and then tear it down */
5656 f_mt_call_complete(cpars);
5657 f_sleep(3.0);
Harald Welte4c422b72019-02-17 16:27:10 +01005658 f_call_hangup(cpars, true, is_csfb := true);
Harald Welte4263c522018-12-06 11:56:27 +01005659
5660 /* Make sure that subscriber is still present and the SGs association is in tact (ref-counting) */
5661 f_ctrl_get_exp(IPA_CTRL, "fsm.SGs-UE.id.imsi:" & hex2str(g_pars.imsi) & ".state", "SGs-ASSOCIATED");
5662
Harald Welte4263c522018-12-06 11:56:27 +01005663 /* Test for successful return by triggering a paging, when the paging
5664 * request is received via SGs, we can be sure that the MSC/VLR has
5665 * recognized that the UE is now back on 4G */
5666 f_sleep(1.0);
5667 f_vty_transceive(MSCVTY, "subscriber imsi " & hex2str(g_pars.imsi) & " paging");
5668 alt {
5669 [] SGsAP.receive(tr_SGsAP_PAGING_REQ(pars.imsi, vlr_name, CS_call_indicator, omit)) {
5670 setverdict(pass);
5671 }
5672 [] SGsAP.receive {
5673 setverdict(fail, "Received unexpected message on SGs");
5674 }
5675 }
5676
5677 f_sgsap_bssmap_screening();
5678
5679 setverdict(pass);
5680}
5681
5682/* Perform a regular BSSAP LU first, do a SGSAP LU and then make a CSFB call */
5683private function f_tc_bssap_lu_sgsap_lu_and_mt_call(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
5684 f_mt_lu_and_csfb_call(id, pars, true);
5685}
5686testcase TC_bssap_lu_sgsap_lu_and_mt_call() runs on MTC_CT {
Philipp Maier8e07a4a2019-02-14 18:23:28 +01005687 var BSC_ConnHdlrPars pars;
Harald Welte4263c522018-12-06 11:56:27 +01005688 var BSC_ConnHdlr vc_conn;
Philipp Maier8e07a4a2019-02-14 18:23:28 +01005689 f_init(1, true);
5690 pars := f_init_pars(118139, true);
Harald Welte4263c522018-12-06 11:56:27 +01005691
Philipp Maier8e07a4a2019-02-14 18:23:28 +01005692 vc_conn := f_start_handler_with_pars(refers(f_tc_bssap_lu_sgsap_lu_and_mt_call), pars);
Harald Welte4263c522018-12-06 11:56:27 +01005693 vc_conn.done;
5694}
5695
Harald Welte4263c522018-12-06 11:56:27 +01005696/* Perform a SGSAP LU and then make a CSFB call */
5697private function f_tc_sgsap_lu_and_mt_call(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
5698 f_mt_lu_and_csfb_call(id, pars, false);
5699}
5700testcase TC_sgsap_lu_and_mt_call() runs on MTC_CT {
Philipp Maier8e07a4a2019-02-14 18:23:28 +01005701 var BSC_ConnHdlrPars pars;
Harald Welte4263c522018-12-06 11:56:27 +01005702 var BSC_ConnHdlr vc_conn;
Philipp Maier8e07a4a2019-02-14 18:23:28 +01005703 f_init(1, true);
5704 pars := f_init_pars(11827, true);
Harald Welte4263c522018-12-06 11:56:27 +01005705
Philipp Maier8e07a4a2019-02-14 18:23:28 +01005706 vc_conn := f_start_handler_with_pars(refers(f_tc_sgsap_lu_and_mt_call), pars);
Harald Welte4263c522018-12-06 11:56:27 +01005707 vc_conn.done;
5708}
5709
Philipp Maier628c0052019-04-09 17:36:57 +02005710/* Simulate an HLR/VLR failure */
5711private function f_tc_sgsap_vlr_failure(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
5712 var octetstring mme_name := f_enc_dns_hostname(mp_mme_name);
5713 var octetstring vlr_name := f_enc_dns_hostname(mp_vlr_name);
5714
5715 var PDU_SGsAP lur;
5716
5717 f_init_handler(pars);
5718
5719 /* Attempt location update (which is expected to fail) */
5720 lur := valueof(ts_SGsAP_LU_REQ(g_pars.imsi, mme_name, IMSI_attach,
5721 ts_SGsAP_LAI('901'H, '70'H, 2342)));
5722 SGsAP.send(lur);
5723
5724 /* Respond to SGsAP-RESET-INDICATION from VLR */
5725 alt {
5726 [] SGsAP.receive(tr_SGsAP_RESET_IND_VLR(vlr_name)); {
5727 SGsAP.send(valueof(ts_SGsAP_RESET_ACK_MME(mme_name)));
5728 setverdict(pass);
5729 }
5730 [] SGsAP.receive {
5731 setverdict(fail, "Received unexpected message on SGs");
5732 }
5733 }
5734
5735 f_sleep(1.0);
5736 setverdict(pass);
5737}
5738testcase TC_sgsap_vlr_failure() runs on MTC_CT {
5739 var BSC_ConnHdlrPars pars;
5740 var BSC_ConnHdlr vc_conn;
5741 f_init(1, true, false);
5742 pars := f_init_pars(11811, true, false);
5743 vc_conn := f_start_handler_with_pars(refers(f_tc_sgsap_vlr_failure), pars);
5744 vc_conn.done;
5745}
5746
Harald Welte4263c522018-12-06 11:56:27 +01005747/* SGs TODO:
5748 * LU attempt for IMSI without NAM_PS in HLR
5749 * LU attempt with AUTH FAIL due to invalid RES/SRES
5750 * LU attempt with no response from HLR (VLR should timeout + LU REJ)
5751 * LU attempt with new TMSI but without TMSI REALL CMPL baco to VLR
5752 * implicit IMSI detach from EPS
5753 * implicit IMSI detach from non-EPS
5754 * MM INFO
5755 *
5756 */
Harald Weltef6dd64d2017-11-19 12:09:51 +01005757
Neels Hofmeyr0ac63152019-05-07 01:20:17 +02005758private function f_tc_ho_inter_bsc_unknown_cell(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
5759 f_init_handler(pars);
5760 var CallParameters cpars := valueof(t_CallParams('12345'H, 0));
Neels Hofmeyr0ac63152019-05-07 01:20:17 +02005761
5762 f_perform_lu();
5763 f_mo_call_establish(cpars);
5764
5765 f_sleep(1.0);
5766
5767 var myBSSMAP_Cause cause_val := GSM0808_CAUSE_BETTER_CELL;
5768 var BssmapCause cause := enum2int(cause_val);
5769
5770 var template BSSMAP_FIELD_CellIdentificationList cil;
5771 cil := { cIl_LAI := { ts_BSSMAP_CI_LAI('023'H, '42'H, 999) } };
5772
5773 BSSAP.send(ts_BSSMAP_HandoverRequired(cause, cil));
5774 BSSAP.receive(tr_BSSMAP_HandoverRequiredReject);
5775
5776 f_call_hangup(cpars, true);
5777}
5778testcase TC_ho_inter_bsc_unknown_cell() runs on MTC_CT {
5779 var BSC_ConnHdlr vc_conn;
5780 f_init();
5781
5782 vc_conn := f_start_handler(refers(f_tc_ho_inter_bsc_unknown_cell), 53);
5783 vc_conn.done;
5784}
5785
5786private altstep as_mgcp_ack_all_mdcx(CallParameters cpars) runs on BSC_ConnHdlr {
5787 var MgcpCommand mgcp_cmd;
5788 [] MGCP.receive(tr_MDCX) -> value mgcp_cmd {
Vadim Yanitskiy42fae8a2024-03-27 02:06:55 +07005789 var charstring conn_id;
5790 f_mgcp_find_param_entry(mgcp_cmd.params, "I", conn_id);
5791 var SDP_Message sdp := valueof(ts_SDP(cpars.mgw_conn_2.mgw_rtp_ip, cpars.mgw_conn_2.mgw_rtp_ip,
5792 hex2str(cpars.mgcp_call_id), "42",
5793 cpars.mgw_conn_2.mgw_rtp_port,
5794 { int2str(cpars.rtp_payload_type) },
5795 { valueof(ts_SDP_rtpmap(cpars.rtp_payload_type,
5796 cpars.rtp_sdp_format)),
5797 valueof(ts_SDP_ptime(20)) }));
5798 MGCP.send(ts_MDCX_ACK(mgcp_cmd.line.trans_id, str2hex(conn_id), sdp));
5799 repeat;
5800 }
Neels Hofmeyr0ac63152019-05-07 01:20:17 +02005801}
5802
Neels Hofmeyr8853afb2021-07-27 22:34:15 +02005803private altstep as_mgcp_ack_all_dlcx(CallParameters cpars) runs on BSC_ConnHdlr {
5804 var MgcpCommand mgcp_cmd;
5805 [] MGCP.receive(tr_DLCX(?)) -> value mgcp_cmd {
5806 MGCP.send(ts_DLCX_ACK2(mgcp_cmd.line.trans_id));
5807 repeat;
5808 }
5809}
5810
Neels Hofmeyr0ac63152019-05-07 01:20:17 +02005811private function f_tc_ho_inter_bsc0(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Pau Espin Pedrol833174e2020-09-03 16:46:02 +02005812 var CallParameters cpars;
5813
5814 cpars := valueof(t_CallParams('12345'H, 0));
5815 if (pars.use_ipv6) {
5816 cpars.mgw_conn_1.mgw_rtp_ip := "::1";
5817 cpars.mgw_conn_2.mgw_rtp_ip := "::2";
5818 cpars.bss_rtp_ip := "::3";
5819 }
Oliver Smith44424db2023-08-22 13:54:09 +02005820 if (pars.use_csd) {
5821 f_set_cpars_csd(cpars, "BS25T", '1'B, GSM48_BCAP_TR_TRANSP, GSM48_BCAP_UR_4800);
5822 }
Neels Hofmeyr0ac63152019-05-07 01:20:17 +02005823
5824 f_init_handler(pars);
5825
5826 f_vty_transceive(MSCVTY, "configure terminal");
5827 f_vty_transceive(MSCVTY, "msc");
5828 f_vty_transceive(MSCVTY, "neighbor a cgi 262 42 23 42 ran-pc 0.24.1");
Neels Hofmeyr2822d072021-06-23 03:20:32 +02005829 f_vty_transceive(MSCVTY, "neighbor a cgi 023 42 5 6 ran-pc 0.24.2");
Neels Hofmeyr0ac63152019-05-07 01:20:17 +02005830 f_vty_transceive(MSCVTY, "exit");
5831 f_vty_transceive(MSCVTY, "exit");
5832
5833 f_perform_lu();
5834 f_mo_call_establish(cpars);
5835
Vadim Yanitskiy5f1018f2024-03-27 14:05:27 +07005836 /* Remember the last n_sd (sequence number),
5837 * we will need it when the other BSS hands over back to us. */
5838 var N_Sd_Array last_n_sd := f_bssmap_last_n_sd();
5839
Neels Hofmeyr0ac63152019-05-07 01:20:17 +02005840 f_sleep(1.0);
5841
5842 var default ack_mdcx := activate(as_mgcp_ack_all_mdcx(cpars));
5843
5844 var myBSSMAP_Cause cause_val := GSM0808_CAUSE_BETTER_CELL;
5845 var BssmapCause cause := enum2int(cause_val);
5846
5847 var template BSSMAP_FIELD_CellIdentificationList cil;
Neels Hofmeyr2822d072021-06-23 03:20:32 +02005848 cil := { cIl_CGI := { ts_BSSMAP_CI_CGI('023'H, '42'H, 5, 6) } };
Neels Hofmeyr0ac63152019-05-07 01:20:17 +02005849
5850 /* old BSS sends Handover Required */
5851 BSSAP.send(ts_BSSMAP_HandoverRequired(cause, cil));
5852
5853 /* Now the action goes on in f_tc_ho_inter_bsc1() */
5854
5855 /* MSC forwards the RR Handover Command to old BSS */
5856 var PDU_BSSAP ho_command;
5857 BSSAP.receive(tr_BSSMAP_HandoverCommand) -> value ho_command;
5858
5859 log("GOT HandoverCommand", ho_command);
5860
5861 BSSAP.receive(tr_BSSMAP_HandoverSucceeded);
5862
5863 /* f_tc_ho_inter_bsc1() completes Handover, then expecting a Clear here. */
5864 f_expect_clear();
5865
5866 log("FIRST inter-BSC Handover done");
5867
5868
5869 /* ------------------------ */
5870
5871 /* Ok, that went well, now the other BSC is handovering back here --
5872 * from now on this here is the new BSS. */
Andreas Eversberge5a6ef12023-07-28 10:45:20 +02005873 f_create_bssmap_exp_n_connect(193);
Neels Hofmeyr0ac63152019-05-07 01:20:17 +02005874
Neels Hofmeyr0d841d92021-06-21 22:27:21 +02005875 var template BSSMAP_IE_EncryptionInformation encryptionInformation;
5876 var template BSSMAP_IE_ChosenEncryptionAlgorithm chosenEncryptionAlgorithm;
5877 var template BSSMAP_IE_KC128 kC128;
5878 var OCT1 a5_perm_alg;
5879 f_get_expected_encryption(encryptionInformation, chosenEncryptionAlgorithm, kC128, a5_perm_alg);
Vadim Yanitskiyc5fcb892022-08-04 04:06:07 +07005880 var template PDU_BSSAP expect_ho_request := tr_BSSMAP_HandoverRequest(encryptionInformation,
5881 chosenEncryptionAlgorithm,
5882 kC128, codecList := ?);
Neels Hofmeyr0ac63152019-05-07 01:20:17 +02005883 var PDU_BSSAP ho_request;
Neels Hofmeyr0d841d92021-06-21 22:27:21 +02005884 alt {
5885 [] BSSAP.receive(expect_ho_request);
5886 [] BSSAP.receive(tr_BSSMAP_HandoverRequest) -> value ho_request {
5887 log("Error: Wrong handoverRequest received. Expected: ", expect_ho_request,
5888 " got ", ho_request);
5889 setverdict(fail, "Wrong handoverRequest received");
5890 mtc.stop;
5891 }
5892 }
Neels Hofmeyr0ac63152019-05-07 01:20:17 +02005893
5894 /* new BSS composes a RR Handover Command */
5895 var PDU_ML3_NW_MS rr_ho_cmd := valueof(ts_RR_HandoverCommand);
5896 var octetstring rr_ho_cmd_enc := enc_PDU_ML3_NW_MS(rr_ho_cmd);
Pau Espin Pedrol833174e2020-09-03 16:46:02 +02005897 var BSSMAP_IE_AoIP_TransportLayerAddress tla tla :=
5898 valueof(f_ts_BSSMAP_IE_AoIP_TLA(cpars.bss_rtp_ip, cpars.bss_rtp_port));
Neels Hofmeyr0ac63152019-05-07 01:20:17 +02005899 BSSAP.send(ts_BSSMAP_HandoverRequestAcknowledge(rr_ho_cmd_enc, lengthof(rr_ho_cmd_enc),
5900 tla, ts_BSSMAP_IE_SpeechCodec({ts_CodecFR})));
5901
5902 /* Now f_tc_ho_inter_bsc1() expects HandoverCommand */
5903
5904 f_sleep(0.5);
5905
5906 /* Notify that the MS is now over here */
5907
5908 BSSAP.send(ts_BSSMAP_HandoverDetect);
5909 f_sleep(0.1);
5910 BSSAP.send(ts_BSSMAP_HandoverComplete);
5911
5912 f_sleep(3.0);
5913
5914 deactivate(ack_mdcx);
5915
Vadim Yanitskiy5f1018f2024-03-27 14:05:27 +07005916 /* Use the n_sd (sequence number) we stored before the first handover.
5917 * Otherwise the MSC may treat our DTAP messages as duplicates and discard them. */
Neels Hofmeyr0ac63152019-05-07 01:20:17 +02005918 f_bssmap_continue_after_n_sd(last_n_sd);
5919
Vadim Yanitskiy5f1018f2024-03-27 14:05:27 +07005920 var default ccrel := activate(as_optional_cc_rel(cpars, true));
Neels Hofmeyr0ac63152019-05-07 01:20:17 +02005921 f_call_hangup(cpars, true);
5922 f_sleep(1.0);
5923 deactivate(ccrel);
5924
5925 setverdict(pass);
5926}
5927private function f_tc_ho_inter_bsc1(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Pau Espin Pedrol833174e2020-09-03 16:46:02 +02005928 var charstring bss_rtp_ip;
5929 if (pars.use_ipv6) {
5930 bss_rtp_ip := "::8";
5931 } else {
5932 bss_rtp_ip := "1.2.3.4";
5933 }
Neels Hofmeyr0ac63152019-05-07 01:20:17 +02005934 f_init_handler(pars);
Andreas Eversberge5a6ef12023-07-28 10:45:20 +02005935 f_create_bssmap_exp_n_connect(194);
Neels Hofmeyr0ac63152019-05-07 01:20:17 +02005936
Neels Hofmeyr0d841d92021-06-21 22:27:21 +02005937 var template BSSMAP_IE_EncryptionInformation encryptionInformation;
5938 var template BSSMAP_IE_ChosenEncryptionAlgorithm chosenEncryptionAlgorithm;
5939 var template BSSMAP_IE_KC128 kC128;
5940 var OCT1 a5_perm_alg;
5941 f_get_expected_encryption(encryptionInformation, chosenEncryptionAlgorithm, kC128, a5_perm_alg);
Vadim Yanitskiyc5fcb892022-08-04 04:06:07 +07005942 var template PDU_BSSAP expect_ho_request := tr_BSSMAP_HandoverRequest(encryptionInformation,
5943 chosenEncryptionAlgorithm,
5944 kC128, codecList := ?);
Neels Hofmeyr0ac63152019-05-07 01:20:17 +02005945 var PDU_BSSAP ho_request;
Neels Hofmeyr0d841d92021-06-21 22:27:21 +02005946 alt {
5947 [] BSSAP.receive(expect_ho_request);
5948 [] BSSAP.receive(tr_BSSMAP_HandoverRequest) -> value ho_request {
5949 log("Error: Wrong handoverRequest received. Expected: ", expect_ho_request,
5950 " got ", ho_request);
5951 setverdict(fail, "Wrong handoverRequest received");
5952 mtc.stop;
5953 }
5954 }
Neels Hofmeyr0ac63152019-05-07 01:20:17 +02005955 /* new BSS composes a RR Handover Command */
5956 var PDU_ML3_NW_MS rr_ho_cmd := valueof(ts_RR_HandoverCommand);
5957 var octetstring rr_ho_cmd_enc := enc_PDU_ML3_NW_MS(rr_ho_cmd);
Pau Espin Pedrol833174e2020-09-03 16:46:02 +02005958 var BSSMAP_IE_AoIP_TransportLayerAddress tla :=
5959 valueof(f_ts_BSSMAP_IE_AoIP_TLA(bss_rtp_ip, 2342));
Neels Hofmeyr0ac63152019-05-07 01:20:17 +02005960 BSSAP.send(ts_BSSMAP_HandoverRequestAcknowledge(rr_ho_cmd_enc, lengthof(rr_ho_cmd_enc),
5961 tla, ts_BSSMAP_IE_SpeechCodec({ts_CodecFR})));
5962
5963 /* Now f_tc_ho_inter_bsc0() expects HandoverCommand */
5964
5965 f_sleep(0.5);
5966
5967 /* Notify that the MS is now over here */
5968
5969 BSSAP.send(ts_BSSMAP_HandoverDetect);
5970 f_sleep(0.1);
5971 BSSAP.send(ts_BSSMAP_HandoverComplete);
5972
5973 f_sleep(3.0);
5974
5975 /* Now I'd like to f_call_hangup() but we don't know any cpars here. So
5976 * ... handover back to the first BSC :P */
5977
5978 var myBSSMAP_Cause cause_val := GSM0808_CAUSE_BETTER_CELL;
5979 var BssmapCause cause := enum2int(cause_val);
5980
5981 var template BSSMAP_FIELD_CellIdentificationList cil;
Neels Hofmeyr2822d072021-06-23 03:20:32 +02005982 cil := { cIl_CGI := { ts_BSSMAP_CI_CGI('262'H, '42'H, 23, 42) } };
Neels Hofmeyr0ac63152019-05-07 01:20:17 +02005983
5984 /* old BSS sends Handover Required */
5985 BSSAP.send(ts_BSSMAP_HandoverRequired(cause, cil));
5986
5987 /* Now the action goes on in f_tc_ho_inter_bsc0() */
5988
5989 /* MSC forwards the RR Handover Command to old BSS */
5990 var PDU_BSSAP ho_command;
5991 BSSAP.receive(tr_BSSMAP_HandoverCommand) -> value ho_command;
5992
5993 log("GOT HandoverCommand", ho_command);
5994
5995 BSSAP.receive(tr_BSSMAP_HandoverSucceeded);
5996
5997 /* f_tc_ho_inter_bsc1() completes Handover, then expecting a Clear here. */
5998 f_expect_clear();
5999 setverdict(pass);
6000}
Oliver Smith44424db2023-08-22 13:54:09 +02006001function f_tc_ho_inter_bsc_main(boolean use_ipv6 := false, integer a5_n := 0, boolean use_csd := false) runs on MTC_CT {
Neels Hofmeyr0ac63152019-05-07 01:20:17 +02006002 var BSC_ConnHdlr vc_conn0;
6003 var BSC_ConnHdlr vc_conn1;
6004 f_init(2);
6005
6006 var BSC_ConnHdlrPars pars0 := f_init_pars(53);
Pau Espin Pedrol833174e2020-09-03 16:46:02 +02006007 pars0.use_ipv6 := use_ipv6;
Oliver Smith44424db2023-08-22 13:54:09 +02006008 pars0.use_csd := use_csd;
Neels Hofmeyr0d841d92021-06-21 22:27:21 +02006009 pars0.net.expect_ciph := a5_n > 0;
6010 pars0.net.expect_auth := pars0.net.expect_ciph;
6011 pars0.net.kc_support := bit2oct('00000001'B << a5_n);
6012 pars0.cm2.classmarkInformationType2_oct5.a5_3 := '1'B;
6013 pars0.cm2.classmarkInformationType2_oct5.a5_2 := '0'B;
6014 pars0.cm2.classmarkInformationType2_oct5.cm3 := '1'B;
6015 pars0.cm3 := valueof(ts_CM3_default);
6016 pars0.use_umts_aka := true;
6017 pars0.vec := f_gen_auth_vec_3g();
6018 pars0.vec_keep := true;
Neels Hofmeyr60122f82021-07-28 17:59:38 +02006019 pars0.ran_idx := 0;
Neels Hofmeyr0d841d92021-06-21 22:27:21 +02006020
Neels Hofmeyr0ac63152019-05-07 01:20:17 +02006021 var BSC_ConnHdlrPars pars1 := f_init_pars(53);
Pau Espin Pedrol833174e2020-09-03 16:46:02 +02006022 pars1.use_ipv6 := use_ipv6;
Oliver Smith44424db2023-08-22 13:54:09 +02006023 pars1.use_csd := use_csd;
Neels Hofmeyr0d841d92021-06-21 22:27:21 +02006024 pars1.net.expect_ciph := pars0.net.expect_ciph;
6025 pars1.net.expect_auth := pars0.net.expect_ciph;
6026 pars1.net.kc_support := bit2oct('00000001'B << a5_n);
6027 pars1.cm2 := pars0.cm2;
6028 pars1.cm3 := pars0.cm3;
6029 pars1.use_umts_aka := true;
6030 /* Both components need the same auth vector info because we expect f_tc_ho_inter_bsc0's ciphering key to be
6031 * identical to the one that shows up in f_tc_ho_inter_bsc1. Can only do that by feeding in a vector to both
6032 * components and then not overwriting it in BSC_ConnectionHandler. */
6033 pars1.vec := pars0.vec;
6034 pars1.vec_keep := true;
Neels Hofmeyr60122f82021-07-28 17:59:38 +02006035 pars1.ran_idx := 1;
Neels Hofmeyr0d841d92021-06-21 22:27:21 +02006036
6037 if (a5_n > 0) {
6038 f_vty_config(MSCVTY, "network", "authentication required");
6039 }
6040 f_vty_config(MSCVTY, "network", "encryption a5 " & int2str(a5_n));
Neels Hofmeyr0ac63152019-05-07 01:20:17 +02006041
Neels Hofmeyr60122f82021-07-28 17:59:38 +02006042 vc_conn0 := f_start_handler_with_pars(refers(f_tc_ho_inter_bsc0), pars0);
6043 vc_conn1 := f_start_handler_with_pars(refers(f_tc_ho_inter_bsc1), pars1);
Neels Hofmeyr0ac63152019-05-07 01:20:17 +02006044 vc_conn0.done;
6045 vc_conn1.done;
6046}
Pau Espin Pedrol833174e2020-09-03 16:46:02 +02006047testcase TC_ho_inter_bsc() runs on MTC_CT {
Neels Hofmeyr0d841d92021-06-21 22:27:21 +02006048 f_tc_ho_inter_bsc_main(false, a5_n := 0);
6049}
6050testcase TC_ho_inter_bsc_a5_1() runs on MTC_CT {
6051 f_tc_ho_inter_bsc_main(false, a5_n := 1);
6052}
6053testcase TC_ho_inter_bsc_a5_3() runs on MTC_CT {
6054 f_tc_ho_inter_bsc_main(false, a5_n := 3);
6055}
6056testcase TC_ho_inter_bsc_a5_4() runs on MTC_CT {
6057 f_tc_ho_inter_bsc_main(false, a5_n := 4);
Pau Espin Pedrol833174e2020-09-03 16:46:02 +02006058}
6059testcase TC_ho_inter_bsc_ipv6() runs on MTC_CT {
6060 f_tc_ho_inter_bsc_main(true);
6061}
Oliver Smith44424db2023-08-22 13:54:09 +02006062testcase TC_ho_inter_bsc_csd() runs on MTC_CT {
6063 f_tc_ho_inter_bsc_main(use_csd := true);
6064}
Neels Hofmeyr0ac63152019-05-07 01:20:17 +02006065
6066function f_ML3_patch_seq_nr_MS_NW(in uint2_t seq_nr, inout octetstring enc_l3) {
6067 log("MS_NW patching N(SD)=", seq_nr, " into dtap ", enc_l3);
6068 enc_l3[2] := (enc_l3[2] and4b '3f'O) or4b bit2oct(int2bit(seq_nr, 8) << 6);
6069 log("MS_NW patched enc_l3: ", enc_l3);
6070}
6071
6072private function f_tc_ho_inter_msc_out(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Pau Espin Pedrol833174e2020-09-03 16:46:02 +02006073 var CallParameters cpars;
Neels Hofmeyr906af102021-07-01 12:08:35 +02006074 var PDU_BSSAP ho_request;
Pau Espin Pedrol833174e2020-09-03 16:46:02 +02006075
6076 cpars := valueof(t_CallParams('12345'H, 0));
6077 if (pars.use_ipv6) {
Oliver Smithbe922912023-08-23 15:27:37 +02006078 cpars.mgw_conn_1.mgw_rtp_ip := "::1";
6079 cpars.mgw_conn_2.mgw_rtp_ip := "::2";
6080 cpars.bss_rtp_ip := "::3";
Pau Espin Pedrol833174e2020-09-03 16:46:02 +02006081 }
Oliver Smithcaa36c92023-08-23 15:30:33 +02006082 if (pars.use_csd) {
6083 f_set_cpars_csd(cpars, "BS25T", '1'B, GSM48_BCAP_TR_TRANSP, GSM48_BCAP_UR_4800);
6084 }
Neels Hofmeyr0ac63152019-05-07 01:20:17 +02006085 var hexstring ho_number := f_gen_msisdn(99999);
6086
6087 f_init_handler(pars);
6088
6089 f_create_mncc_expect(hex2str(ho_number));
6090
6091 f_vty_transceive(MSCVTY, "configure terminal");
6092 f_vty_transceive(MSCVTY, "msc");
6093 f_vty_transceive(MSCVTY, "neighbor a cgi 017 017 1 1 msc-ipa-name msc-017-017-1");
6094 f_vty_transceive(MSCVTY, "exit");
6095 f_vty_transceive(MSCVTY, "exit");
6096
6097 f_perform_lu();
6098 f_mo_call_establish(cpars);
6099
6100 f_sleep(1.0);
6101
6102 var default ack_mdcx := activate(as_mgcp_ack_all_mdcx(cpars));
6103
6104 var myBSSMAP_Cause cause_val := GSM0808_CAUSE_BETTER_CELL;
6105 var BssmapCause cause := enum2int(cause_val);
6106
6107 var template BSSMAP_FIELD_CellIdentificationList cil;
Neels Hofmeyr36ebc332021-06-23 03:20:32 +02006108 cil := { cIl_CGI := { ts_BSSMAP_CI_CGI('017'H, '017'H, 1, 1) } };
Neels Hofmeyr0ac63152019-05-07 01:20:17 +02006109
6110 /* old BSS sends Handover Required */
6111 BSSAP.send(ts_BSSMAP_HandoverRequired(cause, cil));
6112
6113 /* The target cell 017-017 LAC 1 is configured to be a remote MSC of name "msc-017-017-1".
6114 * This MSC tries to reach the other MSC via GSUP. */
6115
Neels Hofmeyr666d39a2021-06-21 22:27:21 +02006116 var template BSSMAP_IE_EncryptionInformation encryptionInformation;
6117 var template BSSMAP_IE_ChosenEncryptionAlgorithm chosenEncryptionAlgorithm;
6118 var template BSSMAP_IE_KC128 kC128;
6119 var OCT1 a5_perm_alg;
6120 f_get_expected_encryption(encryptionInformation, chosenEncryptionAlgorithm, kC128, a5_perm_alg);
Vadim Yanitskiyc5fcb892022-08-04 04:06:07 +07006121 var template PDU_BSSAP expect_ho_request := tr_BSSMAP_HandoverRequest(encryptionInformation,
6122 chosenEncryptionAlgorithm,
6123 kC128, codecList := ?);
Neels Hofmeyr666d39a2021-06-21 22:27:21 +02006124
Neels Hofmeyr0ac63152019-05-07 01:20:17 +02006125 var octetstring remote_msc_name := '6D73632D3031372D3031372D3100'O; /* "msc-017-017-1\0" as octetstring */
6126 var GSUP_PDU prep_ho_req;
Neels Hofmeyr666d39a2021-06-21 22:27:21 +02006127 alt {
6128 [] GSUP.receive(tr_GSUP_E_AN_APDU(OSMO_GSUP_MSGT_E_PREPARE_HANDOVER_REQUEST,
6129 pars.imsi, destination_name := remote_msc_name,
Neels Hofmeyrec2e1f72021-07-02 02:08:32 +02006130 an_apdu := t_GSUP_AN_APDU(OSMO_GSUP_AN_PROTO_48006, pdu := ?))) -> value prep_ho_req;
Neels Hofmeyr666d39a2021-06-21 22:27:21 +02006131 [] GSUP.receive(tr_GSUP_E_AN_APDU(OSMO_GSUP_MSGT_E_PREPARE_HANDOVER_REQUEST)) {
6132 setverdict(fail, "Wrong OSMO_GSUP_MSGT_E_PREPARE_HANDOVER_REQUEST message received");
6133 mtc.stop;
6134 }
6135 }
Neels Hofmeyr0ac63152019-05-07 01:20:17 +02006136
6137 var GSUP_IeValue source_name_ie;
6138 f_gsup_find_ie(prep_ho_req, OSMO_GSUP_SOURCE_NAME_IE, source_name_ie);
6139 var octetstring local_msc_name := source_name_ie.source_name;
6140
Neels Hofmeyrec2e1f72021-07-02 02:08:32 +02006141 /* Decode PDU to 1) match with expect_ho_request and 2) to forward the actual chosen encryption algorithm. */
Neels Hofmeyr906af102021-07-01 12:08:35 +02006142 var GSUP_IeValue an_apdu_ie;
6143 f_gsup_find_ie(prep_ho_req, OSMO_GSUP_AN_APDU_IE, an_apdu_ie);
6144 ho_request := dec_PDU_BSSAP(an_apdu_ie.an_apdu.pdu);
Neels Hofmeyrec2e1f72021-07-02 02:08:32 +02006145 if (not match(ho_request, expect_ho_request)) {
6146 setverdict(fail, "Wrong PDU in OSMO_GSUP_MSGT_E_PREPARE_HANDOVER_REQUEST message received");
6147 mtc.stop;
6148 }
Neels Hofmeyr906af102021-07-01 12:08:35 +02006149
Neels Hofmeyr0ac63152019-05-07 01:20:17 +02006150 /* Remote MSC has figured out its BSC and signals success */
6151 var PDU_ML3_NW_MS rr_ho_cmd := valueof(ts_RR_HandoverCommand);
6152 var octetstring rr_ho_cmd_enc := enc_PDU_ML3_NW_MS(rr_ho_cmd);
6153 var PDU_BSSAP ho_req_ack := valueof(ts_BSSMAP_HandoverRequestAcknowledge(rr_ho_cmd_enc, lengthof(rr_ho_cmd_enc),
Neels Hofmeyr906af102021-07-01 12:08:35 +02006154 aoIPTransportLayer := omit,
6155 speechCodec := ts_BSSMAP_IE_SpeechCodec({ts_CodecFR}),
6156 chosenEncryptionAlgorithm := ho_request.pdu.bssmap.handoverRequest.chosenEncryptionAlgorithm));
Neels Hofmeyr0ac63152019-05-07 01:20:17 +02006157 GSUP.send(ts_GSUP_E_PrepareHandoverResult(
6158 pars.imsi,
6159 ho_number,
6160 remote_msc_name, local_msc_name,
6161 valueof(t_GSUP_AN_APDU(OSMO_GSUP_AN_PROTO_48006, enc_PDU_BSSAP(ho_req_ack)))));
6162
6163 /* MSC forwards the RR Handover Command to old BSS */
6164 BSSAP.receive(tr_BSSMAP_HandoverCommand);
6165
6166 /* The MS shows up at remote new BSS */
6167
6168 GSUP.send(ts_GSUP_E_AN_APDU(OSMO_GSUP_MSGT_E_PROCESS_ACCESS_SIGNALLING_REQUEST,
6169 pars.imsi, remote_msc_name, local_msc_name,
6170 valueof(t_GSUP_AN_APDU(OSMO_GSUP_AN_PROTO_48006,
6171 enc_PDU_BSSAP(valueof(ts_BSSMAP_HandoverDetect))))));
6172 BSSAP.receive(tr_BSSMAP_HandoverSucceeded);
6173 f_sleep(0.1);
6174
6175 /* Save the MS sequence counters for use on the other connection */
6176 var N_Sd_Array last_n_sd := f_bssmap_last_n_sd();
6177
6178 GSUP.send(ts_GSUP_E_AN_APDU(OSMO_GSUP_MSGT_E_SEND_END_SIGNAL_REQUEST,
6179 pars.imsi, remote_msc_name, local_msc_name,
6180 valueof(t_GSUP_AN_APDU(OSMO_GSUP_AN_PROTO_48006,
6181 enc_PDU_BSSAP(valueof(ts_BSSMAP_HandoverComplete))))));
6182
6183 /* The local BSS conn clears, all communication goes via remote MSC now */
6184 f_expect_clear();
6185
6186 /**********************************/
6187 /* Play through some signalling across the inter-MSC link.
6188 * This is a copy of f_tc_lu_and_mo_ussd_single_request() translated into GSUP AN-APDUs. */
6189
6190 if (false) {
6191 var template OCTN facility_req := f_USSD_FACILITY_IE_INVOKE(
6192 invoke_id := 5, /* Phone may not start from 0 or 1 */
6193 op_code := SS_OP_CODE_PROCESS_USS_REQ,
6194 ussd_string := "*#100#"
6195 );
6196
6197 var template OCTN facility_rsp := f_USSD_FACILITY_IE_RETURN_RESULT(
6198 invoke_id := 5, /* InvokeID shall be the same for both REQ and RSP */
6199 op_code := SS_OP_CODE_PROCESS_USS_REQ,
6200 ussd_string := "Your extension is " & hex2str(g_pars.msisdn) & "\r"
6201 )
6202
6203 /* Compose a new SS/REGISTER message with request */
6204 var template (value) PDU_ML3_MS_NW ussd_req := ts_ML3_MO_SS_REGISTER(
6205 tid := 1, /* We just need a single transaction */
6206 ti_flag := c_TIF_ORIG, /* Sent from the side that originates the TI */
6207 facility := valueof(facility_req)
6208 );
6209 var PDU_ML3_MS_NW ussd_req_v := valueof(ussd_req);
6210
6211 /* Compose SS/RELEASE_COMPLETE template with expected response */
6212 var template PDU_ML3_NW_MS ussd_rsp := tr_ML3_MT_SS_RELEASE_COMPLETE(
6213 tid := 1, /* Response should arrive within the same transaction */
6214 ti_flag := c_TIF_REPL, /* Sent to the side that originates the TI */
6215 facility := valueof(facility_rsp)
6216 );
6217
6218 /* Compose expected MSC -> HLR message */
6219 var template GSUP_PDU gsup_req := tr_GSUP_PROC_SS_REQ(
6220 imsi := g_pars.imsi,
6221 state := OSMO_GSUP_SESSION_STATE_BEGIN,
6222 ss := valueof(facility_req)
6223 );
6224
6225 /* To be used for sending response with correct session ID */
6226 var GSUP_PDU gsup_req_complete;
6227
6228 /* Request own number */
6229 /* From remote MSC instead of BSSAP directly */
6230 /* Patch the correct N_SD value into the message. */
6231 var octetstring l3_enc := enc_PDU_ML3_MS_NW(ussd_req_v);
6232 var RAN_Emulation.ConnectionData cd;
6233 f_ML3_patch_seq_nr_MS_NW(f_next_n_sd(last_n_sd, f_ML3_n_sd_idx(ussd_req_v)), l3_enc);
6234 GSUP.send(ts_GSUP_E_AN_APDU(OSMO_GSUP_MSGT_E_PROCESS_ACCESS_SIGNALLING_REQUEST,
6235 pars.imsi, remote_msc_name, local_msc_name,
6236 valueof(t_GSUP_AN_APDU(OSMO_GSUP_AN_PROTO_48006,
6237 enc_PDU_BSSAP(valueof(ts_BSSAP_DTAP(l3_enc)))
6238 ))
6239 ));
6240
6241 /* Expect GSUP message containing the SS payload */
6242 gsup_req_complete := f_expect_gsup_msg(gsup_req);
6243
6244 /* Compose the response from HLR using received session ID */
6245 var template GSUP_PDU gsup_rsp := ts_GSUP_PROC_SS_REQ(
6246 imsi := g_pars.imsi,
6247 sid := gsup_req_complete.ies[1].val.session_id,
6248 state := OSMO_GSUP_SESSION_STATE_END,
6249 ss := valueof(facility_rsp)
6250 );
6251
6252 /* Finally, HLR terminates the session */
6253 GSUP.send(gsup_rsp);
6254
6255 /* The USSD response goes out to remote MSC, on GSUP E instead of BSSAP */
6256 var GSUP_PDU gsup_ussd_rsp;
6257 GSUP.receive(tr_GSUP_E_AN_APDU(OSMO_GSUP_MSGT_E_FORWARD_ACCESS_SIGNALLING_REQUEST,
6258 pars.imsi, destination_name := remote_msc_name)) -> value gsup_ussd_rsp;
6259
6260 var GSUP_IeValue an_apdu;
6261 if (not f_gsup_find_ie(gsup_ussd_rsp, OSMO_GSUP_AN_APDU_IE, an_apdu)) {
6262 setverdict(fail, "No AN-APDU in received GSUP message. Expected USSD response in DTAP, got", gsup_ussd_rsp);
6263 mtc.stop;
6264 }
6265 var PDU_BSSAP bssap_dtap_mt := dec_PDU_BSSAP(an_apdu.an_apdu.pdu);
6266 var PDU_ML3_NW_MS dtap_mt := dec_PDU_ML3_NW_MS(bssap_dtap_mt.pdu.dtap);
6267 log("Expecting", ussd_rsp);
6268 log("Got", dtap_mt);
6269 if (not match(dtap_mt, ussd_rsp)) {
6270 setverdict(fail, "Unexpected GSUP message. Expected USSD response in DTAP, got", gsup_ussd_rsp);
6271 mtc.stop;
6272 }
6273 }
6274 /**********************************/
6275
6276
6277 /* inter-MSC handover back to the first MSC */
Andreas Eversberge5a6ef12023-07-28 10:45:20 +02006278 f_create_bssmap_exp_n_connect(193);
Neels Hofmeyr0ac63152019-05-07 01:20:17 +02006279 cil := { cIl_CGI := { ts_BSSMAP_CI_CGI('262'H, '42'H, 23, 42) } };
6280
6281 /* old BSS sends Handover Required, via inter-MSC E link: like
6282 * BSSAP.send(ts_BSSMAP_HandoverRequired(cause, cil));
6283 * but via GSUP */
6284 GSUP.send(ts_GSUP_E_AN_APDU(OSMO_GSUP_MSGT_E_PREPARE_SUBSEQUENT_HANDOVER_REQUEST,
6285 pars.imsi, remote_msc_name, local_msc_name,
6286 valueof(t_GSUP_AN_APDU(OSMO_GSUP_AN_PROTO_48006,
6287 enc_PDU_BSSAP(valueof(ts_BSSMAP_HandoverRequired(cause, cil)))
6288 ))
6289 ));
6290
6291 /* MSC asks local BSS to prepare Handover to it */
Neels Hofmeyr666d39a2021-06-21 22:27:21 +02006292 f_get_expected_encryption(encryptionInformation, chosenEncryptionAlgorithm, kC128, a5_perm_alg);
Vadim Yanitskiyc5fcb892022-08-04 04:06:07 +07006293 expect_ho_request := tr_BSSMAP_HandoverRequest(encryptionInformation,
6294 chosenEncryptionAlgorithm,
6295 kC128, codecList := ?);
Neels Hofmeyr666d39a2021-06-21 22:27:21 +02006296 alt {
Neels Hofmeyr906af102021-07-01 12:08:35 +02006297 [] BSSAP.receive(expect_ho_request) -> value ho_request;
Neels Hofmeyr666d39a2021-06-21 22:27:21 +02006298 [] BSSAP.receive(tr_BSSMAP_HandoverRequest) -> value ho_request {
6299 log("Error: Wrong handoverRequest received. Expected: ", expect_ho_request,
6300 " got ", ho_request);
6301 setverdict(fail, "Wrong handoverRequest received");
6302 mtc.stop;
6303 }
6304 }
Neels Hofmeyr0ac63152019-05-07 01:20:17 +02006305
6306 /* Make sure the new BSSAP conn continues with the correct N_SD sequence numbers */
6307 f_bssmap_continue_after_n_sd(last_n_sd);
6308
6309 /* new BSS composes a RR Handover Command */
6310 rr_ho_cmd := valueof(ts_RR_HandoverCommand);
6311 rr_ho_cmd_enc := enc_PDU_ML3_NW_MS(rr_ho_cmd);
Pau Espin Pedrol833174e2020-09-03 16:46:02 +02006312 var BSSMAP_IE_AoIP_TransportLayerAddress tla :=
6313 valueof(f_ts_BSSMAP_IE_AoIP_TLA(cpars.bss_rtp_ip, cpars.bss_rtp_port));
Neels Hofmeyr0ac63152019-05-07 01:20:17 +02006314 BSSAP.send(ts_BSSMAP_HandoverRequestAcknowledge(rr_ho_cmd_enc, lengthof(rr_ho_cmd_enc),
Neels Hofmeyr906af102021-07-01 12:08:35 +02006315 tla, ts_BSSMAP_IE_SpeechCodec({ts_CodecFR}),
6316 chosenEncryptionAlgorithm := ho_request.pdu.bssmap.handoverRequest.chosenEncryptionAlgorithm));
Neels Hofmeyr0ac63152019-05-07 01:20:17 +02006317
6318 /* HandoverCommand goes out via remote MSC-I */
6319 var GSUP_PDU prep_subsq_ho_res;
6320 GSUP.receive(tr_GSUP_E_AN_APDU(OSMO_GSUP_MSGT_E_PREPARE_SUBSEQUENT_HANDOVER_RESULT,
6321 pars.imsi, destination_name := remote_msc_name)) -> value prep_subsq_ho_res;
6322
6323 /* MS shows up at the local BSS */
6324 BSSAP.send(ts_BSSMAP_HandoverDetect);
6325 f_sleep(0.1);
6326 BSSAP.send(ts_BSSMAP_HandoverComplete);
6327
6328 /* Handover Succeeded message */
6329 GSUP.receive(tr_GSUP_E_AN_APDU(OSMO_GSUP_MSGT_E_FORWARD_ACCESS_SIGNALLING_REQUEST,
6330 pars.imsi, destination_name := remote_msc_name));
6331
6332 /* MS has handovered to here, Clear Command goes out via remote MSC-I -- in form of a GSUP Close. */
6333 GSUP.receive(tr_GSUP_E_NO_PDU(OSMO_GSUP_MSGT_E_CLOSE,
6334 pars.imsi, destination_name := remote_msc_name));
6335
6336 /* Handover ends successfully. Call goes on for a little longer and then we hang up. */
6337
6338 f_sleep(1.0);
6339 deactivate(ack_mdcx);
6340
6341 /* FIXME: the inter-MSC call has put a number of MNCC messages in the queue, which above code should expect and
6342 * clear out. The f_call_hangup() expects an MNCC_REL_IND, so, for the time being, just clear the MNCC messages
6343 * before starting the call hangup. Instead of this, the individual messages should be tested for above. */
6344 MNCC.clear;
6345
6346 var default ccrel := activate(as_optional_cc_rel(cpars, true));
6347 f_call_hangup(cpars, true);
6348 f_sleep(1.0);
6349 deactivate(ccrel);
6350
6351 setverdict(pass);
6352}
Neels Hofmeyr666d39a2021-06-21 22:27:21 +02006353function f_tc_ho_inter_msc_out_a5(integer a5_n) runs on MTC_CT {
Neels Hofmeyr0ac63152019-05-07 01:20:17 +02006354 var BSC_ConnHdlr vc_conn;
6355 f_init(1);
6356
6357 var BSC_ConnHdlrPars pars := f_init_pars(54);
Neels Hofmeyr666d39a2021-06-21 22:27:21 +02006358 pars.net.expect_ciph := a5_n > 0;
6359 pars.net.expect_auth := pars.net.expect_ciph;
6360 pars.net.kc_support := bit2oct('00000001'B << a5_n);
6361 pars.cm2.classmarkInformationType2_oct5.a5_3 := '1'B;
6362 pars.cm2.classmarkInformationType2_oct5.a5_2 := '0'B;
6363 pars.cm2.classmarkInformationType2_oct5.cm3 := '1'B;
6364 pars.cm3 := valueof(ts_CM3_default);
6365 pars.use_umts_aka := true;
6366
6367 if (a5_n > 0) {
6368 f_vty_config(MSCVTY, "network", "authentication required");
6369 }
6370 f_vty_config(MSCVTY, "network", "encryption a5 " & int2str(a5_n));
Neels Hofmeyr0ac63152019-05-07 01:20:17 +02006371
Neels Hofmeyr60122f82021-07-28 17:59:38 +02006372 vc_conn := f_start_handler_with_pars(refers(f_tc_ho_inter_msc_out), pars);
Neels Hofmeyr0ac63152019-05-07 01:20:17 +02006373 vc_conn.done;
6374}
Neels Hofmeyr666d39a2021-06-21 22:27:21 +02006375testcase TC_ho_inter_msc_out() runs on MTC_CT {
6376 f_tc_ho_inter_msc_out_a5(0);
6377}
6378testcase TC_ho_inter_msc_out_a5_1() runs on MTC_CT {
6379 f_tc_ho_inter_msc_out_a5(1);
6380}
6381testcase TC_ho_inter_msc_out_a5_3() runs on MTC_CT {
6382 f_tc_ho_inter_msc_out_a5(3);
6383}
6384testcase TC_ho_inter_msc_out_a5_4() runs on MTC_CT {
6385 f_tc_ho_inter_msc_out_a5(4);
6386}
Pau Espin Pedrol833174e2020-09-03 16:46:02 +02006387testcase TC_ho_inter_msc_out_ipv6() runs on MTC_CT {
6388 var BSC_ConnHdlr vc_conn;
6389 f_init(1);
6390
6391 var BSC_ConnHdlrPars pars := f_init_pars(54);
6392 pars.use_ipv6 := true;
6393
Neels Hofmeyr60122f82021-07-28 17:59:38 +02006394 vc_conn := f_start_handler_with_pars(refers(f_tc_ho_inter_msc_out), pars);
Pau Espin Pedrol833174e2020-09-03 16:46:02 +02006395 vc_conn.done;
6396}
Oliver Smithcaa36c92023-08-23 15:30:33 +02006397testcase TC_ho_inter_msc_out_csd() runs on MTC_CT {
6398 var BSC_ConnHdlr vc_conn;
6399 f_init(1);
6400
6401 var BSC_ConnHdlrPars pars := f_init_pars(54);
6402 pars.use_csd := true;
6403
6404 vc_conn := f_start_handler_with_pars(refers(f_tc_ho_inter_msc_out), pars);
6405 vc_conn.done;
6406}
Neels Hofmeyr0ac63152019-05-07 01:20:17 +02006407
Oliver Smith1d118ff2019-07-03 10:57:35 +02006408private function f_tc_lu_imsi_auth_tmsi_check_imei(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
6409 pars.net.expect_auth := true;
6410 pars.net.expect_imei := true;
6411 f_init_handler(pars);
6412 f_perform_lu();
6413}
6414testcase TC_lu_imsi_auth_tmsi_check_imei() runs on MTC_CT {
6415 var BSC_ConnHdlr vc_conn;
6416 f_init();
6417 f_vty_config(MSCVTY, "network", "authentication required");
6418 f_vty_config(MSCVTY, "msc", "check-imei-rqd 1");
6419
6420 vc_conn := f_start_handler(refers(f_tc_lu_imsi_auth_tmsi_check_imei), 5);
6421 vc_conn.done;
6422}
6423
6424private function f_tc_lu_imsi_auth3g_tmsi_check_imei(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
6425 pars.net.expect_auth := true;
6426 pars.use_umts_aka := true;
6427 pars.net.expect_imei := true;
6428 f_init_handler(pars);
6429 f_perform_lu();
6430}
6431testcase TC_lu_imsi_auth3g_tmsi_check_imei() runs on MTC_CT {
6432 var BSC_ConnHdlr vc_conn;
6433 f_init();
6434 f_vty_config(MSCVTY, "network", "authentication required");
6435 f_vty_config(MSCVTY, "msc", "check-imei-rqd 1");
6436
6437 vc_conn := f_start_handler(refers(f_tc_lu_imsi_auth3g_tmsi_check_imei), 5);
6438 vc_conn.done;
6439}
6440
6441private function f_tc_lu_imsi_noauth_tmsi_check_imei(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
6442 pars.net.expect_imei := true;
6443 f_init_handler(pars);
6444 f_perform_lu();
6445}
6446testcase TC_lu_imsi_noauth_tmsi_check_imei() runs on MTC_CT {
6447 var BSC_ConnHdlr vc_conn;
6448 f_init();
6449 f_vty_config(MSCVTY, "msc", "check-imei-rqd 1");
6450
6451 vc_conn := f_start_handler(refers(f_tc_lu_imsi_noauth_tmsi_check_imei), 5);
6452 vc_conn.done;
6453}
6454
6455private function f_tc_lu_imsi_noauth_notmsi_check_imei(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
6456 pars.net.expect_tmsi := false;
6457 pars.net.expect_imei := true;
6458 f_init_handler(pars);
6459 f_perform_lu();
6460}
6461testcase TC_lu_imsi_noauth_notmsi_check_imei() runs on MTC_CT {
6462 var BSC_ConnHdlr vc_conn;
6463 f_init();
6464 f_vty_config(MSCVTY, "msc", "no assign-tmsi");
6465 f_vty_config(MSCVTY, "msc", "check-imei-rqd 1");
6466
6467 vc_conn := f_start_handler(refers(f_tc_lu_imsi_noauth_notmsi_check_imei), 5);
6468 vc_conn.done;
6469}
6470
6471private function f_tc_lu_imsi_auth_tmsi_check_imei_nack(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
6472 var PDU_ML3_MS_NW l3_lu;
Oliver Smith1d118ff2019-07-03 10:57:35 +02006473
6474 pars.net.expect_auth := true;
6475 pars.net.expect_imei := true;
6476 pars.net.check_imei_result := OSMO_GSUP_IMEI_RESULT_NACK;
6477 f_init_handler(pars);
6478
6479 /* Cannot use f_perform_lu() as we expect a reject */
6480 l3_lu := f_build_lu_imsi(g_pars.imsi)
6481 f_create_gsup_expect(hex2str(g_pars.imsi));
6482 f_bssap_compl_l3(l3_lu);
6483 BSSAP.send(ts_BSSMAP_ClassmarkUpd(g_pars.cm2, g_pars.cm3));
6484
6485 f_mm_common();
6486 f_msc_lu_hlr();
6487 f_mm_imei();
Oliver Smith91bfa1c2019-07-19 15:01:15 +02006488 f_expect_lu_reject();
Eric Wild85cc1612022-03-30 01:44:29 +02006489 f_expect_clear(verify_vlr_cell_id:=false);
Oliver Smith1d118ff2019-07-03 10:57:35 +02006490}
6491testcase TC_lu_imsi_auth_tmsi_check_imei_nack() runs on MTC_CT {
6492 var BSC_ConnHdlr vc_conn;
6493 f_init();
6494 f_vty_config(MSCVTY, "network", "authentication required");
6495 f_vty_config(MSCVTY, "msc", "check-imei-rqd 1");
6496
6497 vc_conn := f_start_handler(refers(f_tc_lu_imsi_auth_tmsi_check_imei_nack), 5);
6498 vc_conn.done;
6499}
6500
6501private function f_tc_lu_imsi_auth_tmsi_check_imei_err(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
6502 var PDU_ML3_MS_NW l3_lu;
Oliver Smith1d118ff2019-07-03 10:57:35 +02006503
6504 pars.net.expect_auth := true;
6505 pars.net.expect_imei := true;
6506 pars.net.check_imei_error := true;
6507 f_init_handler(pars);
6508
6509 /* Cannot use f_perform_lu() as we expect a reject */
6510 l3_lu := f_build_lu_imsi(g_pars.imsi)
6511 f_create_gsup_expect(hex2str(g_pars.imsi));
6512 f_bssap_compl_l3(l3_lu);
6513 BSSAP.send(ts_BSSMAP_ClassmarkUpd(g_pars.cm2, g_pars.cm3));
6514
6515 f_mm_common();
6516 f_msc_lu_hlr();
6517 f_mm_imei();
Oliver Smith91bfa1c2019-07-19 15:01:15 +02006518 f_expect_lu_reject();
Eric Wild85cc1612022-03-30 01:44:29 +02006519 f_expect_clear(verify_vlr_cell_id:=false);
Oliver Smith1d118ff2019-07-03 10:57:35 +02006520}
6521testcase TC_lu_imsi_auth_tmsi_check_imei_err() runs on MTC_CT {
6522 var BSC_ConnHdlr vc_conn;
6523 f_init();
6524 f_vty_config(MSCVTY, "network", "authentication required");
6525 f_vty_config(MSCVTY, "msc", "check-imei-rqd 1");
6526
6527 vc_conn := f_start_handler(refers(f_tc_lu_imsi_auth_tmsi_check_imei_err), 5);
6528 vc_conn.done;
6529}
6530
6531private function f_tc_lu_imsi_auth_tmsi_check_imei_early(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
6532 pars.net.expect_auth := true;
6533 pars.net.expect_imei_early := true;
6534 f_init_handler(pars);
6535 f_perform_lu();
6536}
6537testcase TC_lu_imsi_auth_tmsi_check_imei_early() runs on MTC_CT {
6538 var BSC_ConnHdlr vc_conn;
6539 f_init();
6540 f_vty_config(MSCVTY, "network", "authentication required");
6541 f_vty_config(MSCVTY, "msc", "check-imei-rqd early");
6542
6543 vc_conn := f_start_handler(refers(f_tc_lu_imsi_auth_tmsi_check_imei_early), 5);
6544 vc_conn.done;
6545}
6546
6547private function f_tc_lu_imsi_auth3g_tmsi_check_imei_early(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
6548 pars.net.expect_auth := true;
6549 pars.use_umts_aka := true;
6550 pars.net.expect_imei_early := true;
6551 f_init_handler(pars);
6552 f_perform_lu();
6553}
6554testcase TC_lu_imsi_auth3g_tmsi_check_imei_early() runs on MTC_CT {
6555 var BSC_ConnHdlr vc_conn;
6556 f_init();
6557 f_vty_config(MSCVTY, "network", "authentication required");
6558 f_vty_config(MSCVTY, "msc", "check-imei-rqd early");
6559
6560 vc_conn := f_start_handler(refers(f_tc_lu_imsi_auth3g_tmsi_check_imei_early), 5);
6561 vc_conn.done;
6562}
6563
6564private function f_tc_lu_imsi_noauth_tmsi_check_imei_early(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
6565 pars.net.expect_imei_early := true;
6566 f_init_handler(pars);
6567 f_perform_lu();
6568}
6569testcase TC_lu_imsi_noauth_tmsi_check_imei_early() runs on MTC_CT {
6570 var BSC_ConnHdlr vc_conn;
6571 f_init();
6572 f_vty_config(MSCVTY, "msc", "check-imei-rqd early");
6573
6574 vc_conn := f_start_handler(refers(f_tc_lu_imsi_noauth_tmsi_check_imei_early), 5);
6575 vc_conn.done;
6576}
6577
6578private function f_tc_lu_imsi_noauth_notmsi_check_imei_early(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
6579 pars.net.expect_tmsi := false;
6580 pars.net.expect_imei_early := true;
6581 f_init_handler(pars);
6582 f_perform_lu();
6583}
6584testcase TC_lu_imsi_noauth_notmsi_check_imei_early() runs on MTC_CT {
6585 var BSC_ConnHdlr vc_conn;
6586 f_init();
6587 f_vty_config(MSCVTY, "msc", "no assign-tmsi");
6588 f_vty_config(MSCVTY, "msc", "check-imei-rqd early");
6589
6590 vc_conn := f_start_handler(refers(f_tc_lu_imsi_noauth_notmsi_check_imei_early), 5);
6591 vc_conn.done;
6592}
6593
6594private function f_tc_lu_imsi_auth_tmsi_check_imei_early_nack(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
6595 var PDU_ML3_MS_NW l3_lu;
Oliver Smith1d118ff2019-07-03 10:57:35 +02006596
6597 pars.net.expect_auth := true;
6598 pars.net.expect_imei_early := true;
6599 pars.net.check_imei_result := OSMO_GSUP_IMEI_RESULT_NACK;
6600 f_init_handler(pars);
6601
6602 /* Cannot use f_perform_lu() as we expect a reject */
6603 l3_lu := f_build_lu_imsi(g_pars.imsi)
6604 f_create_gsup_expect(hex2str(g_pars.imsi));
6605 f_bssap_compl_l3(l3_lu);
6606 BSSAP.send(ts_BSSMAP_ClassmarkUpd(g_pars.cm2, g_pars.cm3));
6607
6608 f_mm_imei_early();
Oliver Smith91bfa1c2019-07-19 15:01:15 +02006609 f_expect_lu_reject();
Eric Wild85cc1612022-03-30 01:44:29 +02006610 f_expect_clear(verify_vlr_cell_id:=false);
Oliver Smith1d118ff2019-07-03 10:57:35 +02006611}
6612testcase TC_lu_imsi_auth_tmsi_check_imei_early_nack() runs on MTC_CT {
6613 var BSC_ConnHdlr vc_conn;
6614 f_init();
6615 f_vty_config(MSCVTY, "network", "authentication required");
6616 f_vty_config(MSCVTY, "msc", "check-imei-rqd early");
6617
6618 vc_conn := f_start_handler(refers(f_tc_lu_imsi_auth_tmsi_check_imei_early_nack), 5);
6619 vc_conn.done;
6620}
6621
6622private function f_tc_lu_imsi_auth_tmsi_check_imei_early_err(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
6623 var PDU_ML3_MS_NW l3_lu;
Oliver Smith1d118ff2019-07-03 10:57:35 +02006624
6625 pars.net.expect_auth := true;
6626 pars.net.expect_imei_early := true;
6627 pars.net.check_imei_error := true;
6628 f_init_handler(pars);
6629
6630 /* Cannot use f_perform_lu() as we expect a reject */
6631 l3_lu := f_build_lu_imsi(g_pars.imsi)
6632 f_create_gsup_expect(hex2str(g_pars.imsi));
6633 f_bssap_compl_l3(l3_lu);
6634 BSSAP.send(ts_BSSMAP_ClassmarkUpd(g_pars.cm2, g_pars.cm3));
6635
6636 f_mm_imei_early();
Oliver Smith91bfa1c2019-07-19 15:01:15 +02006637 f_expect_lu_reject();
Eric Wild85cc1612022-03-30 01:44:29 +02006638 f_expect_clear(verify_vlr_cell_id:=false);
Oliver Smith1d118ff2019-07-03 10:57:35 +02006639}
6640testcase TC_lu_imsi_auth_tmsi_check_imei_early_err() runs on MTC_CT {
6641 var BSC_ConnHdlr vc_conn;
6642 f_init();
6643 f_vty_config(MSCVTY, "network", "authentication required");
6644 f_vty_config(MSCVTY, "msc", "check-imei-rqd early");
6645
6646 vc_conn := f_start_handler(refers(f_tc_lu_imsi_auth_tmsi_check_imei_early_err), 5);
6647 vc_conn.done;
6648}
Neels Hofmeyr0ac63152019-05-07 01:20:17 +02006649
Neels Hofmeyr8df69622019-11-02 19:16:03 +01006650friend function f_tc_invalid_mgcp_crash(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
6651 f_init_handler(pars);
6652 var CallParameters cpars := valueof(t_CallParams('12345'H, 0));
6653
6654 /* Set invalid IP address so that osmo-msc discards the rtp_stream and MGCP endpoint FSM instances in the middle
6655 * of successful MGCP response dispatch. If things aren't safeguarded, the on_success() in osmo_mgcpc_ep_fsm
6656 * will cause a use-after-free after that event dispatch. */
6657 cpars.mgw_conn_1.mgw_rtp_ip := "0.0.0.0";
6658 cpars.mgw_conn_2.mgw_rtp_ip := "0.0.0.0";
6659 cpars.rtp_sdp_format := "FOO/8000";
6660 cpars.expect_release := true;
6661
6662 f_perform_lu();
6663 f_mo_call_establish(cpars);
6664}
6665testcase TC_invalid_mgcp_crash() runs on MTC_CT {
6666 var BSC_ConnHdlr vc_conn;
6667 f_init();
6668
6669 vc_conn := f_start_handler(refers(f_tc_invalid_mgcp_crash), 7);
6670 vc_conn.done;
6671}
6672
Vadim Yanitskiy3c88c352024-04-02 21:21:51 +07006673/* Test how the MSC handles a malformed MM IDENTITY RESPONSE with no identity. */
Vadim Yanitskiyeddebaa2019-12-28 17:45:34 +01006674friend function f_tc_mm_id_resp_no_identity(charstring id, BSC_ConnHdlrPars pars)
6675runs on BSC_ConnHdlr {
Vadim Yanitskiyeddebaa2019-12-28 17:45:34 +01006676 f_init_handler(pars);
6677
Vadim Yanitskiyeddebaa2019-12-28 17:45:34 +01006678 /* Initiate Location Updating using an unknown TMSI */
Vadim Yanitskiy3c88c352024-04-02 21:21:51 +07006679 f_bssap_compl_l3(f_build_lu_tmsi('FFFFFFFF'O));
Vadim Yanitskiyeddebaa2019-12-28 17:45:34 +01006680
6681 /* Expect an Identity Request, send response with no identity */
6682 BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_MM_ID_Req(CM_ID_TYPE_IMSI)));
6683 BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_MM_ID_Rsp({
6684 lengthIndicator := 1,
6685 mobileIdentityV := {
6686 typeOfIdentity := '000'B,
6687 oddEvenInd_identity := {
6688 no_identity := {
6689 oddevenIndicator := '0'B,
6690 fillerDigits := '00000'H
6691 }
6692 }
6693 }
6694 })));
6695
Vadim Yanitskiy3c88c352024-04-02 21:21:51 +07006696 /* XXX: Current osmo-msc does not react on bad/malformed MM IDENTITY RESPONSE immediately.
6697 * It instead relies on expiry of timer X1, which is set to 5.0 seconds by default. This
6698 * is not good (DoS vector) and should ideally be fixed, but for now just work it around. */
6699 f_expect_lu_reject(Tval := 5.0 + 1.0);
Vadim Yanitskiyeddebaa2019-12-28 17:45:34 +01006700 f_expect_clear();
6701}
6702testcase TC_mm_id_resp_no_identity() runs on MTC_CT {
6703 var BSC_ConnHdlr vc_conn;
6704
6705 f_init();
6706
Neels Hofmeyr4e18ccc2020-06-24 19:08:17 +02006707 vc_conn := f_start_handler(refers(f_tc_mm_id_resp_no_identity), 7, verify_cell_id := false);
Vadim Yanitskiyeddebaa2019-12-28 17:45:34 +01006708 vc_conn.done;
6709}
6710
Vadim Yanitskiy25219062020-01-21 01:41:33 +07006711/* Verify the case when T3212 expires during Paging procedure, just before the receipt
6712 * of Paging Response. This used to provoke a NULL-pointer dereference in old versions
6713 * of OsmoMSC, but apparently the bug has been fixed, and we're safe now. */
6714friend function f_tc_lu_and_expire_while_paging(charstring id, BSC_ConnHdlrPars pars)
6715runs on BSC_ConnHdlr {
6716 var charstring imsi := hex2str(pars.imsi);
6717
6718 f_init_handler(pars);
6719
6720 /* Perform location update */
6721 f_perform_lu();
6722
6723 f_ran_register_imsi(g_pars.imsi, g_pars.tmsi);
6724 f_create_gsup_expect(hex2str(g_pars.imsi));
6725
6726 /* Initiate paging procedure from the VTY */
6727 f_vty_transceive(MSCVTY, "subscriber imsi " & imsi & " paging");
6728 f_expect_paging();
6729
6730 /* Emulate T3212 expiration during paging (we don't want to wait, right?) */
6731 f_vty_transceive(MSCVTY, "subscriber imsi " & imsi & " expire");
6732
6733 /* MS sends PAGING RESPONSE, *old* OsmoMSC crashes here... */
6734 f_establish_fully(EST_TYPE_PAG_RESP);
6735
6736 /* The recent OsmoMSC keeps subscriber in its VLR unless the Paging is completed.
6737 * In this case we do not send anything and just wait for a Clear Command. */
Neels Hofmeyr4e18ccc2020-06-24 19:08:17 +02006738 f_expect_clear(verify_vlr_cell_id := false);
Vadim Yanitskiy25219062020-01-21 01:41:33 +07006739}
6740testcase TC_lu_and_expire_while_paging() runs on MTC_CT {
6741 var BSC_ConnHdlr vc_conn;
6742
6743 f_init();
6744
6745 vc_conn := f_start_handler(refers(f_tc_lu_and_expire_while_paging), 7);
6746 vc_conn.done;
6747}
6748
Neels Hofmeyr3ad76a42022-08-09 02:57:49 +02006749private altstep as_mncc_rx_rtp_create(CallParameters cpars) runs on BSC_ConnHdlr {
6750 [] MNCC.receive(tr_MNCC_RTP_CREATE(cpars.mncc_callref));
6751}
6752
Neels Hofmeyr4f099b42021-07-27 03:45:26 +02006753const charstring REEST_LOST_CONNECTION := "REEST_LOST_CONNECTION";
6754const charstring REEST_CLEARED := "REEST_CLEARED";
6755
6756friend function f_tc_call_re_establishment_1(charstring id, BSC_ConnHdlrPars pars)
6757 runs on BSC_ConnHdlr {
6758 f_init_handler(pars, t_guard := 30.0);
6759
6760 f_perform_lu();
6761
6762 var CallParameters cpars := valueof(t_CallParams('12345'H, 0));
6763 f_mo_call_establish(cpars);
6764 f_sleep(3.0);
6765 COORD.send(REEST_LOST_CONNECTION);
6766 COORD.send(cpars);
6767 f_expect_clear(verify_vlr_cell_id := false);
6768 COORD.send(REEST_CLEARED);
6769}
6770
6771friend function f_tc_call_re_establishment_2(charstring id, BSC_ConnHdlrPars pars)
6772 runs on BSC_ConnHdlr {
6773 f_init_handler(pars, t_guard := 30.0);
6774 var CallParameters cpars;
6775
6776 COORD.receive(REEST_LOST_CONNECTION);
6777 COORD.receive(tr_CallParams) -> value cpars;
6778
6779 f_gsup_change_connhdlr(hex2str(g_pars.imsi));
6780 f_create_smpp_expect(hex2str(pars.msisdn));
6781
6782 /* The MS has lost the first channel and decides to show up on a new conn (on a nearby neighbor cell) to ask for
6783 * CM Re-Establishment. Send a Complete Layer 3 to osmo-msc with a CM Re-Establishment Request. */
6784 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
6785 var PDU_ML3_MS_NW l3_info := valueof(ts_CM_REESTABL_REQ(mi));
6786 f_cl3_or_initial_ue(l3_info);
6787
6788 /* At this point the other test component should receive the Clear Command for the first A connection. */
6789
6790 /* This new connection continues with Authentication... */
6791 f_mm_common();
6792
6793 /* ...and with Assignment of a voice channel. */
6794 var template BSSMAP_IE_AoIP_TransportLayerAddress tla_ass :=
Neels Hofmeyr02d513e2022-07-25 22:07:24 +02006795 (f_tr_BSSMAP_IE_AoIP_TLA(cpars.mgw_conn_1.mgw_rtp_ip, ?),
6796 f_tr_BSSMAP_IE_AoIP_TLA(cpars.mgw_conn_2.mgw_rtp_ip, ?));
Neels Hofmeyr4f099b42021-07-27 03:45:26 +02006797 BSSAP.receive(tr_BSSMAP_AssignmentReq(omit, tla_ass));
6798 /* By this Assignment Request, the CM Re-Establishment Request is implicitly accepted. */
6799
6800 /* Send Assignment Complete from BSC */
6801 var template BSSMAP_IE_AoIP_TransportLayerAddress tla;
6802 tla := f_ts_BSSMAP_IE_AoIP_TLA(cpars.bss_rtp_ip, cpars.bss_rtp_port);
6803 var BSSMAP_IE_SpeechCodec codec;
6804 codec := valueof(ts_BSSMAP_IE_SpeechCodec({ts_CodecFR}));
6805
6806 /* Make really sure the other component is done with its MGCP */
6807 COORD.receive(REEST_CLEARED);
6808
6809 /* Transfer state for this call over to this test component so we can resolve MNCC and MGCP in this function. */
6810 f_mncc_change_connhdlr(cpars.mncc_callref);
6811 f_mgcp_change_connhdlr(cpars.mgcp_ep);
6812
6813 /* osmo-msc may redirect the MGW endpoint to the newly allocated channel.
6814 * Apparently osmo-msc currently also sends an MDCX to the CN side, just repeating the same configuration that
6815 * is already in use. This test accepts any number of or even lack of MDCX. */
6816 var default ack_mdcx := activate(as_mgcp_ack_all_mdcx(cpars));
Neels Hofmeyr3ad76a42022-08-09 02:57:49 +02006817 var default optional_rtp_create := activate(as_mncc_rx_rtp_create(cpars));
Neels Hofmeyr4f099b42021-07-27 03:45:26 +02006818
6819 BSSAP.send(ts_BSSMAP_AssignmentComplete(omit, tla, codec));
Neels Hofmeyr3ad76a42022-08-09 02:57:49 +02006820
Neels Hofmeyr4f099b42021-07-27 03:45:26 +02006821 /* The call has been fully re-established.
6822 * Let a bit of time pass before hanging up, for everything to settle. */
6823 f_sleep(3.0);
6824
Neels Hofmeyr3ad76a42022-08-09 02:57:49 +02006825 deactivate(optional_rtp_create);
Neels Hofmeyr4f099b42021-07-27 03:45:26 +02006826 deactivate(ack_mdcx);
6827
6828 /* Hang up the call and clear the new, second A connection */
6829 var default ack_dlcx := activate(as_mgcp_ack_all_dlcx(cpars));
6830
6831 /* CC release. This is the proper MS initiated release sequence as shown by
6832 * https://git.osmocom.org/osmo-msc/tree/doc/sequence_charts/voice_call_full.msc?id=e53ecde83e4fb2470209e818e9ad76a2d6a19190
6833 * f_call_hangup() seems a bit mixed up, so here a "proper" sequence. Fix of f_call_hangup() pending. */
6834 BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_CC_DISC(cpars.transaction_id, '0'B, '0000000'B)));
6835 MNCC.receive(tr_MNCC_DISC_ind(cpars.mncc_callref));
6836 MNCC.send(ts_MNCC_REL_req(cpars.mncc_callref, valueof(ts_MNCC_cause(23))));
6837 BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_CC_RELEASE(cpars.transaction_id)));
6838 BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_CC_REL_COMPL(cpars.transaction_id, '0'B)));
6839 MNCC.receive(tr_MNCC_REL_cnf(cpars.mncc_callref, cause := *));
6840
6841 /* BSSAP clear */
6842 interleave {
6843 [] BSSAP.receive(tr_BSSMAP_ClearCommand) {
6844 BSSAP.send(ts_BSSMAP_ClearComplete);
6845 }
6846 [] BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_IND);
6847 }
6848
6849 f_sleep(1.0);
6850 deactivate(ack_dlcx);
6851}
6852
6853testcase TC_call_re_establishment() runs on MTC_CT {
6854 var BSC_ConnHdlr vc_conn1;
6855 var BSC_ConnHdlr vc_conn2;
6856 f_init();
6857
6858 var BSC_ConnHdlrPars pars1 := f_init_pars(91);
6859 var BSC_ConnHdlrPars pars2 := pars1;
6860
6861 vc_conn1 := f_start_handler_create(pars1);
6862 vc_conn2 := f_start_handler_create(pars2);
6863 connect(vc_conn1:COORD, vc_conn2:COORD);
6864 f_start_handler_run(vc_conn1, refers(f_tc_call_re_establishment_1), pars1);
6865 f_start_handler_run(vc_conn2, refers(f_tc_call_re_establishment_2), pars2);
6866 vc_conn1.done;
6867 vc_conn2.done;
6868}
6869
Neels Hofmeyra9b2dcf2021-07-28 00:57:58 +02006870testcase TC_call_re_establishment_auth() runs on MTC_CT {
6871 var BSC_ConnHdlr vc_conn1;
6872 var BSC_ConnHdlr vc_conn2;
6873 f_init();
6874
6875 f_vty_config(MSCVTY, "network", "authentication required");
6876
6877 var BSC_ConnHdlrPars pars1 := f_init_pars(92);
6878 pars1.net.expect_auth := true;
6879 var BSC_ConnHdlrPars pars2 := pars1;
6880
6881 vc_conn1 := f_start_handler_create(pars1);
6882 vc_conn2 := f_start_handler_create(pars2);
6883 connect(vc_conn1:COORD, vc_conn2:COORD);
6884 f_start_handler_run(vc_conn1, refers(f_tc_call_re_establishment_1), pars1);
6885 f_start_handler_run(vc_conn2, refers(f_tc_call_re_establishment_2), pars2);
6886 vc_conn1.done;
6887 vc_conn2.done;
6888}
6889
Neels Hofmeyr48e4d7d2021-07-28 00:57:58 +02006890testcase TC_call_re_establishment_ciph() runs on MTC_CT {
6891 var BSC_ConnHdlr vc_conn1;
6892 var BSC_ConnHdlr vc_conn2;
6893 f_init();
6894
6895 f_vty_config(MSCVTY, "network", "authentication required");
6896 f_vty_config(MSCVTY, "network", "encryption a5 3");
6897
6898 var BSC_ConnHdlrPars pars1 := f_init_pars(92);
6899 pars1.net.expect_auth := true;
6900 pars1.net.expect_ciph := true;
6901 pars1.net.kc_support := '08'O; /* A5/3 only */
6902 var BSC_ConnHdlrPars pars2 := pars1;
6903
6904 vc_conn1 := f_start_handler_create(pars1);
6905 vc_conn2 := f_start_handler_create(pars2);
6906 connect(vc_conn1:COORD, vc_conn2:COORD);
6907 f_start_handler_run(vc_conn1, refers(f_tc_call_re_establishment_1), pars1);
6908 f_start_handler_run(vc_conn2, refers(f_tc_call_re_establishment_2), pars2);
6909 vc_conn1.done;
6910 vc_conn2.done;
6911}
6912
Neels Hofmeyr07ea7f22022-05-05 01:39:26 +02006913/* Establish a conn with a valid Mobile Identity. Then send a CM Service Request containing a mismatching Mobile
6914 * Identity on the same conn. Caused a crash, see OS#5532. */
6915friend function f_tc_cm_serv_wrong_mi(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
6916 f_init_handler(pars);
6917
6918 /* Set up a fully identified conn */
6919 f_perform_lu();
6920 f_establish_fully();
6921
6922 /* CM Serv Req with mismatching Mobile Identity */
6923 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(f_gen_imsi(99999))); /* ensure it is different from below*/
6924 BSSAP.send(ts_PDU_DTAP_MO(ts_CM_SERV_REQ(CM_TYPE_MO_SMS, mi)));
6925 BSSAP.receive(tr_PDU_DTAP_MT(tr_CM_SERV_REJ));
6926
6927 /* Cancel the first CM Service from f_establish_fully() */
6928 BSSAP.send(ts_BSSMAP_ClearRequest(0));
6929
6930 f_expect_clear();
6931}
6932testcase TC_cm_serv_wrong_mi() runs on MTC_CT {
6933 var BSC_ConnHdlr vc_conn;
6934 f_init();
6935 vc_conn := f_start_handler(refers(f_tc_cm_serv_wrong_mi), 94);
6936 vc_conn.done;
6937}
6938
Neels Hofmeyre860fc42022-10-05 01:15:54 +02006939/* a5 0 a5 0 a5 0 3 a5 0 3 a5 3 a5 3
6940 * HLR has auth info no yes no yes no yes
6941 *
6942 * test case index [0] [1] [2] [3] [4] [5]
6943 * authentication optional No auth No auth attempt auth, auth reject auth
6944 * (%) fall back to +ciph +ciph
6945 * no-auth
6946 *
6947 * [6] [7] [8] [9] [10] [11]
6948 * authentication mandatory reject auth reject auth reject auth
6949 * only +ciph +ciph
6950 *
6951 * (%): Arguably, when HLR has auth info, the MSC should use it. Current behavior of osmo-msc is to not attempt auth at
6952 * all. Related: OS#4830.
6953 */
6954type record of BSC_ConnHdlrNetworkPars rof_netpars;
6955
6956const rof_netpars auth_options_testcases := {
6957 {
6958 /* [0] auth optional, encr a5 0: no-auth" */
6959 kc_support := '01'O,
6960 net_config := { "authentication optional",
6961 "encryption a5 0" },
6962 expect_attach_success := true,
6963 expect_tmsi := true,
6964 expect_auth_attempt := false,
6965 hlr_has_auth_info := false,
6966 expect_auth := false,
6967 expect_ciph := false,
6968 expect_imei := false,
6969 expect_imei_early := false,
6970 check_imei_result := OSMO_GSUP_IMEI_RESULT_ACK,
6971 check_imei_error := false
6972 },
6973 {
6974 /* [1] auth optional, encr a5 0, HLR HAS auth info: no-auth */
6975 kc_support := '01'O,
6976 net_config := { "authentication optional",
6977 "encryption a5 0" },
6978 expect_attach_success := true,
6979 expect_tmsi := true,
6980 expect_auth_attempt := false,
6981 hlr_has_auth_info := true,
6982 expect_auth := false,
6983 expect_ciph := false,
6984 expect_imei := false,
6985 expect_imei_early := false,
6986 check_imei_result := OSMO_GSUP_IMEI_RESULT_ACK,
6987 check_imei_error := false
6988 },
6989 {
6990 /* [2] auth optional, encr a5 0 3, HLR has NO Auth Info: Fall back to no-auth" */
6991 kc_support := '09'O,
6992 net_config := { "authentication optional",
6993 "encryption a5 0 3" },
6994 expect_attach_success := true,
6995 expect_tmsi := true,
6996 expect_auth_attempt := true,
6997 hlr_has_auth_info := false,
6998 expect_auth := false,
6999 expect_ciph := false,
7000 expect_imei := false,
7001 expect_imei_early := false,
7002 check_imei_result := OSMO_GSUP_IMEI_RESULT_ACK,
7003 check_imei_error := false
7004 },
7005 {
7006 /* [3] auth optional, encr a5 0 3, HLR HAS Auth Info: Use A5/3 */
7007 kc_support := '09'O,
7008 net_config := { "authentication optional",
7009 "encryption a5 0 3" },
7010 expect_attach_success := true,
7011 expect_tmsi := true,
7012 expect_auth_attempt := true,
7013 hlr_has_auth_info := true,
7014 expect_auth := true,
7015 expect_ciph := true,
7016 expect_imei := false,
7017 expect_imei_early := false,
7018 check_imei_result := OSMO_GSUP_IMEI_RESULT_ACK,
7019 check_imei_error := false
7020 },
7021 {
7022 /* [4] auth optional, encr a5 3, HLR has NO Auth Info: reject.
7023 * Auth is required implicitly because ciph is required. */
7024 kc_support := '08'O,
7025 net_config := { "authentication optional",
7026 "encryption a5 3" },
7027 expect_attach_success := false,
7028 expect_tmsi := true,
7029 expect_auth_attempt := true,
7030 hlr_has_auth_info := false,
7031 expect_auth := false,
7032 expect_ciph := false,
7033 expect_imei := false,
7034 expect_imei_early := false,
7035 check_imei_result := OSMO_GSUP_IMEI_RESULT_ACK,
7036 check_imei_error := false
7037 },
7038 {
7039 /* [5] auth optional, encr a5 3, HLR HAS Auth Info: auth + ciph.
7040 * Auth is required implicitly because ciph is required. */
7041 kc_support := '08'O,
7042 net_config := { "authentication optional",
7043 "encryption a5 3" },
7044 expect_attach_success := true,
7045 expect_tmsi := true,
7046 expect_auth_attempt := true,
7047 hlr_has_auth_info := true,
7048 expect_auth := true,
7049 expect_ciph := true,
7050 expect_imei := false,
7051 expect_imei_early := false,
7052 check_imei_result := OSMO_GSUP_IMEI_RESULT_ACK,
7053 check_imei_error := false
7054 },
7055
7056 /* Same as above, but with 'authentication required' */
7057
7058 {
7059 /* [6] auth required, encr a5 0, HLR has NO auth info: reject */
7060 kc_support := '01'O,
7061 net_config := { "authentication required",
7062 "encryption a5 0" },
7063 expect_attach_success := false,
7064 expect_tmsi := true,
7065 expect_auth_attempt := true,
7066 hlr_has_auth_info := false,
7067 expect_auth := false,
7068 expect_ciph := false,
7069 expect_imei := false,
7070 expect_imei_early := false,
7071 check_imei_result := OSMO_GSUP_IMEI_RESULT_ACK,
7072 check_imei_error := false
7073 },
7074 {
7075 /* [7] auth required, encr a5 0, HLR HAS auth info: do auth, no ciph" */
7076 kc_support := '01'O,
7077 net_config := { "authentication required",
7078 "encryption a5 0" },
7079 expect_attach_success := true,
7080 expect_tmsi := true,
7081 expect_auth_attempt := true,
7082 hlr_has_auth_info := true,
7083 expect_auth := true,
7084 expect_ciph := false,
7085 expect_imei := false,
7086 expect_imei_early := false,
7087 check_imei_result := OSMO_GSUP_IMEI_RESULT_ACK,
7088 check_imei_error := false
7089 },
7090 {
7091 /* [8] auth required, encr a5 0 3, HLR has NO Auth Info: reject */
7092 kc_support := '09'O,
7093 net_config := { "authentication required",
7094 "encryption a5 0 3" },
7095 expect_attach_success := false,
7096 expect_tmsi := true,
7097 expect_auth_attempt := true,
7098 hlr_has_auth_info := false,
7099 expect_auth := false,
7100 expect_ciph := false,
7101 expect_imei := false,
7102 expect_imei_early := false,
7103 check_imei_result := OSMO_GSUP_IMEI_RESULT_ACK,
7104 check_imei_error := false
7105 },
7106 {
7107 /* [9] auth required, encr a5 0 3, HLR HAS Auth Info: Use A5/3 */
7108 kc_support := '09'O,
7109 net_config := { "authentication required",
7110 "encryption a5 0 3" },
7111 expect_attach_success := true,
7112 expect_tmsi := true,
7113 expect_auth_attempt := true,
7114 hlr_has_auth_info := true,
7115 expect_auth := true,
7116 expect_ciph := true,
7117 expect_imei := false,
7118 expect_imei_early := false,
7119 check_imei_result := OSMO_GSUP_IMEI_RESULT_ACK,
7120 check_imei_error := false
7121 },
7122 {
7123 /* [10] auth required, encr a5 3, HLR has NO Auth Info: reject. */
7124 kc_support := '08'O,
7125 net_config := { "authentication required",
7126 "encryption a5 3" },
7127 expect_attach_success := false,
7128 expect_tmsi := true,
7129 expect_auth_attempt := true,
7130 hlr_has_auth_info := false,
7131 expect_auth := false,
7132 expect_ciph := false,
7133 expect_imei := false,
7134 expect_imei_early := false,
7135 check_imei_result := OSMO_GSUP_IMEI_RESULT_ACK,
7136 check_imei_error := false
7137 },
7138 {
7139 /* [11] auth required, encr a5 3, HLR HAS Auth Info: auth + ciph. */
7140 kc_support := '08'O,
7141 net_config := { "authentication required",
7142 "encryption a5 3" },
7143 expect_attach_success := true,
7144 expect_tmsi := true,
7145 expect_auth_attempt := true,
7146 hlr_has_auth_info := true,
7147 expect_auth := true,
7148 expect_ciph := true,
7149 expect_imei := false,
7150 expect_imei_early := false,
7151 check_imei_result := OSMO_GSUP_IMEI_RESULT_ACK,
7152 check_imei_error := false
7153 }
7154};
7155
7156private function f_tc_auth_options(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
7157 f_init_handler(pars);
7158
7159 /* Location Updating */
7160 log(MSCVTY, "f_perform_lu() starting");
7161 f_perform_lu();
7162 log(MSCVTY, "f_perform_lu() done");
7163
7164 f_sleep(1.0);
7165
7166 if (not pars.net.expect_attach_success) {
7167 /* Expected above LU to fail. In order to test CM Service Request below, a LU has to succeed first. So
7168 * run another LU that will be successful. Careful not to load auth tokens into the VLR that may taint
7169 * the test for CM Service Request below. */
7170
7171 log(MSCVTY, "Running a successful LU so that CM Service Request can be tested");
7172 var BSC_ConnHdlrNetworkPars saved_net := g_pars.net;
7173 g_pars.net.kc_support := '01'O;
7174 g_pars.net.expect_attach_success := true;
7175 g_pars.net.expect_auth_attempt := false;
7176 g_pars.net.expect_auth := false;
7177 g_pars.net.expect_ciph := false;
7178 f_vty_config3(MSCVTY, {"network"}, {"authentication optional", "encryption a5 0"});
7179 f_perform_lu();
7180
7181 /* Reconfigure like it was before */
7182 g_pars.net := saved_net;
7183 f_vty_config3(MSCVTY, {"network"}, g_pars.net.net_config);
7184 log(MSCVTY, "Running a successful LU done");
7185 }
7186
7187 /* CM Service Request */
7188 log(MSCVTY, "f_establish_fully() starting");
7189 f_establish_fully();
7190 log(MSCVTY, "f_establish_fully() done");
7191 BSSAP.send(ts_BSSMAP_ClearRequest(0));
7192 f_expect_clear();
7193}
7194
7195function f_TC_auth_options(integer tc_i) runs on MTC_CT {
7196 f_init();
7197
7198 var BSC_ConnHdlrNetworkPars tc := auth_options_testcases[tc_i];
7199
7200 f_vty_config3(MSCVTY, {"network"}, tc.net_config);
7201
7202 var BSC_ConnHdlrPars pars := f_init_pars(42300 + tc_i);
7203 pars.net := tc;
7204
7205 var BSC_ConnHdlr vc_conn;
7206 vc_conn := f_start_handler_with_pars(refers(f_tc_auth_options), pars);
7207 vc_conn.done;
7208}
7209
7210testcase TC_auth_options_0() runs on MTC_CT {
7211 f_TC_auth_options(0);
7212}
7213
7214testcase TC_auth_options_1() runs on MTC_CT {
7215 f_TC_auth_options(1);
7216}
7217
7218testcase TC_auth_options_2() runs on MTC_CT {
7219 f_TC_auth_options(2);
7220}
7221
7222testcase TC_auth_options_3() runs on MTC_CT {
7223 f_TC_auth_options(3);
7224}
7225
7226testcase TC_auth_options_4() runs on MTC_CT {
7227 f_TC_auth_options(4);
7228}
7229
7230testcase TC_auth_options_5() runs on MTC_CT {
7231 f_TC_auth_options(5);
7232}
7233
7234testcase TC_auth_options_6() runs on MTC_CT {
7235 f_TC_auth_options(6);
7236}
7237
7238testcase TC_auth_options_7() runs on MTC_CT {
7239 f_TC_auth_options(7);
7240}
7241
7242testcase TC_auth_options_8() runs on MTC_CT {
7243 f_TC_auth_options(8);
7244}
7245
7246testcase TC_auth_options_9() runs on MTC_CT {
7247 f_TC_auth_options(9);
7248}
7249
7250testcase TC_auth_options_10() runs on MTC_CT {
7251 f_TC_auth_options(10);
7252}
7253
7254testcase TC_auth_options_11() runs on MTC_CT {
7255 f_TC_auth_options(11);
7256}
7257
Oliver Smithc4a0c3c2023-08-23 15:40:12 +02007258private function f_set_cpars_csd(inout CallParameters cpars, charstring bs_name, BIT1 async,
7259 GSM48_bcap_transp transp, GSM48_bcap_user_rate user_rate) {
Oliver Smith9c417f22023-07-07 13:25:11 +02007260 log("-----------------------------------------------");
Oliver Smithc4a0c3c2023-08-23 15:40:12 +02007261 log("CSD Bearer Service: " & bs_name);
Oliver Smith9c417f22023-07-07 13:25:11 +02007262 log("-----------------------------------------------");
Oliver Smith9c417f22023-07-07 13:25:11 +02007263
Oliver Smith92b280c2023-04-20 13:13:23 +02007264 cpars.csd := true;
Oliver Smithc4a0c3c2023-08-23 15:40:12 +02007265
Oliver Smith9c417f22023-07-07 13:25:11 +02007266 cpars.bearer_cap := valueof(ts_Bcap_csd);
7267 cpars.bearer_cap.octet6.synchronous_asynchronous := async;
7268 cpars.bearer_cap.octet6.connectionElement := int2bit(enum2int(transp), 2);
7269 cpars.bearer_cap.octet6.userRate := int2bit(enum2int(user_rate), 4);
7270
Oliver Smithc4a0c3c2023-08-23 15:40:12 +02007271 cpars.mncc_bearer_cap := valueof(ts_MNCC_bcap_data);
7272 cpars.mncc_bearer_cap.data.async := bit2int(async);
7273 cpars.mncc_bearer_cap.data.transp := transp;
7274 cpars.mncc_bearer_cap.data.user_rate := user_rate;
7275}
7276
7277friend function f_mo_csd(charstring bs_name, BIT1 async, GSM48_bcap_transp transp, GSM48_bcap_user_rate user_rate)
7278 runs on BSC_ConnHdlr {
7279 var CallParameters cpars := valueof(t_CallParams);
7280
7281 g_Tguard.start(20.0);
7282 f_set_cpars_csd(cpars, bs_name, async, transp, user_rate);
Oliver Smith92b280c2023-04-20 13:13:23 +02007283 f_perform_lu();
Oliver Smith98e24bc2023-07-07 12:36:59 +02007284 f_mo_call(cpars, 0.5);
Oliver Smith92b280c2023-04-20 13:13:23 +02007285}
Oliver Smith9c417f22023-07-07 13:25:11 +02007286
7287friend function f_tc_lu_and_mo_csd(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
7288 f_init_handler(pars);
7289
7290 f_mo_csd("BS21T", '1'B, GSM48_BCAP_TR_TRANSP, GSM48_BCAP_UR_300);
7291 f_mo_csd("BS22T", '1'B, GSM48_BCAP_TR_TRANSP, GSM48_BCAP_UR_1200);
7292 f_mo_csd("BS24T", '1'B, GSM48_BCAP_TR_TRANSP, GSM48_BCAP_UR_2400);
7293 f_mo_csd("BS25T", '1'B, GSM48_BCAP_TR_TRANSP, GSM48_BCAP_UR_4800);
7294 f_mo_csd("BS26T", '1'B, GSM48_BCAP_TR_TRANSP, GSM48_BCAP_UR_9600);
7295
7296 f_mo_csd("BS21NT", '1'B, GSM48_BCAP_TR_RLP, GSM48_BCAP_UR_300);
7297 f_mo_csd("BS22NT", '1'B, GSM48_BCAP_TR_RLP, GSM48_BCAP_UR_1200);
7298 f_mo_csd("BS24NT", '1'B, GSM48_BCAP_TR_RLP, GSM48_BCAP_UR_2400);
7299 f_mo_csd("BS25NT", '1'B, GSM48_BCAP_TR_RLP, GSM48_BCAP_UR_4800);
7300 f_mo_csd("BS26NT", '1'B, GSM48_BCAP_TR_RLP, GSM48_BCAP_UR_9600);
7301
7302 f_mo_csd("BS31T", '0'B, GSM48_BCAP_TR_TRANSP, GSM48_BCAP_UR_1200);
7303 f_mo_csd("BS32T", '0'B, GSM48_BCAP_TR_TRANSP, GSM48_BCAP_UR_2400);
7304 f_mo_csd("BS33T", '0'B, GSM48_BCAP_TR_TRANSP, GSM48_BCAP_UR_4800);
7305 f_mo_csd("BS34T", '0'B, GSM48_BCAP_TR_TRANSP, GSM48_BCAP_UR_9600);
7306}
Oliver Smith92b280c2023-04-20 13:13:23 +02007307testcase TC_lu_and_mo_csd() runs on MTC_CT {
7308 var BSC_ConnHdlr vc_conn;
7309 f_init();
7310
7311 vc_conn := f_start_handler(refers(f_tc_lu_and_mo_csd), 7);
7312 vc_conn.done;
7313}
7314
Oliver Smith8cf75ab2023-06-21 16:19:51 +02007315friend function f_mt_csd(charstring bs_name, BIT1 async, GSM48_bcap_transp transp, GSM48_bcap_user_rate user_rate)
7316 runs on BSC_ConnHdlr {
Oliver Smithc1dd36a2023-05-31 13:52:24 +02007317 var CallParameters cpars := valueof(t_CallParams);
Oliver Smith8cf75ab2023-06-21 16:19:51 +02007318
Oliver Smithc4a0c3c2023-08-23 15:40:12 +02007319 g_Tguard.start(20.0);
7320 f_set_cpars_csd(cpars, bs_name, async, transp, user_rate);
Oliver Smithc1dd36a2023-05-31 13:52:24 +02007321 f_perform_lu();
Oliver Smith98e24bc2023-07-07 12:36:59 +02007322 f_mt_call(cpars, 0.5);
Oliver Smithc1dd36a2023-05-31 13:52:24 +02007323}
Oliver Smith8cf75ab2023-06-21 16:19:51 +02007324friend function f_tc_lu_and_mt_csd(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
7325 f_init_handler(pars);
7326
7327 f_mt_csd("BS21T", '1'B, GSM48_BCAP_TR_TRANSP, GSM48_BCAP_UR_300);
7328 f_mt_csd("BS22T", '1'B, GSM48_BCAP_TR_TRANSP, GSM48_BCAP_UR_1200);
7329 f_mt_csd("BS24T", '1'B, GSM48_BCAP_TR_TRANSP, GSM48_BCAP_UR_2400);
7330 f_mt_csd("BS25T", '1'B, GSM48_BCAP_TR_TRANSP, GSM48_BCAP_UR_4800);
7331 f_mt_csd("BS26T", '1'B, GSM48_BCAP_TR_TRANSP, GSM48_BCAP_UR_9600);
7332
7333 f_mt_csd("BS21NT", '1'B, GSM48_BCAP_TR_RLP, GSM48_BCAP_UR_300);
7334 f_mt_csd("BS22NT", '1'B, GSM48_BCAP_TR_RLP, GSM48_BCAP_UR_1200);
7335 f_mt_csd("BS24NT", '1'B, GSM48_BCAP_TR_RLP, GSM48_BCAP_UR_2400);
7336 f_mt_csd("BS25NT", '1'B, GSM48_BCAP_TR_RLP, GSM48_BCAP_UR_4800);
7337 f_mt_csd("BS26NT", '1'B, GSM48_BCAP_TR_RLP, GSM48_BCAP_UR_9600);
7338
7339 f_mt_csd("BS31T", '0'B, GSM48_BCAP_TR_TRANSP, GSM48_BCAP_UR_1200);
7340 f_mt_csd("BS32T", '0'B, GSM48_BCAP_TR_TRANSP, GSM48_BCAP_UR_2400);
7341 f_mt_csd("BS33T", '0'B, GSM48_BCAP_TR_TRANSP, GSM48_BCAP_UR_4800);
7342 f_mt_csd("BS34T", '0'B, GSM48_BCAP_TR_TRANSP, GSM48_BCAP_UR_9600);
7343}
Oliver Smithc1dd36a2023-05-31 13:52:24 +02007344testcase TC_lu_and_mt_csd() runs on MTC_CT {
7345 var BSC_ConnHdlr vc_conn;
7346 f_init();
7347
7348 vc_conn := f_start_handler(refers(f_tc_lu_and_mt_csd), 7);
7349 vc_conn.done;
7350}
7351
Neels Hofmeyra8a2c5e2024-03-25 04:21:48 +01007352/* MSC <-> BSC: ID req/rsp for IMSI */
7353private altstep as_id_req_imsi()
7354runs on BSC_ConnHdlr {
7355 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_MM_ID_Req(CM_ID_TYPE_IMSI))) {
7356 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
7357 BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_MM_ID_Rsp(mi)));
7358 repeat;
7359 }
7360}
7361
7362/* MSC is configured to not assign a TMSI; MS sends LU Request with a TMSI MI (from another cell), and MSC shall not use
7363 * that TMSI. */
7364private function f_tc_lu_tmsi_noauth_notmsi(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
7365 f_init_handler(pars, t_guard := 20.0);
7366
7367 /* Perform Location Updating using an unknown TMSI MI. Expect an ID Request to come from the MSC and answer
7368 * that with as_id_req_imsi(). */
7369 activate(as_id_req_imsi());
7370 f_perform_lu(use_mi := ts_MI_TMSI_LV(pars.tmsi));
7371
7372 f_sleep(1.0);
7373
7374 /* Attached by invalid TMSI, and the MSC has asked for the IMSI. Initiate Paging and make sure the MSC doesn't
7375 * use the invalid TMSI for it. */
7376 f_ran_register_imsi(g_pars.imsi, omit);
7377 f_vty_transceive(MSCVTY, "subscriber imsi " & hex2str(g_pars.imsi) & " paging");
7378 f_expect_paging_tmsi(omit);
Neels Hofmeyr06dec6b2024-03-26 03:40:45 +01007379
7380 /* Respond to paging, to clean up internal paging state for this subscriber, so we can get a clean second run
7381 * out of this test code. Don't use the TMSI in the paging response. */
7382 f_cl3_or_initial_ue(valueof(ts_PAG_RESP(ts_MI_IMSI_LV(pars.imsi))));
7383 f_mm_common();
7384 /* The paging was by VTY, so nothing happens, just a release. */
7385 f_expect_clear();
7386
7387 /* Clean up ttcn state for the second test run to work out. */
7388 f_unregister_gsup_imsi(hex2str(pars.imsi));
7389 f_ran_unregister_imsi(pars.imsi);
Neels Hofmeyra8a2c5e2024-03-25 04:21:48 +01007390}
7391testcase TC_lu_tmsi_noauth_notmsi() runs on MTC_CT {
7392 var BSC_ConnHdlrPars pars;
7393 var BSC_ConnHdlr vc_conn;
7394 f_init();
7395 f_vty_config(MSCVTY, "msc", "no assign-tmsi");
7396 pars := f_init_pars(101);
7397 pars.net.expect_tmsi := false;
7398 pars.tmsi := '0badbad0'O;
7399 pars.mm_info := false;
7400 vc_conn := f_start_handler_with_pars(refers(f_tc_lu_tmsi_noauth_notmsi), pars);
7401 vc_conn.done;
Neels Hofmeyr06dec6b2024-03-26 03:40:45 +01007402
7403 /* Now run the same test *again*, to test against an evil twin VLR entry:
7404 * A vlr_subscr with the correct IMSI is now present in the VLR.
7405 * We again ask for a LU with the 0x0bad TMSI. The VLR will initially create another vlr_subsrc(TMSI=0x0bad).
7406 * When it learns the IMSI via ID Request, it needs to realize that this IMSI is already present on the first
7407 * vsub, and sort out the VLR record so that only one entry for this IMSI exists.
7408 */
7409 pars := f_init_pars(101);
7410 pars.net.expect_tmsi := false;
7411 pars.tmsi := '0badbad0'O;
7412 pars.mm_info := false;
7413 vc_conn := f_start_handler_with_pars(refers(f_tc_lu_tmsi_noauth_notmsi), pars);
7414 vc_conn.done;
Neels Hofmeyra8a2c5e2024-03-25 04:21:48 +01007415}
7416
Harald Weltef6dd64d2017-11-19 12:09:51 +01007417control {
Philipp Maier328d1662018-03-07 10:40:27 +01007418 execute( TC_cr_before_reset() );
Harald Weltea49e36e2018-01-21 19:29:33 +01007419 execute( TC_lu_imsi_noauth_tmsi() );
Harald Welted2328a22018-01-27 14:27:16 +01007420 execute( TC_lu_imsi_noauth_notmsi() );
Neels Hofmeyra8a2c5e2024-03-25 04:21:48 +01007421 execute( TC_lu_tmsi_noauth_notmsi() );
Harald Weltea49e36e2018-01-21 19:29:33 +01007422 execute( TC_lu_imsi_reject() );
7423 execute( TC_lu_imsi_timeout_gsup() );
Harald Welted2328a22018-01-27 14:27:16 +01007424 execute( TC_lu_imsi_auth_tmsi() );
Harald Welte8a397ae2019-04-21 22:03:37 +02007425 execute( TC_lu_imsi_auth3g_tmsi() );
Pau Espin Pedrold3d54a92019-12-17 17:02:54 +01007426 execute( TC_lu_imsi_timeout_tmsi_realloc() );
Harald Welted2328a22018-01-27 14:27:16 +01007427 execute( TC_cmserv_imsi_unknown() );
Neels Hofmeyr13737fb2020-08-19 13:16:14 +00007428 execute( TC_cmserv_tmsi_unknown() );
Harald Welte2bb825f2018-01-22 11:31:18 +01007429 execute( TC_lu_and_mo_call() );
Pau Espin Pedrol833174e2020-09-03 16:46:02 +02007430 execute( TC_lu_and_mo_call_ipv6() );
Pau Espin Pedrola42745c2020-01-10 18:03:28 +01007431 execute( TC_lu_and_mo_call_sccp_tiar_timeout() );
Harald Welte071ed732018-01-23 19:53:52 +01007432 execute( TC_lu_auth_sai_timeout() );
7433 execute( TC_lu_auth_sai_err() );
Harald Weltee1a2f3c2018-01-24 17:28:48 +01007434 execute( TC_lu_clear_request() );
Vadim Yanitskiy109e7552021-02-05 05:36:02 +01007435 execute( TC_mo_call_clear_request() );
7436 execute( TC_mt_call_clear_request() );
Harald Weltee1a2f3c2018-01-24 17:28:48 +01007437 execute( TC_lu_disconnect() );
7438 execute( TC_lu_by_imei() );
7439 execute( TC_lu_by_tmsi_noauth_unknown() );
Neels Hofmeyrfc06c732020-08-19 12:52:28 +00007440 execute( TC_attached_imsi_lu_unknown_tmsi() );
Harald Weltee1a2f3c2018-01-24 17:28:48 +01007441 execute( TC_imsi_detach_by_imsi() );
7442 execute( TC_imsi_detach_by_tmsi() );
7443 execute( TC_imsi_detach_by_imei() );
7444 execute( TC_emerg_call_imei_reject() );
7445 execute( TC_emerg_call_imsi() );
7446 execute( TC_cm_serv_req_vgcs_reject() );
7447 execute( TC_cm_serv_req_vbs_reject() );
7448 execute( TC_cm_serv_req_lcs_reject() );
Harald Welte0195ab12018-01-24 21:50:20 +01007449 execute( TC_cm_reest_req_reject() );
Harald Welte1af6ea82018-01-25 18:33:15 +01007450 execute( TC_lu_auth_2G_fail() );
7451 execute( TC_lu_imsi_auth_tmsi_encr_13_13() );
7452 execute( TC_cl3_no_payload() );
7453 execute( TC_cl3_rnd_payload() );
Harald Welte1852a842018-01-26 22:53:36 +01007454 execute( TC_establish_and_nothing() );
7455 execute( TC_mo_setup_and_nothing() );
7456 execute( TC_mo_crcx_ran_timeout() );
7457 execute( TC_mo_crcx_ran_reject() );
Harald Welted2328a22018-01-27 14:27:16 +01007458 execute( TC_mt_crcx_ran_reject() );
Daniel Willmann8b084372018-02-04 13:35:26 +01007459 execute( TC_mo_setup_and_dtmf_dup() );
Vadim Yanitskiyb56701e2021-02-05 01:54:07 +01007460 execute( TC_mt_t310() );
Harald Welte167458a2018-01-27 15:58:16 +01007461 execute( TC_gsup_cancel() );
Harald Welte9de84792018-01-28 01:06:35 +01007462 execute( TC_lu_imsi_auth_tmsi_encr_1_13() );
7463 execute( TC_lu_imsi_auth_tmsi_encr_3_13() );
7464 execute( TC_lu_imsi_auth_tmsi_encr_3_1() );
Neels Hofmeyr29b8da02018-03-01 18:09:45 +01007465 execute( TC_lu_imsi_auth_tmsi_encr_3_1_no_cm() );
Harald Welte9de84792018-01-28 01:06:35 +01007466 execute( TC_lu_imsi_auth_tmsi_encr_13_2() );
7467 execute( TC_lu_imsi_auth_tmsi_encr_013_2() );
Eric Wild26f4a622021-05-17 15:27:05 +02007468 execute( TC_lu_imsi_auth_tmsi_encr_0134_1() );
7469 execute( TC_lu_imsi_auth_tmsi_encr_0134_34() );
7470 execute( TC_lu_imsi_auth_tmsi_encr_0134_34_no_cm3() );
7471
Philipp Maier94f3f1b2018-03-15 18:54:13 +01007472 execute( TC_mo_release_timeout() );
Philipp Maier2a98a732018-03-19 16:06:12 +01007473 execute( TC_lu_and_mt_call_no_dlcx_resp() );
Philipp Maier75932982018-03-27 14:52:35 +02007474 execute( TC_reset_two() );
Harald Welte33ec09b2018-02-10 15:34:46 +01007475
7476 execute( TC_lu_and_mt_call() );
Pau Espin Pedrol833174e2020-09-03 16:46:02 +02007477 execute( TC_lu_and_mt_call_ipv6() );
Neels Hofmeyrb58d9742019-11-27 18:44:54 +01007478 execute( TC_lu_and_mt_call_already_paging() );
Pau Espin Pedrol9a732a42020-09-15 15:56:33 +02007479 execute( TC_lu_and_mt_call_osmux() );
Harald Welte33ec09b2018-02-10 15:34:46 +01007480
Harald Weltef45efeb2018-04-09 18:19:24 +02007481 execute( TC_lu_and_mo_sms() );
7482 execute( TC_lu_and_mt_sms() );
Neels Hofmeyrb58d9742019-11-27 18:44:54 +01007483 execute( TC_lu_and_mt_sms_already_paging() );
Philipp Maier3983e702018-11-22 19:01:33 +01007484 execute( TC_lu_and_mt_sms_paging_and_nothing() );
Alexander Couzensfc02f242019-09-12 03:43:18 +02007485 execute( TC_lu_and_mt_sms_paging_repeated() );
Harald Weltef640a012018-04-14 17:49:21 +02007486 execute( TC_smpp_mo_sms() );
Vadim Yanitskiy33820762020-01-15 11:26:07 +07007487 execute( TC_smpp_mo_sms_rp_error() );
Harald Weltef640a012018-04-14 17:49:21 +02007488 execute( TC_smpp_mt_sms() );
Harald Weltef45efeb2018-04-09 18:19:24 +02007489
Vadim Yanitskiy103d09f2018-11-12 02:50:23 +07007490 execute( TC_gsup_mo_sms() );
Vadim Yanitskiy9cc019a2018-11-15 02:06:07 +07007491 execute( TC_gsup_mo_smma() );
Vadim Yanitskiyd7b37ab2018-11-24 03:40:20 +07007492 execute( TC_gsup_mt_sms_ack() );
7493 execute( TC_gsup_mt_sms_err() );
Vadim Yanitskiybe1ff4b2019-01-18 15:04:13 +07007494 execute( TC_gsup_mt_sms_rp_mr() );
Vadim Yanitskiy5ac49cc2019-01-24 16:57:31 +07007495 execute( TC_gsup_mo_mt_sms_rp_mr() );
Vadim Yanitskiya2a8a112019-07-08 20:04:32 +07007496 execute( TC_gsup_mt_multi_part_sms() );
Vadim Yanitskiy74b2f4f2024-06-06 22:07:11 +07007497 if (Misc_Helpers.f_osmo_repo_is("nightly")) {
7498 /* timer X36 is not supported by osmo-msc <= 1.11.1
7499 * Related: osmo-msc.git Ic519cab55d65e47b2636124427dab1a1d80fab78 */
7500 execute( TC_gsup_mt_sms_lu_delay() );
7501 }
Vadim Yanitskiy103d09f2018-11-12 02:50:23 +07007502
Vadim Yanitskiy2a978b92018-06-19 17:51:20 +07007503 execute( TC_lu_and_mo_ussd_single_request() );
Vadim Yanitskiy13e4a272018-06-19 18:24:31 +07007504 execute( TC_lu_and_mt_ussd_notification() );
Vadim Yanitskiy2a978b92018-06-19 17:51:20 +07007505 execute( TC_lu_and_mo_ussd_during_mt_call() );
Vadim Yanitskiy13e4a272018-06-19 18:24:31 +07007506 execute( TC_lu_and_mt_ussd_during_mt_call() );
Vadim Yanitskiy2daf52d2018-06-21 04:19:58 +07007507 execute( TC_lu_and_mo_ussd_mo_release() );
Vadim Yanitskiy0e392dd2018-11-29 00:47:54 +07007508 execute( TC_lu_and_ss_session_timeout() );
Vadim Yanitskiy7d1f9182018-05-28 16:21:42 +07007509
Vadim Yanitskiy0e6c9f52019-06-15 01:01:28 +07007510 execute( TC_mt_ussd_for_unknown_subscr() );
Vadim Yanitskiyc3c07d42019-06-17 23:00:44 +07007511 execute( TC_mo_ussd_for_unknown_trans() );
Vadim Yanitskiyd612d282019-06-15 14:46:03 +07007512 execute( TC_proc_ss_for_unknown_session() );
Vadim Yanitskiye5f4ed92019-06-16 02:36:33 +07007513 execute( TC_proc_ss_paging_fail() );
Vadim Yanitskiy29ba8d62019-06-16 15:19:41 +07007514 execute( TC_proc_ss_abort() );
Vadim Yanitskiy0e6c9f52019-06-15 01:01:28 +07007515
Vadim Yanitskiy1c9754d2020-01-07 21:56:55 +01007516 execute( TC_multi_lu_and_mo_ussd() );
7517 execute( TC_multi_lu_and_mt_ussd() );
7518
Stefan Sperling89eb1f32018-12-17 15:06:20 +01007519 execute( TC_cipher_complete_with_invalid_cipher() );
Stefan Sperlinga2d59c62018-12-18 16:32:44 +01007520 execute( TC_cipher_complete_1_without_cipher() );
7521 execute( TC_cipher_complete_3_without_cipher() );
7522 execute( TC_cipher_complete_13_without_cipher() );
Harald Welteb2284bd2019-05-10 11:30:43 +02007523 execute( TC_lu_with_invalid_mcc_mnc() );
Stefan Sperling89eb1f32018-12-17 15:06:20 +01007524
Harald Welte4263c522018-12-06 11:56:27 +01007525 execute( TC_sgsap_reset() );
7526 execute( TC_sgsap_lu() );
7527 execute( TC_sgsap_lu_imsi_reject() );
7528 execute( TC_sgsap_lu_and_nothing() );
7529 execute( TC_sgsap_expl_imsi_det_eps() );
Philipp Maierfc19f172019-03-21 11:17:54 +01007530 execute( TC_sgsap_impl_imsi_det_eps() );
Harald Welte4263c522018-12-06 11:56:27 +01007531 execute( TC_sgsap_expl_imsi_det_noneps() );
Philipp Maier5d812702019-03-21 10:51:26 +01007532 execute( TC_sgsap_impl_imsi_det_noneps() );
Harald Welte4263c522018-12-06 11:56:27 +01007533 execute( TC_sgsap_paging_rej() );
7534 execute( TC_sgsap_paging_subscr_rej() );
7535 execute( TC_sgsap_paging_ue_unr() );
7536 execute( TC_sgsap_paging_and_nothing() );
7537 execute( TC_sgsap_paging_and_lu() );
7538 execute( TC_sgsap_mt_sms() );
7539 execute( TC_sgsap_mo_sms() );
7540 execute( TC_sgsap_mt_sms_and_nothing() );
7541 execute( TC_sgsap_mt_sms_and_reject() );
7542 execute( TC_sgsap_unexp_ud() );
7543 execute( TC_sgsap_unsol_ud() );
7544 execute( TC_bssap_lu_sgsap_lu_and_mt_call() );
7545 execute( TC_sgsap_lu_and_mt_call() );
Philipp Maier628c0052019-04-09 17:36:57 +02007546 execute( TC_sgsap_vlr_failure() );
Harald Welte4263c522018-12-06 11:56:27 +01007547
Neels Hofmeyr0ac63152019-05-07 01:20:17 +02007548 execute( TC_ho_inter_bsc_unknown_cell() );
7549 execute( TC_ho_inter_bsc() );
Neels Hofmeyr0d841d92021-06-21 22:27:21 +02007550 execute( TC_ho_inter_bsc_a5_1() );
7551 execute( TC_ho_inter_bsc_a5_3() );
7552 execute( TC_ho_inter_bsc_a5_4() );
Pau Espin Pedrol833174e2020-09-03 16:46:02 +02007553 execute( TC_ho_inter_bsc_ipv6() );
Oliver Smith44424db2023-08-22 13:54:09 +02007554 execute( TC_ho_inter_bsc_csd() );
Neels Hofmeyr0ac63152019-05-07 01:20:17 +02007555
7556 execute( TC_ho_inter_msc_out() );
Neels Hofmeyr666d39a2021-06-21 22:27:21 +02007557 execute( TC_ho_inter_msc_out_a5_1() );
7558 execute( TC_ho_inter_msc_out_a5_3() );
7559 execute( TC_ho_inter_msc_out_a5_4() );
Pau Espin Pedrol833174e2020-09-03 16:46:02 +02007560 execute( TC_ho_inter_msc_out_ipv6() );
Oliver Smithcaa36c92023-08-23 15:30:33 +02007561 execute( TC_ho_inter_msc_out_csd() );
Neels Hofmeyr0ac63152019-05-07 01:20:17 +02007562
Oliver Smith1d118ff2019-07-03 10:57:35 +02007563 execute( TC_lu_imsi_auth_tmsi_check_imei() );
7564 execute( TC_lu_imsi_auth3g_tmsi_check_imei() );
7565 execute( TC_lu_imsi_noauth_tmsi_check_imei() );
7566 execute( TC_lu_imsi_noauth_notmsi_check_imei() );
7567 execute( TC_lu_imsi_auth_tmsi_check_imei_nack() );
7568 execute( TC_lu_imsi_auth_tmsi_check_imei_err() );
7569 execute( TC_lu_imsi_auth_tmsi_check_imei_early() );
7570 execute( TC_lu_imsi_auth3g_tmsi_check_imei_early() );
7571 execute( TC_lu_imsi_noauth_tmsi_check_imei_early() );
7572 execute( TC_lu_imsi_noauth_notmsi_check_imei_early() );
7573 execute( TC_lu_imsi_auth_tmsi_check_imei_early_nack() );
7574 execute( TC_lu_imsi_auth_tmsi_check_imei_early_err() );
Neels Hofmeyr1b3c6e32018-03-01 17:52:21 +01007575 execute( TC_lu_imsi_auth_tmsi_encr_3_1_log_msc_debug() );
Pau Espin Pedrol609f1d62020-09-15 16:01:55 +02007576
Neels Hofmeyr692c9ee2018-04-10 02:07:13 +02007577 execute( TC_mo_cc_bssmap_clear() );
Neels Hofmeyr8df69622019-11-02 19:16:03 +01007578 execute( TC_invalid_mgcp_crash() );
Vadim Yanitskiyeddebaa2019-12-28 17:45:34 +01007579 execute( TC_mm_id_resp_no_identity() );
Vadim Yanitskiy25219062020-01-21 01:41:33 +07007580 execute( TC_lu_and_expire_while_paging() );
Pau Espin Pedrol174fac22021-02-26 13:20:10 +01007581 execute( TC_paging_response_imsi_unknown() );
7582 execute( TC_paging_response_tmsi_unknown() );
Neels Hofmeyr4f099b42021-07-27 03:45:26 +02007583
7584 execute( TC_call_re_establishment() );
Neels Hofmeyra9b2dcf2021-07-28 00:57:58 +02007585 execute( TC_call_re_establishment_auth() );
Neels Hofmeyr48e4d7d2021-07-28 00:57:58 +02007586 execute( TC_call_re_establishment_ciph() );
Neels Hofmeyr07ea7f22022-05-05 01:39:26 +02007587
7588 execute( TC_cm_serv_wrong_mi() );
Neels Hofmeyre860fc42022-10-05 01:15:54 +02007589
7590 execute( TC_auth_options_0() );
7591 execute( TC_auth_options_1() );
7592 execute( TC_auth_options_2() );
7593 execute( TC_auth_options_3() );
7594 execute( TC_auth_options_4() );
7595 execute( TC_auth_options_5() );
7596 execute( TC_auth_options_6() );
7597 execute( TC_auth_options_7() );
7598 execute( TC_auth_options_8() );
7599 execute( TC_auth_options_9() );
7600 execute( TC_auth_options_10() );
7601 execute( TC_auth_options_11() );
Oliver Smith92b280c2023-04-20 13:13:23 +02007602
7603 execute( TC_lu_and_mo_csd() );
Oliver Smithc1dd36a2023-05-31 13:52:24 +02007604 execute( TC_lu_and_mt_csd() );
Harald Weltef6dd64d2017-11-19 12:09:51 +01007605}
7606
7607
7608}