blob: d4be96b74262f9b56b7330accfebce74c1146fae [file] [log] [blame]
Harald Weltef6dd64d2017-11-19 12:09:51 +01001module MSC_Tests {
2
Harald Weltee13cfb22019-04-23 16:52:02 +02003friend module MSC_Tests_Iu;
4
Harald Weltef6dd64d2017-11-19 12:09:51 +01005import from General_Types all;
6import from Osmocom_Types all;
7
8import from M3UA_Types all;
9import from M3UA_Emulation all;
10
11import from MTP3asp_Types all;
12import from MTP3asp_PortType all;
13
14import from SCCPasp_Types all;
15import from SCCP_Types all;
16import from SCCP_Emulation all;
17
18import from SCTPasp_Types all;
19import from SCTPasp_PortType all;
20
Harald Weltea49e36e2018-01-21 19:29:33 +010021import from Osmocom_CTRL_Functions all;
22import from Osmocom_CTRL_Types all;
23import from Osmocom_CTRL_Adapter all;
24
Harald Welte3ca1c902018-01-24 18:51:27 +010025import from TELNETasp_PortType all;
26import from Osmocom_VTY_Functions all;
27
Harald Weltea49e36e2018-01-21 19:29:33 +010028import from MNCC_Emulation all;
Harald Welte2bb825f2018-01-22 11:31:18 +010029import from MNCC_Types all;
Harald Weltea49e36e2018-01-21 19:29:33 +010030
Harald Welte4aa970c2018-01-26 10:38:09 +010031import from MGCP_Emulation all;
32import from MGCP_Types all;
33import from MGCP_Templates all;
34import from SDP_Types all;
35
Harald Weltea49e36e2018-01-21 19:29:33 +010036import from GSUP_Emulation all;
37import from GSUP_Types all;
38import from IPA_Emulation all;
39
Harald Weltef6dd64d2017-11-19 12:09:51 +010040import from BSSAP_Types all;
Harald Welte6811d102019-04-14 22:23:14 +020041import from RAN_Adapter all;
Harald Weltea49e36e2018-01-21 19:29:33 +010042import from BSSAP_CodecPort all;
43import from BSSMAP_Templates all;
Harald Welte6811d102019-04-14 22:23:14 +020044import from RAN_Emulation all;
Harald Weltea49e36e2018-01-21 19:29:33 +010045import from BSC_ConnectionHandler all;
Harald Weltee13cfb22019-04-23 16:52:02 +020046import from RANAP_Templates all;
Harald Weltef6dd64d2017-11-19 12:09:51 +010047
Harald Welte4263c522018-12-06 11:56:27 +010048import from SGsAP_Templates all;
49import from SGsAP_Types all;
50import from SGsAP_Emulation all;
51
Harald Weltea49e36e2018-01-21 19:29:33 +010052import from MobileL3_Types all;
53import from MobileL3_CommonIE_Types all;
Vadim Yanitskiy103d09f2018-11-12 02:50:23 +070054import from MobileL3_SMS_Types all;
Harald Weltea49e36e2018-01-21 19:29:33 +010055import from L3_Templates all;
Harald Welte158a7ca2018-02-16 18:11:31 +010056import from L3_Common all;
Harald Weltef6dd64d2017-11-19 12:09:51 +010057
Harald Weltef640a012018-04-14 17:49:21 +020058import from SMPP_Types all;
59import from SMPP_Templates all;
60import from SMPP_Emulation all;
61
Stefan Sperlingc307e682018-06-14 15:15:46 +020062import from SCCP_Templates all;
63
Vadim Yanitskiy7d1f9182018-05-28 16:21:42 +070064import from SS_Types all;
65import from SS_Templates all;
66import from USSD_Helpers all;
Harald Welte4263c522018-12-06 11:56:27 +010067import from DNS_Helpers all;
Vadim Yanitskiy7d1f9182018-05-28 16:21:42 +070068
Philipp Maier948747b2019-04-02 15:22:33 +020069import from TCCConversion_Functions all;
70
Harald Welte9b751a62019-04-14 17:39:29 +020071const integer NUM_BSC := 3;
Harald Welte6811d102019-04-14 22:23:14 +020072type record of RAN_Configuration RAN_Configurations;
Harald Weltef6dd64d2017-11-19 12:09:51 +010073
Harald Welte4263c522018-12-06 11:56:27 +010074/* Needed for SGsAP SMS */
75import from MobileL3_SMS_Types all;
76
Harald Weltea4ca4462018-02-09 00:17:14 +010077type component MTC_CT extends CTRL_Adapter_CT {
Harald Weltef6dd64d2017-11-19 12:09:51 +010078 var boolean g_initialized := false;
Harald Weltea49e36e2018-01-21 19:29:33 +010079
Harald Welte6811d102019-04-14 22:23:14 +020080 var RAN_Adapter g_bssap[NUM_BSC];
Harald Weltea4ca4462018-02-09 00:17:14 +010081
Harald Weltea49e36e2018-01-21 19:29:33 +010082 /* no 'adapter_CT' for MNCC or GSUP */
83 var MNCC_Emulation_CT vc_MNCC;
Harald Welte4aa970c2018-01-26 10:38:09 +010084 var MGCP_Emulation_CT vc_MGCP;
Harald Weltea49e36e2018-01-21 19:29:33 +010085 var GSUP_Emulation_CT vc_GSUP;
86 var IPA_Emulation_CT vc_GSUP_IPA;
Harald Weltef640a012018-04-14 17:49:21 +020087 var SMPP_Emulation_CT vc_SMPP;
Harald Welte4263c522018-12-06 11:56:27 +010088 var SGsAP_Emulation_CT vc_SGsAP;
Harald Weltea49e36e2018-01-21 19:29:33 +010089
90 /* only to get events from IPA underneath GSUP */
91 port IPA_CTRL_PT GSUP_IPA_EVENT;
Harald Welte3ca1c902018-01-24 18:51:27 +010092 /* VTY to MSC */
93 port TELNETasp_PT MSCVTY;
Philipp Maier328d1662018-03-07 10:40:27 +010094
95 /* A port to directly send BSSAP messages. This port is used for
96 * tests that require low level access to sen arbitrary BSSAP
97 * messages. Run f_init_bssap_direct() to connect and initialize */
98 port BSSAP_CODEC_PT BSSAP_DIRECT;
99
100 /* When BSSAP messages are directly sent, then the connection
101 * handler is not active, which means that also no guard timer is
102 * set up. The following timer will serve as a replacement */
103 timer Tguard_direct := 60.0;
Harald Weltef6dd64d2017-11-19 12:09:51 +0100104}
105
106modulepar {
Harald Weltea49e36e2018-01-21 19:29:33 +0100107 /* remote parameters of IUT */
108 charstring mp_msc_ip := "127.0.0.1";
109 integer mp_msc_ctrl_port := 4255;
110 integer mp_msc_vty_port := 4254;
Harald Weltef6dd64d2017-11-19 12:09:51 +0100111
Harald Weltea49e36e2018-01-21 19:29:33 +0100112 /* local parameters of emulated HLR */
Philipp Maier9b690e42018-12-21 11:50:03 +0100113 boolean mp_mm_info := false;
Harald Weltea49e36e2018-01-21 19:29:33 +0100114 charstring mp_hlr_ip := "127.0.0.1";
115 integer mp_hlr_port := 4222;
Harald Welte6126fb02018-01-27 20:08:24 +0100116 charstring mp_mgw_ip := "127.0.0.1";
117 integer mp_mgw_port := 2427;
Harald Weltef6dd64d2017-11-19 12:09:51 +0100118
Harald Weltea49e36e2018-01-21 19:29:33 +0100119 charstring mp_msc_mncc := "/tmp/mncc";
Harald Weltea4ca4462018-02-09 00:17:14 +0100120
Harald Weltef640a012018-04-14 17:49:21 +0200121 integer mp_msc_smpp_port := 2775;
122 charstring mp_smpp_system_id := "msc_tester";
123 charstring mp_smpp_password := "osmocom1";
Harald Welte4263c522018-12-06 11:56:27 +0100124 charstring mp_mme_name := "mmec01.mmegi0001.mme.epc.mnc070.mcc901.3gppnetwork.org";
125 charstring mp_vlr_name := "vlr.example.net";
Harald Weltef640a012018-04-14 17:49:21 +0200126
Harald Welte6811d102019-04-14 22:23:14 +0200127 RAN_Configurations mp_bssap_cfg := {
Philipp Maier75932982018-03-27 14:52:35 +0200128 {
129 sccp_service_type := "mtp3_itu",
130 sctp_addr := { 23905, "127.0.0.1", 2905, "127.0.0.1" },
131 own_pc := 185,
132 own_ssn := 254,
133 peer_pc := 187,
134 peer_ssn := 254,
135 sio := '83'O,
136 rctx := 0
137 },
138 {
139 sccp_service_type := "mtp3_itu",
140 sctp_addr := { 23906, "127.0.0.1", 2905, "127.0.0.1" },
141 own_pc := 186,
142 own_ssn := 254,
143 peer_pc := 187,
144 peer_ssn := 254,
145 sio := '83'O,
146 rctx := 1
147 }
Harald Weltea4ca4462018-02-09 00:17:14 +0100148 };
Harald Weltef6dd64d2017-11-19 12:09:51 +0100149}
150
Philipp Maier328d1662018-03-07 10:40:27 +0100151/* altstep for the global guard timer (only used when BSSAP_DIRECT
152 * is used for communication */
153private altstep as_Tguard_direct() runs on MTC_CT {
154 [] Tguard_direct.timeout {
155 setverdict(fail, "Tguard timeout");
Daniel Willmannafce8662018-07-06 23:11:32 +0200156 mtc.stop;
Philipp Maier328d1662018-03-07 10:40:27 +0100157 }
158}
Harald Weltef6dd64d2017-11-19 12:09:51 +0100159
Neels Hofmeyrde76f052019-02-26 05:02:46 +0100160private altstep as_optional_cc_rel(CallParameters cpars) runs on BSC_ConnHdlr {
161 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_CC_RELEASE(cpars.transaction_id))) { repeat; };
162}
163
Harald Weltef640a012018-04-14 17:49:21 +0200164function f_init_smpp(charstring id) runs on MTC_CT {
165 id := id & "-SMPP";
166 var EsmePars pars := {
167 mode := MODE_TRANSCEIVER,
168 bind := {
169 system_id := mp_smpp_system_id,
170 password := mp_smpp_password,
171 system_type := "MSC_Tests",
172 interface_version := hex2int('34'H),
173 addr_ton := unknown,
174 addr_npi := unknown,
175 address_range := ""
176 },
177 esme_role := true
178 }
179
180 vc_SMPP := SMPP_Emulation_CT.create(id);
181 map(vc_SMPP:SMPP_PORT, system:SMPP_PORT);
182 vc_SMPP.start(SMPP_Emulation.main_client(pars, mp_msc_ip, mp_msc_smpp_port, "", -1));
183}
184
185
Harald Weltea49e36e2018-01-21 19:29:33 +0100186function f_init_mncc(charstring id) runs on MTC_CT {
187 id := id & "-MNCC";
188 var MnccOps ops := {
189 create_cb := refers(MNCC_Emulation.ExpectedCreateCallback),
190 unitdata_cb := refers(MNCC_Emulation.DummyUnitdataCallback)
191 }
192
193 vc_MNCC := MNCC_Emulation_CT.create(id);
194 map(vc_MNCC:MNCC, system:MNCC_CODEC_PT);
195 vc_MNCC.start(MNCC_Emulation.main(ops, id, mp_msc_mncc));
Harald Weltef6dd64d2017-11-19 12:09:51 +0100196}
197
Harald Welte4aa970c2018-01-26 10:38:09 +0100198function f_init_mgcp(charstring id) runs on MTC_CT {
199 id := id & "-MGCP";
200 var MGCPOps ops := {
201 create_cb := refers(MGCP_Emulation.ExpectedCreateCallback),
202 unitdata_cb := refers(MGCP_Emulation.DummyUnitdataCallback)
203 }
204 var MGCP_conn_parameters pars := {
Harald Welte6126fb02018-01-27 20:08:24 +0100205 callagent_ip := mp_msc_ip,
Harald Welte4aa970c2018-01-26 10:38:09 +0100206 callagent_udp_port := -1,
Harald Welte6126fb02018-01-27 20:08:24 +0100207 mgw_ip := mp_mgw_ip,
208 mgw_udp_port := mp_mgw_port
Harald Welte4aa970c2018-01-26 10:38:09 +0100209 }
210
211 vc_MGCP := MGCP_Emulation_CT.create(id);
212 map(vc_MGCP:MGCP, system:MGCP_CODEC_PT);
213 vc_MGCP.start(MGCP_Emulation.main(ops, pars, id));
214}
215
Philipp Maierc09a1312019-04-09 16:05:26 +0200216function ForwardUnitdataCallback(PDU_SGsAP msg)
217runs on SGsAP_Emulation_CT return template PDU_SGsAP {
218 SGsAP_CLIENT.send(msg);
219 return omit;
220}
221
Harald Welte4263c522018-12-06 11:56:27 +0100222function f_init_sgsap(charstring id) runs on MTC_CT {
223 id := id & "-SGsAP";
224 var SGsAPOps ops := {
225 create_cb := refers(SGsAP_Emulation.ExpectedCreateCallback),
Philipp Maierc09a1312019-04-09 16:05:26 +0200226 unitdata_cb := refers(ForwardUnitdataCallback)
Harald Welte4263c522018-12-06 11:56:27 +0100227 }
228 var SGsAP_conn_parameters pars := {
229 remote_ip := mp_msc_ip,
230 remote_sctp_port := 29118,
231 local_ip := "",
232 local_sctp_port := -1
233 }
234
235 vc_SGsAP := SGsAP_Emulation_CT.create(id);
236 map(vc_SGsAP:SGsAP, system:SGsAP_CODEC_PT);
237 vc_SGsAP.start(SGsAP_Emulation.main(ops, pars, id));
238}
239
240
Harald Weltea49e36e2018-01-21 19:29:33 +0100241function f_init_gsup(charstring id) runs on MTC_CT {
242 id := id & "-GSUP";
243 var GsupOps ops := {
244 create_cb := refers(GSUP_Emulation.ExpectedCreateCallback)
245 }
246
247 vc_GSUP_IPA := IPA_Emulation_CT.create(id & "-IPA");
248 vc_GSUP := GSUP_Emulation_CT.create(id);
249
250 map(vc_GSUP_IPA:IPA_PORT, system:IPA_CODEC_PT);
251 connect(vc_GSUP:GSUP, vc_GSUP_IPA:IPA_GSUP_PORT);
252 /* we use this hack to get events like ASP_IPA_EVENT_UP */
253 connect(vc_GSUP_IPA:IPA_CTRL_PORT, self:GSUP_IPA_EVENT);
254
255 vc_GSUP.start(GSUP_Emulation.main(ops, id));
256 vc_GSUP_IPA.start(IPA_Emulation.main_server(mp_hlr_ip, mp_hlr_port));
257
258 /* wait for incoming connection to GSUP port before proceeding */
259 timer T := 10.0;
260 T.start;
261 alt {
262 [] GSUP_IPA_EVENT.receive(t_ASP_IPA_EVT_UD(ASP_IPA_EVENT_UP)) { }
263 [] T.timeout {
Harald Welte458fd372018-03-21 11:26:23 +0100264 setverdict(fail, "No connection to GSUP Port");
Daniel Willmannafce8662018-07-06 23:11:32 +0200265 mtc.stop
Harald Weltea49e36e2018-01-21 19:29:33 +0100266 }
267 }
Harald Weltef6dd64d2017-11-19 12:09:51 +0100268}
269
Philipp Maierc09a1312019-04-09 16:05:26 +0200270function f_init(integer num_bsc := 1, boolean sgsap := false, boolean gsup := true) runs on MTC_CT {
Harald Weltef6dd64d2017-11-19 12:09:51 +0100271
272 if (g_initialized == true) {
273 return;
274 }
275 g_initialized := true;
276
Philipp Maier75932982018-03-27 14:52:35 +0200277 if (num_bsc > NUM_BSC) {
Daniel Willmannafce8662018-07-06 23:11:32 +0200278 testcase.stop("excess number of BSC instances requested");
Philipp Maier75932982018-03-27 14:52:35 +0200279 }
280
281 for (var integer i := 0; i < num_bsc; i := i + 1) {
282 if (isbound(mp_bssap_cfg[i])) {
Harald Welte3ca0ce12019-04-23 17:18:48 +0200283 f_ran_adapter_init(g_bssap[i], mp_bssap_cfg[i], "MSC_Test_" & int2str(i), BSC_RanOps);
284 f_ran_adapter_start(g_bssap[i]);
Philipp Maier75932982018-03-27 14:52:35 +0200285 } else {
Daniel Willmannafce8662018-07-06 23:11:32 +0200286 testcase.stop("missing BSSAP configuration");
Philipp Maier75932982018-03-27 14:52:35 +0200287 }
288 }
289
Harald Weltea49e36e2018-01-21 19:29:33 +0100290 f_ipa_ctrl_start(mp_msc_ip, mp_msc_ctrl_port);
291 f_init_mncc("MSC_Test");
Harald Welte4aa970c2018-01-26 10:38:09 +0100292 f_init_mgcp("MSC_Test");
Philipp Maierc09a1312019-04-09 16:05:26 +0200293
294 if (gsup == true) {
295 f_init_gsup("MSC_Test");
296 }
Harald Weltef640a012018-04-14 17:49:21 +0200297 f_init_smpp("MSC_Test");
Philipp Maier57865482019-01-07 18:33:13 +0100298
Philipp Maier8e07a4a2019-02-14 18:23:28 +0100299 if (sgsap == true) {
Philipp Maier57865482019-01-07 18:33:13 +0100300 f_init_sgsap("MSC_Test");
301 }
Harald Welte3ca1c902018-01-24 18:51:27 +0100302
303 map(self:MSCVTY, system:MSCVTY);
304 f_vty_set_prompts(MSCVTY);
305 f_vty_transceive(MSCVTY, "enable");
Harald Welteb14c77a2018-01-25 17:25:44 +0100306
307 /* set some defaults */
308 f_vty_config(MSCVTY, "network", "authentication optional");
309 f_vty_config(MSCVTY, "msc", "assign-tmsi");
310 f_vty_config(MSCVTY, "network", "encryption a5 0");
Harald Weltef6dd64d2017-11-19 12:09:51 +0100311}
312
Philipp Maier328d1662018-03-07 10:40:27 +0100313/* Initialize for a direct connection to BSSAP. This function is an alternative
314 * to f_init() when the high level functions of the BSC_ConnectionHandler are
315 * not needed. */
316function f_init_bssap_direct() runs on MTC_CT {
Harald Welte3ca0ce12019-04-23 17:18:48 +0200317 f_ran_adapter_init(g_bssap[0], mp_bssap_cfg[0], "MSC_Test", omit);
Philipp Maier75932982018-03-27 14:52:35 +0200318 connect(g_bssap[0].vc_SCCP:SCCP_SP_PORT, self:BSSAP_DIRECT);
Philipp Maier328d1662018-03-07 10:40:27 +0100319
320 /* Start guard timer and activate it as default */
321 Tguard_direct.start
322 activate(as_Tguard_direct());
323}
324
Harald Weltef6dd64d2017-11-19 12:09:51 +0100325template PDU_BSSAP ts_BSSAP_BSSMAP := {
326 discriminator := '0'B,
327 spare := '0000000'B,
328 dlci := omit,
329 lengthIndicator := 0, /* overwritten by codec */
330 pdu := ?
331}
332
333template PDU_BSSAP tr_BSSAP_BSSMAP := {
334 discriminator := '0'B,
335 spare := '0000000'B,
336 dlci := omit,
337 lengthIndicator := ?,
338 pdu := {
339 bssmap := ?
340 }
341}
342
343
344type integer BssmapCause;
345
346template (value) BSSMAP_IE_Cause ts_BSSMAP_IE_Cause(BssmapCause val) := {
347 elementIdentifier := '04'O,
348 lengthIndicator := 0,
349 causeValue := int2bit(val, 7),
350 extensionCauseValue := '0'B,
351 spare1 := omit
352}
353
354template (value) PDU_BSSAP ts_BSSMAP_Reset(BssmapCause cause) modifies ts_BSSAP_BSSMAP := {
355 pdu := {
356 bssmap := {
357 reset := {
358 messageType := '30'O,
359 cause := ts_BSSMAP_IE_Cause(cause),
360 a_InterfaceSelectorForReset := omit
361 }
362 }
363 }
364}
365
366template (value) PDU_BSSAP ts_BSSMAP_ResetAck modifies ts_BSSAP_BSSMAP := {
367 pdu := {
368 bssmap := {
369 resetAck := {
370 messageType := '31'O,
371 a_InterfaceSelectorForReset := omit
372 }
373 }
374 }
375}
376
377template PDU_BSSAP tr_BSSMAP_ResetAck modifies tr_BSSAP_BSSMAP := {
378 pdu := {
379 bssmap := {
380 resetAck := {
381 messageType := '31'O,
382 a_InterfaceSelectorForReset := *
383 }
384 }
385 }
386}
387
388template BSSMAP_IE_CellIdentifier ts_BSSMAP_IE_CellID := {
389 elementIdentifier := '05'O,
390 lengthIndicator := 0,
391 cellIdentifierDiscriminator := '0000'B,
392 spare1_4 := '0000'B,
393 cellIdentification := ?
394}
395
396type uint16_t BssmapLAC;
397type uint16_t BssmapCI;
398
399/*
400template BSSMAP_IE_CellIdentifier ts_CellId_CGI(mcc, mnc, lac, ci)
401modifies ts_BSSMAP_IE_CellID := {
402 cellIdentification := {
403 cI_LAC_CGI := {
404 mnc_mcc := FIXME,
405 lac := int2oct(lac, 2),
406 ci := int2oct(ci, 2)
407 }
408 }
409}
410*/
411
412template BSSMAP_IE_CellIdentifier ts_CellID_LAC_CI(BssmapLAC lac, BssmapCI ci)
413modifies ts_BSSMAP_IE_CellID := {
414 cellIdentification := {
415 cI_LAC_CI := {
416 lac := int2oct(lac, 2),
417 ci := int2oct(ci, 2)
418 }
419 }
420}
421
422template BSSMAP_IE_CellIdentifier ts_CellId_CI(BssmapCI ci)
423modifies ts_BSSMAP_IE_CellID := {
424 cellIdentification := {
425 cI_CI := int2oct(ci, 2)
426 }
427}
428
429template BSSMAP_IE_CellIdentifier ts_CellId_none
430modifies ts_BSSMAP_IE_CellID := {
431 cellIdentification := {
432 cI_noCell := ''O
433 }
434}
435
436
437template BSSMAP_IE_Layer3Information ts_BSSMAP_IE_L3Info(octetstring l3info) := {
438 elementIdentifier := '17'O,
439 lengthIndicator := 0,
440 layer3info := l3info
441}
442
443template PDU_BSSAP ts_BSSMAP_ComplL3(BSSMAP_IE_CellIdentifier cell_id, octetstring l3_info)
444modifies ts_BSSAP_BSSMAP := {
445 pdu := {
446 bssmap := {
447 completeLayer3Information := {
448 messageType := '57'O,
449 cellIdentifier := cell_id,
450 layer3Information := ts_BSSMAP_IE_L3Info(l3_info),
451 chosenChannel := omit,
452 lSAIdentifier := omit,
453 aPDU := omit,
454 codecList := omit,
455 redirectAttemptFlag := omit,
456 sendSequenceNumber := omit,
457 iMSI := omit
458 }
459 }
460 }
461}
462
463template PDU_BSSAP ts_BSSMAP_HandoReq(BssmapCause cause, BSSMAP_IE_CellIdentifierList cid_list)
464modifies ts_BSSAP_BSSMAP := {
465 pdu := {
466 bssmap := {
467 handoverRequired := {
468 messageType := '11'O,
469 cause := ts_BSSMAP_IE_Cause(cause),
470 responseRequest := omit,
471 cellIdentifierList := cid_list,
472 circuitPoolList := omit,
473 currentChannelType1 := omit,
474 speechVersion := omit,
475 queueingIndicator := omit,
476 oldToNewBSSInfo := omit,
477 sourceToTargetRNCTransparentInfo := omit,
478 sourceToTargetRNCTransparentInfoCDMA := omit,
479 gERANClassmark := omit,
480 talkerPriority := omit,
481 speechCodec := omit,
482 cSG_Identifier := omit
483 }
484 }
485 }
486}
487
Harald Weltea49e36e2018-01-21 19:29:33 +0100488type function void_fn(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr;
Harald Weltef6dd64d2017-11-19 12:09:51 +0100489
Harald Weltea49e36e2018-01-21 19:29:33 +0100490/* FIXME: move into BSC_ConnectionHandler? */
Harald Welte9b751a62019-04-14 17:39:29 +0200491function f_init_pars(integer imsi_suffix, boolean sgsap := false, boolean gsup := true, integer ran_idx := 0,
492 boolean ran_is_geran := true)
Harald Weltef9abf8d2019-04-21 13:07:17 +0200493runs on MTC_CT return BSC_ConnHdlrPars {
Harald Weltede371492018-01-27 23:44:41 +0100494 var BSC_ConnHdlrNetworkPars net_pars := {
495 kc_support := '0A'O, /* A5/1 and A5/3 enabled */
496 expect_tmsi := true,
497 expect_auth := false,
498 expect_ciph := false
499 };
Harald Weltea49e36e2018-01-21 19:29:33 +0100500 var BSC_ConnHdlrPars pars := {
Harald Weltef9abf8d2019-04-21 13:07:17 +0200501 sccp_addr_own := g_bssap[ran_idx].sccp_addr_own,
502 sccp_addr_peer := g_bssap[ran_idx].sccp_addr_peer,
Harald Welteedbab812018-03-18 16:02:25 +0100503 cell_id := valueof(ts_CellId_CGI('262'H, '42'H, 23, 42)),
Harald Welte81b7f9d2018-01-24 19:06:24 +0100504 imei := f_gen_imei(imsi_suffix),
505 imsi := f_gen_imsi(imsi_suffix),
506 msisdn := f_gen_msisdn(imsi_suffix),
Harald Welte256571e2018-01-24 18:47:19 +0100507 tmsi := omit,
Harald Welte9de84792018-01-28 01:06:35 +0100508 cm1 := valueof(ts_CM1),
Harald Welte82600572018-01-21 20:54:08 +0100509 cm2 := valueof(ts_CM2_default),
Harald Welte16114282018-01-24 22:41:21 +0100510 cm3 := omit,
Harald Weltede371492018-01-27 23:44:41 +0100511 vec := omit,
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +0100512 net := net_pars,
Philipp Maieraeb29a82018-11-08 17:40:53 +0100513 send_early_cm := true,
514 ipa_ctrl_ip := mp_msc_ip,
515 ipa_ctrl_port := mp_msc_ctrl_port,
Philipp Maier9b690e42018-12-21 11:50:03 +0100516 ipa_ctrl_enable := true,
Philipp Maier57865482019-01-07 18:33:13 +0100517 mm_info := mp_mm_info,
Philipp Maierc09a1312019-04-09 16:05:26 +0200518 sgsap_enable := sgsap,
Harald Weltef9abf8d2019-04-21 13:07:17 +0200519 gsup_enable := gsup,
Harald Weltec1f937a2019-04-21 21:19:23 +0200520 ran_idx := ran_idx,
Harald Welte9b751a62019-04-14 17:39:29 +0200521 use_umts_aka := false,
522 ran_is_geran := ran_is_geran
Harald Weltea49e36e2018-01-21 19:29:33 +0100523 };
Harald Weltee13cfb22019-04-23 16:52:02 +0200524 if (not ran_is_geran) {
525 pars.use_umts_aka := true;
526 pars.net.expect_auth := true;
527 }
Neels Hofmeyr9adaa702018-03-01 20:23:19 +0100528 return pars;
529}
530
531function f_start_handler_with_pars(void_fn fn, BSC_ConnHdlrPars pars) runs on MTC_CT return BSC_ConnHdlr {
532 var BSC_ConnHdlr vc_conn;
533 var charstring id := testcasename();
Harald Weltea49e36e2018-01-21 19:29:33 +0100534
535 vc_conn := BSC_ConnHdlr.create(id);
536 /* BSSMAP part / A interface */
Harald Weltef9abf8d2019-04-21 13:07:17 +0200537 connect(vc_conn:BSSAP, g_bssap[pars.ran_idx].vc_RAN:CLIENT);
538 connect(vc_conn:BSSAP_PROC, g_bssap[pars.ran_idx].vc_RAN:PROC);
Harald Weltea49e36e2018-01-21 19:29:33 +0100539 /* MNCC part */
540 connect(vc_conn:MNCC, vc_MNCC:MNCC_CLIENT);
541 connect(vc_conn:MNCC_PROC, vc_MNCC:MNCC_PROC);
Harald Welte4aa970c2018-01-26 10:38:09 +0100542 /* MGCP part */
543 connect(vc_conn:MGCP, vc_MGCP:MGCP_CLIENT);
544 connect(vc_conn:MGCP_PROC, vc_MGCP:MGCP_PROC);
Harald Weltea49e36e2018-01-21 19:29:33 +0100545 /* GSUP part */
Philipp Maierc09a1312019-04-09 16:05:26 +0200546 if (pars.gsup_enable == true) {
547 connect(vc_conn:GSUP, vc_GSUP:GSUP_CLIENT);
548 connect(vc_conn:GSUP_PROC, vc_GSUP:GSUP_PROC);
549 }
Harald Weltef640a012018-04-14 17:49:21 +0200550 /* SMPP part */
551 connect(vc_conn:SMPP, vc_SMPP:SMPP_CLIENT);
552 connect(vc_conn:SMPP_PROC, vc_SMPP:SMPP_PROC);
Harald Welte4263c522018-12-06 11:56:27 +0100553 /* SGs part */
Philipp Maier8e07a4a2019-02-14 18:23:28 +0100554 if (pars.sgsap_enable == true) {
Philipp Maier57865482019-01-07 18:33:13 +0100555 connect(vc_conn:SGsAP, vc_SGsAP:SGsAP_CLIENT);
556 connect(vc_conn:SGsAP_PROC, vc_SGsAP:SGsAP_PROC);
557 }
Harald Weltea49e36e2018-01-21 19:29:33 +0100558
Harald Weltea10db902018-01-27 12:44:49 +0100559 /* We cannot use vc_conn.start(f_init_handler(fn, id, pars)); as we cannot have
560 * a stand-alone 'derefers()' call, see https://www.eclipse.org/forums/index.php/t/1091364/ */
Harald Weltea49e36e2018-01-21 19:29:33 +0100561 vc_conn.start(derefers(fn)(id, pars));
562 return vc_conn;
563}
564
Harald Welte9b751a62019-04-14 17:39:29 +0200565function f_start_handler(void_fn fn, integer imsi_suffix, integer ran_idx := 0, boolean ran_is_geran := true)
566runs on MTC_CT return BSC_ConnHdlr {
567 return f_start_handler_with_pars(fn, f_init_pars(imsi_suffix, ran_idx := ran_idx, ran_is_geran := ran_is_geran));
Neels Hofmeyr9adaa702018-03-01 20:23:19 +0100568}
569
Harald Weltea49e36e2018-01-21 19:29:33 +0100570private function f_tc_lu_imsi_noauth_tmsi(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +0100571 f_init_handler(pars);
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +0100572 f_perform_lu();
Harald Weltea49e36e2018-01-21 19:29:33 +0100573}
Harald Weltea49e36e2018-01-21 19:29:33 +0100574testcase TC_lu_imsi_noauth_tmsi() runs on MTC_CT {
575 var BSC_ConnHdlr vc_conn;
576 f_init();
577
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +0100578 vc_conn := f_start_handler(refers(f_tc_lu_imsi_noauth_tmsi), 1);
Harald Weltea49e36e2018-01-21 19:29:33 +0100579 vc_conn.done;
580}
581
582private function f_tc_lu_imsi_noauth_notmsi(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltede371492018-01-27 23:44:41 +0100583 pars.net.expect_tmsi := false;
Harald Weltea10db902018-01-27 12:44:49 +0100584 f_init_handler(pars);
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +0100585 f_perform_lu();
Harald Weltea49e36e2018-01-21 19:29:33 +0100586}
Harald Weltea49e36e2018-01-21 19:29:33 +0100587testcase TC_lu_imsi_noauth_notmsi() runs on MTC_CT {
588 var BSC_ConnHdlr vc_conn;
589 f_init();
Harald Welte3ca1c902018-01-24 18:51:27 +0100590 f_vty_config(MSCVTY, "msc", "no assign-tmsi");
Harald Weltea49e36e2018-01-21 19:29:33 +0100591
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +0100592 vc_conn := f_start_handler(refers(f_tc_lu_imsi_noauth_notmsi), 2);
Harald Weltea49e36e2018-01-21 19:29:33 +0100593 vc_conn.done;
594}
595
596/* Do LU by IMSI, refuse it on GSUP and expect LU REJ back to MS */
Harald Weltee13cfb22019-04-23 16:52:02 +0200597friend function f_tc_lu_imsi_reject(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +0100598 f_init_handler(pars);
Harald Weltea49e36e2018-01-21 19:29:33 +0100599 var PDU_ML3_MS_NW l3_lu := f_build_lu_imsi(g_pars.imsi);
600
601 f_create_gsup_expect(hex2str(g_pars.imsi));
Harald Weltedceacc72019-04-21 20:58:35 +0200602 f_cl3_or_initial_ue(l3_lu);
Harald Weltea49e36e2018-01-21 19:29:33 +0100603 GSUP.receive(tr_GSUP_UL_REQ(g_pars.imsi));
604 GSUP.send(ts_GSUP_UL_ERR(g_pars.imsi, 23));
605 alt {
Harald Welte5946b332018-03-18 23:32:21 +0100606 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Rej(int2oct(23,1)))) {
607 f_expect_clear();
608 }
Harald Weltea49e36e2018-01-21 19:29:33 +0100609 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Acc)) {
610 setverdict(fail, "Expecting LU REJ, but got ACCEPT");
Daniel Willmannafce8662018-07-06 23:11:32 +0200611 mtc.stop;
Harald Weltea49e36e2018-01-21 19:29:33 +0100612 }
613 }
Harald Weltea49e36e2018-01-21 19:29:33 +0100614}
615testcase TC_lu_imsi_reject() 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_imsi_reject), 3);
Harald Weltea49e36e2018-01-21 19:29:33 +0100620 vc_conn.done;
621}
622
Harald Weltee13cfb22019-04-23 16:52:02 +0200623
624
Harald Weltea49e36e2018-01-21 19:29:33 +0100625/* Do LU by IMSI, timeout on GSUP */
Harald Weltee13cfb22019-04-23 16:52:02 +0200626friend function f_tc_lu_imsi_timeout_gsup(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +0100627 f_init_handler(pars);
Harald Weltea49e36e2018-01-21 19:29:33 +0100628 var PDU_ML3_MS_NW l3_lu := f_build_lu_imsi(g_pars.imsi);
629
630 f_create_gsup_expect(hex2str(g_pars.imsi));
Harald Weltedceacc72019-04-21 20:58:35 +0200631 f_cl3_or_initial_ue(l3_lu);
Harald Weltea49e36e2018-01-21 19:29:33 +0100632 GSUP.receive(tr_GSUP_UL_REQ(g_pars.imsi));
633 /* Normally the HLR would need to respond here, but we decide to force a timeout here */
634 alt {
635 /* FIXME: Expect specific reject cause */
Harald Welte5946b332018-03-18 23:32:21 +0100636 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Rej)) {
637 f_expect_clear();
638 }
Harald Weltea49e36e2018-01-21 19:29:33 +0100639 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Acc)) {
640 setverdict(fail, "Expecting LU REJ, but got ACCEPT");
Daniel Willmannafce8662018-07-06 23:11:32 +0200641 mtc.stop;
Harald Weltea49e36e2018-01-21 19:29:33 +0100642 }
643 }
Harald Weltea49e36e2018-01-21 19:29:33 +0100644}
645testcase TC_lu_imsi_timeout_gsup() runs on MTC_CT {
646 var BSC_ConnHdlr vc_conn;
647 f_init();
648
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +0100649 vc_conn := f_start_handler(refers(f_tc_lu_imsi_timeout_gsup), 4);
Harald Weltea49e36e2018-01-21 19:29:33 +0100650 vc_conn.done;
651}
652
Harald Weltee13cfb22019-04-23 16:52:02 +0200653
Harald Welte7b1b2812018-01-22 21:23:06 +0100654private function f_tc_lu_imsi_auth_tmsi(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltede371492018-01-27 23:44:41 +0100655 pars.net.expect_auth := true;
Harald Weltea10db902018-01-27 12:44:49 +0100656 f_init_handler(pars);
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +0100657 f_perform_lu();
Harald Welte7b1b2812018-01-22 21:23:06 +0100658}
659testcase TC_lu_imsi_auth_tmsi() runs on MTC_CT {
660 var BSC_ConnHdlr vc_conn;
661 f_init();
Harald Welte3ca1c902018-01-24 18:51:27 +0100662 f_vty_config(MSCVTY, "network", "authentication required");
Harald Welte7b1b2812018-01-22 21:23:06 +0100663
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +0100664 vc_conn := f_start_handler(refers(f_tc_lu_imsi_auth_tmsi), 5);
Harald Welte7b1b2812018-01-22 21:23:06 +0100665 vc_conn.done;
666}
667
Harald Weltee13cfb22019-04-23 16:52:02 +0200668
669friend function f_tc_lu_imsi_auth3g_tmsi(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Welte8a397ae2019-04-21 22:03:37 +0200670 pars.net.expect_auth := true;
671 pars.use_umts_aka := true;
672 f_init_handler(pars);
673 f_perform_lu();
674}
675testcase TC_lu_imsi_auth3g_tmsi() runs on MTC_CT {
676 var BSC_ConnHdlr vc_conn;
677 f_init();
678 f_vty_config(MSCVTY, "network", "authentication required");
679
680 vc_conn := f_start_handler(refers(f_tc_lu_imsi_auth3g_tmsi), 1005);
681 vc_conn.done;
682}
Harald Weltea49e36e2018-01-21 19:29:33 +0100683
Harald Weltee13cfb22019-04-23 16:52:02 +0200684
Harald Weltea49e36e2018-01-21 19:29:33 +0100685/* Send CM SERVICE REQ for IMSI that has never performed LU before */
Harald Weltee13cfb22019-04-23 16:52:02 +0200686friend function f_tc_cmserv_imsi_unknown(charstring id, BSC_ConnHdlrPars pars)
Harald Weltea49e36e2018-01-21 19:29:33 +0100687runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +0100688 f_init_handler(pars);
Harald Weltea49e36e2018-01-21 19:29:33 +0100689
690 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
Harald Welteedbab812018-03-18 16:02:25 +0100691 var BSSMAP_IE_CellIdentifier cell_id := valueof(ts_CellId_CGI('262'H, '42'H, 23, 42));
Harald Welte6ed6bf92018-01-24 21:09:15 +0100692 var PDU_ML3_MS_NW l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, mi));
Harald Weltea49e36e2018-01-21 19:29:33 +0100693
694 f_create_gsup_expect(hex2str(g_pars.imsi));
695
696 /* Send BSSAP_Conn_Req with COMPL L3 INFO to MSC */
Harald Weltedceacc72019-04-21 20:58:35 +0200697 f_cl3_or_initial_ue(l3_info);
Harald Weltea49e36e2018-01-21 19:29:33 +0100698
699 timer T := 10.0;
Harald Weltef6dd64d2017-11-19 12:09:51 +0100700 T.start;
701 alt {
Harald Weltea49e36e2018-01-21 19:29:33 +0100702 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_CM_SERV_REJ)) { }
703 //[] BSSAP.receive(tr_PDU_DTAP_MT(tr_CM_SERV_ACC)) { }
Daniel Willmannafce8662018-07-06 23:11:32 +0200704 [] BSSAP.receive {
705 setverdict(fail, "Received unexpected BSSAP");
706 mtc.stop;
707 }
Harald Weltea49e36e2018-01-21 19:29:33 +0100708 [] GSUP.receive(tr_GSUP_UL_REQ(g_pars.imsi)) {
709 setverdict(fail, "Unexpected GSUP UL REQ");
Daniel Willmannafce8662018-07-06 23:11:32 +0200710 mtc.stop;
Harald Weltea49e36e2018-01-21 19:29:33 +0100711 }
Daniel Willmannafce8662018-07-06 23:11:32 +0200712 [] T.timeout {
713 setverdict(fail, "Timeout waiting for CM SERV REQ");
714 mtc.stop;
715 }
Harald Weltef6dd64d2017-11-19 12:09:51 +0100716 }
717
Harald Welte1ddc7162018-01-27 14:25:46 +0100718 f_expect_clear();
Harald Weltef6dd64d2017-11-19 12:09:51 +0100719}
Harald Weltea49e36e2018-01-21 19:29:33 +0100720testcase TC_cmserv_imsi_unknown() runs on MTC_CT {
721 var BSC_ConnHdlr vc_conn;
722 f_init();
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +0100723 vc_conn := f_start_handler(refers(f_tc_cmserv_imsi_unknown), 6);
Harald Weltea49e36e2018-01-21 19:29:33 +0100724 vc_conn.done;
725}
726
Harald Weltee13cfb22019-04-23 16:52:02 +0200727
728friend function f_tc_lu_and_mo_call(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +0100729 f_init_handler(pars);
Harald Welteb71901a2018-01-26 19:16:05 +0100730 var CallParameters cpars := valueof(t_CallParams('12345'H, 0));
731 cpars.bss_rtp_port := 1110;
732 cpars.mgcp_connection_id_bss := '22222'H;
733 cpars.mgcp_connection_id_mss := '33333'H;
Philipp Maierf1e02bb2018-03-15 16:30:00 +0100734 cpars.mgcp_ep := "rtpbridge/1@mgw";
Harald Welte2bb825f2018-01-22 11:31:18 +0100735
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +0100736 f_perform_lu();
Harald Welteb71901a2018-01-26 19:16:05 +0100737 f_mo_call(cpars);
Harald Welte2bb825f2018-01-22 11:31:18 +0100738}
739testcase TC_lu_and_mo_call() runs on MTC_CT {
740 var BSC_ConnHdlr vc_conn;
741 f_init();
742
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +0100743 vc_conn := f_start_handler(refers(f_tc_lu_and_mo_call), 7);
Harald Welte071ed732018-01-23 19:53:52 +0100744 vc_conn.done;
745}
746
Harald Weltee13cfb22019-04-23 16:52:02 +0200747
Harald Welte071ed732018-01-23 19:53:52 +0100748/* Test LU (with authentication enabled), where HLR times out sending SAI response */
Harald Weltee13cfb22019-04-23 16:52:02 +0200749friend function f_tc_lu_auth_sai_timeout(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +0100750 f_init_handler(pars);
Harald Welte071ed732018-01-23 19:53:52 +0100751
752 var PDU_ML3_MS_NW l3_lu := f_build_lu_imsi(g_pars.imsi)
753 var PDU_DTAP_MT dtap_mt;
754
755 /* tell GSUP dispatcher to send this IMSI to us */
756 f_create_gsup_expect(hex2str(g_pars.imsi));
757
758 /* Send BSSAP_Conn_Req with COMPL L3 INFO to MSC */
Harald Weltedceacc72019-04-21 20:58:35 +0200759 f_cl3_or_initial_ue(l3_lu);
Harald Welte071ed732018-01-23 19:53:52 +0100760
761 /* Send Early Classmark, just for the fun of it */
Harald Weltee13cfb22019-04-23 16:52:02 +0200762 if (pars.ran_is_geran) {
763 BSSAP.send(ts_BSSMAP_ClassmarkUpd(g_pars.cm2, g_pars.cm3));
764 }
Harald Welte071ed732018-01-23 19:53:52 +0100765
766 GSUP.receive(tr_GSUP_SAI_REQ(g_pars.imsi));
767 /* The HLR would normally return an auth vector here, but we fail to do so. */
768
769 BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Rej));
Harald Welte1ddc7162018-01-27 14:25:46 +0100770 f_expect_clear();
Harald Welte071ed732018-01-23 19:53:52 +0100771}
772testcase TC_lu_auth_sai_timeout() runs on MTC_CT {
773 var BSC_ConnHdlr vc_conn;
774 f_init();
Harald Welte3ca1c902018-01-24 18:51:27 +0100775 f_vty_config(MSCVTY, "network", "authentication required");
Harald Welte071ed732018-01-23 19:53:52 +0100776
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +0100777 vc_conn := f_start_handler(refers(f_tc_lu_auth_sai_timeout), 8);
Harald Welte071ed732018-01-23 19:53:52 +0100778 vc_conn.done;
779}
780
Harald Weltee13cfb22019-04-23 16:52:02 +0200781
Harald Welte071ed732018-01-23 19:53:52 +0100782/* Test LU (with authentication enabled), where HLR rejects sending SAI error */
Harald Weltee13cfb22019-04-23 16:52:02 +0200783friend function f_tc_lu_auth_sai_err(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +0100784 f_init_handler(pars);
Harald Welte071ed732018-01-23 19:53:52 +0100785
786 var PDU_ML3_MS_NW l3_lu := f_build_lu_imsi(g_pars.imsi)
787 var PDU_DTAP_MT dtap_mt;
788
789 /* tell GSUP dispatcher to send this IMSI to us */
790 f_create_gsup_expect(hex2str(g_pars.imsi));
791
792 /* Send BSSAP_Conn_Req with COMPL L3 INFO to MSC */
Harald Weltedceacc72019-04-21 20:58:35 +0200793 f_cl3_or_initial_ue(l3_lu);
Harald Welte071ed732018-01-23 19:53:52 +0100794
795 /* Send Early Classmark, just for the fun of it */
Harald Weltee13cfb22019-04-23 16:52:02 +0200796 if (pars.ran_is_geran) {
797 BSSAP.send(ts_BSSMAP_ClassmarkUpd(g_pars.cm2, g_pars.cm3));
798 }
Harald Welte071ed732018-01-23 19:53:52 +0100799
800 GSUP.receive(tr_GSUP_SAI_REQ(g_pars.imsi));
801 GSUP.send(ts_GSUP_SAI_ERR(g_pars.imsi, 13));
802
803 BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Rej));
Harald Welte1ddc7162018-01-27 14:25:46 +0100804 f_expect_clear();
Harald Welte071ed732018-01-23 19:53:52 +0100805}
806testcase TC_lu_auth_sai_err() runs on MTC_CT {
807 var BSC_ConnHdlr vc_conn;
808 f_init();
Harald Welte3ca1c902018-01-24 18:51:27 +0100809 f_vty_config(MSCVTY, "network", "authentication required");
Harald Welte071ed732018-01-23 19:53:52 +0100810
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +0100811 vc_conn := f_start_handler(refers(f_tc_lu_auth_sai_err), 9);
Harald Welte2bb825f2018-01-22 11:31:18 +0100812 vc_conn.done;
813}
Harald Weltea49e36e2018-01-21 19:29:33 +0100814
Harald Weltee13cfb22019-04-23 16:52:02 +0200815
Harald Weltebc881782018-01-23 20:09:15 +0100816/* Test LU but BSC will send a clear request in the middle */
817private function f_tc_lu_clear_request(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +0100818 f_init_handler(pars);
Harald Weltebc881782018-01-23 20:09:15 +0100819
820 var PDU_ML3_MS_NW l3_lu := f_build_lu_imsi(g_pars.imsi)
821 var PDU_DTAP_MT dtap_mt;
822
823 /* tell GSUP dispatcher to send this IMSI to us */
824 f_create_gsup_expect(hex2str(g_pars.imsi));
825
826 /* Send BSSAP_Conn_Req with COMPL L3 INFO to MSC */
Harald Weltedceacc72019-04-21 20:58:35 +0200827 f_cl3_or_initial_ue(l3_lu);
Harald Weltebc881782018-01-23 20:09:15 +0100828
829 /* Send Early Classmark, just for the fun of it */
830 BSSAP.send(ts_BSSMAP_ClassmarkUpd(g_pars.cm2, g_pars.cm3));
831
832 f_sleep(1.0);
833 /* send clear request in the middle of the LU */
834 BSSAP.send(ts_BSSMAP_ClearRequest(0));
Neels Hofmeyr2b326fa2018-04-06 00:59:36 +0200835 alt {
836 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Rej)) { repeat; }
837 [] BSSAP.receive(tr_BSSMAP_ClearCommand) {}
838 }
Harald Weltebc881782018-01-23 20:09:15 +0100839 BSSAP.send(ts_BSSMAP_ClearComplete);
Harald Welte89a32492018-01-27 19:07:28 +0100840 alt {
841 /* See https://osmocom.org/issues/2862 */
Neels Hofmeyr2b326fa2018-04-06 00:59:36 +0200842 [] BSSAP.receive(tr_BSSMAP_ClearCommand) {
843 setverdict(fail, "Got a second Clear Command, only one expected");
Daniel Willmannafce8662018-07-06 23:11:32 +0200844 mtc.stop;
Neels Hofmeyr2b326fa2018-04-06 00:59:36 +0200845 repeat;
846 }
Harald Welte6811d102019-04-14 22:23:14 +0200847 [] BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_IND) {}
Harald Welte89a32492018-01-27 19:07:28 +0100848 }
Harald Weltebc881782018-01-23 20:09:15 +0100849 setverdict(pass);
850}
851testcase TC_lu_clear_request() runs on MTC_CT {
852 var BSC_ConnHdlr vc_conn;
853 f_init();
854
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +0100855 vc_conn := f_start_handler(refers(f_tc_lu_clear_request), 10);
Harald Weltebc881782018-01-23 20:09:15 +0100856 vc_conn.done;
857}
858
Harald Welte66af9e62018-01-24 17:28:21 +0100859/* Test LU but BSC will send a clear request in the middle */
Harald Weltee13cfb22019-04-23 16:52:02 +0200860friend function f_tc_lu_disconnect(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +0100861 f_init_handler(pars);
Harald Welte66af9e62018-01-24 17:28:21 +0100862
863 var PDU_ML3_MS_NW l3_lu := f_build_lu_imsi(g_pars.imsi)
864 var PDU_DTAP_MT dtap_mt;
865
866 /* tell GSUP dispatcher to send this IMSI to us */
867 f_create_gsup_expect(hex2str(g_pars.imsi));
868
869 /* Send BSSAP_Conn_Req with COMPL L3 INFO to MSC */
Harald Weltedceacc72019-04-21 20:58:35 +0200870 f_cl3_or_initial_ue(l3_lu);
Harald Welte66af9e62018-01-24 17:28:21 +0100871
872 /* Send Early Classmark, just for the fun of it */
Harald Weltee13cfb22019-04-23 16:52:02 +0200873 if (pars.ran_is_geran) {
874 BSSAP.send(ts_BSSMAP_ClassmarkUpd(g_pars.cm2, g_pars.cm3));
875 }
Harald Welte66af9e62018-01-24 17:28:21 +0100876
877 f_sleep(1.0);
878 /* send clear request in the middle of the LU */
Harald Welte6811d102019-04-14 22:23:14 +0200879 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
Harald Welte66af9e62018-01-24 17:28:21 +0100880 setverdict(pass);
Neels Hofmeyrbb825c92019-03-06 15:35:50 +0100881 f_sleep(1.0);
Harald Welte66af9e62018-01-24 17:28:21 +0100882}
883testcase TC_lu_disconnect() runs on MTC_CT {
884 var BSC_ConnHdlr vc_conn;
885 f_init();
886
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +0100887 vc_conn := f_start_handler(refers(f_tc_lu_disconnect), 11);
Harald Welte66af9e62018-01-24 17:28:21 +0100888 vc_conn.done;
889}
890
Harald Welteba7b6d92018-01-23 21:32:34 +0100891/* Test LU but with illegal mobile identity type = IMEI */
Harald Weltee13cfb22019-04-23 16:52:02 +0200892friend function f_tc_lu_by_imei(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +0100893 f_init_handler(pars);
Harald Welteba7b6d92018-01-23 21:32:34 +0100894
Harald Welte256571e2018-01-24 18:47:19 +0100895 var PDU_ML3_MS_NW l3_lu := f_build_lu_imei(g_pars.imei)
Harald Welteba7b6d92018-01-23 21:32:34 +0100896 var PDU_DTAP_MT dtap_mt;
897
898 /* tell GSUP dispatcher to send this IMSI to us */
899 f_create_gsup_expect(hex2str(g_pars.imsi));
900
901 /* Send BSSAP_Conn_Req with COMPL L3 INFO to MSC */
Harald Weltedceacc72019-04-21 20:58:35 +0200902 f_cl3_or_initial_ue(l3_lu);
Harald Welteba7b6d92018-01-23 21:32:34 +0100903
904 /* Send Early Classmark, just for the fun of it */
Harald Weltee13cfb22019-04-23 16:52:02 +0200905 if (pars.ran_is_geran) {
906 BSSAP.send(ts_BSSMAP_ClassmarkUpd(g_pars.cm2, g_pars.cm3));
907 }
Harald Welteba7b6d92018-01-23 21:32:34 +0100908 /* wait for LU reject, ignore any ID REQ */
909 alt {
910 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Rej)) { }
911 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_MM_ID_Req)) { repeat; }
912 }
913 /* wait for normal teardown */
Harald Welte1ddc7162018-01-27 14:25:46 +0100914 f_expect_clear();
Harald Welteba7b6d92018-01-23 21:32:34 +0100915}
916testcase TC_lu_by_imei() runs on MTC_CT {
917 var BSC_ConnHdlr vc_conn;
918 f_init();
919
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +0100920 vc_conn := f_start_handler(refers(f_tc_lu_by_imei), 12);
Harald Welteba7b6d92018-01-23 21:32:34 +0100921 vc_conn.done;
922}
923
Harald Weltee13cfb22019-04-23 16:52:02 +0200924
Harald Welteba7b6d92018-01-23 21:32:34 +0100925/* Test LU by TMSI with unknown TMSI, expect (and answer) ID REQ. */
926private function f_tc_lu_tmsi_noauth_unknown(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Stefan Sperling04fc4bc2018-06-25 17:44:57 +0200927 /* We piggyback a test for an MSC crash on overlong IMSI (OS#2864) onto this test. */
928 var hexstring overlong_imsi := '012345789ABCDEF0123456789ABCDEF'H;
Harald Weltea10db902018-01-27 12:44:49 +0100929 f_init_handler(pars);
Harald Welteba7b6d92018-01-23 21:32:34 +0100930
931 var PDU_ML3_MS_NW l3_lu := f_build_lu_tmsi('01020304'O); /* FIXME: Random */
932 var PDU_DTAP_MT dtap_mt;
933
934 /* tell GSUP dispatcher to send this IMSI to us */
935 f_create_gsup_expect(hex2str(g_pars.imsi));
936
937 /* Send BSSAP_Conn_Req with COMPL L3 INFO to MSC */
Harald Weltedceacc72019-04-21 20:58:35 +0200938 f_cl3_or_initial_ue(l3_lu);
Harald Welteba7b6d92018-01-23 21:32:34 +0100939
940 /* Send Early Classmark, just for the fun of it */
941 BSSAP.send(ts_BSSMAP_ClassmarkUpd(g_pars.cm2, g_pars.cm3));
942
943 /* Wait for + respond to ID REQ (IMSI) */
944 BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_MM_ID_Req('001'B)));
Stefan Sperling04fc4bc2018-06-25 17:44:57 +0200945 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 +0100946 BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_MM_ID_Rsp_IMSI(g_pars.imsi)));
947
948 /* Expect MSC to do UpdateLocation to HLR; respond to it */
949 GSUP.receive(tr_GSUP_UL_REQ(g_pars.imsi));
950 GSUP.send(ts_GSUP_ISD_REQ(g_pars.imsi, g_pars.msisdn));
951 GSUP.receive(tr_GSUP_ISD_RES(g_pars.imsi));
952 GSUP.send(ts_GSUP_UL_RES(g_pars.imsi));
953
954 alt {
Harald Welte7ec4fa82018-01-27 10:57:40 +0100955 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Acc)) {
956 BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_TmsiRealloc_Cmpl));
957 }
Harald Welteba7b6d92018-01-23 21:32:34 +0100958 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Rej)) {
959 setverdict(fail, "Expected LU ACK, but received REJ");
Daniel Willmannafce8662018-07-06 23:11:32 +0200960 mtc.stop;
Harald Welteba7b6d92018-01-23 21:32:34 +0100961 }
962 }
963
Philipp Maier9b690e42018-12-21 11:50:03 +0100964 /* Wait for MM-Information (if enabled) */
965 f_expect_mm_info();
966
Harald Welteba7b6d92018-01-23 21:32:34 +0100967 /* wait for normal teardown */
Harald Welte1ddc7162018-01-27 14:25:46 +0100968 f_expect_clear();
Harald Welteba7b6d92018-01-23 21:32:34 +0100969}
970testcase TC_lu_by_tmsi_noauth_unknown() runs on MTC_CT {
971 var BSC_ConnHdlr vc_conn;
972 f_init();
973
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +0100974 vc_conn := f_start_handler(refers(f_tc_lu_tmsi_noauth_unknown), 13);
Harald Welteba7b6d92018-01-23 21:32:34 +0100975 vc_conn.done;
976}
977
978
Harald Welte45164da2018-01-24 12:51:27 +0100979/* Test IMSI DETACH (MI=IMSI) */
Harald Weltee13cfb22019-04-23 16:52:02 +0200980friend function f_tc_imsi_detach_by_imsi(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +0100981 f_init_handler(pars);
Harald Welte45164da2018-01-24 12:51:27 +0100982
983 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
984
985 /* Send BSSAP_Conn_Req with COMPL L3 INFO to MSC */
Harald Weltedceacc72019-04-21 20:58:35 +0200986 f_cl3_or_initial_ue(valueof(ts_ML3_MO_MM_IMSI_DET_Ind(mi)));
Harald Welte45164da2018-01-24 12:51:27 +0100987
988 /* Send Early Classmark, just for the fun of it? */
Harald Weltee13cfb22019-04-23 16:52:02 +0200989 if (pars.ran_is_geran) {
990 BSSAP.send(ts_BSSMAP_ClassmarkUpd(g_pars.cm2, g_pars.cm3));
991 }
Harald Welte45164da2018-01-24 12:51:27 +0100992
993 /* wait for normal teardown */
Harald Welte1ddc7162018-01-27 14:25:46 +0100994 f_expect_clear();
Harald Welte45164da2018-01-24 12:51:27 +0100995}
996testcase TC_imsi_detach_by_imsi() runs on MTC_CT {
997 var BSC_ConnHdlr vc_conn;
998 f_init();
999
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001000 vc_conn := f_start_handler(refers(f_tc_imsi_detach_by_imsi), 14);
Harald Welte45164da2018-01-24 12:51:27 +01001001 vc_conn.done;
1002}
1003
Harald Weltee13cfb22019-04-23 16:52:02 +02001004
Harald Welte45164da2018-01-24 12:51:27 +01001005/* Test IMSI DETACH (MI=TMSI) */
Harald Weltee13cfb22019-04-23 16:52:02 +02001006friend function f_tc_imsi_detach_by_tmsi(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +01001007 f_init_handler(pars);
Harald Welte45164da2018-01-24 12:51:27 +01001008
1009 var MobileIdentityLV mi := valueof(ts_MI_TMSI_LV('01020304'O));
1010
1011 /* Send BSSAP_Conn_Req with COMPL L3 INFO to MSC */
Harald Weltedceacc72019-04-21 20:58:35 +02001012 f_cl3_or_initial_ue(valueof(ts_ML3_MO_MM_IMSI_DET_Ind(mi)));
Harald Welte45164da2018-01-24 12:51:27 +01001013
1014 /* Send Early Classmark, just for the fun of it? */
Harald Weltee13cfb22019-04-23 16:52:02 +02001015 if (pars.ran_is_geran) {
1016 BSSAP.send(ts_BSSMAP_ClassmarkUpd(g_pars.cm2, g_pars.cm3));
1017 }
Harald Welte45164da2018-01-24 12:51:27 +01001018
1019 /* wait for normal teardown */
Harald Welte1ddc7162018-01-27 14:25:46 +01001020 f_expect_clear();
Harald Welte45164da2018-01-24 12:51:27 +01001021}
1022testcase TC_imsi_detach_by_tmsi() runs on MTC_CT {
1023 var BSC_ConnHdlr vc_conn;
1024 f_init();
1025
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001026 vc_conn := f_start_handler(refers(f_tc_imsi_detach_by_tmsi), 15);
Harald Welte45164da2018-01-24 12:51:27 +01001027 vc_conn.done;
1028}
1029
Harald Weltee13cfb22019-04-23 16:52:02 +02001030
Harald Welte45164da2018-01-24 12:51:27 +01001031/* Test IMSI DETACH (MI=IMEI), which is illegal */
Harald Weltee13cfb22019-04-23 16:52:02 +02001032friend function f_tc_imsi_detach_by_imei(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +01001033 f_init_handler(pars);
Harald Welte45164da2018-01-24 12:51:27 +01001034
Harald Welte256571e2018-01-24 18:47:19 +01001035 var MobileIdentityLV mi := valueof(ts_MI_IMEI_LV(g_pars.imei));
Harald Welte45164da2018-01-24 12:51:27 +01001036
1037 /* Send BSSAP_Conn_Req with COMPL L3 INFO to MSC */
Harald Weltedceacc72019-04-21 20:58:35 +02001038 f_cl3_or_initial_ue(valueof(ts_ML3_MO_MM_IMSI_DET_Ind(mi)));
Harald Welte45164da2018-01-24 12:51:27 +01001039
1040 /* Send Early Classmark, just for the fun of it? */
Harald Weltee13cfb22019-04-23 16:52:02 +02001041 if (pars.ran_is_geran) {
1042 BSSAP.send(ts_BSSMAP_ClassmarkUpd(g_pars.cm2, g_pars.cm3));
1043 }
Harald Welte45164da2018-01-24 12:51:27 +01001044
1045 /* wait for normal teardown */
Harald Welte1ddc7162018-01-27 14:25:46 +01001046 f_expect_clear();
Harald Welte45164da2018-01-24 12:51:27 +01001047}
1048testcase TC_imsi_detach_by_imei() runs on MTC_CT {
1049 var BSC_ConnHdlr vc_conn;
1050 f_init();
1051
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001052 vc_conn := f_start_handler(refers(f_tc_imsi_detach_by_imei), 16);
Harald Welte45164da2018-01-24 12:51:27 +01001053 vc_conn.done;
1054}
1055
1056
1057/* helper function for an emergency call. caller passes in mobile identity to use */
1058private function f_emerg_call(MobileIdentityLV mi) runs on BSC_ConnHdlr {
Harald Welte0bef21e2018-02-10 09:48:23 +01001059 var CallParameters cpars := valueof(t_CallParams('112'H, 0));
1060 cpars.emergency := true;
Philipp Maierf1e02bb2018-03-15 16:30:00 +01001061 cpars.mgcp_ep := "rtpbridge/1@mgw";
Harald Welte45164da2018-01-24 12:51:27 +01001062
Harald Welte0bef21e2018-02-10 09:48:23 +01001063 f_mo_call(cpars);
Harald Welte45164da2018-01-24 12:51:27 +01001064}
1065
1066/* establish an emergency call by IMEI, no SIM inserted (and hence no IMSI) */
Harald Weltee13cfb22019-04-23 16:52:02 +02001067friend function f_tc_emerg_call_imei_reject(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +01001068 f_init_handler(pars);
Harald Welte45164da2018-01-24 12:51:27 +01001069
Harald Welte256571e2018-01-24 18:47:19 +01001070 var MobileIdentityLV mi := valueof(ts_MI_IMEI_LV(g_pars.imei));
Harald Welte6ed6bf92018-01-24 21:09:15 +01001071 var PDU_ML3_MS_NW l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_EMERG_CALL, mi));
Harald Weltedceacc72019-04-21 20:58:35 +02001072 f_cl3_or_initial_ue(l3_info);
Harald Welte45164da2018-01-24 12:51:27 +01001073 BSSAP.receive(tr_PDU_DTAP_MT(tr_CM_SERV_REJ('05'O)));
Harald Welte1ddc7162018-01-27 14:25:46 +01001074 f_expect_clear();
Harald Welte45164da2018-01-24 12:51:27 +01001075}
1076testcase TC_emerg_call_imei_reject() runs on MTC_CT {
1077 var BSC_ConnHdlr vc_conn;
1078 f_init();
1079
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001080 vc_conn := f_start_handler(refers(f_tc_emerg_call_imei_reject), 17);
Harald Welte45164da2018-01-24 12:51:27 +01001081 vc_conn.done;
1082}
1083
Harald Weltee13cfb22019-04-23 16:52:02 +02001084
Harald Welted5b91402018-01-24 18:48:16 +01001085/* establish an emergency call by IMSI, SIM inserted (and hence IMSI) */
Harald Weltee13cfb22019-04-23 16:52:02 +02001086friend function f_tc_emerg_call_imsi(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +01001087 f_init_handler(pars);
Harald Welte45164da2018-01-24 12:51:27 +01001088 /* First perform location update to ensure subscriber is known */
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +01001089 f_perform_lu();
Harald Welte45164da2018-01-24 12:51:27 +01001090 /* Then issue emergency call identified by IMSI */
1091 f_emerg_call(valueof(ts_MI_IMSI_LV(g_pars.imsi)));
1092}
1093testcase TC_emerg_call_imsi() runs on MTC_CT {
1094 var BSC_ConnHdlr vc_conn;
1095 f_init();
1096
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001097 vc_conn := f_start_handler(refers(f_tc_emerg_call_imsi), 18);
Harald Welte45164da2018-01-24 12:51:27 +01001098 vc_conn.done;
1099}
1100
Harald Weltee13cfb22019-04-23 16:52:02 +02001101
Harald Welte45164da2018-01-24 12:51:27 +01001102/* CM Service Request for VGCS -> reject */
1103private function f_tc_cm_serv_req_vgcs_reject(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +01001104 f_init_handler(pars);
Harald Welte45164da2018-01-24 12:51:27 +01001105
1106 /* First perform location update to ensure subscriber is known */
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +01001107 f_perform_lu();
Harald Welte45164da2018-01-24 12:51:27 +01001108
1109 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
Harald Welte6ed6bf92018-01-24 21:09:15 +01001110 var PDU_ML3_MS_NW l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_VGCS, mi));
Harald Weltedceacc72019-04-21 20:58:35 +02001111 f_cl3_or_initial_ue(l3_info);
Harald Welte45164da2018-01-24 12:51:27 +01001112 BSSAP.receive(tr_PDU_DTAP_MT(tr_CM_SERV_REJ(int2oct(32,1))));
Harald Welte1ddc7162018-01-27 14:25:46 +01001113 f_expect_clear();
Harald Welte45164da2018-01-24 12:51:27 +01001114}
1115testcase TC_cm_serv_req_vgcs_reject() runs on MTC_CT {
1116 var BSC_ConnHdlr vc_conn;
1117 f_init();
1118
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001119 vc_conn := f_start_handler(refers(f_tc_cm_serv_req_vgcs_reject), 19);
Harald Welte45164da2018-01-24 12:51:27 +01001120 vc_conn.done;
1121}
1122
1123/* CM Service Request for VBS -> reject */
1124private function f_tc_cm_serv_req_vbs_reject(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +01001125 f_init_handler(pars);
Harald Welte45164da2018-01-24 12:51:27 +01001126
1127 /* First perform location update to ensure subscriber is known */
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +01001128 f_perform_lu();
Harald Welte45164da2018-01-24 12:51:27 +01001129
1130 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
Harald Welte6ed6bf92018-01-24 21:09:15 +01001131 var PDU_ML3_MS_NW l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_VBS, mi));
Harald Weltedceacc72019-04-21 20:58:35 +02001132 f_cl3_or_initial_ue(l3_info);
Harald Welte45164da2018-01-24 12:51:27 +01001133 BSSAP.receive(tr_PDU_DTAP_MT(tr_CM_SERV_REJ(int2oct(32,1))));
Harald Welte1ddc7162018-01-27 14:25:46 +01001134 f_expect_clear();
Harald Welte45164da2018-01-24 12:51:27 +01001135}
1136testcase TC_cm_serv_req_vbs_reject() runs on MTC_CT {
1137 var BSC_ConnHdlr vc_conn;
1138 f_init();
1139
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001140 vc_conn := f_start_handler(refers(f_tc_cm_serv_req_vbs_reject), 20);
Harald Welte45164da2018-01-24 12:51:27 +01001141 vc_conn.done;
1142}
1143
1144/* CM Service Request for LCS -> reject */
1145private function f_tc_cm_serv_req_lcs_reject(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +01001146 f_init_handler(pars);
Harald Welte45164da2018-01-24 12:51:27 +01001147
1148 /* First perform location update to ensure subscriber is known */
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +01001149 f_perform_lu();
Harald Welte45164da2018-01-24 12:51:27 +01001150
1151 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
Harald Welte6ed6bf92018-01-24 21:09:15 +01001152 var PDU_ML3_MS_NW l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_LCS, mi));
Harald Weltedceacc72019-04-21 20:58:35 +02001153 f_cl3_or_initial_ue(l3_info);
Harald Welte45164da2018-01-24 12:51:27 +01001154 BSSAP.receive(tr_PDU_DTAP_MT(tr_CM_SERV_REJ(int2oct(32,1))));
Harald Welte1ddc7162018-01-27 14:25:46 +01001155 f_expect_clear();
Harald Welte45164da2018-01-24 12:51:27 +01001156}
1157testcase TC_cm_serv_req_lcs_reject() runs on MTC_CT {
1158 var BSC_ConnHdlr vc_conn;
1159 f_init();
1160
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001161 vc_conn := f_start_handler(refers(f_tc_cm_serv_req_lcs_reject), 21);
Harald Welte45164da2018-01-24 12:51:27 +01001162 vc_conn.done;
1163}
1164
Harald Welte0195ab12018-01-24 21:50:20 +01001165/* CM Re-Establishment Request */
1166private function f_tc_cm_reest_req_reject(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +01001167 f_init_handler(pars);
Harald Welte0195ab12018-01-24 21:50:20 +01001168
1169 /* First perform location update to ensure subscriber is known */
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +01001170 f_perform_lu();
Harald Welte0195ab12018-01-24 21:50:20 +01001171
1172 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
1173 var PDU_ML3_MS_NW l3_info := valueof(ts_CM_REEST_REQ(0, mi));
Harald Weltedceacc72019-04-21 20:58:35 +02001174 f_cl3_or_initial_ue(l3_info);
Harald Welte0195ab12018-01-24 21:50:20 +01001175 BSSAP.receive(tr_PDU_DTAP_MT(tr_CM_SERV_REJ(int2oct(32,1))));
Harald Welte1ddc7162018-01-27 14:25:46 +01001176 f_expect_clear();
Harald Welte0195ab12018-01-24 21:50:20 +01001177}
1178testcase TC_cm_reest_req_reject() runs on MTC_CT {
1179 var BSC_ConnHdlr vc_conn;
1180 f_init();
Harald Welte0195ab12018-01-24 21:50:20 +01001181
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001182 vc_conn := f_start_handler(refers(f_tc_cm_reest_req_reject), 22);
Harald Welte0195ab12018-01-24 21:50:20 +01001183 vc_conn.done;
1184}
1185
Harald Weltec638f4d2018-01-24 22:00:36 +01001186/* Test LU (with authentication enabled), with wrong response from MS */
1187private function f_tc_lu_auth_2G_fail(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +01001188 f_init_handler(pars);
Harald Weltec638f4d2018-01-24 22:00:36 +01001189
1190 var PDU_ML3_MS_NW l3_lu := f_build_lu_imsi(g_pars.imsi)
1191
1192 /* tell GSUP dispatcher to send this IMSI to us */
1193 f_create_gsup_expect(hex2str(g_pars.imsi));
1194
1195 /* Send BSSAP_Conn_Req with COMPL L3 INFO to MSC */
Harald Weltedceacc72019-04-21 20:58:35 +02001196 f_cl3_or_initial_ue(l3_lu);
Harald Weltec638f4d2018-01-24 22:00:36 +01001197
1198 /* Send Early Classmark, just for the fun of it */
1199 BSSAP.send(ts_BSSMAP_ClassmarkUpd(g_pars.cm2, g_pars.cm3));
1200
1201 var AuthVector vec := f_gen_auth_vec_2g();
1202 var GSUP_IE auth_tuple := valueof(ts_GSUP_IE_AuthTuple2G(vec.rand, vec.sres, vec.kc));
1203 GSUP.receive(tr_GSUP_SAI_REQ(g_pars.imsi));
1204 GSUP.send(ts_GSUP_SAI_RES(g_pars.imsi, auth_tuple));
1205
1206 BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_MM_AUTH_REQ(vec.rand)));
1207 /* Send back wrong auth response */
1208 BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MT_MM_AUTH_RESP_2G('00000000'O)));
1209
1210 /* Expect GSUP AUTH FAIL REP to HLR */
1211 GSUP.receive(tr_GSUP_AUTH_FAIL_IND(g_pars.imsi));
1212
1213 /* Expect LU REJECT with Cause == Illegal MS */
1214 BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Rej('03'O)));
Harald Welte1ddc7162018-01-27 14:25:46 +01001215 f_expect_clear();
Harald Weltec638f4d2018-01-24 22:00:36 +01001216}
1217testcase TC_lu_auth_2G_fail() runs on MTC_CT {
1218 var BSC_ConnHdlr vc_conn;
1219 f_init();
1220 f_vty_config(MSCVTY, "network", "authentication required");
Harald Weltec638f4d2018-01-24 22:00:36 +01001221
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001222 vc_conn := f_start_handler(refers(f_tc_lu_auth_2G_fail), 23);
Harald Weltec638f4d2018-01-24 22:00:36 +01001223 vc_conn.done;
1224}
1225
Harald Weltede371492018-01-27 23:44:41 +01001226/* A5/1 + A5/3 permitted on network side, and MS capable to do it */
Harald Welte16114282018-01-24 22:41:21 +01001227private 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 +01001228 pars.net.expect_auth := true;
1229 pars.net.expect_ciph := true;
Harald Weltea10db902018-01-27 12:44:49 +01001230 f_init_handler(pars);
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +01001231 f_perform_lu();
Harald Welte16114282018-01-24 22:41:21 +01001232}
1233testcase TC_lu_imsi_auth_tmsi_encr_13_13() runs on MTC_CT {
1234 var BSC_ConnHdlr vc_conn;
1235 f_init();
1236 f_vty_config(MSCVTY, "network", "authentication required");
Harald Welte16114282018-01-24 22:41:21 +01001237 f_vty_config(MSCVTY, "network", "encryption a5 1 3");
1238
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001239 vc_conn := f_start_handler(refers(f_tc_lu_imsi_auth_tmsi_encr_13_13), 24);
Harald Welte16114282018-01-24 22:41:21 +01001240 vc_conn.done;
1241}
1242
Harald Welte1af6ea82018-01-25 18:33:15 +01001243/* Test Complete L3 without payload */
1244private function f_tc_cl3_no_payload(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +01001245 f_init_handler(pars);
Harald Welte1af6ea82018-01-25 18:33:15 +01001246
1247 /* Send Complete L3 Info with empty L3 frame */
1248 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_peer, g_pars.sccp_addr_own,
1249 valueof(ts_BSSMAP_ComplL3(g_pars.cell_id, ''O))));
1250
Harald Weltef466eb42018-01-27 14:26:54 +01001251 timer T := 5.0;
1252 T.start;
Harald Welte1af6ea82018-01-25 18:33:15 +01001253 alt {
Harald Welte6811d102019-04-14 22:23:14 +02001254 [] BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_IND) {}
Harald Welte1af6ea82018-01-25 18:33:15 +01001255 /* Expect LU REJECT with Cause == Illegal MS */
Harald Weltebdb3c452018-03-18 22:43:06 +01001256 [] BSSAP.receive(tr_PDU_DTAP_MT(?)) { repeat; }
Harald Welte6811d102019-04-14 22:23:14 +02001257 [] BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND) { repeat; }
Harald Welte5946b332018-03-18 23:32:21 +01001258 [] as_clear_cmd_compl_disc();
Harald Weltef466eb42018-01-27 14:26:54 +01001259 [] T.timeout {
Daniel Willmann90829d62018-02-15 17:45:14 +01001260 setverdict(fail, "Timeout waiting for ClearCommand or SCCP Release");
Daniel Willmannafce8662018-07-06 23:11:32 +02001261 mtc.stop;
Harald Weltef466eb42018-01-27 14:26:54 +01001262 }
Harald Welte1af6ea82018-01-25 18:33:15 +01001263 }
1264 setverdict(pass);
1265}
1266testcase TC_cl3_no_payload() runs on MTC_CT {
1267 var BSC_ConnHdlr vc_conn;
1268 f_init();
1269
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001270 vc_conn := f_start_handler(refers(f_tc_cl3_no_payload), 25);
Harald Welte1af6ea82018-01-25 18:33:15 +01001271 vc_conn.done;
1272}
1273
1274/* Test Complete L3 with random payload */
1275private function f_tc_cl3_rnd_payload(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +01001276 f_init_handler(pars);
Harald Welte1af6ea82018-01-25 18:33:15 +01001277
Daniel Willmannaa14a382018-07-26 08:29:45 +02001278 /* length is limited by PDU_BSSAP length field which includes some
1279 * other fields beside l3info payload. So payl can only be 240 bytes
1280 * Since rnd() returns values < 1 multiply with 241
1281 */
1282 var integer len := float2int(rnd() * 241.0);
Harald Welte1af6ea82018-01-25 18:33:15 +01001283 var octetstring payl := f_rnd_octstring(len);
1284
1285 /* Send Complete L3 Info with empty L3 frame */
1286 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_peer, g_pars.sccp_addr_own,
1287 valueof(ts_BSSMAP_ComplL3(g_pars.cell_id, payl))));
1288
Harald Weltef466eb42018-01-27 14:26:54 +01001289 timer T := 5.0;
1290 T.start;
Harald Welte1af6ea82018-01-25 18:33:15 +01001291 alt {
1292 /* Immediate disconnect */
Harald Welte6811d102019-04-14 22:23:14 +02001293 [] BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_IND) {}
Harald Welte1af6ea82018-01-25 18:33:15 +01001294 [] BSSAP.receive(tr_PDU_DTAP_MT(?)) { repeat; }
Harald Welte6811d102019-04-14 22:23:14 +02001295 [] BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND) { repeat; }
Harald Welte5946b332018-03-18 23:32:21 +01001296 [] as_clear_cmd_compl_disc();
Harald Weltef466eb42018-01-27 14:26:54 +01001297 [] T.timeout {
Daniel Willmann90829d62018-02-15 17:45:14 +01001298 setverdict(fail, "Timeout waiting for ClearCommand or SCCP Release");
Daniel Willmannafce8662018-07-06 23:11:32 +02001299 mtc.stop;
Harald Weltef466eb42018-01-27 14:26:54 +01001300 }
Harald Welte1af6ea82018-01-25 18:33:15 +01001301 }
1302 setverdict(pass);
1303}
1304testcase TC_cl3_rnd_payload() runs on MTC_CT {
1305 var BSC_ConnHdlr vc_conn;
1306 f_init();
1307
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001308 vc_conn := f_start_handler(refers(f_tc_cl3_rnd_payload), 26);
Harald Welte1af6ea82018-01-25 18:33:15 +01001309 vc_conn.done;
1310}
1311
Harald Welte116e4332018-01-26 22:17:48 +01001312/* Test Complete L3 with random payload */
Harald Weltee13cfb22019-04-23 16:52:02 +02001313friend function f_tc_establish_and_nothing(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +01001314 f_init_handler(pars);
Harald Welte116e4332018-01-26 22:17:48 +01001315
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +01001316 f_perform_lu();
Harald Welte116e4332018-01-26 22:17:48 +01001317
Harald Welteb9e86fa2018-04-09 18:18:31 +02001318 f_establish_fully();
Daniel Willmann898a7e02018-05-17 12:16:16 +02001319 f_expect_clear(10.0);
Harald Welte116e4332018-01-26 22:17:48 +01001320}
1321testcase TC_establish_and_nothing() runs on MTC_CT {
1322 var BSC_ConnHdlr vc_conn;
1323 f_init();
1324
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001325 vc_conn := f_start_handler(refers(f_tc_establish_and_nothing), 27);
Harald Welte116e4332018-01-26 22:17:48 +01001326 vc_conn.done;
1327}
1328
Harald Weltee13cfb22019-04-23 16:52:02 +02001329
Harald Welte12510c52018-01-26 22:26:24 +01001330/* Test MO Call SETUP with no response from MNCC */
Harald Weltee13cfb22019-04-23 16:52:02 +02001331friend function f_tc_mo_setup_and_nothing(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Philipp Maier109e6aa2018-10-17 10:53:32 +02001332 f_init_handler(pars, 190.0);
Harald Weltea10db902018-01-27 12:44:49 +01001333
Harald Welte12510c52018-01-26 22:26:24 +01001334 var CallParameters cpars := valueof(t_CallParams('12345'H, 0));
1335
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +01001336 f_perform_lu();
Harald Welte12510c52018-01-26 22:26:24 +01001337
Harald Welteb9e86fa2018-04-09 18:18:31 +02001338 f_establish_fully();
Harald Welte12510c52018-01-26 22:26:24 +01001339 f_create_mncc_expect(hex2str(cpars.called_party));
1340 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
1341
1342 BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_CC_SETUP(cpars.transaction_id, cpars.called_party)));
1343
Neels Hofmeyrde76f052019-02-26 05:02:46 +01001344 var default ccrel := activate(as_optional_cc_rel(cpars));
1345
Philipp Maier109e6aa2018-10-17 10:53:32 +02001346 f_expect_clear(185.0);
Neels Hofmeyrde76f052019-02-26 05:02:46 +01001347
1348 deactivate(ccrel);
1349
1350 f_sleep(1.0);
Harald Welte12510c52018-01-26 22:26:24 +01001351}
1352testcase TC_mo_setup_and_nothing() runs on MTC_CT {
1353 var BSC_ConnHdlr vc_conn;
1354 f_init();
1355
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001356 vc_conn := f_start_handler(refers(f_tc_mo_setup_and_nothing), 28);
Harald Welte12510c52018-01-26 22:26:24 +01001357 vc_conn.done;
1358}
1359
Harald Weltee13cfb22019-04-23 16:52:02 +02001360
Harald Welte3ab88002018-01-26 22:37:25 +01001361/* Test MO Call with no response to RAN-side CRCX */
Harald Weltee13cfb22019-04-23 16:52:02 +02001362friend function f_tc_mo_crcx_ran_timeout(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +01001363 f_init_handler(pars);
Harald Welte3ab88002018-01-26 22:37:25 +01001364 var CallParameters cpars := valueof(t_CallParams('12345'H, 0));
1365 var MNCC_PDU mncc;
1366 var MgcpCommand mgcp_cmd;
1367
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +01001368 f_perform_lu();
Harald Welte3ab88002018-01-26 22:37:25 +01001369
Harald Welteb9e86fa2018-04-09 18:18:31 +02001370 f_establish_fully();
Harald Welte3ab88002018-01-26 22:37:25 +01001371 f_create_mncc_expect(hex2str(cpars.called_party));
1372 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
1373
1374 BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_CC_SETUP(cpars.transaction_id, cpars.called_party)));
1375 MNCC.receive(tr_MNCC_SETUP_ind(?, tr_MNCC_number(hex2str(cpars.called_party)))) -> value mncc;
1376 cpars.mncc_callref := mncc.u.signal.callref;
1377 MNCC.send(ts_MNCC_CALL_PROC_req(cpars.mncc_callref, cpars.mncc_bearer_cap));
1378 BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_CC_CALL_PROC(cpars.transaction_id)));
1379
1380 MGCP.receive(tr_CRCX) -> value mgcp_cmd;
Harald Welte1852a842018-01-26 22:53:36 +01001381 cpars.mgcp_call_id := f_MgcpCmd_extract_call_id(mgcp_cmd);
1382 cpars.mgcp_ep := mgcp_cmd.line.ep;
Harald Welte3ab88002018-01-26 22:37:25 +01001383 /* never respond to this */
1384
Philipp Maier8e58f592018-03-14 11:10:56 +01001385 /* When the connection with the MGW fails, the MSC will first request
1386 * a release via call control. We will answer this request normally. */
1387 BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_CC_RELEASE(cpars.transaction_id)));
1388 BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_CC_REL_COMPL(cpars.transaction_id)));
1389
Harald Welte1ddc7162018-01-27 14:25:46 +01001390 f_expect_clear(30.0);
Harald Welte3ab88002018-01-26 22:37:25 +01001391}
1392testcase TC_mo_crcx_ran_timeout() runs on MTC_CT {
1393 var BSC_ConnHdlr vc_conn;
1394 f_init();
1395
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001396 vc_conn := f_start_handler(refers(f_tc_mo_crcx_ran_timeout), 29);
Harald Welte3ab88002018-01-26 22:37:25 +01001397 vc_conn.done;
1398}
1399
Harald Weltee13cfb22019-04-23 16:52:02 +02001400
Harald Welte0cc82d92018-01-26 22:52:34 +01001401/* Test MO Call with reject to RAN-side CRCX */
Harald Weltee13cfb22019-04-23 16:52:02 +02001402friend function f_tc_mo_crcx_ran_reject(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +01001403 f_init_handler(pars);
Harald Welte0cc82d92018-01-26 22:52:34 +01001404 var CallParameters cpars := valueof(t_CallParams('12345'H, 0));
1405 var MNCC_PDU mncc;
1406 var MgcpCommand mgcp_cmd;
1407
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +01001408 f_perform_lu();
Harald Welte0cc82d92018-01-26 22:52:34 +01001409
Harald Welteb9e86fa2018-04-09 18:18:31 +02001410 f_establish_fully();
Harald Welte0cc82d92018-01-26 22:52:34 +01001411 f_create_mncc_expect(hex2str(cpars.called_party));
1412 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
1413
1414 BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_CC_SETUP(cpars.transaction_id, cpars.called_party)));
1415 MNCC.receive(tr_MNCC_SETUP_ind(?, tr_MNCC_number(hex2str(cpars.called_party)))) -> value mncc;
1416 cpars.mncc_callref := mncc.u.signal.callref;
1417 MNCC.send(ts_MNCC_CALL_PROC_req(cpars.mncc_callref, cpars.mncc_bearer_cap));
1418 BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_CC_CALL_PROC(cpars.transaction_id)));
1419
1420 MGCP.receive(tr_CRCX) -> value mgcp_cmd;
Philipp Maierf1e02bb2018-03-15 16:30:00 +01001421
1422 /* Detect if the received CRCX is a wildcarded CRCX request. If yes,
1423 * set an endpoint name that fits the pattern. If not, just use the
1424 * endpoint name from the request */
1425 if (match(mgcp_cmd.line.ep, t_MGCP_EP_wildcard)) {
1426 cpars.mgcp_ep := "rtpbridge/1@mgw";
1427 } else {
1428 cpars.mgcp_ep := mgcp_cmd.line.ep;
1429 }
1430
Harald Welte0cc82d92018-01-26 22:52:34 +01001431 cpars.mgcp_call_id := f_MgcpCmd_extract_call_id(mgcp_cmd);
Philipp Maierf1e02bb2018-03-15 16:30:00 +01001432
Harald Welte0cc82d92018-01-26 22:52:34 +01001433 /* Respond to CRCX with error */
1434 var MgcpResponse mgcp_rsp := {
1435 line := {
1436 code := "542",
1437 trans_id := mgcp_cmd.line.trans_id,
1438 string := "FORCED_FAIL"
1439 },
Harald Welte0cc82d92018-01-26 22:52:34 +01001440 sdp := omit
1441 }
Philipp Maierf1e02bb2018-03-15 16:30:00 +01001442 var MgcpParameter mgcp_rsp_param := {
1443 code := "Z",
1444 val := cpars.mgcp_ep
1445 };
1446 mgcp_rsp.params[0] := mgcp_rsp_param;
Harald Welte0cc82d92018-01-26 22:52:34 +01001447 MGCP.send(mgcp_rsp);
1448
1449 timer T := 30.0;
1450 T.start;
1451 alt {
Daniel Willmannafce8662018-07-06 23:11:32 +02001452 [] T.timeout {
1453 setverdict(fail, "Timeout waiting for channel release");
1454 mtc.stop;
1455 }
Daniel Willmann5868e622018-02-15 17:42:59 +01001456 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_CC_RELEASE(cpars.transaction_id))) {
1457 BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_CC_REL_COMPL(cpars.transaction_id)));
1458 repeat;
1459 }
Harald Welte0cc82d92018-01-26 22:52:34 +01001460 [] MNCC.receive { repeat; }
1461 [] GSUP.receive { repeat; }
Philipp Maierc6e06f72018-04-11 18:12:23 +02001462 /* Note: As we did not respond properly to the CRCX from the MSC we
1463 * expect the MSC to omit any further MGCP operation (At least in the
1464 * the current implementation, there is no recovery mechanism implemented
1465 * and a DLCX can not be performed as the MSC does not know a specific
1466 * endpoint yet. */
Daniel Willmannafce8662018-07-06 23:11:32 +02001467 [] MGCP.receive {
1468 setverdict(fail, "Unexpected MGCP message");
1469 mtc.stop;
1470 }
Harald Welte5946b332018-03-18 23:32:21 +01001471 [] as_clear_cmd_compl_disc();
Harald Welte0cc82d92018-01-26 22:52:34 +01001472 }
1473}
1474testcase TC_mo_crcx_ran_reject() runs on MTC_CT {
1475 var BSC_ConnHdlr vc_conn;
1476 f_init();
1477
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001478 vc_conn := f_start_handler(refers(f_tc_mo_crcx_ran_reject), 30);
Harald Welte0cc82d92018-01-26 22:52:34 +01001479 vc_conn.done;
1480}
1481
Harald Welte3ab88002018-01-26 22:37:25 +01001482
Harald Welte812f7a42018-01-27 00:49:18 +01001483/* helper function to start a MT call: MNCC SETUP; Paging; DChan est.; DTAP SETUP */
1484private function f_mt_call_start(inout CallParameters cpars) runs on BSC_ConnHdlr {
1485 var MNCC_PDU mncc;
1486 var MgcpCommand mgcp_cmd;
1487 var OCT4 tmsi;
1488
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +01001489 f_perform_lu();
Harald Welte812f7a42018-01-27 00:49:18 +01001490 if (isvalue(g_pars.tmsi)) {
1491 tmsi := g_pars.tmsi;
1492 } else {
1493 tmsi := 'FFFFFFFF'O;
1494 }
Harald Welte6811d102019-04-14 22:23:14 +02001495 f_ran_register_imsi(g_pars.imsi, tmsi);
Harald Welte812f7a42018-01-27 00:49:18 +01001496
1497 /* Allocate call reference and send SETUP via MNCC to MSC */
1498 cpars.mncc_callref := f_rnd_int(2147483648);
1499 MNCC.send(ts_MNCC_SETUP_req(cpars.mncc_callref, hex2str(g_pars.msisdn),
1500 hex2str(cpars.called_party), hex2str(g_pars.imsi)));
1501
1502 /* MSC->BSC: expect PAGING from MSC */
Harald Weltee035e3e2019-04-21 17:32:05 +02001503 f_expect_paging();
1504
Harald Welte812f7a42018-01-27 00:49:18 +01001505 /* MS -> MSC: PAGING RESPONSE */
Harald Welteb9e86fa2018-04-09 18:18:31 +02001506 f_establish_fully(EST_TYPE_PAG_RESP);
Harald Welte812f7a42018-01-27 00:49:18 +01001507
1508 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
1509
1510 /* MSC->MS: SETUP */
1511 BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_CC_SETUP(cpars.transaction_id, *, cpars.called_party)));
1512}
1513
1514/* Test MT Call */
Harald Weltee13cfb22019-04-23 16:52:02 +02001515friend function f_tc_mt_crcx_ran_reject(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +01001516 f_init_handler(pars);
Harald Welte812f7a42018-01-27 00:49:18 +01001517 var CallParameters cpars := valueof(t_CallParams('123456'H, 0));
1518 var MNCC_PDU mncc;
1519 var MgcpCommand mgcp_cmd;
1520
1521 f_mt_call_start(cpars);
1522
1523 /* MS->MSC: CALL CONFIRMED */
1524 BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_CC_CALL_CONF(cpars.transaction_id)));
1525
1526 MNCC.receive(tr_MNCC_CALL_CONF_ind(cpars.mncc_callref));
1527
1528 MGCP.receive(tr_CRCX) -> value mgcp_cmd;
1529 cpars.mgcp_call_id := f_MgcpCmd_extract_call_id(mgcp_cmd);
Philipp Maierf1e02bb2018-03-15 16:30:00 +01001530
1531 /* Detect if the received CRCX is a wildcarded CRCX request. If yes,
1532 * set an endpoint name that fits the pattern. If not, just use the
1533 * endpoint name from the request */
1534 if (match(mgcp_cmd.line.ep, t_MGCP_EP_wildcard)) {
1535 cpars.mgcp_ep := "rtpbridge/1@mgw";
1536 } else {
1537 cpars.mgcp_ep := mgcp_cmd.line.ep;
1538 }
1539
Harald Welte812f7a42018-01-27 00:49:18 +01001540 /* Respond to CRCX with error */
1541 var MgcpResponse mgcp_rsp := {
1542 line := {
1543 code := "542",
1544 trans_id := mgcp_cmd.line.trans_id,
1545 string := "FORCED_FAIL"
1546 },
Harald Welte812f7a42018-01-27 00:49:18 +01001547 sdp := omit
1548 }
Philipp Maierf1e02bb2018-03-15 16:30:00 +01001549 var MgcpParameter mgcp_rsp_param := {
1550 code := "Z",
1551 val := cpars.mgcp_ep
1552 };
1553 mgcp_rsp.params[0] := mgcp_rsp_param;
Harald Welte812f7a42018-01-27 00:49:18 +01001554 MGCP.send(mgcp_rsp);
1555
1556 timer T := 30.0;
1557 T.start;
1558 alt {
Daniel Willmannafce8662018-07-06 23:11:32 +02001559 [] T.timeout {
1560 setverdict(fail, "Timeout waiting for channel release");
1561 mtc.stop;
1562 }
Harald Welte812f7a42018-01-27 00:49:18 +01001563 [] MNCC.receive { repeat; }
1564 [] GSUP.receive { repeat; }
1565 [] MGCP.receive(tr_DLCX(?)) -> value mgcp_cmd {
1566 MGCP.send(ts_DLCX_ACK2(mgcp_cmd.line.trans_id));
1567 f_create_mgcp_delete_ep(cpars.mgcp_ep);
1568 repeat;
1569 }
1570 [] MGCP.receive { repeat; }
Harald Welte5946b332018-03-18 23:32:21 +01001571 [] as_clear_cmd_compl_disc();
Neels Hofmeyrde76f052019-02-26 05:02:46 +01001572 [] as_optional_cc_rel(cpars);
Harald Welte812f7a42018-01-27 00:49:18 +01001573 }
1574}
1575testcase TC_mt_crcx_ran_reject() runs on MTC_CT {
1576 var BSC_ConnHdlr vc_conn;
1577 f_init();
1578
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001579 vc_conn := f_start_handler(refers(f_tc_mt_crcx_ran_reject), 31);
Harald Welte812f7a42018-01-27 00:49:18 +01001580 vc_conn.done;
1581}
1582
1583
Harald Weltee13cfb22019-04-23 16:52:02 +02001584
Harald Welte812f7a42018-01-27 00:49:18 +01001585/* Test MT Call T310 timer */
Harald Weltee13cfb22019-04-23 16:52:02 +02001586friend function f_tc_mt_t310(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltead2952e2018-01-27 14:12:46 +01001587 f_init_handler(pars, 200.0);
Harald Welte812f7a42018-01-27 00:49:18 +01001588 var CallParameters cpars := valueof(t_CallParams('123456'H, 0));
1589 var MNCC_PDU mncc;
1590 var MgcpCommand mgcp_cmd;
1591
1592 f_mt_call_start(cpars);
1593
1594 /* MS->MSC: CALL CONFIRMED */
1595 BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_CC_CALL_CONF(cpars.transaction_id)));
1596 MNCC.receive(tr_MNCC_CALL_CONF_ind(cpars.mncc_callref));
1597
1598 MGCP.receive(tr_CRCX) -> value mgcp_cmd;
1599 cpars.mgcp_call_id := f_MgcpCmd_extract_call_id(mgcp_cmd);
1600 cpars.mgcp_ep := mgcp_cmd.line.ep;
1601 /* FIXME: Respond to CRCX */
1602
1603 /* old libosmocore T310 default timeout is 180s. so let's wait 190 */
1604 timer T := 190.0;
1605 T.start;
1606 alt {
Daniel Willmannafce8662018-07-06 23:11:32 +02001607 [] T.timeout {
1608 setverdict(fail, "Timeout waiting for T310");
1609 mtc.stop;
1610 }
Harald Welte812f7a42018-01-27 00:49:18 +01001611 [] MNCC.receive(tr_MNCC_DISC_ind(cpars.mncc_callref)) {
1612 MNCC.send(ts_MNCC_REL_req(cpars.mncc_callref, valueof(ts_MNCC_cause(23))));
1613 }
1614 }
1615 BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_CC_DISC(cpars.transaction_id)));
1616 BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_CC_RELEASE(cpars.transaction_id)));
1617 /* FIXME: We're sending this with TIflag 0: allocated by sender, which is wrong */
1618 BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_CC_REL_COMPL(cpars.transaction_id)));
1619
1620 alt {
Harald Welte812f7a42018-01-27 00:49:18 +01001621 [] MGCP.receive(tr_DLCX(?)) -> value mgcp_cmd {
1622 MGCP.send(ts_DLCX_ACK2(mgcp_cmd.line.trans_id));
1623 f_create_mgcp_delete_ep(cpars.mgcp_ep);
1624 repeat;
1625 }
Harald Welte5946b332018-03-18 23:32:21 +01001626 [] as_clear_cmd_compl_disc();
Harald Welte812f7a42018-01-27 00:49:18 +01001627 }
1628}
1629testcase TC_mt_t310() runs on MTC_CT {
1630 var BSC_ConnHdlr vc_conn;
1631 f_init();
1632
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001633 vc_conn := f_start_handler(refers(f_tc_mt_t310), 32);
Harald Welte812f7a42018-01-27 00:49:18 +01001634 vc_conn.done;
1635}
1636
Harald Weltee13cfb22019-04-23 16:52:02 +02001637
Harald Welte167458a2018-01-27 15:58:16 +01001638/* Perform successful LU + MO call, then GSUP LocationCancel. Subscriber must be denied CM SERV */
Harald Weltee13cfb22019-04-23 16:52:02 +02001639friend function f_tc_gsup_cancel(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Welte167458a2018-01-27 15:58:16 +01001640 f_init_handler(pars);
1641 var CallParameters cpars := valueof(t_CallParams('12345'H, 0));
1642 cpars.bss_rtp_port := 1110;
1643 cpars.mgcp_connection_id_bss := '22222'H;
1644 cpars.mgcp_connection_id_mss := '33333'H;
Daniel Willmann9b0235b2018-07-24 12:13:34 +02001645 cpars.mgcp_ep := "rtpbridge/1@mgw";
Harald Welte167458a2018-01-27 15:58:16 +01001646
1647 /* Location Update to make subscriber known */
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +01001648 f_perform_lu();
Harald Welte167458a2018-01-27 15:58:16 +01001649
1650 /* First MO call should succeed */
1651 f_mo_call(cpars);
1652
1653 /* Cancel the subscriber in the VLR */
1654 GSUP.send(ts_GSUP_CL_REQ(g_pars.imsi, OSMO_GSUP_CANCEL_TYPE_WITHDRAW));
1655 alt {
1656 [] GSUP.receive(tr_GSUP_CL_RES(g_pars.imsi)) { }
1657 [] GSUP.receive(tr_GSUP_CL_ERR(g_pars.imsi)) {
1658 setverdict(fail, "Received GSUP Location Cancel Error");
Daniel Willmannafce8662018-07-06 23:11:32 +02001659 mtc.stop;
Harald Welte167458a2018-01-27 15:58:16 +01001660 }
1661 }
1662
1663 /* Follow-up transactions should fail */
1664 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
1665 var PDU_ML3_MS_NW l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, mi));
Harald Weltedceacc72019-04-21 20:58:35 +02001666 f_cl3_or_initial_ue(l3_info);
Harald Welte167458a2018-01-27 15:58:16 +01001667 alt {
1668 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_CM_SERV_REJ)) { }
1669 [] BSSAP.receive {
1670 setverdict(fail, "Received unexpected BSSAP instead of CM SERV REJ");
Daniel Willmannafce8662018-07-06 23:11:32 +02001671 mtc.stop;
Harald Welte167458a2018-01-27 15:58:16 +01001672 }
1673 }
Neels Hofmeyr0f7429a2019-03-07 22:28:41 +01001674
1675 f_expect_clear();
Harald Welte167458a2018-01-27 15:58:16 +01001676 setverdict(pass);
1677}
1678testcase TC_gsup_cancel() runs on MTC_CT {
1679 var BSC_ConnHdlr vc_conn;
1680 f_init();
1681
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001682 vc_conn := f_start_handler(refers(f_tc_gsup_cancel), 33);
Harald Welte167458a2018-01-27 15:58:16 +01001683 vc_conn.done;
1684}
1685
Harald Weltee13cfb22019-04-23 16:52:02 +02001686
Harald Welte9de84792018-01-28 01:06:35 +01001687/* A5/1 only permitted on network side, and MS capable to do it */
1688private function f_tc_lu_imsi_auth_tmsi_encr_1_13(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
1689 pars.net.expect_auth := true;
1690 pars.net.expect_ciph := true;
1691 pars.net.kc_support := '02'O; /* A5/1 only */
1692 f_init_handler(pars);
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +01001693 f_perform_lu();
Harald Welte9de84792018-01-28 01:06:35 +01001694}
1695testcase TC_lu_imsi_auth_tmsi_encr_1_13() runs on MTC_CT {
1696 var BSC_ConnHdlr vc_conn;
1697 f_init();
1698 f_vty_config(MSCVTY, "network", "authentication required");
1699 f_vty_config(MSCVTY, "network", "encryption a5 1");
1700
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001701 vc_conn := f_start_handler(refers(f_tc_lu_imsi_auth_tmsi_encr_1_13), 34);
Harald Welte9de84792018-01-28 01:06:35 +01001702 vc_conn.done;
1703}
1704
1705/* A5/3 only permitted on network side, and MS capable to do it */
1706private function f_tc_lu_imsi_auth_tmsi_encr_3_13(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
1707 pars.net.expect_auth := true;
1708 pars.net.expect_ciph := true;
1709 pars.net.kc_support := '08'O; /* A5/3 only */
1710 f_init_handler(pars);
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +01001711 f_perform_lu();
Harald Welte9de84792018-01-28 01:06:35 +01001712}
1713testcase TC_lu_imsi_auth_tmsi_encr_3_13() runs on MTC_CT {
1714 var BSC_ConnHdlr vc_conn;
1715 f_init();
1716 f_vty_config(MSCVTY, "network", "authentication required");
1717 f_vty_config(MSCVTY, "network", "encryption a5 3");
1718
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001719 vc_conn := f_start_handler(refers(f_tc_lu_imsi_auth_tmsi_encr_3_13), 35);
Harald Welte9de84792018-01-28 01:06:35 +01001720 vc_conn.done;
1721}
1722
1723/* A5/3 only permitted on network side, and MS with only A5/1 support */
1724private function f_tc_lu_imsi_auth_tmsi_encr_3_1(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
1725 pars.net.expect_auth := true;
1726 pars.net.expect_ciph := true;
1727 pars.net.kc_support := '08'O; /* A5/3 only */
1728 pars.cm2.classmarkInformationType2_oct5.a5_3 := '0'B;
1729 f_init_handler(pars, 15.0);
1730
1731 /* cannot use f_perform_lu() as we expect a reject */
1732 var PDU_ML3_MS_NW l3_lu := f_build_lu_imsi(g_pars.imsi);
1733 f_create_gsup_expect(hex2str(g_pars.imsi));
Harald Weltedceacc72019-04-21 20:58:35 +02001734 f_cl3_or_initial_ue(l3_lu);
Neels Hofmeyr29b8da02018-03-01 18:09:45 +01001735 if (pars.send_early_cm) {
1736 BSSAP.send(ts_BSSMAP_ClassmarkUpd(g_pars.cm2, g_pars.cm3));
1737 } else {
1738 pars.cm1.esind := '0'B;
1739 }
Harald Welte9de84792018-01-28 01:06:35 +01001740 f_mm_auth();
1741 alt {
Daniel Willmann52918e52018-09-20 14:39:09 +02001742 [] BSSAP.receive(tr_BSSMAP_ClassmarkReq) {
1743 BSSAP.send(ts_BSSMAP_ClassmarkUpd(g_pars.cm2, g_pars.cm3));
1744 repeat;
1745 }
Harald Welte5946b332018-03-18 23:32:21 +01001746 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Rej)) {
1747 f_expect_clear();
1748 }
Harald Welte9de84792018-01-28 01:06:35 +01001749 [] BSSAP.receive(tr_BSSMAP_CipherModeCmd(?,?)) {
1750 setverdict(fail, "CipherModeCommand despite no A5 intersection");
Daniel Willmannafce8662018-07-06 23:11:32 +02001751 mtc.stop;
Harald Welte9de84792018-01-28 01:06:35 +01001752 }
1753 [] BSSAP.receive {
Harald Welte458fd372018-03-21 11:26:23 +01001754 setverdict(fail, "Unknown/unexpected BSSAP received");
Daniel Willmannafce8662018-07-06 23:11:32 +02001755 mtc.stop;
Harald Welte9de84792018-01-28 01:06:35 +01001756 }
1757 }
1758 setverdict(pass);
1759}
1760testcase TC_lu_imsi_auth_tmsi_encr_3_1() runs on MTC_CT {
1761 var BSC_ConnHdlr vc_conn;
1762 f_init();
1763 f_vty_config(MSCVTY, "network", "authentication required");
1764 f_vty_config(MSCVTY, "network", "encryption a5 3");
1765
Neels Hofmeyr29b8da02018-03-01 18:09:45 +01001766 vc_conn := f_start_handler(refers(f_tc_lu_imsi_auth_tmsi_encr_3_1), 360);
1767 vc_conn.done;
1768}
1769testcase TC_lu_imsi_auth_tmsi_encr_3_1_no_cm() runs on MTC_CT {
1770 var BSC_ConnHdlrPars pars;
1771 var BSC_ConnHdlr vc_conn;
1772 f_init();
1773 f_vty_config(MSCVTY, "network", "authentication required");
1774 f_vty_config(MSCVTY, "network", "encryption a5 3");
1775
1776 pars := f_init_pars(361);
1777 pars.send_early_cm := false;
1778 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 +01001779 vc_conn.done;
1780}
Neels Hofmeyr1b3c6e32018-03-01 17:52:21 +01001781testcase TC_lu_imsi_auth_tmsi_encr_3_1_log_msc_debug() runs on MTC_CT {
1782 var BSC_ConnHdlr vc_conn;
1783 f_init();
1784 f_vty_config(MSCVTY, "network", "authentication required");
1785 f_vty_config(MSCVTY, "network", "encryption a5 3");
1786
1787 /* Make sure the MSC category is on DEBUG level to trigger the log
1788 * message that is reported in OS#2947 to trigger the segfault */
1789 f_vty_config(MSCVTY, "log stderr", "logging level msc debug");
1790
1791 vc_conn := f_start_handler(refers(f_tc_lu_imsi_auth_tmsi_encr_3_1), 362);
1792 vc_conn.done;
1793}
Harald Welte9de84792018-01-28 01:06:35 +01001794
1795/* A5/1 + A5/3 only permitted on network side, and MS with only A5/2 support */
1796private function f_tc_lu_imsi_auth_tmsi_encr_13_2(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
1797 pars.net.expect_auth := true;
1798 pars.net.expect_ciph := true;
1799 pars.net.kc_support := '0A'O; /* A5/1 + A5/3 */
1800 pars.cm1.a5_1 := '1'B;
1801 pars.cm2.a5_1 := '1'B;
1802 pars.cm2.classmarkInformationType2_oct5.a5_3 := '0'B;
1803 pars.cm2.classmarkInformationType2_oct5.a5_2 := '1'B;
1804 f_init_handler(pars, 15.0);
1805
1806 /* cannot use f_perform_lu() as we expect a reject */
1807 var PDU_ML3_MS_NW l3_lu := f_build_lu_imsi(g_pars.imsi);
1808 f_create_gsup_expect(hex2str(g_pars.imsi));
Harald Weltedceacc72019-04-21 20:58:35 +02001809 f_cl3_or_initial_ue(l3_lu);
Harald Welte9de84792018-01-28 01:06:35 +01001810 BSSAP.send(ts_BSSMAP_ClassmarkUpd(g_pars.cm2, g_pars.cm3));
1811 f_mm_auth();
1812 alt {
Harald Welte5946b332018-03-18 23:32:21 +01001813 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Rej)) {
1814 f_expect_clear();
1815 }
Harald Welte9de84792018-01-28 01:06:35 +01001816 [] BSSAP.receive(tr_BSSMAP_CipherModeCmd(?,?)) {
1817 setverdict(fail, "CipherModeCommand despite no A5 intersection");
Daniel Willmannafce8662018-07-06 23:11:32 +02001818 mtc.stop;
Harald Welte9de84792018-01-28 01:06:35 +01001819 }
1820 [] BSSAP.receive {
Harald Welte458fd372018-03-21 11:26:23 +01001821 setverdict(fail, "Unknown/unexpected BSSAP received");
Daniel Willmannafce8662018-07-06 23:11:32 +02001822 mtc.stop;
Harald Welte9de84792018-01-28 01:06:35 +01001823 }
1824 }
1825 setverdict(pass);
1826}
1827testcase TC_lu_imsi_auth_tmsi_encr_13_2() runs on MTC_CT {
1828 var BSC_ConnHdlr vc_conn;
1829 f_init();
1830 f_vty_config(MSCVTY, "network", "authentication required");
1831 f_vty_config(MSCVTY, "network", "encryption a5 1 3");
1832
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001833 vc_conn := f_start_handler(refers(f_tc_lu_imsi_auth_tmsi_encr_13_2), 37);
Harald Welte9de84792018-01-28 01:06:35 +01001834 vc_conn.done;
1835}
1836
1837/* A5/0 + A5/1 + A5/3 only permitted on network side, and MS with only A5/2 support */
1838private function f_tc_lu_imsi_auth_tmsi_encr_013_2(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
1839 pars.net.expect_auth := true;
1840 pars.net.expect_ciph := true;
1841 pars.net.kc_support := '0B'O; /* A5/1 + A5/3 */
1842 pars.cm1.a5_1 := '1'B;
1843 pars.cm2.a5_1 := '1'B;
1844 pars.cm2.classmarkInformationType2_oct5.a5_3 := '0'B;
1845 pars.cm2.classmarkInformationType2_oct5.a5_2 := '1'B;
1846 f_init_handler(pars, 15.0);
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +01001847 f_perform_lu();
Harald Welte9de84792018-01-28 01:06:35 +01001848}
1849testcase TC_lu_imsi_auth_tmsi_encr_013_2() runs on MTC_CT {
1850 var BSC_ConnHdlr vc_conn;
1851 f_init();
1852 f_vty_config(MSCVTY, "network", "authentication required");
1853 f_vty_config(MSCVTY, "network", "encryption a5 0 1 3");
1854
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001855 vc_conn := f_start_handler(refers(f_tc_lu_imsi_auth_tmsi_encr_013_2), 38);
Harald Welte9de84792018-01-28 01:06:35 +01001856 vc_conn.done;
1857}
1858
Harald Welte33ec09b2018-02-10 15:34:46 +01001859/* LU followed by MT call (including paging) */
1860private function f_tc_lu_and_mt_call(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
1861 f_init_handler(pars);
Stefan Sperling26d57be2018-11-12 17:03:26 +01001862 var CallParameters cpars := valueof(t_CallParams('12345'H, 0));
Harald Welte33ec09b2018-02-10 15:34:46 +01001863 cpars.bss_rtp_port := 1110;
1864 cpars.mgcp_connection_id_bss := '10004'H;
1865 cpars.mgcp_connection_id_mss := '10005'H;
1866
Philipp Maier4b2692d2018-03-14 16:37:48 +01001867 /* Note: This is an optional parameter. When the call-agent (MSC) does
1868 * supply a full endpoint name this setting will be overwritten. */
1869 cpars.mgcp_ep := "rtpbridge/1@mgw";
1870
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +01001871 f_perform_lu();
Harald Welte33ec09b2018-02-10 15:34:46 +01001872 f_mt_call(cpars);
1873}
1874testcase TC_lu_and_mt_call() runs on MTC_CT {
1875 var BSC_ConnHdlr vc_conn;
1876 f_init();
1877
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001878 vc_conn := f_start_handler(refers(f_tc_lu_and_mt_call), 39);
Harald Welte33ec09b2018-02-10 15:34:46 +01001879 vc_conn.done;
1880}
1881
Daniel Willmann8b084372018-02-04 13:35:26 +01001882/* Test MO Call SETUP with DTMF */
1883private function f_tc_mo_setup_dtmf_dup(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
1884 f_init_handler(pars);
1885 var CallParameters cpars := valueof(t_CallParams('12345'H, 0));
1886 cpars.bss_rtp_port := 1110;
1887 cpars.mgcp_connection_id_bss := '22222'H;
1888 cpars.mgcp_connection_id_mss := '33333'H;
1889
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +01001890 f_perform_lu();
Daniel Willmann8b084372018-02-04 13:35:26 +01001891 f_mo_seq_dtmf_dup(cpars);
1892}
1893testcase TC_mo_setup_and_dtmf_dup() runs on MTC_CT {
1894 var BSC_ConnHdlr vc_conn;
1895 f_init();
1896
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001897 vc_conn := f_start_handler(refers(f_tc_mo_setup_dtmf_dup), 39);
Daniel Willmann8b084372018-02-04 13:35:26 +01001898 vc_conn.done;
1899}
Harald Welte9de84792018-01-28 01:06:35 +01001900
Philipp Maier328d1662018-03-07 10:40:27 +01001901testcase TC_cr_before_reset() runs on MTC_CT {
1902 timer T := 4.0;
1903 var boolean reset_ack_seen := false;
1904 f_init_bssap_direct();
1905
Harald Welte3ca0ce12019-04-23 17:18:48 +02001906 f_ran_adapter_start(g_bssap[0]);
Daniel Willmann42d1d5b2018-08-07 15:18:41 +02001907
Daniel Willmanne8018962018-08-21 14:18:00 +02001908 f_sleep(3.0);
1909
Philipp Maier328d1662018-03-07 10:40:27 +01001910 /* Make a blind connection attemt, to trigger the deadlock condition */
Philipp Maier75932982018-03-27 14:52:35 +02001911 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 +01001912
1913 /* Send a BSSMAP reset */
Philipp Maier75932982018-03-27 14:52:35 +02001914 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 +01001915 T.start
1916 alt {
1917 [] BSSAP_DIRECT.receive(tr_BSSAP_UNITDATA_ind(?, ?, tr_BSSMAP_ResetAck)) {
1918 reset_ack_seen := true;
1919 repeat;
1920 }
1921
1922 /* Acknowledge MSC sided reset requests */
1923 [] BSSAP_DIRECT.receive(tr_BSSAP_UNITDATA_ind(?, ?, tr_BSSMAP_Reset)) {
Philipp Maier75932982018-03-27 14:52:35 +02001924 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 +01001925 repeat;
1926 }
1927
1928 /* Ignore all other messages (e.g CR from the connection request) */
1929 [] BSSAP_DIRECT.receive { repeat }
1930
1931 /* If we got no BSSMAP RESET ACK back, then the MSC entered the
1932 * deadlock situation. The MSC is then unable to respond to any
1933 * further BSSMAP RESET or any other sort of traffic. */
1934 [reset_ack_seen == true] T.timeout { setverdict(pass) }
1935 [reset_ack_seen == false] T.timeout {
1936 setverdict(fail, "no BSSMAP RESET ACK seen!");
Daniel Willmannafce8662018-07-06 23:11:32 +02001937 mtc.stop;
Philipp Maier328d1662018-03-07 10:40:27 +01001938 }
1939 }
1940}
Harald Welte9de84792018-01-28 01:06:35 +01001941
Philipp Maier94f3f1b2018-03-15 18:54:13 +01001942/* Test MO Call with no response to RAN-side CRCX or DTAP Release */
Harald Weltee13cfb22019-04-23 16:52:02 +02001943friend function f_tc_mo_release_timeout(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Philipp Maier94f3f1b2018-03-15 18:54:13 +01001944 f_init_handler(pars);
1945 var CallParameters cpars := valueof(t_CallParams('12345'H, 0));
1946 var MNCC_PDU mncc;
1947 var MgcpCommand mgcp_cmd;
1948
1949 f_perform_lu();
1950
Harald Welteb9e86fa2018-04-09 18:18:31 +02001951 f_establish_fully();
Philipp Maier94f3f1b2018-03-15 18:54:13 +01001952 f_create_mncc_expect(hex2str(cpars.called_party));
1953 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
1954
1955 BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_CC_SETUP(cpars.transaction_id, cpars.called_party)));
1956 MNCC.receive(tr_MNCC_SETUP_ind(?, tr_MNCC_number(hex2str(cpars.called_party)))) -> value mncc;
1957 cpars.mncc_callref := mncc.u.signal.callref;
1958 MNCC.send(ts_MNCC_CALL_PROC_req(cpars.mncc_callref, cpars.mncc_bearer_cap));
1959 BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_CC_CALL_PROC(cpars.transaction_id)));
1960
1961 /* Drop CRCX */
1962 MGCP.receive(tr_CRCX) -> value mgcp_cmd;
1963
Neels Hofmeyrde76f052019-02-26 05:02:46 +01001964 var default ccrel := activate(as_optional_cc_rel(cpars));
Philipp Maier94f3f1b2018-03-15 18:54:13 +01001965
1966 f_expect_clear(60.0);
Neels Hofmeyrde76f052019-02-26 05:02:46 +01001967
1968 deactivate(ccrel);
Philipp Maier94f3f1b2018-03-15 18:54:13 +01001969}
1970testcase TC_mo_release_timeout() runs on MTC_CT {
1971 var BSC_ConnHdlr vc_conn;
1972 f_init();
1973
1974 vc_conn := f_start_handler(refers(f_tc_mo_release_timeout), 40);
1975 vc_conn.done;
1976}
1977
Harald Welte12510c52018-01-26 22:26:24 +01001978
Philipp Maier2a98a732018-03-19 16:06:12 +01001979/* LU followed by MT call (including paging) */
1980private function f_tc_lu_and_mt_call_no_dlcx_resp(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
1981 f_init_handler(pars);
Stefan Sperling26d57be2018-11-12 17:03:26 +01001982 var CallParameters cpars := valueof(t_CallParams('12345'H, 0));
Philipp Maier2a98a732018-03-19 16:06:12 +01001983 cpars.bss_rtp_port := 1110;
1984 cpars.mgcp_connection_id_bss := '10004'H;
1985 cpars.mgcp_connection_id_mss := '10005'H;
1986
1987 /* Note: This is an optional parameter. When the call-agent (MSC) does
1988 * supply a full endpoint name this setting will be overwritten. */
1989 cpars.mgcp_ep := "rtpbridge/1@mgw";
1990
1991 /* Intentionally disable the CRCX response */
1992 cpars.mgw_drop_dlcx := true;
1993
1994 /* Perform location update and call */
1995 f_perform_lu();
1996 f_mt_call(cpars);
1997}
1998testcase TC_lu_and_mt_call_no_dlcx_resp() runs on MTC_CT {
1999 var BSC_ConnHdlr vc_conn;
2000 f_init();
2001
2002 /* Perform an almost normal looking locationupdate + mt-call, but do
2003 * not respond to the DLCX at the end of the call */
2004 vc_conn := f_start_handler(refers(f_tc_lu_and_mt_call_no_dlcx_resp), 41);
2005 vc_conn.done;
2006
2007 /* Wait a guard period until the MGCP layer in the MSC times out,
2008 * if the MSC is vulnerable to the use-after-free situation that is
2009 * fixed by I78f1b6a9149488a4ad3f120c1e190a83c07d4b89 then it should
2010 * segfault now */
2011 f_sleep(6.0);
2012
2013 /* Run the init procedures once more. If the MSC has crashed, this
2014 * this will fail */
2015 f_init();
2016}
Harald Welte45164da2018-01-24 12:51:27 +01002017
Philipp Maier75932982018-03-27 14:52:35 +02002018/* Two BSSMAP resets from two different BSCs */
2019testcase TC_reset_two() runs on MTC_CT {
2020 var BSC_ConnHdlr vc_conn;
2021 f_init(2);
2022 f_sleep(2.0);
2023 setverdict(pass);
2024}
2025
Harald Weltee13cfb22019-04-23 16:52:02 +02002026/* Two BSSMAP resets from two different BSCs plus one IuCS RANAP Reset */
2027testcase TC_reset_two_1iu() runs on MTC_CT {
2028 var BSC_ConnHdlr vc_conn;
2029 f_init(3);
2030 f_sleep(2.0);
2031 setverdict(pass);
2032}
2033
Harald Weltef640a012018-04-14 17:49:21 +02002034/***********************************************************************
2035 * SMS Testing
2036 ***********************************************************************/
2037
Harald Weltef45efeb2018-04-09 18:19:24 +02002038/* LU followed by MO SMS */
Harald Weltee13cfb22019-04-23 16:52:02 +02002039friend function f_tc_lu_and_mo_sms(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltef45efeb2018-04-09 18:19:24 +02002040 var SmsParameters spars := valueof(t_SmsPars);
2041
2042 f_init_handler(pars);
2043
2044 /* Perform location update and call */
2045 f_perform_lu();
2046
2047 f_establish_fully(EST_TYPE_MO_SMS);
2048
2049 //spars.exp_rp_err := 96; /* invalid mandatory information */
2050 f_mo_sms(spars);
2051
2052 f_expect_clear();
2053}
2054testcase TC_lu_and_mo_sms() runs on MTC_CT {
2055 var BSC_ConnHdlr vc_conn;
2056 f_init();
2057 vc_conn := f_start_handler(refers(f_tc_lu_and_mo_sms), 42);
2058 vc_conn.done;
2059}
2060
Harald Weltee13cfb22019-04-23 16:52:02 +02002061
Harald Weltef45efeb2018-04-09 18:19:24 +02002062private function f_vty_sms_send(charstring imsi, charstring msisdn, charstring text)
Neels Hofmeyr6aaeccf2019-03-06 15:32:26 +01002063runs on BSC_ConnHdlr {
Harald Weltef45efeb2018-04-09 18:19:24 +02002064 f_vty_transceive(MSCVTY, "subscriber imsi "&imsi&" sms sender msisdn "&msisdn&" send "&text);
2065}
2066
Neels Hofmeyr8256ed22019-03-06 15:34:01 +01002067/* Remove still pending SMS */
2068private function f_vty_sms_clear(charstring imsi)
2069runs on BSC_ConnHdlr {
2070 f_vty_transceive(MSCVTY, "subscriber imsi " & imsi & " sms delete-all");
2071 f_vty_transceive(MSCVTY, "sms-queue clear");
2072}
2073
Harald Weltef45efeb2018-04-09 18:19:24 +02002074/* LU followed by MT SMS */
Harald Weltee13cfb22019-04-23 16:52:02 +02002075friend function f_tc_lu_and_mt_sms(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltef45efeb2018-04-09 18:19:24 +02002076 var SmsParameters spars := valueof(t_SmsPars);
2077 var OCT4 tmsi;
2078
2079 f_init_handler(pars);
2080
2081 /* Perform location update and call */
2082 f_perform_lu();
2083
2084 /* register an 'expect' for given IMSI (+TMSI) */
2085 if (isvalue(g_pars.tmsi)) {
2086 tmsi := g_pars.tmsi;
2087 } else {
2088 tmsi := 'FFFFFFFF'O;
2089 }
Harald Welte6811d102019-04-14 22:23:14 +02002090 f_ran_register_imsi(g_pars.imsi, tmsi);
Harald Weltef45efeb2018-04-09 18:19:24 +02002091
Neels Hofmeyr6aaeccf2019-03-06 15:32:26 +01002092 f_vty_sms_send(hex2str(pars.imsi), "2342", "Hello SMS");
Harald Weltef45efeb2018-04-09 18:19:24 +02002093
2094 /* MSC->BSC: expect PAGING from MSC */
Harald Weltee035e3e2019-04-21 17:32:05 +02002095 f_expect_paging();
2096
Harald Weltef45efeb2018-04-09 18:19:24 +02002097 /* Establish DTAP / BSSAP / SCCP connection */
2098 f_establish_fully(EST_TYPE_PAG_RESP);
2099
2100 spars.tp.ud := 'C8329BFD064D9B53'O;
2101 f_mt_sms(spars);
2102
2103 f_expect_clear();
2104}
2105testcase TC_lu_and_mt_sms() runs on MTC_CT {
2106 var BSC_ConnHdlrPars pars;
2107 var BSC_ConnHdlr vc_conn;
2108 f_init();
2109 pars := f_init_pars(43);
2110 vc_conn := f_start_handler_with_pars(refers(f_tc_lu_and_mt_sms), pars);
Harald Weltef45efeb2018-04-09 18:19:24 +02002111 vc_conn.done;
2112}
2113
Harald Weltee13cfb22019-04-23 16:52:02 +02002114
Philipp Maier3983e702018-11-22 19:01:33 +01002115/* Paging for MT SMS but no response */
Harald Weltee13cfb22019-04-23 16:52:02 +02002116friend 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 +01002117 var SmsParameters spars := valueof(t_SmsPars);
2118 var OCT4 tmsi;
Philipp Maier3983e702018-11-22 19:01:33 +01002119 f_init_handler(pars, 150.0);
2120
2121 /* Perform location update */
2122 f_perform_lu();
2123
2124 /* register an 'expect' for given IMSI (+TMSI) */
2125 if (isvalue(g_pars.tmsi)) {
2126 tmsi := g_pars.tmsi;
2127 } else {
2128 tmsi := 'FFFFFFFF'O;
2129 }
Harald Welte6811d102019-04-14 22:23:14 +02002130 f_ran_register_imsi(g_pars.imsi, tmsi);
Philipp Maier3983e702018-11-22 19:01:33 +01002131
Neels Hofmeyr6aaeccf2019-03-06 15:32:26 +01002132 f_vty_sms_send(hex2str(pars.imsi), "2342", "Hello SMS");
2133
Neels Hofmeyr16237742019-03-06 15:34:01 +01002134 /* Expect the MSC to page exactly once */
Harald Weltee13cfb22019-04-23 16:52:02 +02002135 f_expect_paging();
Philipp Maier3983e702018-11-22 19:01:33 +01002136
2137 /* Wait some time to make sure the MSC is not delivering any further
2138 * paging messages or anything else that could be unexpected. */
2139 timer T := 20.0;
2140 T.start
2141 alt {
Harald Weltee13cfb22019-04-23 16:52:02 +02002142 [pars.ran_is_geran] BSSAP.receive(tr_BSSMAP_Paging(g_pars.imsi))
Philipp Maier3983e702018-11-22 19:01:33 +01002143 {
2144 setverdict(fail, "paging seems not to stop!");
2145 mtc.stop;
2146 }
Harald Weltee13cfb22019-04-23 16:52:02 +02002147 [not pars.ran_is_geran] BSSAP.receive(tr_RANAP_Paging(cs_domain, imsi_hex2oct(g_pars.imsi), ?)) {
2148 setverdict(fail, "paging seems not to stop!");
2149 mtc.stop;
2150 }
Philipp Maier3983e702018-11-22 19:01:33 +01002151 [] BSSAP.receive {
2152 setverdict(fail, "unexpected BSSAP message received");
2153 self.stop;
2154 }
2155 [] T.timeout {
2156 setverdict(pass);
2157 }
2158 }
2159
Neels Hofmeyr8256ed22019-03-06 15:34:01 +01002160 f_vty_sms_clear(hex2str(g_pars.imsi));
2161
Philipp Maier3983e702018-11-22 19:01:33 +01002162 setverdict(pass);
2163}
2164testcase TC_lu_and_mt_sms_paging_and_nothing() runs on MTC_CT {
2165 var BSC_ConnHdlrPars pars;
2166 var BSC_ConnHdlr vc_conn;
2167 f_init();
Philipp Maiera99ad262019-01-22 15:35:42 +01002168 pars := f_init_pars(1843);
Philipp Maier3983e702018-11-22 19:01:33 +01002169 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 +01002170 vc_conn.done;
2171}
2172
Harald Weltee13cfb22019-04-23 16:52:02 +02002173
Harald Weltef640a012018-04-14 17:49:21 +02002174/* mobile originated SMS from MS/BTS/BSC side to SMPP */
Harald Weltee13cfb22019-04-23 16:52:02 +02002175friend function f_tc_smpp_mo_sms(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltef640a012018-04-14 17:49:21 +02002176 var SmsParameters spars := valueof(t_SmsPars);
Harald Weltef45efeb2018-04-09 18:19:24 +02002177
Harald Weltef640a012018-04-14 17:49:21 +02002178 f_init_handler(pars);
Harald Weltef45efeb2018-04-09 18:19:24 +02002179
Harald Weltef640a012018-04-14 17:49:21 +02002180 /* Perform location update so IMSI is known + registered in MSC/VLR */
2181 f_perform_lu();
2182 f_establish_fully(EST_TYPE_MO_SMS);
2183
2184 f_mo_sms(spars);
2185
2186 var SMPP_PDU smpp;
2187 var template SMPP_PDU tr_smpp := tr_SMPP(c_SMPP_command_id_deliver_sm, ESME_ROK);
2188 tr_smpp.body.deliver_sm := {
2189 service_type := "CMT",
2190 source_addr_ton := network_specific,
2191 source_addr_npi := isdn,
2192 source_addr := hex2str(pars.msisdn),
2193 dest_addr_ton := f_sm_ton_from_gsm(spars.tp.da.tP_DA_NoPad.tP_TypeOfNumber),
2194 dest_addr_npi := f_sm_npi_from_gsm(spars.tp.da.tP_DA_NoPad.tP_NumberingPlanID),
2195 destination_addr := hex2str(spars.tp.da.tP_DA_NoPad.tP_DAValue),
2196 esm_class := '00000001'B,
2197 protocol_id := 0,
2198 priority_flag := 0,
2199 schedule_delivery_time := "",
2200 replace_if_present := 0,
2201 data_coding := '00000001'B,
2202 sm_default_msg_id := 0,
2203 sm_length := ?,
2204 short_message := spars.tp.ud,
2205 opt_pars := {
2206 {
2207 tag := user_message_reference,
2208 len := 2,
2209 opt_value := {
2210 int2_val := oct2int(spars.tp.msg_ref)
2211 }
2212 }
2213 }
2214 };
2215 alt {
2216 [] SMPP.receive(tr_smpp) -> value smpp {
2217 SMPP.send(ts_SMPP_DELIVER_SM_resp(ESME_ROK, smpp.header.seq_num));
2218 }
2219 [] SMPP.receive(tr_SMPP(c_SMPP_command_id_alert_notification, ESME_ROK)) { repeat; }
2220 }
2221
2222 f_expect_clear();
2223}
2224testcase TC_smpp_mo_sms() runs on MTC_CT {
2225 var BSC_ConnHdlr vc_conn;
2226 f_init();
2227 f_vty_config2(MSCVTY, { "smpp", "esme msc_tester"}, "default-route");
2228 vc_conn := f_start_handler(refers(f_tc_smpp_mo_sms), 44);
2229 vc_conn.done;
2230 f_vty_config2(MSCVTY, { "smpp", "esme msc_tester"}, "no default-route");
2231}
2232
Harald Weltee13cfb22019-04-23 16:52:02 +02002233
Vadim Yanitskiy103d09f2018-11-12 02:50:23 +07002234/* Test MO-SMS from MS/BTS/BSC towards HLR (via GSUP) */
Harald Weltee13cfb22019-04-23 16:52:02 +02002235friend function f_tc_gsup_mo_sms(charstring id, BSC_ConnHdlrPars pars)
Vadim Yanitskiy103d09f2018-11-12 02:50:23 +07002236runs on BSC_ConnHdlr {
2237 var SmsParameters spars := valueof(t_SmsPars);
2238 var GSUP_PDU gsup_msg_rx;
2239 var octetstring sm_tpdu;
2240
2241 f_init_handler(pars);
2242
2243 /* We need to inspect GSUP activity */
2244 f_create_gsup_expect(hex2str(g_pars.imsi));
2245
2246 /* Perform location update */
2247 f_perform_lu();
2248
2249 /* Send CM Service Request for SMS */
2250 f_establish_fully(EST_TYPE_MO_SMS);
2251
2252 /* Prepare expected SM-RP-UI (SM TPDU) */
2253 enc_TPDU_RP_DATA_MS_SGSN_fast(
2254 valueof(ts_SMS_SUBMIT(spars.tp.msg_ref,
2255 spars.tp.da, spars.tp.pid, spars.tp.dcs,
2256 spars.tp.udl, spars.tp.ud)),
2257 sm_tpdu);
2258
2259 var template GSUP_PDU mo_forwardSM := tr_GSUP_MO_FORWARD_SM_REQ(
2260 imsi := g_pars.imsi,
2261 sm_rp_mr := spars.rp.msg_ref,
2262 /* FIXME: extract SM-RP-DA from spars.rp.dest */
2263 sm_rp_da := tr_GSUP_SM_RP_DA_SMSC_ADDR(?),
2264 /* FIXME: MSISDN coding troubles */
2265 sm_rp_oa := tr_GSUP_SM_RP_OA_MSISDN(?),
2266 /* TODO: can we use decmatch here? */
2267 sm_rp_ui := sm_tpdu
2268 );
2269
2270 /* Submit an SMS on DTAP and expect MO-forwardSM-Req on GSUP */
2271 f_mo_sms_submit(spars);
2272 alt {
2273 [] GSUP.receive(mo_forwardSM) -> value gsup_msg_rx {
2274 log("RX MO-forwardSM-Req");
2275 log(gsup_msg_rx);
2276 setverdict(pass);
2277 }
2278 [] GSUP.receive {
2279 log("RX unexpected GSUP message");
2280 setverdict(fail);
2281 mtc.stop;
2282 }
2283 }
2284
2285 /* Trigger RP-ACK by sending MO-forwardSM-Res */
2286 GSUP.send(valueof(ts_GSUP_MO_FORWARD_SM_RES(
2287 imsi := g_pars.imsi,
2288 sm_rp_mr := spars.rp.msg_ref)));
2289 /* Expect RP-ACK on DTAP */
2290 f_mo_sms_wait_rp_ack(spars);
2291
2292 f_expect_clear();
2293}
2294testcase TC_gsup_mo_sms() runs on MTC_CT {
2295 var BSC_ConnHdlr vc_conn;
2296 f_init();
2297 f_vty_config(MSCVTY, "msc", "sms-over-gsup");
2298 vc_conn := f_start_handler(refers(f_tc_gsup_mo_sms), 88);
2299 vc_conn.done;
2300 f_vty_config(MSCVTY, "msc", "no sms-over-gsup");
2301}
2302
Harald Weltee13cfb22019-04-23 16:52:02 +02002303
Vadim Yanitskiy9cc019a2018-11-15 02:06:07 +07002304/* Test MO-SMMA from MS/BTS/BSC towards HLR (via GSUP) */
Harald Weltee13cfb22019-04-23 16:52:02 +02002305friend function f_tc_gsup_mo_smma(charstring id, BSC_ConnHdlrPars pars)
Vadim Yanitskiy9cc019a2018-11-15 02:06:07 +07002306runs on BSC_ConnHdlr {
2307 var SmsParameters spars := valueof(t_SmsPars);
2308 var GSUP_PDU gsup_msg_rx;
2309
2310 f_init_handler(pars);
2311
2312 /* We need to inspect GSUP activity */
2313 f_create_gsup_expect(hex2str(g_pars.imsi));
2314
2315 /* Perform location update */
2316 f_perform_lu();
2317
2318 /* Send CM Service Request for SMS */
2319 f_establish_fully(EST_TYPE_MO_SMS);
2320
2321 var template GSUP_PDU mo_ReadyForSM := tr_GSUP_MO_READY_FOR_SM_REQ(
2322 imsi := g_pars.imsi,
2323 sm_rp_mr := spars.rp.msg_ref,
2324 sm_alert_rsn := GSUP_SM_ALERT_RSN_TYPE_MEM_AVAIL
2325 );
2326
2327 /* Submit an SMS on DTAP and expect MO-forwardSM-Req on GSUP */
2328 f_mo_smma(spars);
2329 alt {
2330 [] GSUP.receive(mo_ReadyForSM) -> value gsup_msg_rx {
2331 log("RX MO-ReadyForSM-Req");
2332 log(gsup_msg_rx);
2333 setverdict(pass);
2334 }
2335 [] GSUP.receive {
2336 log("RX unexpected GSUP message");
2337 setverdict(fail);
2338 mtc.stop;
2339 }
2340 }
2341
2342 /* Trigger RP-ACK by sending MO-forwardSM-Res */
2343 GSUP.send(valueof(ts_GSUP_MO_READY_FOR_SM_RES(
2344 imsi := g_pars.imsi,
2345 sm_rp_mr := spars.rp.msg_ref)));
2346 /* Expect RP-ACK on DTAP */
2347 f_mo_sms_wait_rp_ack(spars);
2348
2349 f_expect_clear();
2350}
2351testcase TC_gsup_mo_smma() runs on MTC_CT {
2352 var BSC_ConnHdlr vc_conn;
2353 f_init();
2354 f_vty_config(MSCVTY, "msc", "sms-over-gsup");
2355 vc_conn := f_start_handler(refers(f_tc_gsup_mo_smma), 89);
2356 vc_conn.done;
2357 f_vty_config(MSCVTY, "msc", "no sms-over-gsup");
2358}
2359
Harald Weltee13cfb22019-04-23 16:52:02 +02002360
Vadim Yanitskiyd7b37ab2018-11-24 03:40:20 +07002361/* Helper for sending MT SMS over GSUP */
2362private function f_gsup_forwardSM_req(SmsParameters spars, OCT1 mms := '00'O)
2363runs on BSC_ConnHdlr {
2364 GSUP.send(ts_GSUP_MT_FORWARD_SM_REQ(
2365 imsi := g_pars.imsi,
2366 /* NOTE: MSC should assign RP-MR itself */
2367 sm_rp_mr := 'FF'O,
2368 /* FIXME: extract SM-RP-DA from spars.rp.dest */
2369 /* TODO: fix encoding of ts_GSUP_SM_RP_DA_IMSI */
2370 sm_rp_da := valueof(ts_GSUP_SM_RP_DA_MSISDN(g_pars.msisdn)),
2371 sm_rp_oa := valueof(ts_GSUP_SM_RP_OA_SMSC_ADDR(g_pars.msisdn)),
2372 /* Encoded SMS TPDU (taken from Wireshark)
2373 * FIXME: we should encode spars somehow */
2374 sm_rp_ui := '00068021436500008111328130858200'O,
2375 sm_rp_mms := mms
2376 ));
2377}
2378
2379/* Test successful MT-SMS (RP-ACK) over GSUP */
Harald Weltee13cfb22019-04-23 16:52:02 +02002380friend function f_tc_gsup_mt_sms_ack(charstring id, BSC_ConnHdlrPars pars)
Vadim Yanitskiyd7b37ab2018-11-24 03:40:20 +07002381runs on BSC_ConnHdlr {
2382 var SmsParameters spars := valueof(t_SmsPars);
2383
2384 f_init_handler(pars);
2385
2386 /* We need to inspect GSUP activity */
2387 f_create_gsup_expect(hex2str(g_pars.imsi));
2388
2389 /* Perform location update */
2390 f_perform_lu();
2391
2392 /* Register an 'expect' for given IMSI (+TMSI) */
2393 if (isvalue(g_pars.tmsi)) {
Harald Welte6811d102019-04-14 22:23:14 +02002394 f_ran_register_imsi(g_pars.imsi, g_pars.tmsi);
Vadim Yanitskiyd7b37ab2018-11-24 03:40:20 +07002395 } else {
Harald Welte6811d102019-04-14 22:23:14 +02002396 f_ran_register_imsi(g_pars.imsi, 'FFFFFFFF'O);
Vadim Yanitskiyd7b37ab2018-11-24 03:40:20 +07002397 }
2398
2399 var template GSUP_PDU mt_forwardSM_res := tr_GSUP_MT_FORWARD_SM_RES(
2400 imsi := g_pars.imsi,
2401 /* NOTE: MSC should assign RP-MR itself */
2402 sm_rp_mr := ?
2403 );
2404
2405 /* Submit a MT SMS on GSUP */
2406 f_gsup_forwardSM_req(spars);
2407
2408 /* Expect Paging Request and Establish DTAP / BSSAP / SCCP connection */
Harald Weltee035e3e2019-04-21 17:32:05 +02002409 f_expect_paging();
Vadim Yanitskiyd7b37ab2018-11-24 03:40:20 +07002410 f_establish_fully(EST_TYPE_PAG_RESP);
2411
2412 /* Wait for MT SMS on DTAP */
2413 f_mt_sms_expect(spars);
2414
2415 /* Send RP-ACK and expect MT-forwardSM-Res on GSUP */
2416 f_mt_sms_send_rp_ack(spars);
2417 alt {
2418 [] GSUP.receive(mt_forwardSM_res) {
2419 log("RX MT-forwardSM-Res (RP-ACK)");
2420 setverdict(pass);
2421 }
2422 [] GSUP.receive {
2423 log("RX unexpected GSUP message");
2424 setverdict(fail);
2425 mtc.stop;
2426 }
2427 }
2428
2429 f_expect_clear();
2430}
2431testcase TC_gsup_mt_sms_ack() runs on MTC_CT {
2432 var BSC_ConnHdlrPars pars;
2433 var BSC_ConnHdlr vc_conn;
2434 f_init();
2435 pars := f_init_pars(90);
2436 f_vty_config(MSCVTY, "msc", "sms-over-gsup");
2437 vc_conn := f_start_handler_with_pars(refers(f_tc_gsup_mt_sms_ack), pars);
2438 vc_conn.done;
2439 f_vty_config(MSCVTY, "msc", "no sms-over-gsup");
2440}
2441
Harald Weltee13cfb22019-04-23 16:52:02 +02002442
Vadim Yanitskiyd7b37ab2018-11-24 03:40:20 +07002443/* Test rejected MT-SMS (RP-ERROR) over GSUP */
Harald Weltee13cfb22019-04-23 16:52:02 +02002444friend function f_tc_gsup_mt_sms_err(charstring id, BSC_ConnHdlrPars pars)
Vadim Yanitskiyd7b37ab2018-11-24 03:40:20 +07002445runs on BSC_ConnHdlr {
2446 var SmsParameters spars := valueof(t_SmsPars);
2447 var OCT1 sm_rp_cause := '78'O; /* dummy RP-Cause value */
2448
2449 f_init_handler(pars);
2450
2451 /* We need to inspect GSUP activity */
2452 f_create_gsup_expect(hex2str(g_pars.imsi));
2453
2454 /* Perform location update */
2455 f_perform_lu();
2456
2457 /* Register an 'expect' for given IMSI (+TMSI) */
2458 if (isvalue(g_pars.tmsi)) {
Harald Welte6811d102019-04-14 22:23:14 +02002459 f_ran_register_imsi(g_pars.imsi, g_pars.tmsi);
Vadim Yanitskiyd7b37ab2018-11-24 03:40:20 +07002460 } else {
Harald Welte6811d102019-04-14 22:23:14 +02002461 f_ran_register_imsi(g_pars.imsi, 'FFFFFFFF'O);
Vadim Yanitskiyd7b37ab2018-11-24 03:40:20 +07002462 }
2463
2464 var template GSUP_PDU mt_forwardSM_err := tr_GSUP_MT_FORWARD_SM_ERR(
2465 imsi := g_pars.imsi,
2466 /* NOTE: MSC should assign RP-MR itself */
2467 sm_rp_mr := ?,
2468 sm_rp_cause := sm_rp_cause
2469 );
2470
2471 /* Submit a MT SMS on GSUP */
2472 f_gsup_forwardSM_req(spars);
2473
2474 /* Expect Paging Request and Establish DTAP / BSSAP / SCCP connection */
Harald Weltee035e3e2019-04-21 17:32:05 +02002475 f_expect_paging();
Vadim Yanitskiyd7b37ab2018-11-24 03:40:20 +07002476 f_establish_fully(EST_TYPE_PAG_RESP);
2477
2478 /* Wait for MT SMS on DTAP */
2479 f_mt_sms_expect(spars);
2480
2481 /* Send RP-ERROR and expect MT-forwardSM-Err on GSUP */
2482 f_mt_sms_send_rp_error(spars, oct2int(sm_rp_cause));
2483 alt {
2484 [] GSUP.receive(mt_forwardSM_err) {
2485 log("RX MT-forwardSM-Err (RP-ERROR)");
2486 setverdict(pass);
2487 mtc.stop;
2488 }
2489 [] GSUP.receive {
2490 log("RX unexpected GSUP message");
2491 setverdict(fail);
2492 mtc.stop;
2493 }
2494 }
2495
2496 f_expect_clear();
2497}
2498testcase TC_gsup_mt_sms_err() runs on MTC_CT {
2499 var BSC_ConnHdlrPars pars;
2500 var BSC_ConnHdlr vc_conn;
2501 f_init();
2502 pars := f_init_pars(91);
2503 f_vty_config(MSCVTY, "msc", "sms-over-gsup");
2504 vc_conn := f_start_handler_with_pars(refers(f_tc_gsup_mt_sms_err), pars);
2505 vc_conn.done;
2506 f_vty_config(MSCVTY, "msc", "no sms-over-gsup");
2507}
2508
Harald Weltee13cfb22019-04-23 16:52:02 +02002509
Vadim Yanitskiybe1ff4b2019-01-18 15:04:13 +07002510/* Test SM-RP-MR assignment for MT-SMS over GSUP */
Harald Weltee13cfb22019-04-23 16:52:02 +02002511friend function f_tc_gsup_mt_sms_rp_mr(charstring id, BSC_ConnHdlrPars pars)
Vadim Yanitskiybe1ff4b2019-01-18 15:04:13 +07002512runs on BSC_ConnHdlr {
2513 var SmsParameters spars1 := valueof(t_SmsPars); /* 1st SMS */
2514 var SmsParameters spars2 := valueof(t_SmsPars); /* 2nd SMS */
2515
2516 f_init_handler(pars);
2517
2518 /* We need to inspect GSUP activity */
2519 f_create_gsup_expect(hex2str(g_pars.imsi));
2520
2521 /* Perform location update */
2522 f_perform_lu();
2523
2524 /* Register an 'expect' for given IMSI (+TMSI) */
2525 if (isvalue(g_pars.tmsi)) {
Harald Welte6811d102019-04-14 22:23:14 +02002526 f_ran_register_imsi(g_pars.imsi, g_pars.tmsi);
Vadim Yanitskiybe1ff4b2019-01-18 15:04:13 +07002527 } else {
Harald Welte6811d102019-04-14 22:23:14 +02002528 f_ran_register_imsi(g_pars.imsi, 'FFFFFFFF'O);
Vadim Yanitskiybe1ff4b2019-01-18 15:04:13 +07002529 }
2530
2531 /* Submit the 1st MT SMS on GSUP */
2532 log("TX MT-forwardSM-Req for the 1st SMS");
2533 f_gsup_forwardSM_req(spars1);
2534
2535 /* Expect Paging Request and Establish DTAP / BSSAP / SCCP connection */
Harald Weltee035e3e2019-04-21 17:32:05 +02002536 f_expect_paging();
Vadim Yanitskiybe1ff4b2019-01-18 15:04:13 +07002537 f_establish_fully(EST_TYPE_PAG_RESP);
2538
2539 /* Wait for 1st MT SMS on DTAP */
2540 f_mt_sms_expect(spars1);
2541 log("RX the 1st SMS on DTAP, DTAP TID is ", spars1.tid,
2542 ", SM-RP-MR is ", spars1.rp.msg_ref);
2543
2544 /* Submit the 2nd MT SMS on GSUP */
2545 log("TX MT-forwardSM-Req for the 2nd SMS");
2546 f_gsup_forwardSM_req(spars2);
2547
2548 /* Wait for 2nd MT SMS on DTAP */
2549 f_mt_sms_expect(spars2);
2550 log("RX the 2nd SMS on DTAP, DTAP TID is ", spars2.tid,
2551 ", SM-RP-MR is ", spars2.rp.msg_ref);
2552
2553 /* Both transaction IDs shall be different */
2554 if (spars1.tid == spars2.tid) {
2555 log("Both DTAP transaction IDs shall be different");
2556 setverdict(fail);
2557 }
2558
2559 /* Both SM-RP-MR values shall be different */
2560 if (spars1.rp.msg_ref == spars2.rp.msg_ref) {
2561 log("Both SM-RP-MR values shall be different");
2562 setverdict(fail);
2563 }
2564
2565 /* Both SM-RP-MR values shall be assigned */
2566 if (spars1.rp.msg_ref == 'FF'O) {
2567 log("Unassigned SM-RP-MR value for the 1st SMS");
2568 setverdict(fail);
2569 }
2570 if (spars2.rp.msg_ref == 'FF'O) {
2571 log("Unassigned SM-RP-MR value for the 2nd SMS");
2572 setverdict(fail);
2573 }
2574
2575 /* Send the 1st RP-ACK and expect MT-forwardSM-Res on GSUP */
2576 f_mt_sms_send_rp_ack(spars1);
2577 alt {
2578 [] GSUP.receive(tr_GSUP_MT_FORWARD_SM_RES(
2579 imsi := g_pars.imsi,
2580 sm_rp_mr := spars1.rp.msg_ref
2581 )) {
2582 log("RX MT-forwardSM-Res (RP-ACK)");
2583 setverdict(pass);
2584 }
2585 [] GSUP.receive {
2586 log("RX unexpected GSUP message");
2587 setverdict(fail);
2588 mtc.stop;
2589 }
2590 }
2591
2592 /* Send the 2nd RP-ACK and expect MT-forwardSM-Res on GSUP */
2593 f_mt_sms_send_rp_ack(spars2);
2594 alt {
2595 [] GSUP.receive(tr_GSUP_MT_FORWARD_SM_RES(
2596 imsi := g_pars.imsi,
2597 sm_rp_mr := spars2.rp.msg_ref
2598 )) {
2599 log("RX MT-forwardSM-Res (RP-ACK)");
2600 setverdict(pass);
2601 }
2602 [] GSUP.receive {
2603 log("RX unexpected GSUP message");
2604 setverdict(fail);
2605 mtc.stop;
2606 }
2607 }
2608
2609 f_expect_clear();
2610}
2611testcase TC_gsup_mt_sms_rp_mr() runs on MTC_CT {
2612 var BSC_ConnHdlrPars pars;
2613 var BSC_ConnHdlr vc_conn;
2614 f_init();
2615 pars := f_init_pars(92);
2616 f_vty_config(MSCVTY, "msc", "sms-over-gsup");
2617 vc_conn := f_start_handler_with_pars(refers(f_tc_gsup_mt_sms_rp_mr), pars);
2618 vc_conn.done;
2619 f_vty_config(MSCVTY, "msc", "no sms-over-gsup");
2620}
2621
Harald Weltee13cfb22019-04-23 16:52:02 +02002622
Vadim Yanitskiy5ac49cc2019-01-24 16:57:31 +07002623/* Test SM-RP-MR assignment for MT-SMS over GSUP */
Harald Weltee13cfb22019-04-23 16:52:02 +02002624friend function f_tc_gsup_mo_mt_sms_rp_mr(charstring id, BSC_ConnHdlrPars pars)
Vadim Yanitskiy5ac49cc2019-01-24 16:57:31 +07002625runs on BSC_ConnHdlr {
2626 var SmsParameters spars_mo := valueof(t_SmsPars); /* MO SMMA */
2627 var SmsParameters spars_mt := valueof(t_SmsPars); /* MT SMS */
2628
2629 f_init_handler(pars);
2630
2631 /* We need to inspect GSUP activity */
2632 f_create_gsup_expect(hex2str(g_pars.imsi));
2633
2634 /* Perform location update */
2635 f_perform_lu();
2636
2637 /* Register an 'expect' for given IMSI (+TMSI) */
2638 if (isvalue(g_pars.tmsi)) {
Harald Welte6811d102019-04-14 22:23:14 +02002639 f_ran_register_imsi(g_pars.imsi, g_pars.tmsi);
Vadim Yanitskiy5ac49cc2019-01-24 16:57:31 +07002640 } else {
Harald Welte6811d102019-04-14 22:23:14 +02002641 f_ran_register_imsi(g_pars.imsi, 'FFFFFFFF'O);
Vadim Yanitskiy5ac49cc2019-01-24 16:57:31 +07002642 }
2643
2644 /* Send CM Service Request for MO SMMA */
2645 f_establish_fully(EST_TYPE_MO_SMS);
2646
2647 /* Submit MO SMMA on DTAP */
2648 log("Submit MO SMMA on DTAP, SM-RP-MR is '00'O");
2649 spars_mo.rp.msg_ref := '00'O;
2650 f_mo_smma(spars_mo);
2651
2652 /* Expect MO-forwardSM-Req for MO SMMA on GSUP */
2653 alt {
2654 [] GSUP.receive(tr_GSUP_MO_READY_FOR_SM_REQ(
2655 imsi := g_pars.imsi,
2656 sm_rp_mr := spars_mo.rp.msg_ref,
2657 sm_alert_rsn := GSUP_SM_ALERT_RSN_TYPE_MEM_AVAIL
2658 )) {
2659 log("RX MO-ReadyForSM-Req, SM-RP-MR is '00'O");
2660 setverdict(pass);
2661 }
2662 [] GSUP.receive {
2663 log("RX unexpected GSUP message");
2664 setverdict(fail);
2665 mtc.stop;
2666 }
2667 }
2668
2669 /* Submit MT SMS on GSUP */
2670 log("TX MT-forwardSM-Req for the MT SMS");
2671 f_gsup_forwardSM_req(spars_mt);
2672
2673 /* Wait for MT SMS on DTAP */
2674 f_mt_sms_expect(spars_mt);
2675 log("RX MT SMS on DTAP, DTAP TID is ", spars_mt.tid,
2676 ", SM-RP-MR is ", spars_mt.rp.msg_ref);
2677
2678 /* Both SM-RP-MR values shall be different */
2679 if (spars_mo.rp.msg_ref == spars_mt.rp.msg_ref) {
2680 log("Both SM-RP-MR values shall be different");
2681 setverdict(fail);
2682 }
2683
2684 /* SM-RP-MR value for MT SMS shall be assigned */
2685 if (spars_mt.rp.msg_ref == 'FF'O) {
2686 log("Unassigned SM-RP-MR value for the MT SMS");
2687 setverdict(fail);
2688 }
2689
2690 /* Trigger RP-ACK for MO SMMA by sending MO-forwardSM-Res */
2691 GSUP.send(valueof(ts_GSUP_MO_READY_FOR_SM_RES(
2692 imsi := g_pars.imsi,
2693 sm_rp_mr := spars_mo.rp.msg_ref)));
2694 /* Expect RP-ACK for MO SMMA on DTAP */
2695 f_mo_sms_wait_rp_ack(spars_mo);
2696
2697 /* Send RP-ACK for MT SMS and expect MT-forwardSM-Res on GSUP */
2698 f_mt_sms_send_rp_ack(spars_mt);
2699 alt {
2700 [] GSUP.receive(tr_GSUP_MT_FORWARD_SM_RES(
2701 imsi := g_pars.imsi,
2702 sm_rp_mr := spars_mt.rp.msg_ref
2703 )) {
2704 log("RX MT-forwardSM-Res (RP-ACK)");
2705 setverdict(pass);
2706 }
2707 [] GSUP.receive {
2708 log("RX unexpected GSUP message");
2709 setverdict(fail);
2710 mtc.stop;
2711 }
2712 }
2713
2714 f_expect_clear();
2715}
2716testcase TC_gsup_mo_mt_sms_rp_mr() runs on MTC_CT {
2717 var BSC_ConnHdlrPars pars;
2718 var BSC_ConnHdlr vc_conn;
2719 f_init();
2720 pars := f_init_pars(93);
2721 f_vty_config(MSCVTY, "msc", "sms-over-gsup");
2722 vc_conn := f_start_handler_with_pars(refers(f_tc_gsup_mo_mt_sms_rp_mr), pars);
2723 vc_conn.done;
2724 f_vty_config(MSCVTY, "msc", "no sms-over-gsup");
2725}
2726
Harald Weltee13cfb22019-04-23 16:52:02 +02002727
Vadim Yanitskiy1cd11a02018-12-03 02:43:35 +07002728/* Test multi-part MT-SMS over GSUP */
2729private function f_tc_gsup_mt_multi_part_sms(charstring id, BSC_ConnHdlrPars pars)
2730runs on BSC_ConnHdlr {
2731 var SmsParameters spars := valueof(t_SmsPars);
2732
2733 f_init_handler(pars);
2734
2735 /* We need to inspect GSUP activity */
2736 f_create_gsup_expect(hex2str(g_pars.imsi));
2737
2738 /* Perform location update */
2739 f_perform_lu();
2740
2741 /* Register an 'expect' for given IMSI (+TMSI) */
2742 if (isvalue(g_pars.tmsi)) {
Harald Welte6811d102019-04-14 22:23:14 +02002743 f_ran_register_imsi(g_pars.imsi, g_pars.tmsi);
Vadim Yanitskiy1cd11a02018-12-03 02:43:35 +07002744 } else {
Harald Welte6811d102019-04-14 22:23:14 +02002745 f_ran_register_imsi(g_pars.imsi, 'FFFFFFFF'O);
Vadim Yanitskiy1cd11a02018-12-03 02:43:35 +07002746 }
2747
2748 var template GSUP_PDU mt_forwardSM_res := tr_GSUP_MT_FORWARD_SM_RES(
2749 imsi := g_pars.imsi,
2750 /* NOTE: MSC should assign RP-MR itself */
2751 sm_rp_mr := ?
2752 );
2753
2754 /* Send 4 messages (NOTE: SM-RP-UI remains unchanged) */
2755 for (var integer i := 3; i >= 0; i := i-1) {
2756 /* Submit a MT SMS on GSUP (MMS is decremented) */
2757 f_gsup_forwardSM_req(spars, int2oct(i, 1));
2758
2759 /* Expect Paging Request and Establish connection */
2760 if (i == 3) { /* ... only once! */
Harald Weltee13cfb22019-04-23 16:52:02 +02002761 f_expect_paging();
Vadim Yanitskiy1cd11a02018-12-03 02:43:35 +07002762 f_establish_fully(EST_TYPE_PAG_RESP);
2763 }
2764
2765 /* Wait for MT SMS on DTAP */
2766 f_mt_sms_expect(spars);
2767
2768 /* Send RP-ACK and expect MT-forwardSM-Res on GSUP */
2769 f_mt_sms_send_rp_ack(spars);
2770 alt {
2771 [] GSUP.receive(mt_forwardSM_res) {
2772 log("RX MT-forwardSM-Res (RP-ACK)");
2773 setverdict(pass);
2774 }
2775 [] GSUP.receive {
2776 log("RX unexpected GSUP message");
2777 setverdict(fail);
2778 mtc.stop;
2779 }
2780 }
2781
2782 /* Keep some 'distance' between transmissions */
2783 f_sleep(1.5);
2784 }
2785
2786 f_expect_clear();
2787}
2788testcase TC_gsup_mt_multi_part_sms() runs on MTC_CT {
2789 var BSC_ConnHdlrPars pars;
2790 var BSC_ConnHdlr vc_conn;
2791 f_init();
2792 pars := f_init_pars(91);
2793 f_vty_config(MSCVTY, "msc", "sms-over-gsup");
2794 vc_conn := f_start_handler_with_pars(refers(f_tc_gsup_mt_multi_part_sms), pars);
2795 vc_conn.done;
2796 f_vty_config(MSCVTY, "msc", "no sms-over-gsup");
2797}
2798
Harald Weltef640a012018-04-14 17:49:21 +02002799/* convert GSM L3 TON to SMPP_TON enum */
2800function f_sm_ton_from_gsm(BIT3 ton) return SMPP_TON {
2801 select (ton) {
2802 case ('000'B) { return unknown; }
2803 case ('001'B) { return international; }
2804 case ('010'B) { return national; }
2805 case ('011'B) { return network_specific; }
2806 case ('100'B) { return subscriber_number; }
2807 case ('101'B) { return alphanumeric; }
2808 case ('110'B) { return abbreviated; }
2809 }
2810 setverdict(fail, "Unknown TON ", ton);
Daniel Willmannafce8662018-07-06 23:11:32 +02002811 mtc.stop;
Harald Weltef640a012018-04-14 17:49:21 +02002812}
2813/* convert GSM L3 NPI to SMPP_NPI enum */
2814function f_sm_npi_from_gsm(BIT4 npi) return SMPP_NPI {
2815 select (npi) {
2816 case ('0000'B) { return unknown; }
2817 case ('0001'B) { return isdn; }
2818 case ('0011'B) { return data; }
2819 case ('0100'B) { return telex; }
2820 case ('0110'B) { return land_mobile; }
2821 case ('1000'B) { return national; }
2822 case ('1001'B) { return private_; }
2823 case ('1010'B) { return ermes; }
2824 }
2825 setverdict(fail, "Unknown NPI ", npi);
Daniel Willmannafce8662018-07-06 23:11:32 +02002826 mtc.stop;
Harald Weltef640a012018-04-14 17:49:21 +02002827}
2828
2829/* build a SMPP_SM from SmsParameters */
2830function f_mt_sm_from_spars(SmsParameters spars)
2831runs on BSC_ConnHdlr return SMPP_SM {
2832 var SMPP_SM sm := {
2833 service_type := "CMT",
2834 source_addr_ton := f_sm_ton_from_gsm(spars.tp.da.tP_DA_NoPad.tP_TypeOfNumber),
2835 source_addr_npi := f_sm_npi_from_gsm(spars.tp.da.tP_DA_NoPad.tP_NumberingPlanID),
2836 source_addr := hex2str(spars.tp.da.tP_DA_NoPad.tP_DAValue),
2837 dest_addr_ton := international,
2838 dest_addr_npi := isdn,
2839 destination_addr := hex2str(g_pars.msisdn),
2840 esm_class := '00000001'B,
2841 protocol_id := 0,
2842 priority_flag := 0,
2843 schedule_delivery_time := "",
2844 validity_period := "",
2845 registered_delivery := '00000000'B,
2846 replace_if_present := 0,
2847 data_coding := '00000001'B,
2848 sm_default_msg_id := 0,
2849 sm_length := spars.tp.udl,
2850 short_message := spars.tp.ud,
2851 opt_pars := {}
2852 };
2853 return sm;
2854}
2855
2856/* helper function to encode SMS from 'spars', send it via SMPP to MSC; receive it on MS side */
2857private function f_smpp_mt_sms(SmsParameters spars, boolean trans_mode) runs on BSC_ConnHdlr {
2858 var SMPP_SM sm := f_mt_sm_from_spars(spars);
2859 if (trans_mode) {
2860 sm.esm_class := '00000010'B;
2861 }
2862
2863 /* actually cause MSC to send a SMS via SUBMIT-SM from SMPP side */
2864 SMPP.send(ts_SMPP_SUBMIT_SM(sm));
2865 if (not match(sm.esm_class, tr_ESM_CLASS_TRANSACTION)) {
2866 /* if we're not in SMPP transaction mode, we expect the SMPP-level ACK
2867 * before we expect the SMS delivery on the BSC/radio side */
2868 SMPP.receive(tr_SMPP(c_SMPP_command_id_submit_sm_resp, ESME_ROK));
2869 }
2870
2871 /* MSC->BSC: expect PAGING from MSC */
Harald Weltee035e3e2019-04-21 17:32:05 +02002872 f_expect_paging();
Harald Weltef640a012018-04-14 17:49:21 +02002873 /* Establish DTAP / BSSAP / SCCP connection */
2874 f_establish_fully(EST_TYPE_PAG_RESP);
2875 SMPP.receive(tr_SMPP(c_SMPP_command_id_alert_notification, ESME_ROK));
2876
2877 f_mt_sms(spars);
2878
2879 if (match(sm.esm_class, tr_ESM_CLASS_TRANSACTION)) {
2880 SMPP.receive(tr_SMPP(c_SMPP_command_id_submit_sm_resp, ESME_ROK));
2881 }
2882 f_expect_clear();
2883}
2884
2885/* mobile terminated SMS, from SMPP to BSC/BTS/MS */
2886private function f_tc_smpp_mt_sms(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
2887 f_init_handler(pars);
2888
2889 /* Perform location update so IMSI is known + registered in MSC/VLR */
2890 f_perform_lu();
2891 SMPP.receive(tr_SMPP(c_SMPP_command_id_alert_notification, ESME_ROK));
2892
2893 /* register an 'expect' for given IMSI (+TMSI) */
2894 var OCT4 tmsi;
2895 if (isvalue(g_pars.tmsi)) {
2896 tmsi := g_pars.tmsi;
2897 } else {
2898 tmsi := 'FFFFFFFF'O;
2899 }
Harald Welte6811d102019-04-14 22:23:14 +02002900 f_ran_register_imsi(g_pars.imsi, tmsi);
Harald Weltef640a012018-04-14 17:49:21 +02002901
2902 var SmsParameters spars := valueof(t_SmsPars);
2903 /* TODO: test with more intelligent user data; test different coding schemes */
2904 spars.tp.ud := '00'O;
2905 spars.tp.udl := 1;
2906
2907 /* first test the non-transaction store+forward mode */
2908 f_smpp_mt_sms(spars, false);
2909
2910 /* then test the transaction mode */
2911 f_smpp_mt_sms(spars, true);
2912}
2913testcase TC_smpp_mt_sms() runs on MTC_CT {
2914 var BSC_ConnHdlr vc_conn;
2915 f_init();
2916 vc_conn := f_start_handler(refers(f_tc_smpp_mt_sms), 45);
2917 vc_conn.done;
2918}
2919
Vadim Yanitskiy7d1f9182018-05-28 16:21:42 +07002920/***********************************************************************
2921 * USSD Testing
2922 ***********************************************************************/
2923
Vadim Yanitskiyce8cc372018-06-21 01:46:33 +07002924private altstep as_unexp_gsup_or_bssap_msg()
2925runs on BSC_ConnHdlr {
2926 [] GSUP.receive {
2927 setverdict(fail, "Unknown/unexpected GSUP received");
2928 self.stop;
2929 }
2930 [] BSSAP.receive {
2931 setverdict(fail, "Unknown/unexpected BSSAP message received");
2932 self.stop;
2933 }
2934}
2935
2936private function f_expect_gsup_msg(template GSUP_PDU msg)
2937runs on BSC_ConnHdlr return GSUP_PDU {
2938 var GSUP_PDU gsup_msg_complete;
2939
2940 alt {
2941 [] GSUP.receive(msg) -> value gsup_msg_complete {
2942 setverdict(pass);
2943 }
2944 /* We don't expect anything else */
2945 [] as_unexp_gsup_or_bssap_msg();
2946 }
2947
2948 return gsup_msg_complete;
2949}
2950
2951private function f_expect_mt_dtap_msg(template PDU_ML3_NW_MS msg)
2952runs on BSC_ConnHdlr return PDU_ML3_NW_MS {
2953 var PDU_DTAP_MT bssap_msg_complete;
2954
2955 alt {
2956 [] BSSAP.receive(tr_PDU_DTAP_MT(msg)) -> value bssap_msg_complete {
2957 setverdict(pass);
2958 }
2959 /* We don't expect anything else */
2960 [] as_unexp_gsup_or_bssap_msg();
2961 }
2962
2963 return bssap_msg_complete.dtap;
2964}
2965
Vadim Yanitskiy2a978b92018-06-19 17:51:20 +07002966/* LU followed by MO USSD request */
Harald Weltee13cfb22019-04-23 16:52:02 +02002967friend function f_tc_lu_and_mo_ussd_single_request(charstring id, BSC_ConnHdlrPars pars)
Vadim Yanitskiy7d1f9182018-05-28 16:21:42 +07002968runs on BSC_ConnHdlr {
2969 f_init_handler(pars);
2970
2971 /* Perform location update */
2972 f_perform_lu();
2973
2974 /* Send CM Service Request for SS/USSD */
2975 f_establish_fully(EST_TYPE_SS_ACT);
2976
Vadim Yanitskiy747689e2018-06-19 00:14:28 +07002977 /* We need to inspect GSUP activity */
2978 f_create_gsup_expect(hex2str(g_pars.imsi));
2979
2980 var template OCTN facility_req := f_USSD_FACILITY_IE_INVOKE(
2981 invoke_id := 5, /* Phone may not start from 0 or 1 */
2982 op_code := SS_OP_CODE_PROCESS_USS_REQ,
2983 ussd_string := "*#100#"
2984 );
2985
2986 var template OCTN facility_rsp := f_USSD_FACILITY_IE_RETURN_RESULT(
2987 invoke_id := 5, /* InvokeID shall be the same for both REQ and RSP */
2988 op_code := SS_OP_CODE_PROCESS_USS_REQ,
2989 ussd_string := "Your extension is " & hex2str(g_pars.msisdn) & "\r"
2990 )
2991
Vadim Yanitskiy7d1f9182018-05-28 16:21:42 +07002992 /* Compose a new SS/REGISTER message with request */
2993 var template (value) PDU_ML3_MS_NW ussd_req := ts_ML3_MO_SS_REGISTER(
2994 tid := 1, /* We just need a single transaction */
2995 ti_flag := c_TIF_ORIG, /* Sent from the side that originates the TI */
Vadim Yanitskiy747689e2018-06-19 00:14:28 +07002996 facility := valueof(facility_req)
Vadim Yanitskiy7d1f9182018-05-28 16:21:42 +07002997 );
2998
2999 /* Compose SS/RELEASE_COMPLETE template with expected response */
3000 var template PDU_ML3_NW_MS ussd_rsp := tr_ML3_MT_SS_RELEASE_COMPLETE(
3001 tid := 1, /* Response should arrive within the same transaction */
3002 ti_flag := c_TIF_REPL, /* Sent to the side that originates the TI */
Vadim Yanitskiy747689e2018-06-19 00:14:28 +07003003 facility := valueof(facility_rsp)
Vadim Yanitskiy7d1f9182018-05-28 16:21:42 +07003004 );
3005
Vadim Yanitskiy747689e2018-06-19 00:14:28 +07003006 /* Compose expected MSC -> HLR message */
3007 var template GSUP_PDU gsup_req := tr_GSUP_PROC_SS_REQ(
3008 imsi := g_pars.imsi,
3009 state := OSMO_GSUP_SESSION_STATE_BEGIN,
3010 ss := valueof(facility_req)
3011 );
3012
3013 /* To be used for sending response with correct session ID */
3014 var GSUP_PDU gsup_req_complete;
3015
3016 /* Request own number */
Vadim Yanitskiy7d1f9182018-05-28 16:21:42 +07003017 BSSAP.send(ts_PDU_DTAP_MO(ussd_req));
Vadim Yanitskiy747689e2018-06-19 00:14:28 +07003018 /* Expect GSUP message containing the SS payload */
3019 gsup_req_complete := f_expect_gsup_msg(gsup_req);
3020
3021 /* Compose the response from HLR using received session ID */
3022 var template GSUP_PDU gsup_rsp := ts_GSUP_PROC_SS_REQ(
3023 imsi := g_pars.imsi,
3024 sid := gsup_req_complete.ies[1].val.session_id,
3025 state := OSMO_GSUP_SESSION_STATE_END,
3026 ss := valueof(facility_rsp)
3027 );
3028
3029 /* Finally, HLR terminates the session */
3030 GSUP.send(gsup_rsp);
3031 /* Expect RELEASE_COMPLETE message with the response */
3032 f_expect_mt_dtap_msg(ussd_rsp);
Vadim Yanitskiy7d1f9182018-05-28 16:21:42 +07003033
3034 f_expect_clear();
3035}
Vadim Yanitskiy2a978b92018-06-19 17:51:20 +07003036testcase TC_lu_and_mo_ussd_single_request() runs on MTC_CT {
Vadim Yanitskiy7d1f9182018-05-28 16:21:42 +07003037 var BSC_ConnHdlr vc_conn;
3038 f_init();
Vadim Yanitskiy2a978b92018-06-19 17:51:20 +07003039 vc_conn := f_start_handler(refers(f_tc_lu_and_mo_ussd_single_request), 46);
Vadim Yanitskiy7d1f9182018-05-28 16:21:42 +07003040 vc_conn.done;
3041}
3042
Harald Weltee13cfb22019-04-23 16:52:02 +02003043
Vadim Yanitskiy13e4a272018-06-19 18:24:31 +07003044/* LU followed by MT USSD notification */
Harald Weltee13cfb22019-04-23 16:52:02 +02003045friend function f_tc_lu_and_mt_ussd_notification(charstring id, BSC_ConnHdlrPars pars)
Vadim Yanitskiy13e4a272018-06-19 18:24:31 +07003046runs on BSC_ConnHdlr {
3047 f_init_handler(pars);
3048
3049 /* Perform location update */
3050 f_perform_lu();
3051
Harald Welte6811d102019-04-14 22:23:14 +02003052 f_ran_register_imsi(g_pars.imsi, g_pars.tmsi);
Vadim Yanitskiy13e4a272018-06-19 18:24:31 +07003053
3054 /* We need to inspect GSUP activity */
3055 f_create_gsup_expect(hex2str(g_pars.imsi));
3056
3057 /* Facility IE with network-originated USSD notification */
3058 var template OCTN facility_req := f_USSD_FACILITY_IE_INVOKE(
3059 op_code := SS_OP_CODE_USS_NOTIFY,
3060 ussd_string := "Mahlzeit!"
3061 );
3062
3063 /* Facility IE with acknowledgment to the USSD notification */
3064 var template OCTN facility_rsp := enc_SS_FacilityInformation(
3065 /* In case of USSD notification, Return Result is empty */
3066 valueof(ts_SS_USSD_FACILITY_RETURN_RESULT_EMPTY())
3067 );
3068
3069 /* Compose a new MT SS/REGISTER message with USSD notification */
3070 var template PDU_ML3_NW_MS ussd_ntf := tr_ML3_MT_SS_REGISTER(
3071 tid := 0, /* FIXME: most likely, it should be 0 */
3072 ti_flag := c_TIF_ORIG, /* Sent from the side that originates the TI */
3073 facility := valueof(facility_req)
3074 );
3075
3076 /* Compose HLR -> MSC GSUP message */
3077 var template (value) GSUP_PDU gsup_req := ts_GSUP_PROC_SS_REQ(
3078 imsi := g_pars.imsi,
3079 sid := '20000101'O,
3080 state := OSMO_GSUP_SESSION_STATE_BEGIN,
3081 ss := valueof(facility_req)
3082 );
3083
3084 /* Send it to MSC and expect Paging Request */
3085 GSUP.send(gsup_req);
3086 alt {
Harald Weltee13cfb22019-04-23 16:52:02 +02003087 [pars.ran_is_geran] BSSAP.receive(tr_BSSMAP_Paging(g_pars.imsi)) {
3088 setverdict(pass);
3089 }
3090 [not pars.ran_is_geran] BSSAP.receive(tr_RANAP_Paging(cs_domain, imsi_hex2oct(g_pars.imsi), ?)) {
Vadim Yanitskiy13e4a272018-06-19 18:24:31 +07003091 setverdict(pass);
3092 }
3093 /* We don't expect anything else */
3094 [] as_unexp_gsup_or_bssap_msg();
3095 }
3096
3097 /* Send Paging Response and expect USSD notification */
3098 f_establish_fully(EST_TYPE_PAG_RESP);
3099 /* Expect MT REGISTER message with USSD notification */
3100 f_expect_mt_dtap_msg(ussd_ntf);
3101
3102 /* Compose a new MO SS/FACILITY message with empty response */
3103 var template (value) PDU_ML3_MS_NW ussd_rsp := ts_ML3_MO_SS_FACILITY(
3104 tid := 0, /* FIXME: it shall match the request tid */
3105 ti_flag := c_TIF_REPL, /* Sent to the side that originates the TI */
3106 facility := valueof(facility_rsp)
3107 );
3108
3109 /* Compose expected MSC -> HLR GSUP message */
3110 var template GSUP_PDU gsup_rsp := tr_GSUP_PROC_SS_REQ(
3111 imsi := g_pars.imsi,
3112 sid := '20000101'O,
3113 state := OSMO_GSUP_SESSION_STATE_CONTINUE,
3114 ss := valueof(facility_rsp)
3115 );
3116
3117 /* MS sends response to the notification */
3118 BSSAP.send(ts_PDU_DTAP_MO(ussd_rsp));
3119 /* Expect GSUP message containing the SS payload */
3120 f_expect_gsup_msg(gsup_rsp);
3121
3122 /* Compose expected MT SS/RELEASE COMPLETE message */
3123 var template PDU_ML3_NW_MS ussd_term := tr_ML3_MT_SS_RELEASE_COMPLETE(
3124 tid := 0, /* FIXME: it shall match the request tid */
3125 ti_flag := c_TIF_ORIG, /* Sent from the side that originates the TI */
3126 facility := omit
3127 );
3128
3129 /* Compose MSC -> HLR GSUP message */
3130 var template GSUP_PDU gsup_term := ts_GSUP_PROC_SS_REQ(
3131 imsi := g_pars.imsi,
3132 sid := '20000101'O,
3133 state := OSMO_GSUP_SESSION_STATE_END
3134 );
3135
3136 /* Finally, HLR terminates the session */
3137 GSUP.send(gsup_term)
3138 /* Expect MT RELEASE COMPLETE without Facility IE */
3139 f_expect_mt_dtap_msg(ussd_term);
3140
3141 f_expect_clear();
3142}
3143testcase TC_lu_and_mt_ussd_notification() runs on MTC_CT {
3144 var BSC_ConnHdlr vc_conn;
3145 f_init();
3146 vc_conn := f_start_handler(refers(f_tc_lu_and_mt_ussd_notification), 47);
3147 vc_conn.done;
3148}
3149
Harald Weltee13cfb22019-04-23 16:52:02 +02003150
Vadim Yanitskiy2a978b92018-06-19 17:51:20 +07003151/* LU followed by MT call and MO USSD request during this call */
Harald Weltee13cfb22019-04-23 16:52:02 +02003152friend function f_tc_lu_and_mo_ussd_during_mt_call(charstring id, BSC_ConnHdlrPars pars)
Vadim Yanitskiy0aaf48d2018-06-06 07:02:47 +07003153runs on BSC_ConnHdlr {
3154 f_init_handler(pars);
3155
3156 /* Call parameters taken from f_tc_lu_and_mt_call */
3157 var CallParameters cpars := valueof(t_CallParams('123456'H, 0));
3158 cpars.mgcp_connection_id_bss := '10004'H;
3159 cpars.mgcp_connection_id_mss := '10005'H;
3160 cpars.mgcp_ep := "rtpbridge/1@mgw";
3161 cpars.bss_rtp_port := 1110;
3162
3163 /* Perform location update */
3164 f_perform_lu();
3165
3166 /* Establish a MT call */
3167 f_mt_call_establish(cpars);
3168
3169 /* Hold the call for some time */
3170 f_sleep(1.0);
3171
Vadim Yanitskiy747689e2018-06-19 00:14:28 +07003172 var template OCTN facility_req := f_USSD_FACILITY_IE_INVOKE(
3173 op_code := SS_OP_CODE_PROCESS_USS_REQ,
3174 ussd_string := "*#100#"
3175 );
3176
3177 var template OCTN facility_rsp := f_USSD_FACILITY_IE_RETURN_RESULT(
3178 op_code := SS_OP_CODE_PROCESS_USS_REQ,
3179 ussd_string := "Your extension is " & hex2str(g_pars.msisdn) & "\r"
3180 )
3181
Vadim Yanitskiy0aaf48d2018-06-06 07:02:47 +07003182 /* Compose a new SS/REGISTER message with request */
3183 var template (value) PDU_ML3_MS_NW ussd_req := ts_ML3_MO_SS_REGISTER(
3184 tid := 1, /* We just need a single transaction */
3185 ti_flag := c_TIF_ORIG, /* Sent from the side that originates the TI */
Vadim Yanitskiy747689e2018-06-19 00:14:28 +07003186 facility := valueof(facility_req)
Vadim Yanitskiy0aaf48d2018-06-06 07:02:47 +07003187 );
3188
3189 /* Compose SS/RELEASE_COMPLETE template with expected response */
3190 var template PDU_ML3_NW_MS ussd_rsp := tr_ML3_MT_SS_RELEASE_COMPLETE(
3191 tid := 1, /* Response should arrive within the same transaction */
3192 ti_flag := c_TIF_REPL, /* Sent to the side that originates the TI */
Vadim Yanitskiy747689e2018-06-19 00:14:28 +07003193 facility := valueof(facility_rsp)
Vadim Yanitskiy0aaf48d2018-06-06 07:02:47 +07003194 );
3195
Vadim Yanitskiy747689e2018-06-19 00:14:28 +07003196 /* Compose expected MSC -> HLR message */
3197 var template GSUP_PDU gsup_req := tr_GSUP_PROC_SS_REQ(
3198 imsi := g_pars.imsi,
3199 state := OSMO_GSUP_SESSION_STATE_BEGIN,
3200 ss := valueof(facility_req)
3201 );
3202
3203 /* To be used for sending response with correct session ID */
3204 var GSUP_PDU gsup_req_complete;
3205
3206 /* Request own number */
Vadim Yanitskiy0aaf48d2018-06-06 07:02:47 +07003207 BSSAP.send(ts_PDU_DTAP_MO(ussd_req));
Vadim Yanitskiy747689e2018-06-19 00:14:28 +07003208 /* Expect GSUP message containing the SS payload */
3209 gsup_req_complete := f_expect_gsup_msg(gsup_req);
3210
3211 /* Compose the response from HLR using received session ID */
3212 var template GSUP_PDU gsup_rsp := ts_GSUP_PROC_SS_REQ(
3213 imsi := g_pars.imsi,
3214 sid := gsup_req_complete.ies[1].val.session_id,
3215 state := OSMO_GSUP_SESSION_STATE_END,
3216 ss := valueof(facility_rsp)
3217 );
3218
3219 /* Finally, HLR terminates the session */
3220 GSUP.send(gsup_rsp);
3221 /* Expect RELEASE_COMPLETE message with the response */
3222 f_expect_mt_dtap_msg(ussd_rsp);
Vadim Yanitskiy0aaf48d2018-06-06 07:02:47 +07003223
3224 /* Hold the call for some time */
3225 f_sleep(1.0);
3226
3227 /* Release the call (does Clear Complete itself) */
3228 f_call_hangup(cpars, true);
3229}
Vadim Yanitskiy2a978b92018-06-19 17:51:20 +07003230testcase TC_lu_and_mo_ussd_during_mt_call() runs on MTC_CT {
Vadim Yanitskiy0aaf48d2018-06-06 07:02:47 +07003231 var BSC_ConnHdlr vc_conn;
3232 f_init();
Vadim Yanitskiy2a978b92018-06-19 17:51:20 +07003233 vc_conn := f_start_handler(refers(f_tc_lu_and_mo_ussd_during_mt_call), 48);
Vadim Yanitskiy0aaf48d2018-06-06 07:02:47 +07003234 vc_conn.done;
3235}
3236
Neels Hofmeyr692c9ee2018-04-10 02:07:13 +02003237/* BSSMAP Clear Request in the middle of a call, see OS#3062 */
Harald Weltee13cfb22019-04-23 16:52:02 +02003238friend function f_tc_mo_cc_bssmap_clear(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Neels Hofmeyr692c9ee2018-04-10 02:07:13 +02003239 f_init_handler(pars);
3240 var CallParameters cpars := valueof(t_CallParams('12345'H, 0));
3241 var MNCC_PDU mncc;
3242 var MgcpCommand mgcp_cmd;
3243
3244 f_perform_lu();
3245
3246 f_establish_fully();
3247 f_create_mncc_expect(hex2str(cpars.called_party));
3248 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
3249
3250 BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_CC_SETUP(cpars.transaction_id, cpars.called_party)));
3251 MNCC.receive(tr_MNCC_SETUP_ind(?, tr_MNCC_number(hex2str(cpars.called_party)))) -> value mncc;
3252 cpars.mncc_callref := mncc.u.signal.callref;
3253 log("mncc_callref=", cpars.mncc_callref);
3254 MNCC.send(ts_MNCC_CALL_PROC_req(cpars.mncc_callref, cpars.mncc_bearer_cap));
3255 BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_CC_CALL_PROC(cpars.transaction_id)));
3256
3257 MNCC.send(ts_MNCC_ALERT_req(cpars.mncc_callref));
3258 BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_CC_ALERTING(cpars.transaction_id)));
3259 MGCP.receive(tr_CRCX);
3260
3261 f_sleep(1.0);
Harald Weltee13cfb22019-04-23 16:52:02 +02003262 if (pars.ran_is_geran) {
3263 BSSAP.send(ts_BSSMAP_ClearRequest(0));
3264 } else {
3265 BSSAP.send(ts_RANAP_IuReleaseRequest(ts_RanapCause_om_intervention));
3266 }
Neels Hofmeyr692c9ee2018-04-10 02:07:13 +02003267
Neels Hofmeyrde76f052019-02-26 05:02:46 +01003268 var default ccrel := activate(as_optional_cc_rel(cpars));
Neels Hofmeyr692c9ee2018-04-10 02:07:13 +02003269
Harald Weltee13cfb22019-04-23 16:52:02 +02003270 if (pars.ran_is_geran) {
3271 interleave {
3272 [] MNCC.receive(tr_MNCC_REL_ind(?, ?)) { };
3273 [] BSSAP.receive(tr_BSSMAP_ClearCommand) {
Neels Hofmeyrde76f052019-02-26 05:02:46 +01003274 BSSAP.send(ts_BSSMAP_ClearComplete);
Harald Weltee13cfb22019-04-23 16:52:02 +02003275 };
3276 }
3277 } else {
3278 interleave {
3279 [] MNCC.receive(tr_MNCC_REL_ind(?, ?)) { };
3280 [] BSSAP.receive(tr_RANAP_IuReleaseCommand(?)) {
3281 BSSAP.send(ts_RANAP_IuReleaseComplete);
3282 };
3283 }
Neels Hofmeyrde76f052019-02-26 05:02:46 +01003284 }
3285
3286 deactivate(ccrel);
Neels Hofmeyr692c9ee2018-04-10 02:07:13 +02003287
3288 f_sleep(1.0);
3289}
3290testcase TC_mo_cc_bssmap_clear() runs on MTC_CT {
3291 var BSC_ConnHdlr vc_conn;
3292 f_init();
3293
3294 vc_conn := f_start_handler(refers(f_tc_mo_cc_bssmap_clear), 43);
3295 vc_conn.done;
3296}
3297
Harald Weltee13cfb22019-04-23 16:52:02 +02003298
Vadim Yanitskiy13e4a272018-06-19 18:24:31 +07003299/* LU followed by MT call and MT USSD request during this call */
Harald Weltee13cfb22019-04-23 16:52:02 +02003300friend function f_tc_lu_and_mt_ussd_during_mt_call(charstring id, BSC_ConnHdlrPars pars)
Vadim Yanitskiy13e4a272018-06-19 18:24:31 +07003301runs on BSC_ConnHdlr {
3302 f_init_handler(pars);
3303
3304 /* Call parameters taken from f_tc_lu_and_mt_call */
3305 var CallParameters cpars := valueof(t_CallParams('123456'H, 0));
3306 cpars.mgcp_connection_id_bss := '10004'H;
3307 cpars.mgcp_connection_id_mss := '10005'H;
3308 cpars.mgcp_ep := "rtpbridge/1@mgw";
3309 cpars.bss_rtp_port := 1110;
3310
3311 /* Perform location update */
3312 f_perform_lu();
3313
3314 /* Establish a MT call */
3315 f_mt_call_establish(cpars);
3316
3317 /* Hold the call for some time */
3318 f_sleep(1.0);
3319
3320 var template OCTN facility_req := f_USSD_FACILITY_IE_INVOKE(
3321 op_code := SS_OP_CODE_USS_REQUEST,
3322 ussd_string := "Please type anything..."
3323 );
3324
3325 var template OCTN facility_rsp := f_USSD_FACILITY_IE_RETURN_RESULT(
3326 op_code := SS_OP_CODE_USS_REQUEST,
3327 ussd_string := "Nope."
3328 )
3329
3330 /* Compose MT SS/REGISTER message with network-originated request */
3331 var template (value) PDU_ML3_NW_MS ussd_req := ts_ML3_MT_SS_REGISTER(
3332 tid := 0, /* FIXME: most likely, it should be 0 */
3333 ti_flag := c_TIF_ORIG, /* Sent from the side that originates the TI */
3334 facility := valueof(facility_req)
3335 );
3336
3337 /* Compose HLR -> MSC GSUP message */
3338 var template (value) GSUP_PDU gsup_req := ts_GSUP_PROC_SS_REQ(
3339 imsi := g_pars.imsi,
3340 sid := '20000101'O,
3341 state := OSMO_GSUP_SESSION_STATE_BEGIN,
3342 ss := valueof(facility_req)
3343 );
3344
3345 /* Send it to MSC */
3346 GSUP.send(gsup_req);
3347 /* Expect MT REGISTER message with USSD request */
3348 f_expect_mt_dtap_msg(ussd_req);
3349
3350 /* Compose a new MO SS/FACILITY message with response */
3351 var template (value) PDU_ML3_MS_NW ussd_rsp := ts_ML3_MO_SS_FACILITY(
3352 tid := 0, /* FIXME: it shall match the request tid */
3353 ti_flag := c_TIF_REPL, /* Sent to the side that originates the TI */
3354 facility := valueof(facility_rsp)
3355 );
3356
3357 /* Compose expected MSC -> HLR GSUP message */
3358 var template GSUP_PDU gsup_rsp := tr_GSUP_PROC_SS_REQ(
3359 imsi := g_pars.imsi,
3360 sid := '20000101'O,
3361 state := OSMO_GSUP_SESSION_STATE_CONTINUE,
3362 ss := valueof(facility_rsp)
3363 );
3364
3365 /* MS sends response */
3366 BSSAP.send(ts_PDU_DTAP_MO(ussd_rsp));
3367 f_expect_gsup_msg(gsup_rsp);
3368
3369 /* Compose expected MT SS/RELEASE COMPLETE message */
3370 var template PDU_ML3_NW_MS ussd_term := tr_ML3_MT_SS_RELEASE_COMPLETE(
3371 tid := 0, /* FIXME: it shall match the request tid */
3372 ti_flag := c_TIF_ORIG, /* Sent from the side that originates the TI */
3373 facility := omit
3374 );
3375
3376 /* Compose MSC -> HLR GSUP message */
3377 var template GSUP_PDU gsup_term := ts_GSUP_PROC_SS_REQ(
3378 imsi := g_pars.imsi,
3379 sid := '20000101'O,
3380 state := OSMO_GSUP_SESSION_STATE_END
3381 );
3382
3383 /* Finally, HLR terminates the session */
3384 GSUP.send(gsup_term);
3385 /* Expect MT RELEASE COMPLETE without Facility IE */
3386 f_expect_mt_dtap_msg(ussd_term);
3387
3388 /* Hold the call for some time */
3389 f_sleep(1.0);
3390
3391 /* Release the call (does Clear Complete itself) */
3392 f_call_hangup(cpars, true);
3393}
3394testcase TC_lu_and_mt_ussd_during_mt_call() runs on MTC_CT {
3395 var BSC_ConnHdlr vc_conn;
3396 f_init();
3397 vc_conn := f_start_handler(refers(f_tc_lu_and_mt_ussd_during_mt_call), 49);
3398 vc_conn.done;
3399}
3400
Harald Weltee13cfb22019-04-23 16:52:02 +02003401
Vadim Yanitskiy2daf52d2018-06-21 04:19:58 +07003402/* LU followed by MO USSD request and MO Release during transaction */
Harald Weltee13cfb22019-04-23 16:52:02 +02003403friend function f_tc_lu_and_mo_ussd_mo_release(charstring id, BSC_ConnHdlrPars pars)
Vadim Yanitskiy2daf52d2018-06-21 04:19:58 +07003404runs on BSC_ConnHdlr {
3405 f_init_handler(pars);
3406
3407 /* Perform location update */
3408 f_perform_lu();
3409
3410 /* Send CM Service Request for SS/USSD */
3411 f_establish_fully(EST_TYPE_SS_ACT);
3412
3413 /* We need to inspect GSUP activity */
3414 f_create_gsup_expect(hex2str(g_pars.imsi));
3415
3416 var template OCTN facility_ms_req := f_USSD_FACILITY_IE_INVOKE(
3417 invoke_id := 1, /* Initial request */
3418 op_code := SS_OP_CODE_PROCESS_USS_REQ,
3419 ussd_string := "*6766*266#"
3420 );
3421
3422 var template OCTN facility_net_req := f_USSD_FACILITY_IE_INVOKE(
3423 invoke_id := 2, /* Counter request */
3424 op_code := SS_OP_CODE_USS_REQUEST,
3425 ussd_string := "Password?!?"
3426 )
3427
3428 /* Compose MO SS/REGISTER message with request */
3429 var template (value) PDU_ML3_MS_NW ussd_ms_req := ts_ML3_MO_SS_REGISTER(
3430 tid := 1, /* We just need a single transaction */
3431 ti_flag := c_TIF_ORIG, /* Sent from the side that originates the TI */
3432 facility := valueof(facility_ms_req)
3433 );
3434
3435 /* Compose expected MSC -> HLR message */
3436 var template GSUP_PDU gsup_ms_req := tr_GSUP_PROC_SS_REQ(
3437 imsi := g_pars.imsi,
3438 state := OSMO_GSUP_SESSION_STATE_BEGIN,
3439 ss := valueof(facility_ms_req)
3440 );
3441
3442 /* To be used for sending response with correct session ID */
3443 var GSUP_PDU gsup_ms_req_complete;
3444
3445 /* Initiate a new transaction */
3446 BSSAP.send(ts_PDU_DTAP_MO(ussd_ms_req));
3447 /* Expect GSUP request with original Facility IE */
3448 gsup_ms_req_complete := f_expect_gsup_msg(gsup_ms_req);
3449
3450 /* Compose the response from HLR using received session ID */
3451 var template (value) GSUP_PDU gsup_net_req := ts_GSUP_PROC_SS_REQ(
3452 imsi := g_pars.imsi,
3453 sid := gsup_ms_req_complete.ies[1].val.session_id,
3454 state := OSMO_GSUP_SESSION_STATE_CONTINUE,
3455 ss := valueof(facility_net_req)
3456 );
3457
3458 /* Compose expected MT SS/FACILITY template with counter request */
3459 var template PDU_ML3_NW_MS ussd_net_req := tr_ML3_MT_SS_FACILITY(
3460 tid := 1, /* Response should arrive within the same transaction */
3461 ti_flag := c_TIF_REPL, /* Sent to the side that originates the TI */
3462 facility := valueof(facility_net_req)
3463 );
3464
3465 /* Send response over GSUP */
3466 GSUP.send(gsup_net_req);
3467 /* Expect MT SS/FACILITY message with counter request */
3468 f_expect_mt_dtap_msg(ussd_net_req);
3469
3470 /* Compose MO SS/RELEASE COMPLETE */
3471 var template (value) PDU_ML3_MS_NW ussd_abort := ts_ML3_MO_SS_RELEASE_COMPLETE(
3472 tid := 1, /* Response should arrive within the same transaction */
3473 ti_flag := c_TIF_ORIG, /* Sent from the side that originates the TI */
3474 facility := omit
3475 /* TODO: cause? */
3476 );
3477
3478 /* Compose expected HLR -> MSC abort message */
3479 var template GSUP_PDU gsup_abort := tr_GSUP_PROC_SS_REQ(
3480 imsi := g_pars.imsi,
3481 sid := gsup_ms_req_complete.ies[1].val.session_id,
3482 state := OSMO_GSUP_SESSION_STATE_END
3483 );
3484
3485 /* Abort transaction */
3486 BSSAP.send(ts_PDU_DTAP_MO(ussd_abort));
3487 /* Expect GSUP message indicating abort */
3488 f_expect_gsup_msg(gsup_abort);
3489
3490 f_expect_clear();
3491}
3492testcase TC_lu_and_mo_ussd_mo_release() runs on MTC_CT {
3493 var BSC_ConnHdlr vc_conn;
3494 f_init();
3495 vc_conn := f_start_handler(refers(f_tc_lu_and_mo_ussd_mo_release), 50);
3496 vc_conn.done;
3497}
3498
Harald Weltee13cfb22019-04-23 16:52:02 +02003499
Vadim Yanitskiy0e392dd2018-11-29 00:47:54 +07003500/* LU followed by MO USSD request and MT Release due to timeout */
Harald Weltee13cfb22019-04-23 16:52:02 +02003501friend function f_tc_lu_and_ss_session_timeout(charstring id, BSC_ConnHdlrPars pars)
Vadim Yanitskiy0e392dd2018-11-29 00:47:54 +07003502runs on BSC_ConnHdlr {
3503 f_init_handler(pars);
3504
3505 /* Perform location update */
3506 f_perform_lu();
3507
3508 /* Send CM Service Request for SS/USSD */
3509 f_establish_fully(EST_TYPE_SS_ACT);
3510
3511 /* We need to inspect GSUP activity */
3512 f_create_gsup_expect(hex2str(g_pars.imsi));
3513
3514 var template OCTN facility_ms_req := f_USSD_FACILITY_IE_INVOKE(
3515 invoke_id := 1,
3516 op_code := SS_OP_CODE_PROCESS_USS_REQ,
3517 ussd_string := "#release_me");
3518
3519 /* Compose MO SS/REGISTER message with request */
3520 var template (value) PDU_ML3_MS_NW ussd_ms_req := ts_ML3_MO_SS_REGISTER(
3521 tid := 1, /* An arbitrary transaction identifier */
3522 ti_flag := c_TIF_ORIG, /* Sent from the side that originates the TI */
3523 facility := valueof(facility_ms_req));
3524
3525 /* Compose expected MSC -> HLR message */
3526 var template GSUP_PDU gsup_ms_req := tr_GSUP_PROC_SS_REQ(
3527 imsi := g_pars.imsi,
3528 state := OSMO_GSUP_SESSION_STATE_BEGIN,
3529 ss := valueof(facility_ms_req));
3530
3531 /* To be used for sending response with correct session ID */
3532 var GSUP_PDU gsup_ms_req_complete;
3533
3534 /* Initiate a new SS transaction */
3535 BSSAP.send(ts_PDU_DTAP_MO(ussd_ms_req));
3536 /* Expect GSUP request with original Facility IE */
3537 gsup_ms_req_complete := f_expect_gsup_msg(gsup_ms_req);
3538
3539 /* Don't respond, wait for timeout */
3540 f_sleep(3.0);
3541
3542 var template PDU_ML3_NW_MS dtap_rel := tr_ML3_MT_SS_RELEASE_COMPLETE(
3543 tid := 1, /* Should match the request's tid */
3544 ti_flag := c_TIF_REPL, /* Sent to the side that originates the TI */
3545 cause := *, /* TODO: expect some specific value */
3546 facility := omit);
3547
3548 var template GSUP_PDU gsup_rel := tr_GSUP_PROC_SS_ERR(
3549 imsi := g_pars.imsi,
3550 sid := gsup_ms_req_complete.ies[1].val.session_id,
3551 state := OSMO_GSUP_SESSION_STATE_END,
3552 cause := ?); /* TODO: expect some specific value */
3553
3554 /* Expect release on both interfaces */
3555 interleave {
3556 [] BSSAP.receive(tr_PDU_DTAP_MT(dtap_rel)) { };
3557 [] GSUP.receive(gsup_rel) { };
3558 }
3559
3560 f_expect_clear();
3561 setverdict(pass);
3562}
3563testcase TC_lu_and_ss_session_timeout() runs on MTC_CT {
3564 var BSC_ConnHdlr vc_conn;
3565 f_init();
Vadim Yanitskiy36d28dd2018-12-03 02:45:45 +07003566 f_vty_config(MSCVTY, "msc", "ncss guard-timeout 3");
Vadim Yanitskiy0e392dd2018-11-29 00:47:54 +07003567 vc_conn := f_start_handler(refers(f_tc_lu_and_ss_session_timeout), 51);
3568 vc_conn.done;
Vadim Yanitskiy36d28dd2018-12-03 02:45:45 +07003569 f_vty_config(MSCVTY, "msc", "ncss guard-timeout 0");
Vadim Yanitskiy0e392dd2018-11-29 00:47:54 +07003570}
3571
Harald Weltee13cfb22019-04-23 16:52:02 +02003572
Stefan Sperling89eb1f32018-12-17 15:06:20 +01003573/* A5/1 only permitted on network side; attempt an invalid CIPHER MODE COMPLETE with A5/3 which MSC should reject. */
3574private function f_tc_cipher_complete_with_invalid_cipher(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
3575 pars.net.expect_auth := true;
3576 pars.net.expect_ciph := true;
3577 pars.net.kc_support := '02'O; /* A5/1 only */
3578 f_init_handler(pars);
3579
3580 g_pars.vec := f_gen_auth_vec_2g();
3581
3582 /* Can't use f_perform_lu() directly. Code below is based on it. */
3583
3584 /* tell GSUP dispatcher to send this IMSI to us */
3585 f_create_gsup_expect(hex2str(g_pars.imsi));
3586
3587 /* Send BSSAP_Conn_Req with COMPL L3 INFO to MSC */
3588 var PDU_ML3_MS_NW l3_lu := f_build_lu_imsi(g_pars.imsi)
Harald Weltedceacc72019-04-21 20:58:35 +02003589 f_cl3_or_initial_ue(l3_lu);
Stefan Sperling89eb1f32018-12-17 15:06:20 +01003590
3591 f_mm_auth();
3592
3593 var OCT1 a5_net := f_alg_mask_from_cm(g_pars.cm2);
3594 var OCT1 a5_intersect := g_pars.net.kc_support and4b a5_net;
3595 alt {
3596 [] BSSAP.receive(tr_BSSMAP_CipherModeCmd(a5_intersect, g_pars.vec.kc)) {
3597 BSSAP.send(ts_BSSMAP_CipherModeCompl(int2oct(4 /* "accept" A5/3 */, 1)));
3598 }
3599 [] BSSAP.receive(tr_BSSMAP_CipherModeCmd(?, g_pars.vec.kc)) {
3600 setverdict(fail, "Wrong ciphering algorithm mask in CiphModCmd");
3601 mtc.stop;
3602 }
3603 [] BSSAP.receive {
3604 setverdict(fail, "Unknown/unexpected BSSAP received");
3605 mtc.stop;
3606 }
3607 }
3608
3609 /* Expect LU reject from MSC. */
3610 alt {
3611 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Rej)) {
3612 setverdict(pass);
3613 }
3614 [] BSSAP.receive {
3615 setverdict(fail, "Unknown/unexpected BSSAP received");
3616 mtc.stop;
3617 }
3618 }
Stefan Sperlingc620b352018-12-18 17:23:36 +01003619 f_expect_clear();
Stefan Sperling89eb1f32018-12-17 15:06:20 +01003620}
3621
3622testcase TC_cipher_complete_with_invalid_cipher() runs on MTC_CT {
3623 var BSC_ConnHdlr vc_conn;
3624 f_init();
3625 f_vty_config(MSCVTY, "network", "encryption a5 1");
3626
3627 vc_conn := f_start_handler(refers(f_tc_cipher_complete_with_invalid_cipher), 52);
3628 vc_conn.done;
3629}
3630
Harald Weltef640a012018-04-14 17:49:21 +02003631/* TODO (SMS):
3632 * different user data lengths
3633 * SMPP transaction mode with unsuccessful delivery
3634 * queued MT-SMS with no paging response + later delivery
3635 * different data coding schemes
3636 * multi-part SMS
3637 * user-data headers
3638 * TP-PID for SMS to SIM
3639 * behavior if SMS memory is full + RP-SMMA
3640 * delivery reports
3641 * SMPP osmocom extensions
3642 * more-messages-to-send
3643 * SMS during ongoing call (SACCH/SAPI3)
3644 */
3645
3646/* TODO (General):
Harald Welteba7b6d92018-01-23 21:32:34 +01003647 * continue to send repeated MO signalling messages to keep channel open: does MSC tmeout?
3648 * malformed messages (missing IE, invalid message type): properly rejected?
3649 * MT call while LU or is ongoing: Do we use existing lchan or page while lchan active?
3650 * 3G/2G auth permutations
3651 * encryption algorithms vs. classmark vs. vty config
Harald Welteba7b6d92018-01-23 21:32:34 +01003652 * send new transaction after/during clear (like SMS, ...)
Harald Welte45164da2018-01-24 12:51:27 +01003653 * too long L3 INFO in DTAP
3654 * too long / padded BSSAP
3655 * too long / short TLV values
Harald Welteba7b6d92018-01-23 21:32:34 +01003656 */
Harald Weltef6dd64d2017-11-19 12:09:51 +01003657
Harald Weltee13cfb22019-04-23 16:52:02 +02003658/***********************************************************************
3659 * SGsAP Testing
3660 ***********************************************************************/
3661
Philipp Maier948747b2019-04-02 15:22:33 +02003662/* Check if a subscriber exists in the VLR */
3663private function f_ctrl_subscr_in_vlr(charstring imsi_or_msisdn) runs on BSC_ConnHdlr return boolean {
3664
3665 var CtrlValue active_subsribers;
3666 var integer rc;
3667 active_subsribers := f_ctrl_get(IPA_CTRL, "subscriber-list-active-v1");
3668
3669 rc := f_strstr(active_subsribers, imsi_or_msisdn);
3670 if (rc < 0) {
3671 return false;
3672 }
3673
3674 return true;
3675}
3676
Harald Welte4263c522018-12-06 11:56:27 +01003677/* Perform a location updatye at the A-Interface and run some checks to confirm
3678 * that everything is back to normal. */
3679private function f_sgsap_bssmap_screening() runs on BSC_ConnHdlr {
3680 var SmsParameters spars := valueof(t_SmsPars);
3681
3682 /* Perform a location update, the SGs association is expected to fall
3683 * back to NULL */
3684 f_perform_lu();
3685 f_ctrl_get_exp(IPA_CTRL, "fsm.SGs-UE.id.imsi:" & hex2str(g_pars.imsi) & ".state", "SGs-NULL");
3686
3687 /* Trigger a paging request and expect the paging on BSSMAP, this is
3688 * to make sure that pagings are sent throught the A-Interface again
3689 * and not throught the SGs interface.*/
Harald Welte6811d102019-04-14 22:23:14 +02003690 f_ran_register_imsi(g_pars.imsi, g_pars.tmsi);
Harald Welte4263c522018-12-06 11:56:27 +01003691 f_vty_transceive(MSCVTY, "subscriber imsi " & hex2str(g_pars.imsi) & " paging");
3692
3693 alt {
Harald Weltee13cfb22019-04-23 16:52:02 +02003694 [g_pars.ran_is_geran] BSSAP.receive(tr_BSSMAP_Paging(g_pars.imsi)); {
3695 setverdict(pass);
3696 }
3697 [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 +01003698 setverdict(pass);
3699 }
3700 [] SGsAP.receive {
3701 setverdict(fail, "Received unexpected message on SGs");
3702 }
3703 }
3704
3705 /* Send an SMS to make sure that also payload messages are routed
3706 * throught the A-Interface again */
3707 f_establish_fully(EST_TYPE_MO_SMS);
3708 f_mo_sms(spars);
3709 f_expect_clear();
3710}
3711
3712private function f_tc_sgsap_reset(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
3713 var charstring vlr_name;
3714 f_init_handler(pars);
3715
3716 vlr_name := f_sgsap_reset_mme(mp_mme_name);
3717 log("VLR name: ", vlr_name);
3718 setverdict(pass);
Neels Hofmeyrc0b520d2019-03-06 15:35:50 +01003719 f_sleep(1.0);
Harald Welte4263c522018-12-06 11:56:27 +01003720}
3721
3722testcase TC_sgsap_reset() runs on MTC_CT {
Philipp Maier8e07a4a2019-02-14 18:23:28 +01003723 var BSC_ConnHdlrPars pars;
Harald Welte4263c522018-12-06 11:56:27 +01003724 var BSC_ConnHdlr vc_conn;
Philipp Maier8e07a4a2019-02-14 18:23:28 +01003725 f_init(1, true);
3726 pars := f_init_pars(11810, true);
3727 vc_conn := f_start_handler_with_pars(refers(f_tc_sgsap_reset), pars);
Harald Welte4263c522018-12-06 11:56:27 +01003728 vc_conn.done;
3729}
3730
3731/* like f_mm_auth() but for SGs */
3732function f_mm_auth_sgs() runs on BSC_ConnHdlr {
3733 if (g_pars.net.expect_auth) {
3734 g_pars.vec := f_gen_auth_vec_3g();
3735 var GSUP_IE auth_tuple := valueof(ts_GSUP_IE_AuthTuple2G3G(g_pars.vec.rand,
3736 g_pars.vec.sres,
3737 g_pars.vec.kc,
3738 g_pars.vec.ik,
3739 g_pars.vec.ck,
3740 g_pars.vec.autn,
3741 g_pars.vec.res));
3742 GSUP.receive(tr_GSUP_SAI_REQ(g_pars.imsi));
3743 GSUP.send(ts_GSUP_SAI_RES(g_pars.imsi, auth_tuple));
3744 SGsAP.receive(tr_ML3_MT_MM_AUTH_REQ_3G(g_pars.vec.rand, g_pars.vec.autn));
3745 SGsAP.send(ts_ML3_MT_MM_AUTH_RESP_3G(g_pars.vec.sres, g_pars.vec.res));
3746 }
3747}
3748
3749/* like f_perform_lu(), but on SGs rather than BSSAP */
3750function f_sgs_perform_lu() runs on BSC_ConnHdlr {
3751 var octetstring mme_name := f_enc_dns_hostname(mp_mme_name);
3752 var PDU_SGsAP lur;
3753 var PDU_SGsAP lua;
3754 var PDU_SGsAP mm_info;
3755 var octetstring mm_info_dtap;
3756
3757 /* tell GSUP dispatcher to send this IMSI to us */
3758 f_create_gsup_expect(hex2str(g_pars.imsi));
3759
3760 lur := valueof(ts_SGsAP_LU_REQ(g_pars.imsi, mme_name, IMSI_attach,
3761 ts_SGsAP_LAI('901'H, '70'H, 2342)));
3762 /* Old LAI, if MS sends it */
3763 /* TMSI status, if MS has no valid TMSI */
3764 /* IMEISV, if it supports "automatic device detection" */
3765 /* TAI, if available in MME */
3766 /* E-CGI, if available in MME */
3767 SGsAP.send(lur);
3768
3769 /* FIXME: is this really done over SGs? The Ue is already authenticated
3770 * via the MME ... */
3771 f_mm_auth_sgs();
3772
3773 /* Expect MSC to perform LU with HLR */
3774 GSUP.receive(tr_GSUP_UL_REQ(g_pars.imsi));
3775 GSUP.send(ts_GSUP_ISD_REQ(g_pars.imsi, g_pars.msisdn));
3776 GSUP.receive(tr_GSUP_ISD_RES(g_pars.imsi));
3777 GSUP.send(ts_GSUP_UL_RES(g_pars.imsi));
3778
3779 alt {
3780 [] SGsAP.receive(tr_SGsAP_LU_ACCEPT(g_pars.imsi, ?)) -> value lua {
3781 if (isvalue(lua.sGsAP_LOCATION_UPDATE_ACCEPT.newTMSIorIMSI.iD.iD.tmsi_ptmsi.octets)) {
3782 g_pars.tmsi :=lua.sGsAP_LOCATION_UPDATE_ACCEPT.newTMSIorIMSI.iD.iD.tmsi_ptmsi.octets
3783 SGsAP.send(ts_SGsAP_TMSI_REALL_CMPL(g_pars.imsi));
3784 }
3785 setverdict(pass);
3786 }
3787 [] SGsAP.receive(tr_SGsAP_LU_REJECT(g_pars.imsi, ?, ?)) {
3788 setverdict(fail, "Received LU-REJECT instead of ACCEPT");
3789 }
3790 [] SGsAP.receive {
3791 setverdict(fail, "Received unexpected message on SGs");
3792 }
3793 }
3794
3795 /* Check MM information */
3796 if (mp_mm_info == true) {
3797 SGsAP.receive(tr_SGsAP_MM_INFO_REQ(g_pars.imsi, ?)) -> value mm_info;
3798 mm_info_dtap := '0532'O & mm_info.sGsAP_MM_INFORMATION_REQUEST.mM_Information.information;
3799 if (not match(dec_PDU_ML3_NW_MS(mm_info_dtap), tr_ML3_MT_MM_Info)) {
3800 setverdict(fail, "Unexpected MM Information");
3801 }
3802 }
3803
3804 f_ctrl_get_exp(IPA_CTRL, "fsm.SGs-UE.id.imsi:" & hex2str(g_pars.imsi) & ".state", "SGs-ASSOCIATED");
3805}
3806
3807private function f_tc_sgsap_lu(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
3808 f_init_handler(pars);
3809 f_sgs_perform_lu();
3810 f_ctrl_get_exp(IPA_CTRL, "fsm.SGs-UE.id.imsi:" & hex2str(g_pars.imsi) & ".state", "SGs-ASSOCIATED");
3811
3812 f_sgsap_bssmap_screening();
3813
3814 setverdict(pass);
3815}
3816testcase TC_sgsap_lu() runs on MTC_CT {
Philipp Maier8e07a4a2019-02-14 18:23:28 +01003817 var BSC_ConnHdlrPars pars;
Harald Welte4263c522018-12-06 11:56:27 +01003818 var BSC_ConnHdlr vc_conn;
Philipp Maier8e07a4a2019-02-14 18:23:28 +01003819 f_init(1, true);
3820 pars := f_init_pars(11811, true);
3821 vc_conn := f_start_handler_with_pars(refers(f_tc_sgsap_lu), pars);
Harald Welte4263c522018-12-06 11:56:27 +01003822 vc_conn.done;
3823}
3824
3825/* Do LU by IMSI, refuse it on GSUP and expect LU REJ back to MS */
3826private function f_tc_sgsap_lu_imsi_reject(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
3827 f_init_handler(pars);
3828 var PDU_SGsAP lur;
3829
3830 f_create_gsup_expect(hex2str(g_pars.imsi));
3831 var octetstring mme_name := f_enc_dns_hostname(mp_mme_name);
3832 lur := valueof(ts_SGsAP_LU_REQ(g_pars.imsi, mme_name, IMSI_attach,
3833 ts_SGsAP_LAI('901'H, '70'H, 2342)));
3834 SGsAP.send(lur);
3835
3836 GSUP.receive(tr_GSUP_UL_REQ(g_pars.imsi));
3837 GSUP.send(ts_GSUP_UL_ERR(g_pars.imsi, 23));
3838 alt {
3839 [] SGsAP.receive(tr_SGsAP_LU_REJECT(g_pars.imsi, ?, ?)) {
3840 setverdict(pass);
3841 }
3842 [] SGsAP.receive(tr_SGsAP_LU_ACCEPT(g_pars.imsi, ?)) {
3843 setverdict(fail, "Expecting LU REJ, but got ACCEPT");
3844 mtc.stop;
3845 }
3846 [] SGsAP.receive {
3847 setverdict(fail, "Received unexpected message on SGs");
3848 }
3849 }
3850
3851 f_sgsap_bssmap_screening();
3852
3853 setverdict(pass);
3854}
3855testcase TC_sgsap_lu_imsi_reject() runs on MTC_CT {
Philipp Maier8e07a4a2019-02-14 18:23:28 +01003856 var BSC_ConnHdlrPars pars;
Harald Welte4263c522018-12-06 11:56:27 +01003857 var BSC_ConnHdlr vc_conn;
Philipp Maier8e07a4a2019-02-14 18:23:28 +01003858 f_init(1, true);
3859 pars := f_init_pars(11812, true);
Harald Welte4263c522018-12-06 11:56:27 +01003860
Philipp Maier8e07a4a2019-02-14 18:23:28 +01003861 vc_conn := f_start_handler_with_pars(refers(f_tc_sgsap_lu_imsi_reject), pars);
Harald Welte4263c522018-12-06 11:56:27 +01003862 vc_conn.done;
3863}
3864
3865/* Do LU by IMSI, but then remain silent so that Ts6-1 times out */
3866private function f_tc_sgsap_lu_and_nothing(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
3867 var octetstring mme_name := f_enc_dns_hostname(mp_mme_name);
3868 var PDU_SGsAP lur;
3869
3870 f_init_handler(pars);
3871
3872 /* tell GSUP dispatcher to send this IMSI to us */
3873 f_create_gsup_expect(hex2str(g_pars.imsi));
3874
3875 lur := valueof(ts_SGsAP_LU_REQ(g_pars.imsi, mme_name, IMSI_attach,
3876 ts_SGsAP_LAI('901'H, '70'H, 2342)));
3877 /* Old LAI, if MS sends it */
3878 /* TMSI status, if MS has no valid TMSI */
3879 /* IMEISV, if it supports "automatic device detection" */
3880 /* TAI, if available in MME */
3881 /* E-CGI, if available in MME */
3882 SGsAP.send(lur);
3883
3884 /* FIXME: is this really done over SGs? The Ue is already authenticated
3885 * via the MME ... */
3886 f_mm_auth_sgs();
3887
3888 /* Expect MSC to perform LU with HLR */
3889 GSUP.receive(tr_GSUP_UL_REQ(g_pars.imsi));
3890 GSUP.send(ts_GSUP_ISD_REQ(g_pars.imsi, g_pars.msisdn));
3891 GSUP.receive(tr_GSUP_ISD_RES(g_pars.imsi));
3892 GSUP.send(ts_GSUP_UL_RES(g_pars.imsi));
3893
3894 alt {
3895 [] SGsAP.receive(tr_SGsAP_LU_ACCEPT(g_pars.imsi, ?)) {
3896 setverdict(pass);
3897 }
3898 [] SGsAP.receive(tr_SGsAP_LU_REJECT(g_pars.imsi, ?, ?)) {
3899 setverdict(fail, "Received LU-REJECT instead of ACCEPT");
3900 }
3901 [] SGsAP.receive {
3902 setverdict(fail, "Received unexpected message on SGs");
3903 }
3904 }
3905
3906 f_ctrl_get_exp(IPA_CTRL, "fsm.SGs-UE.id.imsi:" & hex2str(g_pars.imsi) & ".state", "SGs-ASSOCIATED");
3907
3908 /* Wait until the VLR has abort the TMSI reallocation procedure */
3909 f_sleep(45.0);
3910
3911 /* The outcome does not change the SGs state, see also 5.2.3.4 */
3912 f_ctrl_get_exp(IPA_CTRL, "fsm.SGs-UE.id.imsi:" & hex2str(g_pars.imsi) & ".state", "SGs-ASSOCIATED");
3913
3914 f_sgsap_bssmap_screening();
3915
3916 setverdict(pass);
3917}
3918testcase TC_sgsap_lu_and_nothing() runs on MTC_CT {
Philipp Maier8e07a4a2019-02-14 18:23:28 +01003919 var BSC_ConnHdlrPars pars;
Harald Welte4263c522018-12-06 11:56:27 +01003920 var BSC_ConnHdlr vc_conn;
Philipp Maier8e07a4a2019-02-14 18:23:28 +01003921 f_init(1, true);
3922 pars := f_init_pars(11813, true);
Harald Welte4263c522018-12-06 11:56:27 +01003923
Philipp Maier8e07a4a2019-02-14 18:23:28 +01003924 vc_conn := f_start_handler_with_pars(refers(f_tc_sgsap_lu_and_nothing), pars);
Harald Welte4263c522018-12-06 11:56:27 +01003925 vc_conn.done;
3926}
3927
3928private function f_tc_sgsap_expl_imsi_det_eps(charstring id, BSC_ConnHdlrPars pars)
3929runs on BSC_ConnHdlr {
3930 f_init_handler(pars);
3931 f_sgs_perform_lu();
3932 f_sleep(3.0);
3933
3934 var octetstring mme_name := f_enc_dns_hostname(mp_mme_name);
3935 SGsAP.send(ts_SGsAP_EPS_DETACH_IND(g_pars.imsi, mme_name, UE_initiated));
3936 SGsAP.receive(tr_SGsAP_EPS_DETACH_ACK(g_pars.imsi));
3937 f_ctrl_get_exp(IPA_CTRL, "fsm.SGs-UE.id.imsi:" & hex2str(g_pars.imsi) & ".state", "SGs-NULL");
3938
3939 f_sgsap_bssmap_screening();
3940
3941 setverdict(pass);
3942}
3943testcase TC_sgsap_expl_imsi_det_eps() runs on MTC_CT {
Philipp Maier8e07a4a2019-02-14 18:23:28 +01003944 var BSC_ConnHdlrPars pars;
Harald Welte4263c522018-12-06 11:56:27 +01003945 var BSC_ConnHdlr vc_conn;
Philipp Maier8e07a4a2019-02-14 18:23:28 +01003946 f_init(1, true);
3947 pars := f_init_pars(11814, true);
3948 vc_conn := f_start_handler_with_pars(refers(f_tc_sgsap_expl_imsi_det_eps), pars);
Harald Welte4263c522018-12-06 11:56:27 +01003949 vc_conn.done;
3950}
3951
Philipp Maierfc19f172019-03-21 11:17:54 +01003952private function f_tc_sgsap_impl_imsi_det_eps(charstring id, BSC_ConnHdlrPars pars)
3953runs on BSC_ConnHdlr {
3954 f_init_handler(pars);
3955 f_sgs_perform_lu();
3956 f_sleep(3.0);
3957
3958 var octetstring mme_name := f_enc_dns_hostname(mp_mme_name);
3959 SGsAP.send(ts_SGsAP_EPS_DETACH_IND(g_pars.imsi, mme_name, network_initiated));
3960 SGsAP.receive(tr_SGsAP_EPS_DETACH_ACK(g_pars.imsi));
3961 f_ctrl_get_exp(IPA_CTRL, "fsm.SGs-UE.id.imsi:" & hex2str(g_pars.imsi) & ".state", "SGs-NULL");
3962
3963 f_sgsap_bssmap_screening();
3964
3965 setverdict(pass);
3966}
3967testcase TC_sgsap_impl_imsi_det_eps() runs on MTC_CT {
3968 var BSC_ConnHdlrPars pars;
3969 var BSC_ConnHdlr vc_conn;
3970 f_init(1, true);
3971 pars := f_init_pars(11814, true);
3972 vc_conn := f_start_handler_with_pars(refers(f_tc_sgsap_impl_imsi_det_eps), pars);
3973 vc_conn.done;
3974}
3975
Harald Welte4263c522018-12-06 11:56:27 +01003976private function f_tc_sgsap_expl_imsi_det_noneps(charstring id, BSC_ConnHdlrPars pars)
3977runs on BSC_ConnHdlr {
3978 f_init_handler(pars);
3979 f_sgs_perform_lu();
3980 f_sleep(3.0);
3981
3982 var octetstring mme_name := f_enc_dns_hostname(mp_mme_name);
3983 SGsAP.send(ts_SGsAP_IMSI_DETACH_IND(g_pars.imsi, mme_name, combined_UE_initiated));
3984 SGsAP.receive(tr_SGsAP_IMSI_DETACH_ACK(g_pars.imsi));
Philipp Maierd08e7e72019-04-02 15:27:10 +02003985
3986 if (f_ctrl_subscr_in_vlr(hex2str(g_pars.imsi))) {
3987 setverdict(fail, "subscriber not removed from VLR");
3988 }
Harald Welte4263c522018-12-06 11:56:27 +01003989
3990 f_sgsap_bssmap_screening();
3991
3992 setverdict(pass);
3993}
3994testcase TC_sgsap_expl_imsi_det_noneps() runs on MTC_CT {
Philipp Maier8e07a4a2019-02-14 18:23:28 +01003995 var BSC_ConnHdlrPars pars;
Harald Welte4263c522018-12-06 11:56:27 +01003996 var BSC_ConnHdlr vc_conn;
Philipp Maier8e07a4a2019-02-14 18:23:28 +01003997 f_init(1, true);
3998 pars := f_init_pars(11815, true);
3999 vc_conn := f_start_handler_with_pars(refers(f_tc_sgsap_expl_imsi_det_noneps), pars);
Harald Welte4263c522018-12-06 11:56:27 +01004000 vc_conn.done;
4001}
4002
Philipp Maier5d812702019-03-21 10:51:26 +01004003private function f_tc_sgsap_impl_imsi_det_noneps(charstring id, BSC_ConnHdlrPars pars)
4004runs on BSC_ConnHdlr {
4005 f_init_handler(pars);
4006 f_sgs_perform_lu();
4007 f_sleep(3.0);
4008
4009 var octetstring mme_name := f_enc_dns_hostname(mp_mme_name);
4010 SGsAP.send(ts_SGsAP_IMSI_DETACH_IND(g_pars.imsi, mme_name, implicit_network_initiated));
4011 SGsAP.receive(tr_SGsAP_IMSI_DETACH_ACK(g_pars.imsi));
4012
4013 if (f_ctrl_subscr_in_vlr(hex2str(g_pars.imsi))) {
4014 setverdict(fail, "subscriber not removed from VLR");
4015 }
4016
4017 f_sgsap_bssmap_screening();
4018
4019 setverdict(pass);
4020}
4021testcase TC_sgsap_impl_imsi_det_noneps() runs on MTC_CT {
4022 var BSC_ConnHdlrPars pars;
4023 var BSC_ConnHdlr vc_conn;
4024 f_init(1, true);
4025 pars := f_init_pars(11815, true);
4026 vc_conn := f_start_handler_with_pars(refers(f_tc_sgsap_impl_imsi_det_noneps), pars);
4027 vc_conn.done;
4028}
4029
Harald Welte4263c522018-12-06 11:56:27 +01004030/* Trigger a paging request via VTY and send a paging reject in response */
4031private function f_tc_sgsap_paging_rej(charstring id, BSC_ConnHdlrPars pars)
4032runs on BSC_ConnHdlr {
4033 f_init_handler(pars);
4034 f_sgs_perform_lu();
4035 f_sleep(1.0);
4036
4037 var octetstring vlr_name := f_enc_dns_hostname(mp_vlr_name);
4038 var template PDU_SGsAP exp_resp := tr_SGsAP_PAGING_REQ(g_pars.imsi, vlr_name, CS_call_indicator, omit);
4039 var template LocationAreaId exp_lai := ts_SGsAP_IE_Lai(valueof(ts_SGsAP_LAI('901'H, '70'H, 2342)));
4040 exp_resp.sGsAP_PAGING_REQUEST.locationAreaId := exp_lai;
4041
4042 /* Initiate paging via VTY */
4043 f_vty_transceive(MSCVTY, "subscriber imsi " & hex2str(g_pars.imsi) & " paging");
4044 alt {
4045 [] SGsAP.receive(exp_resp) {
4046 setverdict(pass);
4047 }
4048 [] SGsAP.receive {
4049 setverdict(fail, "Received unexpected message on SGs");
4050 }
4051 }
4052
4053 /* Now reject the paging */
4054 SGsAP.send(ts_SGsAP_PAGING_REJ(g_pars.imsi, IMSI_unknown));
4055
4056 /* Wait for the states inside the MSC to settle and check the state
4057 * of the SGs Association */
4058 f_sleep(1.0);
4059 f_ctrl_get_exp(IPA_CTRL, "fsm.SGs-UE.id.imsi:" & hex2str(g_pars.imsi) & ".state", "SGs-NULL");
4060
4061 /* FIXME: At the moment we send an IMSI_unknown as cause code, which is fine,
4062 * but we also need to cover tha case where the cause code indicates an
4063 * "IMSI detached for EPS services". In those cases the VLR is expected to
4064 * try paging on tha A/Iu interface. This will be another testcase similar to
4065 * this one, but extended with checks for the presence of the A/Iu paging
4066 * messages. */
4067
4068 f_sgsap_bssmap_screening();
4069
4070 setverdict(pass);
4071}
4072testcase TC_sgsap_paging_rej() runs on MTC_CT {
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004073 var BSC_ConnHdlrPars pars;
Harald Welte4263c522018-12-06 11:56:27 +01004074 var BSC_ConnHdlr vc_conn;
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004075 f_init(1, true);
4076 pars := f_init_pars(11816, true);
4077 vc_conn := f_start_handler_with_pars(refers(f_tc_sgsap_paging_rej), pars);
Harald Welte4263c522018-12-06 11:56:27 +01004078 vc_conn.done;
4079}
4080
4081/* Trigger a paging request via VTY and send a paging reject that indicates
4082 * that the subscriber intentionally rejected the call. */
4083private function f_tc_sgsap_paging_subscr_rej(charstring id, BSC_ConnHdlrPars pars)
4084runs on BSC_ConnHdlr {
4085 f_init_handler(pars);
4086 f_sgs_perform_lu();
4087 f_sleep(1.0);
4088
4089 var octetstring vlr_name := f_enc_dns_hostname(mp_vlr_name);
4090 var template PDU_SGsAP exp_resp := tr_SGsAP_PAGING_REQ(g_pars.imsi, vlr_name, CS_call_indicator, omit);
4091 var template LocationAreaId exp_lai := ts_SGsAP_IE_Lai(valueof(ts_SGsAP_LAI('901'H, '70'H, 2342)));
4092 exp_resp.sGsAP_PAGING_REQUEST.locationAreaId := exp_lai;
4093
4094 /* Initiate paging via VTY */
4095 f_vty_transceive(MSCVTY, "subscriber imsi " & hex2str(g_pars.imsi) & " paging");
4096 alt {
4097 [] SGsAP.receive(exp_resp) {
4098 setverdict(pass);
4099 }
4100 [] SGsAP.receive {
4101 setverdict(fail, "Received unexpected message on SGs");
4102 }
4103 }
4104
4105 /* Now reject the paging */
4106 SGsAP.send(ts_SGsAP_PAGING_REJ(g_pars.imsi, user_rejected_mobile_terminating_CS_fallback_call));
4107
4108 /* Wait for the states inside the MSC to settle and check the state
4109 * of the SGs Association */
4110 f_sleep(1.0);
4111 f_ctrl_get_exp(IPA_CTRL, "fsm.SGs-UE.id.imsi:" & hex2str(g_pars.imsi) & ".state", "SGs-ASSOCIATED");
4112
4113 /* FIXME: The VLR is supposed to trigger an User Determined User Busy (UDUB) as specified
4114 * in 3GPP TS 24.082, this is not yet implemented in the MSC or in this tests, we need
4115 * to check back how this works and how it can be tested */
4116
4117 f_sgsap_bssmap_screening();
4118
4119 setverdict(pass);
4120}
4121testcase TC_sgsap_paging_subscr_rej() runs on MTC_CT {
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004122 var BSC_ConnHdlrPars pars;
Harald Welte4263c522018-12-06 11:56:27 +01004123 var BSC_ConnHdlr vc_conn;
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004124 f_init(1, true);
4125 pars := f_init_pars(11817, true);
4126 vc_conn := f_start_handler_with_pars(refers(f_tc_sgsap_paging_subscr_rej), pars);
Harald Welte4263c522018-12-06 11:56:27 +01004127 vc_conn.done;
4128}
4129
4130/* Trigger a paging request via VTY and send an UE unreacable messge in response */
4131private function f_tc_sgsap_paging_ue_unr(charstring id, BSC_ConnHdlrPars pars)
4132runs on BSC_ConnHdlr {
4133 f_init_handler(pars);
4134 f_sgs_perform_lu();
4135 f_sleep(1.0);
4136
4137 var octetstring vlr_name := f_enc_dns_hostname(mp_vlr_name);
4138 var template PDU_SGsAP exp_resp := tr_SGsAP_PAGING_REQ(g_pars.imsi, vlr_name, CS_call_indicator, omit);
4139 var template LocationAreaId exp_lai := ts_SGsAP_IE_Lai(valueof(ts_SGsAP_LAI('901'H, '70'H, 2342)));
4140 exp_resp.sGsAP_PAGING_REQUEST.locationAreaId := exp_lai;
4141
4142 /* Initiate paging via VTY */
4143 f_vty_transceive(MSCVTY, "subscriber imsi " & hex2str(g_pars.imsi) & " paging");
4144 alt {
4145 [] SGsAP.receive(exp_resp) {
4146 setverdict(pass);
4147 }
4148 [] SGsAP.receive {
4149 setverdict(fail, "Received unexpected message on SGs");
4150 }
4151 }
4152
4153 /* Now pretend that the UE is unreachable */
4154 SGsAP.send(ts_SGsAP_UE_UNREACHABLE(g_pars.imsi, UE_unreachable));
4155
4156 /* Wait for the states inside the MSC to settle and check the state
4157 * of the SGs Association. */
4158 f_sleep(1.0);
4159 f_ctrl_get_exp(IPA_CTRL, "fsm.SGs-UE.id.imsi:" & hex2str(g_pars.imsi) & ".state", "SGs-ASSOCIATED");
4160
4161 f_sgsap_bssmap_screening();
4162
4163 setverdict(pass);
4164}
4165testcase TC_sgsap_paging_ue_unr() runs on MTC_CT {
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004166 var BSC_ConnHdlrPars pars;
Harald Welte4263c522018-12-06 11:56:27 +01004167 var BSC_ConnHdlr vc_conn;
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004168 f_init(1, true);
4169 pars := f_init_pars(11818, true);
4170 vc_conn := f_start_handler_with_pars(refers(f_tc_sgsap_paging_ue_unr), pars);
Harald Welte4263c522018-12-06 11:56:27 +01004171 vc_conn.done;
4172}
4173
4174/* Trigger a paging request via VTY but don't respond to it */
4175private function f_tc_sgsap_paging_and_nothing(charstring id, BSC_ConnHdlrPars pars)
4176runs on BSC_ConnHdlr {
4177 f_init_handler(pars);
4178 f_sgs_perform_lu();
4179 f_sleep(1.0);
4180
4181 var octetstring vlr_name := f_enc_dns_hostname(mp_vlr_name);
4182 var template PDU_SGsAP exp_resp := tr_SGsAP_PAGING_REQ(g_pars.imsi, vlr_name, CS_call_indicator, omit);
4183 var template LocationAreaId exp_lai := ts_SGsAP_IE_Lai(valueof(ts_SGsAP_LAI('901'H, '70'H, 2342)));
4184 exp_resp.sGsAP_PAGING_REQUEST.locationAreaId := exp_lai;
4185
4186 /* Initiate paging via VTY */
4187 f_vty_transceive(MSCVTY, "subscriber imsi " & hex2str(g_pars.imsi) & " paging");
4188 alt {
4189 [] SGsAP.receive(exp_resp) {
4190 setverdict(pass);
4191 }
4192 [] SGsAP.receive {
4193 setverdict(fail, "Received unexpected message on SGs");
4194 }
4195 }
4196
4197 /* Now do nothing, the MSC/VLR should fail silently to page after a
4198 * few seconds, The SGs association must remain unchanged. */
4199 f_sleep(15.0);
4200 f_ctrl_get_exp(IPA_CTRL, "fsm.SGs-UE.id.imsi:" & hex2str(g_pars.imsi) & ".state", "SGs-ASSOCIATED");
4201
4202 f_sgsap_bssmap_screening();
4203
4204 setverdict(pass);
4205}
4206testcase TC_sgsap_paging_and_nothing() runs on MTC_CT {
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004207 var BSC_ConnHdlrPars pars;
Harald Welte4263c522018-12-06 11:56:27 +01004208 var BSC_ConnHdlr vc_conn;
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004209 f_init(1, true);
4210 pars := f_init_pars(11819, true);
4211 vc_conn := f_start_handler_with_pars(refers(f_tc_sgsap_paging_and_nothing), pars);
Harald Welte4263c522018-12-06 11:56:27 +01004212 vc_conn.done;
4213}
4214
4215/* Trigger a paging request via VTY and slip in an LU */
4216private function f_tc_sgsap_paging_and_lu(charstring id, BSC_ConnHdlrPars pars)
4217runs on BSC_ConnHdlr {
4218 var octetstring vlr_name := f_enc_dns_hostname(mp_vlr_name);
4219 f_init_handler(pars);
4220
4221 /* First we prepar the situation, where the SGs association is in state
4222 * NULL and the confirmed by radio contact indicator is set to false
4223 * as well. This can be archived by performing an SGs LU and then
4224 * resetting the VLR */
4225 f_sgs_perform_lu();
4226 f_sgsap_reset_mme(mp_mme_name);
4227 f_sleep(1.0);
4228 f_ctrl_get_exp(IPA_CTRL, "fsm.SGs-UE.id.imsi:" & hex2str(g_pars.imsi) & ".state", "SGs-NULL");
4229
4230 /* Perform a paging, expect the paging messages on the SGs interface */
4231 f_vty_transceive(MSCVTY, "subscriber imsi " & hex2str(g_pars.imsi) & " paging");
4232 alt {
4233 [] SGsAP.receive(tr_SGsAP_PAGING_REQ(pars.imsi, vlr_name, CS_call_indicator, omit)) {
4234 setverdict(pass);
4235 }
4236 [] SGsAP.receive {
4237 setverdict(fail, "Received unexpected message on SGs");
4238 }
4239 }
4240
4241 /* Perform the LU as normal */
4242 f_sgs_perform_lu();
4243 f_ctrl_get_exp(IPA_CTRL, "fsm.SGs-UE.id.imsi:" & hex2str(g_pars.imsi) & ".state", "SGs-ASSOCIATED");
4244
4245 /* Expect a new paging request right after the LU */
4246 alt {
4247 [] SGsAP.receive(tr_SGsAP_PAGING_REQ(pars.imsi, vlr_name, CS_call_indicator, omit)) {
4248 setverdict(pass);
4249 }
4250 [] SGsAP.receive {
4251 setverdict(fail, "Received unexpected message on SGs");
4252 }
4253 }
4254
4255 /* Test is done now, lets round everything up by rejecting the paging
4256 * cleanly. */
4257 SGsAP.send(ts_SGsAP_PAGING_REJ(g_pars.imsi, user_rejected_mobile_terminating_CS_fallback_call));
4258 f_ctrl_get_exp(IPA_CTRL, "fsm.SGs-UE.id.imsi:" & hex2str(g_pars.imsi) & ".state", "SGs-ASSOCIATED");
4259
4260 f_sgsap_bssmap_screening();
4261
4262 setverdict(pass);
4263}
4264testcase TC_sgsap_paging_and_lu() runs on MTC_CT {
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004265 var BSC_ConnHdlrPars pars;
Harald Welte4263c522018-12-06 11:56:27 +01004266 var BSC_ConnHdlr vc_conn;
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004267 f_init(1, true);
4268 pars := f_init_pars(11820, true);
4269 vc_conn := f_start_handler_with_pars(refers(f_tc_sgsap_paging_and_lu), pars);
Harald Welte4263c522018-12-06 11:56:27 +01004270 vc_conn.done;
4271}
4272
4273/* Send unexpected unit-data through the SGs interface */
4274private function f_tc_sgsap_unexp_ud(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
4275 f_init_handler(pars);
4276 f_sleep(1.0);
4277
4278 /* This simulates what happens when a subscriber without SGs
4279 * association gets unitdata via the SGs interface. */
4280
4281 /* Make sure the subscriber exists and the SGs association
4282 * is in NULL state */
4283 f_perform_lu();
4284 f_ctrl_get_exp(IPA_CTRL, "fsm.SGs-UE.id.imsi:" & hex2str(g_pars.imsi) & ".state", "SGs-NULL");
4285
4286 /* Send some random unit data, the MSC/VLR should send a release
4287 * immediately. */
4288 SGsAP.send(ts_SGsAP_UL_UD(pars.imsi,'1234'O));
4289 SGsAP.receive(tr_SGsAP_RELEASE_REQ(pars.imsi, IMSI_detached_for_EPS_nonEPS_services));
4290
4291 f_sgsap_bssmap_screening();
4292
4293 setverdict(pass);
4294}
4295testcase TC_sgsap_unexp_ud() runs on MTC_CT {
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004296 var BSC_ConnHdlrPars pars;
Harald Welte4263c522018-12-06 11:56:27 +01004297 var BSC_ConnHdlr vc_conn;
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004298 f_init(1, true);
4299 pars := f_init_pars(11821, true);
4300 vc_conn := f_start_handler_with_pars(refers(f_tc_sgsap_unexp_ud), pars);
Harald Welte4263c522018-12-06 11:56:27 +01004301 vc_conn.done;
4302}
4303
4304/* Send unsolicited unit-data through the SGs interface */
4305private function f_tc_sgsap_unsol_ud(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
4306 f_init_handler(pars);
4307 f_sleep(1.0);
4308
4309 /* This simulates what happens when the MME attempts to send unitdata
4310 * to a subscriber that is completely unknown to the VLR */
4311
4312 /* Send some random unit data, the MSC/VLR should send a release
4313 * immediately. */
4314 SGsAP.send(ts_SGsAP_UL_UD(pars.imsi,'1234'O));
4315 SGsAP.receive(tr_SGsAP_RELEASE_REQ(pars.imsi, IMSI_unknown));
4316
4317 f_sgsap_bssmap_screening();
4318
4319 setverdict(pass);
4320}
4321testcase TC_sgsap_unsol_ud() runs on MTC_CT {
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004322 var BSC_ConnHdlrPars pars;
Harald Welte4263c522018-12-06 11:56:27 +01004323 var BSC_ConnHdlr vc_conn;
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004324 f_init(1, true);
4325 pars := f_init_pars(11822, true);
4326 vc_conn := f_start_handler_with_pars(refers(f_tc_sgsap_unsol_ud), pars);
Harald Welte4263c522018-12-06 11:56:27 +01004327 vc_conn.done;
4328}
4329
4330private altstep as_other_sms_sgs() runs on BSC_ConnHdlr {
4331 /* FIXME: Match an actual payload (second questionmark), the type is
4332 * octetstring, how do we use a tr_PDU_DTAP_MT here? */
4333 [] SGsAP.receive(tr_SGsAP_DL_UD(?,?)) {
4334 setverdict(fail, "Unexpected SMS related PDU from MSC");
4335 mtc.stop;
4336 }
4337}
4338
4339/* receive a MT-SMS delivered from the MSC/SMSC over an already existing SGsAP connection */
4340function f_mt_sms_sgs(inout SmsParameters spars)
4341runs on BSC_ConnHdlr {
4342 var template (value) TPDU_RP_DATA_MS_SGSN tp_mo;
4343 var template (value) RPDU_MS_SGSN rp_mo;
4344 var template (value) PDU_ML3_MS_NW l3_mo;
4345
4346 var template TPDU_RP_DATA_SGSN_MS tp_mt;
4347 var template RPDU_SGSN_MS rp_mt;
4348 var template PDU_ML3_NW_MS l3_mt;
4349
4350 var PDU_ML3_NW_MS sgsap_l3_mt;
4351
4352 var default d := activate(as_other_sms_sgs());
4353
4354 /* Expect CP-DATA(RP-DATA(SMS-DELIVER)) */
4355 tp_mt := tr_SMS_DELIVER(?, spars.tp.ud, spars.tp.pid, spars.tp.dcs, ?);
4356 rp_mt := tr_RP_DATA_MT(?, ?, omit, tp_mt);
4357 l3_mt := tr_ML3_MT_SMS(?, c_TIF_ORIG, tr_CP_DATA_MT(rp_mt));
4358
4359 SGsAP.receive(l3_mt) -> value sgsap_l3_mt;
4360
4361 /* Extract relevant identifiers */
4362 spars.tid := bit2int(sgsap_l3_mt.tiOrSkip.transactionId.tio);
4363 spars.rp.msg_ref := sgsap_l3_mt.msgs.sms.cP_DATA.cP_User_Data.cP_RPDU.rP_DATA_SGSN_MS.rP_MessageReference;
4364
4365 /* send CP-ACK for CP-DATA just received */
4366 l3_mo := ts_ML3_MO_SMS(spars.tid, c_TIF_REPL, ts_CP_ACK_MO);
4367
4368 SGsAP.send(l3_mo);
4369
4370 /* send RP-ACK for RP-DATA */
4371 rp_mo := ts_RP_ACK_MO(spars.rp.msg_ref);
4372 l3_mo := ts_ML3_MO_SMS(spars.tid, c_TIF_REPL, ts_CP_DATA_MO(rp_mo));
4373
4374 SGsAP.send(l3_mo);
4375
4376 /* expect CP-ACK for CP-DATA(RP-ACK) just sent */
4377 l3_mt := tr_ML3_MT_SMS(spars.tid, c_TIF_ORIG, tr_CP_ACK_MT);
4378
4379 SGsAP.receive(l3_mt);
4380
4381 deactivate(d);
4382
4383 setverdict(pass);
4384}
4385
4386/* submit a MO-SMS to MSC/SMSC over an already existing SGsAP connection */
4387function f_mo_sms_sgs(inout SmsParameters spars)
4388runs on BSC_ConnHdlr {
4389 var template (value) TPDU_RP_DATA_MS_SGSN tp_mo;
4390 var template (value) RPDU_MS_SGSN rp_mo;
4391 var template (value) PDU_ML3_MS_NW l3_mo;
4392
4393 var template TPDU_RP_DATA_SGSN_MS tp_mt;
4394 var template RPDU_SGSN_MS rp_mt;
4395 var template PDU_ML3_NW_MS l3_mt;
4396
4397 var default d := activate(as_other_sms_sgs());
4398
4399 /* just in case this is routed to SMPP.. */
4400 f_create_smpp_expect(hex2str(spars.tp.da.tP_DA_NoPad.tP_DAValue));
4401
4402 tp_mo := ts_SMS_SUBMIT(spars.tp.msg_ref, spars.tp.da, spars.tp.pid, spars.tp.dcs,
4403 spars.tp.udl, spars.tp.ud);
4404 rp_mo := ts_RP_DATA_MO(spars.rp.msg_ref, spars.rp.orig, spars.rp.dest, tp_mo);
4405 l3_mo := ts_ML3_MO_SMS(spars.tid, c_TIF_ORIG, ts_CP_DATA_MO(rp_mo));
4406
4407 SGsAP.send(l3_mo);
4408
4409 /* receive CP-ACK for CP-DATA above */
4410 SGsAP.receive(tr_ML3_MT_SMS(spars.tid, c_TIF_REPL, tr_CP_ACK_MT));
4411
4412 if (ispresent(spars.exp_rp_err)) {
4413 /* expect an RP-ERROR message from MSC with given cause */
4414 rp_mt := tr_RP_ERROR_MT(spars.rp.msg_ref, spars.exp_rp_err);
4415 l3_mt := tr_ML3_MT_SMS(spars.tid, c_TIF_REPL, tr_CP_DATA_MT(rp_mt));
4416 SGsAP.receive(l3_mt);
4417 /* send CP-ACK for CP-DATA just received */
4418 l3_mo := ts_ML3_MO_SMS(spars.tid, c_TIF_ORIG, ts_CP_ACK_MO);
4419 SGsAP.send(l3_mo);
4420 } else {
4421 /* expect RP-ACK for RP-DATA */
4422 rp_mt := tr_RP_ACK_MT(spars.rp.msg_ref);
4423 l3_mt := tr_ML3_MT_SMS(spars.tid, c_TIF_REPL, tr_CP_DATA_MT(rp_mt));
4424 SGsAP.receive(l3_mt);
4425 /* send CP-ACO for CP-DATA just received */
4426 l3_mo := ts_ML3_MO_SMS(spars.tid, c_TIF_ORIG, ts_CP_ACK_MO);
4427 SGsAP.send(l3_mo);
4428 }
4429
4430 deactivate(d);
4431
4432 setverdict(pass);
4433}
4434
4435private function f_vty_sms_send_conn_hdlr(charstring imsi, charstring msisdn, charstring text)
4436runs on BSC_ConnHdlr {
4437 f_vty_transceive(MSCVTY, "subscriber imsi "&imsi&" sms sender msisdn "&msisdn&" send "&text);
4438}
4439
4440/* Send a MT SMS via SGs interface */
4441private function f_tc_sgsap_mt_sms(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
4442 f_init_handler(pars);
4443 f_sgs_perform_lu();
4444 f_sleep(1.0);
4445 var SmsParameters spars := valueof(t_SmsPars);
4446 spars.tp.ud := 'C8329BFD064D9B53'O;
4447
4448 /* Trigger SMS via VTY */
4449 f_vty_sms_send_conn_hdlr(hex2str(pars.imsi), "2342", "Hello SMS");
4450 var octetstring vlr_name := f_enc_dns_hostname(mp_vlr_name);
4451
4452 /* Expect a paging request and respond accordingly with a service request */
4453 SGsAP.receive(tr_SGsAP_PAGING_REQ(pars.imsi, vlr_name, SMS_indicator, omit));
4454 SGsAP.send(ts_SGsAP_SERVICE_REQ(pars.imsi, SMS_indicator, EMM_CONNECTED));
4455
4456 /* Connection is now live, receive the MT-SMS */
4457 f_mt_sms_sgs(spars);
4458
4459 /* Expect a concluding release from the MSC */
4460 SGsAP.receive(tr_SGsAP_RELEASE_REQ(pars.imsi, omit));
4461
4462 /* Make sure that subscriber is still present and the SGs association is in tact (ref-counting) */
4463 f_ctrl_get_exp(IPA_CTRL, "fsm.SGs-UE.id.imsi:" & hex2str(g_pars.imsi) & ".state", "SGs-ASSOCIATED");
4464
4465 f_sgsap_bssmap_screening();
4466
4467 setverdict(pass);
4468}
4469testcase TC_sgsap_mt_sms() runs on MTC_CT {
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004470 var BSC_ConnHdlrPars pars;
Harald Welte4263c522018-12-06 11:56:27 +01004471 var BSC_ConnHdlr vc_conn;
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004472 f_init(1, true);
4473 pars := f_init_pars(11823, true);
4474 vc_conn := f_start_handler_with_pars(refers(f_tc_sgsap_mt_sms), pars);
Harald Welte4263c522018-12-06 11:56:27 +01004475 vc_conn.done;
4476}
4477
4478/* Send a MO SMS via SGs interface */
4479private function f_tc_sgsap_mo_sms(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
4480 f_init_handler(pars);
4481 f_sgs_perform_lu();
4482 f_sleep(1.0);
4483 var SmsParameters spars := valueof(t_SmsPars);
4484 spars.tp.ud := 'C8329BFD064D9B53'O;
4485
4486 /* Send the MO-SMS */
4487 f_mo_sms_sgs(spars);
4488
4489 /* Expect a concluding release from the MSC/VLR */
4490 SGsAP.receive(tr_SGsAP_RELEASE_REQ(pars.imsi, omit));
4491
4492 /* Make sure that subscriber is still present and the SGs association is in tact (ref-counting) */
4493 f_ctrl_get_exp(IPA_CTRL, "fsm.SGs-UE.id.imsi:" & hex2str(g_pars.imsi) & ".state", "SGs-ASSOCIATED");
4494
4495 setverdict(pass);
4496
4497 f_sgsap_bssmap_screening()
4498}
4499testcase TC_sgsap_mo_sms() runs on MTC_CT {
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004500 var BSC_ConnHdlrPars pars;
Harald Welte4263c522018-12-06 11:56:27 +01004501 var BSC_ConnHdlr vc_conn;
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004502 f_init(1, true);
4503 pars := f_init_pars(11824, true);
4504 vc_conn := f_start_handler_with_pars(refers(f_tc_sgsap_mo_sms), pars);
Harald Welte4263c522018-12-06 11:56:27 +01004505 vc_conn.done;
4506}
4507
4508/* Trigger sending of an MT sms via VTY but never respond to anything */
4509private function f_tc_sgsap_mt_sms_and_nothing(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
4510 f_init_handler(pars, 170.0);
4511 f_sgs_perform_lu();
4512 f_sleep(1.0);
4513
4514 var SmsParameters spars := valueof(t_SmsPars);
4515 spars.tp.ud := 'C8329BFD064D9B53'O;
4516 var integer page_count := 0;
4517 var octetstring vlr_name := f_enc_dns_hostname(mp_vlr_name);
4518 var template PDU_SGsAP exp_pag_req := tr_SGsAP_PAGING_REQ(g_pars.imsi, vlr_name, SMS_indicator, omit);
4519 var template LocationAreaId exp_lai := ts_SGsAP_IE_Lai(valueof(ts_SGsAP_LAI('901'H, '70'H, 2342)));
4520 exp_pag_req.sGsAP_PAGING_REQUEST.locationAreaId := exp_lai;
4521
4522 /* Trigger SMS via VTY */
4523 f_vty_sms_send_conn_hdlr(hex2str(pars.imsi), "2342", "Hello SMS");
4524
Neels Hofmeyr16237742019-03-06 15:34:01 +01004525 /* Expect the MSC/VLR to page exactly once */
4526 SGsAP.receive(exp_pag_req);
Harald Welte4263c522018-12-06 11:56:27 +01004527
4528 /* Wait some time to make sure the MSC is not delivering any further
4529 * paging messages or anything else that could be unexpected. */
4530 timer T := 20.0;
4531 T.start
4532 alt {
4533 [] SGsAP.receive(exp_pag_req)
4534 {
4535 setverdict(fail, "paging seems not to stop!");
4536 mtc.stop;
4537 }
4538 [] SGsAP.receive {
4539 setverdict(fail, "unexpected SGsAP message received");
4540 self.stop;
4541 }
4542 [] T.timeout {
4543 setverdict(pass);
4544 }
4545 }
4546
4547 /* Even on a failed paging the SGs Association should stay intact */
4548 f_ctrl_get_exp(IPA_CTRL, "fsm.SGs-UE.id.imsi:" & hex2str(g_pars.imsi) & ".state", "SGs-ASSOCIATED");
4549
4550 /* Note: We do not execute f_sgsap_bssmap_screening() here since the
4551 * MSC/VLR would re-try to deliver the test SMS trigered above and
4552 * so the screening would fail. */
4553
Neels Hofmeyr8256ed22019-03-06 15:34:01 +01004554 f_vty_sms_clear(hex2str(g_pars.imsi));
4555
Harald Welte4263c522018-12-06 11:56:27 +01004556 f_vty_transceive(MSCVTY, "subscriber imsi " & hex2str(g_pars.imsi) & " expire");
4557
4558 setverdict(pass);
Neels Hofmeyrb0f82342019-03-06 15:36:51 +01004559
4560 f_sgsap_bssmap_screening();
Harald Welte4263c522018-12-06 11:56:27 +01004561}
4562testcase TC_sgsap_mt_sms_and_nothing() runs on MTC_CT {
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004563 var BSC_ConnHdlrPars pars;
Harald Welte4263c522018-12-06 11:56:27 +01004564 var BSC_ConnHdlr vc_conn;
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004565 f_init(1, true);
4566 pars := f_init_pars(11825, true);
4567 vc_conn := f_start_handler_with_pars(refers(f_tc_sgsap_mt_sms_and_nothing), pars);
Harald Welte4263c522018-12-06 11:56:27 +01004568 vc_conn.done;
4569}
4570
4571/* Trigger sending of an MT sms via VTY but reject the paging immediately */
4572private function f_tc_sgsap_mt_sms_and_reject(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
4573 f_init_handler(pars, 150.0);
4574 f_sgs_perform_lu();
4575 f_sleep(1.0);
4576
4577 var SmsParameters spars := valueof(t_SmsPars);
4578 spars.tp.ud := 'C8329BFD064D9B53'O;
4579 var integer page_count := 0;
4580 var octetstring vlr_name := f_enc_dns_hostname(mp_vlr_name);
4581 var template PDU_SGsAP exp_pag_req := tr_SGsAP_PAGING_REQ(g_pars.imsi, vlr_name, SMS_indicator, omit);
4582 var template LocationAreaId exp_lai := ts_SGsAP_IE_Lai(valueof(ts_SGsAP_LAI('901'H, '70'H, 2342)));
4583 exp_pag_req.sGsAP_PAGING_REQUEST.locationAreaId := exp_lai;
4584
4585 /* Trigger SMS via VTY */
4586 f_vty_sms_send_conn_hdlr(hex2str(pars.imsi), "2342", "Hello SMS");
4587
4588 /* Expect a paging request and reject it immediately */
4589 SGsAP.receive(exp_pag_req);
4590 SGsAP.send(ts_SGsAP_PAGING_REJ(g_pars.imsi, IMSI_unknown));
4591
4592 /* The MSC/VLR should no longer try to page once the paging has been
4593 * rejected. Wait some time and check if there are no unexpected
4594 * messages on the SGs interface. */
4595 timer T := 20.0;
4596 T.start
4597 alt {
4598 [] SGsAP.receive(exp_pag_req)
4599 {
4600 setverdict(fail, "paging seems not to stop!");
4601 mtc.stop;
4602 }
4603 [] SGsAP.receive {
4604 setverdict(fail, "unexpected SGsAP message received");
4605 self.stop;
4606 }
4607 [] T.timeout {
4608 setverdict(pass);
4609 }
4610 }
4611
Neels Hofmeyr8256ed22019-03-06 15:34:01 +01004612 f_vty_sms_clear(hex2str(g_pars.imsi));
4613
Harald Welte4263c522018-12-06 11:56:27 +01004614 /* A rejected paging with IMSI_unknown (see above) should always send
4615 * the SGs association to NULL. */
4616 f_ctrl_get_exp(IPA_CTRL, "fsm.SGs-UE.id.imsi:" & hex2str(g_pars.imsi) & ".state", "SGs-NULL");
4617
4618 f_sgsap_bssmap_screening();
4619
Harald Welte4263c522018-12-06 11:56:27 +01004620 setverdict(pass);
4621}
4622testcase TC_sgsap_mt_sms_and_reject() runs on MTC_CT {
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004623 var BSC_ConnHdlrPars pars;
Harald Welte4263c522018-12-06 11:56:27 +01004624 var BSC_ConnHdlr vc_conn;
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004625 f_init(1, true);
4626 pars := f_init_pars(11826, true);
4627 vc_conn := f_start_handler_with_pars(refers(f_tc_sgsap_mt_sms_and_reject), pars);
Harald Welte4263c522018-12-06 11:56:27 +01004628 vc_conn.done;
4629}
4630
4631/* Perform an MT CSDB call including LU */
4632private function f_mt_lu_and_csfb_call(charstring id, BSC_ConnHdlrPars pars, boolean bssmap_lu) runs on BSC_ConnHdlr {
4633 f_init_handler(pars);
4634
4635 /* Be sure that the BSSMAP reset is done before we begin. */
4636 f_sleep(2.0);
4637
4638 /* Testcase variation: See what happens when we do a regular BSSMAP
4639 * LU first (this should not hurt in any way!) */
4640 if (bssmap_lu) {
4641 f_perform_lu();
4642 }
4643
4644 f_sgs_perform_lu();
4645 f_sleep(1.0);
4646
4647 var octetstring vlr_name := f_enc_dns_hostname(mp_vlr_name);
4648 var CallParameters cpars := valueof(t_CallParams('12345'H, 0));
4649 cpars.bss_rtp_port := 1110;
4650 cpars.mgcp_connection_id_bss := '10004'H;
4651 cpars.mgcp_connection_id_mss := '10005'H;
4652
4653 /* Note: This is an optional parameter. When the call-agent (MSC) does
4654 * supply a full endpoint name this setting will be overwritten. */
4655 cpars.mgcp_ep := "rtpbridge/1@mgw";
4656
4657 /* Initiate a call via MNCC interface */
4658 f_mt_call_initate(cpars);
4659
4660 /* Expect a paging request and respond accordingly with a service request */
4661 SGsAP.receive(tr_SGsAP_PAGING_REQ(pars.imsi, vlr_name, CS_call_indicator, omit));
4662 SGsAP.send(ts_SGsAP_SERVICE_REQ(pars.imsi, CS_call_indicator, EMM_CONNECTED));
4663
4664 /* Complete the call, hold it for some time and then tear it down */
4665 f_mt_call_complete(cpars);
4666 f_sleep(3.0);
Harald Welte4c422b72019-02-17 16:27:10 +01004667 f_call_hangup(cpars, true, is_csfb := true);
Harald Welte4263c522018-12-06 11:56:27 +01004668
4669 /* Make sure that subscriber is still present and the SGs association is in tact (ref-counting) */
4670 f_ctrl_get_exp(IPA_CTRL, "fsm.SGs-UE.id.imsi:" & hex2str(g_pars.imsi) & ".state", "SGs-ASSOCIATED");
4671
4672 /* Finally simulate the return of the UE to the 4G network */
4673 SGsAP.send(ts_SGsAP_MO_CSFB_IND(pars.imsi));
4674
4675 /* Test for successful return by triggering a paging, when the paging
4676 * request is received via SGs, we can be sure that the MSC/VLR has
4677 * recognized that the UE is now back on 4G */
4678 f_sleep(1.0);
4679 f_vty_transceive(MSCVTY, "subscriber imsi " & hex2str(g_pars.imsi) & " paging");
4680 alt {
4681 [] SGsAP.receive(tr_SGsAP_PAGING_REQ(pars.imsi, vlr_name, CS_call_indicator, omit)) {
4682 setverdict(pass);
4683 }
4684 [] SGsAP.receive {
4685 setverdict(fail, "Received unexpected message on SGs");
4686 }
4687 }
4688
4689 f_sgsap_bssmap_screening();
4690
4691 setverdict(pass);
4692}
4693
4694/* Perform a regular BSSAP LU first, do a SGSAP LU and then make a CSFB call */
4695private function f_tc_bssap_lu_sgsap_lu_and_mt_call(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
4696 f_mt_lu_and_csfb_call(id, pars, true);
4697}
4698testcase TC_bssap_lu_sgsap_lu_and_mt_call() runs on MTC_CT {
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004699 var BSC_ConnHdlrPars pars;
Harald Welte4263c522018-12-06 11:56:27 +01004700 var BSC_ConnHdlr vc_conn;
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004701 f_init(1, true);
4702 pars := f_init_pars(118139, true);
Harald Welte4263c522018-12-06 11:56:27 +01004703
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004704 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 +01004705 vc_conn.done;
4706}
4707
4708
4709/* Perform a SGSAP LU and then make a CSFB call */
4710private function f_tc_sgsap_lu_and_mt_call(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
4711 f_mt_lu_and_csfb_call(id, pars, false);
4712}
4713testcase TC_sgsap_lu_and_mt_call() runs on MTC_CT {
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004714 var BSC_ConnHdlrPars pars;
Harald Welte4263c522018-12-06 11:56:27 +01004715 var BSC_ConnHdlr vc_conn;
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004716 f_init(1, true);
4717 pars := f_init_pars(11827, true);
Harald Welte4263c522018-12-06 11:56:27 +01004718
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004719 vc_conn := f_start_handler_with_pars(refers(f_tc_sgsap_lu_and_mt_call), pars);
Harald Welte4263c522018-12-06 11:56:27 +01004720 vc_conn.done;
4721}
4722
Philipp Maier628c0052019-04-09 17:36:57 +02004723/* Simulate an HLR/VLR failure */
4724private function f_tc_sgsap_vlr_failure(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
4725 var octetstring mme_name := f_enc_dns_hostname(mp_mme_name);
4726 var octetstring vlr_name := f_enc_dns_hostname(mp_vlr_name);
4727
4728 var PDU_SGsAP lur;
4729
4730 f_init_handler(pars);
4731
4732 /* Attempt location update (which is expected to fail) */
4733 lur := valueof(ts_SGsAP_LU_REQ(g_pars.imsi, mme_name, IMSI_attach,
4734 ts_SGsAP_LAI('901'H, '70'H, 2342)));
4735 SGsAP.send(lur);
4736
4737 /* Respond to SGsAP-RESET-INDICATION from VLR */
4738 alt {
4739 [] SGsAP.receive(tr_SGsAP_RESET_IND_VLR(vlr_name)); {
4740 SGsAP.send(valueof(ts_SGsAP_RESET_ACK_MME(mme_name)));
4741 setverdict(pass);
4742 }
4743 [] SGsAP.receive {
4744 setverdict(fail, "Received unexpected message on SGs");
4745 }
4746 }
4747
4748 f_sleep(1.0);
4749 setverdict(pass);
4750}
4751testcase TC_sgsap_vlr_failure() runs on MTC_CT {
4752 var BSC_ConnHdlrPars pars;
4753 var BSC_ConnHdlr vc_conn;
4754 f_init(1, true, false);
4755 pars := f_init_pars(11811, true, false);
4756 vc_conn := f_start_handler_with_pars(refers(f_tc_sgsap_vlr_failure), pars);
4757 vc_conn.done;
4758}
4759
Harald Welte4263c522018-12-06 11:56:27 +01004760/* SGs TODO:
4761 * LU attempt for IMSI without NAM_PS in HLR
4762 * LU attempt with AUTH FAIL due to invalid RES/SRES
4763 * LU attempt with no response from HLR (VLR should timeout + LU REJ)
4764 * LU attempt with new TMSI but without TMSI REALL CMPL baco to VLR
4765 * implicit IMSI detach from EPS
4766 * implicit IMSI detach from non-EPS
4767 * MM INFO
4768 *
4769 */
Harald Weltef6dd64d2017-11-19 12:09:51 +01004770
4771control {
Philipp Maier328d1662018-03-07 10:40:27 +01004772 execute( TC_cr_before_reset() );
Harald Weltea49e36e2018-01-21 19:29:33 +01004773 execute( TC_lu_imsi_noauth_tmsi() );
Harald Welted2328a22018-01-27 14:27:16 +01004774 execute( TC_lu_imsi_noauth_notmsi() );
Harald Weltea49e36e2018-01-21 19:29:33 +01004775 execute( TC_lu_imsi_reject() );
4776 execute( TC_lu_imsi_timeout_gsup() );
Harald Welted2328a22018-01-27 14:27:16 +01004777 execute( TC_lu_imsi_auth_tmsi() );
Harald Welte8a397ae2019-04-21 22:03:37 +02004778 execute( TC_lu_imsi_auth3g_tmsi() );
Harald Welted2328a22018-01-27 14:27:16 +01004779 execute( TC_cmserv_imsi_unknown() );
Harald Welte2bb825f2018-01-22 11:31:18 +01004780 execute( TC_lu_and_mo_call() );
Harald Welte071ed732018-01-23 19:53:52 +01004781 execute( TC_lu_auth_sai_timeout() );
4782 execute( TC_lu_auth_sai_err() );
Harald Weltee1a2f3c2018-01-24 17:28:48 +01004783 execute( TC_lu_clear_request() );
4784 execute( TC_lu_disconnect() );
4785 execute( TC_lu_by_imei() );
4786 execute( TC_lu_by_tmsi_noauth_unknown() );
4787 execute( TC_imsi_detach_by_imsi() );
4788 execute( TC_imsi_detach_by_tmsi() );
4789 execute( TC_imsi_detach_by_imei() );
4790 execute( TC_emerg_call_imei_reject() );
4791 execute( TC_emerg_call_imsi() );
4792 execute( TC_cm_serv_req_vgcs_reject() );
4793 execute( TC_cm_serv_req_vbs_reject() );
4794 execute( TC_cm_serv_req_lcs_reject() );
Harald Welte0195ab12018-01-24 21:50:20 +01004795 execute( TC_cm_reest_req_reject() );
Harald Welte1af6ea82018-01-25 18:33:15 +01004796 execute( TC_lu_auth_2G_fail() );
4797 execute( TC_lu_imsi_auth_tmsi_encr_13_13() );
4798 execute( TC_cl3_no_payload() );
4799 execute( TC_cl3_rnd_payload() );
Harald Welte1852a842018-01-26 22:53:36 +01004800 execute( TC_establish_and_nothing() );
4801 execute( TC_mo_setup_and_nothing() );
4802 execute( TC_mo_crcx_ran_timeout() );
4803 execute( TC_mo_crcx_ran_reject() );
Harald Welted2328a22018-01-27 14:27:16 +01004804 execute( TC_mt_crcx_ran_reject() );
Daniel Willmann8b084372018-02-04 13:35:26 +01004805 execute( TC_mo_setup_and_dtmf_dup() );
Harald Welteaa54cf82018-01-30 08:15:32 +01004806 //execute( TC_mt_t310() );
Harald Welte167458a2018-01-27 15:58:16 +01004807 execute( TC_gsup_cancel() );
Harald Welte9de84792018-01-28 01:06:35 +01004808 execute( TC_lu_imsi_auth_tmsi_encr_1_13() );
4809 execute( TC_lu_imsi_auth_tmsi_encr_3_13() );
4810 execute( TC_lu_imsi_auth_tmsi_encr_3_1() );
Neels Hofmeyr29b8da02018-03-01 18:09:45 +01004811 execute( TC_lu_imsi_auth_tmsi_encr_3_1_no_cm() );
Harald Welte9de84792018-01-28 01:06:35 +01004812 execute( TC_lu_imsi_auth_tmsi_encr_13_2() );
4813 execute( TC_lu_imsi_auth_tmsi_encr_013_2() );
Philipp Maier94f3f1b2018-03-15 18:54:13 +01004814 execute( TC_mo_release_timeout() );
Philipp Maier2a98a732018-03-19 16:06:12 +01004815 execute( TC_lu_and_mt_call_no_dlcx_resp() );
Philipp Maier75932982018-03-27 14:52:35 +02004816 execute( TC_reset_two() );
Harald Welte33ec09b2018-02-10 15:34:46 +01004817
4818 execute( TC_lu_and_mt_call() );
4819
Harald Weltef45efeb2018-04-09 18:19:24 +02004820 execute( TC_lu_and_mo_sms() );
4821 execute( TC_lu_and_mt_sms() );
Philipp Maier3983e702018-11-22 19:01:33 +01004822 execute( TC_lu_and_mt_sms_paging_and_nothing() );
Harald Weltef640a012018-04-14 17:49:21 +02004823 execute( TC_smpp_mo_sms() );
4824 execute( TC_smpp_mt_sms() );
Harald Weltef45efeb2018-04-09 18:19:24 +02004825
Vadim Yanitskiy103d09f2018-11-12 02:50:23 +07004826 execute( TC_gsup_mo_sms() );
Vadim Yanitskiy9cc019a2018-11-15 02:06:07 +07004827 execute( TC_gsup_mo_smma() );
Vadim Yanitskiyd7b37ab2018-11-24 03:40:20 +07004828 execute( TC_gsup_mt_sms_ack() );
4829 execute( TC_gsup_mt_sms_err() );
Vadim Yanitskiybe1ff4b2019-01-18 15:04:13 +07004830 execute( TC_gsup_mt_sms_rp_mr() );
Vadim Yanitskiy5ac49cc2019-01-24 16:57:31 +07004831 execute( TC_gsup_mo_mt_sms_rp_mr() );
Vadim Yanitskiy103d09f2018-11-12 02:50:23 +07004832
Vadim Yanitskiy2a978b92018-06-19 17:51:20 +07004833 execute( TC_lu_and_mo_ussd_single_request() );
Vadim Yanitskiy13e4a272018-06-19 18:24:31 +07004834 execute( TC_lu_and_mt_ussd_notification() );
Vadim Yanitskiy2a978b92018-06-19 17:51:20 +07004835 execute( TC_lu_and_mo_ussd_during_mt_call() );
Vadim Yanitskiy13e4a272018-06-19 18:24:31 +07004836 execute( TC_lu_and_mt_ussd_during_mt_call() );
Vadim Yanitskiy2daf52d2018-06-21 04:19:58 +07004837 execute( TC_lu_and_mo_ussd_mo_release() );
Vadim Yanitskiy0e392dd2018-11-29 00:47:54 +07004838 execute( TC_lu_and_ss_session_timeout() );
Vadim Yanitskiy7d1f9182018-05-28 16:21:42 +07004839
Stefan Sperling89eb1f32018-12-17 15:06:20 +01004840 execute( TC_cipher_complete_with_invalid_cipher() );
4841
Harald Welte4263c522018-12-06 11:56:27 +01004842 execute( TC_sgsap_reset() );
4843 execute( TC_sgsap_lu() );
4844 execute( TC_sgsap_lu_imsi_reject() );
4845 execute( TC_sgsap_lu_and_nothing() );
4846 execute( TC_sgsap_expl_imsi_det_eps() );
Philipp Maierfc19f172019-03-21 11:17:54 +01004847 execute( TC_sgsap_impl_imsi_det_eps() );
Harald Welte4263c522018-12-06 11:56:27 +01004848 execute( TC_sgsap_expl_imsi_det_noneps() );
Philipp Maier5d812702019-03-21 10:51:26 +01004849 execute( TC_sgsap_impl_imsi_det_noneps() );
Harald Welte4263c522018-12-06 11:56:27 +01004850 execute( TC_sgsap_paging_rej() );
4851 execute( TC_sgsap_paging_subscr_rej() );
4852 execute( TC_sgsap_paging_ue_unr() );
4853 execute( TC_sgsap_paging_and_nothing() );
4854 execute( TC_sgsap_paging_and_lu() );
4855 execute( TC_sgsap_mt_sms() );
4856 execute( TC_sgsap_mo_sms() );
4857 execute( TC_sgsap_mt_sms_and_nothing() );
4858 execute( TC_sgsap_mt_sms_and_reject() );
4859 execute( TC_sgsap_unexp_ud() );
4860 execute( TC_sgsap_unsol_ud() );
4861 execute( TC_bssap_lu_sgsap_lu_and_mt_call() );
4862 execute( TC_sgsap_lu_and_mt_call() );
Philipp Maier628c0052019-04-09 17:36:57 +02004863 execute( TC_sgsap_vlr_failure() );
Harald Welte4263c522018-12-06 11:56:27 +01004864
Neels Hofmeyr1b3c6e32018-03-01 17:52:21 +01004865 /* Run this last: at the time of writing this test crashes the MSC */
4866 execute( TC_lu_imsi_auth_tmsi_encr_3_1_log_msc_debug() );
Philipp Maierdb7fb8d2019-02-11 10:50:13 +01004867 execute( TC_gsup_mt_multi_part_sms() );
Neels Hofmeyr692c9ee2018-04-10 02:07:13 +02004868 execute( TC_mo_cc_bssmap_clear() );
Harald Weltef6dd64d2017-11-19 12:09:51 +01004869}
4870
4871
4872}