blob: 4b00e345ec956314695fbfe3724ea2c54ce413b6 [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;
16
Harald Weltef6dd64d2017-11-19 12:09:51 +010017import from General_Types all;
18import from Osmocom_Types all;
19
20import from M3UA_Types all;
21import from M3UA_Emulation all;
22
23import from MTP3asp_Types all;
24import from MTP3asp_PortType all;
25
26import from SCCPasp_Types all;
27import from SCCP_Types all;
28import from SCCP_Emulation all;
29
30import from SCTPasp_Types all;
31import from SCTPasp_PortType all;
32
Harald Weltea49e36e2018-01-21 19:29:33 +010033import from Osmocom_CTRL_Functions all;
34import from Osmocom_CTRL_Types all;
35import from Osmocom_CTRL_Adapter all;
36
Harald Welte3ca1c902018-01-24 18:51:27 +010037import from TELNETasp_PortType all;
38import from Osmocom_VTY_Functions all;
39
Harald Weltea49e36e2018-01-21 19:29:33 +010040import from MNCC_Emulation all;
Harald Welte2bb825f2018-01-22 11:31:18 +010041import from MNCC_Types all;
Harald Weltea49e36e2018-01-21 19:29:33 +010042
Harald Welte4aa970c2018-01-26 10:38:09 +010043import from MGCP_Emulation all;
44import from MGCP_Types all;
45import from MGCP_Templates all;
46import from SDP_Types all;
47
Harald Weltea49e36e2018-01-21 19:29:33 +010048import from GSUP_Emulation all;
49import from GSUP_Types all;
50import from IPA_Emulation all;
51
Harald Weltef6dd64d2017-11-19 12:09:51 +010052import from BSSAP_Types all;
Harald Welte6811d102019-04-14 22:23:14 +020053import from RAN_Adapter all;
Harald Weltea49e36e2018-01-21 19:29:33 +010054import from BSSAP_CodecPort all;
55import from BSSMAP_Templates all;
Harald Welte6811d102019-04-14 22:23:14 +020056import from RAN_Emulation all;
Harald Weltea49e36e2018-01-21 19:29:33 +010057import from BSC_ConnectionHandler all;
Harald Weltee13cfb22019-04-23 16:52:02 +020058import from RANAP_Templates all;
Harald Weltef6dd64d2017-11-19 12:09:51 +010059
Harald Welte4263c522018-12-06 11:56:27 +010060import from SGsAP_Templates all;
61import from SGsAP_Types all;
62import from SGsAP_Emulation all;
63
Harald Weltea49e36e2018-01-21 19:29:33 +010064import from MobileL3_Types all;
65import from MobileL3_CommonIE_Types all;
Vadim Yanitskiy103d09f2018-11-12 02:50:23 +070066import from MobileL3_SMS_Types all;
Harald Weltea49e36e2018-01-21 19:29:33 +010067import from L3_Templates all;
Harald Welte158a7ca2018-02-16 18:11:31 +010068import from L3_Common all;
Harald Weltef6dd64d2017-11-19 12:09:51 +010069
Harald Weltef640a012018-04-14 17:49:21 +020070import from SMPP_Types all;
71import from SMPP_Templates all;
72import from SMPP_Emulation all;
73
Stefan Sperlingc307e682018-06-14 15:15:46 +020074import from SCCP_Templates all;
75
Vadim Yanitskiy7d1f9182018-05-28 16:21:42 +070076import from SS_Types all;
77import from SS_Templates all;
78import from USSD_Helpers all;
Harald Welte4263c522018-12-06 11:56:27 +010079import from DNS_Helpers all;
Vadim Yanitskiy7d1f9182018-05-28 16:21:42 +070080
Philipp Maier948747b2019-04-02 15:22:33 +020081import from TCCConversion_Functions all;
82
Harald Welte9b751a62019-04-14 17:39:29 +020083const integer NUM_BSC := 3;
Harald Welte6811d102019-04-14 22:23:14 +020084type record of RAN_Configuration RAN_Configurations;
Harald Weltef6dd64d2017-11-19 12:09:51 +010085
Harald Welte4263c522018-12-06 11:56:27 +010086/* Needed for SGsAP SMS */
87import from MobileL3_SMS_Types all;
88
Harald Weltea4ca4462018-02-09 00:17:14 +010089type component MTC_CT extends CTRL_Adapter_CT {
Harald Weltef6dd64d2017-11-19 12:09:51 +010090 var boolean g_initialized := false;
Harald Weltea49e36e2018-01-21 19:29:33 +010091
Harald Welte6811d102019-04-14 22:23:14 +020092 var RAN_Adapter g_bssap[NUM_BSC];
Harald Weltea4ca4462018-02-09 00:17:14 +010093
Harald Weltea49e36e2018-01-21 19:29:33 +010094 /* no 'adapter_CT' for MNCC or GSUP */
95 var MNCC_Emulation_CT vc_MNCC;
Harald Welte4aa970c2018-01-26 10:38:09 +010096 var MGCP_Emulation_CT vc_MGCP;
Harald Weltea49e36e2018-01-21 19:29:33 +010097 var GSUP_Emulation_CT vc_GSUP;
98 var IPA_Emulation_CT vc_GSUP_IPA;
Harald Weltef640a012018-04-14 17:49:21 +020099 var SMPP_Emulation_CT vc_SMPP;
Harald Welte4263c522018-12-06 11:56:27 +0100100 var SGsAP_Emulation_CT vc_SGsAP;
Harald Weltea49e36e2018-01-21 19:29:33 +0100101
102 /* only to get events from IPA underneath GSUP */
103 port IPA_CTRL_PT GSUP_IPA_EVENT;
Harald Welte3ca1c902018-01-24 18:51:27 +0100104 /* VTY to MSC */
105 port TELNETasp_PT MSCVTY;
Philipp Maier328d1662018-03-07 10:40:27 +0100106
107 /* A port to directly send BSSAP messages. This port is used for
108 * tests that require low level access to sen arbitrary BSSAP
109 * messages. Run f_init_bssap_direct() to connect and initialize */
110 port BSSAP_CODEC_PT BSSAP_DIRECT;
111
112 /* When BSSAP messages are directly sent, then the connection
113 * handler is not active, which means that also no guard timer is
114 * set up. The following timer will serve as a replacement */
115 timer Tguard_direct := 60.0;
Harald Weltef6dd64d2017-11-19 12:09:51 +0100116}
117
118modulepar {
Harald Weltea49e36e2018-01-21 19:29:33 +0100119 /* remote parameters of IUT */
120 charstring mp_msc_ip := "127.0.0.1";
121 integer mp_msc_ctrl_port := 4255;
122 integer mp_msc_vty_port := 4254;
Harald Weltef6dd64d2017-11-19 12:09:51 +0100123
Harald Weltea49e36e2018-01-21 19:29:33 +0100124 /* local parameters of emulated HLR */
Philipp Maier9b690e42018-12-21 11:50:03 +0100125 boolean mp_mm_info := false;
Harald Weltea49e36e2018-01-21 19:29:33 +0100126 charstring mp_hlr_ip := "127.0.0.1";
127 integer mp_hlr_port := 4222;
Harald Welte6126fb02018-01-27 20:08:24 +0100128 charstring mp_mgw_ip := "127.0.0.1";
129 integer mp_mgw_port := 2427;
Harald Weltef6dd64d2017-11-19 12:09:51 +0100130
Harald Weltea49e36e2018-01-21 19:29:33 +0100131 charstring mp_msc_mncc := "/tmp/mncc";
Harald Weltea4ca4462018-02-09 00:17:14 +0100132
Harald Weltef640a012018-04-14 17:49:21 +0200133 integer mp_msc_smpp_port := 2775;
134 charstring mp_smpp_system_id := "msc_tester";
135 charstring mp_smpp_password := "osmocom1";
Harald Welte4263c522018-12-06 11:56:27 +0100136 charstring mp_mme_name := "mmec01.mmegi0001.mme.epc.mnc070.mcc901.3gppnetwork.org";
137 charstring mp_vlr_name := "vlr.example.net";
Harald Weltef640a012018-04-14 17:49:21 +0200138
Pau Espin Pedrol690d6592019-05-31 17:56:32 +0200139 /* Whether to enable osmux tests. Can be dropped completely and enable
140 unconditionally once new version of osmo-msc is released (current
141 version: 1.3.1) */
142 boolean mp_enable_osmux_test := true;
143
Harald Welte6811d102019-04-14 22:23:14 +0200144 RAN_Configurations mp_bssap_cfg := {
Philipp Maier75932982018-03-27 14:52:35 +0200145 {
146 sccp_service_type := "mtp3_itu",
147 sctp_addr := { 23905, "127.0.0.1", 2905, "127.0.0.1" },
148 own_pc := 185,
149 own_ssn := 254,
150 peer_pc := 187,
151 peer_ssn := 254,
152 sio := '83'O,
153 rctx := 0
154 },
155 {
156 sccp_service_type := "mtp3_itu",
157 sctp_addr := { 23906, "127.0.0.1", 2905, "127.0.0.1" },
158 own_pc := 186,
159 own_ssn := 254,
160 peer_pc := 187,
161 peer_ssn := 254,
162 sio := '83'O,
163 rctx := 1
164 }
Harald Weltea4ca4462018-02-09 00:17:14 +0100165 };
Harald Weltef6dd64d2017-11-19 12:09:51 +0100166}
167
Philipp Maier328d1662018-03-07 10:40:27 +0100168/* altstep for the global guard timer (only used when BSSAP_DIRECT
169 * is used for communication */
170private altstep as_Tguard_direct() runs on MTC_CT {
171 [] Tguard_direct.timeout {
172 setverdict(fail, "Tguard timeout");
Daniel Willmannafce8662018-07-06 23:11:32 +0200173 mtc.stop;
Philipp Maier328d1662018-03-07 10:40:27 +0100174 }
175}
Harald Weltef6dd64d2017-11-19 12:09:51 +0100176
Neels Hofmeyr2ca1ab42019-03-08 03:45:43 +0100177private altstep as_optional_cc_rel(CallParameters cpars, boolean respond := false) runs on BSC_ConnHdlr {
178 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_CC_RELEASE(cpars.transaction_id))) {
179 if (respond) {
180 var BIT1 tid_remote := '1'B;
181 if (cpars.mo_call) {
182 tid_remote := '0'B;
183 }
184 BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_CC_REL_COMPL(cpars.transaction_id, tid_remote)));
185 }
186 }
Neels Hofmeyrde76f052019-02-26 05:02:46 +0100187}
188
Harald Weltef640a012018-04-14 17:49:21 +0200189function f_init_smpp(charstring id) runs on MTC_CT {
190 id := id & "-SMPP";
191 var EsmePars pars := {
192 mode := MODE_TRANSCEIVER,
193 bind := {
194 system_id := mp_smpp_system_id,
195 password := mp_smpp_password,
196 system_type := "MSC_Tests",
197 interface_version := hex2int('34'H),
198 addr_ton := unknown,
199 addr_npi := unknown,
200 address_range := ""
201 },
202 esme_role := true
203 }
204
205 vc_SMPP := SMPP_Emulation_CT.create(id);
206 map(vc_SMPP:SMPP_PORT, system:SMPP_PORT);
207 vc_SMPP.start(SMPP_Emulation.main_client(pars, mp_msc_ip, mp_msc_smpp_port, "", -1));
208}
209
210
Harald Weltea49e36e2018-01-21 19:29:33 +0100211function f_init_mncc(charstring id) runs on MTC_CT {
212 id := id & "-MNCC";
213 var MnccOps ops := {
214 create_cb := refers(MNCC_Emulation.ExpectedCreateCallback),
215 unitdata_cb := refers(MNCC_Emulation.DummyUnitdataCallback)
216 }
217
218 vc_MNCC := MNCC_Emulation_CT.create(id);
219 map(vc_MNCC:MNCC, system:MNCC_CODEC_PT);
220 vc_MNCC.start(MNCC_Emulation.main(ops, id, mp_msc_mncc));
Harald Weltef6dd64d2017-11-19 12:09:51 +0100221}
222
Harald Welte4aa970c2018-01-26 10:38:09 +0100223function f_init_mgcp(charstring id) runs on MTC_CT {
224 id := id & "-MGCP";
225 var MGCPOps ops := {
226 create_cb := refers(MGCP_Emulation.ExpectedCreateCallback),
227 unitdata_cb := refers(MGCP_Emulation.DummyUnitdataCallback)
228 }
229 var MGCP_conn_parameters pars := {
Harald Welte6126fb02018-01-27 20:08:24 +0100230 callagent_ip := mp_msc_ip,
Harald Welte4aa970c2018-01-26 10:38:09 +0100231 callagent_udp_port := -1,
Harald Welte6126fb02018-01-27 20:08:24 +0100232 mgw_ip := mp_mgw_ip,
Pau Espin Pedrol1a026a52019-06-18 17:21:52 +0200233 mgw_udp_port := mp_mgw_port,
234 multi_conn_mode := false
Harald Welte4aa970c2018-01-26 10:38:09 +0100235 }
236
237 vc_MGCP := MGCP_Emulation_CT.create(id);
238 map(vc_MGCP:MGCP, system:MGCP_CODEC_PT);
239 vc_MGCP.start(MGCP_Emulation.main(ops, pars, id));
240}
241
Philipp Maierc09a1312019-04-09 16:05:26 +0200242function ForwardUnitdataCallback(PDU_SGsAP msg)
243runs on SGsAP_Emulation_CT return template PDU_SGsAP {
244 SGsAP_CLIENT.send(msg);
245 return omit;
246}
247
Harald Welte4263c522018-12-06 11:56:27 +0100248function f_init_sgsap(charstring id) runs on MTC_CT {
249 id := id & "-SGsAP";
250 var SGsAPOps ops := {
251 create_cb := refers(SGsAP_Emulation.ExpectedCreateCallback),
Philipp Maierc09a1312019-04-09 16:05:26 +0200252 unitdata_cb := refers(ForwardUnitdataCallback)
Harald Welte4263c522018-12-06 11:56:27 +0100253 }
254 var SGsAP_conn_parameters pars := {
255 remote_ip := mp_msc_ip,
256 remote_sctp_port := 29118,
257 local_ip := "",
258 local_sctp_port := -1
259 }
260
261 vc_SGsAP := SGsAP_Emulation_CT.create(id);
262 map(vc_SGsAP:SGsAP, system:SGsAP_CODEC_PT);
263 vc_SGsAP.start(SGsAP_Emulation.main(ops, pars, id));
264}
265
266
Harald Weltea49e36e2018-01-21 19:29:33 +0100267function f_init_gsup(charstring id) runs on MTC_CT {
268 id := id & "-GSUP";
269 var GsupOps ops := {
270 create_cb := refers(GSUP_Emulation.ExpectedCreateCallback)
271 }
272
273 vc_GSUP_IPA := IPA_Emulation_CT.create(id & "-IPA");
274 vc_GSUP := GSUP_Emulation_CT.create(id);
275
276 map(vc_GSUP_IPA:IPA_PORT, system:IPA_CODEC_PT);
277 connect(vc_GSUP:GSUP, vc_GSUP_IPA:IPA_GSUP_PORT);
278 /* we use this hack to get events like ASP_IPA_EVENT_UP */
279 connect(vc_GSUP_IPA:IPA_CTRL_PORT, self:GSUP_IPA_EVENT);
280
281 vc_GSUP.start(GSUP_Emulation.main(ops, id));
282 vc_GSUP_IPA.start(IPA_Emulation.main_server(mp_hlr_ip, mp_hlr_port));
283
284 /* wait for incoming connection to GSUP port before proceeding */
285 timer T := 10.0;
286 T.start;
287 alt {
288 [] GSUP_IPA_EVENT.receive(t_ASP_IPA_EVT_UD(ASP_IPA_EVENT_UP)) { }
289 [] T.timeout {
Harald Welte458fd372018-03-21 11:26:23 +0100290 setverdict(fail, "No connection to GSUP Port");
Daniel Willmannafce8662018-07-06 23:11:32 +0200291 mtc.stop
Harald Weltea49e36e2018-01-21 19:29:33 +0100292 }
293 }
Harald Weltef6dd64d2017-11-19 12:09:51 +0100294}
295
Pau Espin Pedrola65697d2019-05-21 12:54:39 +0200296function 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 +0100297
298 if (g_initialized == true) {
299 return;
300 }
301 g_initialized := true;
302
Philipp Maier75932982018-03-27 14:52:35 +0200303 if (num_bsc > NUM_BSC) {
Daniel Willmannafce8662018-07-06 23:11:32 +0200304 testcase.stop("excess number of BSC instances requested");
Philipp Maier75932982018-03-27 14:52:35 +0200305 }
306
307 for (var integer i := 0; i < num_bsc; i := i + 1) {
308 if (isbound(mp_bssap_cfg[i])) {
Pau Espin Pedrola65697d2019-05-21 12:54:39 +0200309 var RanOps ranops := BSC_RanOps;
310 ranops.use_osmux := osmux;
311 f_ran_adapter_init(g_bssap[i], mp_bssap_cfg[i], "MSC_Test_" & int2str(i), ranops);
Harald Welte3ca0ce12019-04-23 17:18:48 +0200312 f_ran_adapter_start(g_bssap[i]);
Philipp Maier75932982018-03-27 14:52:35 +0200313 } else {
Daniel Willmannafce8662018-07-06 23:11:32 +0200314 testcase.stop("missing BSSAP configuration");
Philipp Maier75932982018-03-27 14:52:35 +0200315 }
316 }
317
Harald Weltea49e36e2018-01-21 19:29:33 +0100318 f_ipa_ctrl_start(mp_msc_ip, mp_msc_ctrl_port);
319 f_init_mncc("MSC_Test");
Harald Welte4aa970c2018-01-26 10:38:09 +0100320 f_init_mgcp("MSC_Test");
Philipp Maierc09a1312019-04-09 16:05:26 +0200321
322 if (gsup == true) {
323 f_init_gsup("MSC_Test");
324 }
Harald Weltef640a012018-04-14 17:49:21 +0200325 f_init_smpp("MSC_Test");
Philipp Maier57865482019-01-07 18:33:13 +0100326
Philipp Maier8e07a4a2019-02-14 18:23:28 +0100327 if (sgsap == true) {
Philipp Maier57865482019-01-07 18:33:13 +0100328 f_init_sgsap("MSC_Test");
329 }
Harald Welte3ca1c902018-01-24 18:51:27 +0100330
331 map(self:MSCVTY, system:MSCVTY);
332 f_vty_set_prompts(MSCVTY);
333 f_vty_transceive(MSCVTY, "enable");
Harald Welteb14c77a2018-01-25 17:25:44 +0100334
335 /* set some defaults */
336 f_vty_config(MSCVTY, "network", "authentication optional");
337 f_vty_config(MSCVTY, "msc", "assign-tmsi");
338 f_vty_config(MSCVTY, "network", "encryption a5 0");
Pau Espin Pedrol690d6592019-05-31 17:56:32 +0200339 if (mp_enable_osmux_test) {
340 if (osmux) {
341 f_vty_config(MSCVTY, "msc", "osmux on");
342 } else {
343 f_vty_config(MSCVTY, "msc", "osmux off");
344 }
Pau Espin Pedrol3dd33bc2019-05-31 17:51:20 +0200345 }
Harald Weltef6dd64d2017-11-19 12:09:51 +0100346}
347
Philipp Maier328d1662018-03-07 10:40:27 +0100348/* Initialize for a direct connection to BSSAP. This function is an alternative
349 * to f_init() when the high level functions of the BSC_ConnectionHandler are
350 * not needed. */
351function f_init_bssap_direct() runs on MTC_CT {
Harald Welte3ca0ce12019-04-23 17:18:48 +0200352 f_ran_adapter_init(g_bssap[0], mp_bssap_cfg[0], "MSC_Test", omit);
Philipp Maier75932982018-03-27 14:52:35 +0200353 connect(g_bssap[0].vc_SCCP:SCCP_SP_PORT, self:BSSAP_DIRECT);
Philipp Maier328d1662018-03-07 10:40:27 +0100354
355 /* Start guard timer and activate it as default */
356 Tguard_direct.start
357 activate(as_Tguard_direct());
358}
359
Harald Weltea49e36e2018-01-21 19:29:33 +0100360type function void_fn(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr;
Harald Weltef6dd64d2017-11-19 12:09:51 +0100361
Harald Weltea49e36e2018-01-21 19:29:33 +0100362/* FIXME: move into BSC_ConnectionHandler? */
Harald Welte9b751a62019-04-14 17:39:29 +0200363function f_init_pars(integer imsi_suffix, boolean sgsap := false, boolean gsup := true, integer ran_idx := 0,
Pau Espin Pedrola65697d2019-05-21 12:54:39 +0200364 boolean ran_is_geran := true, boolean use_osmux := false)
Harald Weltef9abf8d2019-04-21 13:07:17 +0200365runs on MTC_CT return BSC_ConnHdlrPars {
Harald Weltede371492018-01-27 23:44:41 +0100366 var BSC_ConnHdlrNetworkPars net_pars := {
367 kc_support := '0A'O, /* A5/1 and A5/3 enabled */
368 expect_tmsi := true,
369 expect_auth := false,
370 expect_ciph := false
371 };
Harald Weltea49e36e2018-01-21 19:29:33 +0100372 var BSC_ConnHdlrPars pars := {
Harald Weltef9abf8d2019-04-21 13:07:17 +0200373 sccp_addr_own := g_bssap[ran_idx].sccp_addr_own,
374 sccp_addr_peer := g_bssap[ran_idx].sccp_addr_peer,
Harald Welteedbab812018-03-18 16:02:25 +0100375 cell_id := valueof(ts_CellId_CGI('262'H, '42'H, 23, 42)),
Harald Welte81b7f9d2018-01-24 19:06:24 +0100376 imei := f_gen_imei(imsi_suffix),
377 imsi := f_gen_imsi(imsi_suffix),
378 msisdn := f_gen_msisdn(imsi_suffix),
Harald Welte256571e2018-01-24 18:47:19 +0100379 tmsi := omit,
Harald Welte9de84792018-01-28 01:06:35 +0100380 cm1 := valueof(ts_CM1),
Harald Welte82600572018-01-21 20:54:08 +0100381 cm2 := valueof(ts_CM2_default),
Harald Welte16114282018-01-24 22:41:21 +0100382 cm3 := omit,
Harald Weltede371492018-01-27 23:44:41 +0100383 vec := omit,
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +0100384 net := net_pars,
Philipp Maieraeb29a82018-11-08 17:40:53 +0100385 send_early_cm := true,
386 ipa_ctrl_ip := mp_msc_ip,
387 ipa_ctrl_port := mp_msc_ctrl_port,
Philipp Maier9b690e42018-12-21 11:50:03 +0100388 ipa_ctrl_enable := true,
Philipp Maier57865482019-01-07 18:33:13 +0100389 mm_info := mp_mm_info,
Philipp Maierc09a1312019-04-09 16:05:26 +0200390 sgsap_enable := sgsap,
Harald Weltef9abf8d2019-04-21 13:07:17 +0200391 gsup_enable := gsup,
Harald Weltec1f937a2019-04-21 21:19:23 +0200392 ran_idx := ran_idx,
Harald Welte9b751a62019-04-14 17:39:29 +0200393 use_umts_aka := false,
Pau Espin Pedrola65697d2019-05-21 12:54:39 +0200394 ran_is_geran := ran_is_geran,
395 use_osmux := use_osmux
Harald Weltea49e36e2018-01-21 19:29:33 +0100396 };
Harald Weltee13cfb22019-04-23 16:52:02 +0200397 if (not ran_is_geran) {
398 pars.use_umts_aka := true;
399 pars.net.expect_auth := true;
400 }
Neels Hofmeyr9adaa702018-03-01 20:23:19 +0100401 return pars;
402}
403
Neels Hofmeyr0ac63152019-05-07 01:20:17 +0200404function f_start_handler_with_pars(void_fn fn, BSC_ConnHdlrPars pars, integer bssap_idx := 0) runs on MTC_CT return BSC_ConnHdlr {
Neels Hofmeyr9adaa702018-03-01 20:23:19 +0100405 var BSC_ConnHdlr vc_conn;
Neels Hofmeyr0ac63152019-05-07 01:20:17 +0200406 var charstring id := testcasename() & int2str(bssap_idx);
Harald Weltea49e36e2018-01-21 19:29:33 +0100407
408 vc_conn := BSC_ConnHdlr.create(id);
409 /* BSSMAP part / A interface */
Neels Hofmeyr0ac63152019-05-07 01:20:17 +0200410 connect(vc_conn:BSSAP, g_bssap[pars.ran_idx + bssap_idx].vc_RAN:CLIENT);
411 connect(vc_conn:BSSAP_PROC, g_bssap[pars.ran_idx + bssap_idx].vc_RAN:PROC);
Harald Weltea49e36e2018-01-21 19:29:33 +0100412 /* MNCC part */
413 connect(vc_conn:MNCC, vc_MNCC:MNCC_CLIENT);
414 connect(vc_conn:MNCC_PROC, vc_MNCC:MNCC_PROC);
Harald Welte4aa970c2018-01-26 10:38:09 +0100415 /* MGCP part */
416 connect(vc_conn:MGCP, vc_MGCP:MGCP_CLIENT);
417 connect(vc_conn:MGCP_PROC, vc_MGCP:MGCP_PROC);
Harald Weltea49e36e2018-01-21 19:29:33 +0100418 /* GSUP part */
Philipp Maierc09a1312019-04-09 16:05:26 +0200419 if (pars.gsup_enable == true) {
420 connect(vc_conn:GSUP, vc_GSUP:GSUP_CLIENT);
421 connect(vc_conn:GSUP_PROC, vc_GSUP:GSUP_PROC);
422 }
Harald Weltef640a012018-04-14 17:49:21 +0200423 /* SMPP part */
424 connect(vc_conn:SMPP, vc_SMPP:SMPP_CLIENT);
425 connect(vc_conn:SMPP_PROC, vc_SMPP:SMPP_PROC);
Harald Welte4263c522018-12-06 11:56:27 +0100426 /* SGs part */
Philipp Maier8e07a4a2019-02-14 18:23:28 +0100427 if (pars.sgsap_enable == true) {
Philipp Maier57865482019-01-07 18:33:13 +0100428 connect(vc_conn:SGsAP, vc_SGsAP:SGsAP_CLIENT);
429 connect(vc_conn:SGsAP_PROC, vc_SGsAP:SGsAP_PROC);
430 }
Harald Weltea49e36e2018-01-21 19:29:33 +0100431
Harald Weltea10db902018-01-27 12:44:49 +0100432 /* We cannot use vc_conn.start(f_init_handler(fn, id, pars)); as we cannot have
433 * a stand-alone 'derefers()' call, see https://www.eclipse.org/forums/index.php/t/1091364/ */
Harald Weltea49e36e2018-01-21 19:29:33 +0100434 vc_conn.start(derefers(fn)(id, pars));
435 return vc_conn;
436}
437
Pau Espin Pedrola65697d2019-05-21 12:54:39 +0200438function f_start_handler(void_fn fn, integer imsi_suffix, integer ran_idx := 0, boolean ran_is_geran := true, boolean use_osmux := false)
Harald Welte9b751a62019-04-14 17:39:29 +0200439runs on MTC_CT return BSC_ConnHdlr {
Pau Espin Pedrola65697d2019-05-21 12:54:39 +0200440 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));
Neels Hofmeyr9adaa702018-03-01 20:23:19 +0100441}
442
Harald Weltea49e36e2018-01-21 19:29:33 +0100443private function f_tc_lu_imsi_noauth_tmsi(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +0100444 f_init_handler(pars);
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +0100445 f_perform_lu();
Harald Weltea49e36e2018-01-21 19:29:33 +0100446}
Harald Weltea49e36e2018-01-21 19:29:33 +0100447testcase TC_lu_imsi_noauth_tmsi() runs on MTC_CT {
448 var BSC_ConnHdlr vc_conn;
449 f_init();
450
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +0100451 vc_conn := f_start_handler(refers(f_tc_lu_imsi_noauth_tmsi), 1);
Harald Weltea49e36e2018-01-21 19:29:33 +0100452 vc_conn.done;
453}
454
455private function f_tc_lu_imsi_noauth_notmsi(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltede371492018-01-27 23:44:41 +0100456 pars.net.expect_tmsi := false;
Harald Weltea10db902018-01-27 12:44:49 +0100457 f_init_handler(pars);
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +0100458 f_perform_lu();
Harald Weltea49e36e2018-01-21 19:29:33 +0100459}
Harald Weltea49e36e2018-01-21 19:29:33 +0100460testcase TC_lu_imsi_noauth_notmsi() runs on MTC_CT {
461 var BSC_ConnHdlr vc_conn;
462 f_init();
Harald Welte3ca1c902018-01-24 18:51:27 +0100463 f_vty_config(MSCVTY, "msc", "no assign-tmsi");
Harald Weltea49e36e2018-01-21 19:29:33 +0100464
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +0100465 vc_conn := f_start_handler(refers(f_tc_lu_imsi_noauth_notmsi), 2);
Harald Weltea49e36e2018-01-21 19:29:33 +0100466 vc_conn.done;
467}
468
469/* Do LU by IMSI, refuse it on GSUP and expect LU REJ back to MS */
Harald Weltee13cfb22019-04-23 16:52:02 +0200470friend function f_tc_lu_imsi_reject(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +0100471 f_init_handler(pars);
Harald Weltea49e36e2018-01-21 19:29:33 +0100472 var PDU_ML3_MS_NW l3_lu := f_build_lu_imsi(g_pars.imsi);
473
474 f_create_gsup_expect(hex2str(g_pars.imsi));
Harald Weltedceacc72019-04-21 20:58:35 +0200475 f_cl3_or_initial_ue(l3_lu);
Harald Welteb7817992019-05-09 13:15:39 +0200476 f_mm_auth();
Harald Weltea49e36e2018-01-21 19:29:33 +0100477 GSUP.receive(tr_GSUP_UL_REQ(g_pars.imsi));
478 GSUP.send(ts_GSUP_UL_ERR(g_pars.imsi, 23));
479 alt {
Harald Welte5946b332018-03-18 23:32:21 +0100480 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Rej(int2oct(23,1)))) {
481 f_expect_clear();
482 }
Harald Weltea49e36e2018-01-21 19:29:33 +0100483 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Acc)) {
484 setverdict(fail, "Expecting LU REJ, but got ACCEPT");
Daniel Willmannafce8662018-07-06 23:11:32 +0200485 mtc.stop;
Harald Weltea49e36e2018-01-21 19:29:33 +0100486 }
487 }
Harald Weltea49e36e2018-01-21 19:29:33 +0100488}
489testcase TC_lu_imsi_reject() runs on MTC_CT {
490 var BSC_ConnHdlr vc_conn;
491 f_init();
492
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +0100493 vc_conn := f_start_handler(refers(f_tc_lu_imsi_reject), 3);
Harald Weltea49e36e2018-01-21 19:29:33 +0100494 vc_conn.done;
495}
496
Harald Weltee13cfb22019-04-23 16:52:02 +0200497
498
Harald Weltea49e36e2018-01-21 19:29:33 +0100499/* Do LU by IMSI, timeout on GSUP */
Harald Weltee13cfb22019-04-23 16:52:02 +0200500friend function f_tc_lu_imsi_timeout_gsup(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +0100501 f_init_handler(pars);
Harald Weltea49e36e2018-01-21 19:29:33 +0100502 var PDU_ML3_MS_NW l3_lu := f_build_lu_imsi(g_pars.imsi);
503
504 f_create_gsup_expect(hex2str(g_pars.imsi));
Harald Weltedceacc72019-04-21 20:58:35 +0200505 f_cl3_or_initial_ue(l3_lu);
Harald Welteb7817992019-05-09 13:15:39 +0200506 f_mm_auth();
Harald Weltea49e36e2018-01-21 19:29:33 +0100507 GSUP.receive(tr_GSUP_UL_REQ(g_pars.imsi));
508 /* Normally the HLR would need to respond here, but we decide to force a timeout here */
509 alt {
510 /* FIXME: Expect specific reject cause */
Harald Welte5946b332018-03-18 23:32:21 +0100511 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Rej)) {
512 f_expect_clear();
513 }
Harald Weltea49e36e2018-01-21 19:29:33 +0100514 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Acc)) {
515 setverdict(fail, "Expecting LU REJ, but got ACCEPT");
Daniel Willmannafce8662018-07-06 23:11:32 +0200516 mtc.stop;
Harald Weltea49e36e2018-01-21 19:29:33 +0100517 }
518 }
Harald Weltea49e36e2018-01-21 19:29:33 +0100519}
520testcase TC_lu_imsi_timeout_gsup() runs on MTC_CT {
521 var BSC_ConnHdlr vc_conn;
522 f_init();
523
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +0100524 vc_conn := f_start_handler(refers(f_tc_lu_imsi_timeout_gsup), 4);
Harald Weltea49e36e2018-01-21 19:29:33 +0100525 vc_conn.done;
526}
527
Harald Weltee13cfb22019-04-23 16:52:02 +0200528
Harald Welte7b1b2812018-01-22 21:23:06 +0100529private function f_tc_lu_imsi_auth_tmsi(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltede371492018-01-27 23:44:41 +0100530 pars.net.expect_auth := true;
Harald Weltea10db902018-01-27 12:44:49 +0100531 f_init_handler(pars);
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +0100532 f_perform_lu();
Harald Welte7b1b2812018-01-22 21:23:06 +0100533}
534testcase TC_lu_imsi_auth_tmsi() runs on MTC_CT {
535 var BSC_ConnHdlr vc_conn;
536 f_init();
Harald Welte3ca1c902018-01-24 18:51:27 +0100537 f_vty_config(MSCVTY, "network", "authentication required");
Harald Welte7b1b2812018-01-22 21:23:06 +0100538
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +0100539 vc_conn := f_start_handler(refers(f_tc_lu_imsi_auth_tmsi), 5);
Harald Welte7b1b2812018-01-22 21:23:06 +0100540 vc_conn.done;
541}
542
Harald Weltee13cfb22019-04-23 16:52:02 +0200543
544friend function f_tc_lu_imsi_auth3g_tmsi(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Welte8a397ae2019-04-21 22:03:37 +0200545 pars.net.expect_auth := true;
546 pars.use_umts_aka := true;
547 f_init_handler(pars);
548 f_perform_lu();
549}
550testcase TC_lu_imsi_auth3g_tmsi() runs on MTC_CT {
551 var BSC_ConnHdlr vc_conn;
552 f_init();
553 f_vty_config(MSCVTY, "network", "authentication required");
554
555 vc_conn := f_start_handler(refers(f_tc_lu_imsi_auth3g_tmsi), 1005);
556 vc_conn.done;
557}
Harald Weltea49e36e2018-01-21 19:29:33 +0100558
Harald Weltee13cfb22019-04-23 16:52:02 +0200559
Harald Weltea49e36e2018-01-21 19:29:33 +0100560/* Send CM SERVICE REQ for IMSI that has never performed LU before */
Harald Weltee13cfb22019-04-23 16:52:02 +0200561friend function f_tc_cmserv_imsi_unknown(charstring id, BSC_ConnHdlrPars pars)
Harald Weltea49e36e2018-01-21 19:29:33 +0100562runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +0100563 f_init_handler(pars);
Harald Weltea49e36e2018-01-21 19:29:33 +0100564
565 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
Harald Welteedbab812018-03-18 16:02:25 +0100566 var BSSMAP_IE_CellIdentifier cell_id := valueof(ts_CellId_CGI('262'H, '42'H, 23, 42));
Harald Welte6ed6bf92018-01-24 21:09:15 +0100567 var PDU_ML3_MS_NW l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, mi));
Harald Weltea49e36e2018-01-21 19:29:33 +0100568
569 f_create_gsup_expect(hex2str(g_pars.imsi));
570
571 /* Send BSSAP_Conn_Req with COMPL L3 INFO to MSC */
Harald Weltedceacc72019-04-21 20:58:35 +0200572 f_cl3_or_initial_ue(l3_info);
Harald Welteb7817992019-05-09 13:15:39 +0200573 f_mm_auth();
Harald Weltea49e36e2018-01-21 19:29:33 +0100574
575 timer T := 10.0;
Harald Weltef6dd64d2017-11-19 12:09:51 +0100576 T.start;
577 alt {
Harald Weltea49e36e2018-01-21 19:29:33 +0100578 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_CM_SERV_REJ)) { }
579 //[] BSSAP.receive(tr_PDU_DTAP_MT(tr_CM_SERV_ACC)) { }
Daniel Willmannafce8662018-07-06 23:11:32 +0200580 [] BSSAP.receive {
581 setverdict(fail, "Received unexpected BSSAP");
582 mtc.stop;
583 }
Harald Weltea49e36e2018-01-21 19:29:33 +0100584 [] GSUP.receive(tr_GSUP_UL_REQ(g_pars.imsi)) {
585 setverdict(fail, "Unexpected GSUP UL REQ");
Daniel Willmannafce8662018-07-06 23:11:32 +0200586 mtc.stop;
Harald Weltea49e36e2018-01-21 19:29:33 +0100587 }
Daniel Willmannafce8662018-07-06 23:11:32 +0200588 [] T.timeout {
589 setverdict(fail, "Timeout waiting for CM SERV REQ");
590 mtc.stop;
591 }
Harald Weltef6dd64d2017-11-19 12:09:51 +0100592 }
593
Harald Welte1ddc7162018-01-27 14:25:46 +0100594 f_expect_clear();
Harald Weltef6dd64d2017-11-19 12:09:51 +0100595}
Harald Weltea49e36e2018-01-21 19:29:33 +0100596testcase TC_cmserv_imsi_unknown() runs on MTC_CT {
597 var BSC_ConnHdlr vc_conn;
598 f_init();
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +0100599 vc_conn := f_start_handler(refers(f_tc_cmserv_imsi_unknown), 6);
Harald Weltea49e36e2018-01-21 19:29:33 +0100600 vc_conn.done;
601}
602
Harald Weltee13cfb22019-04-23 16:52:02 +0200603
604friend function f_tc_lu_and_mo_call(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +0100605 f_init_handler(pars);
Harald Welteb71901a2018-01-26 19:16:05 +0100606 var CallParameters cpars := valueof(t_CallParams('12345'H, 0));
607 cpars.bss_rtp_port := 1110;
608 cpars.mgcp_connection_id_bss := '22222'H;
609 cpars.mgcp_connection_id_mss := '33333'H;
Philipp Maierf1e02bb2018-03-15 16:30:00 +0100610 cpars.mgcp_ep := "rtpbridge/1@mgw";
Harald Welte2bb825f2018-01-22 11:31:18 +0100611
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +0100612 f_perform_lu();
Harald Welteb71901a2018-01-26 19:16:05 +0100613 f_mo_call(cpars);
Harald Welte2bb825f2018-01-22 11:31:18 +0100614}
615testcase TC_lu_and_mo_call() runs on MTC_CT {
616 var BSC_ConnHdlr vc_conn;
617 f_init();
618
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +0100619 vc_conn := f_start_handler(refers(f_tc_lu_and_mo_call), 7);
Harald Welte071ed732018-01-23 19:53:52 +0100620 vc_conn.done;
621}
622
Harald Weltee13cfb22019-04-23 16:52:02 +0200623
Harald Welte071ed732018-01-23 19:53:52 +0100624/* Test LU (with authentication enabled), where HLR times out sending SAI response */
Harald Weltee13cfb22019-04-23 16:52:02 +0200625friend function f_tc_lu_auth_sai_timeout(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +0100626 f_init_handler(pars);
Harald Welte071ed732018-01-23 19:53:52 +0100627
628 var PDU_ML3_MS_NW l3_lu := f_build_lu_imsi(g_pars.imsi)
629 var PDU_DTAP_MT dtap_mt;
630
631 /* tell GSUP dispatcher to send this IMSI to us */
632 f_create_gsup_expect(hex2str(g_pars.imsi));
633
634 /* Send BSSAP_Conn_Req with COMPL L3 INFO to MSC */
Harald Weltedceacc72019-04-21 20:58:35 +0200635 f_cl3_or_initial_ue(l3_lu);
Harald Welte071ed732018-01-23 19:53:52 +0100636
637 /* Send Early Classmark, just for the fun of it */
Harald Weltee13cfb22019-04-23 16:52:02 +0200638 if (pars.ran_is_geran) {
639 BSSAP.send(ts_BSSMAP_ClassmarkUpd(g_pars.cm2, g_pars.cm3));
640 }
Harald Welte071ed732018-01-23 19:53:52 +0100641
642 GSUP.receive(tr_GSUP_SAI_REQ(g_pars.imsi));
643 /* The HLR would normally return an auth vector here, but we fail to do so. */
644
645 BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Rej));
Harald Welte1ddc7162018-01-27 14:25:46 +0100646 f_expect_clear();
Harald Welte071ed732018-01-23 19:53:52 +0100647}
648testcase TC_lu_auth_sai_timeout() runs on MTC_CT {
649 var BSC_ConnHdlr vc_conn;
650 f_init();
Harald Welte3ca1c902018-01-24 18:51:27 +0100651 f_vty_config(MSCVTY, "network", "authentication required");
Harald Welte071ed732018-01-23 19:53:52 +0100652
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +0100653 vc_conn := f_start_handler(refers(f_tc_lu_auth_sai_timeout), 8);
Harald Welte071ed732018-01-23 19:53:52 +0100654 vc_conn.done;
655}
656
Harald Weltee13cfb22019-04-23 16:52:02 +0200657
Harald Welte071ed732018-01-23 19:53:52 +0100658/* Test LU (with authentication enabled), where HLR rejects sending SAI error */
Harald Weltee13cfb22019-04-23 16:52:02 +0200659friend function f_tc_lu_auth_sai_err(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +0100660 f_init_handler(pars);
Harald Welte071ed732018-01-23 19:53:52 +0100661
662 var PDU_ML3_MS_NW l3_lu := f_build_lu_imsi(g_pars.imsi)
663 var PDU_DTAP_MT dtap_mt;
664
665 /* tell GSUP dispatcher to send this IMSI to us */
666 f_create_gsup_expect(hex2str(g_pars.imsi));
667
668 /* Send BSSAP_Conn_Req with COMPL L3 INFO to MSC */
Harald Weltedceacc72019-04-21 20:58:35 +0200669 f_cl3_or_initial_ue(l3_lu);
Harald Welte071ed732018-01-23 19:53:52 +0100670
671 /* Send Early Classmark, just for the fun of it */
Harald Weltee13cfb22019-04-23 16:52:02 +0200672 if (pars.ran_is_geran) {
673 BSSAP.send(ts_BSSMAP_ClassmarkUpd(g_pars.cm2, g_pars.cm3));
674 }
Harald Welte071ed732018-01-23 19:53:52 +0100675
676 GSUP.receive(tr_GSUP_SAI_REQ(g_pars.imsi));
677 GSUP.send(ts_GSUP_SAI_ERR(g_pars.imsi, 13));
678
679 BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Rej));
Harald Welte1ddc7162018-01-27 14:25:46 +0100680 f_expect_clear();
Harald Welte071ed732018-01-23 19:53:52 +0100681}
682testcase TC_lu_auth_sai_err() runs on MTC_CT {
683 var BSC_ConnHdlr vc_conn;
684 f_init();
Harald Welte3ca1c902018-01-24 18:51:27 +0100685 f_vty_config(MSCVTY, "network", "authentication required");
Harald Welte071ed732018-01-23 19:53:52 +0100686
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +0100687 vc_conn := f_start_handler(refers(f_tc_lu_auth_sai_err), 9);
Harald Welte2bb825f2018-01-22 11:31:18 +0100688 vc_conn.done;
689}
Harald Weltea49e36e2018-01-21 19:29:33 +0100690
Harald Weltee13cfb22019-04-23 16:52:02 +0200691
Harald Weltebc881782018-01-23 20:09:15 +0100692/* Test LU but BSC will send a clear request in the middle */
693private function f_tc_lu_clear_request(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +0100694 f_init_handler(pars);
Harald Weltebc881782018-01-23 20:09:15 +0100695
696 var PDU_ML3_MS_NW l3_lu := f_build_lu_imsi(g_pars.imsi)
697 var PDU_DTAP_MT dtap_mt;
698
699 /* tell GSUP dispatcher to send this IMSI to us */
700 f_create_gsup_expect(hex2str(g_pars.imsi));
701
702 /* Send BSSAP_Conn_Req with COMPL L3 INFO to MSC */
Harald Weltedceacc72019-04-21 20:58:35 +0200703 f_cl3_or_initial_ue(l3_lu);
Harald Weltebc881782018-01-23 20:09:15 +0100704
705 /* Send Early Classmark, just for the fun of it */
706 BSSAP.send(ts_BSSMAP_ClassmarkUpd(g_pars.cm2, g_pars.cm3));
707
708 f_sleep(1.0);
709 /* send clear request in the middle of the LU */
710 BSSAP.send(ts_BSSMAP_ClearRequest(0));
Neels Hofmeyr2b326fa2018-04-06 00:59:36 +0200711 alt {
712 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Rej)) { repeat; }
713 [] BSSAP.receive(tr_BSSMAP_ClearCommand) {}
714 }
Harald Weltebc881782018-01-23 20:09:15 +0100715 BSSAP.send(ts_BSSMAP_ClearComplete);
Harald Welte89a32492018-01-27 19:07:28 +0100716 alt {
717 /* See https://osmocom.org/issues/2862 */
Neels Hofmeyr2b326fa2018-04-06 00:59:36 +0200718 [] BSSAP.receive(tr_BSSMAP_ClearCommand) {
719 setverdict(fail, "Got a second Clear Command, only one expected");
Daniel Willmannafce8662018-07-06 23:11:32 +0200720 mtc.stop;
Neels Hofmeyr2b326fa2018-04-06 00:59:36 +0200721 repeat;
722 }
Harald Welte6811d102019-04-14 22:23:14 +0200723 [] BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_IND) {}
Harald Welte89a32492018-01-27 19:07:28 +0100724 }
Harald Weltebc881782018-01-23 20:09:15 +0100725 setverdict(pass);
726}
727testcase TC_lu_clear_request() runs on MTC_CT {
728 var BSC_ConnHdlr vc_conn;
729 f_init();
730
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +0100731 vc_conn := f_start_handler(refers(f_tc_lu_clear_request), 10);
Harald Weltebc881782018-01-23 20:09:15 +0100732 vc_conn.done;
733}
734
Harald Welte66af9e62018-01-24 17:28:21 +0100735/* Test LU but BSC will send a clear request in the middle */
Harald Weltee13cfb22019-04-23 16:52:02 +0200736friend function f_tc_lu_disconnect(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +0100737 f_init_handler(pars);
Harald Welte66af9e62018-01-24 17:28:21 +0100738
739 var PDU_ML3_MS_NW l3_lu := f_build_lu_imsi(g_pars.imsi)
740 var PDU_DTAP_MT dtap_mt;
741
742 /* tell GSUP dispatcher to send this IMSI to us */
743 f_create_gsup_expect(hex2str(g_pars.imsi));
744
745 /* Send BSSAP_Conn_Req with COMPL L3 INFO to MSC */
Harald Weltedceacc72019-04-21 20:58:35 +0200746 f_cl3_or_initial_ue(l3_lu);
Harald Welte66af9e62018-01-24 17:28:21 +0100747
748 /* Send Early Classmark, just for the fun of it */
Harald Weltee13cfb22019-04-23 16:52:02 +0200749 if (pars.ran_is_geran) {
750 BSSAP.send(ts_BSSMAP_ClassmarkUpd(g_pars.cm2, g_pars.cm3));
751 }
Harald Welte66af9e62018-01-24 17:28:21 +0100752
753 f_sleep(1.0);
754 /* send clear request in the middle of the LU */
Harald Welte6811d102019-04-14 22:23:14 +0200755 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
Harald Welte66af9e62018-01-24 17:28:21 +0100756 setverdict(pass);
Neels Hofmeyrbb825c92019-03-06 15:35:50 +0100757 f_sleep(1.0);
Harald Welte66af9e62018-01-24 17:28:21 +0100758}
759testcase TC_lu_disconnect() runs on MTC_CT {
760 var BSC_ConnHdlr vc_conn;
761 f_init();
762
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +0100763 vc_conn := f_start_handler(refers(f_tc_lu_disconnect), 11);
Harald Welte66af9e62018-01-24 17:28:21 +0100764 vc_conn.done;
765}
766
Harald Welteba7b6d92018-01-23 21:32:34 +0100767/* Test LU but with illegal mobile identity type = IMEI */
Harald Weltee13cfb22019-04-23 16:52:02 +0200768friend function f_tc_lu_by_imei(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +0100769 f_init_handler(pars);
Harald Welteba7b6d92018-01-23 21:32:34 +0100770
Harald Welte256571e2018-01-24 18:47:19 +0100771 var PDU_ML3_MS_NW l3_lu := f_build_lu_imei(g_pars.imei)
Harald Welteba7b6d92018-01-23 21:32:34 +0100772 var PDU_DTAP_MT dtap_mt;
773
774 /* tell GSUP dispatcher to send this IMSI to us */
775 f_create_gsup_expect(hex2str(g_pars.imsi));
776
777 /* Send BSSAP_Conn_Req with COMPL L3 INFO to MSC */
Harald Weltedceacc72019-04-21 20:58:35 +0200778 f_cl3_or_initial_ue(l3_lu);
Harald Welteba7b6d92018-01-23 21:32:34 +0100779
780 /* Send Early Classmark, just for the fun of it */
Harald Weltee13cfb22019-04-23 16:52:02 +0200781 if (pars.ran_is_geran) {
782 BSSAP.send(ts_BSSMAP_ClassmarkUpd(g_pars.cm2, g_pars.cm3));
783 }
Harald Welteba7b6d92018-01-23 21:32:34 +0100784 /* wait for LU reject, ignore any ID REQ */
785 alt {
786 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Rej)) { }
787 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_MM_ID_Req)) { repeat; }
788 }
789 /* wait for normal teardown */
Harald Welte1ddc7162018-01-27 14:25:46 +0100790 f_expect_clear();
Harald Welteba7b6d92018-01-23 21:32:34 +0100791}
792testcase TC_lu_by_imei() runs on MTC_CT {
793 var BSC_ConnHdlr vc_conn;
794 f_init();
795
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +0100796 vc_conn := f_start_handler(refers(f_tc_lu_by_imei), 12);
Harald Welteba7b6d92018-01-23 21:32:34 +0100797 vc_conn.done;
798}
799
Harald Weltee13cfb22019-04-23 16:52:02 +0200800
Harald Welteba7b6d92018-01-23 21:32:34 +0100801/* Test LU by TMSI with unknown TMSI, expect (and answer) ID REQ. */
802private function f_tc_lu_tmsi_noauth_unknown(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Stefan Sperling04fc4bc2018-06-25 17:44:57 +0200803 /* We piggyback a test for an MSC crash on overlong IMSI (OS#2864) onto this test. */
804 var hexstring overlong_imsi := '012345789ABCDEF0123456789ABCDEF'H;
Harald Weltea10db902018-01-27 12:44:49 +0100805 f_init_handler(pars);
Harald Welteba7b6d92018-01-23 21:32:34 +0100806
807 var PDU_ML3_MS_NW l3_lu := f_build_lu_tmsi('01020304'O); /* FIXME: Random */
808 var PDU_DTAP_MT dtap_mt;
809
810 /* tell GSUP dispatcher to send this IMSI to us */
811 f_create_gsup_expect(hex2str(g_pars.imsi));
812
813 /* Send BSSAP_Conn_Req with COMPL L3 INFO to MSC */
Harald Weltedceacc72019-04-21 20:58:35 +0200814 f_cl3_or_initial_ue(l3_lu);
Harald Welteba7b6d92018-01-23 21:32:34 +0100815
816 /* Send Early Classmark, just for the fun of it */
817 BSSAP.send(ts_BSSMAP_ClassmarkUpd(g_pars.cm2, g_pars.cm3));
818
819 /* Wait for + respond to ID REQ (IMSI) */
820 BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_MM_ID_Req('001'B)));
Stefan Sperling04fc4bc2018-06-25 17:44:57 +0200821 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 +0100822 BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_MM_ID_Rsp_IMSI(g_pars.imsi)));
823
824 /* Expect MSC to do UpdateLocation to HLR; respond to it */
825 GSUP.receive(tr_GSUP_UL_REQ(g_pars.imsi));
826 GSUP.send(ts_GSUP_ISD_REQ(g_pars.imsi, g_pars.msisdn));
827 GSUP.receive(tr_GSUP_ISD_RES(g_pars.imsi));
828 GSUP.send(ts_GSUP_UL_RES(g_pars.imsi));
829
830 alt {
Harald Welte7ec4fa82018-01-27 10:57:40 +0100831 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Acc)) {
832 BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_TmsiRealloc_Cmpl));
833 }
Harald Welteba7b6d92018-01-23 21:32:34 +0100834 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Rej)) {
835 setverdict(fail, "Expected LU ACK, but received REJ");
Daniel Willmannafce8662018-07-06 23:11:32 +0200836 mtc.stop;
Harald Welteba7b6d92018-01-23 21:32:34 +0100837 }
838 }
839
Philipp Maier9b690e42018-12-21 11:50:03 +0100840 /* Wait for MM-Information (if enabled) */
841 f_expect_mm_info();
842
Harald Welteba7b6d92018-01-23 21:32:34 +0100843 /* wait for normal teardown */
Harald Welte1ddc7162018-01-27 14:25:46 +0100844 f_expect_clear();
Harald Welteba7b6d92018-01-23 21:32:34 +0100845}
846testcase TC_lu_by_tmsi_noauth_unknown() runs on MTC_CT {
847 var BSC_ConnHdlr vc_conn;
848 f_init();
849
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +0100850 vc_conn := f_start_handler(refers(f_tc_lu_tmsi_noauth_unknown), 13);
Harald Welteba7b6d92018-01-23 21:32:34 +0100851 vc_conn.done;
852}
853
854
Harald Welte45164da2018-01-24 12:51:27 +0100855/* Test IMSI DETACH (MI=IMSI) */
Harald Weltee13cfb22019-04-23 16:52:02 +0200856friend function f_tc_imsi_detach_by_imsi(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +0100857 f_init_handler(pars);
Harald Welte45164da2018-01-24 12:51:27 +0100858
859 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
860
861 /* Send BSSAP_Conn_Req with COMPL L3 INFO to MSC */
Harald Weltedceacc72019-04-21 20:58:35 +0200862 f_cl3_or_initial_ue(valueof(ts_ML3_MO_MM_IMSI_DET_Ind(mi)));
Harald Welte45164da2018-01-24 12:51:27 +0100863
864 /* Send Early Classmark, just for the fun of it? */
Harald Weltee13cfb22019-04-23 16:52:02 +0200865 if (pars.ran_is_geran) {
866 BSSAP.send(ts_BSSMAP_ClassmarkUpd(g_pars.cm2, g_pars.cm3));
867 }
Harald Welte45164da2018-01-24 12:51:27 +0100868
869 /* wait for normal teardown */
Harald Welte1ddc7162018-01-27 14:25:46 +0100870 f_expect_clear();
Harald Welte45164da2018-01-24 12:51:27 +0100871}
872testcase TC_imsi_detach_by_imsi() runs on MTC_CT {
873 var BSC_ConnHdlr vc_conn;
874 f_init();
875
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +0100876 vc_conn := f_start_handler(refers(f_tc_imsi_detach_by_imsi), 14);
Harald Welte45164da2018-01-24 12:51:27 +0100877 vc_conn.done;
878}
879
Harald Weltee13cfb22019-04-23 16:52:02 +0200880
Harald Welte45164da2018-01-24 12:51:27 +0100881/* Test IMSI DETACH (MI=TMSI) */
Harald Weltee13cfb22019-04-23 16:52:02 +0200882friend function f_tc_imsi_detach_by_tmsi(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +0100883 f_init_handler(pars);
Harald Welte45164da2018-01-24 12:51:27 +0100884
885 var MobileIdentityLV mi := valueof(ts_MI_TMSI_LV('01020304'O));
886
887 /* Send BSSAP_Conn_Req with COMPL L3 INFO to MSC */
Harald Weltedceacc72019-04-21 20:58:35 +0200888 f_cl3_or_initial_ue(valueof(ts_ML3_MO_MM_IMSI_DET_Ind(mi)));
Harald Welte45164da2018-01-24 12:51:27 +0100889
890 /* Send Early Classmark, just for the fun of it? */
Harald Weltee13cfb22019-04-23 16:52:02 +0200891 if (pars.ran_is_geran) {
892 BSSAP.send(ts_BSSMAP_ClassmarkUpd(g_pars.cm2, g_pars.cm3));
893 }
Harald Welte45164da2018-01-24 12:51:27 +0100894
895 /* wait for normal teardown */
Harald Welte1ddc7162018-01-27 14:25:46 +0100896 f_expect_clear();
Harald Welte45164da2018-01-24 12:51:27 +0100897}
898testcase TC_imsi_detach_by_tmsi() runs on MTC_CT {
899 var BSC_ConnHdlr vc_conn;
900 f_init();
901
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +0100902 vc_conn := f_start_handler(refers(f_tc_imsi_detach_by_tmsi), 15);
Harald Welte45164da2018-01-24 12:51:27 +0100903 vc_conn.done;
904}
905
Harald Weltee13cfb22019-04-23 16:52:02 +0200906
Harald Welte45164da2018-01-24 12:51:27 +0100907/* Test IMSI DETACH (MI=IMEI), which is illegal */
Harald Weltee13cfb22019-04-23 16:52:02 +0200908friend function f_tc_imsi_detach_by_imei(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +0100909 f_init_handler(pars);
Harald Welte45164da2018-01-24 12:51:27 +0100910
Harald Welte256571e2018-01-24 18:47:19 +0100911 var MobileIdentityLV mi := valueof(ts_MI_IMEI_LV(g_pars.imei));
Harald Welte45164da2018-01-24 12:51:27 +0100912
913 /* Send BSSAP_Conn_Req with COMPL L3 INFO to MSC */
Harald Weltedceacc72019-04-21 20:58:35 +0200914 f_cl3_or_initial_ue(valueof(ts_ML3_MO_MM_IMSI_DET_Ind(mi)));
Harald Welte45164da2018-01-24 12:51:27 +0100915
916 /* Send Early Classmark, just for the fun of it? */
Harald Weltee13cfb22019-04-23 16:52:02 +0200917 if (pars.ran_is_geran) {
918 BSSAP.send(ts_BSSMAP_ClassmarkUpd(g_pars.cm2, g_pars.cm3));
919 }
Harald Welte45164da2018-01-24 12:51:27 +0100920
921 /* wait for normal teardown */
Harald Welte1ddc7162018-01-27 14:25:46 +0100922 f_expect_clear();
Harald Welte45164da2018-01-24 12:51:27 +0100923}
924testcase TC_imsi_detach_by_imei() runs on MTC_CT {
925 var BSC_ConnHdlr vc_conn;
926 f_init();
927
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +0100928 vc_conn := f_start_handler(refers(f_tc_imsi_detach_by_imei), 16);
Harald Welte45164da2018-01-24 12:51:27 +0100929 vc_conn.done;
930}
931
932
933/* helper function for an emergency call. caller passes in mobile identity to use */
934private function f_emerg_call(MobileIdentityLV mi) runs on BSC_ConnHdlr {
Harald Welte0bef21e2018-02-10 09:48:23 +0100935 var CallParameters cpars := valueof(t_CallParams('112'H, 0));
936 cpars.emergency := true;
Philipp Maierf1e02bb2018-03-15 16:30:00 +0100937 cpars.mgcp_ep := "rtpbridge/1@mgw";
Harald Welte45164da2018-01-24 12:51:27 +0100938
Harald Welte0bef21e2018-02-10 09:48:23 +0100939 f_mo_call(cpars);
Harald Welte45164da2018-01-24 12:51:27 +0100940}
941
942/* establish an emergency call by IMEI, no SIM inserted (and hence no IMSI) */
Harald Weltee13cfb22019-04-23 16:52:02 +0200943friend function f_tc_emerg_call_imei_reject(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +0100944 f_init_handler(pars);
Harald Welte45164da2018-01-24 12:51:27 +0100945
Harald Welte256571e2018-01-24 18:47:19 +0100946 var MobileIdentityLV mi := valueof(ts_MI_IMEI_LV(g_pars.imei));
Harald Welte6ed6bf92018-01-24 21:09:15 +0100947 var PDU_ML3_MS_NW l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_EMERG_CALL, mi));
Harald Weltedceacc72019-04-21 20:58:35 +0200948 f_cl3_or_initial_ue(l3_info);
Harald Welte45164da2018-01-24 12:51:27 +0100949 BSSAP.receive(tr_PDU_DTAP_MT(tr_CM_SERV_REJ('05'O)));
Harald Welte1ddc7162018-01-27 14:25:46 +0100950 f_expect_clear();
Harald Welte45164da2018-01-24 12:51:27 +0100951}
952testcase TC_emerg_call_imei_reject() runs on MTC_CT {
953 var BSC_ConnHdlr vc_conn;
954 f_init();
955
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +0100956 vc_conn := f_start_handler(refers(f_tc_emerg_call_imei_reject), 17);
Harald Welte45164da2018-01-24 12:51:27 +0100957 vc_conn.done;
958}
959
Harald Weltee13cfb22019-04-23 16:52:02 +0200960
Harald Welted5b91402018-01-24 18:48:16 +0100961/* establish an emergency call by IMSI, SIM inserted (and hence IMSI) */
Harald Weltee13cfb22019-04-23 16:52:02 +0200962friend function f_tc_emerg_call_imsi(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +0100963 f_init_handler(pars);
Harald Welte45164da2018-01-24 12:51:27 +0100964 /* First perform location update to ensure subscriber is known */
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +0100965 f_perform_lu();
Harald Welte45164da2018-01-24 12:51:27 +0100966 /* Then issue emergency call identified by IMSI */
967 f_emerg_call(valueof(ts_MI_IMSI_LV(g_pars.imsi)));
968}
969testcase TC_emerg_call_imsi() runs on MTC_CT {
970 var BSC_ConnHdlr vc_conn;
971 f_init();
972
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +0100973 vc_conn := f_start_handler(refers(f_tc_emerg_call_imsi), 18);
Harald Welte45164da2018-01-24 12:51:27 +0100974 vc_conn.done;
975}
976
Harald Weltee13cfb22019-04-23 16:52:02 +0200977
Harald Welte45164da2018-01-24 12:51:27 +0100978/* CM Service Request for VGCS -> reject */
979private function f_tc_cm_serv_req_vgcs_reject(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +0100980 f_init_handler(pars);
Harald Welte45164da2018-01-24 12:51:27 +0100981
982 /* First perform location update to ensure subscriber is known */
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +0100983 f_perform_lu();
Harald Welte45164da2018-01-24 12:51:27 +0100984
985 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
Harald Welte6ed6bf92018-01-24 21:09:15 +0100986 var PDU_ML3_MS_NW l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_VGCS, mi));
Harald Weltedceacc72019-04-21 20:58:35 +0200987 f_cl3_or_initial_ue(l3_info);
Harald Welte45164da2018-01-24 12:51:27 +0100988 BSSAP.receive(tr_PDU_DTAP_MT(tr_CM_SERV_REJ(int2oct(32,1))));
Harald Welte1ddc7162018-01-27 14:25:46 +0100989 f_expect_clear();
Harald Welte45164da2018-01-24 12:51:27 +0100990}
991testcase TC_cm_serv_req_vgcs_reject() runs on MTC_CT {
992 var BSC_ConnHdlr vc_conn;
993 f_init();
994
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +0100995 vc_conn := f_start_handler(refers(f_tc_cm_serv_req_vgcs_reject), 19);
Harald Welte45164da2018-01-24 12:51:27 +0100996 vc_conn.done;
997}
998
999/* CM Service Request for VBS -> reject */
1000private function f_tc_cm_serv_req_vbs_reject(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +01001001 f_init_handler(pars);
Harald Welte45164da2018-01-24 12:51:27 +01001002
1003 /* First perform location update to ensure subscriber is known */
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +01001004 f_perform_lu();
Harald Welte45164da2018-01-24 12:51:27 +01001005
1006 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
Harald Welte6ed6bf92018-01-24 21:09:15 +01001007 var PDU_ML3_MS_NW l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_VBS, mi));
Harald Weltedceacc72019-04-21 20:58:35 +02001008 f_cl3_or_initial_ue(l3_info);
Harald Welte45164da2018-01-24 12:51:27 +01001009 BSSAP.receive(tr_PDU_DTAP_MT(tr_CM_SERV_REJ(int2oct(32,1))));
Harald Welte1ddc7162018-01-27 14:25:46 +01001010 f_expect_clear();
Harald Welte45164da2018-01-24 12:51:27 +01001011}
1012testcase TC_cm_serv_req_vbs_reject() runs on MTC_CT {
1013 var BSC_ConnHdlr vc_conn;
1014 f_init();
1015
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001016 vc_conn := f_start_handler(refers(f_tc_cm_serv_req_vbs_reject), 20);
Harald Welte45164da2018-01-24 12:51:27 +01001017 vc_conn.done;
1018}
1019
1020/* CM Service Request for LCS -> reject */
1021private function f_tc_cm_serv_req_lcs_reject(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +01001022 f_init_handler(pars);
Harald Welte45164da2018-01-24 12:51:27 +01001023
1024 /* First perform location update to ensure subscriber is known */
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +01001025 f_perform_lu();
Harald Welte45164da2018-01-24 12:51:27 +01001026
1027 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
Harald Welte6ed6bf92018-01-24 21:09:15 +01001028 var PDU_ML3_MS_NW l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_LCS, mi));
Harald Weltedceacc72019-04-21 20:58:35 +02001029 f_cl3_or_initial_ue(l3_info);
Harald Welte45164da2018-01-24 12:51:27 +01001030 BSSAP.receive(tr_PDU_DTAP_MT(tr_CM_SERV_REJ(int2oct(32,1))));
Harald Welte1ddc7162018-01-27 14:25:46 +01001031 f_expect_clear();
Harald Welte45164da2018-01-24 12:51:27 +01001032}
1033testcase TC_cm_serv_req_lcs_reject() runs on MTC_CT {
1034 var BSC_ConnHdlr vc_conn;
1035 f_init();
1036
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001037 vc_conn := f_start_handler(refers(f_tc_cm_serv_req_lcs_reject), 21);
Harald Welte45164da2018-01-24 12:51:27 +01001038 vc_conn.done;
1039}
1040
Harald Welte0195ab12018-01-24 21:50:20 +01001041/* CM Re-Establishment Request */
1042private function f_tc_cm_reest_req_reject(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +01001043 f_init_handler(pars);
Harald Welte0195ab12018-01-24 21:50:20 +01001044
1045 /* First perform location update to ensure subscriber is known */
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +01001046 f_perform_lu();
Harald Welte0195ab12018-01-24 21:50:20 +01001047
1048 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
1049 var PDU_ML3_MS_NW l3_info := valueof(ts_CM_REEST_REQ(0, mi));
Harald Weltedceacc72019-04-21 20:58:35 +02001050 f_cl3_or_initial_ue(l3_info);
Harald Welte0195ab12018-01-24 21:50:20 +01001051 BSSAP.receive(tr_PDU_DTAP_MT(tr_CM_SERV_REJ(int2oct(32,1))));
Harald Welte1ddc7162018-01-27 14:25:46 +01001052 f_expect_clear();
Harald Welte0195ab12018-01-24 21:50:20 +01001053}
1054testcase TC_cm_reest_req_reject() runs on MTC_CT {
1055 var BSC_ConnHdlr vc_conn;
1056 f_init();
Harald Welte0195ab12018-01-24 21:50:20 +01001057
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001058 vc_conn := f_start_handler(refers(f_tc_cm_reest_req_reject), 22);
Harald Welte0195ab12018-01-24 21:50:20 +01001059 vc_conn.done;
1060}
1061
Harald Weltec638f4d2018-01-24 22:00:36 +01001062/* Test LU (with authentication enabled), with wrong response from MS */
1063private function f_tc_lu_auth_2G_fail(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +01001064 f_init_handler(pars);
Harald Weltec638f4d2018-01-24 22:00:36 +01001065
1066 var PDU_ML3_MS_NW l3_lu := f_build_lu_imsi(g_pars.imsi)
1067
1068 /* tell GSUP dispatcher to send this IMSI to us */
1069 f_create_gsup_expect(hex2str(g_pars.imsi));
1070
1071 /* Send BSSAP_Conn_Req with COMPL L3 INFO to MSC */
Harald Weltedceacc72019-04-21 20:58:35 +02001072 f_cl3_or_initial_ue(l3_lu);
Harald Weltec638f4d2018-01-24 22:00:36 +01001073
1074 /* Send Early Classmark, just for the fun of it */
1075 BSSAP.send(ts_BSSMAP_ClassmarkUpd(g_pars.cm2, g_pars.cm3));
1076
1077 var AuthVector vec := f_gen_auth_vec_2g();
1078 var GSUP_IE auth_tuple := valueof(ts_GSUP_IE_AuthTuple2G(vec.rand, vec.sres, vec.kc));
1079 GSUP.receive(tr_GSUP_SAI_REQ(g_pars.imsi));
1080 GSUP.send(ts_GSUP_SAI_RES(g_pars.imsi, auth_tuple));
1081
1082 BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_MM_AUTH_REQ(vec.rand)));
1083 /* Send back wrong auth response */
1084 BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MT_MM_AUTH_RESP_2G('00000000'O)));
1085
1086 /* Expect GSUP AUTH FAIL REP to HLR */
1087 GSUP.receive(tr_GSUP_AUTH_FAIL_IND(g_pars.imsi));
1088
1089 /* Expect LU REJECT with Cause == Illegal MS */
1090 BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Rej('03'O)));
Harald Welte1ddc7162018-01-27 14:25:46 +01001091 f_expect_clear();
Harald Weltec638f4d2018-01-24 22:00:36 +01001092}
1093testcase TC_lu_auth_2G_fail() runs on MTC_CT {
1094 var BSC_ConnHdlr vc_conn;
1095 f_init();
1096 f_vty_config(MSCVTY, "network", "authentication required");
Harald Weltec638f4d2018-01-24 22:00:36 +01001097
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001098 vc_conn := f_start_handler(refers(f_tc_lu_auth_2G_fail), 23);
Harald Weltec638f4d2018-01-24 22:00:36 +01001099 vc_conn.done;
1100}
1101
Harald Weltede371492018-01-27 23:44:41 +01001102/* A5/1 + A5/3 permitted on network side, and MS capable to do it */
Harald Welte16114282018-01-24 22:41:21 +01001103private 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 +01001104 pars.net.expect_auth := true;
1105 pars.net.expect_ciph := true;
Harald Weltea10db902018-01-27 12:44:49 +01001106 f_init_handler(pars);
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +01001107 f_perform_lu();
Harald Welte16114282018-01-24 22:41:21 +01001108}
1109testcase TC_lu_imsi_auth_tmsi_encr_13_13() runs on MTC_CT {
1110 var BSC_ConnHdlr vc_conn;
1111 f_init();
1112 f_vty_config(MSCVTY, "network", "authentication required");
Harald Welte16114282018-01-24 22:41:21 +01001113 f_vty_config(MSCVTY, "network", "encryption a5 1 3");
1114
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001115 vc_conn := f_start_handler(refers(f_tc_lu_imsi_auth_tmsi_encr_13_13), 24);
Harald Welte16114282018-01-24 22:41:21 +01001116 vc_conn.done;
1117}
1118
Harald Welte1af6ea82018-01-25 18:33:15 +01001119/* Test Complete L3 without payload */
1120private function f_tc_cl3_no_payload(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +01001121 f_init_handler(pars);
Harald Welte1af6ea82018-01-25 18:33:15 +01001122
1123 /* Send Complete L3 Info with empty L3 frame */
1124 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_peer, g_pars.sccp_addr_own,
1125 valueof(ts_BSSMAP_ComplL3(g_pars.cell_id, ''O))));
1126
Harald Weltef466eb42018-01-27 14:26:54 +01001127 timer T := 5.0;
1128 T.start;
Harald Welte1af6ea82018-01-25 18:33:15 +01001129 alt {
Harald Welte6811d102019-04-14 22:23:14 +02001130 [] BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_IND) {}
Harald Welte1af6ea82018-01-25 18:33:15 +01001131 /* Expect LU REJECT with Cause == Illegal MS */
Harald Weltebdb3c452018-03-18 22:43:06 +01001132 [] BSSAP.receive(tr_PDU_DTAP_MT(?)) { repeat; }
Harald Welte6811d102019-04-14 22:23:14 +02001133 [] BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND) { repeat; }
Harald Welte5946b332018-03-18 23:32:21 +01001134 [] as_clear_cmd_compl_disc();
Harald Weltef466eb42018-01-27 14:26:54 +01001135 [] T.timeout {
Daniel Willmann90829d62018-02-15 17:45:14 +01001136 setverdict(fail, "Timeout waiting for ClearCommand or SCCP Release");
Daniel Willmannafce8662018-07-06 23:11:32 +02001137 mtc.stop;
Harald Weltef466eb42018-01-27 14:26:54 +01001138 }
Harald Welte1af6ea82018-01-25 18:33:15 +01001139 }
1140 setverdict(pass);
1141}
1142testcase TC_cl3_no_payload() runs on MTC_CT {
1143 var BSC_ConnHdlr vc_conn;
1144 f_init();
1145
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001146 vc_conn := f_start_handler(refers(f_tc_cl3_no_payload), 25);
Harald Welte1af6ea82018-01-25 18:33:15 +01001147 vc_conn.done;
1148}
1149
1150/* Test Complete L3 with random payload */
1151private function f_tc_cl3_rnd_payload(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +01001152 f_init_handler(pars);
Harald Welte1af6ea82018-01-25 18:33:15 +01001153
Daniel Willmannaa14a382018-07-26 08:29:45 +02001154 /* length is limited by PDU_BSSAP length field which includes some
1155 * other fields beside l3info payload. So payl can only be 240 bytes
1156 * Since rnd() returns values < 1 multiply with 241
1157 */
1158 var integer len := float2int(rnd() * 241.0);
Harald Welte1af6ea82018-01-25 18:33:15 +01001159 var octetstring payl := f_rnd_octstring(len);
1160
1161 /* Send Complete L3 Info with empty L3 frame */
1162 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_peer, g_pars.sccp_addr_own,
1163 valueof(ts_BSSMAP_ComplL3(g_pars.cell_id, payl))));
1164
Harald Weltef466eb42018-01-27 14:26:54 +01001165 timer T := 5.0;
1166 T.start;
Harald Welte1af6ea82018-01-25 18:33:15 +01001167 alt {
1168 /* Immediate disconnect */
Harald Welte6811d102019-04-14 22:23:14 +02001169 [] BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_IND) {}
Harald Welte1af6ea82018-01-25 18:33:15 +01001170 [] BSSAP.receive(tr_PDU_DTAP_MT(?)) { repeat; }
Harald Welte6811d102019-04-14 22:23:14 +02001171 [] BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND) { repeat; }
Harald Welte5946b332018-03-18 23:32:21 +01001172 [] as_clear_cmd_compl_disc();
Harald Weltef466eb42018-01-27 14:26:54 +01001173 [] T.timeout {
Daniel Willmann90829d62018-02-15 17:45:14 +01001174 setverdict(fail, "Timeout waiting for ClearCommand or SCCP Release");
Daniel Willmannafce8662018-07-06 23:11:32 +02001175 mtc.stop;
Harald Weltef466eb42018-01-27 14:26:54 +01001176 }
Harald Welte1af6ea82018-01-25 18:33:15 +01001177 }
1178 setverdict(pass);
1179}
1180testcase TC_cl3_rnd_payload() runs on MTC_CT {
1181 var BSC_ConnHdlr vc_conn;
1182 f_init();
1183
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001184 vc_conn := f_start_handler(refers(f_tc_cl3_rnd_payload), 26);
Harald Welte1af6ea82018-01-25 18:33:15 +01001185 vc_conn.done;
1186}
1187
Harald Welte116e4332018-01-26 22:17:48 +01001188/* Test Complete L3 with random payload */
Harald Weltee13cfb22019-04-23 16:52:02 +02001189friend function f_tc_establish_and_nothing(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +01001190 f_init_handler(pars);
Harald Welte116e4332018-01-26 22:17:48 +01001191
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +01001192 f_perform_lu();
Harald Welte116e4332018-01-26 22:17:48 +01001193
Harald Welteb9e86fa2018-04-09 18:18:31 +02001194 f_establish_fully();
Daniel Willmann898a7e02018-05-17 12:16:16 +02001195 f_expect_clear(10.0);
Harald Welte116e4332018-01-26 22:17:48 +01001196}
1197testcase TC_establish_and_nothing() runs on MTC_CT {
1198 var BSC_ConnHdlr vc_conn;
1199 f_init();
1200
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001201 vc_conn := f_start_handler(refers(f_tc_establish_and_nothing), 27);
Harald Welte116e4332018-01-26 22:17:48 +01001202 vc_conn.done;
1203}
1204
Harald Weltee13cfb22019-04-23 16:52:02 +02001205
Harald Welte12510c52018-01-26 22:26:24 +01001206/* Test MO Call SETUP with no response from MNCC */
Harald Weltee13cfb22019-04-23 16:52:02 +02001207friend function f_tc_mo_setup_and_nothing(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Philipp Maier109e6aa2018-10-17 10:53:32 +02001208 f_init_handler(pars, 190.0);
Harald Weltea10db902018-01-27 12:44:49 +01001209
Harald Welte12510c52018-01-26 22:26:24 +01001210 var CallParameters cpars := valueof(t_CallParams('12345'H, 0));
1211
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +01001212 f_perform_lu();
Harald Welte12510c52018-01-26 22:26:24 +01001213
Harald Welteb9e86fa2018-04-09 18:18:31 +02001214 f_establish_fully();
Harald Welte12510c52018-01-26 22:26:24 +01001215 f_create_mncc_expect(hex2str(cpars.called_party));
1216 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
1217
1218 BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_CC_SETUP(cpars.transaction_id, cpars.called_party)));
1219
Neels Hofmeyrde76f052019-02-26 05:02:46 +01001220 var default ccrel := activate(as_optional_cc_rel(cpars));
1221
Philipp Maier109e6aa2018-10-17 10:53:32 +02001222 f_expect_clear(185.0);
Neels Hofmeyrde76f052019-02-26 05:02:46 +01001223
1224 deactivate(ccrel);
1225
1226 f_sleep(1.0);
Harald Welte12510c52018-01-26 22:26:24 +01001227}
1228testcase TC_mo_setup_and_nothing() runs on MTC_CT {
1229 var BSC_ConnHdlr vc_conn;
1230 f_init();
1231
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001232 vc_conn := f_start_handler(refers(f_tc_mo_setup_and_nothing), 28);
Harald Welte12510c52018-01-26 22:26:24 +01001233 vc_conn.done;
1234}
1235
Harald Weltee13cfb22019-04-23 16:52:02 +02001236
Harald Welte3ab88002018-01-26 22:37:25 +01001237/* Test MO Call with no response to RAN-side CRCX */
Harald Weltee13cfb22019-04-23 16:52:02 +02001238friend function f_tc_mo_crcx_ran_timeout(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +01001239 f_init_handler(pars);
Harald Welte3ab88002018-01-26 22:37:25 +01001240 var CallParameters cpars := valueof(t_CallParams('12345'H, 0));
1241 var MNCC_PDU mncc;
1242 var MgcpCommand mgcp_cmd;
1243
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +01001244 f_perform_lu();
Harald Welte3ab88002018-01-26 22:37:25 +01001245
Harald Welteb9e86fa2018-04-09 18:18:31 +02001246 f_establish_fully();
Harald Welte3ab88002018-01-26 22:37:25 +01001247 f_create_mncc_expect(hex2str(cpars.called_party));
1248 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
1249
1250 BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_CC_SETUP(cpars.transaction_id, cpars.called_party)));
1251 MNCC.receive(tr_MNCC_SETUP_ind(?, tr_MNCC_number(hex2str(cpars.called_party)))) -> value mncc;
1252 cpars.mncc_callref := mncc.u.signal.callref;
1253 MNCC.send(ts_MNCC_CALL_PROC_req(cpars.mncc_callref, cpars.mncc_bearer_cap));
1254 BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_CC_CALL_PROC(cpars.transaction_id)));
1255
1256 MGCP.receive(tr_CRCX) -> value mgcp_cmd;
Harald Welte1852a842018-01-26 22:53:36 +01001257 cpars.mgcp_call_id := f_MgcpCmd_extract_call_id(mgcp_cmd);
1258 cpars.mgcp_ep := mgcp_cmd.line.ep;
Harald Welte3ab88002018-01-26 22:37:25 +01001259 /* never respond to this */
1260
Philipp Maier8e58f592018-03-14 11:10:56 +01001261 /* When the connection with the MGW fails, the MSC will first request
1262 * a release via call control. We will answer this request normally. */
1263 BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_CC_RELEASE(cpars.transaction_id)));
1264 BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_CC_REL_COMPL(cpars.transaction_id)));
1265
Harald Welte1ddc7162018-01-27 14:25:46 +01001266 f_expect_clear(30.0);
Harald Welte3ab88002018-01-26 22:37:25 +01001267}
1268testcase TC_mo_crcx_ran_timeout() runs on MTC_CT {
1269 var BSC_ConnHdlr vc_conn;
1270 f_init();
1271
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001272 vc_conn := f_start_handler(refers(f_tc_mo_crcx_ran_timeout), 29);
Harald Welte3ab88002018-01-26 22:37:25 +01001273 vc_conn.done;
1274}
1275
Harald Weltee13cfb22019-04-23 16:52:02 +02001276
Harald Welte0cc82d92018-01-26 22:52:34 +01001277/* Test MO Call with reject to RAN-side CRCX */
Harald Weltee13cfb22019-04-23 16:52:02 +02001278friend function f_tc_mo_crcx_ran_reject(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +01001279 f_init_handler(pars);
Harald Welte0cc82d92018-01-26 22:52:34 +01001280 var CallParameters cpars := valueof(t_CallParams('12345'H, 0));
1281 var MNCC_PDU mncc;
1282 var MgcpCommand mgcp_cmd;
1283
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +01001284 f_perform_lu();
Harald Welte0cc82d92018-01-26 22:52:34 +01001285
Harald Welteb9e86fa2018-04-09 18:18:31 +02001286 f_establish_fully();
Harald Welte0cc82d92018-01-26 22:52:34 +01001287 f_create_mncc_expect(hex2str(cpars.called_party));
1288 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
1289
1290 BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_CC_SETUP(cpars.transaction_id, cpars.called_party)));
1291 MNCC.receive(tr_MNCC_SETUP_ind(?, tr_MNCC_number(hex2str(cpars.called_party)))) -> value mncc;
1292 cpars.mncc_callref := mncc.u.signal.callref;
1293 MNCC.send(ts_MNCC_CALL_PROC_req(cpars.mncc_callref, cpars.mncc_bearer_cap));
1294 BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_CC_CALL_PROC(cpars.transaction_id)));
1295
1296 MGCP.receive(tr_CRCX) -> value mgcp_cmd;
Philipp Maierf1e02bb2018-03-15 16:30:00 +01001297
1298 /* Detect if the received CRCX is a wildcarded CRCX request. If yes,
1299 * set an endpoint name that fits the pattern. If not, just use the
1300 * endpoint name from the request */
1301 if (match(mgcp_cmd.line.ep, t_MGCP_EP_wildcard)) {
1302 cpars.mgcp_ep := "rtpbridge/1@mgw";
1303 } else {
1304 cpars.mgcp_ep := mgcp_cmd.line.ep;
1305 }
1306
Harald Welte0cc82d92018-01-26 22:52:34 +01001307 cpars.mgcp_call_id := f_MgcpCmd_extract_call_id(mgcp_cmd);
Philipp Maierf1e02bb2018-03-15 16:30:00 +01001308
Harald Welte0cc82d92018-01-26 22:52:34 +01001309 /* Respond to CRCX with error */
1310 var MgcpResponse mgcp_rsp := {
1311 line := {
1312 code := "542",
1313 trans_id := mgcp_cmd.line.trans_id,
1314 string := "FORCED_FAIL"
1315 },
Harald Welte0cc82d92018-01-26 22:52:34 +01001316 sdp := omit
1317 }
Philipp Maierf1e02bb2018-03-15 16:30:00 +01001318 var MgcpParameter mgcp_rsp_param := {
1319 code := "Z",
1320 val := cpars.mgcp_ep
1321 };
1322 mgcp_rsp.params[0] := mgcp_rsp_param;
Harald Welte0cc82d92018-01-26 22:52:34 +01001323 MGCP.send(mgcp_rsp);
1324
1325 timer T := 30.0;
1326 T.start;
1327 alt {
Daniel Willmannafce8662018-07-06 23:11:32 +02001328 [] T.timeout {
1329 setverdict(fail, "Timeout waiting for channel release");
1330 mtc.stop;
1331 }
Daniel Willmann5868e622018-02-15 17:42:59 +01001332 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_CC_RELEASE(cpars.transaction_id))) {
1333 BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_CC_REL_COMPL(cpars.transaction_id)));
1334 repeat;
1335 }
Harald Welte0cc82d92018-01-26 22:52:34 +01001336 [] MNCC.receive { repeat; }
1337 [] GSUP.receive { repeat; }
Philipp Maierc6e06f72018-04-11 18:12:23 +02001338 /* Note: As we did not respond properly to the CRCX from the MSC we
1339 * expect the MSC to omit any further MGCP operation (At least in the
1340 * the current implementation, there is no recovery mechanism implemented
1341 * and a DLCX can not be performed as the MSC does not know a specific
1342 * endpoint yet. */
Daniel Willmannafce8662018-07-06 23:11:32 +02001343 [] MGCP.receive {
1344 setverdict(fail, "Unexpected MGCP message");
1345 mtc.stop;
1346 }
Harald Welte5946b332018-03-18 23:32:21 +01001347 [] as_clear_cmd_compl_disc();
Harald Welte0cc82d92018-01-26 22:52:34 +01001348 }
1349}
1350testcase TC_mo_crcx_ran_reject() runs on MTC_CT {
1351 var BSC_ConnHdlr vc_conn;
1352 f_init();
1353
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001354 vc_conn := f_start_handler(refers(f_tc_mo_crcx_ran_reject), 30);
Harald Welte0cc82d92018-01-26 22:52:34 +01001355 vc_conn.done;
1356}
1357
Harald Welte3ab88002018-01-26 22:37:25 +01001358
Harald Welte812f7a42018-01-27 00:49:18 +01001359/* helper function to start a MT call: MNCC SETUP; Paging; DChan est.; DTAP SETUP */
1360private function f_mt_call_start(inout CallParameters cpars) runs on BSC_ConnHdlr {
1361 var MNCC_PDU mncc;
1362 var MgcpCommand mgcp_cmd;
1363 var OCT4 tmsi;
1364
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +01001365 f_perform_lu();
Harald Welte812f7a42018-01-27 00:49:18 +01001366 if (isvalue(g_pars.tmsi)) {
1367 tmsi := g_pars.tmsi;
1368 } else {
1369 tmsi := 'FFFFFFFF'O;
1370 }
Harald Welte6811d102019-04-14 22:23:14 +02001371 f_ran_register_imsi(g_pars.imsi, tmsi);
Harald Welte812f7a42018-01-27 00:49:18 +01001372
1373 /* Allocate call reference and send SETUP via MNCC to MSC */
1374 cpars.mncc_callref := f_rnd_int(2147483648);
1375 MNCC.send(ts_MNCC_SETUP_req(cpars.mncc_callref, hex2str(g_pars.msisdn),
1376 hex2str(cpars.called_party), hex2str(g_pars.imsi)));
1377
1378 /* MSC->BSC: expect PAGING from MSC */
Harald Weltee035e3e2019-04-21 17:32:05 +02001379 f_expect_paging();
1380
Harald Welte812f7a42018-01-27 00:49:18 +01001381 /* MS -> MSC: PAGING RESPONSE */
Harald Welteb9e86fa2018-04-09 18:18:31 +02001382 f_establish_fully(EST_TYPE_PAG_RESP);
Harald Welte812f7a42018-01-27 00:49:18 +01001383
1384 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
1385
1386 /* MSC->MS: SETUP */
1387 BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_CC_SETUP(cpars.transaction_id, *, cpars.called_party)));
1388}
1389
1390/* Test MT Call */
Harald Weltee13cfb22019-04-23 16:52:02 +02001391friend function f_tc_mt_crcx_ran_reject(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +01001392 f_init_handler(pars);
Harald Welte812f7a42018-01-27 00:49:18 +01001393 var CallParameters cpars := valueof(t_CallParams('123456'H, 0));
1394 var MNCC_PDU mncc;
1395 var MgcpCommand mgcp_cmd;
1396
1397 f_mt_call_start(cpars);
1398
1399 /* MS->MSC: CALL CONFIRMED */
1400 BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_CC_CALL_CONF(cpars.transaction_id)));
1401
1402 MNCC.receive(tr_MNCC_CALL_CONF_ind(cpars.mncc_callref));
1403
1404 MGCP.receive(tr_CRCX) -> value mgcp_cmd;
1405 cpars.mgcp_call_id := f_MgcpCmd_extract_call_id(mgcp_cmd);
Philipp Maierf1e02bb2018-03-15 16:30:00 +01001406
1407 /* Detect if the received CRCX is a wildcarded CRCX request. If yes,
1408 * set an endpoint name that fits the pattern. If not, just use the
1409 * endpoint name from the request */
1410 if (match(mgcp_cmd.line.ep, t_MGCP_EP_wildcard)) {
1411 cpars.mgcp_ep := "rtpbridge/1@mgw";
1412 } else {
1413 cpars.mgcp_ep := mgcp_cmd.line.ep;
1414 }
1415
Harald Welte812f7a42018-01-27 00:49:18 +01001416 /* Respond to CRCX with error */
1417 var MgcpResponse mgcp_rsp := {
1418 line := {
1419 code := "542",
1420 trans_id := mgcp_cmd.line.trans_id,
1421 string := "FORCED_FAIL"
1422 },
Harald Welte812f7a42018-01-27 00:49:18 +01001423 sdp := omit
1424 }
Philipp Maierf1e02bb2018-03-15 16:30:00 +01001425 var MgcpParameter mgcp_rsp_param := {
1426 code := "Z",
1427 val := cpars.mgcp_ep
1428 };
1429 mgcp_rsp.params[0] := mgcp_rsp_param;
Harald Welte812f7a42018-01-27 00:49:18 +01001430 MGCP.send(mgcp_rsp);
1431
1432 timer T := 30.0;
1433 T.start;
1434 alt {
Daniel Willmannafce8662018-07-06 23:11:32 +02001435 [] T.timeout {
1436 setverdict(fail, "Timeout waiting for channel release");
1437 mtc.stop;
1438 }
Harald Welte812f7a42018-01-27 00:49:18 +01001439 [] MNCC.receive { repeat; }
1440 [] GSUP.receive { repeat; }
1441 [] MGCP.receive(tr_DLCX(?)) -> value mgcp_cmd {
1442 MGCP.send(ts_DLCX_ACK2(mgcp_cmd.line.trans_id));
1443 f_create_mgcp_delete_ep(cpars.mgcp_ep);
1444 repeat;
1445 }
1446 [] MGCP.receive { repeat; }
Harald Welte5946b332018-03-18 23:32:21 +01001447 [] as_clear_cmd_compl_disc();
Neels Hofmeyrde76f052019-02-26 05:02:46 +01001448 [] as_optional_cc_rel(cpars);
Harald Welte812f7a42018-01-27 00:49:18 +01001449 }
1450}
1451testcase TC_mt_crcx_ran_reject() runs on MTC_CT {
1452 var BSC_ConnHdlr vc_conn;
1453 f_init();
1454
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001455 vc_conn := f_start_handler(refers(f_tc_mt_crcx_ran_reject), 31);
Harald Welte812f7a42018-01-27 00:49:18 +01001456 vc_conn.done;
1457}
1458
1459
Harald Weltee13cfb22019-04-23 16:52:02 +02001460
Harald Welte812f7a42018-01-27 00:49:18 +01001461/* Test MT Call T310 timer */
Harald Weltee13cfb22019-04-23 16:52:02 +02001462friend function f_tc_mt_t310(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltead2952e2018-01-27 14:12:46 +01001463 f_init_handler(pars, 200.0);
Harald Welte812f7a42018-01-27 00:49:18 +01001464 var CallParameters cpars := valueof(t_CallParams('123456'H, 0));
1465 var MNCC_PDU mncc;
1466 var MgcpCommand mgcp_cmd;
1467
1468 f_mt_call_start(cpars);
1469
1470 /* MS->MSC: CALL CONFIRMED */
1471 BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_CC_CALL_CONF(cpars.transaction_id)));
1472 MNCC.receive(tr_MNCC_CALL_CONF_ind(cpars.mncc_callref));
1473
1474 MGCP.receive(tr_CRCX) -> value mgcp_cmd;
1475 cpars.mgcp_call_id := f_MgcpCmd_extract_call_id(mgcp_cmd);
1476 cpars.mgcp_ep := mgcp_cmd.line.ep;
1477 /* FIXME: Respond to CRCX */
1478
1479 /* old libosmocore T310 default timeout is 180s. so let's wait 190 */
1480 timer T := 190.0;
1481 T.start;
1482 alt {
Daniel Willmannafce8662018-07-06 23:11:32 +02001483 [] T.timeout {
1484 setverdict(fail, "Timeout waiting for T310");
1485 mtc.stop;
1486 }
Harald Welte812f7a42018-01-27 00:49:18 +01001487 [] MNCC.receive(tr_MNCC_DISC_ind(cpars.mncc_callref)) {
1488 MNCC.send(ts_MNCC_REL_req(cpars.mncc_callref, valueof(ts_MNCC_cause(23))));
1489 }
1490 }
1491 BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_CC_DISC(cpars.transaction_id)));
1492 BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_CC_RELEASE(cpars.transaction_id)));
1493 /* FIXME: We're sending this with TIflag 0: allocated by sender, which is wrong */
1494 BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_CC_REL_COMPL(cpars.transaction_id)));
1495
1496 alt {
Harald Welte812f7a42018-01-27 00:49:18 +01001497 [] MGCP.receive(tr_DLCX(?)) -> value mgcp_cmd {
1498 MGCP.send(ts_DLCX_ACK2(mgcp_cmd.line.trans_id));
1499 f_create_mgcp_delete_ep(cpars.mgcp_ep);
1500 repeat;
1501 }
Harald Welte5946b332018-03-18 23:32:21 +01001502 [] as_clear_cmd_compl_disc();
Harald Welte812f7a42018-01-27 00:49:18 +01001503 }
1504}
1505testcase TC_mt_t310() runs on MTC_CT {
1506 var BSC_ConnHdlr vc_conn;
1507 f_init();
1508
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001509 vc_conn := f_start_handler(refers(f_tc_mt_t310), 32);
Harald Welte812f7a42018-01-27 00:49:18 +01001510 vc_conn.done;
1511}
1512
Harald Weltee13cfb22019-04-23 16:52:02 +02001513
Harald Welte167458a2018-01-27 15:58:16 +01001514/* Perform successful LU + MO call, then GSUP LocationCancel. Subscriber must be denied CM SERV */
Harald Weltee13cfb22019-04-23 16:52:02 +02001515friend function f_tc_gsup_cancel(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Welte167458a2018-01-27 15:58:16 +01001516 f_init_handler(pars);
1517 var CallParameters cpars := valueof(t_CallParams('12345'H, 0));
1518 cpars.bss_rtp_port := 1110;
1519 cpars.mgcp_connection_id_bss := '22222'H;
1520 cpars.mgcp_connection_id_mss := '33333'H;
Daniel Willmann9b0235b2018-07-24 12:13:34 +02001521 cpars.mgcp_ep := "rtpbridge/1@mgw";
Harald Welte167458a2018-01-27 15:58:16 +01001522
1523 /* Location Update to make subscriber known */
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +01001524 f_perform_lu();
Harald Welte167458a2018-01-27 15:58:16 +01001525
1526 /* First MO call should succeed */
1527 f_mo_call(cpars);
1528
1529 /* Cancel the subscriber in the VLR */
1530 GSUP.send(ts_GSUP_CL_REQ(g_pars.imsi, OSMO_GSUP_CANCEL_TYPE_WITHDRAW));
1531 alt {
1532 [] GSUP.receive(tr_GSUP_CL_RES(g_pars.imsi)) { }
1533 [] GSUP.receive(tr_GSUP_CL_ERR(g_pars.imsi)) {
1534 setverdict(fail, "Received GSUP Location Cancel Error");
Daniel Willmannafce8662018-07-06 23:11:32 +02001535 mtc.stop;
Harald Welte167458a2018-01-27 15:58:16 +01001536 }
1537 }
1538
1539 /* Follow-up transactions should fail */
1540 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
1541 var PDU_ML3_MS_NW l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, mi));
Harald Weltedceacc72019-04-21 20:58:35 +02001542 f_cl3_or_initial_ue(l3_info);
Harald Welte167458a2018-01-27 15:58:16 +01001543 alt {
1544 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_CM_SERV_REJ)) { }
1545 [] BSSAP.receive {
1546 setverdict(fail, "Received unexpected BSSAP instead of CM SERV REJ");
Daniel Willmannafce8662018-07-06 23:11:32 +02001547 mtc.stop;
Harald Welte167458a2018-01-27 15:58:16 +01001548 }
1549 }
Neels Hofmeyr0f7429a2019-03-07 22:28:41 +01001550
1551 f_expect_clear();
Harald Welte167458a2018-01-27 15:58:16 +01001552 setverdict(pass);
1553}
1554testcase TC_gsup_cancel() runs on MTC_CT {
1555 var BSC_ConnHdlr vc_conn;
1556 f_init();
1557
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001558 vc_conn := f_start_handler(refers(f_tc_gsup_cancel), 33);
Harald Welte167458a2018-01-27 15:58:16 +01001559 vc_conn.done;
1560}
1561
Harald Weltee13cfb22019-04-23 16:52:02 +02001562
Harald Welte9de84792018-01-28 01:06:35 +01001563/* A5/1 only permitted on network side, and MS capable to do it */
1564private function f_tc_lu_imsi_auth_tmsi_encr_1_13(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
1565 pars.net.expect_auth := true;
1566 pars.net.expect_ciph := true;
1567 pars.net.kc_support := '02'O; /* A5/1 only */
1568 f_init_handler(pars);
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +01001569 f_perform_lu();
Harald Welte9de84792018-01-28 01:06:35 +01001570}
1571testcase TC_lu_imsi_auth_tmsi_encr_1_13() runs on MTC_CT {
1572 var BSC_ConnHdlr vc_conn;
1573 f_init();
1574 f_vty_config(MSCVTY, "network", "authentication required");
1575 f_vty_config(MSCVTY, "network", "encryption a5 1");
1576
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001577 vc_conn := f_start_handler(refers(f_tc_lu_imsi_auth_tmsi_encr_1_13), 34);
Harald Welte9de84792018-01-28 01:06:35 +01001578 vc_conn.done;
1579}
1580
1581/* A5/3 only permitted on network side, and MS capable to do it */
1582private function f_tc_lu_imsi_auth_tmsi_encr_3_13(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
1583 pars.net.expect_auth := true;
1584 pars.net.expect_ciph := true;
1585 pars.net.kc_support := '08'O; /* A5/3 only */
1586 f_init_handler(pars);
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +01001587 f_perform_lu();
Harald Welte9de84792018-01-28 01:06:35 +01001588}
1589testcase TC_lu_imsi_auth_tmsi_encr_3_13() runs on MTC_CT {
1590 var BSC_ConnHdlr vc_conn;
1591 f_init();
1592 f_vty_config(MSCVTY, "network", "authentication required");
1593 f_vty_config(MSCVTY, "network", "encryption a5 3");
1594
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001595 vc_conn := f_start_handler(refers(f_tc_lu_imsi_auth_tmsi_encr_3_13), 35);
Harald Welte9de84792018-01-28 01:06:35 +01001596 vc_conn.done;
1597}
1598
1599/* A5/3 only permitted on network side, and MS with only A5/1 support */
1600private function f_tc_lu_imsi_auth_tmsi_encr_3_1(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
1601 pars.net.expect_auth := true;
1602 pars.net.expect_ciph := true;
1603 pars.net.kc_support := '08'O; /* A5/3 only */
1604 pars.cm2.classmarkInformationType2_oct5.a5_3 := '0'B;
1605 f_init_handler(pars, 15.0);
1606
1607 /* cannot use f_perform_lu() as we expect a reject */
1608 var PDU_ML3_MS_NW l3_lu := f_build_lu_imsi(g_pars.imsi);
1609 f_create_gsup_expect(hex2str(g_pars.imsi));
Harald Weltedceacc72019-04-21 20:58:35 +02001610 f_cl3_or_initial_ue(l3_lu);
Neels Hofmeyr29b8da02018-03-01 18:09:45 +01001611 if (pars.send_early_cm) {
1612 BSSAP.send(ts_BSSMAP_ClassmarkUpd(g_pars.cm2, g_pars.cm3));
1613 } else {
1614 pars.cm1.esind := '0'B;
1615 }
Harald Welte9de84792018-01-28 01:06:35 +01001616 f_mm_auth();
1617 alt {
Daniel Willmann52918e52018-09-20 14:39:09 +02001618 [] BSSAP.receive(tr_BSSMAP_ClassmarkReq) {
1619 BSSAP.send(ts_BSSMAP_ClassmarkUpd(g_pars.cm2, g_pars.cm3));
1620 repeat;
1621 }
Harald Welte5946b332018-03-18 23:32:21 +01001622 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Rej)) {
1623 f_expect_clear();
1624 }
Harald Welte9de84792018-01-28 01:06:35 +01001625 [] BSSAP.receive(tr_BSSMAP_CipherModeCmd(?,?)) {
1626 setverdict(fail, "CipherModeCommand despite no A5 intersection");
Daniel Willmannafce8662018-07-06 23:11:32 +02001627 mtc.stop;
Harald Welte9de84792018-01-28 01:06:35 +01001628 }
1629 [] BSSAP.receive {
Harald Welte458fd372018-03-21 11:26:23 +01001630 setverdict(fail, "Unknown/unexpected BSSAP received");
Daniel Willmannafce8662018-07-06 23:11:32 +02001631 mtc.stop;
Harald Welte9de84792018-01-28 01:06:35 +01001632 }
1633 }
1634 setverdict(pass);
1635}
1636testcase TC_lu_imsi_auth_tmsi_encr_3_1() runs on MTC_CT {
1637 var BSC_ConnHdlr vc_conn;
1638 f_init();
1639 f_vty_config(MSCVTY, "network", "authentication required");
1640 f_vty_config(MSCVTY, "network", "encryption a5 3");
1641
Neels Hofmeyr29b8da02018-03-01 18:09:45 +01001642 vc_conn := f_start_handler(refers(f_tc_lu_imsi_auth_tmsi_encr_3_1), 360);
1643 vc_conn.done;
1644}
1645testcase TC_lu_imsi_auth_tmsi_encr_3_1_no_cm() runs on MTC_CT {
1646 var BSC_ConnHdlrPars pars;
1647 var BSC_ConnHdlr vc_conn;
1648 f_init();
1649 f_vty_config(MSCVTY, "network", "authentication required");
1650 f_vty_config(MSCVTY, "network", "encryption a5 3");
1651
1652 pars := f_init_pars(361);
1653 pars.send_early_cm := false;
1654 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 +01001655 vc_conn.done;
1656}
Neels Hofmeyr1b3c6e32018-03-01 17:52:21 +01001657testcase TC_lu_imsi_auth_tmsi_encr_3_1_log_msc_debug() runs on MTC_CT {
1658 var BSC_ConnHdlr vc_conn;
1659 f_init();
1660 f_vty_config(MSCVTY, "network", "authentication required");
1661 f_vty_config(MSCVTY, "network", "encryption a5 3");
1662
1663 /* Make sure the MSC category is on DEBUG level to trigger the log
1664 * message that is reported in OS#2947 to trigger the segfault */
1665 f_vty_config(MSCVTY, "log stderr", "logging level msc debug");
1666
1667 vc_conn := f_start_handler(refers(f_tc_lu_imsi_auth_tmsi_encr_3_1), 362);
1668 vc_conn.done;
1669}
Harald Welte9de84792018-01-28 01:06:35 +01001670
1671/* A5/1 + A5/3 only permitted on network side, and MS with only A5/2 support */
1672private function f_tc_lu_imsi_auth_tmsi_encr_13_2(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
1673 pars.net.expect_auth := true;
1674 pars.net.expect_ciph := true;
1675 pars.net.kc_support := '0A'O; /* A5/1 + A5/3 */
1676 pars.cm1.a5_1 := '1'B;
1677 pars.cm2.a5_1 := '1'B;
1678 pars.cm2.classmarkInformationType2_oct5.a5_3 := '0'B;
1679 pars.cm2.classmarkInformationType2_oct5.a5_2 := '1'B;
1680 f_init_handler(pars, 15.0);
1681
1682 /* cannot use f_perform_lu() as we expect a reject */
1683 var PDU_ML3_MS_NW l3_lu := f_build_lu_imsi(g_pars.imsi);
1684 f_create_gsup_expect(hex2str(g_pars.imsi));
Harald Weltedceacc72019-04-21 20:58:35 +02001685 f_cl3_or_initial_ue(l3_lu);
Harald Welte9de84792018-01-28 01:06:35 +01001686 BSSAP.send(ts_BSSMAP_ClassmarkUpd(g_pars.cm2, g_pars.cm3));
1687 f_mm_auth();
1688 alt {
Harald Welte5946b332018-03-18 23:32:21 +01001689 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Rej)) {
1690 f_expect_clear();
1691 }
Harald Welte9de84792018-01-28 01:06:35 +01001692 [] BSSAP.receive(tr_BSSMAP_CipherModeCmd(?,?)) {
1693 setverdict(fail, "CipherModeCommand despite no A5 intersection");
Daniel Willmannafce8662018-07-06 23:11:32 +02001694 mtc.stop;
Harald Welte9de84792018-01-28 01:06:35 +01001695 }
1696 [] BSSAP.receive {
Harald Welte458fd372018-03-21 11:26:23 +01001697 setverdict(fail, "Unknown/unexpected BSSAP received");
Daniel Willmannafce8662018-07-06 23:11:32 +02001698 mtc.stop;
Harald Welte9de84792018-01-28 01:06:35 +01001699 }
1700 }
1701 setverdict(pass);
1702}
1703testcase TC_lu_imsi_auth_tmsi_encr_13_2() runs on MTC_CT {
1704 var BSC_ConnHdlr vc_conn;
1705 f_init();
1706 f_vty_config(MSCVTY, "network", "authentication required");
1707 f_vty_config(MSCVTY, "network", "encryption a5 1 3");
1708
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001709 vc_conn := f_start_handler(refers(f_tc_lu_imsi_auth_tmsi_encr_13_2), 37);
Harald Welte9de84792018-01-28 01:06:35 +01001710 vc_conn.done;
1711}
1712
1713/* A5/0 + A5/1 + A5/3 only permitted on network side, and MS with only A5/2 support */
1714private function f_tc_lu_imsi_auth_tmsi_encr_013_2(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
1715 pars.net.expect_auth := true;
1716 pars.net.expect_ciph := true;
1717 pars.net.kc_support := '0B'O; /* A5/1 + A5/3 */
1718 pars.cm1.a5_1 := '1'B;
1719 pars.cm2.a5_1 := '1'B;
1720 pars.cm2.classmarkInformationType2_oct5.a5_3 := '0'B;
1721 pars.cm2.classmarkInformationType2_oct5.a5_2 := '1'B;
1722 f_init_handler(pars, 15.0);
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +01001723 f_perform_lu();
Harald Welte9de84792018-01-28 01:06:35 +01001724}
1725testcase TC_lu_imsi_auth_tmsi_encr_013_2() runs on MTC_CT {
1726 var BSC_ConnHdlr vc_conn;
1727 f_init();
1728 f_vty_config(MSCVTY, "network", "authentication required");
1729 f_vty_config(MSCVTY, "network", "encryption a5 0 1 3");
1730
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001731 vc_conn := f_start_handler(refers(f_tc_lu_imsi_auth_tmsi_encr_013_2), 38);
Harald Welte9de84792018-01-28 01:06:35 +01001732 vc_conn.done;
1733}
1734
Harald Welte33ec09b2018-02-10 15:34:46 +01001735/* LU followed by MT call (including paging) */
1736private function f_tc_lu_and_mt_call(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
1737 f_init_handler(pars);
Stefan Sperling26d57be2018-11-12 17:03:26 +01001738 var CallParameters cpars := valueof(t_CallParams('12345'H, 0));
Harald Welte33ec09b2018-02-10 15:34:46 +01001739 cpars.bss_rtp_port := 1110;
1740 cpars.mgcp_connection_id_bss := '10004'H;
1741 cpars.mgcp_connection_id_mss := '10005'H;
Pau Espin Pedrola65697d2019-05-21 12:54:39 +02001742 cpars.use_osmux := pars.use_osmux;
Harald Welte33ec09b2018-02-10 15:34:46 +01001743
Philipp Maier4b2692d2018-03-14 16:37:48 +01001744 /* Note: This is an optional parameter. When the call-agent (MSC) does
1745 * supply a full endpoint name this setting will be overwritten. */
1746 cpars.mgcp_ep := "rtpbridge/1@mgw";
1747
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +01001748 f_perform_lu();
Harald Welte33ec09b2018-02-10 15:34:46 +01001749 f_mt_call(cpars);
1750}
1751testcase TC_lu_and_mt_call() runs on MTC_CT {
1752 var BSC_ConnHdlr vc_conn;
1753 f_init();
1754
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001755 vc_conn := f_start_handler(refers(f_tc_lu_and_mt_call), 39);
Harald Welte33ec09b2018-02-10 15:34:46 +01001756 vc_conn.done;
1757}
1758
Pau Espin Pedrola65697d2019-05-21 12:54:39 +02001759testcase TC_lu_and_mt_call_osmux() runs on MTC_CT {
1760 var BSC_ConnHdlr vc_conn;
1761 f_init(1, false, true, true);
Pau Espin Pedrola65697d2019-05-21 12:54:39 +02001762
1763 vc_conn := f_start_handler(refers(f_tc_lu_and_mt_call), 39, 0, true, true);
1764 vc_conn.done;
1765}
1766
Daniel Willmann8b084372018-02-04 13:35:26 +01001767/* Test MO Call SETUP with DTMF */
1768private function f_tc_mo_setup_dtmf_dup(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
1769 f_init_handler(pars);
1770 var CallParameters cpars := valueof(t_CallParams('12345'H, 0));
1771 cpars.bss_rtp_port := 1110;
1772 cpars.mgcp_connection_id_bss := '22222'H;
1773 cpars.mgcp_connection_id_mss := '33333'H;
1774
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +01001775 f_perform_lu();
Daniel Willmann8b084372018-02-04 13:35:26 +01001776 f_mo_seq_dtmf_dup(cpars);
1777}
1778testcase TC_mo_setup_and_dtmf_dup() runs on MTC_CT {
1779 var BSC_ConnHdlr vc_conn;
1780 f_init();
1781
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001782 vc_conn := f_start_handler(refers(f_tc_mo_setup_dtmf_dup), 39);
Daniel Willmann8b084372018-02-04 13:35:26 +01001783 vc_conn.done;
1784}
Harald Welte9de84792018-01-28 01:06:35 +01001785
Philipp Maier328d1662018-03-07 10:40:27 +01001786testcase TC_cr_before_reset() runs on MTC_CT {
1787 timer T := 4.0;
1788 var boolean reset_ack_seen := false;
1789 f_init_bssap_direct();
1790
Harald Welte3ca0ce12019-04-23 17:18:48 +02001791 f_ran_adapter_start(g_bssap[0]);
Daniel Willmann42d1d5b2018-08-07 15:18:41 +02001792
Daniel Willmanne8018962018-08-21 14:18:00 +02001793 f_sleep(3.0);
1794
Philipp Maier328d1662018-03-07 10:40:27 +01001795 /* Make a blind connection attemt, to trigger the deadlock condition */
Philipp Maier75932982018-03-27 14:52:35 +02001796 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 +01001797
1798 /* Send a BSSMAP reset */
Philipp Maier75932982018-03-27 14:52:35 +02001799 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 +01001800 T.start
1801 alt {
1802 [] BSSAP_DIRECT.receive(tr_BSSAP_UNITDATA_ind(?, ?, tr_BSSMAP_ResetAck)) {
1803 reset_ack_seen := true;
1804 repeat;
1805 }
1806
1807 /* Acknowledge MSC sided reset requests */
1808 [] BSSAP_DIRECT.receive(tr_BSSAP_UNITDATA_ind(?, ?, tr_BSSMAP_Reset)) {
Philipp Maier75932982018-03-27 14:52:35 +02001809 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 +01001810 repeat;
1811 }
1812
1813 /* Ignore all other messages (e.g CR from the connection request) */
1814 [] BSSAP_DIRECT.receive { repeat }
1815
1816 /* If we got no BSSMAP RESET ACK back, then the MSC entered the
1817 * deadlock situation. The MSC is then unable to respond to any
1818 * further BSSMAP RESET or any other sort of traffic. */
1819 [reset_ack_seen == true] T.timeout { setverdict(pass) }
1820 [reset_ack_seen == false] T.timeout {
1821 setverdict(fail, "no BSSMAP RESET ACK seen!");
Daniel Willmannafce8662018-07-06 23:11:32 +02001822 mtc.stop;
Philipp Maier328d1662018-03-07 10:40:27 +01001823 }
1824 }
1825}
Harald Welte9de84792018-01-28 01:06:35 +01001826
Philipp Maier94f3f1b2018-03-15 18:54:13 +01001827/* Test MO Call with no response to RAN-side CRCX or DTAP Release */
Harald Weltee13cfb22019-04-23 16:52:02 +02001828friend function f_tc_mo_release_timeout(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Philipp Maier94f3f1b2018-03-15 18:54:13 +01001829 f_init_handler(pars);
1830 var CallParameters cpars := valueof(t_CallParams('12345'H, 0));
1831 var MNCC_PDU mncc;
1832 var MgcpCommand mgcp_cmd;
1833
1834 f_perform_lu();
1835
Harald Welteb9e86fa2018-04-09 18:18:31 +02001836 f_establish_fully();
Philipp Maier94f3f1b2018-03-15 18:54:13 +01001837 f_create_mncc_expect(hex2str(cpars.called_party));
1838 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
1839
1840 BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_CC_SETUP(cpars.transaction_id, cpars.called_party)));
1841 MNCC.receive(tr_MNCC_SETUP_ind(?, tr_MNCC_number(hex2str(cpars.called_party)))) -> value mncc;
1842 cpars.mncc_callref := mncc.u.signal.callref;
1843 MNCC.send(ts_MNCC_CALL_PROC_req(cpars.mncc_callref, cpars.mncc_bearer_cap));
1844 BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_CC_CALL_PROC(cpars.transaction_id)));
1845
1846 /* Drop CRCX */
1847 MGCP.receive(tr_CRCX) -> value mgcp_cmd;
1848
Neels Hofmeyrde76f052019-02-26 05:02:46 +01001849 var default ccrel := activate(as_optional_cc_rel(cpars));
Philipp Maier94f3f1b2018-03-15 18:54:13 +01001850
1851 f_expect_clear(60.0);
Neels Hofmeyrde76f052019-02-26 05:02:46 +01001852
1853 deactivate(ccrel);
Philipp Maier94f3f1b2018-03-15 18:54:13 +01001854}
1855testcase TC_mo_release_timeout() runs on MTC_CT {
1856 var BSC_ConnHdlr vc_conn;
1857 f_init();
1858
1859 vc_conn := f_start_handler(refers(f_tc_mo_release_timeout), 40);
1860 vc_conn.done;
1861}
1862
Harald Welte12510c52018-01-26 22:26:24 +01001863
Philipp Maier2a98a732018-03-19 16:06:12 +01001864/* LU followed by MT call (including paging) */
1865private function f_tc_lu_and_mt_call_no_dlcx_resp(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
1866 f_init_handler(pars);
Stefan Sperling26d57be2018-11-12 17:03:26 +01001867 var CallParameters cpars := valueof(t_CallParams('12345'H, 0));
Philipp Maier2a98a732018-03-19 16:06:12 +01001868 cpars.bss_rtp_port := 1110;
1869 cpars.mgcp_connection_id_bss := '10004'H;
1870 cpars.mgcp_connection_id_mss := '10005'H;
1871
1872 /* Note: This is an optional parameter. When the call-agent (MSC) does
1873 * supply a full endpoint name this setting will be overwritten. */
1874 cpars.mgcp_ep := "rtpbridge/1@mgw";
1875
1876 /* Intentionally disable the CRCX response */
1877 cpars.mgw_drop_dlcx := true;
1878
1879 /* Perform location update and call */
1880 f_perform_lu();
1881 f_mt_call(cpars);
1882}
1883testcase TC_lu_and_mt_call_no_dlcx_resp() runs on MTC_CT {
1884 var BSC_ConnHdlr vc_conn;
1885 f_init();
1886
1887 /* Perform an almost normal looking locationupdate + mt-call, but do
1888 * not respond to the DLCX at the end of the call */
1889 vc_conn := f_start_handler(refers(f_tc_lu_and_mt_call_no_dlcx_resp), 41);
1890 vc_conn.done;
1891
1892 /* Wait a guard period until the MGCP layer in the MSC times out,
1893 * if the MSC is vulnerable to the use-after-free situation that is
1894 * fixed by I78f1b6a9149488a4ad3f120c1e190a83c07d4b89 then it should
1895 * segfault now */
1896 f_sleep(6.0);
1897
1898 /* Run the init procedures once more. If the MSC has crashed, this
1899 * this will fail */
1900 f_init();
1901}
Harald Welte45164da2018-01-24 12:51:27 +01001902
Philipp Maier75932982018-03-27 14:52:35 +02001903/* Two BSSMAP resets from two different BSCs */
1904testcase TC_reset_two() runs on MTC_CT {
1905 var BSC_ConnHdlr vc_conn;
1906 f_init(2);
1907 f_sleep(2.0);
1908 setverdict(pass);
1909}
1910
Harald Weltee13cfb22019-04-23 16:52:02 +02001911/* Two BSSMAP resets from two different BSCs plus one IuCS RANAP Reset */
1912testcase TC_reset_two_1iu() runs on MTC_CT {
1913 var BSC_ConnHdlr vc_conn;
1914 f_init(3);
1915 f_sleep(2.0);
1916 setverdict(pass);
1917}
1918
Harald Weltef640a012018-04-14 17:49:21 +02001919/***********************************************************************
1920 * SMS Testing
1921 ***********************************************************************/
1922
Harald Weltef45efeb2018-04-09 18:19:24 +02001923/* LU followed by MO SMS */
Harald Weltee13cfb22019-04-23 16:52:02 +02001924friend function f_tc_lu_and_mo_sms(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltef45efeb2018-04-09 18:19:24 +02001925 var SmsParameters spars := valueof(t_SmsPars);
1926
1927 f_init_handler(pars);
1928
1929 /* Perform location update and call */
1930 f_perform_lu();
1931
1932 f_establish_fully(EST_TYPE_MO_SMS);
1933
1934 //spars.exp_rp_err := 96; /* invalid mandatory information */
1935 f_mo_sms(spars);
1936
1937 f_expect_clear();
1938}
1939testcase TC_lu_and_mo_sms() runs on MTC_CT {
1940 var BSC_ConnHdlr vc_conn;
1941 f_init();
1942 vc_conn := f_start_handler(refers(f_tc_lu_and_mo_sms), 42);
1943 vc_conn.done;
1944}
1945
Harald Weltee13cfb22019-04-23 16:52:02 +02001946
Harald Weltef45efeb2018-04-09 18:19:24 +02001947private function f_vty_sms_send(charstring imsi, charstring msisdn, charstring text)
Neels Hofmeyr6aaeccf2019-03-06 15:32:26 +01001948runs on BSC_ConnHdlr {
Harald Weltef45efeb2018-04-09 18:19:24 +02001949 f_vty_transceive(MSCVTY, "subscriber imsi "&imsi&" sms sender msisdn "&msisdn&" send "&text);
1950}
1951
Neels Hofmeyr8256ed22019-03-06 15:34:01 +01001952/* Remove still pending SMS */
1953private function f_vty_sms_clear(charstring imsi)
1954runs on BSC_ConnHdlr {
1955 f_vty_transceive(MSCVTY, "subscriber imsi " & imsi & " sms delete-all");
1956 f_vty_transceive(MSCVTY, "sms-queue clear");
1957}
1958
Harald Weltef45efeb2018-04-09 18:19:24 +02001959/* LU followed by MT SMS */
Harald Weltee13cfb22019-04-23 16:52:02 +02001960friend function f_tc_lu_and_mt_sms(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltef45efeb2018-04-09 18:19:24 +02001961 var SmsParameters spars := valueof(t_SmsPars);
1962 var OCT4 tmsi;
1963
1964 f_init_handler(pars);
1965
1966 /* Perform location update and call */
1967 f_perform_lu();
1968
1969 /* register an 'expect' for given IMSI (+TMSI) */
1970 if (isvalue(g_pars.tmsi)) {
1971 tmsi := g_pars.tmsi;
1972 } else {
1973 tmsi := 'FFFFFFFF'O;
1974 }
Harald Welte6811d102019-04-14 22:23:14 +02001975 f_ran_register_imsi(g_pars.imsi, tmsi);
Harald Weltef45efeb2018-04-09 18:19:24 +02001976
Neels Hofmeyr6aaeccf2019-03-06 15:32:26 +01001977 f_vty_sms_send(hex2str(pars.imsi), "2342", "Hello SMS");
Harald Weltef45efeb2018-04-09 18:19:24 +02001978
1979 /* MSC->BSC: expect PAGING from MSC */
Harald Weltee035e3e2019-04-21 17:32:05 +02001980 f_expect_paging();
1981
Harald Weltef45efeb2018-04-09 18:19:24 +02001982 /* Establish DTAP / BSSAP / SCCP connection */
1983 f_establish_fully(EST_TYPE_PAG_RESP);
1984
1985 spars.tp.ud := 'C8329BFD064D9B53'O;
1986 f_mt_sms(spars);
1987
1988 f_expect_clear();
1989}
1990testcase TC_lu_and_mt_sms() runs on MTC_CT {
1991 var BSC_ConnHdlrPars pars;
1992 var BSC_ConnHdlr vc_conn;
1993 f_init();
1994 pars := f_init_pars(43);
1995 vc_conn := f_start_handler_with_pars(refers(f_tc_lu_and_mt_sms), pars);
Harald Weltef45efeb2018-04-09 18:19:24 +02001996 vc_conn.done;
1997}
1998
Harald Weltee13cfb22019-04-23 16:52:02 +02001999
Philipp Maier3983e702018-11-22 19:01:33 +01002000/* Paging for MT SMS but no response */
Harald Weltee13cfb22019-04-23 16:52:02 +02002001friend 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 +01002002 var SmsParameters spars := valueof(t_SmsPars);
2003 var OCT4 tmsi;
Philipp Maier3983e702018-11-22 19:01:33 +01002004 f_init_handler(pars, 150.0);
2005
2006 /* Perform location update */
2007 f_perform_lu();
2008
2009 /* register an 'expect' for given IMSI (+TMSI) */
2010 if (isvalue(g_pars.tmsi)) {
2011 tmsi := g_pars.tmsi;
2012 } else {
2013 tmsi := 'FFFFFFFF'O;
2014 }
Harald Welte6811d102019-04-14 22:23:14 +02002015 f_ran_register_imsi(g_pars.imsi, tmsi);
Philipp Maier3983e702018-11-22 19:01:33 +01002016
Neels Hofmeyr6aaeccf2019-03-06 15:32:26 +01002017 f_vty_sms_send(hex2str(pars.imsi), "2342", "Hello SMS");
2018
Neels Hofmeyr16237742019-03-06 15:34:01 +01002019 /* Expect the MSC to page exactly once */
Harald Weltee13cfb22019-04-23 16:52:02 +02002020 f_expect_paging();
Philipp Maier3983e702018-11-22 19:01:33 +01002021
2022 /* Wait some time to make sure the MSC is not delivering any further
2023 * paging messages or anything else that could be unexpected. */
2024 timer T := 20.0;
2025 T.start
2026 alt {
Harald Weltee13cfb22019-04-23 16:52:02 +02002027 [pars.ran_is_geran] BSSAP.receive(tr_BSSMAP_Paging(g_pars.imsi))
Philipp Maier3983e702018-11-22 19:01:33 +01002028 {
2029 setverdict(fail, "paging seems not to stop!");
2030 mtc.stop;
2031 }
Harald Welte62113fc2019-05-09 13:04:02 +02002032 [not pars.ran_is_geran] BSSAP.receive(tr_RANAP_Paging(cs_domain, imsi_hex2oct(g_pars.imsi))) {
Harald Weltee13cfb22019-04-23 16:52:02 +02002033 setverdict(fail, "paging seems not to stop!");
2034 mtc.stop;
2035 }
Philipp Maier3983e702018-11-22 19:01:33 +01002036 [] BSSAP.receive {
2037 setverdict(fail, "unexpected BSSAP message received");
2038 self.stop;
2039 }
2040 [] T.timeout {
2041 setverdict(pass);
2042 }
2043 }
2044
Neels Hofmeyr8256ed22019-03-06 15:34:01 +01002045 f_vty_sms_clear(hex2str(g_pars.imsi));
2046
Philipp Maier3983e702018-11-22 19:01:33 +01002047 setverdict(pass);
2048}
2049testcase TC_lu_and_mt_sms_paging_and_nothing() runs on MTC_CT {
2050 var BSC_ConnHdlrPars pars;
2051 var BSC_ConnHdlr vc_conn;
2052 f_init();
Philipp Maiera99ad262019-01-22 15:35:42 +01002053 pars := f_init_pars(1843);
Philipp Maier3983e702018-11-22 19:01:33 +01002054 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 +01002055 vc_conn.done;
2056}
2057
Harald Weltee13cfb22019-04-23 16:52:02 +02002058
Harald Weltef640a012018-04-14 17:49:21 +02002059/* mobile originated SMS from MS/BTS/BSC side to SMPP */
Harald Weltee13cfb22019-04-23 16:52:02 +02002060friend function f_tc_smpp_mo_sms(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltef640a012018-04-14 17:49:21 +02002061 var SmsParameters spars := valueof(t_SmsPars);
Harald Weltef45efeb2018-04-09 18:19:24 +02002062
Harald Weltef640a012018-04-14 17:49:21 +02002063 f_init_handler(pars);
Harald Weltef45efeb2018-04-09 18:19:24 +02002064
Harald Weltef640a012018-04-14 17:49:21 +02002065 /* Perform location update so IMSI is known + registered in MSC/VLR */
2066 f_perform_lu();
2067 f_establish_fully(EST_TYPE_MO_SMS);
2068
2069 f_mo_sms(spars);
2070
2071 var SMPP_PDU smpp;
2072 var template SMPP_PDU tr_smpp := tr_SMPP(c_SMPP_command_id_deliver_sm, ESME_ROK);
2073 tr_smpp.body.deliver_sm := {
2074 service_type := "CMT",
2075 source_addr_ton := network_specific,
2076 source_addr_npi := isdn,
2077 source_addr := hex2str(pars.msisdn),
2078 dest_addr_ton := f_sm_ton_from_gsm(spars.tp.da.tP_DA_NoPad.tP_TypeOfNumber),
2079 dest_addr_npi := f_sm_npi_from_gsm(spars.tp.da.tP_DA_NoPad.tP_NumberingPlanID),
2080 destination_addr := hex2str(spars.tp.da.tP_DA_NoPad.tP_DAValue),
2081 esm_class := '00000001'B,
2082 protocol_id := 0,
2083 priority_flag := 0,
2084 schedule_delivery_time := "",
2085 replace_if_present := 0,
2086 data_coding := '00000001'B,
2087 sm_default_msg_id := 0,
2088 sm_length := ?,
2089 short_message := spars.tp.ud,
2090 opt_pars := {
2091 {
2092 tag := user_message_reference,
2093 len := 2,
2094 opt_value := {
2095 int2_val := oct2int(spars.tp.msg_ref)
2096 }
2097 }
2098 }
2099 };
2100 alt {
2101 [] SMPP.receive(tr_smpp) -> value smpp {
2102 SMPP.send(ts_SMPP_DELIVER_SM_resp(ESME_ROK, smpp.header.seq_num));
2103 }
2104 [] SMPP.receive(tr_SMPP(c_SMPP_command_id_alert_notification, ESME_ROK)) { repeat; }
2105 }
2106
2107 f_expect_clear();
2108}
2109testcase TC_smpp_mo_sms() runs on MTC_CT {
2110 var BSC_ConnHdlr vc_conn;
2111 f_init();
2112 f_vty_config2(MSCVTY, { "smpp", "esme msc_tester"}, "default-route");
2113 vc_conn := f_start_handler(refers(f_tc_smpp_mo_sms), 44);
2114 vc_conn.done;
2115 f_vty_config2(MSCVTY, { "smpp", "esme msc_tester"}, "no default-route");
2116}
2117
Harald Weltee13cfb22019-04-23 16:52:02 +02002118
Vadim Yanitskiy103d09f2018-11-12 02:50:23 +07002119/* Test MO-SMS from MS/BTS/BSC towards HLR (via GSUP) */
Harald Weltee13cfb22019-04-23 16:52:02 +02002120friend function f_tc_gsup_mo_sms(charstring id, BSC_ConnHdlrPars pars)
Vadim Yanitskiy103d09f2018-11-12 02:50:23 +07002121runs on BSC_ConnHdlr {
2122 var SmsParameters spars := valueof(t_SmsPars);
2123 var GSUP_PDU gsup_msg_rx;
2124 var octetstring sm_tpdu;
2125
2126 f_init_handler(pars);
2127
2128 /* We need to inspect GSUP activity */
2129 f_create_gsup_expect(hex2str(g_pars.imsi));
2130
2131 /* Perform location update */
2132 f_perform_lu();
2133
2134 /* Send CM Service Request for SMS */
2135 f_establish_fully(EST_TYPE_MO_SMS);
2136
2137 /* Prepare expected SM-RP-UI (SM TPDU) */
2138 enc_TPDU_RP_DATA_MS_SGSN_fast(
2139 valueof(ts_SMS_SUBMIT(spars.tp.msg_ref,
2140 spars.tp.da, spars.tp.pid, spars.tp.dcs,
2141 spars.tp.udl, spars.tp.ud)),
2142 sm_tpdu);
2143
2144 var template GSUP_PDU mo_forwardSM := tr_GSUP_MO_FORWARD_SM_REQ(
2145 imsi := g_pars.imsi,
2146 sm_rp_mr := spars.rp.msg_ref,
2147 /* FIXME: extract SM-RP-DA from spars.rp.dest */
2148 sm_rp_da := tr_GSUP_SM_RP_DA_SMSC_ADDR(?),
2149 /* FIXME: MSISDN coding troubles */
2150 sm_rp_oa := tr_GSUP_SM_RP_OA_MSISDN(?),
2151 /* TODO: can we use decmatch here? */
2152 sm_rp_ui := sm_tpdu
2153 );
2154
2155 /* Submit an SMS on DTAP and expect MO-forwardSM-Req on GSUP */
2156 f_mo_sms_submit(spars);
2157 alt {
2158 [] GSUP.receive(mo_forwardSM) -> value gsup_msg_rx {
2159 log("RX MO-forwardSM-Req");
2160 log(gsup_msg_rx);
2161 setverdict(pass);
2162 }
2163 [] GSUP.receive {
2164 log("RX unexpected GSUP message");
2165 setverdict(fail);
2166 mtc.stop;
2167 }
2168 }
2169
2170 /* Trigger RP-ACK by sending MO-forwardSM-Res */
2171 GSUP.send(valueof(ts_GSUP_MO_FORWARD_SM_RES(
2172 imsi := g_pars.imsi,
2173 sm_rp_mr := spars.rp.msg_ref)));
2174 /* Expect RP-ACK on DTAP */
2175 f_mo_sms_wait_rp_ack(spars);
2176
2177 f_expect_clear();
2178}
2179testcase TC_gsup_mo_sms() runs on MTC_CT {
2180 var BSC_ConnHdlr vc_conn;
2181 f_init();
2182 f_vty_config(MSCVTY, "msc", "sms-over-gsup");
2183 vc_conn := f_start_handler(refers(f_tc_gsup_mo_sms), 88);
2184 vc_conn.done;
2185 f_vty_config(MSCVTY, "msc", "no sms-over-gsup");
2186}
2187
Harald Weltee13cfb22019-04-23 16:52:02 +02002188
Vadim Yanitskiy9cc019a2018-11-15 02:06:07 +07002189/* Test MO-SMMA from MS/BTS/BSC towards HLR (via GSUP) */
Harald Weltee13cfb22019-04-23 16:52:02 +02002190friend function f_tc_gsup_mo_smma(charstring id, BSC_ConnHdlrPars pars)
Vadim Yanitskiy9cc019a2018-11-15 02:06:07 +07002191runs on BSC_ConnHdlr {
2192 var SmsParameters spars := valueof(t_SmsPars);
2193 var GSUP_PDU gsup_msg_rx;
2194
2195 f_init_handler(pars);
2196
2197 /* We need to inspect GSUP activity */
2198 f_create_gsup_expect(hex2str(g_pars.imsi));
2199
2200 /* Perform location update */
2201 f_perform_lu();
2202
2203 /* Send CM Service Request for SMS */
2204 f_establish_fully(EST_TYPE_MO_SMS);
2205
2206 var template GSUP_PDU mo_ReadyForSM := tr_GSUP_MO_READY_FOR_SM_REQ(
2207 imsi := g_pars.imsi,
2208 sm_rp_mr := spars.rp.msg_ref,
2209 sm_alert_rsn := GSUP_SM_ALERT_RSN_TYPE_MEM_AVAIL
2210 );
2211
2212 /* Submit an SMS on DTAP and expect MO-forwardSM-Req on GSUP */
2213 f_mo_smma(spars);
2214 alt {
2215 [] GSUP.receive(mo_ReadyForSM) -> value gsup_msg_rx {
2216 log("RX MO-ReadyForSM-Req");
2217 log(gsup_msg_rx);
2218 setverdict(pass);
2219 }
2220 [] GSUP.receive {
2221 log("RX unexpected GSUP message");
2222 setverdict(fail);
2223 mtc.stop;
2224 }
2225 }
2226
2227 /* Trigger RP-ACK by sending MO-forwardSM-Res */
2228 GSUP.send(valueof(ts_GSUP_MO_READY_FOR_SM_RES(
2229 imsi := g_pars.imsi,
2230 sm_rp_mr := spars.rp.msg_ref)));
2231 /* Expect RP-ACK on DTAP */
2232 f_mo_sms_wait_rp_ack(spars);
2233
2234 f_expect_clear();
2235}
2236testcase TC_gsup_mo_smma() runs on MTC_CT {
2237 var BSC_ConnHdlr vc_conn;
2238 f_init();
2239 f_vty_config(MSCVTY, "msc", "sms-over-gsup");
2240 vc_conn := f_start_handler(refers(f_tc_gsup_mo_smma), 89);
2241 vc_conn.done;
2242 f_vty_config(MSCVTY, "msc", "no sms-over-gsup");
2243}
2244
Harald Weltee13cfb22019-04-23 16:52:02 +02002245
Vadim Yanitskiyd7b37ab2018-11-24 03:40:20 +07002246/* Helper for sending MT SMS over GSUP */
2247private function f_gsup_forwardSM_req(SmsParameters spars, OCT1 mms := '00'O)
2248runs on BSC_ConnHdlr {
2249 GSUP.send(ts_GSUP_MT_FORWARD_SM_REQ(
2250 imsi := g_pars.imsi,
2251 /* NOTE: MSC should assign RP-MR itself */
2252 sm_rp_mr := 'FF'O,
2253 /* FIXME: extract SM-RP-DA from spars.rp.dest */
2254 /* TODO: fix encoding of ts_GSUP_SM_RP_DA_IMSI */
2255 sm_rp_da := valueof(ts_GSUP_SM_RP_DA_MSISDN(g_pars.msisdn)),
2256 sm_rp_oa := valueof(ts_GSUP_SM_RP_OA_SMSC_ADDR(g_pars.msisdn)),
2257 /* Encoded SMS TPDU (taken from Wireshark)
2258 * FIXME: we should encode spars somehow */
2259 sm_rp_ui := '00068021436500008111328130858200'O,
2260 sm_rp_mms := mms
2261 ));
2262}
2263
2264/* Test successful MT-SMS (RP-ACK) over GSUP */
Harald Weltee13cfb22019-04-23 16:52:02 +02002265friend function f_tc_gsup_mt_sms_ack(charstring id, BSC_ConnHdlrPars pars)
Vadim Yanitskiyd7b37ab2018-11-24 03:40:20 +07002266runs on BSC_ConnHdlr {
2267 var SmsParameters spars := valueof(t_SmsPars);
2268
2269 f_init_handler(pars);
2270
2271 /* We need to inspect GSUP activity */
2272 f_create_gsup_expect(hex2str(g_pars.imsi));
2273
2274 /* Perform location update */
2275 f_perform_lu();
2276
2277 /* Register an 'expect' for given IMSI (+TMSI) */
2278 if (isvalue(g_pars.tmsi)) {
Harald Welte6811d102019-04-14 22:23:14 +02002279 f_ran_register_imsi(g_pars.imsi, g_pars.tmsi);
Vadim Yanitskiyd7b37ab2018-11-24 03:40:20 +07002280 } else {
Harald Welte6811d102019-04-14 22:23:14 +02002281 f_ran_register_imsi(g_pars.imsi, 'FFFFFFFF'O);
Vadim Yanitskiyd7b37ab2018-11-24 03:40:20 +07002282 }
2283
2284 var template GSUP_PDU mt_forwardSM_res := tr_GSUP_MT_FORWARD_SM_RES(
2285 imsi := g_pars.imsi,
2286 /* NOTE: MSC should assign RP-MR itself */
2287 sm_rp_mr := ?
2288 );
2289
2290 /* Submit a MT SMS on GSUP */
2291 f_gsup_forwardSM_req(spars);
2292
2293 /* Expect Paging Request and Establish DTAP / BSSAP / SCCP connection */
Harald Weltee035e3e2019-04-21 17:32:05 +02002294 f_expect_paging();
Vadim Yanitskiyd7b37ab2018-11-24 03:40:20 +07002295 f_establish_fully(EST_TYPE_PAG_RESP);
2296
2297 /* Wait for MT SMS on DTAP */
2298 f_mt_sms_expect(spars);
2299
2300 /* Send RP-ACK and expect MT-forwardSM-Res on GSUP */
2301 f_mt_sms_send_rp_ack(spars);
2302 alt {
2303 [] GSUP.receive(mt_forwardSM_res) {
2304 log("RX MT-forwardSM-Res (RP-ACK)");
2305 setverdict(pass);
2306 }
2307 [] GSUP.receive {
2308 log("RX unexpected GSUP message");
2309 setverdict(fail);
2310 mtc.stop;
2311 }
2312 }
2313
2314 f_expect_clear();
2315}
2316testcase TC_gsup_mt_sms_ack() runs on MTC_CT {
2317 var BSC_ConnHdlrPars pars;
2318 var BSC_ConnHdlr vc_conn;
2319 f_init();
2320 pars := f_init_pars(90);
2321 f_vty_config(MSCVTY, "msc", "sms-over-gsup");
2322 vc_conn := f_start_handler_with_pars(refers(f_tc_gsup_mt_sms_ack), pars);
2323 vc_conn.done;
2324 f_vty_config(MSCVTY, "msc", "no sms-over-gsup");
2325}
2326
Harald Weltee13cfb22019-04-23 16:52:02 +02002327
Vadim Yanitskiyd7b37ab2018-11-24 03:40:20 +07002328/* Test rejected MT-SMS (RP-ERROR) over GSUP */
Harald Weltee13cfb22019-04-23 16:52:02 +02002329friend function f_tc_gsup_mt_sms_err(charstring id, BSC_ConnHdlrPars pars)
Vadim Yanitskiyd7b37ab2018-11-24 03:40:20 +07002330runs on BSC_ConnHdlr {
2331 var SmsParameters spars := valueof(t_SmsPars);
2332 var OCT1 sm_rp_cause := '78'O; /* dummy RP-Cause value */
2333
2334 f_init_handler(pars);
2335
2336 /* We need to inspect GSUP activity */
2337 f_create_gsup_expect(hex2str(g_pars.imsi));
2338
2339 /* Perform location update */
2340 f_perform_lu();
2341
2342 /* Register an 'expect' for given IMSI (+TMSI) */
2343 if (isvalue(g_pars.tmsi)) {
Harald Welte6811d102019-04-14 22:23:14 +02002344 f_ran_register_imsi(g_pars.imsi, g_pars.tmsi);
Vadim Yanitskiyd7b37ab2018-11-24 03:40:20 +07002345 } else {
Harald Welte6811d102019-04-14 22:23:14 +02002346 f_ran_register_imsi(g_pars.imsi, 'FFFFFFFF'O);
Vadim Yanitskiyd7b37ab2018-11-24 03:40:20 +07002347 }
2348
2349 var template GSUP_PDU mt_forwardSM_err := tr_GSUP_MT_FORWARD_SM_ERR(
2350 imsi := g_pars.imsi,
2351 /* NOTE: MSC should assign RP-MR itself */
2352 sm_rp_mr := ?,
2353 sm_rp_cause := sm_rp_cause
2354 );
2355
2356 /* Submit a MT SMS on GSUP */
2357 f_gsup_forwardSM_req(spars);
2358
2359 /* Expect Paging Request and Establish DTAP / BSSAP / SCCP connection */
Harald Weltee035e3e2019-04-21 17:32:05 +02002360 f_expect_paging();
Vadim Yanitskiyd7b37ab2018-11-24 03:40:20 +07002361 f_establish_fully(EST_TYPE_PAG_RESP);
2362
2363 /* Wait for MT SMS on DTAP */
2364 f_mt_sms_expect(spars);
2365
2366 /* Send RP-ERROR and expect MT-forwardSM-Err on GSUP */
2367 f_mt_sms_send_rp_error(spars, oct2int(sm_rp_cause));
2368 alt {
2369 [] GSUP.receive(mt_forwardSM_err) {
2370 log("RX MT-forwardSM-Err (RP-ERROR)");
2371 setverdict(pass);
2372 mtc.stop;
2373 }
2374 [] GSUP.receive {
2375 log("RX unexpected GSUP message");
2376 setverdict(fail);
2377 mtc.stop;
2378 }
2379 }
2380
2381 f_expect_clear();
2382}
2383testcase TC_gsup_mt_sms_err() runs on MTC_CT {
2384 var BSC_ConnHdlrPars pars;
2385 var BSC_ConnHdlr vc_conn;
2386 f_init();
2387 pars := f_init_pars(91);
2388 f_vty_config(MSCVTY, "msc", "sms-over-gsup");
2389 vc_conn := f_start_handler_with_pars(refers(f_tc_gsup_mt_sms_err), pars);
2390 vc_conn.done;
2391 f_vty_config(MSCVTY, "msc", "no sms-over-gsup");
2392}
2393
Harald Weltee13cfb22019-04-23 16:52:02 +02002394
Vadim Yanitskiybe1ff4b2019-01-18 15:04:13 +07002395/* Test SM-RP-MR assignment for MT-SMS over GSUP */
Harald Weltee13cfb22019-04-23 16:52:02 +02002396friend function f_tc_gsup_mt_sms_rp_mr(charstring id, BSC_ConnHdlrPars pars)
Vadim Yanitskiybe1ff4b2019-01-18 15:04:13 +07002397runs on BSC_ConnHdlr {
2398 var SmsParameters spars1 := valueof(t_SmsPars); /* 1st SMS */
2399 var SmsParameters spars2 := valueof(t_SmsPars); /* 2nd SMS */
2400
2401 f_init_handler(pars);
2402
2403 /* We need to inspect GSUP activity */
2404 f_create_gsup_expect(hex2str(g_pars.imsi));
2405
2406 /* Perform location update */
2407 f_perform_lu();
2408
2409 /* Register an 'expect' for given IMSI (+TMSI) */
2410 if (isvalue(g_pars.tmsi)) {
Harald Welte6811d102019-04-14 22:23:14 +02002411 f_ran_register_imsi(g_pars.imsi, g_pars.tmsi);
Vadim Yanitskiybe1ff4b2019-01-18 15:04:13 +07002412 } else {
Harald Welte6811d102019-04-14 22:23:14 +02002413 f_ran_register_imsi(g_pars.imsi, 'FFFFFFFF'O);
Vadim Yanitskiybe1ff4b2019-01-18 15:04:13 +07002414 }
2415
2416 /* Submit the 1st MT SMS on GSUP */
2417 log("TX MT-forwardSM-Req for the 1st SMS");
2418 f_gsup_forwardSM_req(spars1);
2419
2420 /* Expect Paging Request and Establish DTAP / BSSAP / SCCP connection */
Harald Weltee035e3e2019-04-21 17:32:05 +02002421 f_expect_paging();
Vadim Yanitskiybe1ff4b2019-01-18 15:04:13 +07002422 f_establish_fully(EST_TYPE_PAG_RESP);
2423
2424 /* Wait for 1st MT SMS on DTAP */
2425 f_mt_sms_expect(spars1);
2426 log("RX the 1st SMS on DTAP, DTAP TID is ", spars1.tid,
2427 ", SM-RP-MR is ", spars1.rp.msg_ref);
2428
2429 /* Submit the 2nd MT SMS on GSUP */
2430 log("TX MT-forwardSM-Req for the 2nd SMS");
2431 f_gsup_forwardSM_req(spars2);
2432
2433 /* Wait for 2nd MT SMS on DTAP */
2434 f_mt_sms_expect(spars2);
2435 log("RX the 2nd SMS on DTAP, DTAP TID is ", spars2.tid,
2436 ", SM-RP-MR is ", spars2.rp.msg_ref);
2437
2438 /* Both transaction IDs shall be different */
2439 if (spars1.tid == spars2.tid) {
2440 log("Both DTAP transaction IDs shall be different");
2441 setverdict(fail);
2442 }
2443
2444 /* Both SM-RP-MR values shall be different */
2445 if (spars1.rp.msg_ref == spars2.rp.msg_ref) {
2446 log("Both SM-RP-MR values shall be different");
2447 setverdict(fail);
2448 }
2449
2450 /* Both SM-RP-MR values shall be assigned */
2451 if (spars1.rp.msg_ref == 'FF'O) {
2452 log("Unassigned SM-RP-MR value for the 1st SMS");
2453 setverdict(fail);
2454 }
2455 if (spars2.rp.msg_ref == 'FF'O) {
2456 log("Unassigned SM-RP-MR value for the 2nd SMS");
2457 setverdict(fail);
2458 }
2459
2460 /* Send the 1st RP-ACK and expect MT-forwardSM-Res on GSUP */
2461 f_mt_sms_send_rp_ack(spars1);
2462 alt {
2463 [] GSUP.receive(tr_GSUP_MT_FORWARD_SM_RES(
2464 imsi := g_pars.imsi,
2465 sm_rp_mr := spars1.rp.msg_ref
2466 )) {
2467 log("RX MT-forwardSM-Res (RP-ACK)");
2468 setverdict(pass);
2469 }
2470 [] GSUP.receive {
2471 log("RX unexpected GSUP message");
2472 setverdict(fail);
2473 mtc.stop;
2474 }
2475 }
2476
2477 /* Send the 2nd RP-ACK and expect MT-forwardSM-Res on GSUP */
2478 f_mt_sms_send_rp_ack(spars2);
2479 alt {
2480 [] GSUP.receive(tr_GSUP_MT_FORWARD_SM_RES(
2481 imsi := g_pars.imsi,
2482 sm_rp_mr := spars2.rp.msg_ref
2483 )) {
2484 log("RX MT-forwardSM-Res (RP-ACK)");
2485 setverdict(pass);
2486 }
2487 [] GSUP.receive {
2488 log("RX unexpected GSUP message");
2489 setverdict(fail);
2490 mtc.stop;
2491 }
2492 }
2493
2494 f_expect_clear();
2495}
2496testcase TC_gsup_mt_sms_rp_mr() runs on MTC_CT {
2497 var BSC_ConnHdlrPars pars;
2498 var BSC_ConnHdlr vc_conn;
2499 f_init();
2500 pars := f_init_pars(92);
2501 f_vty_config(MSCVTY, "msc", "sms-over-gsup");
2502 vc_conn := f_start_handler_with_pars(refers(f_tc_gsup_mt_sms_rp_mr), pars);
2503 vc_conn.done;
2504 f_vty_config(MSCVTY, "msc", "no sms-over-gsup");
2505}
2506
Harald Weltee13cfb22019-04-23 16:52:02 +02002507
Vadim Yanitskiy5ac49cc2019-01-24 16:57:31 +07002508/* Test SM-RP-MR assignment for MT-SMS over GSUP */
Harald Weltee13cfb22019-04-23 16:52:02 +02002509friend function f_tc_gsup_mo_mt_sms_rp_mr(charstring id, BSC_ConnHdlrPars pars)
Vadim Yanitskiy5ac49cc2019-01-24 16:57:31 +07002510runs on BSC_ConnHdlr {
2511 var SmsParameters spars_mo := valueof(t_SmsPars); /* MO SMMA */
2512 var SmsParameters spars_mt := valueof(t_SmsPars); /* MT SMS */
2513
2514 f_init_handler(pars);
2515
2516 /* We need to inspect GSUP activity */
2517 f_create_gsup_expect(hex2str(g_pars.imsi));
2518
2519 /* Perform location update */
2520 f_perform_lu();
2521
2522 /* Register an 'expect' for given IMSI (+TMSI) */
2523 if (isvalue(g_pars.tmsi)) {
Harald Welte6811d102019-04-14 22:23:14 +02002524 f_ran_register_imsi(g_pars.imsi, g_pars.tmsi);
Vadim Yanitskiy5ac49cc2019-01-24 16:57:31 +07002525 } else {
Harald Welte6811d102019-04-14 22:23:14 +02002526 f_ran_register_imsi(g_pars.imsi, 'FFFFFFFF'O);
Vadim Yanitskiy5ac49cc2019-01-24 16:57:31 +07002527 }
2528
2529 /* Send CM Service Request for MO SMMA */
2530 f_establish_fully(EST_TYPE_MO_SMS);
2531
2532 /* Submit MO SMMA on DTAP */
2533 log("Submit MO SMMA on DTAP, SM-RP-MR is '00'O");
2534 spars_mo.rp.msg_ref := '00'O;
2535 f_mo_smma(spars_mo);
2536
2537 /* Expect MO-forwardSM-Req for MO SMMA on GSUP */
2538 alt {
2539 [] GSUP.receive(tr_GSUP_MO_READY_FOR_SM_REQ(
2540 imsi := g_pars.imsi,
2541 sm_rp_mr := spars_mo.rp.msg_ref,
2542 sm_alert_rsn := GSUP_SM_ALERT_RSN_TYPE_MEM_AVAIL
2543 )) {
2544 log("RX MO-ReadyForSM-Req, SM-RP-MR is '00'O");
2545 setverdict(pass);
2546 }
2547 [] GSUP.receive {
2548 log("RX unexpected GSUP message");
2549 setverdict(fail);
2550 mtc.stop;
2551 }
2552 }
2553
2554 /* Submit MT SMS on GSUP */
2555 log("TX MT-forwardSM-Req for the MT SMS");
2556 f_gsup_forwardSM_req(spars_mt);
2557
2558 /* Wait for MT SMS on DTAP */
2559 f_mt_sms_expect(spars_mt);
2560 log("RX MT SMS on DTAP, DTAP TID is ", spars_mt.tid,
2561 ", SM-RP-MR is ", spars_mt.rp.msg_ref);
2562
2563 /* Both SM-RP-MR values shall be different */
2564 if (spars_mo.rp.msg_ref == spars_mt.rp.msg_ref) {
2565 log("Both SM-RP-MR values shall be different");
2566 setverdict(fail);
2567 }
2568
2569 /* SM-RP-MR value for MT SMS shall be assigned */
2570 if (spars_mt.rp.msg_ref == 'FF'O) {
2571 log("Unassigned SM-RP-MR value for the MT SMS");
2572 setverdict(fail);
2573 }
2574
2575 /* Trigger RP-ACK for MO SMMA by sending MO-forwardSM-Res */
2576 GSUP.send(valueof(ts_GSUP_MO_READY_FOR_SM_RES(
2577 imsi := g_pars.imsi,
2578 sm_rp_mr := spars_mo.rp.msg_ref)));
2579 /* Expect RP-ACK for MO SMMA on DTAP */
2580 f_mo_sms_wait_rp_ack(spars_mo);
2581
2582 /* Send RP-ACK for MT SMS and expect MT-forwardSM-Res on GSUP */
2583 f_mt_sms_send_rp_ack(spars_mt);
2584 alt {
2585 [] GSUP.receive(tr_GSUP_MT_FORWARD_SM_RES(
2586 imsi := g_pars.imsi,
2587 sm_rp_mr := spars_mt.rp.msg_ref
2588 )) {
2589 log("RX MT-forwardSM-Res (RP-ACK)");
2590 setverdict(pass);
2591 }
2592 [] GSUP.receive {
2593 log("RX unexpected GSUP message");
2594 setverdict(fail);
2595 mtc.stop;
2596 }
2597 }
2598
2599 f_expect_clear();
2600}
2601testcase TC_gsup_mo_mt_sms_rp_mr() runs on MTC_CT {
2602 var BSC_ConnHdlrPars pars;
2603 var BSC_ConnHdlr vc_conn;
2604 f_init();
2605 pars := f_init_pars(93);
2606 f_vty_config(MSCVTY, "msc", "sms-over-gsup");
2607 vc_conn := f_start_handler_with_pars(refers(f_tc_gsup_mo_mt_sms_rp_mr), pars);
2608 vc_conn.done;
2609 f_vty_config(MSCVTY, "msc", "no sms-over-gsup");
2610}
2611
Harald Weltee13cfb22019-04-23 16:52:02 +02002612
Vadim Yanitskiy1cd11a02018-12-03 02:43:35 +07002613/* Test multi-part MT-SMS over GSUP */
2614private function f_tc_gsup_mt_multi_part_sms(charstring id, BSC_ConnHdlrPars pars)
2615runs on BSC_ConnHdlr {
2616 var SmsParameters spars := valueof(t_SmsPars);
2617
2618 f_init_handler(pars);
2619
2620 /* We need to inspect GSUP activity */
2621 f_create_gsup_expect(hex2str(g_pars.imsi));
2622
2623 /* Perform location update */
2624 f_perform_lu();
2625
2626 /* Register an 'expect' for given IMSI (+TMSI) */
2627 if (isvalue(g_pars.tmsi)) {
Harald Welte6811d102019-04-14 22:23:14 +02002628 f_ran_register_imsi(g_pars.imsi, g_pars.tmsi);
Vadim Yanitskiy1cd11a02018-12-03 02:43:35 +07002629 } else {
Harald Welte6811d102019-04-14 22:23:14 +02002630 f_ran_register_imsi(g_pars.imsi, 'FFFFFFFF'O);
Vadim Yanitskiy1cd11a02018-12-03 02:43:35 +07002631 }
2632
2633 var template GSUP_PDU mt_forwardSM_res := tr_GSUP_MT_FORWARD_SM_RES(
2634 imsi := g_pars.imsi,
2635 /* NOTE: MSC should assign RP-MR itself */
2636 sm_rp_mr := ?
2637 );
2638
2639 /* Send 4 messages (NOTE: SM-RP-UI remains unchanged) */
2640 for (var integer i := 3; i >= 0; i := i-1) {
2641 /* Submit a MT SMS on GSUP (MMS is decremented) */
2642 f_gsup_forwardSM_req(spars, int2oct(i, 1));
2643
2644 /* Expect Paging Request and Establish connection */
2645 if (i == 3) { /* ... only once! */
Harald Weltee13cfb22019-04-23 16:52:02 +02002646 f_expect_paging();
Vadim Yanitskiy1cd11a02018-12-03 02:43:35 +07002647 f_establish_fully(EST_TYPE_PAG_RESP);
2648 }
2649
2650 /* Wait for MT SMS on DTAP */
2651 f_mt_sms_expect(spars);
2652
2653 /* Send RP-ACK and expect MT-forwardSM-Res on GSUP */
2654 f_mt_sms_send_rp_ack(spars);
2655 alt {
2656 [] GSUP.receive(mt_forwardSM_res) {
2657 log("RX MT-forwardSM-Res (RP-ACK)");
2658 setverdict(pass);
2659 }
2660 [] GSUP.receive {
2661 log("RX unexpected GSUP message");
2662 setverdict(fail);
2663 mtc.stop;
2664 }
2665 }
2666
2667 /* Keep some 'distance' between transmissions */
2668 f_sleep(1.5);
2669 }
2670
2671 f_expect_clear();
2672}
2673testcase TC_gsup_mt_multi_part_sms() runs on MTC_CT {
2674 var BSC_ConnHdlrPars pars;
2675 var BSC_ConnHdlr vc_conn;
2676 f_init();
2677 pars := f_init_pars(91);
2678 f_vty_config(MSCVTY, "msc", "sms-over-gsup");
2679 vc_conn := f_start_handler_with_pars(refers(f_tc_gsup_mt_multi_part_sms), pars);
2680 vc_conn.done;
2681 f_vty_config(MSCVTY, "msc", "no sms-over-gsup");
2682}
2683
Harald Weltef640a012018-04-14 17:49:21 +02002684/* convert GSM L3 TON to SMPP_TON enum */
2685function f_sm_ton_from_gsm(BIT3 ton) return SMPP_TON {
2686 select (ton) {
2687 case ('000'B) { return unknown; }
2688 case ('001'B) { return international; }
2689 case ('010'B) { return national; }
2690 case ('011'B) { return network_specific; }
2691 case ('100'B) { return subscriber_number; }
2692 case ('101'B) { return alphanumeric; }
2693 case ('110'B) { return abbreviated; }
2694 }
2695 setverdict(fail, "Unknown TON ", ton);
Daniel Willmannafce8662018-07-06 23:11:32 +02002696 mtc.stop;
Harald Weltef640a012018-04-14 17:49:21 +02002697}
2698/* convert GSM L3 NPI to SMPP_NPI enum */
2699function f_sm_npi_from_gsm(BIT4 npi) return SMPP_NPI {
2700 select (npi) {
2701 case ('0000'B) { return unknown; }
2702 case ('0001'B) { return isdn; }
2703 case ('0011'B) { return data; }
2704 case ('0100'B) { return telex; }
2705 case ('0110'B) { return land_mobile; }
2706 case ('1000'B) { return national; }
2707 case ('1001'B) { return private_; }
2708 case ('1010'B) { return ermes; }
2709 }
2710 setverdict(fail, "Unknown NPI ", npi);
Daniel Willmannafce8662018-07-06 23:11:32 +02002711 mtc.stop;
Harald Weltef640a012018-04-14 17:49:21 +02002712}
2713
2714/* build a SMPP_SM from SmsParameters */
2715function f_mt_sm_from_spars(SmsParameters spars)
2716runs on BSC_ConnHdlr return SMPP_SM {
2717 var SMPP_SM sm := {
2718 service_type := "CMT",
2719 source_addr_ton := f_sm_ton_from_gsm(spars.tp.da.tP_DA_NoPad.tP_TypeOfNumber),
2720 source_addr_npi := f_sm_npi_from_gsm(spars.tp.da.tP_DA_NoPad.tP_NumberingPlanID),
2721 source_addr := hex2str(spars.tp.da.tP_DA_NoPad.tP_DAValue),
2722 dest_addr_ton := international,
2723 dest_addr_npi := isdn,
2724 destination_addr := hex2str(g_pars.msisdn),
2725 esm_class := '00000001'B,
2726 protocol_id := 0,
2727 priority_flag := 0,
2728 schedule_delivery_time := "",
2729 validity_period := "",
2730 registered_delivery := '00000000'B,
2731 replace_if_present := 0,
2732 data_coding := '00000001'B,
2733 sm_default_msg_id := 0,
2734 sm_length := spars.tp.udl,
2735 short_message := spars.tp.ud,
2736 opt_pars := {}
2737 };
2738 return sm;
2739}
2740
2741/* helper function to encode SMS from 'spars', send it via SMPP to MSC; receive it on MS side */
2742private function f_smpp_mt_sms(SmsParameters spars, boolean trans_mode) runs on BSC_ConnHdlr {
2743 var SMPP_SM sm := f_mt_sm_from_spars(spars);
2744 if (trans_mode) {
2745 sm.esm_class := '00000010'B;
2746 }
2747
2748 /* actually cause MSC to send a SMS via SUBMIT-SM from SMPP side */
2749 SMPP.send(ts_SMPP_SUBMIT_SM(sm));
2750 if (not match(sm.esm_class, tr_ESM_CLASS_TRANSACTION)) {
2751 /* if we're not in SMPP transaction mode, we expect the SMPP-level ACK
2752 * before we expect the SMS delivery on the BSC/radio side */
2753 SMPP.receive(tr_SMPP(c_SMPP_command_id_submit_sm_resp, ESME_ROK));
2754 }
2755
2756 /* MSC->BSC: expect PAGING from MSC */
Harald Weltee035e3e2019-04-21 17:32:05 +02002757 f_expect_paging();
Harald Weltef640a012018-04-14 17:49:21 +02002758 /* Establish DTAP / BSSAP / SCCP connection */
2759 f_establish_fully(EST_TYPE_PAG_RESP);
2760 SMPP.receive(tr_SMPP(c_SMPP_command_id_alert_notification, ESME_ROK));
2761
2762 f_mt_sms(spars);
2763
2764 if (match(sm.esm_class, tr_ESM_CLASS_TRANSACTION)) {
2765 SMPP.receive(tr_SMPP(c_SMPP_command_id_submit_sm_resp, ESME_ROK));
2766 }
2767 f_expect_clear();
2768}
2769
2770/* mobile terminated SMS, from SMPP to BSC/BTS/MS */
2771private function f_tc_smpp_mt_sms(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
2772 f_init_handler(pars);
2773
2774 /* Perform location update so IMSI is known + registered in MSC/VLR */
2775 f_perform_lu();
2776 SMPP.receive(tr_SMPP(c_SMPP_command_id_alert_notification, ESME_ROK));
2777
2778 /* register an 'expect' for given IMSI (+TMSI) */
2779 var OCT4 tmsi;
2780 if (isvalue(g_pars.tmsi)) {
2781 tmsi := g_pars.tmsi;
2782 } else {
2783 tmsi := 'FFFFFFFF'O;
2784 }
Harald Welte6811d102019-04-14 22:23:14 +02002785 f_ran_register_imsi(g_pars.imsi, tmsi);
Harald Weltef640a012018-04-14 17:49:21 +02002786
2787 var SmsParameters spars := valueof(t_SmsPars);
2788 /* TODO: test with more intelligent user data; test different coding schemes */
2789 spars.tp.ud := '00'O;
2790 spars.tp.udl := 1;
2791
2792 /* first test the non-transaction store+forward mode */
2793 f_smpp_mt_sms(spars, false);
2794
2795 /* then test the transaction mode */
2796 f_smpp_mt_sms(spars, true);
2797}
2798testcase TC_smpp_mt_sms() runs on MTC_CT {
2799 var BSC_ConnHdlr vc_conn;
2800 f_init();
2801 vc_conn := f_start_handler(refers(f_tc_smpp_mt_sms), 45);
2802 vc_conn.done;
2803}
2804
Vadim Yanitskiy7d1f9182018-05-28 16:21:42 +07002805/***********************************************************************
2806 * USSD Testing
2807 ***********************************************************************/
2808
Vadim Yanitskiyce8cc372018-06-21 01:46:33 +07002809private altstep as_unexp_gsup_or_bssap_msg()
2810runs on BSC_ConnHdlr {
2811 [] GSUP.receive {
2812 setverdict(fail, "Unknown/unexpected GSUP received");
2813 self.stop;
2814 }
2815 [] BSSAP.receive {
2816 setverdict(fail, "Unknown/unexpected BSSAP message received");
2817 self.stop;
2818 }
2819}
2820
Vadim Yanitskiye5f4ed92019-06-16 02:36:33 +07002821private function f_expect_gsup_msg(template GSUP_PDU msg,
2822 float T_val := 2.0)
Vadim Yanitskiyce8cc372018-06-21 01:46:33 +07002823runs on BSC_ConnHdlr return GSUP_PDU {
2824 var GSUP_PDU gsup_msg_complete;
Vadim Yanitskiye5f4ed92019-06-16 02:36:33 +07002825 timer T := T_val;
Vadim Yanitskiyce8cc372018-06-21 01:46:33 +07002826
Vadim Yanitskiyd1e1ce52019-06-15 03:40:59 +07002827 T.start;
Vadim Yanitskiyce8cc372018-06-21 01:46:33 +07002828 alt {
2829 [] GSUP.receive(msg) -> value gsup_msg_complete {
2830 setverdict(pass);
2831 }
2832 /* We don't expect anything else */
2833 [] as_unexp_gsup_or_bssap_msg();
Vadim Yanitskiyd1e1ce52019-06-15 03:40:59 +07002834 [] T.timeout {
2835 setverdict(fail, "Timeout waiting for GSUP message: ", msg);
2836 }
Vadim Yanitskiyce8cc372018-06-21 01:46:33 +07002837 }
2838
2839 return gsup_msg_complete;
2840}
2841
Vadim Yanitskiye5f4ed92019-06-16 02:36:33 +07002842private function f_expect_mt_dtap_msg(template PDU_ML3_NW_MS msg,
2843 float T_val := 2.0)
Vadim Yanitskiyce8cc372018-06-21 01:46:33 +07002844runs on BSC_ConnHdlr return PDU_ML3_NW_MS {
2845 var PDU_DTAP_MT bssap_msg_complete;
Vadim Yanitskiye5f4ed92019-06-16 02:36:33 +07002846 timer T := T_val;
Vadim Yanitskiyce8cc372018-06-21 01:46:33 +07002847
Vadim Yanitskiyd1e1ce52019-06-15 03:40:59 +07002848 T.start;
Vadim Yanitskiyce8cc372018-06-21 01:46:33 +07002849 alt {
2850 [] BSSAP.receive(tr_PDU_DTAP_MT(msg)) -> value bssap_msg_complete {
2851 setverdict(pass);
2852 }
2853 /* We don't expect anything else */
2854 [] as_unexp_gsup_or_bssap_msg();
Vadim Yanitskiyd1e1ce52019-06-15 03:40:59 +07002855 [] T.timeout {
2856 setverdict(fail, "Timeout waiting for BSSAP message: ", msg);
2857 }
Vadim Yanitskiyce8cc372018-06-21 01:46:33 +07002858 }
2859
2860 return bssap_msg_complete.dtap;
2861}
2862
Vadim Yanitskiy2a978b92018-06-19 17:51:20 +07002863/* LU followed by MO USSD request */
Harald Weltee13cfb22019-04-23 16:52:02 +02002864friend function f_tc_lu_and_mo_ussd_single_request(charstring id, BSC_ConnHdlrPars pars)
Vadim Yanitskiy7d1f9182018-05-28 16:21:42 +07002865runs on BSC_ConnHdlr {
2866 f_init_handler(pars);
2867
2868 /* Perform location update */
2869 f_perform_lu();
2870
2871 /* Send CM Service Request for SS/USSD */
2872 f_establish_fully(EST_TYPE_SS_ACT);
2873
Vadim Yanitskiy747689e2018-06-19 00:14:28 +07002874 /* We need to inspect GSUP activity */
2875 f_create_gsup_expect(hex2str(g_pars.imsi));
2876
2877 var template OCTN facility_req := f_USSD_FACILITY_IE_INVOKE(
2878 invoke_id := 5, /* Phone may not start from 0 or 1 */
2879 op_code := SS_OP_CODE_PROCESS_USS_REQ,
2880 ussd_string := "*#100#"
2881 );
2882
2883 var template OCTN facility_rsp := f_USSD_FACILITY_IE_RETURN_RESULT(
2884 invoke_id := 5, /* InvokeID shall be the same for both REQ and RSP */
2885 op_code := SS_OP_CODE_PROCESS_USS_REQ,
2886 ussd_string := "Your extension is " & hex2str(g_pars.msisdn) & "\r"
2887 )
2888
Vadim Yanitskiy7d1f9182018-05-28 16:21:42 +07002889 /* Compose a new SS/REGISTER message with request */
2890 var template (value) PDU_ML3_MS_NW ussd_req := ts_ML3_MO_SS_REGISTER(
2891 tid := 1, /* We just need a single transaction */
2892 ti_flag := c_TIF_ORIG, /* Sent from the side that originates the TI */
Vadim Yanitskiy747689e2018-06-19 00:14:28 +07002893 facility := valueof(facility_req)
Vadim Yanitskiy7d1f9182018-05-28 16:21:42 +07002894 );
2895
2896 /* Compose SS/RELEASE_COMPLETE template with expected response */
2897 var template PDU_ML3_NW_MS ussd_rsp := tr_ML3_MT_SS_RELEASE_COMPLETE(
2898 tid := 1, /* Response should arrive within the same transaction */
2899 ti_flag := c_TIF_REPL, /* Sent to the side that originates the TI */
Vadim Yanitskiy747689e2018-06-19 00:14:28 +07002900 facility := valueof(facility_rsp)
Vadim Yanitskiy7d1f9182018-05-28 16:21:42 +07002901 );
2902
Vadim Yanitskiy747689e2018-06-19 00:14:28 +07002903 /* Compose expected MSC -> HLR message */
2904 var template GSUP_PDU gsup_req := tr_GSUP_PROC_SS_REQ(
2905 imsi := g_pars.imsi,
2906 state := OSMO_GSUP_SESSION_STATE_BEGIN,
2907 ss := valueof(facility_req)
2908 );
2909
2910 /* To be used for sending response with correct session ID */
2911 var GSUP_PDU gsup_req_complete;
2912
2913 /* Request own number */
Vadim Yanitskiy7d1f9182018-05-28 16:21:42 +07002914 BSSAP.send(ts_PDU_DTAP_MO(ussd_req));
Vadim Yanitskiy747689e2018-06-19 00:14:28 +07002915 /* Expect GSUP message containing the SS payload */
2916 gsup_req_complete := f_expect_gsup_msg(gsup_req);
2917
2918 /* Compose the response from HLR using received session ID */
2919 var template GSUP_PDU gsup_rsp := ts_GSUP_PROC_SS_REQ(
2920 imsi := g_pars.imsi,
2921 sid := gsup_req_complete.ies[1].val.session_id,
2922 state := OSMO_GSUP_SESSION_STATE_END,
2923 ss := valueof(facility_rsp)
2924 );
2925
2926 /* Finally, HLR terminates the session */
2927 GSUP.send(gsup_rsp);
2928 /* Expect RELEASE_COMPLETE message with the response */
2929 f_expect_mt_dtap_msg(ussd_rsp);
Vadim Yanitskiy7d1f9182018-05-28 16:21:42 +07002930
2931 f_expect_clear();
2932}
Vadim Yanitskiy2a978b92018-06-19 17:51:20 +07002933testcase TC_lu_and_mo_ussd_single_request() runs on MTC_CT {
Vadim Yanitskiy7d1f9182018-05-28 16:21:42 +07002934 var BSC_ConnHdlr vc_conn;
2935 f_init();
Vadim Yanitskiy2a978b92018-06-19 17:51:20 +07002936 vc_conn := f_start_handler(refers(f_tc_lu_and_mo_ussd_single_request), 46);
Vadim Yanitskiy7d1f9182018-05-28 16:21:42 +07002937 vc_conn.done;
2938}
2939
Harald Weltee13cfb22019-04-23 16:52:02 +02002940
Vadim Yanitskiy13e4a272018-06-19 18:24:31 +07002941/* LU followed by MT USSD notification */
Harald Weltee13cfb22019-04-23 16:52:02 +02002942friend function f_tc_lu_and_mt_ussd_notification(charstring id, BSC_ConnHdlrPars pars)
Vadim Yanitskiy13e4a272018-06-19 18:24:31 +07002943runs on BSC_ConnHdlr {
Vadim Yanitskiyd1e1ce52019-06-15 03:40:59 +07002944 timer T := 5.0;
2945
Vadim Yanitskiy13e4a272018-06-19 18:24:31 +07002946 f_init_handler(pars);
2947
2948 /* Perform location update */
2949 f_perform_lu();
2950
Harald Welte6811d102019-04-14 22:23:14 +02002951 f_ran_register_imsi(g_pars.imsi, g_pars.tmsi);
Vadim Yanitskiy13e4a272018-06-19 18:24:31 +07002952
2953 /* We need to inspect GSUP activity */
2954 f_create_gsup_expect(hex2str(g_pars.imsi));
2955
2956 /* Facility IE with network-originated USSD notification */
2957 var template OCTN facility_req := f_USSD_FACILITY_IE_INVOKE(
2958 op_code := SS_OP_CODE_USS_NOTIFY,
2959 ussd_string := "Mahlzeit!"
2960 );
2961
2962 /* Facility IE with acknowledgment to the USSD notification */
2963 var template OCTN facility_rsp := enc_SS_FacilityInformation(
2964 /* In case of USSD notification, Return Result is empty */
2965 valueof(ts_SS_USSD_FACILITY_RETURN_RESULT_EMPTY())
2966 );
2967
2968 /* Compose a new MT SS/REGISTER message with USSD notification */
2969 var template PDU_ML3_NW_MS ussd_ntf := tr_ML3_MT_SS_REGISTER(
2970 tid := 0, /* FIXME: most likely, it should be 0 */
2971 ti_flag := c_TIF_ORIG, /* Sent from the side that originates the TI */
2972 facility := valueof(facility_req)
2973 );
2974
2975 /* Compose HLR -> MSC GSUP message */
2976 var template (value) GSUP_PDU gsup_req := ts_GSUP_PROC_SS_REQ(
2977 imsi := g_pars.imsi,
2978 sid := '20000101'O,
2979 state := OSMO_GSUP_SESSION_STATE_BEGIN,
2980 ss := valueof(facility_req)
2981 );
2982
2983 /* Send it to MSC and expect Paging Request */
2984 GSUP.send(gsup_req);
Vadim Yanitskiyd1e1ce52019-06-15 03:40:59 +07002985 T.start;
Vadim Yanitskiy13e4a272018-06-19 18:24:31 +07002986 alt {
Harald Weltee13cfb22019-04-23 16:52:02 +02002987 [pars.ran_is_geran] BSSAP.receive(tr_BSSMAP_Paging(g_pars.imsi)) {
2988 setverdict(pass);
2989 }
Harald Welte62113fc2019-05-09 13:04:02 +02002990 [not pars.ran_is_geran] BSSAP.receive(tr_RANAP_Paging(cs_domain, imsi_hex2oct(g_pars.imsi))) {
Vadim Yanitskiy13e4a272018-06-19 18:24:31 +07002991 setverdict(pass);
2992 }
2993 /* We don't expect anything else */
2994 [] as_unexp_gsup_or_bssap_msg();
Vadim Yanitskiyd1e1ce52019-06-15 03:40:59 +07002995 [] T.timeout {
2996 setverdict(fail, "Timeout waiting for Paging Request");
2997 }
Vadim Yanitskiy13e4a272018-06-19 18:24:31 +07002998 }
2999
3000 /* Send Paging Response and expect USSD notification */
3001 f_establish_fully(EST_TYPE_PAG_RESP);
3002 /* Expect MT REGISTER message with USSD notification */
3003 f_expect_mt_dtap_msg(ussd_ntf);
3004
3005 /* Compose a new MO SS/FACILITY message with empty response */
3006 var template (value) PDU_ML3_MS_NW ussd_rsp := ts_ML3_MO_SS_FACILITY(
3007 tid := 0, /* FIXME: it shall match the request tid */
3008 ti_flag := c_TIF_REPL, /* Sent to the side that originates the TI */
3009 facility := valueof(facility_rsp)
3010 );
3011
3012 /* Compose expected MSC -> HLR GSUP message */
3013 var template GSUP_PDU gsup_rsp := tr_GSUP_PROC_SS_REQ(
3014 imsi := g_pars.imsi,
3015 sid := '20000101'O,
3016 state := OSMO_GSUP_SESSION_STATE_CONTINUE,
3017 ss := valueof(facility_rsp)
3018 );
3019
3020 /* MS sends response to the notification */
3021 BSSAP.send(ts_PDU_DTAP_MO(ussd_rsp));
3022 /* Expect GSUP message containing the SS payload */
3023 f_expect_gsup_msg(gsup_rsp);
3024
3025 /* Compose expected MT SS/RELEASE COMPLETE message */
3026 var template PDU_ML3_NW_MS ussd_term := tr_ML3_MT_SS_RELEASE_COMPLETE(
3027 tid := 0, /* FIXME: it shall match the request tid */
3028 ti_flag := c_TIF_ORIG, /* Sent from the side that originates the TI */
3029 facility := omit
3030 );
3031
3032 /* Compose MSC -> HLR GSUP message */
3033 var template GSUP_PDU gsup_term := ts_GSUP_PROC_SS_REQ(
3034 imsi := g_pars.imsi,
3035 sid := '20000101'O,
3036 state := OSMO_GSUP_SESSION_STATE_END
3037 );
3038
3039 /* Finally, HLR terminates the session */
3040 GSUP.send(gsup_term)
3041 /* Expect MT RELEASE COMPLETE without Facility IE */
3042 f_expect_mt_dtap_msg(ussd_term);
3043
3044 f_expect_clear();
3045}
3046testcase TC_lu_and_mt_ussd_notification() runs on MTC_CT {
3047 var BSC_ConnHdlr vc_conn;
3048 f_init();
3049 vc_conn := f_start_handler(refers(f_tc_lu_and_mt_ussd_notification), 47);
3050 vc_conn.done;
3051}
3052
Harald Weltee13cfb22019-04-23 16:52:02 +02003053
Vadim Yanitskiy2a978b92018-06-19 17:51:20 +07003054/* LU followed by MT call and MO USSD request during this call */
Harald Weltee13cfb22019-04-23 16:52:02 +02003055friend function f_tc_lu_and_mo_ussd_during_mt_call(charstring id, BSC_ConnHdlrPars pars)
Vadim Yanitskiy0aaf48d2018-06-06 07:02:47 +07003056runs on BSC_ConnHdlr {
3057 f_init_handler(pars);
3058
3059 /* Call parameters taken from f_tc_lu_and_mt_call */
3060 var CallParameters cpars := valueof(t_CallParams('123456'H, 0));
3061 cpars.mgcp_connection_id_bss := '10004'H;
3062 cpars.mgcp_connection_id_mss := '10005'H;
3063 cpars.mgcp_ep := "rtpbridge/1@mgw";
3064 cpars.bss_rtp_port := 1110;
3065
3066 /* Perform location update */
3067 f_perform_lu();
3068
3069 /* Establish a MT call */
3070 f_mt_call_establish(cpars);
3071
3072 /* Hold the call for some time */
3073 f_sleep(1.0);
3074
Vadim Yanitskiy747689e2018-06-19 00:14:28 +07003075 var template OCTN facility_req := f_USSD_FACILITY_IE_INVOKE(
3076 op_code := SS_OP_CODE_PROCESS_USS_REQ,
3077 ussd_string := "*#100#"
3078 );
3079
3080 var template OCTN facility_rsp := f_USSD_FACILITY_IE_RETURN_RESULT(
3081 op_code := SS_OP_CODE_PROCESS_USS_REQ,
3082 ussd_string := "Your extension is " & hex2str(g_pars.msisdn) & "\r"
3083 )
3084
Vadim Yanitskiy0aaf48d2018-06-06 07:02:47 +07003085 /* Compose a new SS/REGISTER message with request */
3086 var template (value) PDU_ML3_MS_NW ussd_req := ts_ML3_MO_SS_REGISTER(
3087 tid := 1, /* We just need a single transaction */
3088 ti_flag := c_TIF_ORIG, /* Sent from the side that originates the TI */
Vadim Yanitskiy747689e2018-06-19 00:14:28 +07003089 facility := valueof(facility_req)
Vadim Yanitskiy0aaf48d2018-06-06 07:02:47 +07003090 );
3091
3092 /* Compose SS/RELEASE_COMPLETE template with expected response */
3093 var template PDU_ML3_NW_MS ussd_rsp := tr_ML3_MT_SS_RELEASE_COMPLETE(
3094 tid := 1, /* Response should arrive within the same transaction */
3095 ti_flag := c_TIF_REPL, /* Sent to the side that originates the TI */
Vadim Yanitskiy747689e2018-06-19 00:14:28 +07003096 facility := valueof(facility_rsp)
Vadim Yanitskiy0aaf48d2018-06-06 07:02:47 +07003097 );
3098
Vadim Yanitskiy747689e2018-06-19 00:14:28 +07003099 /* Compose expected MSC -> HLR message */
3100 var template GSUP_PDU gsup_req := tr_GSUP_PROC_SS_REQ(
3101 imsi := g_pars.imsi,
3102 state := OSMO_GSUP_SESSION_STATE_BEGIN,
3103 ss := valueof(facility_req)
3104 );
3105
3106 /* To be used for sending response with correct session ID */
3107 var GSUP_PDU gsup_req_complete;
3108
3109 /* Request own number */
Vadim Yanitskiy0aaf48d2018-06-06 07:02:47 +07003110 BSSAP.send(ts_PDU_DTAP_MO(ussd_req));
Vadim Yanitskiy747689e2018-06-19 00:14:28 +07003111 /* Expect GSUP message containing the SS payload */
3112 gsup_req_complete := f_expect_gsup_msg(gsup_req);
3113
3114 /* Compose the response from HLR using received session ID */
3115 var template GSUP_PDU gsup_rsp := ts_GSUP_PROC_SS_REQ(
3116 imsi := g_pars.imsi,
3117 sid := gsup_req_complete.ies[1].val.session_id,
3118 state := OSMO_GSUP_SESSION_STATE_END,
3119 ss := valueof(facility_rsp)
3120 );
3121
3122 /* Finally, HLR terminates the session */
3123 GSUP.send(gsup_rsp);
3124 /* Expect RELEASE_COMPLETE message with the response */
3125 f_expect_mt_dtap_msg(ussd_rsp);
Vadim Yanitskiy0aaf48d2018-06-06 07:02:47 +07003126
3127 /* Hold the call for some time */
3128 f_sleep(1.0);
3129
3130 /* Release the call (does Clear Complete itself) */
3131 f_call_hangup(cpars, true);
3132}
Vadim Yanitskiy2a978b92018-06-19 17:51:20 +07003133testcase TC_lu_and_mo_ussd_during_mt_call() runs on MTC_CT {
Vadim Yanitskiy0aaf48d2018-06-06 07:02:47 +07003134 var BSC_ConnHdlr vc_conn;
3135 f_init();
Vadim Yanitskiy2a978b92018-06-19 17:51:20 +07003136 vc_conn := f_start_handler(refers(f_tc_lu_and_mo_ussd_during_mt_call), 48);
Vadim Yanitskiy0aaf48d2018-06-06 07:02:47 +07003137 vc_conn.done;
3138}
3139
Neels Hofmeyr692c9ee2018-04-10 02:07:13 +02003140/* BSSMAP Clear Request in the middle of a call, see OS#3062 */
Harald Weltee13cfb22019-04-23 16:52:02 +02003141friend function f_tc_mo_cc_bssmap_clear(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Neels Hofmeyr692c9ee2018-04-10 02:07:13 +02003142 f_init_handler(pars);
3143 var CallParameters cpars := valueof(t_CallParams('12345'H, 0));
3144 var MNCC_PDU mncc;
3145 var MgcpCommand mgcp_cmd;
3146
3147 f_perform_lu();
3148
3149 f_establish_fully();
3150 f_create_mncc_expect(hex2str(cpars.called_party));
3151 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
3152
3153 BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_CC_SETUP(cpars.transaction_id, cpars.called_party)));
3154 MNCC.receive(tr_MNCC_SETUP_ind(?, tr_MNCC_number(hex2str(cpars.called_party)))) -> value mncc;
3155 cpars.mncc_callref := mncc.u.signal.callref;
3156 log("mncc_callref=", cpars.mncc_callref);
3157 MNCC.send(ts_MNCC_CALL_PROC_req(cpars.mncc_callref, cpars.mncc_bearer_cap));
3158 BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_CC_CALL_PROC(cpars.transaction_id)));
3159
3160 MNCC.send(ts_MNCC_ALERT_req(cpars.mncc_callref));
3161 BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_CC_ALERTING(cpars.transaction_id)));
3162 MGCP.receive(tr_CRCX);
3163
3164 f_sleep(1.0);
Harald Weltee13cfb22019-04-23 16:52:02 +02003165 if (pars.ran_is_geran) {
3166 BSSAP.send(ts_BSSMAP_ClearRequest(0));
3167 } else {
3168 BSSAP.send(ts_RANAP_IuReleaseRequest(ts_RanapCause_om_intervention));
3169 }
Neels Hofmeyr692c9ee2018-04-10 02:07:13 +02003170
Neels Hofmeyrde76f052019-02-26 05:02:46 +01003171 var default ccrel := activate(as_optional_cc_rel(cpars));
Neels Hofmeyr692c9ee2018-04-10 02:07:13 +02003172
Harald Weltee13cfb22019-04-23 16:52:02 +02003173 if (pars.ran_is_geran) {
3174 interleave {
3175 [] MNCC.receive(tr_MNCC_REL_ind(?, ?)) { };
3176 [] BSSAP.receive(tr_BSSMAP_ClearCommand) {
Neels Hofmeyrde76f052019-02-26 05:02:46 +01003177 BSSAP.send(ts_BSSMAP_ClearComplete);
Harald Weltee13cfb22019-04-23 16:52:02 +02003178 };
3179 }
3180 } else {
3181 interleave {
3182 [] MNCC.receive(tr_MNCC_REL_ind(?, ?)) { };
3183 [] BSSAP.receive(tr_RANAP_IuReleaseCommand(?)) {
3184 BSSAP.send(ts_RANAP_IuReleaseComplete);
3185 };
3186 }
Neels Hofmeyrde76f052019-02-26 05:02:46 +01003187 }
3188
3189 deactivate(ccrel);
Neels Hofmeyr692c9ee2018-04-10 02:07:13 +02003190
3191 f_sleep(1.0);
3192}
3193testcase TC_mo_cc_bssmap_clear() runs on MTC_CT {
3194 var BSC_ConnHdlr vc_conn;
3195 f_init();
3196
3197 vc_conn := f_start_handler(refers(f_tc_mo_cc_bssmap_clear), 43);
3198 vc_conn.done;
3199}
3200
Harald Weltee13cfb22019-04-23 16:52:02 +02003201
Vadim Yanitskiy13e4a272018-06-19 18:24:31 +07003202/* LU followed by MT call and MT USSD request during this call */
Harald Weltee13cfb22019-04-23 16:52:02 +02003203friend function f_tc_lu_and_mt_ussd_during_mt_call(charstring id, BSC_ConnHdlrPars pars)
Vadim Yanitskiy13e4a272018-06-19 18:24:31 +07003204runs on BSC_ConnHdlr {
3205 f_init_handler(pars);
3206
3207 /* Call parameters taken from f_tc_lu_and_mt_call */
3208 var CallParameters cpars := valueof(t_CallParams('123456'H, 0));
3209 cpars.mgcp_connection_id_bss := '10004'H;
3210 cpars.mgcp_connection_id_mss := '10005'H;
3211 cpars.mgcp_ep := "rtpbridge/1@mgw";
3212 cpars.bss_rtp_port := 1110;
3213
3214 /* Perform location update */
3215 f_perform_lu();
3216
3217 /* Establish a MT call */
3218 f_mt_call_establish(cpars);
3219
3220 /* Hold the call for some time */
3221 f_sleep(1.0);
3222
3223 var template OCTN facility_req := f_USSD_FACILITY_IE_INVOKE(
3224 op_code := SS_OP_CODE_USS_REQUEST,
3225 ussd_string := "Please type anything..."
3226 );
3227
3228 var template OCTN facility_rsp := f_USSD_FACILITY_IE_RETURN_RESULT(
3229 op_code := SS_OP_CODE_USS_REQUEST,
3230 ussd_string := "Nope."
3231 )
3232
3233 /* Compose MT SS/REGISTER message with network-originated request */
3234 var template (value) PDU_ML3_NW_MS ussd_req := ts_ML3_MT_SS_REGISTER(
3235 tid := 0, /* FIXME: most likely, it should be 0 */
3236 ti_flag := c_TIF_ORIG, /* Sent from the side that originates the TI */
3237 facility := valueof(facility_req)
3238 );
3239
3240 /* Compose HLR -> MSC GSUP message */
3241 var template (value) GSUP_PDU gsup_req := ts_GSUP_PROC_SS_REQ(
3242 imsi := g_pars.imsi,
3243 sid := '20000101'O,
3244 state := OSMO_GSUP_SESSION_STATE_BEGIN,
3245 ss := valueof(facility_req)
3246 );
3247
3248 /* Send it to MSC */
3249 GSUP.send(gsup_req);
3250 /* Expect MT REGISTER message with USSD request */
3251 f_expect_mt_dtap_msg(ussd_req);
3252
3253 /* Compose a new MO SS/FACILITY message with response */
3254 var template (value) PDU_ML3_MS_NW ussd_rsp := ts_ML3_MO_SS_FACILITY(
3255 tid := 0, /* FIXME: it shall match the request tid */
3256 ti_flag := c_TIF_REPL, /* Sent to the side that originates the TI */
3257 facility := valueof(facility_rsp)
3258 );
3259
3260 /* Compose expected MSC -> HLR GSUP message */
3261 var template GSUP_PDU gsup_rsp := tr_GSUP_PROC_SS_REQ(
3262 imsi := g_pars.imsi,
3263 sid := '20000101'O,
3264 state := OSMO_GSUP_SESSION_STATE_CONTINUE,
3265 ss := valueof(facility_rsp)
3266 );
3267
3268 /* MS sends response */
3269 BSSAP.send(ts_PDU_DTAP_MO(ussd_rsp));
3270 f_expect_gsup_msg(gsup_rsp);
3271
3272 /* Compose expected MT SS/RELEASE COMPLETE message */
3273 var template PDU_ML3_NW_MS ussd_term := tr_ML3_MT_SS_RELEASE_COMPLETE(
3274 tid := 0, /* FIXME: it shall match the request tid */
3275 ti_flag := c_TIF_ORIG, /* Sent from the side that originates the TI */
3276 facility := omit
3277 );
3278
3279 /* Compose MSC -> HLR GSUP message */
3280 var template GSUP_PDU gsup_term := ts_GSUP_PROC_SS_REQ(
3281 imsi := g_pars.imsi,
3282 sid := '20000101'O,
3283 state := OSMO_GSUP_SESSION_STATE_END
3284 );
3285
3286 /* Finally, HLR terminates the session */
3287 GSUP.send(gsup_term);
3288 /* Expect MT RELEASE COMPLETE without Facility IE */
3289 f_expect_mt_dtap_msg(ussd_term);
3290
3291 /* Hold the call for some time */
3292 f_sleep(1.0);
3293
3294 /* Release the call (does Clear Complete itself) */
3295 f_call_hangup(cpars, true);
3296}
3297testcase TC_lu_and_mt_ussd_during_mt_call() runs on MTC_CT {
3298 var BSC_ConnHdlr vc_conn;
3299 f_init();
3300 vc_conn := f_start_handler(refers(f_tc_lu_and_mt_ussd_during_mt_call), 49);
3301 vc_conn.done;
3302}
3303
Harald Weltee13cfb22019-04-23 16:52:02 +02003304
Vadim Yanitskiy2daf52d2018-06-21 04:19:58 +07003305/* LU followed by MO USSD request and MO Release during transaction */
Harald Weltee13cfb22019-04-23 16:52:02 +02003306friend function f_tc_lu_and_mo_ussd_mo_release(charstring id, BSC_ConnHdlrPars pars)
Vadim Yanitskiy2daf52d2018-06-21 04:19:58 +07003307runs on BSC_ConnHdlr {
3308 f_init_handler(pars);
3309
3310 /* Perform location update */
3311 f_perform_lu();
3312
3313 /* Send CM Service Request for SS/USSD */
3314 f_establish_fully(EST_TYPE_SS_ACT);
3315
3316 /* We need to inspect GSUP activity */
3317 f_create_gsup_expect(hex2str(g_pars.imsi));
3318
3319 var template OCTN facility_ms_req := f_USSD_FACILITY_IE_INVOKE(
3320 invoke_id := 1, /* Initial request */
3321 op_code := SS_OP_CODE_PROCESS_USS_REQ,
3322 ussd_string := "*6766*266#"
3323 );
3324
3325 var template OCTN facility_net_req := f_USSD_FACILITY_IE_INVOKE(
3326 invoke_id := 2, /* Counter request */
3327 op_code := SS_OP_CODE_USS_REQUEST,
3328 ussd_string := "Password?!?"
3329 )
3330
3331 /* Compose MO SS/REGISTER message with request */
3332 var template (value) PDU_ML3_MS_NW ussd_ms_req := ts_ML3_MO_SS_REGISTER(
3333 tid := 1, /* We just need a single transaction */
3334 ti_flag := c_TIF_ORIG, /* Sent from the side that originates the TI */
3335 facility := valueof(facility_ms_req)
3336 );
3337
3338 /* Compose expected MSC -> HLR message */
3339 var template GSUP_PDU gsup_ms_req := tr_GSUP_PROC_SS_REQ(
3340 imsi := g_pars.imsi,
3341 state := OSMO_GSUP_SESSION_STATE_BEGIN,
3342 ss := valueof(facility_ms_req)
3343 );
3344
3345 /* To be used for sending response with correct session ID */
3346 var GSUP_PDU gsup_ms_req_complete;
3347
3348 /* Initiate a new transaction */
3349 BSSAP.send(ts_PDU_DTAP_MO(ussd_ms_req));
3350 /* Expect GSUP request with original Facility IE */
3351 gsup_ms_req_complete := f_expect_gsup_msg(gsup_ms_req);
3352
3353 /* Compose the response from HLR using received session ID */
3354 var template (value) GSUP_PDU gsup_net_req := ts_GSUP_PROC_SS_REQ(
3355 imsi := g_pars.imsi,
3356 sid := gsup_ms_req_complete.ies[1].val.session_id,
3357 state := OSMO_GSUP_SESSION_STATE_CONTINUE,
3358 ss := valueof(facility_net_req)
3359 );
3360
3361 /* Compose expected MT SS/FACILITY template with counter request */
3362 var template PDU_ML3_NW_MS ussd_net_req := tr_ML3_MT_SS_FACILITY(
3363 tid := 1, /* Response should arrive within the same transaction */
3364 ti_flag := c_TIF_REPL, /* Sent to the side that originates the TI */
3365 facility := valueof(facility_net_req)
3366 );
3367
3368 /* Send response over GSUP */
3369 GSUP.send(gsup_net_req);
3370 /* Expect MT SS/FACILITY message with counter request */
3371 f_expect_mt_dtap_msg(ussd_net_req);
3372
3373 /* Compose MO SS/RELEASE COMPLETE */
3374 var template (value) PDU_ML3_MS_NW ussd_abort := ts_ML3_MO_SS_RELEASE_COMPLETE(
3375 tid := 1, /* Response should arrive within the same transaction */
3376 ti_flag := c_TIF_ORIG, /* Sent from the side that originates the TI */
3377 facility := omit
3378 /* TODO: cause? */
3379 );
3380
3381 /* Compose expected HLR -> MSC abort message */
3382 var template GSUP_PDU gsup_abort := tr_GSUP_PROC_SS_REQ(
3383 imsi := g_pars.imsi,
3384 sid := gsup_ms_req_complete.ies[1].val.session_id,
3385 state := OSMO_GSUP_SESSION_STATE_END
3386 );
3387
3388 /* Abort transaction */
3389 BSSAP.send(ts_PDU_DTAP_MO(ussd_abort));
3390 /* Expect GSUP message indicating abort */
3391 f_expect_gsup_msg(gsup_abort);
3392
3393 f_expect_clear();
3394}
3395testcase TC_lu_and_mo_ussd_mo_release() runs on MTC_CT {
3396 var BSC_ConnHdlr vc_conn;
3397 f_init();
3398 vc_conn := f_start_handler(refers(f_tc_lu_and_mo_ussd_mo_release), 50);
3399 vc_conn.done;
3400}
3401
Harald Weltee13cfb22019-04-23 16:52:02 +02003402
Vadim Yanitskiy0e392dd2018-11-29 00:47:54 +07003403/* LU followed by MO USSD request and MT Release due to timeout */
Harald Weltee13cfb22019-04-23 16:52:02 +02003404friend function f_tc_lu_and_ss_session_timeout(charstring id, BSC_ConnHdlrPars pars)
Vadim Yanitskiy0e392dd2018-11-29 00:47:54 +07003405runs on BSC_ConnHdlr {
3406 f_init_handler(pars);
3407
3408 /* Perform location update */
3409 f_perform_lu();
3410
3411 /* Send CM Service Request for SS/USSD */
3412 f_establish_fully(EST_TYPE_SS_ACT);
3413
3414 /* We need to inspect GSUP activity */
3415 f_create_gsup_expect(hex2str(g_pars.imsi));
3416
3417 var template OCTN facility_ms_req := f_USSD_FACILITY_IE_INVOKE(
3418 invoke_id := 1,
3419 op_code := SS_OP_CODE_PROCESS_USS_REQ,
3420 ussd_string := "#release_me");
3421
3422 /* Compose MO SS/REGISTER message with request */
3423 var template (value) PDU_ML3_MS_NW ussd_ms_req := ts_ML3_MO_SS_REGISTER(
3424 tid := 1, /* An arbitrary transaction identifier */
3425 ti_flag := c_TIF_ORIG, /* Sent from the side that originates the TI */
3426 facility := valueof(facility_ms_req));
3427
3428 /* Compose expected MSC -> HLR message */
3429 var template GSUP_PDU gsup_ms_req := tr_GSUP_PROC_SS_REQ(
3430 imsi := g_pars.imsi,
3431 state := OSMO_GSUP_SESSION_STATE_BEGIN,
3432 ss := valueof(facility_ms_req));
3433
3434 /* To be used for sending response with correct session ID */
3435 var GSUP_PDU gsup_ms_req_complete;
3436
3437 /* Initiate a new SS transaction */
3438 BSSAP.send(ts_PDU_DTAP_MO(ussd_ms_req));
3439 /* Expect GSUP request with original Facility IE */
3440 gsup_ms_req_complete := f_expect_gsup_msg(gsup_ms_req);
3441
3442 /* Don't respond, wait for timeout */
3443 f_sleep(3.0);
3444
3445 var template PDU_ML3_NW_MS dtap_rel := tr_ML3_MT_SS_RELEASE_COMPLETE(
3446 tid := 1, /* Should match the request's tid */
3447 ti_flag := c_TIF_REPL, /* Sent to the side that originates the TI */
3448 cause := *, /* TODO: expect some specific value */
3449 facility := omit);
3450
3451 var template GSUP_PDU gsup_rel := tr_GSUP_PROC_SS_ERR(
3452 imsi := g_pars.imsi,
3453 sid := gsup_ms_req_complete.ies[1].val.session_id,
3454 state := OSMO_GSUP_SESSION_STATE_END,
3455 cause := ?); /* TODO: expect some specific value */
3456
3457 /* Expect release on both interfaces */
3458 interleave {
3459 [] BSSAP.receive(tr_PDU_DTAP_MT(dtap_rel)) { };
3460 [] GSUP.receive(gsup_rel) { };
3461 }
3462
3463 f_expect_clear();
3464 setverdict(pass);
3465}
3466testcase TC_lu_and_ss_session_timeout() runs on MTC_CT {
3467 var BSC_ConnHdlr vc_conn;
3468 f_init();
Vadim Yanitskiy36d28dd2018-12-03 02:45:45 +07003469 f_vty_config(MSCVTY, "msc", "ncss guard-timeout 3");
Vadim Yanitskiy0e392dd2018-11-29 00:47:54 +07003470 vc_conn := f_start_handler(refers(f_tc_lu_and_ss_session_timeout), 51);
3471 vc_conn.done;
Vadim Yanitskiy36d28dd2018-12-03 02:45:45 +07003472 f_vty_config(MSCVTY, "msc", "ncss guard-timeout 0");
Vadim Yanitskiy0e392dd2018-11-29 00:47:54 +07003473}
3474
Vadim Yanitskiy0e6c9f52019-06-15 01:01:28 +07003475/* MT (network-originated) USSD for unknown subscriber */
3476friend function f_tc_mt_ussd_for_unknown_subscr(charstring id, BSC_ConnHdlrPars pars)
3477runs on BSC_ConnHdlr {
3478 var hexstring imsi := '000000000000000'H; /* Some unknown IMSI */
3479 var OCT4 sid := '20000222'O;
Vadim Yanitskiy0e6c9f52019-06-15 01:01:28 +07003480
3481 f_init_handler(pars);
3482 f_ran_register_imsi(imsi, 'FFFFFFFF'O);
3483 f_create_gsup_expect(hex2str(imsi));
3484
3485 var template (value) GSUP_PDU gsup_req := ts_GSUP_PROC_SS_REQ(
3486 imsi := imsi,
3487 sid := sid,
3488 state := OSMO_GSUP_SESSION_STATE_BEGIN,
3489 ss := f_rnd_octstring(23)
3490 );
3491
3492 /* Error with cause GMM_CAUSE_IMSI_UNKNOWN */
3493 var template GSUP_PDU gsup_rsp := tr_GSUP_PROC_SS_ERR(
3494 imsi := imsi,
3495 sid := sid,
3496 state := OSMO_GSUP_SESSION_STATE_END,
3497 cause := 2 /* FIXME: introduce an enumerated type! */
3498 );
3499
3500 /* Initiate a MT USSD notification */
3501 GSUP.send(gsup_req);
3502
3503 /* Expect GSUP PROC_SS_ERROR message */
Vadim Yanitskiy851798c2019-06-15 14:22:28 +07003504 f_expect_gsup_msg(gsup_rsp);
Vadim Yanitskiy0e6c9f52019-06-15 01:01:28 +07003505}
3506testcase TC_mt_ussd_for_unknown_subscr() runs on MTC_CT {
3507 var BSC_ConnHdlr vc_conn;
3508 f_init();
3509 vc_conn := f_start_handler(refers(f_tc_mt_ussd_for_unknown_subscr), 0);
3510 vc_conn.done;
3511}
3512
Vadim Yanitskiyc3c07d42019-06-17 23:00:44 +07003513/* MO (mobile-originated) SS/USSD for unknown transaction */
3514friend function f_tc_mo_ussd_for_unknown_trans(charstring id, BSC_ConnHdlrPars pars)
3515runs on BSC_ConnHdlr {
3516 f_init_handler(pars);
3517
3518 f_ran_register_imsi(g_pars.imsi, 'FFFFFFFF'O);
3519 f_create_gsup_expect(hex2str(g_pars.imsi));
3520
3521 /* Perform location update */
3522 f_perform_lu();
3523
3524 /* Send CM Service Request for SS/USSD */
3525 f_establish_fully(EST_TYPE_SS_ACT);
3526
3527 /* GSM 04.80 FACILITY message for a non-existing transaction */
3528 var template (value) PDU_ML3_MS_NW mo_ss_fac := ts_ML3_MO_SS_FACILITY(
3529 tid := 1, /* An arbitrary transaction identifier */
3530 ti_flag := c_TIF_ORIG, /* Sent from the side that originates the TI */
3531 facility := f_rnd_octstring(23) /* We don't care about the Facility IE */
3532 );
3533
3534 /* GSM 04.80 RELEASE COMPLETE message for a non-existing transaction */
3535 var template (value) PDU_ML3_MS_NW mo_ss_rel := ts_ML3_MO_SS_RELEASE_COMPLETE(
3536 tid := 1, /* An arbitrary transaction identifier */
3537 ti_flag := c_TIF_ORIG, /* Sent from the side that originates the TI */
3538 facility := f_rnd_octstring(23) /* We don't care about the Facility IE */
3539 );
3540
3541 /* Expected response from the network */
3542 var template PDU_ML3_NW_MS mt_ss_rel := tr_ML3_MT_SS_RELEASE_COMPLETE(
3543 tid := 1, /* Same as in the FACILITY message */
3544 ti_flag := c_TIF_REPL, /* Sent to the side that originates the TI */
3545 facility := omit
3546 );
3547
3548 /* Send GSM 04.80 FACILITY for non-existing transaction */
3549 BSSAP.send(ts_PDU_DTAP_MO(mo_ss_fac));
3550
3551 /* Expect GSM 04.80 RELEASE COMPLETE message */
3552 f_expect_mt_dtap_msg(mt_ss_rel);
3553 f_expect_clear();
3554
3555 /* Send another CM Service Request for SS/USSD */
3556 f_establish_fully(EST_TYPE_SS_ACT);
3557
3558 /* Send GSM 04.80 RELEASE COMPLETE for non-existing transaction */
3559 BSSAP.send(ts_PDU_DTAP_MO(mo_ss_rel));
3560
3561 /* Expect GSM 04.80 RELEASE COMPLETE message */
3562 f_expect_mt_dtap_msg(mt_ss_rel);
3563 f_expect_clear();
3564}
3565testcase TC_mo_ussd_for_unknown_trans() runs on MTC_CT {
3566 var BSC_ConnHdlr vc_conn;
3567 f_init();
3568 vc_conn := f_start_handler(refers(f_tc_mo_ussd_for_unknown_trans), 111);
3569 vc_conn.done;
3570}
3571
Vadim Yanitskiyd612d282019-06-15 14:46:03 +07003572/* MT (network-originated) USSD for unknown session */
3573friend function f_tc_proc_ss_for_unknown_session(charstring id, BSC_ConnHdlrPars pars)
3574runs on BSC_ConnHdlr {
3575 var OCT4 sid := '20000333'O;
3576
3577 f_init_handler(pars);
3578
3579 /* Perform location update */
3580 f_perform_lu();
3581
3582 f_ran_register_imsi(g_pars.imsi, 'FFFFFFFF'O);
3583 f_create_gsup_expect(hex2str(g_pars.imsi));
3584
3585 /* Request referencing a non-existing SS session */
3586 var template (value) GSUP_PDU gsup_req := ts_GSUP_PROC_SS_REQ(
3587 imsi := g_pars.imsi,
3588 sid := sid,
3589 state := OSMO_GSUP_SESSION_STATE_CONTINUE,
3590 ss := f_rnd_octstring(23)
3591 );
3592
3593 /* Error with some cause value */
3594 var template GSUP_PDU gsup_rsp := tr_GSUP_PROC_SS_ERR(
3595 imsi := g_pars.imsi,
3596 sid := sid,
3597 state := OSMO_GSUP_SESSION_STATE_END,
3598 cause := ? /* FIXME: introduce an enumerated type! */
3599 );
3600
3601 /* Initiate a MT USSD notification */
3602 GSUP.send(gsup_req);
3603
3604 /* Expect GSUP PROC_SS_ERROR message */
3605 f_expect_gsup_msg(gsup_rsp);
3606}
3607testcase TC_proc_ss_for_unknown_session() runs on MTC_CT {
3608 var BSC_ConnHdlr vc_conn;
3609 f_init();
3610 vc_conn := f_start_handler(refers(f_tc_proc_ss_for_unknown_session), 110);
3611 vc_conn.done;
3612}
3613
Vadim Yanitskiye5f4ed92019-06-16 02:36:33 +07003614/* MT (network-originated) USSD and no response to Paging Request */
3615friend function f_tc_proc_ss_paging_fail(charstring id, BSC_ConnHdlrPars pars)
3616runs on BSC_ConnHdlr {
3617 timer TP := 2.0; /* Paging timer */
3618
3619 f_init_handler(pars);
3620
3621 /* Perform location update */
3622 f_perform_lu();
3623
3624 f_ran_register_imsi(g_pars.imsi, 'FFFFFFFF'O);
3625 f_create_gsup_expect(hex2str(g_pars.imsi));
3626
3627 var template (value) GSUP_PDU gsup_req := ts_GSUP_PROC_SS_REQ(
3628 imsi := g_pars.imsi,
3629 sid := '20000444'O,
3630 state := OSMO_GSUP_SESSION_STATE_BEGIN,
3631 ss := f_rnd_octstring(23)
3632 );
3633
3634 /* Error with some cause value */
3635 var template GSUP_PDU gsup_rsp := tr_GSUP_PROC_SS_ERR(
3636 imsi := g_pars.imsi,
3637 sid := '20000444'O,
3638 state := OSMO_GSUP_SESSION_STATE_END,
3639 cause := ? /* FIXME: introduce an enumerated type! */
3640 );
3641
3642 /* Initiate a MT USSD notification */
3643 GSUP.send(gsup_req);
3644
3645 /* Send it to MSC and expect Paging Request */
3646 TP.start;
3647 alt {
3648 [pars.ran_is_geran] BSSAP.receive(tr_BSSMAP_Paging(g_pars.imsi)) {
3649 setverdict(pass);
3650 }
3651 [not pars.ran_is_geran] BSSAP.receive(tr_RANAP_Paging(cs_domain, imsi_hex2oct(g_pars.imsi))) {
3652 setverdict(pass);
3653 }
3654 /* We don't expect anything else */
3655 [] as_unexp_gsup_or_bssap_msg();
3656 [] TP.timeout {
3657 setverdict(fail, "Timeout waiting for Paging Request");
3658 }
3659 }
3660
3661 /* Expect GSUP PROC_SS_ERROR message */
3662 f_expect_gsup_msg(gsup_rsp, T_val := 10.0);
3663}
3664testcase TC_proc_ss_paging_fail() runs on MTC_CT {
3665 var BSC_ConnHdlr vc_conn;
3666 f_init();
3667 vc_conn := f_start_handler(refers(f_tc_proc_ss_paging_fail), 101);
3668 vc_conn.done;
3669}
3670
Vadim Yanitskiy29ba8d62019-06-16 15:19:41 +07003671/* MT (network-originated) USSD followed by immediate abort */
3672friend function f_tc_proc_ss_abort(charstring id, BSC_ConnHdlrPars pars)
3673runs on BSC_ConnHdlr {
3674 var octetstring facility := f_rnd_octstring(23);
3675 var OCT4 sid := '20000555'O;
3676 timer TP := 2.0;
3677
3678 f_init_handler(pars);
3679
3680 /* Perform location update */
3681 f_perform_lu();
3682
3683 f_ran_register_imsi(g_pars.imsi, 'FFFFFFFF'O);
3684 f_create_gsup_expect(hex2str(g_pars.imsi));
3685
3686 /* PROC_SS_REQ initiates a mobile-originated SS/USSD session */
3687 var template (value) GSUP_PDU gsup_req := ts_GSUP_PROC_SS_REQ(
3688 imsi := g_pars.imsi, sid := sid,
3689 state := OSMO_GSUP_SESSION_STATE_BEGIN,
3690 ss := facility
3691 );
3692
3693 /* On the MS side, we expect GSM 04.80 REGISTER message */
3694 var template PDU_ML3_NW_MS dtap_reg := tr_ML3_MT_SS_REGISTER(
3695 tid := 0, /* Most likely, it should be 0 */
3696 ti_flag := c_TIF_ORIG, /* Sent from the side that originates the TI */
3697 facility := facility
3698 );
3699
3700 /* PROC_SS_ERR with SESSION_STATE_END terminates the SS/USSD session */
3701 var template (value) GSUP_PDU gsup_abort := ts_GSUP_PROC_SS_ERR(
3702 imsi := g_pars.imsi, sid := sid,
3703 state := OSMO_GSUP_SESSION_STATE_END,
3704 cause := 0 /* FIXME: introduce an enumerated type! */
3705 );
3706
3707 /* On the MS side, we expect GSM 04.80 REGISTER message */
3708 var template PDU_ML3_NW_MS dtap_rel := tr_ML3_MT_SS_RELEASE_COMPLETE(
3709 tid := 0, /* Most likely, it should be 0 */
3710 ti_flag := c_TIF_ORIG, /* Sent from the side that originates the TI */
3711 cause := *, /* FIXME: expect some specific cause value */
3712 facility := omit
3713 );
3714
3715 /* Initiate a MT USSD with random payload */
3716 GSUP.send(gsup_req);
3717
3718 /* Expect Paging Request */
3719 TP.start;
3720 alt {
3721 [pars.ran_is_geran] BSSAP.receive(tr_BSSMAP_Paging(g_pars.imsi)) {
3722 setverdict(pass);
3723 }
3724 [not pars.ran_is_geran] BSSAP.receive(tr_RANAP_Paging(cs_domain, imsi_hex2oct(g_pars.imsi))) {
3725 setverdict(pass);
3726 }
3727 /* We don't expect anything else */
3728 [] as_unexp_gsup_or_bssap_msg();
3729 [] TP.timeout {
3730 setverdict(fail, "Timeout waiting for Paging Request");
3731 }
3732 }
3733
3734 /* Send Paging Response and establish connection */
3735 f_establish_fully(EST_TYPE_PAG_RESP);
3736 /* Expect MT REGISTER message with random facility */
3737 f_expect_mt_dtap_msg(dtap_reg);
3738
3739 /* HLR/EUSE decides to abort the session even
3740 * before getting any response from the MS */
3741 /* Initiate a MT USSD with random payload */
3742 GSUP.send(gsup_abort);
3743
3744 /* Expect RELEASE COMPLETE on ths MS side */
3745 f_expect_mt_dtap_msg(dtap_rel);
3746
3747 f_expect_clear();
3748}
3749testcase TC_proc_ss_abort() runs on MTC_CT {
3750 var BSC_ConnHdlr vc_conn;
3751 f_init();
3752 vc_conn := f_start_handler(refers(f_tc_proc_ss_abort), 102);
3753 vc_conn.done;
3754}
3755
Harald Weltee13cfb22019-04-23 16:52:02 +02003756
Stefan Sperling89eb1f32018-12-17 15:06:20 +01003757/* A5/1 only permitted on network side; attempt an invalid CIPHER MODE COMPLETE with A5/3 which MSC should reject. */
3758private function f_tc_cipher_complete_with_invalid_cipher(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
3759 pars.net.expect_auth := true;
3760 pars.net.expect_ciph := true;
3761 pars.net.kc_support := '02'O; /* A5/1 only */
3762 f_init_handler(pars);
3763
3764 g_pars.vec := f_gen_auth_vec_2g();
3765
3766 /* Can't use f_perform_lu() directly. Code below is based on it. */
3767
3768 /* tell GSUP dispatcher to send this IMSI to us */
3769 f_create_gsup_expect(hex2str(g_pars.imsi));
3770
3771 /* Send BSSAP_Conn_Req with COMPL L3 INFO to MSC */
3772 var PDU_ML3_MS_NW l3_lu := f_build_lu_imsi(g_pars.imsi)
Harald Weltedceacc72019-04-21 20:58:35 +02003773 f_cl3_or_initial_ue(l3_lu);
Stefan Sperling89eb1f32018-12-17 15:06:20 +01003774
3775 f_mm_auth();
3776
3777 var OCT1 a5_net := f_alg_mask_from_cm(g_pars.cm2);
3778 var OCT1 a5_intersect := g_pars.net.kc_support and4b a5_net;
3779 alt {
3780 [] BSSAP.receive(tr_BSSMAP_CipherModeCmd(a5_intersect, g_pars.vec.kc)) {
3781 BSSAP.send(ts_BSSMAP_CipherModeCompl(int2oct(4 /* "accept" A5/3 */, 1)));
3782 }
3783 [] BSSAP.receive(tr_BSSMAP_CipherModeCmd(?, g_pars.vec.kc)) {
3784 setverdict(fail, "Wrong ciphering algorithm mask in CiphModCmd");
3785 mtc.stop;
3786 }
3787 [] BSSAP.receive {
3788 setverdict(fail, "Unknown/unexpected BSSAP received");
3789 mtc.stop;
3790 }
3791 }
3792
3793 /* Expect LU reject from MSC. */
3794 alt {
3795 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Rej)) {
3796 setverdict(pass);
3797 }
3798 [] BSSAP.receive {
3799 setverdict(fail, "Unknown/unexpected BSSAP received");
3800 mtc.stop;
3801 }
3802 }
Stefan Sperlingc620b352018-12-18 17:23:36 +01003803 f_expect_clear();
Stefan Sperling89eb1f32018-12-17 15:06:20 +01003804}
3805
3806testcase TC_cipher_complete_with_invalid_cipher() runs on MTC_CT {
3807 var BSC_ConnHdlr vc_conn;
3808 f_init();
3809 f_vty_config(MSCVTY, "network", "encryption a5 1");
3810
3811 vc_conn := f_start_handler(refers(f_tc_cipher_complete_with_invalid_cipher), 52);
3812 vc_conn.done;
3813}
3814
Harald Welteb2284bd2019-05-10 11:30:43 +02003815/* Location Update with invalid (non-matching) MCC/MNC reported on BSSMAP level from BSC */
3816friend function f_tc_lu_with_invalid_mcc_mnc(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
3817 f_init_handler(pars);
3818
3819 /* tell GSUP dispatcher to send this IMSI to us */
3820 f_create_gsup_expect(hex2str(g_pars.imsi));
3821
3822 /* modify the cell ID which will be used to construct the COMPLELTE L3 or InitialUE */
3823 g_pars.cell_id := valueof(ts_CellId_CGI('333'H, '22'H, 23, 42));
3824
3825 /* Send BSSAP_Conn_Req with COMPL L3 INFO to MSC */
3826 var PDU_ML3_MS_NW l3_lu := f_build_lu_imsi(g_pars.imsi)
3827 f_cl3_or_initial_ue(l3_lu);
3828
3829 /* Expect LU reject from MSC. */
3830 alt {
3831 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Rej)) {
3832 setverdict(pass);
3833 }
3834 [] BSSAP.receive {
3835 setverdict(fail, "Unknown/unexpected BSSAP received");
3836 mtc.stop;
3837 }
3838 }
3839 f_expect_clear();
3840}
3841testcase TC_lu_with_invalid_mcc_mnc() runs on MTC_CT {
3842 var BSC_ConnHdlr vc_conn;
3843 f_init();
3844 vc_conn := f_start_handler(refers(f_tc_lu_with_invalid_mcc_mnc), 54);
3845 vc_conn.done;
3846}
3847
Stefan Sperlinga2d59c62018-12-18 16:32:44 +01003848private function f_tc_cipher_complete_without_alg(charstring id, BSC_ConnHdlrPars pars, octetstring kc_support) runs on BSC_ConnHdlr {
3849 pars.net.expect_auth := true;
3850 pars.net.expect_ciph := true;
3851 pars.net.kc_support := kc_support;
3852 f_init_handler(pars);
3853
3854 g_pars.vec := f_gen_auth_vec_2g();
3855
3856 /* Can't use f_perform_lu() directly. Code below is based on it. */
3857
3858 /* tell GSUP dispatcher to send this IMSI to us */
3859 f_create_gsup_expect(hex2str(g_pars.imsi));
3860
3861 /* Send BSSAP_Conn_Req with COMPL L3 INFO to MSC */
3862 var PDU_ML3_MS_NW l3_lu := f_build_lu_imsi(g_pars.imsi)
3863 f_cl3_or_initial_ue(l3_lu);
3864
3865 f_mm_auth();
3866
3867 var OCT1 a5_net := f_alg_mask_from_cm(g_pars.cm2);
3868 var OCT1 a5_intersect := g_pars.net.kc_support and4b a5_net;
3869 alt {
3870 [] BSSAP.receive(tr_BSSMAP_CipherModeCmd(a5_intersect, g_pars.vec.kc)) {
3871 BSSAP.send(ts_BSSMAP_CipherModeComplAlg(omit));
3872 }
3873 [] BSSAP.receive(tr_BSSMAP_ClassmarkReq) {
3874 BSSAP.send(ts_BSSMAP_ClassmarkUpd(g_pars.cm2, g_pars.cm3));
3875 repeat;
3876 }
3877 [] BSSAP.receive(tr_BSSMAP_CipherModeCmd(?, g_pars.vec.kc)) {
3878 setverdict(fail, "Wrong ciphering algorithm mask in CiphModCmd");
3879 mtc.stop;
3880 }
3881 [] BSSAP.receive {
3882 setverdict(fail, "Unknown/unexpected BSSAP received");
3883 mtc.stop;
3884 }
3885 }
3886
3887 /* TODO: Verify MSC is using the best cipher available! How? */
3888
3889 f_msc_lu_hlr();
3890 f_accept_reject_lu();
3891 f_expect_clear();
3892 setverdict(pass);
3893}
3894
3895/* A5/1 only permitted on network side; attempt CIPHER MODE COMPLETE without specifying the accepted algorithm. */
3896private function f_tc_cipher_complete_1_without_cipher(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
3897 f_tc_cipher_complete_without_alg(id, pars, '02'O /* A5/1 only */);
3898}
3899
3900/* A5/3 only permitted on network side; attempt CIPHER MODE COMPLETE without specifying the accepted algorithm. */
3901private function f_tc_cipher_complete_3_without_cipher(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
3902 f_tc_cipher_complete_without_alg(id, pars, '08'O /* A5/3 only */);
3903}
3904
3905/* A5/1 + A5/3 permitted on network side; attempt CIPHER MODE COMPLETE without specifying the accepted algorithm. */
3906private function f_tc_cipher_complete_13_without_cipher(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
3907 f_tc_cipher_complete_without_alg(id, pars, '0A'O /* A5/1 and A5/3 enabled */);
3908}
3909
3910testcase TC_cipher_complete_1_without_cipher() runs on MTC_CT {
3911 var BSC_ConnHdlr vc_conn;
3912 f_init();
3913 f_vty_config(MSCVTY, "network", "encryption a5 1");
3914
3915 vc_conn := f_start_handler(refers(f_tc_cipher_complete_1_without_cipher), 53);
3916 vc_conn.done;
3917}
3918
3919testcase TC_cipher_complete_3_without_cipher() runs on MTC_CT {
3920 var BSC_ConnHdlr vc_conn;
3921 f_init();
3922 f_vty_config(MSCVTY, "network", "encryption a5 3");
3923
3924 vc_conn := f_start_handler(refers(f_tc_cipher_complete_3_without_cipher), 54);
3925 vc_conn.done;
3926}
3927
3928testcase TC_cipher_complete_13_without_cipher() runs on MTC_CT {
3929 var BSC_ConnHdlr vc_conn;
3930 f_init();
3931 f_vty_config(MSCVTY, "network", "encryption a5 1 3");
3932
3933 vc_conn := f_start_handler(refers(f_tc_cipher_complete_13_without_cipher), 55);
3934 vc_conn.done;
3935}
Harald Welteb2284bd2019-05-10 11:30:43 +02003936
Harald Weltef640a012018-04-14 17:49:21 +02003937/* TODO (SMS):
3938 * different user data lengths
3939 * SMPP transaction mode with unsuccessful delivery
3940 * queued MT-SMS with no paging response + later delivery
3941 * different data coding schemes
3942 * multi-part SMS
3943 * user-data headers
3944 * TP-PID for SMS to SIM
3945 * behavior if SMS memory is full + RP-SMMA
3946 * delivery reports
3947 * SMPP osmocom extensions
3948 * more-messages-to-send
3949 * SMS during ongoing call (SACCH/SAPI3)
3950 */
3951
3952/* TODO (General):
Harald Welteba7b6d92018-01-23 21:32:34 +01003953 * continue to send repeated MO signalling messages to keep channel open: does MSC tmeout?
3954 * malformed messages (missing IE, invalid message type): properly rejected?
3955 * MT call while LU or is ongoing: Do we use existing lchan or page while lchan active?
3956 * 3G/2G auth permutations
3957 * encryption algorithms vs. classmark vs. vty config
Harald Welteba7b6d92018-01-23 21:32:34 +01003958 * send new transaction after/during clear (like SMS, ...)
Harald Welte45164da2018-01-24 12:51:27 +01003959 * too long L3 INFO in DTAP
3960 * too long / padded BSSAP
3961 * too long / short TLV values
Harald Welteba7b6d92018-01-23 21:32:34 +01003962 */
Harald Weltef6dd64d2017-11-19 12:09:51 +01003963
Harald Weltee13cfb22019-04-23 16:52:02 +02003964/***********************************************************************
3965 * SGsAP Testing
3966 ***********************************************************************/
3967
Philipp Maier948747b2019-04-02 15:22:33 +02003968/* Check if a subscriber exists in the VLR */
3969private function f_ctrl_subscr_in_vlr(charstring imsi_or_msisdn) runs on BSC_ConnHdlr return boolean {
3970
3971 var CtrlValue active_subsribers;
3972 var integer rc;
3973 active_subsribers := f_ctrl_get(IPA_CTRL, "subscriber-list-active-v1");
3974
3975 rc := f_strstr(active_subsribers, imsi_or_msisdn);
3976 if (rc < 0) {
3977 return false;
3978 }
3979
3980 return true;
3981}
3982
Harald Welte4263c522018-12-06 11:56:27 +01003983/* Perform a location updatye at the A-Interface and run some checks to confirm
3984 * that everything is back to normal. */
3985private function f_sgsap_bssmap_screening() runs on BSC_ConnHdlr {
3986 var SmsParameters spars := valueof(t_SmsPars);
3987
3988 /* Perform a location update, the SGs association is expected to fall
3989 * back to NULL */
3990 f_perform_lu();
3991 f_ctrl_get_exp(IPA_CTRL, "fsm.SGs-UE.id.imsi:" & hex2str(g_pars.imsi) & ".state", "SGs-NULL");
3992
3993 /* Trigger a paging request and expect the paging on BSSMAP, this is
3994 * to make sure that pagings are sent throught the A-Interface again
3995 * and not throught the SGs interface.*/
Harald Welte6811d102019-04-14 22:23:14 +02003996 f_ran_register_imsi(g_pars.imsi, g_pars.tmsi);
Harald Welte4263c522018-12-06 11:56:27 +01003997 f_vty_transceive(MSCVTY, "subscriber imsi " & hex2str(g_pars.imsi) & " paging");
3998
3999 alt {
Harald Weltee13cfb22019-04-23 16:52:02 +02004000 [g_pars.ran_is_geran] BSSAP.receive(tr_BSSMAP_Paging(g_pars.imsi)); {
4001 setverdict(pass);
4002 }
Harald Welte62113fc2019-05-09 13:04:02 +02004003 [not g_pars.ran_is_geran] BSSAP.receive(tr_RANAP_Paging(cs_domain, imsi_hex2oct(g_pars.imsi))) {
Harald Welte4263c522018-12-06 11:56:27 +01004004 setverdict(pass);
4005 }
4006 [] SGsAP.receive {
4007 setverdict(fail, "Received unexpected message on SGs");
4008 }
4009 }
4010
4011 /* Send an SMS to make sure that also payload messages are routed
4012 * throught the A-Interface again */
4013 f_establish_fully(EST_TYPE_MO_SMS);
4014 f_mo_sms(spars);
4015 f_expect_clear();
4016}
4017
4018private function f_tc_sgsap_reset(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
4019 var charstring vlr_name;
4020 f_init_handler(pars);
4021
4022 vlr_name := f_sgsap_reset_mme(mp_mme_name);
4023 log("VLR name: ", vlr_name);
4024 setverdict(pass);
Neels Hofmeyrc0b520d2019-03-06 15:35:50 +01004025 f_sleep(1.0);
Harald Welte4263c522018-12-06 11:56:27 +01004026}
4027
4028testcase TC_sgsap_reset() runs on MTC_CT {
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004029 var BSC_ConnHdlrPars pars;
Harald Welte4263c522018-12-06 11:56:27 +01004030 var BSC_ConnHdlr vc_conn;
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004031 f_init(1, true);
4032 pars := f_init_pars(11810, true);
4033 vc_conn := f_start_handler_with_pars(refers(f_tc_sgsap_reset), pars);
Harald Welte4263c522018-12-06 11:56:27 +01004034 vc_conn.done;
4035}
4036
4037/* like f_mm_auth() but for SGs */
4038function f_mm_auth_sgs() runs on BSC_ConnHdlr {
4039 if (g_pars.net.expect_auth) {
4040 g_pars.vec := f_gen_auth_vec_3g();
4041 var GSUP_IE auth_tuple := valueof(ts_GSUP_IE_AuthTuple2G3G(g_pars.vec.rand,
4042 g_pars.vec.sres,
4043 g_pars.vec.kc,
4044 g_pars.vec.ik,
4045 g_pars.vec.ck,
4046 g_pars.vec.autn,
4047 g_pars.vec.res));
4048 GSUP.receive(tr_GSUP_SAI_REQ(g_pars.imsi));
4049 GSUP.send(ts_GSUP_SAI_RES(g_pars.imsi, auth_tuple));
4050 SGsAP.receive(tr_ML3_MT_MM_AUTH_REQ_3G(g_pars.vec.rand, g_pars.vec.autn));
4051 SGsAP.send(ts_ML3_MT_MM_AUTH_RESP_3G(g_pars.vec.sres, g_pars.vec.res));
4052 }
4053}
4054
4055/* like f_perform_lu(), but on SGs rather than BSSAP */
4056function f_sgs_perform_lu() runs on BSC_ConnHdlr {
4057 var octetstring mme_name := f_enc_dns_hostname(mp_mme_name);
4058 var PDU_SGsAP lur;
4059 var PDU_SGsAP lua;
4060 var PDU_SGsAP mm_info;
4061 var octetstring mm_info_dtap;
4062
4063 /* tell GSUP dispatcher to send this IMSI to us */
4064 f_create_gsup_expect(hex2str(g_pars.imsi));
4065
4066 lur := valueof(ts_SGsAP_LU_REQ(g_pars.imsi, mme_name, IMSI_attach,
4067 ts_SGsAP_LAI('901'H, '70'H, 2342)));
4068 /* Old LAI, if MS sends it */
4069 /* TMSI status, if MS has no valid TMSI */
4070 /* IMEISV, if it supports "automatic device detection" */
4071 /* TAI, if available in MME */
4072 /* E-CGI, if available in MME */
4073 SGsAP.send(lur);
4074
4075 /* FIXME: is this really done over SGs? The Ue is already authenticated
4076 * via the MME ... */
4077 f_mm_auth_sgs();
4078
4079 /* Expect MSC to perform LU with HLR */
4080 GSUP.receive(tr_GSUP_UL_REQ(g_pars.imsi));
4081 GSUP.send(ts_GSUP_ISD_REQ(g_pars.imsi, g_pars.msisdn));
4082 GSUP.receive(tr_GSUP_ISD_RES(g_pars.imsi));
4083 GSUP.send(ts_GSUP_UL_RES(g_pars.imsi));
4084
4085 alt {
4086 [] SGsAP.receive(tr_SGsAP_LU_ACCEPT(g_pars.imsi, ?)) -> value lua {
4087 if (isvalue(lua.sGsAP_LOCATION_UPDATE_ACCEPT.newTMSIorIMSI.iD.iD.tmsi_ptmsi.octets)) {
4088 g_pars.tmsi :=lua.sGsAP_LOCATION_UPDATE_ACCEPT.newTMSIorIMSI.iD.iD.tmsi_ptmsi.octets
4089 SGsAP.send(ts_SGsAP_TMSI_REALL_CMPL(g_pars.imsi));
4090 }
4091 setverdict(pass);
4092 }
4093 [] SGsAP.receive(tr_SGsAP_LU_REJECT(g_pars.imsi, ?, ?)) {
4094 setverdict(fail, "Received LU-REJECT instead of ACCEPT");
4095 }
4096 [] SGsAP.receive {
4097 setverdict(fail, "Received unexpected message on SGs");
4098 }
4099 }
4100
4101 /* Check MM information */
4102 if (mp_mm_info == true) {
4103 SGsAP.receive(tr_SGsAP_MM_INFO_REQ(g_pars.imsi, ?)) -> value mm_info;
4104 mm_info_dtap := '0532'O & mm_info.sGsAP_MM_INFORMATION_REQUEST.mM_Information.information;
4105 if (not match(dec_PDU_ML3_NW_MS(mm_info_dtap), tr_ML3_MT_MM_Info)) {
4106 setverdict(fail, "Unexpected MM Information");
4107 }
4108 }
4109
4110 f_ctrl_get_exp(IPA_CTRL, "fsm.SGs-UE.id.imsi:" & hex2str(g_pars.imsi) & ".state", "SGs-ASSOCIATED");
4111}
4112
4113private function f_tc_sgsap_lu(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
4114 f_init_handler(pars);
4115 f_sgs_perform_lu();
4116 f_ctrl_get_exp(IPA_CTRL, "fsm.SGs-UE.id.imsi:" & hex2str(g_pars.imsi) & ".state", "SGs-ASSOCIATED");
4117
4118 f_sgsap_bssmap_screening();
4119
4120 setverdict(pass);
4121}
4122testcase TC_sgsap_lu() runs on MTC_CT {
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004123 var BSC_ConnHdlrPars pars;
Harald Welte4263c522018-12-06 11:56:27 +01004124 var BSC_ConnHdlr vc_conn;
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004125 f_init(1, true);
4126 pars := f_init_pars(11811, true);
4127 vc_conn := f_start_handler_with_pars(refers(f_tc_sgsap_lu), pars);
Harald Welte4263c522018-12-06 11:56:27 +01004128 vc_conn.done;
4129}
4130
4131/* Do LU by IMSI, refuse it on GSUP and expect LU REJ back to MS */
4132private function f_tc_sgsap_lu_imsi_reject(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
4133 f_init_handler(pars);
4134 var PDU_SGsAP lur;
4135
4136 f_create_gsup_expect(hex2str(g_pars.imsi));
4137 var octetstring mme_name := f_enc_dns_hostname(mp_mme_name);
4138 lur := valueof(ts_SGsAP_LU_REQ(g_pars.imsi, mme_name, IMSI_attach,
4139 ts_SGsAP_LAI('901'H, '70'H, 2342)));
4140 SGsAP.send(lur);
4141
4142 GSUP.receive(tr_GSUP_UL_REQ(g_pars.imsi));
4143 GSUP.send(ts_GSUP_UL_ERR(g_pars.imsi, 23));
4144 alt {
4145 [] SGsAP.receive(tr_SGsAP_LU_REJECT(g_pars.imsi, ?, ?)) {
4146 setverdict(pass);
4147 }
4148 [] SGsAP.receive(tr_SGsAP_LU_ACCEPT(g_pars.imsi, ?)) {
4149 setverdict(fail, "Expecting LU REJ, but got ACCEPT");
4150 mtc.stop;
4151 }
4152 [] SGsAP.receive {
4153 setverdict(fail, "Received unexpected message on SGs");
4154 }
4155 }
4156
4157 f_sgsap_bssmap_screening();
4158
4159 setverdict(pass);
4160}
4161testcase TC_sgsap_lu_imsi_reject() runs on MTC_CT {
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004162 var BSC_ConnHdlrPars pars;
Harald Welte4263c522018-12-06 11:56:27 +01004163 var BSC_ConnHdlr vc_conn;
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004164 f_init(1, true);
4165 pars := f_init_pars(11812, true);
Harald Welte4263c522018-12-06 11:56:27 +01004166
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004167 vc_conn := f_start_handler_with_pars(refers(f_tc_sgsap_lu_imsi_reject), pars);
Harald Welte4263c522018-12-06 11:56:27 +01004168 vc_conn.done;
4169}
4170
4171/* Do LU by IMSI, but then remain silent so that Ts6-1 times out */
4172private function f_tc_sgsap_lu_and_nothing(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
4173 var octetstring mme_name := f_enc_dns_hostname(mp_mme_name);
4174 var PDU_SGsAP lur;
4175
4176 f_init_handler(pars);
4177
4178 /* tell GSUP dispatcher to send this IMSI to us */
4179 f_create_gsup_expect(hex2str(g_pars.imsi));
4180
4181 lur := valueof(ts_SGsAP_LU_REQ(g_pars.imsi, mme_name, IMSI_attach,
4182 ts_SGsAP_LAI('901'H, '70'H, 2342)));
4183 /* Old LAI, if MS sends it */
4184 /* TMSI status, if MS has no valid TMSI */
4185 /* IMEISV, if it supports "automatic device detection" */
4186 /* TAI, if available in MME */
4187 /* E-CGI, if available in MME */
4188 SGsAP.send(lur);
4189
4190 /* FIXME: is this really done over SGs? The Ue is already authenticated
4191 * via the MME ... */
4192 f_mm_auth_sgs();
4193
4194 /* Expect MSC to perform LU with HLR */
4195 GSUP.receive(tr_GSUP_UL_REQ(g_pars.imsi));
4196 GSUP.send(ts_GSUP_ISD_REQ(g_pars.imsi, g_pars.msisdn));
4197 GSUP.receive(tr_GSUP_ISD_RES(g_pars.imsi));
4198 GSUP.send(ts_GSUP_UL_RES(g_pars.imsi));
4199
4200 alt {
4201 [] SGsAP.receive(tr_SGsAP_LU_ACCEPT(g_pars.imsi, ?)) {
4202 setverdict(pass);
4203 }
4204 [] SGsAP.receive(tr_SGsAP_LU_REJECT(g_pars.imsi, ?, ?)) {
4205 setverdict(fail, "Received LU-REJECT instead of ACCEPT");
4206 }
4207 [] SGsAP.receive {
4208 setverdict(fail, "Received unexpected message on SGs");
4209 }
4210 }
4211
4212 f_ctrl_get_exp(IPA_CTRL, "fsm.SGs-UE.id.imsi:" & hex2str(g_pars.imsi) & ".state", "SGs-ASSOCIATED");
4213
4214 /* Wait until the VLR has abort the TMSI reallocation procedure */
4215 f_sleep(45.0);
4216
4217 /* The outcome does not change the SGs state, see also 5.2.3.4 */
4218 f_ctrl_get_exp(IPA_CTRL, "fsm.SGs-UE.id.imsi:" & hex2str(g_pars.imsi) & ".state", "SGs-ASSOCIATED");
4219
4220 f_sgsap_bssmap_screening();
4221
4222 setverdict(pass);
4223}
4224testcase TC_sgsap_lu_and_nothing() runs on MTC_CT {
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004225 var BSC_ConnHdlrPars pars;
Harald Welte4263c522018-12-06 11:56:27 +01004226 var BSC_ConnHdlr vc_conn;
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004227 f_init(1, true);
4228 pars := f_init_pars(11813, true);
Harald Welte4263c522018-12-06 11:56:27 +01004229
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004230 vc_conn := f_start_handler_with_pars(refers(f_tc_sgsap_lu_and_nothing), pars);
Harald Welte4263c522018-12-06 11:56:27 +01004231 vc_conn.done;
4232}
4233
4234private function f_tc_sgsap_expl_imsi_det_eps(charstring id, BSC_ConnHdlrPars pars)
4235runs on BSC_ConnHdlr {
4236 f_init_handler(pars);
4237 f_sgs_perform_lu();
4238 f_sleep(3.0);
4239
4240 var octetstring mme_name := f_enc_dns_hostname(mp_mme_name);
4241 SGsAP.send(ts_SGsAP_EPS_DETACH_IND(g_pars.imsi, mme_name, UE_initiated));
4242 SGsAP.receive(tr_SGsAP_EPS_DETACH_ACK(g_pars.imsi));
4243 f_ctrl_get_exp(IPA_CTRL, "fsm.SGs-UE.id.imsi:" & hex2str(g_pars.imsi) & ".state", "SGs-NULL");
4244
4245 f_sgsap_bssmap_screening();
4246
4247 setverdict(pass);
4248}
4249testcase TC_sgsap_expl_imsi_det_eps() runs on MTC_CT {
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004250 var BSC_ConnHdlrPars pars;
Harald Welte4263c522018-12-06 11:56:27 +01004251 var BSC_ConnHdlr vc_conn;
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004252 f_init(1, true);
4253 pars := f_init_pars(11814, true);
4254 vc_conn := f_start_handler_with_pars(refers(f_tc_sgsap_expl_imsi_det_eps), pars);
Harald Welte4263c522018-12-06 11:56:27 +01004255 vc_conn.done;
4256}
4257
Philipp Maierfc19f172019-03-21 11:17:54 +01004258private function f_tc_sgsap_impl_imsi_det_eps(charstring id, BSC_ConnHdlrPars pars)
4259runs on BSC_ConnHdlr {
4260 f_init_handler(pars);
4261 f_sgs_perform_lu();
4262 f_sleep(3.0);
4263
4264 var octetstring mme_name := f_enc_dns_hostname(mp_mme_name);
4265 SGsAP.send(ts_SGsAP_EPS_DETACH_IND(g_pars.imsi, mme_name, network_initiated));
4266 SGsAP.receive(tr_SGsAP_EPS_DETACH_ACK(g_pars.imsi));
4267 f_ctrl_get_exp(IPA_CTRL, "fsm.SGs-UE.id.imsi:" & hex2str(g_pars.imsi) & ".state", "SGs-NULL");
4268
4269 f_sgsap_bssmap_screening();
4270
4271 setverdict(pass);
4272}
4273testcase TC_sgsap_impl_imsi_det_eps() runs on MTC_CT {
4274 var BSC_ConnHdlrPars pars;
4275 var BSC_ConnHdlr vc_conn;
4276 f_init(1, true);
4277 pars := f_init_pars(11814, true);
4278 vc_conn := f_start_handler_with_pars(refers(f_tc_sgsap_impl_imsi_det_eps), pars);
4279 vc_conn.done;
4280}
4281
Harald Welte4263c522018-12-06 11:56:27 +01004282private function f_tc_sgsap_expl_imsi_det_noneps(charstring id, BSC_ConnHdlrPars pars)
4283runs on BSC_ConnHdlr {
4284 f_init_handler(pars);
4285 f_sgs_perform_lu();
4286 f_sleep(3.0);
4287
4288 var octetstring mme_name := f_enc_dns_hostname(mp_mme_name);
4289 SGsAP.send(ts_SGsAP_IMSI_DETACH_IND(g_pars.imsi, mme_name, combined_UE_initiated));
4290 SGsAP.receive(tr_SGsAP_IMSI_DETACH_ACK(g_pars.imsi));
Philipp Maierd08e7e72019-04-02 15:27:10 +02004291
4292 if (f_ctrl_subscr_in_vlr(hex2str(g_pars.imsi))) {
4293 setverdict(fail, "subscriber not removed from VLR");
4294 }
Harald Welte4263c522018-12-06 11:56:27 +01004295
4296 f_sgsap_bssmap_screening();
4297
4298 setverdict(pass);
4299}
4300testcase TC_sgsap_expl_imsi_det_noneps() runs on MTC_CT {
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004301 var BSC_ConnHdlrPars pars;
Harald Welte4263c522018-12-06 11:56:27 +01004302 var BSC_ConnHdlr vc_conn;
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004303 f_init(1, true);
4304 pars := f_init_pars(11815, true);
4305 vc_conn := f_start_handler_with_pars(refers(f_tc_sgsap_expl_imsi_det_noneps), pars);
Harald Welte4263c522018-12-06 11:56:27 +01004306 vc_conn.done;
4307}
4308
Philipp Maier5d812702019-03-21 10:51:26 +01004309private function f_tc_sgsap_impl_imsi_det_noneps(charstring id, BSC_ConnHdlrPars pars)
4310runs on BSC_ConnHdlr {
4311 f_init_handler(pars);
4312 f_sgs_perform_lu();
4313 f_sleep(3.0);
4314
4315 var octetstring mme_name := f_enc_dns_hostname(mp_mme_name);
4316 SGsAP.send(ts_SGsAP_IMSI_DETACH_IND(g_pars.imsi, mme_name, implicit_network_initiated));
4317 SGsAP.receive(tr_SGsAP_IMSI_DETACH_ACK(g_pars.imsi));
4318
4319 if (f_ctrl_subscr_in_vlr(hex2str(g_pars.imsi))) {
4320 setverdict(fail, "subscriber not removed from VLR");
4321 }
4322
4323 f_sgsap_bssmap_screening();
4324
4325 setverdict(pass);
4326}
4327testcase TC_sgsap_impl_imsi_det_noneps() runs on MTC_CT {
4328 var BSC_ConnHdlrPars pars;
4329 var BSC_ConnHdlr vc_conn;
4330 f_init(1, true);
4331 pars := f_init_pars(11815, true);
4332 vc_conn := f_start_handler_with_pars(refers(f_tc_sgsap_impl_imsi_det_noneps), pars);
4333 vc_conn.done;
4334}
4335
Harald Welte4263c522018-12-06 11:56:27 +01004336/* Trigger a paging request via VTY and send a paging reject in response */
4337private function f_tc_sgsap_paging_rej(charstring id, BSC_ConnHdlrPars pars)
4338runs on BSC_ConnHdlr {
4339 f_init_handler(pars);
4340 f_sgs_perform_lu();
4341 f_sleep(1.0);
4342
4343 var octetstring vlr_name := f_enc_dns_hostname(mp_vlr_name);
4344 var template PDU_SGsAP exp_resp := tr_SGsAP_PAGING_REQ(g_pars.imsi, vlr_name, CS_call_indicator, omit);
4345 var template LocationAreaId exp_lai := ts_SGsAP_IE_Lai(valueof(ts_SGsAP_LAI('901'H, '70'H, 2342)));
4346 exp_resp.sGsAP_PAGING_REQUEST.locationAreaId := exp_lai;
4347
4348 /* Initiate paging via VTY */
4349 f_vty_transceive(MSCVTY, "subscriber imsi " & hex2str(g_pars.imsi) & " paging");
4350 alt {
4351 [] SGsAP.receive(exp_resp) {
4352 setverdict(pass);
4353 }
4354 [] SGsAP.receive {
4355 setverdict(fail, "Received unexpected message on SGs");
4356 }
4357 }
4358
4359 /* Now reject the paging */
4360 SGsAP.send(ts_SGsAP_PAGING_REJ(g_pars.imsi, IMSI_unknown));
4361
4362 /* Wait for the states inside the MSC to settle and check the state
4363 * of the SGs Association */
4364 f_sleep(1.0);
4365 f_ctrl_get_exp(IPA_CTRL, "fsm.SGs-UE.id.imsi:" & hex2str(g_pars.imsi) & ".state", "SGs-NULL");
4366
4367 /* FIXME: At the moment we send an IMSI_unknown as cause code, which is fine,
4368 * but we also need to cover tha case where the cause code indicates an
4369 * "IMSI detached for EPS services". In those cases the VLR is expected to
4370 * try paging on tha A/Iu interface. This will be another testcase similar to
4371 * this one, but extended with checks for the presence of the A/Iu paging
4372 * messages. */
4373
4374 f_sgsap_bssmap_screening();
4375
4376 setverdict(pass);
4377}
4378testcase TC_sgsap_paging_rej() runs on MTC_CT {
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004379 var BSC_ConnHdlrPars pars;
Harald Welte4263c522018-12-06 11:56:27 +01004380 var BSC_ConnHdlr vc_conn;
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004381 f_init(1, true);
4382 pars := f_init_pars(11816, true);
4383 vc_conn := f_start_handler_with_pars(refers(f_tc_sgsap_paging_rej), pars);
Harald Welte4263c522018-12-06 11:56:27 +01004384 vc_conn.done;
4385}
4386
4387/* Trigger a paging request via VTY and send a paging reject that indicates
4388 * that the subscriber intentionally rejected the call. */
4389private function f_tc_sgsap_paging_subscr_rej(charstring id, BSC_ConnHdlrPars pars)
4390runs on BSC_ConnHdlr {
4391 f_init_handler(pars);
4392 f_sgs_perform_lu();
4393 f_sleep(1.0);
4394
4395 var octetstring vlr_name := f_enc_dns_hostname(mp_vlr_name);
4396 var template PDU_SGsAP exp_resp := tr_SGsAP_PAGING_REQ(g_pars.imsi, vlr_name, CS_call_indicator, omit);
4397 var template LocationAreaId exp_lai := ts_SGsAP_IE_Lai(valueof(ts_SGsAP_LAI('901'H, '70'H, 2342)));
4398 exp_resp.sGsAP_PAGING_REQUEST.locationAreaId := exp_lai;
4399
4400 /* Initiate paging via VTY */
4401 f_vty_transceive(MSCVTY, "subscriber imsi " & hex2str(g_pars.imsi) & " paging");
4402 alt {
4403 [] SGsAP.receive(exp_resp) {
4404 setverdict(pass);
4405 }
4406 [] SGsAP.receive {
4407 setverdict(fail, "Received unexpected message on SGs");
4408 }
4409 }
4410
4411 /* Now reject the paging */
4412 SGsAP.send(ts_SGsAP_PAGING_REJ(g_pars.imsi, user_rejected_mobile_terminating_CS_fallback_call));
4413
4414 /* Wait for the states inside the MSC to settle and check the state
4415 * of the SGs Association */
4416 f_sleep(1.0);
4417 f_ctrl_get_exp(IPA_CTRL, "fsm.SGs-UE.id.imsi:" & hex2str(g_pars.imsi) & ".state", "SGs-ASSOCIATED");
4418
4419 /* FIXME: The VLR is supposed to trigger an User Determined User Busy (UDUB) as specified
4420 * in 3GPP TS 24.082, this is not yet implemented in the MSC or in this tests, we need
4421 * to check back how this works and how it can be tested */
4422
4423 f_sgsap_bssmap_screening();
4424
4425 setverdict(pass);
4426}
4427testcase TC_sgsap_paging_subscr_rej() runs on MTC_CT {
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004428 var BSC_ConnHdlrPars pars;
Harald Welte4263c522018-12-06 11:56:27 +01004429 var BSC_ConnHdlr vc_conn;
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004430 f_init(1, true);
4431 pars := f_init_pars(11817, true);
4432 vc_conn := f_start_handler_with_pars(refers(f_tc_sgsap_paging_subscr_rej), pars);
Harald Welte4263c522018-12-06 11:56:27 +01004433 vc_conn.done;
4434}
4435
4436/* Trigger a paging request via VTY and send an UE unreacable messge in response */
4437private function f_tc_sgsap_paging_ue_unr(charstring id, BSC_ConnHdlrPars pars)
4438runs on BSC_ConnHdlr {
4439 f_init_handler(pars);
4440 f_sgs_perform_lu();
4441 f_sleep(1.0);
4442
4443 var octetstring vlr_name := f_enc_dns_hostname(mp_vlr_name);
4444 var template PDU_SGsAP exp_resp := tr_SGsAP_PAGING_REQ(g_pars.imsi, vlr_name, CS_call_indicator, omit);
4445 var template LocationAreaId exp_lai := ts_SGsAP_IE_Lai(valueof(ts_SGsAP_LAI('901'H, '70'H, 2342)));
4446 exp_resp.sGsAP_PAGING_REQUEST.locationAreaId := exp_lai;
4447
4448 /* Initiate paging via VTY */
4449 f_vty_transceive(MSCVTY, "subscriber imsi " & hex2str(g_pars.imsi) & " paging");
4450 alt {
4451 [] SGsAP.receive(exp_resp) {
4452 setverdict(pass);
4453 }
4454 [] SGsAP.receive {
4455 setverdict(fail, "Received unexpected message on SGs");
4456 }
4457 }
4458
4459 /* Now pretend that the UE is unreachable */
4460 SGsAP.send(ts_SGsAP_UE_UNREACHABLE(g_pars.imsi, UE_unreachable));
4461
4462 /* Wait for the states inside the MSC to settle and check the state
4463 * of the SGs Association. */
4464 f_sleep(1.0);
4465 f_ctrl_get_exp(IPA_CTRL, "fsm.SGs-UE.id.imsi:" & hex2str(g_pars.imsi) & ".state", "SGs-ASSOCIATED");
4466
4467 f_sgsap_bssmap_screening();
4468
4469 setverdict(pass);
4470}
4471testcase TC_sgsap_paging_ue_unr() runs on MTC_CT {
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004472 var BSC_ConnHdlrPars pars;
Harald Welte4263c522018-12-06 11:56:27 +01004473 var BSC_ConnHdlr vc_conn;
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004474 f_init(1, true);
4475 pars := f_init_pars(11818, true);
4476 vc_conn := f_start_handler_with_pars(refers(f_tc_sgsap_paging_ue_unr), pars);
Harald Welte4263c522018-12-06 11:56:27 +01004477 vc_conn.done;
4478}
4479
4480/* Trigger a paging request via VTY but don't respond to it */
4481private function f_tc_sgsap_paging_and_nothing(charstring id, BSC_ConnHdlrPars pars)
4482runs on BSC_ConnHdlr {
4483 f_init_handler(pars);
4484 f_sgs_perform_lu();
4485 f_sleep(1.0);
4486
4487 var octetstring vlr_name := f_enc_dns_hostname(mp_vlr_name);
4488 var template PDU_SGsAP exp_resp := tr_SGsAP_PAGING_REQ(g_pars.imsi, vlr_name, CS_call_indicator, omit);
4489 var template LocationAreaId exp_lai := ts_SGsAP_IE_Lai(valueof(ts_SGsAP_LAI('901'H, '70'H, 2342)));
4490 exp_resp.sGsAP_PAGING_REQUEST.locationAreaId := exp_lai;
4491
4492 /* Initiate paging via VTY */
4493 f_vty_transceive(MSCVTY, "subscriber imsi " & hex2str(g_pars.imsi) & " paging");
4494 alt {
4495 [] SGsAP.receive(exp_resp) {
4496 setverdict(pass);
4497 }
4498 [] SGsAP.receive {
4499 setverdict(fail, "Received unexpected message on SGs");
4500 }
4501 }
4502
4503 /* Now do nothing, the MSC/VLR should fail silently to page after a
4504 * few seconds, The SGs association must remain unchanged. */
4505 f_sleep(15.0);
4506 f_ctrl_get_exp(IPA_CTRL, "fsm.SGs-UE.id.imsi:" & hex2str(g_pars.imsi) & ".state", "SGs-ASSOCIATED");
4507
4508 f_sgsap_bssmap_screening();
4509
4510 setverdict(pass);
4511}
4512testcase TC_sgsap_paging_and_nothing() runs on MTC_CT {
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004513 var BSC_ConnHdlrPars pars;
Harald Welte4263c522018-12-06 11:56:27 +01004514 var BSC_ConnHdlr vc_conn;
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004515 f_init(1, true);
4516 pars := f_init_pars(11819, true);
4517 vc_conn := f_start_handler_with_pars(refers(f_tc_sgsap_paging_and_nothing), pars);
Harald Welte4263c522018-12-06 11:56:27 +01004518 vc_conn.done;
4519}
4520
4521/* Trigger a paging request via VTY and slip in an LU */
4522private function f_tc_sgsap_paging_and_lu(charstring id, BSC_ConnHdlrPars pars)
4523runs on BSC_ConnHdlr {
4524 var octetstring vlr_name := f_enc_dns_hostname(mp_vlr_name);
4525 f_init_handler(pars);
4526
4527 /* First we prepar the situation, where the SGs association is in state
4528 * NULL and the confirmed by radio contact indicator is set to false
4529 * as well. This can be archived by performing an SGs LU and then
4530 * resetting the VLR */
4531 f_sgs_perform_lu();
4532 f_sgsap_reset_mme(mp_mme_name);
4533 f_sleep(1.0);
4534 f_ctrl_get_exp(IPA_CTRL, "fsm.SGs-UE.id.imsi:" & hex2str(g_pars.imsi) & ".state", "SGs-NULL");
4535
4536 /* Perform a paging, expect the paging messages on the SGs interface */
4537 f_vty_transceive(MSCVTY, "subscriber imsi " & hex2str(g_pars.imsi) & " paging");
4538 alt {
4539 [] SGsAP.receive(tr_SGsAP_PAGING_REQ(pars.imsi, vlr_name, CS_call_indicator, omit)) {
4540 setverdict(pass);
4541 }
4542 [] SGsAP.receive {
4543 setverdict(fail, "Received unexpected message on SGs");
4544 }
4545 }
4546
4547 /* Perform the LU as normal */
4548 f_sgs_perform_lu();
4549 f_ctrl_get_exp(IPA_CTRL, "fsm.SGs-UE.id.imsi:" & hex2str(g_pars.imsi) & ".state", "SGs-ASSOCIATED");
4550
4551 /* Expect a new paging request right after the LU */
4552 alt {
4553 [] SGsAP.receive(tr_SGsAP_PAGING_REQ(pars.imsi, vlr_name, CS_call_indicator, omit)) {
4554 setverdict(pass);
4555 }
4556 [] SGsAP.receive {
4557 setverdict(fail, "Received unexpected message on SGs");
4558 }
4559 }
4560
4561 /* Test is done now, lets round everything up by rejecting the paging
4562 * cleanly. */
4563 SGsAP.send(ts_SGsAP_PAGING_REJ(g_pars.imsi, user_rejected_mobile_terminating_CS_fallback_call));
4564 f_ctrl_get_exp(IPA_CTRL, "fsm.SGs-UE.id.imsi:" & hex2str(g_pars.imsi) & ".state", "SGs-ASSOCIATED");
4565
4566 f_sgsap_bssmap_screening();
4567
4568 setverdict(pass);
4569}
4570testcase TC_sgsap_paging_and_lu() runs on MTC_CT {
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004571 var BSC_ConnHdlrPars pars;
Harald Welte4263c522018-12-06 11:56:27 +01004572 var BSC_ConnHdlr vc_conn;
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004573 f_init(1, true);
4574 pars := f_init_pars(11820, true);
4575 vc_conn := f_start_handler_with_pars(refers(f_tc_sgsap_paging_and_lu), pars);
Harald Welte4263c522018-12-06 11:56:27 +01004576 vc_conn.done;
4577}
4578
4579/* Send unexpected unit-data through the SGs interface */
4580private function f_tc_sgsap_unexp_ud(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
4581 f_init_handler(pars);
4582 f_sleep(1.0);
4583
4584 /* This simulates what happens when a subscriber without SGs
4585 * association gets unitdata via the SGs interface. */
4586
4587 /* Make sure the subscriber exists and the SGs association
4588 * is in NULL state */
4589 f_perform_lu();
4590 f_ctrl_get_exp(IPA_CTRL, "fsm.SGs-UE.id.imsi:" & hex2str(g_pars.imsi) & ".state", "SGs-NULL");
4591
4592 /* Send some random unit data, the MSC/VLR should send a release
4593 * immediately. */
4594 SGsAP.send(ts_SGsAP_UL_UD(pars.imsi,'1234'O));
4595 SGsAP.receive(tr_SGsAP_RELEASE_REQ(pars.imsi, IMSI_detached_for_EPS_nonEPS_services));
4596
4597 f_sgsap_bssmap_screening();
4598
4599 setverdict(pass);
4600}
4601testcase TC_sgsap_unexp_ud() runs on MTC_CT {
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004602 var BSC_ConnHdlrPars pars;
Harald Welte4263c522018-12-06 11:56:27 +01004603 var BSC_ConnHdlr vc_conn;
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004604 f_init(1, true);
4605 pars := f_init_pars(11821, true);
4606 vc_conn := f_start_handler_with_pars(refers(f_tc_sgsap_unexp_ud), pars);
Harald Welte4263c522018-12-06 11:56:27 +01004607 vc_conn.done;
4608}
4609
4610/* Send unsolicited unit-data through the SGs interface */
4611private function f_tc_sgsap_unsol_ud(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
4612 f_init_handler(pars);
4613 f_sleep(1.0);
4614
4615 /* This simulates what happens when the MME attempts to send unitdata
4616 * to a subscriber that is completely unknown to the VLR */
4617
4618 /* Send some random unit data, the MSC/VLR should send a release
4619 * immediately. */
4620 SGsAP.send(ts_SGsAP_UL_UD(pars.imsi,'1234'O));
4621 SGsAP.receive(tr_SGsAP_RELEASE_REQ(pars.imsi, IMSI_unknown));
4622
4623 f_sgsap_bssmap_screening();
4624
4625 setverdict(pass);
4626}
4627testcase TC_sgsap_unsol_ud() runs on MTC_CT {
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004628 var BSC_ConnHdlrPars pars;
Harald Welte4263c522018-12-06 11:56:27 +01004629 var BSC_ConnHdlr vc_conn;
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004630 f_init(1, true);
4631 pars := f_init_pars(11822, true);
4632 vc_conn := f_start_handler_with_pars(refers(f_tc_sgsap_unsol_ud), pars);
Harald Welte4263c522018-12-06 11:56:27 +01004633 vc_conn.done;
4634}
4635
4636private altstep as_other_sms_sgs() runs on BSC_ConnHdlr {
4637 /* FIXME: Match an actual payload (second questionmark), the type is
4638 * octetstring, how do we use a tr_PDU_DTAP_MT here? */
4639 [] SGsAP.receive(tr_SGsAP_DL_UD(?,?)) {
4640 setverdict(fail, "Unexpected SMS related PDU from MSC");
4641 mtc.stop;
4642 }
4643}
4644
4645/* receive a MT-SMS delivered from the MSC/SMSC over an already existing SGsAP connection */
4646function f_mt_sms_sgs(inout SmsParameters spars)
4647runs on BSC_ConnHdlr {
4648 var template (value) TPDU_RP_DATA_MS_SGSN tp_mo;
4649 var template (value) RPDU_MS_SGSN rp_mo;
4650 var template (value) PDU_ML3_MS_NW l3_mo;
4651
4652 var template TPDU_RP_DATA_SGSN_MS tp_mt;
4653 var template RPDU_SGSN_MS rp_mt;
4654 var template PDU_ML3_NW_MS l3_mt;
4655
4656 var PDU_ML3_NW_MS sgsap_l3_mt;
4657
4658 var default d := activate(as_other_sms_sgs());
4659
4660 /* Expect CP-DATA(RP-DATA(SMS-DELIVER)) */
4661 tp_mt := tr_SMS_DELIVER(?, spars.tp.ud, spars.tp.pid, spars.tp.dcs, ?);
4662 rp_mt := tr_RP_DATA_MT(?, ?, omit, tp_mt);
4663 l3_mt := tr_ML3_MT_SMS(?, c_TIF_ORIG, tr_CP_DATA_MT(rp_mt));
4664
4665 SGsAP.receive(l3_mt) -> value sgsap_l3_mt;
4666
4667 /* Extract relevant identifiers */
4668 spars.tid := bit2int(sgsap_l3_mt.tiOrSkip.transactionId.tio);
4669 spars.rp.msg_ref := sgsap_l3_mt.msgs.sms.cP_DATA.cP_User_Data.cP_RPDU.rP_DATA_SGSN_MS.rP_MessageReference;
4670
4671 /* send CP-ACK for CP-DATA just received */
4672 l3_mo := ts_ML3_MO_SMS(spars.tid, c_TIF_REPL, ts_CP_ACK_MO);
4673
4674 SGsAP.send(l3_mo);
4675
4676 /* send RP-ACK for RP-DATA */
4677 rp_mo := ts_RP_ACK_MO(spars.rp.msg_ref);
4678 l3_mo := ts_ML3_MO_SMS(spars.tid, c_TIF_REPL, ts_CP_DATA_MO(rp_mo));
4679
4680 SGsAP.send(l3_mo);
4681
4682 /* expect CP-ACK for CP-DATA(RP-ACK) just sent */
4683 l3_mt := tr_ML3_MT_SMS(spars.tid, c_TIF_ORIG, tr_CP_ACK_MT);
4684
4685 SGsAP.receive(l3_mt);
4686
4687 deactivate(d);
4688
4689 setverdict(pass);
4690}
4691
4692/* submit a MO-SMS to MSC/SMSC over an already existing SGsAP connection */
4693function f_mo_sms_sgs(inout SmsParameters spars)
4694runs on BSC_ConnHdlr {
4695 var template (value) TPDU_RP_DATA_MS_SGSN tp_mo;
4696 var template (value) RPDU_MS_SGSN rp_mo;
4697 var template (value) PDU_ML3_MS_NW l3_mo;
4698
4699 var template TPDU_RP_DATA_SGSN_MS tp_mt;
4700 var template RPDU_SGSN_MS rp_mt;
4701 var template PDU_ML3_NW_MS l3_mt;
4702
4703 var default d := activate(as_other_sms_sgs());
4704
4705 /* just in case this is routed to SMPP.. */
4706 f_create_smpp_expect(hex2str(spars.tp.da.tP_DA_NoPad.tP_DAValue));
4707
4708 tp_mo := ts_SMS_SUBMIT(spars.tp.msg_ref, spars.tp.da, spars.tp.pid, spars.tp.dcs,
4709 spars.tp.udl, spars.tp.ud);
4710 rp_mo := ts_RP_DATA_MO(spars.rp.msg_ref, spars.rp.orig, spars.rp.dest, tp_mo);
4711 l3_mo := ts_ML3_MO_SMS(spars.tid, c_TIF_ORIG, ts_CP_DATA_MO(rp_mo));
4712
4713 SGsAP.send(l3_mo);
4714
4715 /* receive CP-ACK for CP-DATA above */
4716 SGsAP.receive(tr_ML3_MT_SMS(spars.tid, c_TIF_REPL, tr_CP_ACK_MT));
4717
4718 if (ispresent(spars.exp_rp_err)) {
4719 /* expect an RP-ERROR message from MSC with given cause */
4720 rp_mt := tr_RP_ERROR_MT(spars.rp.msg_ref, spars.exp_rp_err);
4721 l3_mt := tr_ML3_MT_SMS(spars.tid, c_TIF_REPL, tr_CP_DATA_MT(rp_mt));
4722 SGsAP.receive(l3_mt);
4723 /* send CP-ACK for CP-DATA just received */
4724 l3_mo := ts_ML3_MO_SMS(spars.tid, c_TIF_ORIG, ts_CP_ACK_MO);
4725 SGsAP.send(l3_mo);
4726 } else {
4727 /* expect RP-ACK for RP-DATA */
4728 rp_mt := tr_RP_ACK_MT(spars.rp.msg_ref);
4729 l3_mt := tr_ML3_MT_SMS(spars.tid, c_TIF_REPL, tr_CP_DATA_MT(rp_mt));
4730 SGsAP.receive(l3_mt);
4731 /* send CP-ACO for CP-DATA just received */
4732 l3_mo := ts_ML3_MO_SMS(spars.tid, c_TIF_ORIG, ts_CP_ACK_MO);
4733 SGsAP.send(l3_mo);
4734 }
4735
4736 deactivate(d);
4737
4738 setverdict(pass);
4739}
4740
4741private function f_vty_sms_send_conn_hdlr(charstring imsi, charstring msisdn, charstring text)
4742runs on BSC_ConnHdlr {
4743 f_vty_transceive(MSCVTY, "subscriber imsi "&imsi&" sms sender msisdn "&msisdn&" send "&text);
4744}
4745
4746/* Send a MT SMS via SGs interface */
4747private function f_tc_sgsap_mt_sms(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
4748 f_init_handler(pars);
4749 f_sgs_perform_lu();
4750 f_sleep(1.0);
4751 var SmsParameters spars := valueof(t_SmsPars);
4752 spars.tp.ud := 'C8329BFD064D9B53'O;
4753
4754 /* Trigger SMS via VTY */
4755 f_vty_sms_send_conn_hdlr(hex2str(pars.imsi), "2342", "Hello SMS");
4756 var octetstring vlr_name := f_enc_dns_hostname(mp_vlr_name);
4757
4758 /* Expect a paging request and respond accordingly with a service request */
4759 SGsAP.receive(tr_SGsAP_PAGING_REQ(pars.imsi, vlr_name, SMS_indicator, omit));
4760 SGsAP.send(ts_SGsAP_SERVICE_REQ(pars.imsi, SMS_indicator, EMM_CONNECTED));
4761
4762 /* Connection is now live, receive the MT-SMS */
4763 f_mt_sms_sgs(spars);
4764
4765 /* Expect a concluding release from the MSC */
4766 SGsAP.receive(tr_SGsAP_RELEASE_REQ(pars.imsi, omit));
4767
4768 /* Make sure that subscriber is still present and the SGs association is in tact (ref-counting) */
4769 f_ctrl_get_exp(IPA_CTRL, "fsm.SGs-UE.id.imsi:" & hex2str(g_pars.imsi) & ".state", "SGs-ASSOCIATED");
4770
4771 f_sgsap_bssmap_screening();
4772
4773 setverdict(pass);
4774}
4775testcase TC_sgsap_mt_sms() runs on MTC_CT {
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004776 var BSC_ConnHdlrPars pars;
Harald Welte4263c522018-12-06 11:56:27 +01004777 var BSC_ConnHdlr vc_conn;
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004778 f_init(1, true);
4779 pars := f_init_pars(11823, true);
4780 vc_conn := f_start_handler_with_pars(refers(f_tc_sgsap_mt_sms), pars);
Harald Welte4263c522018-12-06 11:56:27 +01004781 vc_conn.done;
4782}
4783
4784/* Send a MO SMS via SGs interface */
4785private function f_tc_sgsap_mo_sms(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
4786 f_init_handler(pars);
4787 f_sgs_perform_lu();
4788 f_sleep(1.0);
4789 var SmsParameters spars := valueof(t_SmsPars);
4790 spars.tp.ud := 'C8329BFD064D9B53'O;
4791
4792 /* Send the MO-SMS */
4793 f_mo_sms_sgs(spars);
4794
4795 /* Expect a concluding release from the MSC/VLR */
4796 SGsAP.receive(tr_SGsAP_RELEASE_REQ(pars.imsi, omit));
4797
4798 /* Make sure that subscriber is still present and the SGs association is in tact (ref-counting) */
4799 f_ctrl_get_exp(IPA_CTRL, "fsm.SGs-UE.id.imsi:" & hex2str(g_pars.imsi) & ".state", "SGs-ASSOCIATED");
4800
4801 setverdict(pass);
4802
4803 f_sgsap_bssmap_screening()
4804}
4805testcase TC_sgsap_mo_sms() runs on MTC_CT {
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004806 var BSC_ConnHdlrPars pars;
Harald Welte4263c522018-12-06 11:56:27 +01004807 var BSC_ConnHdlr vc_conn;
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004808 f_init(1, true);
4809 pars := f_init_pars(11824, true);
4810 vc_conn := f_start_handler_with_pars(refers(f_tc_sgsap_mo_sms), pars);
Harald Welte4263c522018-12-06 11:56:27 +01004811 vc_conn.done;
4812}
4813
4814/* Trigger sending of an MT sms via VTY but never respond to anything */
4815private function f_tc_sgsap_mt_sms_and_nothing(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
4816 f_init_handler(pars, 170.0);
4817 f_sgs_perform_lu();
4818 f_sleep(1.0);
4819
4820 var SmsParameters spars := valueof(t_SmsPars);
4821 spars.tp.ud := 'C8329BFD064D9B53'O;
4822 var integer page_count := 0;
4823 var octetstring vlr_name := f_enc_dns_hostname(mp_vlr_name);
4824 var template PDU_SGsAP exp_pag_req := tr_SGsAP_PAGING_REQ(g_pars.imsi, vlr_name, SMS_indicator, omit);
4825 var template LocationAreaId exp_lai := ts_SGsAP_IE_Lai(valueof(ts_SGsAP_LAI('901'H, '70'H, 2342)));
4826 exp_pag_req.sGsAP_PAGING_REQUEST.locationAreaId := exp_lai;
4827
4828 /* Trigger SMS via VTY */
4829 f_vty_sms_send_conn_hdlr(hex2str(pars.imsi), "2342", "Hello SMS");
4830
Neels Hofmeyr16237742019-03-06 15:34:01 +01004831 /* Expect the MSC/VLR to page exactly once */
4832 SGsAP.receive(exp_pag_req);
Harald Welte4263c522018-12-06 11:56:27 +01004833
4834 /* Wait some time to make sure the MSC is not delivering any further
4835 * paging messages or anything else that could be unexpected. */
4836 timer T := 20.0;
4837 T.start
4838 alt {
4839 [] SGsAP.receive(exp_pag_req)
4840 {
4841 setverdict(fail, "paging seems not to stop!");
4842 mtc.stop;
4843 }
4844 [] SGsAP.receive {
4845 setverdict(fail, "unexpected SGsAP message received");
4846 self.stop;
4847 }
4848 [] T.timeout {
4849 setverdict(pass);
4850 }
4851 }
4852
4853 /* Even on a failed paging the SGs Association should stay intact */
4854 f_ctrl_get_exp(IPA_CTRL, "fsm.SGs-UE.id.imsi:" & hex2str(g_pars.imsi) & ".state", "SGs-ASSOCIATED");
4855
4856 /* Note: We do not execute f_sgsap_bssmap_screening() here since the
4857 * MSC/VLR would re-try to deliver the test SMS trigered above and
4858 * so the screening would fail. */
4859
Neels Hofmeyr8256ed22019-03-06 15:34:01 +01004860 f_vty_sms_clear(hex2str(g_pars.imsi));
4861
Harald Welte4263c522018-12-06 11:56:27 +01004862 f_vty_transceive(MSCVTY, "subscriber imsi " & hex2str(g_pars.imsi) & " expire");
4863
4864 setverdict(pass);
Neels Hofmeyrb0f82342019-03-06 15:36:51 +01004865
4866 f_sgsap_bssmap_screening();
Harald Welte4263c522018-12-06 11:56:27 +01004867}
4868testcase TC_sgsap_mt_sms_and_nothing() runs on MTC_CT {
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004869 var BSC_ConnHdlrPars pars;
Harald Welte4263c522018-12-06 11:56:27 +01004870 var BSC_ConnHdlr vc_conn;
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004871 f_init(1, true);
4872 pars := f_init_pars(11825, true);
4873 vc_conn := f_start_handler_with_pars(refers(f_tc_sgsap_mt_sms_and_nothing), pars);
Harald Welte4263c522018-12-06 11:56:27 +01004874 vc_conn.done;
4875}
4876
4877/* Trigger sending of an MT sms via VTY but reject the paging immediately */
4878private function f_tc_sgsap_mt_sms_and_reject(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
4879 f_init_handler(pars, 150.0);
4880 f_sgs_perform_lu();
4881 f_sleep(1.0);
4882
4883 var SmsParameters spars := valueof(t_SmsPars);
4884 spars.tp.ud := 'C8329BFD064D9B53'O;
4885 var integer page_count := 0;
4886 var octetstring vlr_name := f_enc_dns_hostname(mp_vlr_name);
4887 var template PDU_SGsAP exp_pag_req := tr_SGsAP_PAGING_REQ(g_pars.imsi, vlr_name, SMS_indicator, omit);
4888 var template LocationAreaId exp_lai := ts_SGsAP_IE_Lai(valueof(ts_SGsAP_LAI('901'H, '70'H, 2342)));
4889 exp_pag_req.sGsAP_PAGING_REQUEST.locationAreaId := exp_lai;
4890
4891 /* Trigger SMS via VTY */
4892 f_vty_sms_send_conn_hdlr(hex2str(pars.imsi), "2342", "Hello SMS");
4893
4894 /* Expect a paging request and reject it immediately */
4895 SGsAP.receive(exp_pag_req);
4896 SGsAP.send(ts_SGsAP_PAGING_REJ(g_pars.imsi, IMSI_unknown));
4897
4898 /* The MSC/VLR should no longer try to page once the paging has been
4899 * rejected. Wait some time and check if there are no unexpected
4900 * messages on the SGs interface. */
4901 timer T := 20.0;
4902 T.start
4903 alt {
4904 [] SGsAP.receive(exp_pag_req)
4905 {
4906 setverdict(fail, "paging seems not to stop!");
4907 mtc.stop;
4908 }
4909 [] SGsAP.receive {
4910 setverdict(fail, "unexpected SGsAP message received");
4911 self.stop;
4912 }
4913 [] T.timeout {
4914 setverdict(pass);
4915 }
4916 }
4917
Neels Hofmeyr8256ed22019-03-06 15:34:01 +01004918 f_vty_sms_clear(hex2str(g_pars.imsi));
4919
Harald Welte4263c522018-12-06 11:56:27 +01004920 /* A rejected paging with IMSI_unknown (see above) should always send
4921 * the SGs association to NULL. */
4922 f_ctrl_get_exp(IPA_CTRL, "fsm.SGs-UE.id.imsi:" & hex2str(g_pars.imsi) & ".state", "SGs-NULL");
4923
4924 f_sgsap_bssmap_screening();
4925
Harald Welte4263c522018-12-06 11:56:27 +01004926 setverdict(pass);
4927}
4928testcase TC_sgsap_mt_sms_and_reject() runs on MTC_CT {
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004929 var BSC_ConnHdlrPars pars;
Harald Welte4263c522018-12-06 11:56:27 +01004930 var BSC_ConnHdlr vc_conn;
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004931 f_init(1, true);
4932 pars := f_init_pars(11826, true);
4933 vc_conn := f_start_handler_with_pars(refers(f_tc_sgsap_mt_sms_and_reject), pars);
Harald Welte4263c522018-12-06 11:56:27 +01004934 vc_conn.done;
4935}
4936
4937/* Perform an MT CSDB call including LU */
4938private function f_mt_lu_and_csfb_call(charstring id, BSC_ConnHdlrPars pars, boolean bssmap_lu) runs on BSC_ConnHdlr {
4939 f_init_handler(pars);
4940
4941 /* Be sure that the BSSMAP reset is done before we begin. */
4942 f_sleep(2.0);
4943
4944 /* Testcase variation: See what happens when we do a regular BSSMAP
4945 * LU first (this should not hurt in any way!) */
4946 if (bssmap_lu) {
4947 f_perform_lu();
4948 }
4949
4950 f_sgs_perform_lu();
4951 f_sleep(1.0);
4952
4953 var octetstring vlr_name := f_enc_dns_hostname(mp_vlr_name);
4954 var CallParameters cpars := valueof(t_CallParams('12345'H, 0));
4955 cpars.bss_rtp_port := 1110;
4956 cpars.mgcp_connection_id_bss := '10004'H;
4957 cpars.mgcp_connection_id_mss := '10005'H;
4958
4959 /* Note: This is an optional parameter. When the call-agent (MSC) does
4960 * supply a full endpoint name this setting will be overwritten. */
4961 cpars.mgcp_ep := "rtpbridge/1@mgw";
4962
4963 /* Initiate a call via MNCC interface */
4964 f_mt_call_initate(cpars);
4965
4966 /* Expect a paging request and respond accordingly with a service request */
4967 SGsAP.receive(tr_SGsAP_PAGING_REQ(pars.imsi, vlr_name, CS_call_indicator, omit));
4968 SGsAP.send(ts_SGsAP_SERVICE_REQ(pars.imsi, CS_call_indicator, EMM_CONNECTED));
4969
4970 /* Complete the call, hold it for some time and then tear it down */
4971 f_mt_call_complete(cpars);
4972 f_sleep(3.0);
Harald Welte4c422b72019-02-17 16:27:10 +01004973 f_call_hangup(cpars, true, is_csfb := true);
Harald Welte4263c522018-12-06 11:56:27 +01004974
4975 /* Make sure that subscriber is still present and the SGs association is in tact (ref-counting) */
4976 f_ctrl_get_exp(IPA_CTRL, "fsm.SGs-UE.id.imsi:" & hex2str(g_pars.imsi) & ".state", "SGs-ASSOCIATED");
4977
4978 /* Finally simulate the return of the UE to the 4G network */
4979 SGsAP.send(ts_SGsAP_MO_CSFB_IND(pars.imsi));
4980
4981 /* Test for successful return by triggering a paging, when the paging
4982 * request is received via SGs, we can be sure that the MSC/VLR has
4983 * recognized that the UE is now back on 4G */
4984 f_sleep(1.0);
4985 f_vty_transceive(MSCVTY, "subscriber imsi " & hex2str(g_pars.imsi) & " paging");
4986 alt {
4987 [] SGsAP.receive(tr_SGsAP_PAGING_REQ(pars.imsi, vlr_name, CS_call_indicator, omit)) {
4988 setverdict(pass);
4989 }
4990 [] SGsAP.receive {
4991 setverdict(fail, "Received unexpected message on SGs");
4992 }
4993 }
4994
4995 f_sgsap_bssmap_screening();
4996
4997 setverdict(pass);
4998}
4999
5000/* Perform a regular BSSAP LU first, do a SGSAP LU and then make a CSFB call */
5001private function f_tc_bssap_lu_sgsap_lu_and_mt_call(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
5002 f_mt_lu_and_csfb_call(id, pars, true);
5003}
5004testcase TC_bssap_lu_sgsap_lu_and_mt_call() runs on MTC_CT {
Philipp Maier8e07a4a2019-02-14 18:23:28 +01005005 var BSC_ConnHdlrPars pars;
Harald Welte4263c522018-12-06 11:56:27 +01005006 var BSC_ConnHdlr vc_conn;
Philipp Maier8e07a4a2019-02-14 18:23:28 +01005007 f_init(1, true);
5008 pars := f_init_pars(118139, true);
Harald Welte4263c522018-12-06 11:56:27 +01005009
Philipp Maier8e07a4a2019-02-14 18:23:28 +01005010 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 +01005011 vc_conn.done;
5012}
5013
5014
5015/* Perform a SGSAP LU and then make a CSFB call */
5016private function f_tc_sgsap_lu_and_mt_call(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
5017 f_mt_lu_and_csfb_call(id, pars, false);
5018}
5019testcase TC_sgsap_lu_and_mt_call() runs on MTC_CT {
Philipp Maier8e07a4a2019-02-14 18:23:28 +01005020 var BSC_ConnHdlrPars pars;
Harald Welte4263c522018-12-06 11:56:27 +01005021 var BSC_ConnHdlr vc_conn;
Philipp Maier8e07a4a2019-02-14 18:23:28 +01005022 f_init(1, true);
5023 pars := f_init_pars(11827, true);
Harald Welte4263c522018-12-06 11:56:27 +01005024
Philipp Maier8e07a4a2019-02-14 18:23:28 +01005025 vc_conn := f_start_handler_with_pars(refers(f_tc_sgsap_lu_and_mt_call), pars);
Harald Welte4263c522018-12-06 11:56:27 +01005026 vc_conn.done;
5027}
5028
Philipp Maier628c0052019-04-09 17:36:57 +02005029/* Simulate an HLR/VLR failure */
5030private function f_tc_sgsap_vlr_failure(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
5031 var octetstring mme_name := f_enc_dns_hostname(mp_mme_name);
5032 var octetstring vlr_name := f_enc_dns_hostname(mp_vlr_name);
5033
5034 var PDU_SGsAP lur;
5035
5036 f_init_handler(pars);
5037
5038 /* Attempt location update (which is expected to fail) */
5039 lur := valueof(ts_SGsAP_LU_REQ(g_pars.imsi, mme_name, IMSI_attach,
5040 ts_SGsAP_LAI('901'H, '70'H, 2342)));
5041 SGsAP.send(lur);
5042
5043 /* Respond to SGsAP-RESET-INDICATION from VLR */
5044 alt {
5045 [] SGsAP.receive(tr_SGsAP_RESET_IND_VLR(vlr_name)); {
5046 SGsAP.send(valueof(ts_SGsAP_RESET_ACK_MME(mme_name)));
5047 setverdict(pass);
5048 }
5049 [] SGsAP.receive {
5050 setverdict(fail, "Received unexpected message on SGs");
5051 }
5052 }
5053
5054 f_sleep(1.0);
5055 setverdict(pass);
5056}
5057testcase TC_sgsap_vlr_failure() runs on MTC_CT {
5058 var BSC_ConnHdlrPars pars;
5059 var BSC_ConnHdlr vc_conn;
5060 f_init(1, true, false);
5061 pars := f_init_pars(11811, true, false);
5062 vc_conn := f_start_handler_with_pars(refers(f_tc_sgsap_vlr_failure), pars);
5063 vc_conn.done;
5064}
5065
Harald Welte4263c522018-12-06 11:56:27 +01005066/* SGs TODO:
5067 * LU attempt for IMSI without NAM_PS in HLR
5068 * LU attempt with AUTH FAIL due to invalid RES/SRES
5069 * LU attempt with no response from HLR (VLR should timeout + LU REJ)
5070 * LU attempt with new TMSI but without TMSI REALL CMPL baco to VLR
5071 * implicit IMSI detach from EPS
5072 * implicit IMSI detach from non-EPS
5073 * MM INFO
5074 *
5075 */
Harald Weltef6dd64d2017-11-19 12:09:51 +01005076
Neels Hofmeyr0ac63152019-05-07 01:20:17 +02005077private function f_tc_ho_inter_bsc_unknown_cell(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
5078 f_init_handler(pars);
5079 var CallParameters cpars := valueof(t_CallParams('12345'H, 0));
5080 cpars.bss_rtp_port := 1110;
5081 cpars.mgcp_connection_id_bss := '22222'H;
5082 cpars.mgcp_connection_id_mss := '33333'H;
5083 cpars.mgcp_ep := "rtpbridge/1@mgw";
5084 cpars.mo_call := true;
5085
5086 f_perform_lu();
5087 f_mo_call_establish(cpars);
5088
5089 f_sleep(1.0);
5090
5091 var myBSSMAP_Cause cause_val := GSM0808_CAUSE_BETTER_CELL;
5092 var BssmapCause cause := enum2int(cause_val);
5093
5094 var template BSSMAP_FIELD_CellIdentificationList cil;
5095 cil := { cIl_LAI := { ts_BSSMAP_CI_LAI('023'H, '42'H, 999) } };
5096
5097 BSSAP.send(ts_BSSMAP_HandoverRequired(cause, cil));
5098 BSSAP.receive(tr_BSSMAP_HandoverRequiredReject);
5099
5100 f_call_hangup(cpars, true);
5101}
5102testcase TC_ho_inter_bsc_unknown_cell() runs on MTC_CT {
5103 var BSC_ConnHdlr vc_conn;
5104 f_init();
5105
5106 vc_conn := f_start_handler(refers(f_tc_ho_inter_bsc_unknown_cell), 53);
5107 vc_conn.done;
5108}
5109
5110private altstep as_mgcp_ack_all_mdcx(CallParameters cpars) runs on BSC_ConnHdlr {
5111 var MgcpCommand mgcp_cmd;
5112 [] MGCP.receive(tr_MDCX) -> value mgcp_cmd {
5113 var SDP_Message sdp := valueof(ts_SDP(cpars.mgw_rtp_ip_mss, cpars.mgw_rtp_ip_mss,
5114 hex2str(cpars.mgcp_call_id), "42",
5115 cpars.mgw_rtp_port_mss,
5116 { int2str(cpars.rtp_payload_type) },
5117 { valueof(ts_SDP_rtpmap(cpars.rtp_payload_type,
5118 cpars.rtp_sdp_format)),
5119 valueof(ts_SDP_ptime(20)) }));
5120 MGCP.send(ts_MDCX_ACK(mgcp_cmd.line.trans_id, cpars.mgcp_connection_id_mss, sdp));
5121 repeat;
5122 }
5123}
5124
5125private function f_tc_ho_inter_bsc0(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
5126 var CallParameters cpars := valueof(t_CallParams('12345'H, 0));
5127 cpars.bss_rtp_port := 1110;
5128 cpars.mgcp_connection_id_bss := '22222'H;
5129 cpars.mgcp_connection_id_mss := '33333'H;
5130 cpars.mgcp_ep := "rtpbridge/1@mgw";
5131 cpars.mo_call := true;
5132
5133 f_init_handler(pars);
5134
5135 f_vty_transceive(MSCVTY, "configure terminal");
5136 f_vty_transceive(MSCVTY, "msc");
5137 f_vty_transceive(MSCVTY, "neighbor a cgi 262 42 23 42 ran-pc 0.24.1");
5138 f_vty_transceive(MSCVTY, "neighbor a lac 5 ran-pc 0.24.2");
5139 f_vty_transceive(MSCVTY, "exit");
5140 f_vty_transceive(MSCVTY, "exit");
5141
5142 f_perform_lu();
5143 f_mo_call_establish(cpars);
5144
5145 f_sleep(1.0);
5146
5147 var default ack_mdcx := activate(as_mgcp_ack_all_mdcx(cpars));
5148
5149 var myBSSMAP_Cause cause_val := GSM0808_CAUSE_BETTER_CELL;
5150 var BssmapCause cause := enum2int(cause_val);
5151
5152 var template BSSMAP_FIELD_CellIdentificationList cil;
5153 cil := { cIl_LAI := { ts_BSSMAP_CI_LAI('023'H, '42'H, 5) } };
5154
5155 /* old BSS sends Handover Required */
5156 BSSAP.send(ts_BSSMAP_HandoverRequired(cause, cil));
5157
5158 /* Now the action goes on in f_tc_ho_inter_bsc1() */
5159
5160 /* MSC forwards the RR Handover Command to old BSS */
5161 var PDU_BSSAP ho_command;
5162 BSSAP.receive(tr_BSSMAP_HandoverCommand) -> value ho_command;
5163
5164 log("GOT HandoverCommand", ho_command);
5165
5166 BSSAP.receive(tr_BSSMAP_HandoverSucceeded);
5167
5168 /* f_tc_ho_inter_bsc1() completes Handover, then expecting a Clear here. */
5169 f_expect_clear();
5170
5171 log("FIRST inter-BSC Handover done");
5172
5173
5174 /* ------------------------ */
5175
5176 /* Ok, that went well, now the other BSC is handovering back here --
5177 * from now on this here is the new BSS. */
5178 f_create_bssmap_exp_handoverRequest(193);
5179
5180 var PDU_BSSAP ho_request;
5181 BSSAP.receive(tr_BSSMAP_HandoverRequest) -> value ho_request;
5182
5183 /* new BSS composes a RR Handover Command */
5184 var PDU_ML3_NW_MS rr_ho_cmd := valueof(ts_RR_HandoverCommand);
5185 var octetstring rr_ho_cmd_enc := enc_PDU_ML3_NW_MS(rr_ho_cmd);
5186 var BSSMAP_IE_AoIP_TransportLayerAddress tla := valueof(ts_BSSMAP_IE_AoIP_TLA4('01020304'O, 2342));
5187 BSSAP.send(ts_BSSMAP_HandoverRequestAcknowledge(rr_ho_cmd_enc, lengthof(rr_ho_cmd_enc),
5188 tla, ts_BSSMAP_IE_SpeechCodec({ts_CodecFR})));
5189
5190 /* Now f_tc_ho_inter_bsc1() expects HandoverCommand */
5191
5192 f_sleep(0.5);
5193
5194 /* Notify that the MS is now over here */
5195
5196 BSSAP.send(ts_BSSMAP_HandoverDetect);
5197 f_sleep(0.1);
5198 BSSAP.send(ts_BSSMAP_HandoverComplete);
5199
5200 f_sleep(3.0);
5201
5202 deactivate(ack_mdcx);
5203
5204 var default ccrel := activate(as_optional_cc_rel(cpars, true));
5205
5206 /* blatant cheating */
5207 var N_Sd_Array last_n_sd := f_bssmap_last_n_sd();
5208 last_n_sd[0] := 3;
5209 f_bssmap_continue_after_n_sd(last_n_sd);
5210
5211 f_call_hangup(cpars, true);
5212 f_sleep(1.0);
5213 deactivate(ccrel);
5214
5215 setverdict(pass);
5216}
5217private function f_tc_ho_inter_bsc1(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
5218 f_init_handler(pars);
5219 f_create_bssmap_exp_handoverRequest(194);
5220
5221 var PDU_BSSAP ho_request;
5222 BSSAP.receive(tr_BSSMAP_HandoverRequest) -> value ho_request;
5223
5224 /* new BSS composes a RR Handover Command */
5225 var PDU_ML3_NW_MS rr_ho_cmd := valueof(ts_RR_HandoverCommand);
5226 var octetstring rr_ho_cmd_enc := enc_PDU_ML3_NW_MS(rr_ho_cmd);
5227 var BSSMAP_IE_AoIP_TransportLayerAddress tla := valueof(ts_BSSMAP_IE_AoIP_TLA4('01020304'O, 2342));
5228 BSSAP.send(ts_BSSMAP_HandoverRequestAcknowledge(rr_ho_cmd_enc, lengthof(rr_ho_cmd_enc),
5229 tla, ts_BSSMAP_IE_SpeechCodec({ts_CodecFR})));
5230
5231 /* Now f_tc_ho_inter_bsc0() expects HandoverCommand */
5232
5233 f_sleep(0.5);
5234
5235 /* Notify that the MS is now over here */
5236
5237 BSSAP.send(ts_BSSMAP_HandoverDetect);
5238 f_sleep(0.1);
5239 BSSAP.send(ts_BSSMAP_HandoverComplete);
5240
5241 f_sleep(3.0);
5242
5243 /* Now I'd like to f_call_hangup() but we don't know any cpars here. So
5244 * ... handover back to the first BSC :P */
5245
5246 var myBSSMAP_Cause cause_val := GSM0808_CAUSE_BETTER_CELL;
5247 var BssmapCause cause := enum2int(cause_val);
5248
5249 var template BSSMAP_FIELD_CellIdentificationList cil;
5250 cil := { cIl_LAI := { ts_BSSMAP_CI_LAI('262'H, '42'H, 23) } };
5251
5252 /* old BSS sends Handover Required */
5253 BSSAP.send(ts_BSSMAP_HandoverRequired(cause, cil));
5254
5255 /* Now the action goes on in f_tc_ho_inter_bsc0() */
5256
5257 /* MSC forwards the RR Handover Command to old BSS */
5258 var PDU_BSSAP ho_command;
5259 BSSAP.receive(tr_BSSMAP_HandoverCommand) -> value ho_command;
5260
5261 log("GOT HandoverCommand", ho_command);
5262
5263 BSSAP.receive(tr_BSSMAP_HandoverSucceeded);
5264
5265 /* f_tc_ho_inter_bsc1() completes Handover, then expecting a Clear here. */
5266 f_expect_clear();
5267 setverdict(pass);
5268}
5269testcase TC_ho_inter_bsc() runs on MTC_CT {
5270 var BSC_ConnHdlr vc_conn0;
5271 var BSC_ConnHdlr vc_conn1;
5272 f_init(2);
5273
5274 var BSC_ConnHdlrPars pars0 := f_init_pars(53);
5275 var BSC_ConnHdlrPars pars1 := f_init_pars(53);
5276
5277 vc_conn0 := f_start_handler_with_pars(refers(f_tc_ho_inter_bsc0), pars0, 0);
5278 vc_conn1 := f_start_handler_with_pars(refers(f_tc_ho_inter_bsc1), pars1, 1);
5279 vc_conn0.done;
5280 vc_conn1.done;
5281}
5282
5283function f_ML3_patch_seq_nr_MS_NW(in uint2_t seq_nr, inout octetstring enc_l3) {
5284 log("MS_NW patching N(SD)=", seq_nr, " into dtap ", enc_l3);
5285 enc_l3[2] := (enc_l3[2] and4b '3f'O) or4b bit2oct(int2bit(seq_nr, 8) << 6);
5286 log("MS_NW patched enc_l3: ", enc_l3);
5287}
5288
5289private function f_tc_ho_inter_msc_out(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
5290 var CallParameters cpars := valueof(t_CallParams('12345'H, 0));
5291 cpars.bss_rtp_port := 1110;
5292 cpars.mgcp_connection_id_bss := '22222'H;
5293 cpars.mgcp_connection_id_mss := '33333'H;
5294 cpars.mgcp_ep := "rtpbridge/1@mgw";
5295 cpars.mo_call := true;
5296 var hexstring ho_number := f_gen_msisdn(99999);
5297
5298 f_init_handler(pars);
5299
5300 f_create_mncc_expect(hex2str(ho_number));
5301
5302 f_vty_transceive(MSCVTY, "configure terminal");
5303 f_vty_transceive(MSCVTY, "msc");
5304 f_vty_transceive(MSCVTY, "neighbor a cgi 017 017 1 1 msc-ipa-name msc-017-017-1");
5305 f_vty_transceive(MSCVTY, "exit");
5306 f_vty_transceive(MSCVTY, "exit");
5307
5308 f_perform_lu();
5309 f_mo_call_establish(cpars);
5310
5311 f_sleep(1.0);
5312
5313 var default ack_mdcx := activate(as_mgcp_ack_all_mdcx(cpars));
5314
5315 var myBSSMAP_Cause cause_val := GSM0808_CAUSE_BETTER_CELL;
5316 var BssmapCause cause := enum2int(cause_val);
5317
5318 var template BSSMAP_FIELD_CellIdentificationList cil;
5319 cil := { cIl_LAI := { ts_BSSMAP_CI_LAI('017'H, '017'H, 1) } };
5320
5321 /* old BSS sends Handover Required */
5322 BSSAP.send(ts_BSSMAP_HandoverRequired(cause, cil));
5323
5324 /* The target cell 017-017 LAC 1 is configured to be a remote MSC of name "msc-017-017-1".
5325 * This MSC tries to reach the other MSC via GSUP. */
5326
5327 var octetstring remote_msc_name := '6D73632D3031372D3031372D3100'O; /* "msc-017-017-1\0" as octetstring */
5328 var GSUP_PDU prep_ho_req;
5329 GSUP.receive(tr_GSUP_E_AN_APDU(OSMO_GSUP_MSGT_E_PREPARE_HANDOVER_REQUEST,
5330 pars.imsi, destination_name := remote_msc_name)) -> value prep_ho_req;
5331
5332 var GSUP_IeValue source_name_ie;
5333 f_gsup_find_ie(prep_ho_req, OSMO_GSUP_SOURCE_NAME_IE, source_name_ie);
5334 var octetstring local_msc_name := source_name_ie.source_name;
5335
5336 /* Remote MSC has figured out its BSC and signals success */
5337 var PDU_ML3_NW_MS rr_ho_cmd := valueof(ts_RR_HandoverCommand);
5338 var octetstring rr_ho_cmd_enc := enc_PDU_ML3_NW_MS(rr_ho_cmd);
5339 var PDU_BSSAP ho_req_ack := valueof(ts_BSSMAP_HandoverRequestAcknowledge(rr_ho_cmd_enc, lengthof(rr_ho_cmd_enc),
5340 aoIPTransportLayer := omit,
5341 speechCodec := ts_BSSMAP_IE_SpeechCodec({ts_CodecFR})));
5342 GSUP.send(ts_GSUP_E_PrepareHandoverResult(
5343 pars.imsi,
5344 ho_number,
5345 remote_msc_name, local_msc_name,
5346 valueof(t_GSUP_AN_APDU(OSMO_GSUP_AN_PROTO_48006, enc_PDU_BSSAP(ho_req_ack)))));
5347
5348 /* MSC forwards the RR Handover Command to old BSS */
5349 BSSAP.receive(tr_BSSMAP_HandoverCommand);
5350
5351 /* The MS shows up at remote new BSS */
5352
5353 GSUP.send(ts_GSUP_E_AN_APDU(OSMO_GSUP_MSGT_E_PROCESS_ACCESS_SIGNALLING_REQUEST,
5354 pars.imsi, remote_msc_name, local_msc_name,
5355 valueof(t_GSUP_AN_APDU(OSMO_GSUP_AN_PROTO_48006,
5356 enc_PDU_BSSAP(valueof(ts_BSSMAP_HandoverDetect))))));
5357 BSSAP.receive(tr_BSSMAP_HandoverSucceeded);
5358 f_sleep(0.1);
5359
5360 /* Save the MS sequence counters for use on the other connection */
5361 var N_Sd_Array last_n_sd := f_bssmap_last_n_sd();
5362
5363 GSUP.send(ts_GSUP_E_AN_APDU(OSMO_GSUP_MSGT_E_SEND_END_SIGNAL_REQUEST,
5364 pars.imsi, remote_msc_name, local_msc_name,
5365 valueof(t_GSUP_AN_APDU(OSMO_GSUP_AN_PROTO_48006,
5366 enc_PDU_BSSAP(valueof(ts_BSSMAP_HandoverComplete))))));
5367
5368 /* The local BSS conn clears, all communication goes via remote MSC now */
5369 f_expect_clear();
5370
5371 /**********************************/
5372 /* Play through some signalling across the inter-MSC link.
5373 * This is a copy of f_tc_lu_and_mo_ussd_single_request() translated into GSUP AN-APDUs. */
5374
5375 if (false) {
5376 var template OCTN facility_req := f_USSD_FACILITY_IE_INVOKE(
5377 invoke_id := 5, /* Phone may not start from 0 or 1 */
5378 op_code := SS_OP_CODE_PROCESS_USS_REQ,
5379 ussd_string := "*#100#"
5380 );
5381
5382 var template OCTN facility_rsp := f_USSD_FACILITY_IE_RETURN_RESULT(
5383 invoke_id := 5, /* InvokeID shall be the same for both REQ and RSP */
5384 op_code := SS_OP_CODE_PROCESS_USS_REQ,
5385 ussd_string := "Your extension is " & hex2str(g_pars.msisdn) & "\r"
5386 )
5387
5388 /* Compose a new SS/REGISTER message with request */
5389 var template (value) PDU_ML3_MS_NW ussd_req := ts_ML3_MO_SS_REGISTER(
5390 tid := 1, /* We just need a single transaction */
5391 ti_flag := c_TIF_ORIG, /* Sent from the side that originates the TI */
5392 facility := valueof(facility_req)
5393 );
5394 var PDU_ML3_MS_NW ussd_req_v := valueof(ussd_req);
5395
5396 /* Compose SS/RELEASE_COMPLETE template with expected response */
5397 var template PDU_ML3_NW_MS ussd_rsp := tr_ML3_MT_SS_RELEASE_COMPLETE(
5398 tid := 1, /* Response should arrive within the same transaction */
5399 ti_flag := c_TIF_REPL, /* Sent to the side that originates the TI */
5400 facility := valueof(facility_rsp)
5401 );
5402
5403 /* Compose expected MSC -> HLR message */
5404 var template GSUP_PDU gsup_req := tr_GSUP_PROC_SS_REQ(
5405 imsi := g_pars.imsi,
5406 state := OSMO_GSUP_SESSION_STATE_BEGIN,
5407 ss := valueof(facility_req)
5408 );
5409
5410 /* To be used for sending response with correct session ID */
5411 var GSUP_PDU gsup_req_complete;
5412
5413 /* Request own number */
5414 /* From remote MSC instead of BSSAP directly */
5415 /* Patch the correct N_SD value into the message. */
5416 var octetstring l3_enc := enc_PDU_ML3_MS_NW(ussd_req_v);
5417 var RAN_Emulation.ConnectionData cd;
5418 f_ML3_patch_seq_nr_MS_NW(f_next_n_sd(last_n_sd, f_ML3_n_sd_idx(ussd_req_v)), l3_enc);
5419 GSUP.send(ts_GSUP_E_AN_APDU(OSMO_GSUP_MSGT_E_PROCESS_ACCESS_SIGNALLING_REQUEST,
5420 pars.imsi, remote_msc_name, local_msc_name,
5421 valueof(t_GSUP_AN_APDU(OSMO_GSUP_AN_PROTO_48006,
5422 enc_PDU_BSSAP(valueof(ts_BSSAP_DTAP(l3_enc)))
5423 ))
5424 ));
5425
5426 /* Expect GSUP message containing the SS payload */
5427 gsup_req_complete := f_expect_gsup_msg(gsup_req);
5428
5429 /* Compose the response from HLR using received session ID */
5430 var template GSUP_PDU gsup_rsp := ts_GSUP_PROC_SS_REQ(
5431 imsi := g_pars.imsi,
5432 sid := gsup_req_complete.ies[1].val.session_id,
5433 state := OSMO_GSUP_SESSION_STATE_END,
5434 ss := valueof(facility_rsp)
5435 );
5436
5437 /* Finally, HLR terminates the session */
5438 GSUP.send(gsup_rsp);
5439
5440 /* The USSD response goes out to remote MSC, on GSUP E instead of BSSAP */
5441 var GSUP_PDU gsup_ussd_rsp;
5442 GSUP.receive(tr_GSUP_E_AN_APDU(OSMO_GSUP_MSGT_E_FORWARD_ACCESS_SIGNALLING_REQUEST,
5443 pars.imsi, destination_name := remote_msc_name)) -> value gsup_ussd_rsp;
5444
5445 var GSUP_IeValue an_apdu;
5446 if (not f_gsup_find_ie(gsup_ussd_rsp, OSMO_GSUP_AN_APDU_IE, an_apdu)) {
5447 setverdict(fail, "No AN-APDU in received GSUP message. Expected USSD response in DTAP, got", gsup_ussd_rsp);
5448 mtc.stop;
5449 }
5450 var PDU_BSSAP bssap_dtap_mt := dec_PDU_BSSAP(an_apdu.an_apdu.pdu);
5451 var PDU_ML3_NW_MS dtap_mt := dec_PDU_ML3_NW_MS(bssap_dtap_mt.pdu.dtap);
5452 log("Expecting", ussd_rsp);
5453 log("Got", dtap_mt);
5454 if (not match(dtap_mt, ussd_rsp)) {
5455 setverdict(fail, "Unexpected GSUP message. Expected USSD response in DTAP, got", gsup_ussd_rsp);
5456 mtc.stop;
5457 }
5458 }
5459 /**********************************/
5460
5461
5462 /* inter-MSC handover back to the first MSC */
5463 f_create_bssmap_exp_handoverRequest(193);
5464 cil := { cIl_CGI := { ts_BSSMAP_CI_CGI('262'H, '42'H, 23, 42) } };
5465
5466 /* old BSS sends Handover Required, via inter-MSC E link: like
5467 * BSSAP.send(ts_BSSMAP_HandoverRequired(cause, cil));
5468 * but via GSUP */
5469 GSUP.send(ts_GSUP_E_AN_APDU(OSMO_GSUP_MSGT_E_PREPARE_SUBSEQUENT_HANDOVER_REQUEST,
5470 pars.imsi, remote_msc_name, local_msc_name,
5471 valueof(t_GSUP_AN_APDU(OSMO_GSUP_AN_PROTO_48006,
5472 enc_PDU_BSSAP(valueof(ts_BSSMAP_HandoverRequired(cause, cil)))
5473 ))
5474 ));
5475
5476 /* MSC asks local BSS to prepare Handover to it */
5477 BSSAP.receive(tr_BSSMAP_HandoverRequest);
5478
5479 /* Make sure the new BSSAP conn continues with the correct N_SD sequence numbers */
5480 f_bssmap_continue_after_n_sd(last_n_sd);
5481
5482 /* new BSS composes a RR Handover Command */
5483 rr_ho_cmd := valueof(ts_RR_HandoverCommand);
5484 rr_ho_cmd_enc := enc_PDU_ML3_NW_MS(rr_ho_cmd);
5485 var BSSMAP_IE_AoIP_TransportLayerAddress tla := valueof(ts_BSSMAP_IE_AoIP_TLA4('01020304'O, 2342));
5486 BSSAP.send(ts_BSSMAP_HandoverRequestAcknowledge(rr_ho_cmd_enc, lengthof(rr_ho_cmd_enc),
5487 tla, ts_BSSMAP_IE_SpeechCodec({ts_CodecFR})));
5488
5489 /* HandoverCommand goes out via remote MSC-I */
5490 var GSUP_PDU prep_subsq_ho_res;
5491 GSUP.receive(tr_GSUP_E_AN_APDU(OSMO_GSUP_MSGT_E_PREPARE_SUBSEQUENT_HANDOVER_RESULT,
5492 pars.imsi, destination_name := remote_msc_name)) -> value prep_subsq_ho_res;
5493
5494 /* MS shows up at the local BSS */
5495 BSSAP.send(ts_BSSMAP_HandoverDetect);
5496 f_sleep(0.1);
5497 BSSAP.send(ts_BSSMAP_HandoverComplete);
5498
5499 /* Handover Succeeded message */
5500 GSUP.receive(tr_GSUP_E_AN_APDU(OSMO_GSUP_MSGT_E_FORWARD_ACCESS_SIGNALLING_REQUEST,
5501 pars.imsi, destination_name := remote_msc_name));
5502
5503 /* MS has handovered to here, Clear Command goes out via remote MSC-I -- in form of a GSUP Close. */
5504 GSUP.receive(tr_GSUP_E_NO_PDU(OSMO_GSUP_MSGT_E_CLOSE,
5505 pars.imsi, destination_name := remote_msc_name));
5506
5507 /* Handover ends successfully. Call goes on for a little longer and then we hang up. */
5508
5509 f_sleep(1.0);
5510 deactivate(ack_mdcx);
5511
5512 /* FIXME: the inter-MSC call has put a number of MNCC messages in the queue, which above code should expect and
5513 * clear out. The f_call_hangup() expects an MNCC_REL_IND, so, for the time being, just clear the MNCC messages
5514 * before starting the call hangup. Instead of this, the individual messages should be tested for above. */
5515 MNCC.clear;
5516
5517 var default ccrel := activate(as_optional_cc_rel(cpars, true));
5518 f_call_hangup(cpars, true);
5519 f_sleep(1.0);
5520 deactivate(ccrel);
5521
5522 setverdict(pass);
5523}
5524testcase TC_ho_inter_msc_out() runs on MTC_CT {
5525 var BSC_ConnHdlr vc_conn;
5526 f_init(1);
5527
5528 var BSC_ConnHdlrPars pars := f_init_pars(54);
5529
5530 vc_conn := f_start_handler_with_pars(refers(f_tc_ho_inter_msc_out), pars, 0);
5531 vc_conn.done;
5532}
5533
5534
Harald Weltef6dd64d2017-11-19 12:09:51 +01005535control {
Philipp Maier328d1662018-03-07 10:40:27 +01005536 execute( TC_cr_before_reset() );
Harald Weltea49e36e2018-01-21 19:29:33 +01005537 execute( TC_lu_imsi_noauth_tmsi() );
Harald Welted2328a22018-01-27 14:27:16 +01005538 execute( TC_lu_imsi_noauth_notmsi() );
Harald Weltea49e36e2018-01-21 19:29:33 +01005539 execute( TC_lu_imsi_reject() );
5540 execute( TC_lu_imsi_timeout_gsup() );
Harald Welted2328a22018-01-27 14:27:16 +01005541 execute( TC_lu_imsi_auth_tmsi() );
Harald Welte8a397ae2019-04-21 22:03:37 +02005542 execute( TC_lu_imsi_auth3g_tmsi() );
Harald Welted2328a22018-01-27 14:27:16 +01005543 execute( TC_cmserv_imsi_unknown() );
Harald Welte2bb825f2018-01-22 11:31:18 +01005544 execute( TC_lu_and_mo_call() );
Harald Welte071ed732018-01-23 19:53:52 +01005545 execute( TC_lu_auth_sai_timeout() );
5546 execute( TC_lu_auth_sai_err() );
Harald Weltee1a2f3c2018-01-24 17:28:48 +01005547 execute( TC_lu_clear_request() );
5548 execute( TC_lu_disconnect() );
5549 execute( TC_lu_by_imei() );
5550 execute( TC_lu_by_tmsi_noauth_unknown() );
5551 execute( TC_imsi_detach_by_imsi() );
5552 execute( TC_imsi_detach_by_tmsi() );
5553 execute( TC_imsi_detach_by_imei() );
5554 execute( TC_emerg_call_imei_reject() );
5555 execute( TC_emerg_call_imsi() );
5556 execute( TC_cm_serv_req_vgcs_reject() );
5557 execute( TC_cm_serv_req_vbs_reject() );
5558 execute( TC_cm_serv_req_lcs_reject() );
Harald Welte0195ab12018-01-24 21:50:20 +01005559 execute( TC_cm_reest_req_reject() );
Harald Welte1af6ea82018-01-25 18:33:15 +01005560 execute( TC_lu_auth_2G_fail() );
5561 execute( TC_lu_imsi_auth_tmsi_encr_13_13() );
5562 execute( TC_cl3_no_payload() );
5563 execute( TC_cl3_rnd_payload() );
Harald Welte1852a842018-01-26 22:53:36 +01005564 execute( TC_establish_and_nothing() );
5565 execute( TC_mo_setup_and_nothing() );
5566 execute( TC_mo_crcx_ran_timeout() );
5567 execute( TC_mo_crcx_ran_reject() );
Harald Welted2328a22018-01-27 14:27:16 +01005568 execute( TC_mt_crcx_ran_reject() );
Daniel Willmann8b084372018-02-04 13:35:26 +01005569 execute( TC_mo_setup_and_dtmf_dup() );
Harald Welteaa54cf82018-01-30 08:15:32 +01005570 //execute( TC_mt_t310() );
Harald Welte167458a2018-01-27 15:58:16 +01005571 execute( TC_gsup_cancel() );
Harald Welte9de84792018-01-28 01:06:35 +01005572 execute( TC_lu_imsi_auth_tmsi_encr_1_13() );
5573 execute( TC_lu_imsi_auth_tmsi_encr_3_13() );
5574 execute( TC_lu_imsi_auth_tmsi_encr_3_1() );
Neels Hofmeyr29b8da02018-03-01 18:09:45 +01005575 execute( TC_lu_imsi_auth_tmsi_encr_3_1_no_cm() );
Harald Welte9de84792018-01-28 01:06:35 +01005576 execute( TC_lu_imsi_auth_tmsi_encr_13_2() );
5577 execute( TC_lu_imsi_auth_tmsi_encr_013_2() );
Philipp Maier94f3f1b2018-03-15 18:54:13 +01005578 execute( TC_mo_release_timeout() );
Philipp Maier2a98a732018-03-19 16:06:12 +01005579 execute( TC_lu_and_mt_call_no_dlcx_resp() );
Philipp Maier75932982018-03-27 14:52:35 +02005580 execute( TC_reset_two() );
Harald Welte33ec09b2018-02-10 15:34:46 +01005581
5582 execute( TC_lu_and_mt_call() );
5583
Harald Weltef45efeb2018-04-09 18:19:24 +02005584 execute( TC_lu_and_mo_sms() );
5585 execute( TC_lu_and_mt_sms() );
Philipp Maier3983e702018-11-22 19:01:33 +01005586 execute( TC_lu_and_mt_sms_paging_and_nothing() );
Harald Weltef640a012018-04-14 17:49:21 +02005587 execute( TC_smpp_mo_sms() );
5588 execute( TC_smpp_mt_sms() );
Harald Weltef45efeb2018-04-09 18:19:24 +02005589
Vadim Yanitskiy103d09f2018-11-12 02:50:23 +07005590 execute( TC_gsup_mo_sms() );
Vadim Yanitskiy9cc019a2018-11-15 02:06:07 +07005591 execute( TC_gsup_mo_smma() );
Vadim Yanitskiyd7b37ab2018-11-24 03:40:20 +07005592 execute( TC_gsup_mt_sms_ack() );
5593 execute( TC_gsup_mt_sms_err() );
Vadim Yanitskiybe1ff4b2019-01-18 15:04:13 +07005594 execute( TC_gsup_mt_sms_rp_mr() );
Vadim Yanitskiy5ac49cc2019-01-24 16:57:31 +07005595 execute( TC_gsup_mo_mt_sms_rp_mr() );
Vadim Yanitskiy103d09f2018-11-12 02:50:23 +07005596
Vadim Yanitskiy2a978b92018-06-19 17:51:20 +07005597 execute( TC_lu_and_mo_ussd_single_request() );
Vadim Yanitskiy13e4a272018-06-19 18:24:31 +07005598 execute( TC_lu_and_mt_ussd_notification() );
Vadim Yanitskiy2a978b92018-06-19 17:51:20 +07005599 execute( TC_lu_and_mo_ussd_during_mt_call() );
Vadim Yanitskiy13e4a272018-06-19 18:24:31 +07005600 execute( TC_lu_and_mt_ussd_during_mt_call() );
Vadim Yanitskiy2daf52d2018-06-21 04:19:58 +07005601 execute( TC_lu_and_mo_ussd_mo_release() );
Vadim Yanitskiy0e392dd2018-11-29 00:47:54 +07005602 execute( TC_lu_and_ss_session_timeout() );
Vadim Yanitskiy7d1f9182018-05-28 16:21:42 +07005603
Vadim Yanitskiy0e6c9f52019-06-15 01:01:28 +07005604 execute( TC_mt_ussd_for_unknown_subscr() );
Vadim Yanitskiyc3c07d42019-06-17 23:00:44 +07005605 execute( TC_mo_ussd_for_unknown_trans() );
Vadim Yanitskiyd612d282019-06-15 14:46:03 +07005606 execute( TC_proc_ss_for_unknown_session() );
Vadim Yanitskiye5f4ed92019-06-16 02:36:33 +07005607 execute( TC_proc_ss_paging_fail() );
Vadim Yanitskiy29ba8d62019-06-16 15:19:41 +07005608 execute( TC_proc_ss_abort() );
Vadim Yanitskiy0e6c9f52019-06-15 01:01:28 +07005609
Stefan Sperling89eb1f32018-12-17 15:06:20 +01005610 execute( TC_cipher_complete_with_invalid_cipher() );
Stefan Sperlinga2d59c62018-12-18 16:32:44 +01005611 execute( TC_cipher_complete_1_without_cipher() );
5612 execute( TC_cipher_complete_3_without_cipher() );
5613 execute( TC_cipher_complete_13_without_cipher() );
Harald Welteb2284bd2019-05-10 11:30:43 +02005614 execute( TC_lu_with_invalid_mcc_mnc() );
Stefan Sperling89eb1f32018-12-17 15:06:20 +01005615
Harald Welte4263c522018-12-06 11:56:27 +01005616 execute( TC_sgsap_reset() );
5617 execute( TC_sgsap_lu() );
5618 execute( TC_sgsap_lu_imsi_reject() );
5619 execute( TC_sgsap_lu_and_nothing() );
5620 execute( TC_sgsap_expl_imsi_det_eps() );
Philipp Maierfc19f172019-03-21 11:17:54 +01005621 execute( TC_sgsap_impl_imsi_det_eps() );
Harald Welte4263c522018-12-06 11:56:27 +01005622 execute( TC_sgsap_expl_imsi_det_noneps() );
Philipp Maier5d812702019-03-21 10:51:26 +01005623 execute( TC_sgsap_impl_imsi_det_noneps() );
Harald Welte4263c522018-12-06 11:56:27 +01005624 execute( TC_sgsap_paging_rej() );
5625 execute( TC_sgsap_paging_subscr_rej() );
5626 execute( TC_sgsap_paging_ue_unr() );
5627 execute( TC_sgsap_paging_and_nothing() );
5628 execute( TC_sgsap_paging_and_lu() );
5629 execute( TC_sgsap_mt_sms() );
5630 execute( TC_sgsap_mo_sms() );
5631 execute( TC_sgsap_mt_sms_and_nothing() );
5632 execute( TC_sgsap_mt_sms_and_reject() );
5633 execute( TC_sgsap_unexp_ud() );
5634 execute( TC_sgsap_unsol_ud() );
5635 execute( TC_bssap_lu_sgsap_lu_and_mt_call() );
5636 execute( TC_sgsap_lu_and_mt_call() );
Philipp Maier628c0052019-04-09 17:36:57 +02005637 execute( TC_sgsap_vlr_failure() );
Harald Welte4263c522018-12-06 11:56:27 +01005638
Neels Hofmeyr0ac63152019-05-07 01:20:17 +02005639 execute( TC_ho_inter_bsc_unknown_cell() );
5640 execute( TC_ho_inter_bsc() );
5641
5642 execute( TC_ho_inter_msc_out() );
5643
Neels Hofmeyr1b3c6e32018-03-01 17:52:21 +01005644 /* Run this last: at the time of writing this test crashes the MSC */
5645 execute( TC_lu_imsi_auth_tmsi_encr_3_1_log_msc_debug() );
Philipp Maierdb7fb8d2019-02-11 10:50:13 +01005646 execute( TC_gsup_mt_multi_part_sms() );
Neels Hofmeyr692c9ee2018-04-10 02:07:13 +02005647 execute( TC_mo_cc_bssmap_clear() );
Pau Espin Pedrol690d6592019-05-31 17:56:32 +02005648 if (mp_enable_osmux_test) {
5649 execute( TC_lu_and_mt_call_osmux() );
5650 }
Harald Weltef6dd64d2017-11-19 12:09:51 +01005651}
5652
5653
5654}