blob: af654a3bd72ec0b81037c1886ea2109737608705 [file] [log] [blame]
Harald Weltef6dd64d2017-11-19 12:09:51 +01001module MSC_Tests {
2
3import from General_Types all;
4import from Osmocom_Types all;
5
6import from M3UA_Types all;
7import from M3UA_Emulation all;
8
9import from MTP3asp_Types all;
10import from MTP3asp_PortType all;
11
12import from SCCPasp_Types all;
13import from SCCP_Types all;
14import from SCCP_Emulation all;
15
16import from SCTPasp_Types all;
17import from SCTPasp_PortType all;
18
Harald Weltea49e36e2018-01-21 19:29:33 +010019import from Osmocom_CTRL_Functions all;
20import from Osmocom_CTRL_Types all;
21import from Osmocom_CTRL_Adapter all;
22
Harald Welte3ca1c902018-01-24 18:51:27 +010023import from TELNETasp_PortType all;
24import from Osmocom_VTY_Functions all;
25
Harald Weltea49e36e2018-01-21 19:29:33 +010026import from MNCC_Emulation all;
Harald Welte2bb825f2018-01-22 11:31:18 +010027import from MNCC_Types all;
Harald Weltea49e36e2018-01-21 19:29:33 +010028
Harald Welte4aa970c2018-01-26 10:38:09 +010029import from MGCP_Emulation all;
30import from MGCP_Types all;
31import from MGCP_Templates all;
32import from SDP_Types all;
33
Harald Weltea49e36e2018-01-21 19:29:33 +010034import from GSUP_Emulation all;
35import from GSUP_Types all;
36import from IPA_Emulation all;
37
Harald Weltef6dd64d2017-11-19 12:09:51 +010038import from BSSAP_Types all;
Harald Welte6811d102019-04-14 22:23:14 +020039import from RAN_Adapter all;
Harald Weltea49e36e2018-01-21 19:29:33 +010040import from BSSAP_CodecPort all;
41import from BSSMAP_Templates all;
Harald Welte6811d102019-04-14 22:23:14 +020042import from RAN_Emulation all;
Harald Weltea49e36e2018-01-21 19:29:33 +010043import from BSC_ConnectionHandler all;
Harald Weltef6dd64d2017-11-19 12:09:51 +010044
Harald Welte4263c522018-12-06 11:56:27 +010045import from SGsAP_Templates all;
46import from SGsAP_Types all;
47import from SGsAP_Emulation all;
48
Harald Weltea49e36e2018-01-21 19:29:33 +010049import from MobileL3_Types all;
50import from MobileL3_CommonIE_Types all;
Vadim Yanitskiy103d09f2018-11-12 02:50:23 +070051import from MobileL3_SMS_Types all;
Harald Weltea49e36e2018-01-21 19:29:33 +010052import from L3_Templates all;
Harald Welte158a7ca2018-02-16 18:11:31 +010053import from L3_Common all;
Harald Weltef6dd64d2017-11-19 12:09:51 +010054
Harald Weltef640a012018-04-14 17:49:21 +020055import from SMPP_Types all;
56import from SMPP_Templates all;
57import from SMPP_Emulation all;
58
Stefan Sperlingc307e682018-06-14 15:15:46 +020059import from SCCP_Templates all;
60
Vadim Yanitskiy7d1f9182018-05-28 16:21:42 +070061import from SS_Types all;
62import from SS_Templates all;
63import from USSD_Helpers all;
Harald Welte4263c522018-12-06 11:56:27 +010064import from DNS_Helpers all;
Vadim Yanitskiy7d1f9182018-05-28 16:21:42 +070065
Philipp Maier948747b2019-04-02 15:22:33 +020066import from TCCConversion_Functions all;
67
Harald Welte9b751a62019-04-14 17:39:29 +020068const integer NUM_BSC := 3;
Harald Welte6811d102019-04-14 22:23:14 +020069type record of RAN_Configuration RAN_Configurations;
Harald Weltef6dd64d2017-11-19 12:09:51 +010070
Harald Welte4263c522018-12-06 11:56:27 +010071/* Needed for SGsAP SMS */
72import from MobileL3_SMS_Types all;
73
Harald Weltea4ca4462018-02-09 00:17:14 +010074type component MTC_CT extends CTRL_Adapter_CT {
Harald Weltef6dd64d2017-11-19 12:09:51 +010075 var boolean g_initialized := false;
Harald Weltea49e36e2018-01-21 19:29:33 +010076
Harald Welte6811d102019-04-14 22:23:14 +020077 var RAN_Adapter g_bssap[NUM_BSC];
Harald Weltea4ca4462018-02-09 00:17:14 +010078
Harald Weltea49e36e2018-01-21 19:29:33 +010079 /* no 'adapter_CT' for MNCC or GSUP */
80 var MNCC_Emulation_CT vc_MNCC;
Harald Welte4aa970c2018-01-26 10:38:09 +010081 var MGCP_Emulation_CT vc_MGCP;
Harald Weltea49e36e2018-01-21 19:29:33 +010082 var GSUP_Emulation_CT vc_GSUP;
83 var IPA_Emulation_CT vc_GSUP_IPA;
Harald Weltef640a012018-04-14 17:49:21 +020084 var SMPP_Emulation_CT vc_SMPP;
Harald Welte4263c522018-12-06 11:56:27 +010085 var SGsAP_Emulation_CT vc_SGsAP;
Harald Weltea49e36e2018-01-21 19:29:33 +010086
87 /* only to get events from IPA underneath GSUP */
88 port IPA_CTRL_PT GSUP_IPA_EVENT;
Harald Welte3ca1c902018-01-24 18:51:27 +010089 /* VTY to MSC */
90 port TELNETasp_PT MSCVTY;
Philipp Maier328d1662018-03-07 10:40:27 +010091
92 /* A port to directly send BSSAP messages. This port is used for
93 * tests that require low level access to sen arbitrary BSSAP
94 * messages. Run f_init_bssap_direct() to connect and initialize */
95 port BSSAP_CODEC_PT BSSAP_DIRECT;
96
97 /* When BSSAP messages are directly sent, then the connection
98 * handler is not active, which means that also no guard timer is
99 * set up. The following timer will serve as a replacement */
100 timer Tguard_direct := 60.0;
Harald Weltef6dd64d2017-11-19 12:09:51 +0100101}
102
103modulepar {
Harald Weltea49e36e2018-01-21 19:29:33 +0100104 /* remote parameters of IUT */
105 charstring mp_msc_ip := "127.0.0.1";
106 integer mp_msc_ctrl_port := 4255;
107 integer mp_msc_vty_port := 4254;
Harald Weltef6dd64d2017-11-19 12:09:51 +0100108
Harald Weltea49e36e2018-01-21 19:29:33 +0100109 /* local parameters of emulated HLR */
Philipp Maier9b690e42018-12-21 11:50:03 +0100110 boolean mp_mm_info := false;
Harald Weltea49e36e2018-01-21 19:29:33 +0100111 charstring mp_hlr_ip := "127.0.0.1";
112 integer mp_hlr_port := 4222;
Harald Welte6126fb02018-01-27 20:08:24 +0100113 charstring mp_mgw_ip := "127.0.0.1";
114 integer mp_mgw_port := 2427;
Harald Weltef6dd64d2017-11-19 12:09:51 +0100115
Harald Weltea49e36e2018-01-21 19:29:33 +0100116 charstring mp_msc_mncc := "/tmp/mncc";
Harald Weltea4ca4462018-02-09 00:17:14 +0100117
Harald Weltef640a012018-04-14 17:49:21 +0200118 integer mp_msc_smpp_port := 2775;
119 charstring mp_smpp_system_id := "msc_tester";
120 charstring mp_smpp_password := "osmocom1";
Harald Welte4263c522018-12-06 11:56:27 +0100121 charstring mp_mme_name := "mmec01.mmegi0001.mme.epc.mnc070.mcc901.3gppnetwork.org";
122 charstring mp_vlr_name := "vlr.example.net";
Harald Weltef640a012018-04-14 17:49:21 +0200123
Harald Welte6811d102019-04-14 22:23:14 +0200124 RAN_Configurations mp_bssap_cfg := {
Philipp Maier75932982018-03-27 14:52:35 +0200125 {
126 sccp_service_type := "mtp3_itu",
127 sctp_addr := { 23905, "127.0.0.1", 2905, "127.0.0.1" },
128 own_pc := 185,
129 own_ssn := 254,
130 peer_pc := 187,
131 peer_ssn := 254,
132 sio := '83'O,
133 rctx := 0
134 },
135 {
136 sccp_service_type := "mtp3_itu",
137 sctp_addr := { 23906, "127.0.0.1", 2905, "127.0.0.1" },
138 own_pc := 186,
139 own_ssn := 254,
140 peer_pc := 187,
141 peer_ssn := 254,
142 sio := '83'O,
143 rctx := 1
144 }
Harald Weltea4ca4462018-02-09 00:17:14 +0100145 };
Harald Weltef6dd64d2017-11-19 12:09:51 +0100146}
147
Philipp Maier328d1662018-03-07 10:40:27 +0100148/* altstep for the global guard timer (only used when BSSAP_DIRECT
149 * is used for communication */
150private altstep as_Tguard_direct() runs on MTC_CT {
151 [] Tguard_direct.timeout {
152 setverdict(fail, "Tguard timeout");
Daniel Willmannafce8662018-07-06 23:11:32 +0200153 mtc.stop;
Philipp Maier328d1662018-03-07 10:40:27 +0100154 }
155}
Harald Weltef6dd64d2017-11-19 12:09:51 +0100156
Neels Hofmeyrde76f052019-02-26 05:02:46 +0100157private altstep as_optional_cc_rel(CallParameters cpars) runs on BSC_ConnHdlr {
158 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_CC_RELEASE(cpars.transaction_id))) { repeat; };
159}
160
Harald Weltef640a012018-04-14 17:49:21 +0200161function f_init_smpp(charstring id) runs on MTC_CT {
162 id := id & "-SMPP";
163 var EsmePars pars := {
164 mode := MODE_TRANSCEIVER,
165 bind := {
166 system_id := mp_smpp_system_id,
167 password := mp_smpp_password,
168 system_type := "MSC_Tests",
169 interface_version := hex2int('34'H),
170 addr_ton := unknown,
171 addr_npi := unknown,
172 address_range := ""
173 },
174 esme_role := true
175 }
176
177 vc_SMPP := SMPP_Emulation_CT.create(id);
178 map(vc_SMPP:SMPP_PORT, system:SMPP_PORT);
179 vc_SMPP.start(SMPP_Emulation.main_client(pars, mp_msc_ip, mp_msc_smpp_port, "", -1));
180}
181
182
Harald Weltea49e36e2018-01-21 19:29:33 +0100183function f_init_mncc(charstring id) runs on MTC_CT {
184 id := id & "-MNCC";
185 var MnccOps ops := {
186 create_cb := refers(MNCC_Emulation.ExpectedCreateCallback),
187 unitdata_cb := refers(MNCC_Emulation.DummyUnitdataCallback)
188 }
189
190 vc_MNCC := MNCC_Emulation_CT.create(id);
191 map(vc_MNCC:MNCC, system:MNCC_CODEC_PT);
192 vc_MNCC.start(MNCC_Emulation.main(ops, id, mp_msc_mncc));
Harald Weltef6dd64d2017-11-19 12:09:51 +0100193}
194
Harald Welte4aa970c2018-01-26 10:38:09 +0100195function f_init_mgcp(charstring id) runs on MTC_CT {
196 id := id & "-MGCP";
197 var MGCPOps ops := {
198 create_cb := refers(MGCP_Emulation.ExpectedCreateCallback),
199 unitdata_cb := refers(MGCP_Emulation.DummyUnitdataCallback)
200 }
201 var MGCP_conn_parameters pars := {
Harald Welte6126fb02018-01-27 20:08:24 +0100202 callagent_ip := mp_msc_ip,
Harald Welte4aa970c2018-01-26 10:38:09 +0100203 callagent_udp_port := -1,
Harald Welte6126fb02018-01-27 20:08:24 +0100204 mgw_ip := mp_mgw_ip,
205 mgw_udp_port := mp_mgw_port
Harald Welte4aa970c2018-01-26 10:38:09 +0100206 }
207
208 vc_MGCP := MGCP_Emulation_CT.create(id);
209 map(vc_MGCP:MGCP, system:MGCP_CODEC_PT);
210 vc_MGCP.start(MGCP_Emulation.main(ops, pars, id));
211}
212
Philipp Maierc09a1312019-04-09 16:05:26 +0200213function ForwardUnitdataCallback(PDU_SGsAP msg)
214runs on SGsAP_Emulation_CT return template PDU_SGsAP {
215 SGsAP_CLIENT.send(msg);
216 return omit;
217}
218
Harald Welte4263c522018-12-06 11:56:27 +0100219function f_init_sgsap(charstring id) runs on MTC_CT {
220 id := id & "-SGsAP";
221 var SGsAPOps ops := {
222 create_cb := refers(SGsAP_Emulation.ExpectedCreateCallback),
Philipp Maierc09a1312019-04-09 16:05:26 +0200223 unitdata_cb := refers(ForwardUnitdataCallback)
Harald Welte4263c522018-12-06 11:56:27 +0100224 }
225 var SGsAP_conn_parameters pars := {
226 remote_ip := mp_msc_ip,
227 remote_sctp_port := 29118,
228 local_ip := "",
229 local_sctp_port := -1
230 }
231
232 vc_SGsAP := SGsAP_Emulation_CT.create(id);
233 map(vc_SGsAP:SGsAP, system:SGsAP_CODEC_PT);
234 vc_SGsAP.start(SGsAP_Emulation.main(ops, pars, id));
235}
236
237
Harald Weltea49e36e2018-01-21 19:29:33 +0100238function f_init_gsup(charstring id) runs on MTC_CT {
239 id := id & "-GSUP";
240 var GsupOps ops := {
241 create_cb := refers(GSUP_Emulation.ExpectedCreateCallback)
242 }
243
244 vc_GSUP_IPA := IPA_Emulation_CT.create(id & "-IPA");
245 vc_GSUP := GSUP_Emulation_CT.create(id);
246
247 map(vc_GSUP_IPA:IPA_PORT, system:IPA_CODEC_PT);
248 connect(vc_GSUP:GSUP, vc_GSUP_IPA:IPA_GSUP_PORT);
249 /* we use this hack to get events like ASP_IPA_EVENT_UP */
250 connect(vc_GSUP_IPA:IPA_CTRL_PORT, self:GSUP_IPA_EVENT);
251
252 vc_GSUP.start(GSUP_Emulation.main(ops, id));
253 vc_GSUP_IPA.start(IPA_Emulation.main_server(mp_hlr_ip, mp_hlr_port));
254
255 /* wait for incoming connection to GSUP port before proceeding */
256 timer T := 10.0;
257 T.start;
258 alt {
259 [] GSUP_IPA_EVENT.receive(t_ASP_IPA_EVT_UD(ASP_IPA_EVENT_UP)) { }
260 [] T.timeout {
Harald Welte458fd372018-03-21 11:26:23 +0100261 setverdict(fail, "No connection to GSUP Port");
Daniel Willmannafce8662018-07-06 23:11:32 +0200262 mtc.stop
Harald Weltea49e36e2018-01-21 19:29:33 +0100263 }
264 }
Harald Weltef6dd64d2017-11-19 12:09:51 +0100265}
266
Philipp Maierc09a1312019-04-09 16:05:26 +0200267function f_init(integer num_bsc := 1, boolean sgsap := false, boolean gsup := true) runs on MTC_CT {
Harald Weltef6dd64d2017-11-19 12:09:51 +0100268
269 if (g_initialized == true) {
270 return;
271 }
272 g_initialized := true;
273
Philipp Maier75932982018-03-27 14:52:35 +0200274 if (num_bsc > NUM_BSC) {
Daniel Willmannafce8662018-07-06 23:11:32 +0200275 testcase.stop("excess number of BSC instances requested");
Philipp Maier75932982018-03-27 14:52:35 +0200276 }
277
278 for (var integer i := 0; i < num_bsc; i := i + 1) {
279 if (isbound(mp_bssap_cfg[i])) {
Harald Welte3ca0ce12019-04-23 17:18:48 +0200280 f_ran_adapter_init(g_bssap[i], mp_bssap_cfg[i], "MSC_Test_" & int2str(i), BSC_RanOps);
281 f_ran_adapter_start(g_bssap[i]);
Philipp Maier75932982018-03-27 14:52:35 +0200282 } else {
Daniel Willmannafce8662018-07-06 23:11:32 +0200283 testcase.stop("missing BSSAP configuration");
Philipp Maier75932982018-03-27 14:52:35 +0200284 }
285 }
286
Harald Weltea49e36e2018-01-21 19:29:33 +0100287 f_ipa_ctrl_start(mp_msc_ip, mp_msc_ctrl_port);
288 f_init_mncc("MSC_Test");
Harald Welte4aa970c2018-01-26 10:38:09 +0100289 f_init_mgcp("MSC_Test");
Philipp Maierc09a1312019-04-09 16:05:26 +0200290
291 if (gsup == true) {
292 f_init_gsup("MSC_Test");
293 }
Harald Weltef640a012018-04-14 17:49:21 +0200294 f_init_smpp("MSC_Test");
Philipp Maier57865482019-01-07 18:33:13 +0100295
Philipp Maier8e07a4a2019-02-14 18:23:28 +0100296 if (sgsap == true) {
Philipp Maier57865482019-01-07 18:33:13 +0100297 f_init_sgsap("MSC_Test");
298 }
Harald Welte3ca1c902018-01-24 18:51:27 +0100299
300 map(self:MSCVTY, system:MSCVTY);
301 f_vty_set_prompts(MSCVTY);
302 f_vty_transceive(MSCVTY, "enable");
Harald Welteb14c77a2018-01-25 17:25:44 +0100303
304 /* set some defaults */
305 f_vty_config(MSCVTY, "network", "authentication optional");
306 f_vty_config(MSCVTY, "msc", "assign-tmsi");
307 f_vty_config(MSCVTY, "network", "encryption a5 0");
Harald Weltef6dd64d2017-11-19 12:09:51 +0100308}
309
Philipp Maier328d1662018-03-07 10:40:27 +0100310/* Initialize for a direct connection to BSSAP. This function is an alternative
311 * to f_init() when the high level functions of the BSC_ConnectionHandler are
312 * not needed. */
313function f_init_bssap_direct() runs on MTC_CT {
Harald Welte3ca0ce12019-04-23 17:18:48 +0200314 f_ran_adapter_init(g_bssap[0], mp_bssap_cfg[0], "MSC_Test", omit);
Philipp Maier75932982018-03-27 14:52:35 +0200315 connect(g_bssap[0].vc_SCCP:SCCP_SP_PORT, self:BSSAP_DIRECT);
Philipp Maier328d1662018-03-07 10:40:27 +0100316
317 /* Start guard timer and activate it as default */
318 Tguard_direct.start
319 activate(as_Tguard_direct());
320}
321
Harald Weltef6dd64d2017-11-19 12:09:51 +0100322template PDU_BSSAP ts_BSSAP_BSSMAP := {
323 discriminator := '0'B,
324 spare := '0000000'B,
325 dlci := omit,
326 lengthIndicator := 0, /* overwritten by codec */
327 pdu := ?
328}
329
330template PDU_BSSAP tr_BSSAP_BSSMAP := {
331 discriminator := '0'B,
332 spare := '0000000'B,
333 dlci := omit,
334 lengthIndicator := ?,
335 pdu := {
336 bssmap := ?
337 }
338}
339
340
341type integer BssmapCause;
342
343template (value) BSSMAP_IE_Cause ts_BSSMAP_IE_Cause(BssmapCause val) := {
344 elementIdentifier := '04'O,
345 lengthIndicator := 0,
346 causeValue := int2bit(val, 7),
347 extensionCauseValue := '0'B,
348 spare1 := omit
349}
350
351template (value) PDU_BSSAP ts_BSSMAP_Reset(BssmapCause cause) modifies ts_BSSAP_BSSMAP := {
352 pdu := {
353 bssmap := {
354 reset := {
355 messageType := '30'O,
356 cause := ts_BSSMAP_IE_Cause(cause),
357 a_InterfaceSelectorForReset := omit
358 }
359 }
360 }
361}
362
363template (value) PDU_BSSAP ts_BSSMAP_ResetAck modifies ts_BSSAP_BSSMAP := {
364 pdu := {
365 bssmap := {
366 resetAck := {
367 messageType := '31'O,
368 a_InterfaceSelectorForReset := omit
369 }
370 }
371 }
372}
373
374template PDU_BSSAP tr_BSSMAP_ResetAck modifies tr_BSSAP_BSSMAP := {
375 pdu := {
376 bssmap := {
377 resetAck := {
378 messageType := '31'O,
379 a_InterfaceSelectorForReset := *
380 }
381 }
382 }
383}
384
385template BSSMAP_IE_CellIdentifier ts_BSSMAP_IE_CellID := {
386 elementIdentifier := '05'O,
387 lengthIndicator := 0,
388 cellIdentifierDiscriminator := '0000'B,
389 spare1_4 := '0000'B,
390 cellIdentification := ?
391}
392
393type uint16_t BssmapLAC;
394type uint16_t BssmapCI;
395
396/*
397template BSSMAP_IE_CellIdentifier ts_CellId_CGI(mcc, mnc, lac, ci)
398modifies ts_BSSMAP_IE_CellID := {
399 cellIdentification := {
400 cI_LAC_CGI := {
401 mnc_mcc := FIXME,
402 lac := int2oct(lac, 2),
403 ci := int2oct(ci, 2)
404 }
405 }
406}
407*/
408
409template BSSMAP_IE_CellIdentifier ts_CellID_LAC_CI(BssmapLAC lac, BssmapCI ci)
410modifies ts_BSSMAP_IE_CellID := {
411 cellIdentification := {
412 cI_LAC_CI := {
413 lac := int2oct(lac, 2),
414 ci := int2oct(ci, 2)
415 }
416 }
417}
418
419template BSSMAP_IE_CellIdentifier ts_CellId_CI(BssmapCI ci)
420modifies ts_BSSMAP_IE_CellID := {
421 cellIdentification := {
422 cI_CI := int2oct(ci, 2)
423 }
424}
425
426template BSSMAP_IE_CellIdentifier ts_CellId_none
427modifies ts_BSSMAP_IE_CellID := {
428 cellIdentification := {
429 cI_noCell := ''O
430 }
431}
432
433
434template BSSMAP_IE_Layer3Information ts_BSSMAP_IE_L3Info(octetstring l3info) := {
435 elementIdentifier := '17'O,
436 lengthIndicator := 0,
437 layer3info := l3info
438}
439
440template PDU_BSSAP ts_BSSMAP_ComplL3(BSSMAP_IE_CellIdentifier cell_id, octetstring l3_info)
441modifies ts_BSSAP_BSSMAP := {
442 pdu := {
443 bssmap := {
444 completeLayer3Information := {
445 messageType := '57'O,
446 cellIdentifier := cell_id,
447 layer3Information := ts_BSSMAP_IE_L3Info(l3_info),
448 chosenChannel := omit,
449 lSAIdentifier := omit,
450 aPDU := omit,
451 codecList := omit,
452 redirectAttemptFlag := omit,
453 sendSequenceNumber := omit,
454 iMSI := omit
455 }
456 }
457 }
458}
459
460template PDU_BSSAP ts_BSSMAP_HandoReq(BssmapCause cause, BSSMAP_IE_CellIdentifierList cid_list)
461modifies ts_BSSAP_BSSMAP := {
462 pdu := {
463 bssmap := {
464 handoverRequired := {
465 messageType := '11'O,
466 cause := ts_BSSMAP_IE_Cause(cause),
467 responseRequest := omit,
468 cellIdentifierList := cid_list,
469 circuitPoolList := omit,
470 currentChannelType1 := omit,
471 speechVersion := omit,
472 queueingIndicator := omit,
473 oldToNewBSSInfo := omit,
474 sourceToTargetRNCTransparentInfo := omit,
475 sourceToTargetRNCTransparentInfoCDMA := omit,
476 gERANClassmark := omit,
477 talkerPriority := omit,
478 speechCodec := omit,
479 cSG_Identifier := omit
480 }
481 }
482 }
483}
484
Harald Weltea49e36e2018-01-21 19:29:33 +0100485type function void_fn(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr;
Harald Weltef6dd64d2017-11-19 12:09:51 +0100486
Harald Weltea49e36e2018-01-21 19:29:33 +0100487/* FIXME: move into BSC_ConnectionHandler? */
Harald Welte9b751a62019-04-14 17:39:29 +0200488function f_init_pars(integer imsi_suffix, boolean sgsap := false, boolean gsup := true, integer ran_idx := 0,
489 boolean ran_is_geran := true)
Harald Weltef9abf8d2019-04-21 13:07:17 +0200490runs on MTC_CT return BSC_ConnHdlrPars {
Harald Weltede371492018-01-27 23:44:41 +0100491 var BSC_ConnHdlrNetworkPars net_pars := {
492 kc_support := '0A'O, /* A5/1 and A5/3 enabled */
493 expect_tmsi := true,
494 expect_auth := false,
495 expect_ciph := false
496 };
Harald Weltea49e36e2018-01-21 19:29:33 +0100497 var BSC_ConnHdlrPars pars := {
Harald Weltef9abf8d2019-04-21 13:07:17 +0200498 sccp_addr_own := g_bssap[ran_idx].sccp_addr_own,
499 sccp_addr_peer := g_bssap[ran_idx].sccp_addr_peer,
Harald Welteedbab812018-03-18 16:02:25 +0100500 cell_id := valueof(ts_CellId_CGI('262'H, '42'H, 23, 42)),
Harald Welte81b7f9d2018-01-24 19:06:24 +0100501 imei := f_gen_imei(imsi_suffix),
502 imsi := f_gen_imsi(imsi_suffix),
503 msisdn := f_gen_msisdn(imsi_suffix),
Harald Welte256571e2018-01-24 18:47:19 +0100504 tmsi := omit,
Harald Welte9de84792018-01-28 01:06:35 +0100505 cm1 := valueof(ts_CM1),
Harald Welte82600572018-01-21 20:54:08 +0100506 cm2 := valueof(ts_CM2_default),
Harald Welte16114282018-01-24 22:41:21 +0100507 cm3 := omit,
Harald Weltede371492018-01-27 23:44:41 +0100508 vec := omit,
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +0100509 net := net_pars,
Philipp Maieraeb29a82018-11-08 17:40:53 +0100510 send_early_cm := true,
511 ipa_ctrl_ip := mp_msc_ip,
512 ipa_ctrl_port := mp_msc_ctrl_port,
Philipp Maier9b690e42018-12-21 11:50:03 +0100513 ipa_ctrl_enable := true,
Philipp Maier57865482019-01-07 18:33:13 +0100514 mm_info := mp_mm_info,
Philipp Maierc09a1312019-04-09 16:05:26 +0200515 sgsap_enable := sgsap,
Harald Weltef9abf8d2019-04-21 13:07:17 +0200516 gsup_enable := gsup,
Harald Weltec1f937a2019-04-21 21:19:23 +0200517 ran_idx := ran_idx,
Harald Welte9b751a62019-04-14 17:39:29 +0200518 use_umts_aka := false,
519 ran_is_geran := ran_is_geran
Harald Weltea49e36e2018-01-21 19:29:33 +0100520 };
Neels Hofmeyr9adaa702018-03-01 20:23:19 +0100521 return pars;
522}
523
524function f_start_handler_with_pars(void_fn fn, BSC_ConnHdlrPars pars) runs on MTC_CT return BSC_ConnHdlr {
525 var BSC_ConnHdlr vc_conn;
526 var charstring id := testcasename();
Harald Weltea49e36e2018-01-21 19:29:33 +0100527
528 vc_conn := BSC_ConnHdlr.create(id);
529 /* BSSMAP part / A interface */
Harald Weltef9abf8d2019-04-21 13:07:17 +0200530 connect(vc_conn:BSSAP, g_bssap[pars.ran_idx].vc_RAN:CLIENT);
531 connect(vc_conn:BSSAP_PROC, g_bssap[pars.ran_idx].vc_RAN:PROC);
Harald Weltea49e36e2018-01-21 19:29:33 +0100532 /* MNCC part */
533 connect(vc_conn:MNCC, vc_MNCC:MNCC_CLIENT);
534 connect(vc_conn:MNCC_PROC, vc_MNCC:MNCC_PROC);
Harald Welte4aa970c2018-01-26 10:38:09 +0100535 /* MGCP part */
536 connect(vc_conn:MGCP, vc_MGCP:MGCP_CLIENT);
537 connect(vc_conn:MGCP_PROC, vc_MGCP:MGCP_PROC);
Harald Weltea49e36e2018-01-21 19:29:33 +0100538 /* GSUP part */
Philipp Maierc09a1312019-04-09 16:05:26 +0200539 if (pars.gsup_enable == true) {
540 connect(vc_conn:GSUP, vc_GSUP:GSUP_CLIENT);
541 connect(vc_conn:GSUP_PROC, vc_GSUP:GSUP_PROC);
542 }
Harald Weltef640a012018-04-14 17:49:21 +0200543 /* SMPP part */
544 connect(vc_conn:SMPP, vc_SMPP:SMPP_CLIENT);
545 connect(vc_conn:SMPP_PROC, vc_SMPP:SMPP_PROC);
Harald Welte4263c522018-12-06 11:56:27 +0100546 /* SGs part */
Philipp Maier8e07a4a2019-02-14 18:23:28 +0100547 if (pars.sgsap_enable == true) {
Philipp Maier57865482019-01-07 18:33:13 +0100548 connect(vc_conn:SGsAP, vc_SGsAP:SGsAP_CLIENT);
549 connect(vc_conn:SGsAP_PROC, vc_SGsAP:SGsAP_PROC);
550 }
Harald Weltea49e36e2018-01-21 19:29:33 +0100551
Harald Weltea10db902018-01-27 12:44:49 +0100552 /* We cannot use vc_conn.start(f_init_handler(fn, id, pars)); as we cannot have
553 * a stand-alone 'derefers()' call, see https://www.eclipse.org/forums/index.php/t/1091364/ */
Harald Weltea49e36e2018-01-21 19:29:33 +0100554 vc_conn.start(derefers(fn)(id, pars));
555 return vc_conn;
556}
557
Harald Welte9b751a62019-04-14 17:39:29 +0200558function f_start_handler(void_fn fn, integer imsi_suffix, integer ran_idx := 0, boolean ran_is_geran := true)
559runs on MTC_CT return BSC_ConnHdlr {
560 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 +0100561}
562
Harald Weltea49e36e2018-01-21 19:29:33 +0100563private function f_tc_lu_imsi_noauth_tmsi(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +0100564 f_init_handler(pars);
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +0100565 f_perform_lu();
Harald Weltea49e36e2018-01-21 19:29:33 +0100566}
Harald Weltea49e36e2018-01-21 19:29:33 +0100567testcase TC_lu_imsi_noauth_tmsi() runs on MTC_CT {
568 var BSC_ConnHdlr vc_conn;
569 f_init();
570
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +0100571 vc_conn := f_start_handler(refers(f_tc_lu_imsi_noauth_tmsi), 1);
Harald Weltea49e36e2018-01-21 19:29:33 +0100572 vc_conn.done;
573}
574
575private function f_tc_lu_imsi_noauth_notmsi(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltede371492018-01-27 23:44:41 +0100576 pars.net.expect_tmsi := false;
Harald Weltea10db902018-01-27 12:44:49 +0100577 f_init_handler(pars);
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +0100578 f_perform_lu();
Harald Weltea49e36e2018-01-21 19:29:33 +0100579}
Harald Weltea49e36e2018-01-21 19:29:33 +0100580testcase TC_lu_imsi_noauth_notmsi() runs on MTC_CT {
581 var BSC_ConnHdlr vc_conn;
582 f_init();
Harald Welte3ca1c902018-01-24 18:51:27 +0100583 f_vty_config(MSCVTY, "msc", "no assign-tmsi");
Harald Weltea49e36e2018-01-21 19:29:33 +0100584
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +0100585 vc_conn := f_start_handler(refers(f_tc_lu_imsi_noauth_notmsi), 2);
Harald Weltea49e36e2018-01-21 19:29:33 +0100586 vc_conn.done;
587}
588
589/* Do LU by IMSI, refuse it on GSUP and expect LU REJ back to MS */
590private function f_tc_lu_imsi_reject(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +0100591 f_init_handler(pars);
Harald Weltea49e36e2018-01-21 19:29:33 +0100592 var PDU_ML3_MS_NW l3_lu := f_build_lu_imsi(g_pars.imsi);
593
594 f_create_gsup_expect(hex2str(g_pars.imsi));
Harald Weltedceacc72019-04-21 20:58:35 +0200595 f_cl3_or_initial_ue(l3_lu);
Harald Weltea49e36e2018-01-21 19:29:33 +0100596 GSUP.receive(tr_GSUP_UL_REQ(g_pars.imsi));
597 GSUP.send(ts_GSUP_UL_ERR(g_pars.imsi, 23));
598 alt {
Harald Welte5946b332018-03-18 23:32:21 +0100599 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Rej(int2oct(23,1)))) {
600 f_expect_clear();
601 }
Harald Weltea49e36e2018-01-21 19:29:33 +0100602 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Acc)) {
603 setverdict(fail, "Expecting LU REJ, but got ACCEPT");
Daniel Willmannafce8662018-07-06 23:11:32 +0200604 mtc.stop;
Harald Weltea49e36e2018-01-21 19:29:33 +0100605 }
606 }
Harald Weltea49e36e2018-01-21 19:29:33 +0100607}
608testcase TC_lu_imsi_reject() runs on MTC_CT {
609 var BSC_ConnHdlr vc_conn;
610 f_init();
611
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +0100612 vc_conn := f_start_handler(refers(f_tc_lu_imsi_reject), 3);
Harald Weltea49e36e2018-01-21 19:29:33 +0100613 vc_conn.done;
614}
615
616/* Do LU by IMSI, timeout on GSUP */
617private function f_tc_lu_imsi_timeout_gsup(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +0100618 f_init_handler(pars);
Harald Weltea49e36e2018-01-21 19:29:33 +0100619 var PDU_ML3_MS_NW l3_lu := f_build_lu_imsi(g_pars.imsi);
620
621 f_create_gsup_expect(hex2str(g_pars.imsi));
Harald Weltedceacc72019-04-21 20:58:35 +0200622 f_cl3_or_initial_ue(l3_lu);
Harald Weltea49e36e2018-01-21 19:29:33 +0100623 GSUP.receive(tr_GSUP_UL_REQ(g_pars.imsi));
624 /* Normally the HLR would need to respond here, but we decide to force a timeout here */
625 alt {
626 /* FIXME: Expect specific reject cause */
Harald Welte5946b332018-03-18 23:32:21 +0100627 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Rej)) {
628 f_expect_clear();
629 }
Harald Weltea49e36e2018-01-21 19:29:33 +0100630 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Acc)) {
631 setverdict(fail, "Expecting LU REJ, but got ACCEPT");
Daniel Willmannafce8662018-07-06 23:11:32 +0200632 mtc.stop;
Harald Weltea49e36e2018-01-21 19:29:33 +0100633 }
634 }
Harald Weltea49e36e2018-01-21 19:29:33 +0100635}
636testcase TC_lu_imsi_timeout_gsup() runs on MTC_CT {
637 var BSC_ConnHdlr vc_conn;
638 f_init();
639
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +0100640 vc_conn := f_start_handler(refers(f_tc_lu_imsi_timeout_gsup), 4);
Harald Weltea49e36e2018-01-21 19:29:33 +0100641 vc_conn.done;
642}
643
Harald Welte7b1b2812018-01-22 21:23:06 +0100644private function f_tc_lu_imsi_auth_tmsi(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltede371492018-01-27 23:44:41 +0100645 pars.net.expect_auth := true;
Harald Weltea10db902018-01-27 12:44:49 +0100646 f_init_handler(pars);
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +0100647 f_perform_lu();
Harald Welte7b1b2812018-01-22 21:23:06 +0100648}
649testcase TC_lu_imsi_auth_tmsi() runs on MTC_CT {
650 var BSC_ConnHdlr vc_conn;
651 f_init();
Harald Welte3ca1c902018-01-24 18:51:27 +0100652 f_vty_config(MSCVTY, "network", "authentication required");
Harald Welte7b1b2812018-01-22 21:23:06 +0100653
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +0100654 vc_conn := f_start_handler(refers(f_tc_lu_imsi_auth_tmsi), 5);
Harald Welte7b1b2812018-01-22 21:23:06 +0100655 vc_conn.done;
656}
657
Harald Welte8a397ae2019-04-21 22:03:37 +0200658private function f_tc_lu_imsi_auth3g_tmsi(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
659 pars.net.expect_auth := true;
660 pars.use_umts_aka := true;
661 f_init_handler(pars);
662 f_perform_lu();
663}
664testcase TC_lu_imsi_auth3g_tmsi() runs on MTC_CT {
665 var BSC_ConnHdlr vc_conn;
666 f_init();
667 f_vty_config(MSCVTY, "network", "authentication required");
668
669 vc_conn := f_start_handler(refers(f_tc_lu_imsi_auth3g_tmsi), 1005);
670 vc_conn.done;
671}
Harald Weltea49e36e2018-01-21 19:29:33 +0100672
673/* Send CM SERVICE REQ for IMSI that has never performed LU before */
674private function f_tc_cmserv_imsi_unknown(charstring id, BSC_ConnHdlrPars pars)
675runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +0100676 f_init_handler(pars);
Harald Weltea49e36e2018-01-21 19:29:33 +0100677
678 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
Harald Welteedbab812018-03-18 16:02:25 +0100679 var BSSMAP_IE_CellIdentifier cell_id := valueof(ts_CellId_CGI('262'H, '42'H, 23, 42));
Harald Welte6ed6bf92018-01-24 21:09:15 +0100680 var PDU_ML3_MS_NW l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, mi));
Harald Weltea49e36e2018-01-21 19:29:33 +0100681
682 f_create_gsup_expect(hex2str(g_pars.imsi));
683
684 /* Send BSSAP_Conn_Req with COMPL L3 INFO to MSC */
Harald Weltedceacc72019-04-21 20:58:35 +0200685 f_cl3_or_initial_ue(l3_info);
Harald Weltea49e36e2018-01-21 19:29:33 +0100686
687 timer T := 10.0;
Harald Weltef6dd64d2017-11-19 12:09:51 +0100688 T.start;
689 alt {
Harald Weltea49e36e2018-01-21 19:29:33 +0100690 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_CM_SERV_REJ)) { }
691 //[] BSSAP.receive(tr_PDU_DTAP_MT(tr_CM_SERV_ACC)) { }
Daniel Willmannafce8662018-07-06 23:11:32 +0200692 [] BSSAP.receive {
693 setverdict(fail, "Received unexpected BSSAP");
694 mtc.stop;
695 }
Harald Weltea49e36e2018-01-21 19:29:33 +0100696 [] GSUP.receive(tr_GSUP_UL_REQ(g_pars.imsi)) {
697 setverdict(fail, "Unexpected GSUP UL REQ");
Daniel Willmannafce8662018-07-06 23:11:32 +0200698 mtc.stop;
Harald Weltea49e36e2018-01-21 19:29:33 +0100699 }
Daniel Willmannafce8662018-07-06 23:11:32 +0200700 [] T.timeout {
701 setverdict(fail, "Timeout waiting for CM SERV REQ");
702 mtc.stop;
703 }
Harald Weltef6dd64d2017-11-19 12:09:51 +0100704 }
705
Harald Welte1ddc7162018-01-27 14:25:46 +0100706 f_expect_clear();
Harald Weltef6dd64d2017-11-19 12:09:51 +0100707}
Harald Weltea49e36e2018-01-21 19:29:33 +0100708testcase TC_cmserv_imsi_unknown() runs on MTC_CT {
709 var BSC_ConnHdlr vc_conn;
710 f_init();
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +0100711 vc_conn := f_start_handler(refers(f_tc_cmserv_imsi_unknown), 6);
Harald Weltea49e36e2018-01-21 19:29:33 +0100712 vc_conn.done;
713}
714
Harald Welte2bb825f2018-01-22 11:31:18 +0100715private function f_tc_lu_and_mo_call(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +0100716 f_init_handler(pars);
Harald Welteb71901a2018-01-26 19:16:05 +0100717 var CallParameters cpars := valueof(t_CallParams('12345'H, 0));
718 cpars.bss_rtp_port := 1110;
719 cpars.mgcp_connection_id_bss := '22222'H;
720 cpars.mgcp_connection_id_mss := '33333'H;
Philipp Maierf1e02bb2018-03-15 16:30:00 +0100721 cpars.mgcp_ep := "rtpbridge/1@mgw";
Harald Welte2bb825f2018-01-22 11:31:18 +0100722
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +0100723 f_perform_lu();
Harald Welteb71901a2018-01-26 19:16:05 +0100724 f_mo_call(cpars);
Harald Welte2bb825f2018-01-22 11:31:18 +0100725}
726testcase TC_lu_and_mo_call() runs on MTC_CT {
727 var BSC_ConnHdlr vc_conn;
728 f_init();
729
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +0100730 vc_conn := f_start_handler(refers(f_tc_lu_and_mo_call), 7);
Harald Welte071ed732018-01-23 19:53:52 +0100731 vc_conn.done;
732}
733
734/* Test LU (with authentication enabled), where HLR times out sending SAI response */
735private function f_tc_lu_auth_sai_timeout(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +0100736 f_init_handler(pars);
Harald Welte071ed732018-01-23 19:53:52 +0100737
738 var PDU_ML3_MS_NW l3_lu := f_build_lu_imsi(g_pars.imsi)
739 var PDU_DTAP_MT dtap_mt;
740
741 /* tell GSUP dispatcher to send this IMSI to us */
742 f_create_gsup_expect(hex2str(g_pars.imsi));
743
744 /* Send BSSAP_Conn_Req with COMPL L3 INFO to MSC */
Harald Weltedceacc72019-04-21 20:58:35 +0200745 f_cl3_or_initial_ue(l3_lu);
Harald Welte071ed732018-01-23 19:53:52 +0100746
747 /* Send Early Classmark, just for the fun of it */
748 BSSAP.send(ts_BSSMAP_ClassmarkUpd(g_pars.cm2, g_pars.cm3));
749
750 GSUP.receive(tr_GSUP_SAI_REQ(g_pars.imsi));
751 /* The HLR would normally return an auth vector here, but we fail to do so. */
752
753 BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Rej));
Harald Welte1ddc7162018-01-27 14:25:46 +0100754 f_expect_clear();
Harald Welte071ed732018-01-23 19:53:52 +0100755}
756testcase TC_lu_auth_sai_timeout() runs on MTC_CT {
757 var BSC_ConnHdlr vc_conn;
758 f_init();
Harald Welte3ca1c902018-01-24 18:51:27 +0100759 f_vty_config(MSCVTY, "network", "authentication required");
Harald Welte071ed732018-01-23 19:53:52 +0100760
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +0100761 vc_conn := f_start_handler(refers(f_tc_lu_auth_sai_timeout), 8);
Harald Welte071ed732018-01-23 19:53:52 +0100762 vc_conn.done;
763}
764
765/* Test LU (with authentication enabled), where HLR rejects sending SAI error */
766private function f_tc_lu_auth_sai_err(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +0100767 f_init_handler(pars);
Harald Welte071ed732018-01-23 19:53:52 +0100768
769 var PDU_ML3_MS_NW l3_lu := f_build_lu_imsi(g_pars.imsi)
770 var PDU_DTAP_MT dtap_mt;
771
772 /* tell GSUP dispatcher to send this IMSI to us */
773 f_create_gsup_expect(hex2str(g_pars.imsi));
774
775 /* Send BSSAP_Conn_Req with COMPL L3 INFO to MSC */
Harald Weltedceacc72019-04-21 20:58:35 +0200776 f_cl3_or_initial_ue(l3_lu);
Harald Welte071ed732018-01-23 19:53:52 +0100777
778 /* Send Early Classmark, just for the fun of it */
779 BSSAP.send(ts_BSSMAP_ClassmarkUpd(g_pars.cm2, g_pars.cm3));
780
781 GSUP.receive(tr_GSUP_SAI_REQ(g_pars.imsi));
782 GSUP.send(ts_GSUP_SAI_ERR(g_pars.imsi, 13));
783
784 BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Rej));
Harald Welte1ddc7162018-01-27 14:25:46 +0100785 f_expect_clear();
Harald Welte071ed732018-01-23 19:53:52 +0100786}
787testcase TC_lu_auth_sai_err() runs on MTC_CT {
788 var BSC_ConnHdlr vc_conn;
789 f_init();
Harald Welte3ca1c902018-01-24 18:51:27 +0100790 f_vty_config(MSCVTY, "network", "authentication required");
Harald Welte071ed732018-01-23 19:53:52 +0100791
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +0100792 vc_conn := f_start_handler(refers(f_tc_lu_auth_sai_err), 9);
Harald Welte2bb825f2018-01-22 11:31:18 +0100793 vc_conn.done;
794}
Harald Weltea49e36e2018-01-21 19:29:33 +0100795
Harald Weltebc881782018-01-23 20:09:15 +0100796/* Test LU but BSC will send a clear request in the middle */
797private function f_tc_lu_clear_request(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +0100798 f_init_handler(pars);
Harald Weltebc881782018-01-23 20:09:15 +0100799
800 var PDU_ML3_MS_NW l3_lu := f_build_lu_imsi(g_pars.imsi)
801 var PDU_DTAP_MT dtap_mt;
802
803 /* tell GSUP dispatcher to send this IMSI to us */
804 f_create_gsup_expect(hex2str(g_pars.imsi));
805
806 /* Send BSSAP_Conn_Req with COMPL L3 INFO to MSC */
Harald Weltedceacc72019-04-21 20:58:35 +0200807 f_cl3_or_initial_ue(l3_lu);
Harald Weltebc881782018-01-23 20:09:15 +0100808
809 /* Send Early Classmark, just for the fun of it */
810 BSSAP.send(ts_BSSMAP_ClassmarkUpd(g_pars.cm2, g_pars.cm3));
811
812 f_sleep(1.0);
813 /* send clear request in the middle of the LU */
814 BSSAP.send(ts_BSSMAP_ClearRequest(0));
Neels Hofmeyr2b326fa2018-04-06 00:59:36 +0200815 alt {
816 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Rej)) { repeat; }
817 [] BSSAP.receive(tr_BSSMAP_ClearCommand) {}
818 }
Harald Weltebc881782018-01-23 20:09:15 +0100819 BSSAP.send(ts_BSSMAP_ClearComplete);
Harald Welte89a32492018-01-27 19:07:28 +0100820 alt {
821 /* See https://osmocom.org/issues/2862 */
Neels Hofmeyr2b326fa2018-04-06 00:59:36 +0200822 [] BSSAP.receive(tr_BSSMAP_ClearCommand) {
823 setverdict(fail, "Got a second Clear Command, only one expected");
Daniel Willmannafce8662018-07-06 23:11:32 +0200824 mtc.stop;
Neels Hofmeyr2b326fa2018-04-06 00:59:36 +0200825 repeat;
826 }
Harald Welte6811d102019-04-14 22:23:14 +0200827 [] BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_IND) {}
Harald Welte89a32492018-01-27 19:07:28 +0100828 }
Harald Weltebc881782018-01-23 20:09:15 +0100829 setverdict(pass);
830}
831testcase TC_lu_clear_request() runs on MTC_CT {
832 var BSC_ConnHdlr vc_conn;
833 f_init();
834
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +0100835 vc_conn := f_start_handler(refers(f_tc_lu_clear_request), 10);
Harald Weltebc881782018-01-23 20:09:15 +0100836 vc_conn.done;
837}
838
Harald Welte66af9e62018-01-24 17:28:21 +0100839/* Test LU but BSC will send a clear request in the middle */
840private function f_tc_lu_disconnect(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +0100841 f_init_handler(pars);
Harald Welte66af9e62018-01-24 17:28:21 +0100842
843 var PDU_ML3_MS_NW l3_lu := f_build_lu_imsi(g_pars.imsi)
844 var PDU_DTAP_MT dtap_mt;
845
846 /* tell GSUP dispatcher to send this IMSI to us */
847 f_create_gsup_expect(hex2str(g_pars.imsi));
848
849 /* Send BSSAP_Conn_Req with COMPL L3 INFO to MSC */
Harald Weltedceacc72019-04-21 20:58:35 +0200850 f_cl3_or_initial_ue(l3_lu);
Harald Welte66af9e62018-01-24 17:28:21 +0100851
852 /* Send Early Classmark, just for the fun of it */
853 BSSAP.send(ts_BSSMAP_ClassmarkUpd(g_pars.cm2, g_pars.cm3));
854
855 f_sleep(1.0);
856 /* send clear request in the middle of the LU */
Harald Welte6811d102019-04-14 22:23:14 +0200857 BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
Harald Welte66af9e62018-01-24 17:28:21 +0100858 setverdict(pass);
Neels Hofmeyrbb825c92019-03-06 15:35:50 +0100859 f_sleep(1.0);
Harald Welte66af9e62018-01-24 17:28:21 +0100860}
861testcase TC_lu_disconnect() runs on MTC_CT {
862 var BSC_ConnHdlr vc_conn;
863 f_init();
864
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +0100865 vc_conn := f_start_handler(refers(f_tc_lu_disconnect), 11);
Harald Welte66af9e62018-01-24 17:28:21 +0100866 vc_conn.done;
867}
868
869
Harald Welteba7b6d92018-01-23 21:32:34 +0100870/* Test LU but with illegal mobile identity type = IMEI */
871private function f_tc_lu_by_imei(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +0100872 f_init_handler(pars);
Harald Welteba7b6d92018-01-23 21:32:34 +0100873
Harald Welte256571e2018-01-24 18:47:19 +0100874 var PDU_ML3_MS_NW l3_lu := f_build_lu_imei(g_pars.imei)
Harald Welteba7b6d92018-01-23 21:32:34 +0100875 var PDU_DTAP_MT dtap_mt;
876
877 /* tell GSUP dispatcher to send this IMSI to us */
878 f_create_gsup_expect(hex2str(g_pars.imsi));
879
880 /* Send BSSAP_Conn_Req with COMPL L3 INFO to MSC */
Harald Weltedceacc72019-04-21 20:58:35 +0200881 f_cl3_or_initial_ue(l3_lu);
Harald Welteba7b6d92018-01-23 21:32:34 +0100882
883 /* Send Early Classmark, just for the fun of it */
884 BSSAP.send(ts_BSSMAP_ClassmarkUpd(g_pars.cm2, g_pars.cm3));
885 /* wait for LU reject, ignore any ID REQ */
886 alt {
887 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Rej)) { }
888 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_MM_ID_Req)) { repeat; }
889 }
890 /* wait for normal teardown */
Harald Welte1ddc7162018-01-27 14:25:46 +0100891 f_expect_clear();
Harald Welteba7b6d92018-01-23 21:32:34 +0100892}
893testcase TC_lu_by_imei() runs on MTC_CT {
894 var BSC_ConnHdlr vc_conn;
895 f_init();
896
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +0100897 vc_conn := f_start_handler(refers(f_tc_lu_by_imei), 12);
Harald Welteba7b6d92018-01-23 21:32:34 +0100898 vc_conn.done;
899}
900
901/* Test LU by TMSI with unknown TMSI, expect (and answer) ID REQ. */
902private function f_tc_lu_tmsi_noauth_unknown(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Stefan Sperling04fc4bc2018-06-25 17:44:57 +0200903 /* We piggyback a test for an MSC crash on overlong IMSI (OS#2864) onto this test. */
904 var hexstring overlong_imsi := '012345789ABCDEF0123456789ABCDEF'H;
Harald Weltea10db902018-01-27 12:44:49 +0100905 f_init_handler(pars);
Harald Welteba7b6d92018-01-23 21:32:34 +0100906
907 var PDU_ML3_MS_NW l3_lu := f_build_lu_tmsi('01020304'O); /* FIXME: Random */
908 var PDU_DTAP_MT dtap_mt;
909
910 /* tell GSUP dispatcher to send this IMSI to us */
911 f_create_gsup_expect(hex2str(g_pars.imsi));
912
913 /* Send BSSAP_Conn_Req with COMPL L3 INFO to MSC */
Harald Weltedceacc72019-04-21 20:58:35 +0200914 f_cl3_or_initial_ue(l3_lu);
Harald Welteba7b6d92018-01-23 21:32:34 +0100915
916 /* Send Early Classmark, just for the fun of it */
917 BSSAP.send(ts_BSSMAP_ClassmarkUpd(g_pars.cm2, g_pars.cm3));
918
919 /* Wait for + respond to ID REQ (IMSI) */
920 BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_MM_ID_Req('001'B)));
Stefan Sperling04fc4bc2018-06-25 17:44:57 +0200921 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 +0100922 BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_MM_ID_Rsp_IMSI(g_pars.imsi)));
923
924 /* Expect MSC to do UpdateLocation to HLR; respond to it */
925 GSUP.receive(tr_GSUP_UL_REQ(g_pars.imsi));
926 GSUP.send(ts_GSUP_ISD_REQ(g_pars.imsi, g_pars.msisdn));
927 GSUP.receive(tr_GSUP_ISD_RES(g_pars.imsi));
928 GSUP.send(ts_GSUP_UL_RES(g_pars.imsi));
929
930 alt {
Harald Welte7ec4fa82018-01-27 10:57:40 +0100931 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Acc)) {
932 BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_TmsiRealloc_Cmpl));
933 }
Harald Welteba7b6d92018-01-23 21:32:34 +0100934 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Rej)) {
935 setverdict(fail, "Expected LU ACK, but received REJ");
Daniel Willmannafce8662018-07-06 23:11:32 +0200936 mtc.stop;
Harald Welteba7b6d92018-01-23 21:32:34 +0100937 }
938 }
939
Philipp Maier9b690e42018-12-21 11:50:03 +0100940 /* Wait for MM-Information (if enabled) */
941 f_expect_mm_info();
942
Harald Welteba7b6d92018-01-23 21:32:34 +0100943 /* wait for normal teardown */
Harald Welte1ddc7162018-01-27 14:25:46 +0100944 f_expect_clear();
Harald Welteba7b6d92018-01-23 21:32:34 +0100945}
946testcase TC_lu_by_tmsi_noauth_unknown() runs on MTC_CT {
947 var BSC_ConnHdlr vc_conn;
948 f_init();
949
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +0100950 vc_conn := f_start_handler(refers(f_tc_lu_tmsi_noauth_unknown), 13);
Harald Welteba7b6d92018-01-23 21:32:34 +0100951 vc_conn.done;
952}
953
954
Harald Welte45164da2018-01-24 12:51:27 +0100955/* Test IMSI DETACH (MI=IMSI) */
956private function f_tc_imsi_detach_by_imsi(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +0100957 f_init_handler(pars);
Harald Welte45164da2018-01-24 12:51:27 +0100958
959 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
960
961 /* Send BSSAP_Conn_Req with COMPL L3 INFO to MSC */
Harald Weltedceacc72019-04-21 20:58:35 +0200962 f_cl3_or_initial_ue(valueof(ts_ML3_MO_MM_IMSI_DET_Ind(mi)));
Harald Welte45164da2018-01-24 12:51:27 +0100963
964 /* Send Early Classmark, just for the fun of it? */
965 BSSAP.send(ts_BSSMAP_ClassmarkUpd(g_pars.cm2, g_pars.cm3));
966
967 /* wait for normal teardown */
Harald Welte1ddc7162018-01-27 14:25:46 +0100968 f_expect_clear();
Harald Welte45164da2018-01-24 12:51:27 +0100969}
970testcase TC_imsi_detach_by_imsi() 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_imsi_detach_by_imsi), 14);
Harald Welte45164da2018-01-24 12:51:27 +0100975 vc_conn.done;
976}
977
978/* Test IMSI DETACH (MI=TMSI) */
979private function f_tc_imsi_detach_by_tmsi(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +0100980 f_init_handler(pars);
Harald Welte45164da2018-01-24 12:51:27 +0100981
982 var MobileIdentityLV mi := valueof(ts_MI_TMSI_LV('01020304'O));
983
984 /* Send BSSAP_Conn_Req with COMPL L3 INFO to MSC */
Harald Weltedceacc72019-04-21 20:58:35 +0200985 f_cl3_or_initial_ue(valueof(ts_ML3_MO_MM_IMSI_DET_Ind(mi)));
Harald Welte45164da2018-01-24 12:51:27 +0100986
987 /* Send Early Classmark, just for the fun of it? */
988 BSSAP.send(ts_BSSMAP_ClassmarkUpd(g_pars.cm2, g_pars.cm3));
989
990 /* wait for normal teardown */
Harald Welte1ddc7162018-01-27 14:25:46 +0100991 f_expect_clear();
Harald Welte45164da2018-01-24 12:51:27 +0100992}
993testcase TC_imsi_detach_by_tmsi() runs on MTC_CT {
994 var BSC_ConnHdlr vc_conn;
995 f_init();
996
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +0100997 vc_conn := f_start_handler(refers(f_tc_imsi_detach_by_tmsi), 15);
Harald Welte45164da2018-01-24 12:51:27 +0100998 vc_conn.done;
999}
1000
1001/* Test IMSI DETACH (MI=IMEI), which is illegal */
1002private function f_tc_imsi_detach_by_imei(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +01001003 f_init_handler(pars);
Harald Welte45164da2018-01-24 12:51:27 +01001004
Harald Welte256571e2018-01-24 18:47:19 +01001005 var MobileIdentityLV mi := valueof(ts_MI_IMEI_LV(g_pars.imei));
Harald Welte45164da2018-01-24 12:51:27 +01001006
1007 /* Send BSSAP_Conn_Req with COMPL L3 INFO to MSC */
Harald Weltedceacc72019-04-21 20:58:35 +02001008 f_cl3_or_initial_ue(valueof(ts_ML3_MO_MM_IMSI_DET_Ind(mi)));
Harald Welte45164da2018-01-24 12:51:27 +01001009
1010 /* Send Early Classmark, just for the fun of it? */
1011 BSSAP.send(ts_BSSMAP_ClassmarkUpd(g_pars.cm2, g_pars.cm3));
1012
1013 /* wait for normal teardown */
Harald Welte1ddc7162018-01-27 14:25:46 +01001014 f_expect_clear();
Harald Welte45164da2018-01-24 12:51:27 +01001015}
1016testcase TC_imsi_detach_by_imei() runs on MTC_CT {
1017 var BSC_ConnHdlr vc_conn;
1018 f_init();
1019
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001020 vc_conn := f_start_handler(refers(f_tc_imsi_detach_by_imei), 16);
Harald Welte45164da2018-01-24 12:51:27 +01001021 vc_conn.done;
1022}
1023
1024
1025/* helper function for an emergency call. caller passes in mobile identity to use */
1026private function f_emerg_call(MobileIdentityLV mi) runs on BSC_ConnHdlr {
Harald Welte0bef21e2018-02-10 09:48:23 +01001027 var CallParameters cpars := valueof(t_CallParams('112'H, 0));
1028 cpars.emergency := true;
Philipp Maierf1e02bb2018-03-15 16:30:00 +01001029 cpars.mgcp_ep := "rtpbridge/1@mgw";
Harald Welte45164da2018-01-24 12:51:27 +01001030
Harald Welte0bef21e2018-02-10 09:48:23 +01001031 f_mo_call(cpars);
Harald Welte45164da2018-01-24 12:51:27 +01001032}
1033
1034/* establish an emergency call by IMEI, no SIM inserted (and hence no IMSI) */
1035private function f_tc_emerg_call_imei_reject(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +01001036 f_init_handler(pars);
Harald Welte45164da2018-01-24 12:51:27 +01001037
Harald Welte256571e2018-01-24 18:47:19 +01001038 var MobileIdentityLV mi := valueof(ts_MI_IMEI_LV(g_pars.imei));
Harald Welte6ed6bf92018-01-24 21:09:15 +01001039 var PDU_ML3_MS_NW l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_EMERG_CALL, mi));
Harald Weltedceacc72019-04-21 20:58:35 +02001040 f_cl3_or_initial_ue(l3_info);
Harald Welte45164da2018-01-24 12:51:27 +01001041 BSSAP.receive(tr_PDU_DTAP_MT(tr_CM_SERV_REJ('05'O)));
Harald Welte1ddc7162018-01-27 14:25:46 +01001042 f_expect_clear();
Harald Welte45164da2018-01-24 12:51:27 +01001043}
1044testcase TC_emerg_call_imei_reject() runs on MTC_CT {
1045 var BSC_ConnHdlr vc_conn;
1046 f_init();
1047
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001048 vc_conn := f_start_handler(refers(f_tc_emerg_call_imei_reject), 17);
Harald Welte45164da2018-01-24 12:51:27 +01001049 vc_conn.done;
1050}
1051
Harald Welted5b91402018-01-24 18:48:16 +01001052/* establish an emergency call by IMSI, SIM inserted (and hence IMSI) */
Harald Welte45164da2018-01-24 12:51:27 +01001053private function f_tc_emerg_call_imsi(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +01001054 f_init_handler(pars);
Harald Welte45164da2018-01-24 12:51:27 +01001055 /* First perform location update to ensure subscriber is known */
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +01001056 f_perform_lu();
Harald Welte45164da2018-01-24 12:51:27 +01001057 /* Then issue emergency call identified by IMSI */
1058 f_emerg_call(valueof(ts_MI_IMSI_LV(g_pars.imsi)));
1059}
1060testcase TC_emerg_call_imsi() runs on MTC_CT {
1061 var BSC_ConnHdlr vc_conn;
1062 f_init();
1063
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001064 vc_conn := f_start_handler(refers(f_tc_emerg_call_imsi), 18);
Harald Welte45164da2018-01-24 12:51:27 +01001065 vc_conn.done;
1066}
1067
1068/* CM Service Request for VGCS -> reject */
1069private function f_tc_cm_serv_req_vgcs_reject(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +01001070 f_init_handler(pars);
Harald Welte45164da2018-01-24 12:51:27 +01001071
1072 /* First perform location update to ensure subscriber is known */
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +01001073 f_perform_lu();
Harald Welte45164da2018-01-24 12:51:27 +01001074
1075 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
Harald Welte6ed6bf92018-01-24 21:09:15 +01001076 var PDU_ML3_MS_NW l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_VGCS, mi));
Harald Weltedceacc72019-04-21 20:58:35 +02001077 f_cl3_or_initial_ue(l3_info);
Harald Welte45164da2018-01-24 12:51:27 +01001078 BSSAP.receive(tr_PDU_DTAP_MT(tr_CM_SERV_REJ(int2oct(32,1))));
Harald Welte1ddc7162018-01-27 14:25:46 +01001079 f_expect_clear();
Harald Welte45164da2018-01-24 12:51:27 +01001080}
1081testcase TC_cm_serv_req_vgcs_reject() runs on MTC_CT {
1082 var BSC_ConnHdlr vc_conn;
1083 f_init();
1084
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001085 vc_conn := f_start_handler(refers(f_tc_cm_serv_req_vgcs_reject), 19);
Harald Welte45164da2018-01-24 12:51:27 +01001086 vc_conn.done;
1087}
1088
1089/* CM Service Request for VBS -> reject */
1090private function f_tc_cm_serv_req_vbs_reject(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +01001091 f_init_handler(pars);
Harald Welte45164da2018-01-24 12:51:27 +01001092
1093 /* First perform location update to ensure subscriber is known */
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +01001094 f_perform_lu();
Harald Welte45164da2018-01-24 12:51:27 +01001095
1096 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
Harald Welte6ed6bf92018-01-24 21:09:15 +01001097 var PDU_ML3_MS_NW l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_VBS, mi));
Harald Weltedceacc72019-04-21 20:58:35 +02001098 f_cl3_or_initial_ue(l3_info);
Harald Welte45164da2018-01-24 12:51:27 +01001099 BSSAP.receive(tr_PDU_DTAP_MT(tr_CM_SERV_REJ(int2oct(32,1))));
Harald Welte1ddc7162018-01-27 14:25:46 +01001100 f_expect_clear();
Harald Welte45164da2018-01-24 12:51:27 +01001101}
1102testcase TC_cm_serv_req_vbs_reject() runs on MTC_CT {
1103 var BSC_ConnHdlr vc_conn;
1104 f_init();
1105
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001106 vc_conn := f_start_handler(refers(f_tc_cm_serv_req_vbs_reject), 20);
Harald Welte45164da2018-01-24 12:51:27 +01001107 vc_conn.done;
1108}
1109
1110/* CM Service Request for LCS -> reject */
1111private function f_tc_cm_serv_req_lcs_reject(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +01001112 f_init_handler(pars);
Harald Welte45164da2018-01-24 12:51:27 +01001113
1114 /* First perform location update to ensure subscriber is known */
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +01001115 f_perform_lu();
Harald Welte45164da2018-01-24 12:51:27 +01001116
1117 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
Harald Welte6ed6bf92018-01-24 21:09:15 +01001118 var PDU_ML3_MS_NW l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_LCS, mi));
Harald Weltedceacc72019-04-21 20:58:35 +02001119 f_cl3_or_initial_ue(l3_info);
Harald Welte45164da2018-01-24 12:51:27 +01001120 BSSAP.receive(tr_PDU_DTAP_MT(tr_CM_SERV_REJ(int2oct(32,1))));
Harald Welte1ddc7162018-01-27 14:25:46 +01001121 f_expect_clear();
Harald Welte45164da2018-01-24 12:51:27 +01001122}
1123testcase TC_cm_serv_req_lcs_reject() runs on MTC_CT {
1124 var BSC_ConnHdlr vc_conn;
1125 f_init();
1126
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001127 vc_conn := f_start_handler(refers(f_tc_cm_serv_req_lcs_reject), 21);
Harald Welte45164da2018-01-24 12:51:27 +01001128 vc_conn.done;
1129}
1130
Harald Welte0195ab12018-01-24 21:50:20 +01001131/* CM Re-Establishment Request */
1132private function f_tc_cm_reest_req_reject(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +01001133 f_init_handler(pars);
Harald Welte0195ab12018-01-24 21:50:20 +01001134
1135 /* First perform location update to ensure subscriber is known */
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +01001136 f_perform_lu();
Harald Welte0195ab12018-01-24 21:50:20 +01001137
1138 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
1139 var PDU_ML3_MS_NW l3_info := valueof(ts_CM_REEST_REQ(0, mi));
Harald Weltedceacc72019-04-21 20:58:35 +02001140 f_cl3_or_initial_ue(l3_info);
Harald Welte0195ab12018-01-24 21:50:20 +01001141 BSSAP.receive(tr_PDU_DTAP_MT(tr_CM_SERV_REJ(int2oct(32,1))));
Harald Welte1ddc7162018-01-27 14:25:46 +01001142 f_expect_clear();
Harald Welte0195ab12018-01-24 21:50:20 +01001143}
1144testcase TC_cm_reest_req_reject() runs on MTC_CT {
1145 var BSC_ConnHdlr vc_conn;
1146 f_init();
Harald Welte0195ab12018-01-24 21:50:20 +01001147
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001148 vc_conn := f_start_handler(refers(f_tc_cm_reest_req_reject), 22);
Harald Welte0195ab12018-01-24 21:50:20 +01001149 vc_conn.done;
1150}
1151
Harald Weltec638f4d2018-01-24 22:00:36 +01001152/* Test LU (with authentication enabled), with wrong response from MS */
1153private function f_tc_lu_auth_2G_fail(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +01001154 f_init_handler(pars);
Harald Weltec638f4d2018-01-24 22:00:36 +01001155
1156 var PDU_ML3_MS_NW l3_lu := f_build_lu_imsi(g_pars.imsi)
1157
1158 /* tell GSUP dispatcher to send this IMSI to us */
1159 f_create_gsup_expect(hex2str(g_pars.imsi));
1160
1161 /* Send BSSAP_Conn_Req with COMPL L3 INFO to MSC */
Harald Weltedceacc72019-04-21 20:58:35 +02001162 f_cl3_or_initial_ue(l3_lu);
Harald Weltec638f4d2018-01-24 22:00:36 +01001163
1164 /* Send Early Classmark, just for the fun of it */
1165 BSSAP.send(ts_BSSMAP_ClassmarkUpd(g_pars.cm2, g_pars.cm3));
1166
1167 var AuthVector vec := f_gen_auth_vec_2g();
1168 var GSUP_IE auth_tuple := valueof(ts_GSUP_IE_AuthTuple2G(vec.rand, vec.sres, vec.kc));
1169 GSUP.receive(tr_GSUP_SAI_REQ(g_pars.imsi));
1170 GSUP.send(ts_GSUP_SAI_RES(g_pars.imsi, auth_tuple));
1171
1172 BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_MM_AUTH_REQ(vec.rand)));
1173 /* Send back wrong auth response */
1174 BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MT_MM_AUTH_RESP_2G('00000000'O)));
1175
1176 /* Expect GSUP AUTH FAIL REP to HLR */
1177 GSUP.receive(tr_GSUP_AUTH_FAIL_IND(g_pars.imsi));
1178
1179 /* Expect LU REJECT with Cause == Illegal MS */
1180 BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Rej('03'O)));
Harald Welte1ddc7162018-01-27 14:25:46 +01001181 f_expect_clear();
Harald Weltec638f4d2018-01-24 22:00:36 +01001182}
1183testcase TC_lu_auth_2G_fail() runs on MTC_CT {
1184 var BSC_ConnHdlr vc_conn;
1185 f_init();
1186 f_vty_config(MSCVTY, "network", "authentication required");
Harald Weltec638f4d2018-01-24 22:00:36 +01001187
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001188 vc_conn := f_start_handler(refers(f_tc_lu_auth_2G_fail), 23);
Harald Weltec638f4d2018-01-24 22:00:36 +01001189 vc_conn.done;
1190}
1191
Harald Weltede371492018-01-27 23:44:41 +01001192/* A5/1 + A5/3 permitted on network side, and MS capable to do it */
Harald Welte16114282018-01-24 22:41:21 +01001193private 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 +01001194 pars.net.expect_auth := true;
1195 pars.net.expect_ciph := true;
Harald Weltea10db902018-01-27 12:44:49 +01001196 f_init_handler(pars);
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +01001197 f_perform_lu();
Harald Welte16114282018-01-24 22:41:21 +01001198}
1199testcase TC_lu_imsi_auth_tmsi_encr_13_13() runs on MTC_CT {
1200 var BSC_ConnHdlr vc_conn;
1201 f_init();
1202 f_vty_config(MSCVTY, "network", "authentication required");
Harald Welte16114282018-01-24 22:41:21 +01001203 f_vty_config(MSCVTY, "network", "encryption a5 1 3");
1204
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001205 vc_conn := f_start_handler(refers(f_tc_lu_imsi_auth_tmsi_encr_13_13), 24);
Harald Welte16114282018-01-24 22:41:21 +01001206 vc_conn.done;
1207}
1208
Harald Welte1af6ea82018-01-25 18:33:15 +01001209/* Test Complete L3 without payload */
1210private function f_tc_cl3_no_payload(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +01001211 f_init_handler(pars);
Harald Welte1af6ea82018-01-25 18:33:15 +01001212
1213 /* Send Complete L3 Info with empty L3 frame */
1214 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_peer, g_pars.sccp_addr_own,
1215 valueof(ts_BSSMAP_ComplL3(g_pars.cell_id, ''O))));
1216
Harald Weltef466eb42018-01-27 14:26:54 +01001217 timer T := 5.0;
1218 T.start;
Harald Welte1af6ea82018-01-25 18:33:15 +01001219 alt {
Harald Welte6811d102019-04-14 22:23:14 +02001220 [] BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_IND) {}
Harald Welte1af6ea82018-01-25 18:33:15 +01001221 /* Expect LU REJECT with Cause == Illegal MS */
Harald Weltebdb3c452018-03-18 22:43:06 +01001222 [] BSSAP.receive(tr_PDU_DTAP_MT(?)) { repeat; }
Harald Welte6811d102019-04-14 22:23:14 +02001223 [] BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND) { repeat; }
Harald Welte5946b332018-03-18 23:32:21 +01001224 [] as_clear_cmd_compl_disc();
Harald Weltef466eb42018-01-27 14:26:54 +01001225 [] T.timeout {
Daniel Willmann90829d62018-02-15 17:45:14 +01001226 setverdict(fail, "Timeout waiting for ClearCommand or SCCP Release");
Daniel Willmannafce8662018-07-06 23:11:32 +02001227 mtc.stop;
Harald Weltef466eb42018-01-27 14:26:54 +01001228 }
Harald Welte1af6ea82018-01-25 18:33:15 +01001229 }
1230 setverdict(pass);
1231}
1232testcase TC_cl3_no_payload() runs on MTC_CT {
1233 var BSC_ConnHdlr vc_conn;
1234 f_init();
1235
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001236 vc_conn := f_start_handler(refers(f_tc_cl3_no_payload), 25);
Harald Welte1af6ea82018-01-25 18:33:15 +01001237 vc_conn.done;
1238}
1239
1240/* Test Complete L3 with random payload */
1241private function f_tc_cl3_rnd_payload(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +01001242 f_init_handler(pars);
Harald Welte1af6ea82018-01-25 18:33:15 +01001243
Daniel Willmannaa14a382018-07-26 08:29:45 +02001244 /* length is limited by PDU_BSSAP length field which includes some
1245 * other fields beside l3info payload. So payl can only be 240 bytes
1246 * Since rnd() returns values < 1 multiply with 241
1247 */
1248 var integer len := float2int(rnd() * 241.0);
Harald Welte1af6ea82018-01-25 18:33:15 +01001249 var octetstring payl := f_rnd_octstring(len);
1250
1251 /* Send Complete L3 Info with empty L3 frame */
1252 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_peer, g_pars.sccp_addr_own,
1253 valueof(ts_BSSMAP_ComplL3(g_pars.cell_id, payl))));
1254
Harald Weltef466eb42018-01-27 14:26:54 +01001255 timer T := 5.0;
1256 T.start;
Harald Welte1af6ea82018-01-25 18:33:15 +01001257 alt {
1258 /* Immediate disconnect */
Harald Welte6811d102019-04-14 22:23:14 +02001259 [] BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_IND) {}
Harald Welte1af6ea82018-01-25 18:33:15 +01001260 [] BSSAP.receive(tr_PDU_DTAP_MT(?)) { repeat; }
Harald Welte6811d102019-04-14 22:23:14 +02001261 [] BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND) { repeat; }
Harald Welte5946b332018-03-18 23:32:21 +01001262 [] as_clear_cmd_compl_disc();
Harald Weltef466eb42018-01-27 14:26:54 +01001263 [] T.timeout {
Daniel Willmann90829d62018-02-15 17:45:14 +01001264 setverdict(fail, "Timeout waiting for ClearCommand or SCCP Release");
Daniel Willmannafce8662018-07-06 23:11:32 +02001265 mtc.stop;
Harald Weltef466eb42018-01-27 14:26:54 +01001266 }
Harald Welte1af6ea82018-01-25 18:33:15 +01001267 }
1268 setverdict(pass);
1269}
1270testcase TC_cl3_rnd_payload() runs on MTC_CT {
1271 var BSC_ConnHdlr vc_conn;
1272 f_init();
1273
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001274 vc_conn := f_start_handler(refers(f_tc_cl3_rnd_payload), 26);
Harald Welte1af6ea82018-01-25 18:33:15 +01001275 vc_conn.done;
1276}
1277
Harald Welte116e4332018-01-26 22:17:48 +01001278/* Test Complete L3 with random payload */
1279private function f_tc_establish_and_nothing(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +01001280 f_init_handler(pars);
Harald Welte116e4332018-01-26 22:17:48 +01001281
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +01001282 f_perform_lu();
Harald Welte116e4332018-01-26 22:17:48 +01001283
Harald Welteb9e86fa2018-04-09 18:18:31 +02001284 f_establish_fully();
Daniel Willmann898a7e02018-05-17 12:16:16 +02001285 f_expect_clear(10.0);
Harald Welte116e4332018-01-26 22:17:48 +01001286}
1287testcase TC_establish_and_nothing() runs on MTC_CT {
1288 var BSC_ConnHdlr vc_conn;
1289 f_init();
1290
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001291 vc_conn := f_start_handler(refers(f_tc_establish_and_nothing), 27);
Harald Welte116e4332018-01-26 22:17:48 +01001292 vc_conn.done;
1293}
1294
Harald Welte12510c52018-01-26 22:26:24 +01001295/* Test MO Call SETUP with no response from MNCC */
1296private function f_tc_mo_setup_and_nothing(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Philipp Maier109e6aa2018-10-17 10:53:32 +02001297 f_init_handler(pars, 190.0);
Harald Weltea10db902018-01-27 12:44:49 +01001298
Harald Welte12510c52018-01-26 22:26:24 +01001299 var CallParameters cpars := valueof(t_CallParams('12345'H, 0));
1300
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +01001301 f_perform_lu();
Harald Welte12510c52018-01-26 22:26:24 +01001302
Harald Welteb9e86fa2018-04-09 18:18:31 +02001303 f_establish_fully();
Harald Welte12510c52018-01-26 22:26:24 +01001304 f_create_mncc_expect(hex2str(cpars.called_party));
1305 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
1306
1307 BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_CC_SETUP(cpars.transaction_id, cpars.called_party)));
1308
Neels Hofmeyrde76f052019-02-26 05:02:46 +01001309 var default ccrel := activate(as_optional_cc_rel(cpars));
1310
Philipp Maier109e6aa2018-10-17 10:53:32 +02001311 f_expect_clear(185.0);
Neels Hofmeyrde76f052019-02-26 05:02:46 +01001312
1313 deactivate(ccrel);
1314
1315 f_sleep(1.0);
Harald Welte12510c52018-01-26 22:26:24 +01001316}
1317testcase TC_mo_setup_and_nothing() runs on MTC_CT {
1318 var BSC_ConnHdlr vc_conn;
1319 f_init();
1320
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001321 vc_conn := f_start_handler(refers(f_tc_mo_setup_and_nothing), 28);
Harald Welte12510c52018-01-26 22:26:24 +01001322 vc_conn.done;
1323}
1324
Harald Welte3ab88002018-01-26 22:37:25 +01001325/* Test MO Call with no response to RAN-side CRCX */
1326private function f_tc_mo_crcx_ran_timeout(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +01001327 f_init_handler(pars);
Harald Welte3ab88002018-01-26 22:37:25 +01001328 var CallParameters cpars := valueof(t_CallParams('12345'H, 0));
1329 var MNCC_PDU mncc;
1330 var MgcpCommand mgcp_cmd;
1331
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +01001332 f_perform_lu();
Harald Welte3ab88002018-01-26 22:37:25 +01001333
Harald Welteb9e86fa2018-04-09 18:18:31 +02001334 f_establish_fully();
Harald Welte3ab88002018-01-26 22:37:25 +01001335 f_create_mncc_expect(hex2str(cpars.called_party));
1336 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
1337
1338 BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_CC_SETUP(cpars.transaction_id, cpars.called_party)));
1339 MNCC.receive(tr_MNCC_SETUP_ind(?, tr_MNCC_number(hex2str(cpars.called_party)))) -> value mncc;
1340 cpars.mncc_callref := mncc.u.signal.callref;
1341 MNCC.send(ts_MNCC_CALL_PROC_req(cpars.mncc_callref, cpars.mncc_bearer_cap));
1342 BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_CC_CALL_PROC(cpars.transaction_id)));
1343
1344 MGCP.receive(tr_CRCX) -> value mgcp_cmd;
Harald Welte1852a842018-01-26 22:53:36 +01001345 cpars.mgcp_call_id := f_MgcpCmd_extract_call_id(mgcp_cmd);
1346 cpars.mgcp_ep := mgcp_cmd.line.ep;
Harald Welte3ab88002018-01-26 22:37:25 +01001347 /* never respond to this */
1348
Philipp Maier8e58f592018-03-14 11:10:56 +01001349 /* When the connection with the MGW fails, the MSC will first request
1350 * a release via call control. We will answer this request normally. */
1351 BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_CC_RELEASE(cpars.transaction_id)));
1352 BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_CC_REL_COMPL(cpars.transaction_id)));
1353
Harald Welte1ddc7162018-01-27 14:25:46 +01001354 f_expect_clear(30.0);
Harald Welte3ab88002018-01-26 22:37:25 +01001355}
1356testcase TC_mo_crcx_ran_timeout() runs on MTC_CT {
1357 var BSC_ConnHdlr vc_conn;
1358 f_init();
1359
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001360 vc_conn := f_start_handler(refers(f_tc_mo_crcx_ran_timeout), 29);
Harald Welte3ab88002018-01-26 22:37:25 +01001361 vc_conn.done;
1362}
1363
Harald Welte0cc82d92018-01-26 22:52:34 +01001364/* Test MO Call with reject to RAN-side CRCX */
1365private function f_tc_mo_crcx_ran_reject(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +01001366 f_init_handler(pars);
Harald Welte0cc82d92018-01-26 22:52:34 +01001367 var CallParameters cpars := valueof(t_CallParams('12345'H, 0));
1368 var MNCC_PDU mncc;
1369 var MgcpCommand mgcp_cmd;
1370
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +01001371 f_perform_lu();
Harald Welte0cc82d92018-01-26 22:52:34 +01001372
Harald Welteb9e86fa2018-04-09 18:18:31 +02001373 f_establish_fully();
Harald Welte0cc82d92018-01-26 22:52:34 +01001374 f_create_mncc_expect(hex2str(cpars.called_party));
1375 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
1376
1377 BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_CC_SETUP(cpars.transaction_id, cpars.called_party)));
1378 MNCC.receive(tr_MNCC_SETUP_ind(?, tr_MNCC_number(hex2str(cpars.called_party)))) -> value mncc;
1379 cpars.mncc_callref := mncc.u.signal.callref;
1380 MNCC.send(ts_MNCC_CALL_PROC_req(cpars.mncc_callref, cpars.mncc_bearer_cap));
1381 BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_CC_CALL_PROC(cpars.transaction_id)));
1382
1383 MGCP.receive(tr_CRCX) -> value mgcp_cmd;
Philipp Maierf1e02bb2018-03-15 16:30:00 +01001384
1385 /* Detect if the received CRCX is a wildcarded CRCX request. If yes,
1386 * set an endpoint name that fits the pattern. If not, just use the
1387 * endpoint name from the request */
1388 if (match(mgcp_cmd.line.ep, t_MGCP_EP_wildcard)) {
1389 cpars.mgcp_ep := "rtpbridge/1@mgw";
1390 } else {
1391 cpars.mgcp_ep := mgcp_cmd.line.ep;
1392 }
1393
Harald Welte0cc82d92018-01-26 22:52:34 +01001394 cpars.mgcp_call_id := f_MgcpCmd_extract_call_id(mgcp_cmd);
Philipp Maierf1e02bb2018-03-15 16:30:00 +01001395
Harald Welte0cc82d92018-01-26 22:52:34 +01001396 /* Respond to CRCX with error */
1397 var MgcpResponse mgcp_rsp := {
1398 line := {
1399 code := "542",
1400 trans_id := mgcp_cmd.line.trans_id,
1401 string := "FORCED_FAIL"
1402 },
Harald Welte0cc82d92018-01-26 22:52:34 +01001403 sdp := omit
1404 }
Philipp Maierf1e02bb2018-03-15 16:30:00 +01001405 var MgcpParameter mgcp_rsp_param := {
1406 code := "Z",
1407 val := cpars.mgcp_ep
1408 };
1409 mgcp_rsp.params[0] := mgcp_rsp_param;
Harald Welte0cc82d92018-01-26 22:52:34 +01001410 MGCP.send(mgcp_rsp);
1411
1412 timer T := 30.0;
1413 T.start;
1414 alt {
Daniel Willmannafce8662018-07-06 23:11:32 +02001415 [] T.timeout {
1416 setverdict(fail, "Timeout waiting for channel release");
1417 mtc.stop;
1418 }
Daniel Willmann5868e622018-02-15 17:42:59 +01001419 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_CC_RELEASE(cpars.transaction_id))) {
1420 BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_CC_REL_COMPL(cpars.transaction_id)));
1421 repeat;
1422 }
Harald Welte0cc82d92018-01-26 22:52:34 +01001423 [] MNCC.receive { repeat; }
1424 [] GSUP.receive { repeat; }
Philipp Maierc6e06f72018-04-11 18:12:23 +02001425 /* Note: As we did not respond properly to the CRCX from the MSC we
1426 * expect the MSC to omit any further MGCP operation (At least in the
1427 * the current implementation, there is no recovery mechanism implemented
1428 * and a DLCX can not be performed as the MSC does not know a specific
1429 * endpoint yet. */
Daniel Willmannafce8662018-07-06 23:11:32 +02001430 [] MGCP.receive {
1431 setverdict(fail, "Unexpected MGCP message");
1432 mtc.stop;
1433 }
Harald Welte5946b332018-03-18 23:32:21 +01001434 [] as_clear_cmd_compl_disc();
Harald Welte0cc82d92018-01-26 22:52:34 +01001435 }
1436}
1437testcase TC_mo_crcx_ran_reject() runs on MTC_CT {
1438 var BSC_ConnHdlr vc_conn;
1439 f_init();
1440
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001441 vc_conn := f_start_handler(refers(f_tc_mo_crcx_ran_reject), 30);
Harald Welte0cc82d92018-01-26 22:52:34 +01001442 vc_conn.done;
1443}
1444
Harald Welte3ab88002018-01-26 22:37:25 +01001445
Harald Welte812f7a42018-01-27 00:49:18 +01001446/* helper function to start a MT call: MNCC SETUP; Paging; DChan est.; DTAP SETUP */
1447private function f_mt_call_start(inout CallParameters cpars) runs on BSC_ConnHdlr {
1448 var MNCC_PDU mncc;
1449 var MgcpCommand mgcp_cmd;
1450 var OCT4 tmsi;
1451
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +01001452 f_perform_lu();
Harald Welte812f7a42018-01-27 00:49:18 +01001453 if (isvalue(g_pars.tmsi)) {
1454 tmsi := g_pars.tmsi;
1455 } else {
1456 tmsi := 'FFFFFFFF'O;
1457 }
Harald Welte6811d102019-04-14 22:23:14 +02001458 f_ran_register_imsi(g_pars.imsi, tmsi);
Harald Welte812f7a42018-01-27 00:49:18 +01001459
1460 /* Allocate call reference and send SETUP via MNCC to MSC */
1461 cpars.mncc_callref := f_rnd_int(2147483648);
1462 MNCC.send(ts_MNCC_SETUP_req(cpars.mncc_callref, hex2str(g_pars.msisdn),
1463 hex2str(cpars.called_party), hex2str(g_pars.imsi)));
1464
1465 /* MSC->BSC: expect PAGING from MSC */
Harald Weltee035e3e2019-04-21 17:32:05 +02001466 f_expect_paging();
1467
Harald Welte812f7a42018-01-27 00:49:18 +01001468 /* MS -> MSC: PAGING RESPONSE */
Harald Welteb9e86fa2018-04-09 18:18:31 +02001469 f_establish_fully(EST_TYPE_PAG_RESP);
Harald Welte812f7a42018-01-27 00:49:18 +01001470
1471 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
1472
1473 /* MSC->MS: SETUP */
1474 BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_CC_SETUP(cpars.transaction_id, *, cpars.called_party)));
1475}
1476
1477/* Test MT Call */
1478private function f_tc_mt_crcx_ran_reject(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +01001479 f_init_handler(pars);
Harald Welte812f7a42018-01-27 00:49:18 +01001480 var CallParameters cpars := valueof(t_CallParams('123456'H, 0));
1481 var MNCC_PDU mncc;
1482 var MgcpCommand mgcp_cmd;
1483
1484 f_mt_call_start(cpars);
1485
1486 /* MS->MSC: CALL CONFIRMED */
1487 BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_CC_CALL_CONF(cpars.transaction_id)));
1488
1489 MNCC.receive(tr_MNCC_CALL_CONF_ind(cpars.mncc_callref));
1490
1491 MGCP.receive(tr_CRCX) -> value mgcp_cmd;
1492 cpars.mgcp_call_id := f_MgcpCmd_extract_call_id(mgcp_cmd);
Philipp Maierf1e02bb2018-03-15 16:30:00 +01001493
1494 /* Detect if the received CRCX is a wildcarded CRCX request. If yes,
1495 * set an endpoint name that fits the pattern. If not, just use the
1496 * endpoint name from the request */
1497 if (match(mgcp_cmd.line.ep, t_MGCP_EP_wildcard)) {
1498 cpars.mgcp_ep := "rtpbridge/1@mgw";
1499 } else {
1500 cpars.mgcp_ep := mgcp_cmd.line.ep;
1501 }
1502
Harald Welte812f7a42018-01-27 00:49:18 +01001503 /* Respond to CRCX with error */
1504 var MgcpResponse mgcp_rsp := {
1505 line := {
1506 code := "542",
1507 trans_id := mgcp_cmd.line.trans_id,
1508 string := "FORCED_FAIL"
1509 },
Harald Welte812f7a42018-01-27 00:49:18 +01001510 sdp := omit
1511 }
Philipp Maierf1e02bb2018-03-15 16:30:00 +01001512 var MgcpParameter mgcp_rsp_param := {
1513 code := "Z",
1514 val := cpars.mgcp_ep
1515 };
1516 mgcp_rsp.params[0] := mgcp_rsp_param;
Harald Welte812f7a42018-01-27 00:49:18 +01001517 MGCP.send(mgcp_rsp);
1518
1519 timer T := 30.0;
1520 T.start;
1521 alt {
Daniel Willmannafce8662018-07-06 23:11:32 +02001522 [] T.timeout {
1523 setverdict(fail, "Timeout waiting for channel release");
1524 mtc.stop;
1525 }
Harald Welte812f7a42018-01-27 00:49:18 +01001526 [] MNCC.receive { repeat; }
1527 [] GSUP.receive { repeat; }
1528 [] MGCP.receive(tr_DLCX(?)) -> value mgcp_cmd {
1529 MGCP.send(ts_DLCX_ACK2(mgcp_cmd.line.trans_id));
1530 f_create_mgcp_delete_ep(cpars.mgcp_ep);
1531 repeat;
1532 }
1533 [] MGCP.receive { repeat; }
Harald Welte5946b332018-03-18 23:32:21 +01001534 [] as_clear_cmd_compl_disc();
Neels Hofmeyrde76f052019-02-26 05:02:46 +01001535 [] as_optional_cc_rel(cpars);
Harald Welte812f7a42018-01-27 00:49:18 +01001536 }
1537}
1538testcase TC_mt_crcx_ran_reject() runs on MTC_CT {
1539 var BSC_ConnHdlr vc_conn;
1540 f_init();
1541
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001542 vc_conn := f_start_handler(refers(f_tc_mt_crcx_ran_reject), 31);
Harald Welte812f7a42018-01-27 00:49:18 +01001543 vc_conn.done;
1544}
1545
1546
1547/* Test MT Call T310 timer */
1548private function f_tc_mt_t310(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltead2952e2018-01-27 14:12:46 +01001549 f_init_handler(pars, 200.0);
Harald Welte812f7a42018-01-27 00:49:18 +01001550 var CallParameters cpars := valueof(t_CallParams('123456'H, 0));
1551 var MNCC_PDU mncc;
1552 var MgcpCommand mgcp_cmd;
1553
1554 f_mt_call_start(cpars);
1555
1556 /* MS->MSC: CALL CONFIRMED */
1557 BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_CC_CALL_CONF(cpars.transaction_id)));
1558 MNCC.receive(tr_MNCC_CALL_CONF_ind(cpars.mncc_callref));
1559
1560 MGCP.receive(tr_CRCX) -> value mgcp_cmd;
1561 cpars.mgcp_call_id := f_MgcpCmd_extract_call_id(mgcp_cmd);
1562 cpars.mgcp_ep := mgcp_cmd.line.ep;
1563 /* FIXME: Respond to CRCX */
1564
1565 /* old libosmocore T310 default timeout is 180s. so let's wait 190 */
1566 timer T := 190.0;
1567 T.start;
1568 alt {
Daniel Willmannafce8662018-07-06 23:11:32 +02001569 [] T.timeout {
1570 setverdict(fail, "Timeout waiting for T310");
1571 mtc.stop;
1572 }
Harald Welte812f7a42018-01-27 00:49:18 +01001573 [] MNCC.receive(tr_MNCC_DISC_ind(cpars.mncc_callref)) {
1574 MNCC.send(ts_MNCC_REL_req(cpars.mncc_callref, valueof(ts_MNCC_cause(23))));
1575 }
1576 }
1577 BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_CC_DISC(cpars.transaction_id)));
1578 BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_CC_RELEASE(cpars.transaction_id)));
1579 /* FIXME: We're sending this with TIflag 0: allocated by sender, which is wrong */
1580 BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_CC_REL_COMPL(cpars.transaction_id)));
1581
1582 alt {
Harald Welte812f7a42018-01-27 00:49:18 +01001583 [] MGCP.receive(tr_DLCX(?)) -> value mgcp_cmd {
1584 MGCP.send(ts_DLCX_ACK2(mgcp_cmd.line.trans_id));
1585 f_create_mgcp_delete_ep(cpars.mgcp_ep);
1586 repeat;
1587 }
Harald Welte5946b332018-03-18 23:32:21 +01001588 [] as_clear_cmd_compl_disc();
Harald Welte812f7a42018-01-27 00:49:18 +01001589 }
1590}
1591testcase TC_mt_t310() runs on MTC_CT {
1592 var BSC_ConnHdlr vc_conn;
1593 f_init();
1594
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001595 vc_conn := f_start_handler(refers(f_tc_mt_t310), 32);
Harald Welte812f7a42018-01-27 00:49:18 +01001596 vc_conn.done;
1597}
1598
Harald Welte167458a2018-01-27 15:58:16 +01001599/* Perform successful LU + MO call, then GSUP LocationCancel. Subscriber must be denied CM SERV */
1600private function f_tc_gsup_cancel(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
1601 f_init_handler(pars);
1602 var CallParameters cpars := valueof(t_CallParams('12345'H, 0));
1603 cpars.bss_rtp_port := 1110;
1604 cpars.mgcp_connection_id_bss := '22222'H;
1605 cpars.mgcp_connection_id_mss := '33333'H;
Daniel Willmann9b0235b2018-07-24 12:13:34 +02001606 cpars.mgcp_ep := "rtpbridge/1@mgw";
Harald Welte167458a2018-01-27 15:58:16 +01001607
1608 /* Location Update to make subscriber known */
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +01001609 f_perform_lu();
Harald Welte167458a2018-01-27 15:58:16 +01001610
1611 /* First MO call should succeed */
1612 f_mo_call(cpars);
1613
1614 /* Cancel the subscriber in the VLR */
1615 GSUP.send(ts_GSUP_CL_REQ(g_pars.imsi, OSMO_GSUP_CANCEL_TYPE_WITHDRAW));
1616 alt {
1617 [] GSUP.receive(tr_GSUP_CL_RES(g_pars.imsi)) { }
1618 [] GSUP.receive(tr_GSUP_CL_ERR(g_pars.imsi)) {
1619 setverdict(fail, "Received GSUP Location Cancel Error");
Daniel Willmannafce8662018-07-06 23:11:32 +02001620 mtc.stop;
Harald Welte167458a2018-01-27 15:58:16 +01001621 }
1622 }
1623
1624 /* Follow-up transactions should fail */
1625 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
1626 var PDU_ML3_MS_NW l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, mi));
Harald Weltedceacc72019-04-21 20:58:35 +02001627 f_cl3_or_initial_ue(l3_info);
Harald Welte167458a2018-01-27 15:58:16 +01001628 alt {
1629 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_CM_SERV_REJ)) { }
1630 [] BSSAP.receive {
1631 setverdict(fail, "Received unexpected BSSAP instead of CM SERV REJ");
Daniel Willmannafce8662018-07-06 23:11:32 +02001632 mtc.stop;
Harald Welte167458a2018-01-27 15:58:16 +01001633 }
1634 }
Neels Hofmeyr0f7429a2019-03-07 22:28:41 +01001635
1636 f_expect_clear();
Harald Welte167458a2018-01-27 15:58:16 +01001637 setverdict(pass);
1638}
1639testcase TC_gsup_cancel() runs on MTC_CT {
1640 var BSC_ConnHdlr vc_conn;
1641 f_init();
1642
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001643 vc_conn := f_start_handler(refers(f_tc_gsup_cancel), 33);
Harald Welte167458a2018-01-27 15:58:16 +01001644 vc_conn.done;
1645}
1646
Harald Welte9de84792018-01-28 01:06:35 +01001647/* A5/1 only permitted on network side, and MS capable to do it */
1648private function f_tc_lu_imsi_auth_tmsi_encr_1_13(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
1649 pars.net.expect_auth := true;
1650 pars.net.expect_ciph := true;
1651 pars.net.kc_support := '02'O; /* A5/1 only */
1652 f_init_handler(pars);
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +01001653 f_perform_lu();
Harald Welte9de84792018-01-28 01:06:35 +01001654}
1655testcase TC_lu_imsi_auth_tmsi_encr_1_13() runs on MTC_CT {
1656 var BSC_ConnHdlr vc_conn;
1657 f_init();
1658 f_vty_config(MSCVTY, "network", "authentication required");
1659 f_vty_config(MSCVTY, "network", "encryption a5 1");
1660
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001661 vc_conn := f_start_handler(refers(f_tc_lu_imsi_auth_tmsi_encr_1_13), 34);
Harald Welte9de84792018-01-28 01:06:35 +01001662 vc_conn.done;
1663}
1664
1665/* A5/3 only permitted on network side, and MS capable to do it */
1666private function f_tc_lu_imsi_auth_tmsi_encr_3_13(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
1667 pars.net.expect_auth := true;
1668 pars.net.expect_ciph := true;
1669 pars.net.kc_support := '08'O; /* A5/3 only */
1670 f_init_handler(pars);
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +01001671 f_perform_lu();
Harald Welte9de84792018-01-28 01:06:35 +01001672}
1673testcase TC_lu_imsi_auth_tmsi_encr_3_13() runs on MTC_CT {
1674 var BSC_ConnHdlr vc_conn;
1675 f_init();
1676 f_vty_config(MSCVTY, "network", "authentication required");
1677 f_vty_config(MSCVTY, "network", "encryption a5 3");
1678
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001679 vc_conn := f_start_handler(refers(f_tc_lu_imsi_auth_tmsi_encr_3_13), 35);
Harald Welte9de84792018-01-28 01:06:35 +01001680 vc_conn.done;
1681}
1682
1683/* A5/3 only permitted on network side, and MS with only A5/1 support */
1684private function f_tc_lu_imsi_auth_tmsi_encr_3_1(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
1685 pars.net.expect_auth := true;
1686 pars.net.expect_ciph := true;
1687 pars.net.kc_support := '08'O; /* A5/3 only */
1688 pars.cm2.classmarkInformationType2_oct5.a5_3 := '0'B;
1689 f_init_handler(pars, 15.0);
1690
1691 /* cannot use f_perform_lu() as we expect a reject */
1692 var PDU_ML3_MS_NW l3_lu := f_build_lu_imsi(g_pars.imsi);
1693 f_create_gsup_expect(hex2str(g_pars.imsi));
Harald Weltedceacc72019-04-21 20:58:35 +02001694 f_cl3_or_initial_ue(l3_lu);
Neels Hofmeyr29b8da02018-03-01 18:09:45 +01001695 if (pars.send_early_cm) {
1696 BSSAP.send(ts_BSSMAP_ClassmarkUpd(g_pars.cm2, g_pars.cm3));
1697 } else {
1698 pars.cm1.esind := '0'B;
1699 }
Harald Welte9de84792018-01-28 01:06:35 +01001700 f_mm_auth();
1701 alt {
Daniel Willmann52918e52018-09-20 14:39:09 +02001702 [] BSSAP.receive(tr_BSSMAP_ClassmarkReq) {
1703 BSSAP.send(ts_BSSMAP_ClassmarkUpd(g_pars.cm2, g_pars.cm3));
1704 repeat;
1705 }
Harald Welte5946b332018-03-18 23:32:21 +01001706 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Rej)) {
1707 f_expect_clear();
1708 }
Harald Welte9de84792018-01-28 01:06:35 +01001709 [] BSSAP.receive(tr_BSSMAP_CipherModeCmd(?,?)) {
1710 setverdict(fail, "CipherModeCommand despite no A5 intersection");
Daniel Willmannafce8662018-07-06 23:11:32 +02001711 mtc.stop;
Harald Welte9de84792018-01-28 01:06:35 +01001712 }
1713 [] BSSAP.receive {
Harald Welte458fd372018-03-21 11:26:23 +01001714 setverdict(fail, "Unknown/unexpected BSSAP received");
Daniel Willmannafce8662018-07-06 23:11:32 +02001715 mtc.stop;
Harald Welte9de84792018-01-28 01:06:35 +01001716 }
1717 }
1718 setverdict(pass);
1719}
1720testcase TC_lu_imsi_auth_tmsi_encr_3_1() runs on MTC_CT {
1721 var BSC_ConnHdlr vc_conn;
1722 f_init();
1723 f_vty_config(MSCVTY, "network", "authentication required");
1724 f_vty_config(MSCVTY, "network", "encryption a5 3");
1725
Neels Hofmeyr29b8da02018-03-01 18:09:45 +01001726 vc_conn := f_start_handler(refers(f_tc_lu_imsi_auth_tmsi_encr_3_1), 360);
1727 vc_conn.done;
1728}
1729testcase TC_lu_imsi_auth_tmsi_encr_3_1_no_cm() runs on MTC_CT {
1730 var BSC_ConnHdlrPars pars;
1731 var BSC_ConnHdlr vc_conn;
1732 f_init();
1733 f_vty_config(MSCVTY, "network", "authentication required");
1734 f_vty_config(MSCVTY, "network", "encryption a5 3");
1735
1736 pars := f_init_pars(361);
1737 pars.send_early_cm := false;
1738 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 +01001739 vc_conn.done;
1740}
Neels Hofmeyr1b3c6e32018-03-01 17:52:21 +01001741testcase TC_lu_imsi_auth_tmsi_encr_3_1_log_msc_debug() runs on MTC_CT {
1742 var BSC_ConnHdlr vc_conn;
1743 f_init();
1744 f_vty_config(MSCVTY, "network", "authentication required");
1745 f_vty_config(MSCVTY, "network", "encryption a5 3");
1746
1747 /* Make sure the MSC category is on DEBUG level to trigger the log
1748 * message that is reported in OS#2947 to trigger the segfault */
1749 f_vty_config(MSCVTY, "log stderr", "logging level msc debug");
1750
1751 vc_conn := f_start_handler(refers(f_tc_lu_imsi_auth_tmsi_encr_3_1), 362);
1752 vc_conn.done;
1753}
Harald Welte9de84792018-01-28 01:06:35 +01001754
1755/* A5/1 + A5/3 only permitted on network side, and MS with only A5/2 support */
1756private function f_tc_lu_imsi_auth_tmsi_encr_13_2(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
1757 pars.net.expect_auth := true;
1758 pars.net.expect_ciph := true;
1759 pars.net.kc_support := '0A'O; /* A5/1 + A5/3 */
1760 pars.cm1.a5_1 := '1'B;
1761 pars.cm2.a5_1 := '1'B;
1762 pars.cm2.classmarkInformationType2_oct5.a5_3 := '0'B;
1763 pars.cm2.classmarkInformationType2_oct5.a5_2 := '1'B;
1764 f_init_handler(pars, 15.0);
1765
1766 /* cannot use f_perform_lu() as we expect a reject */
1767 var PDU_ML3_MS_NW l3_lu := f_build_lu_imsi(g_pars.imsi);
1768 f_create_gsup_expect(hex2str(g_pars.imsi));
Harald Weltedceacc72019-04-21 20:58:35 +02001769 f_cl3_or_initial_ue(l3_lu);
Harald Welte9de84792018-01-28 01:06:35 +01001770 BSSAP.send(ts_BSSMAP_ClassmarkUpd(g_pars.cm2, g_pars.cm3));
1771 f_mm_auth();
1772 alt {
Harald Welte5946b332018-03-18 23:32:21 +01001773 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Rej)) {
1774 f_expect_clear();
1775 }
Harald Welte9de84792018-01-28 01:06:35 +01001776 [] BSSAP.receive(tr_BSSMAP_CipherModeCmd(?,?)) {
1777 setverdict(fail, "CipherModeCommand despite no A5 intersection");
Daniel Willmannafce8662018-07-06 23:11:32 +02001778 mtc.stop;
Harald Welte9de84792018-01-28 01:06:35 +01001779 }
1780 [] BSSAP.receive {
Harald Welte458fd372018-03-21 11:26:23 +01001781 setverdict(fail, "Unknown/unexpected BSSAP received");
Daniel Willmannafce8662018-07-06 23:11:32 +02001782 mtc.stop;
Harald Welte9de84792018-01-28 01:06:35 +01001783 }
1784 }
1785 setverdict(pass);
1786}
1787testcase TC_lu_imsi_auth_tmsi_encr_13_2() runs on MTC_CT {
1788 var BSC_ConnHdlr vc_conn;
1789 f_init();
1790 f_vty_config(MSCVTY, "network", "authentication required");
1791 f_vty_config(MSCVTY, "network", "encryption a5 1 3");
1792
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001793 vc_conn := f_start_handler(refers(f_tc_lu_imsi_auth_tmsi_encr_13_2), 37);
Harald Welte9de84792018-01-28 01:06:35 +01001794 vc_conn.done;
1795}
1796
1797/* A5/0 + A5/1 + A5/3 only permitted on network side, and MS with only A5/2 support */
1798private function f_tc_lu_imsi_auth_tmsi_encr_013_2(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
1799 pars.net.expect_auth := true;
1800 pars.net.expect_ciph := true;
1801 pars.net.kc_support := '0B'O; /* A5/1 + A5/3 */
1802 pars.cm1.a5_1 := '1'B;
1803 pars.cm2.a5_1 := '1'B;
1804 pars.cm2.classmarkInformationType2_oct5.a5_3 := '0'B;
1805 pars.cm2.classmarkInformationType2_oct5.a5_2 := '1'B;
1806 f_init_handler(pars, 15.0);
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +01001807 f_perform_lu();
Harald Welte9de84792018-01-28 01:06:35 +01001808}
1809testcase TC_lu_imsi_auth_tmsi_encr_013_2() runs on MTC_CT {
1810 var BSC_ConnHdlr vc_conn;
1811 f_init();
1812 f_vty_config(MSCVTY, "network", "authentication required");
1813 f_vty_config(MSCVTY, "network", "encryption a5 0 1 3");
1814
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001815 vc_conn := f_start_handler(refers(f_tc_lu_imsi_auth_tmsi_encr_013_2), 38);
Harald Welte9de84792018-01-28 01:06:35 +01001816 vc_conn.done;
1817}
1818
Harald Welte33ec09b2018-02-10 15:34:46 +01001819/* LU followed by MT call (including paging) */
1820private function f_tc_lu_and_mt_call(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
1821 f_init_handler(pars);
Stefan Sperling26d57be2018-11-12 17:03:26 +01001822 var CallParameters cpars := valueof(t_CallParams('12345'H, 0));
Harald Welte33ec09b2018-02-10 15:34:46 +01001823 cpars.bss_rtp_port := 1110;
1824 cpars.mgcp_connection_id_bss := '10004'H;
1825 cpars.mgcp_connection_id_mss := '10005'H;
1826
Philipp Maier4b2692d2018-03-14 16:37:48 +01001827 /* Note: This is an optional parameter. When the call-agent (MSC) does
1828 * supply a full endpoint name this setting will be overwritten. */
1829 cpars.mgcp_ep := "rtpbridge/1@mgw";
1830
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +01001831 f_perform_lu();
Harald Welte33ec09b2018-02-10 15:34:46 +01001832 f_mt_call(cpars);
1833}
1834testcase TC_lu_and_mt_call() runs on MTC_CT {
1835 var BSC_ConnHdlr vc_conn;
1836 f_init();
1837
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001838 vc_conn := f_start_handler(refers(f_tc_lu_and_mt_call), 39);
Harald Welte33ec09b2018-02-10 15:34:46 +01001839 vc_conn.done;
1840}
1841
Daniel Willmann8b084372018-02-04 13:35:26 +01001842/* Test MO Call SETUP with DTMF */
1843private function f_tc_mo_setup_dtmf_dup(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
1844 f_init_handler(pars);
1845 var CallParameters cpars := valueof(t_CallParams('12345'H, 0));
1846 cpars.bss_rtp_port := 1110;
1847 cpars.mgcp_connection_id_bss := '22222'H;
1848 cpars.mgcp_connection_id_mss := '33333'H;
1849
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +01001850 f_perform_lu();
Daniel Willmann8b084372018-02-04 13:35:26 +01001851 f_mo_seq_dtmf_dup(cpars);
1852}
1853testcase TC_mo_setup_and_dtmf_dup() runs on MTC_CT {
1854 var BSC_ConnHdlr vc_conn;
1855 f_init();
1856
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001857 vc_conn := f_start_handler(refers(f_tc_mo_setup_dtmf_dup), 39);
Daniel Willmann8b084372018-02-04 13:35:26 +01001858 vc_conn.done;
1859}
Harald Welte9de84792018-01-28 01:06:35 +01001860
Philipp Maier328d1662018-03-07 10:40:27 +01001861testcase TC_cr_before_reset() runs on MTC_CT {
1862 timer T := 4.0;
1863 var boolean reset_ack_seen := false;
1864 f_init_bssap_direct();
1865
Harald Welte3ca0ce12019-04-23 17:18:48 +02001866 f_ran_adapter_start(g_bssap[0]);
Daniel Willmann42d1d5b2018-08-07 15:18:41 +02001867
Daniel Willmanne8018962018-08-21 14:18:00 +02001868 f_sleep(3.0);
1869
Philipp Maier328d1662018-03-07 10:40:27 +01001870 /* Make a blind connection attemt, to trigger the deadlock condition */
Philipp Maier75932982018-03-27 14:52:35 +02001871 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 +01001872
1873 /* Send a BSSMAP reset */
Philipp Maier75932982018-03-27 14:52:35 +02001874 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 +01001875 T.start
1876 alt {
1877 [] BSSAP_DIRECT.receive(tr_BSSAP_UNITDATA_ind(?, ?, tr_BSSMAP_ResetAck)) {
1878 reset_ack_seen := true;
1879 repeat;
1880 }
1881
1882 /* Acknowledge MSC sided reset requests */
1883 [] BSSAP_DIRECT.receive(tr_BSSAP_UNITDATA_ind(?, ?, tr_BSSMAP_Reset)) {
Philipp Maier75932982018-03-27 14:52:35 +02001884 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 +01001885 repeat;
1886 }
1887
1888 /* Ignore all other messages (e.g CR from the connection request) */
1889 [] BSSAP_DIRECT.receive { repeat }
1890
1891 /* If we got no BSSMAP RESET ACK back, then the MSC entered the
1892 * deadlock situation. The MSC is then unable to respond to any
1893 * further BSSMAP RESET or any other sort of traffic. */
1894 [reset_ack_seen == true] T.timeout { setverdict(pass) }
1895 [reset_ack_seen == false] T.timeout {
1896 setverdict(fail, "no BSSMAP RESET ACK seen!");
Daniel Willmannafce8662018-07-06 23:11:32 +02001897 mtc.stop;
Philipp Maier328d1662018-03-07 10:40:27 +01001898 }
1899 }
1900}
Harald Welte9de84792018-01-28 01:06:35 +01001901
Philipp Maier94f3f1b2018-03-15 18:54:13 +01001902/* Test MO Call with no response to RAN-side CRCX or DTAP Release */
1903private function f_tc_mo_release_timeout(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
1904 f_init_handler(pars);
1905 var CallParameters cpars := valueof(t_CallParams('12345'H, 0));
1906 var MNCC_PDU mncc;
1907 var MgcpCommand mgcp_cmd;
1908
1909 f_perform_lu();
1910
Harald Welteb9e86fa2018-04-09 18:18:31 +02001911 f_establish_fully();
Philipp Maier94f3f1b2018-03-15 18:54:13 +01001912 f_create_mncc_expect(hex2str(cpars.called_party));
1913 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
1914
1915 BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_CC_SETUP(cpars.transaction_id, cpars.called_party)));
1916 MNCC.receive(tr_MNCC_SETUP_ind(?, tr_MNCC_number(hex2str(cpars.called_party)))) -> value mncc;
1917 cpars.mncc_callref := mncc.u.signal.callref;
1918 MNCC.send(ts_MNCC_CALL_PROC_req(cpars.mncc_callref, cpars.mncc_bearer_cap));
1919 BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_CC_CALL_PROC(cpars.transaction_id)));
1920
1921 /* Drop CRCX */
1922 MGCP.receive(tr_CRCX) -> value mgcp_cmd;
1923
Neels Hofmeyrde76f052019-02-26 05:02:46 +01001924 var default ccrel := activate(as_optional_cc_rel(cpars));
Philipp Maier94f3f1b2018-03-15 18:54:13 +01001925
1926 f_expect_clear(60.0);
Neels Hofmeyrde76f052019-02-26 05:02:46 +01001927
1928 deactivate(ccrel);
Philipp Maier94f3f1b2018-03-15 18:54:13 +01001929}
1930testcase TC_mo_release_timeout() runs on MTC_CT {
1931 var BSC_ConnHdlr vc_conn;
1932 f_init();
1933
1934 vc_conn := f_start_handler(refers(f_tc_mo_release_timeout), 40);
1935 vc_conn.done;
1936}
1937
Harald Welte12510c52018-01-26 22:26:24 +01001938
Philipp Maier2a98a732018-03-19 16:06:12 +01001939/* LU followed by MT call (including paging) */
1940private function f_tc_lu_and_mt_call_no_dlcx_resp(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
1941 f_init_handler(pars);
Stefan Sperling26d57be2018-11-12 17:03:26 +01001942 var CallParameters cpars := valueof(t_CallParams('12345'H, 0));
Philipp Maier2a98a732018-03-19 16:06:12 +01001943 cpars.bss_rtp_port := 1110;
1944 cpars.mgcp_connection_id_bss := '10004'H;
1945 cpars.mgcp_connection_id_mss := '10005'H;
1946
1947 /* Note: This is an optional parameter. When the call-agent (MSC) does
1948 * supply a full endpoint name this setting will be overwritten. */
1949 cpars.mgcp_ep := "rtpbridge/1@mgw";
1950
1951 /* Intentionally disable the CRCX response */
1952 cpars.mgw_drop_dlcx := true;
1953
1954 /* Perform location update and call */
1955 f_perform_lu();
1956 f_mt_call(cpars);
1957}
1958testcase TC_lu_and_mt_call_no_dlcx_resp() runs on MTC_CT {
1959 var BSC_ConnHdlr vc_conn;
1960 f_init();
1961
1962 /* Perform an almost normal looking locationupdate + mt-call, but do
1963 * not respond to the DLCX at the end of the call */
1964 vc_conn := f_start_handler(refers(f_tc_lu_and_mt_call_no_dlcx_resp), 41);
1965 vc_conn.done;
1966
1967 /* Wait a guard period until the MGCP layer in the MSC times out,
1968 * if the MSC is vulnerable to the use-after-free situation that is
1969 * fixed by I78f1b6a9149488a4ad3f120c1e190a83c07d4b89 then it should
1970 * segfault now */
1971 f_sleep(6.0);
1972
1973 /* Run the init procedures once more. If the MSC has crashed, this
1974 * this will fail */
1975 f_init();
1976}
Harald Welte45164da2018-01-24 12:51:27 +01001977
Philipp Maier75932982018-03-27 14:52:35 +02001978/* Two BSSMAP resets from two different BSCs */
1979testcase TC_reset_two() runs on MTC_CT {
1980 var BSC_ConnHdlr vc_conn;
1981 f_init(2);
1982 f_sleep(2.0);
1983 setverdict(pass);
1984}
1985
Harald Weltef640a012018-04-14 17:49:21 +02001986/***********************************************************************
1987 * SMS Testing
1988 ***********************************************************************/
1989
Harald Weltef45efeb2018-04-09 18:19:24 +02001990/* LU followed by MO SMS */
1991private function f_tc_lu_and_mo_sms(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
1992 var SmsParameters spars := valueof(t_SmsPars);
1993
1994 f_init_handler(pars);
1995
1996 /* Perform location update and call */
1997 f_perform_lu();
1998
1999 f_establish_fully(EST_TYPE_MO_SMS);
2000
2001 //spars.exp_rp_err := 96; /* invalid mandatory information */
2002 f_mo_sms(spars);
2003
2004 f_expect_clear();
2005}
2006testcase TC_lu_and_mo_sms() runs on MTC_CT {
2007 var BSC_ConnHdlr vc_conn;
2008 f_init();
2009 vc_conn := f_start_handler(refers(f_tc_lu_and_mo_sms), 42);
2010 vc_conn.done;
2011}
2012
2013private function f_vty_sms_send(charstring imsi, charstring msisdn, charstring text)
Neels Hofmeyr6aaeccf2019-03-06 15:32:26 +01002014runs on BSC_ConnHdlr {
Harald Weltef45efeb2018-04-09 18:19:24 +02002015 f_vty_transceive(MSCVTY, "subscriber imsi "&imsi&" sms sender msisdn "&msisdn&" send "&text);
2016}
2017
Neels Hofmeyr8256ed22019-03-06 15:34:01 +01002018/* Remove still pending SMS */
2019private function f_vty_sms_clear(charstring imsi)
2020runs on BSC_ConnHdlr {
2021 f_vty_transceive(MSCVTY, "subscriber imsi " & imsi & " sms delete-all");
2022 f_vty_transceive(MSCVTY, "sms-queue clear");
2023}
2024
Harald Weltef45efeb2018-04-09 18:19:24 +02002025/* LU followed by MT SMS */
2026private function f_tc_lu_and_mt_sms(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
2027 var SmsParameters spars := valueof(t_SmsPars);
2028 var OCT4 tmsi;
2029
2030 f_init_handler(pars);
2031
2032 /* Perform location update and call */
2033 f_perform_lu();
2034
2035 /* register an 'expect' for given IMSI (+TMSI) */
2036 if (isvalue(g_pars.tmsi)) {
2037 tmsi := g_pars.tmsi;
2038 } else {
2039 tmsi := 'FFFFFFFF'O;
2040 }
Harald Welte6811d102019-04-14 22:23:14 +02002041 f_ran_register_imsi(g_pars.imsi, tmsi);
Harald Weltef45efeb2018-04-09 18:19:24 +02002042
Neels Hofmeyr6aaeccf2019-03-06 15:32:26 +01002043 f_vty_sms_send(hex2str(pars.imsi), "2342", "Hello SMS");
Harald Weltef45efeb2018-04-09 18:19:24 +02002044
2045 /* MSC->BSC: expect PAGING from MSC */
Harald Weltee035e3e2019-04-21 17:32:05 +02002046 f_expect_paging();
2047
Harald Weltef45efeb2018-04-09 18:19:24 +02002048 /* Establish DTAP / BSSAP / SCCP connection */
2049 f_establish_fully(EST_TYPE_PAG_RESP);
2050
2051 spars.tp.ud := 'C8329BFD064D9B53'O;
2052 f_mt_sms(spars);
2053
2054 f_expect_clear();
2055}
2056testcase TC_lu_and_mt_sms() runs on MTC_CT {
2057 var BSC_ConnHdlrPars pars;
2058 var BSC_ConnHdlr vc_conn;
2059 f_init();
2060 pars := f_init_pars(43);
2061 vc_conn := f_start_handler_with_pars(refers(f_tc_lu_and_mt_sms), pars);
Harald Weltef45efeb2018-04-09 18:19:24 +02002062 vc_conn.done;
2063}
2064
Philipp Maier3983e702018-11-22 19:01:33 +01002065/* Paging for MT SMS but no response */
2066private function f_tc_lu_and_mt_sms_paging_and_nothing(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
2067 var SmsParameters spars := valueof(t_SmsPars);
2068 var OCT4 tmsi;
Philipp Maier3983e702018-11-22 19:01:33 +01002069 f_init_handler(pars, 150.0);
2070
2071 /* Perform location update */
2072 f_perform_lu();
2073
2074 /* register an 'expect' for given IMSI (+TMSI) */
2075 if (isvalue(g_pars.tmsi)) {
2076 tmsi := g_pars.tmsi;
2077 } else {
2078 tmsi := 'FFFFFFFF'O;
2079 }
Harald Welte6811d102019-04-14 22:23:14 +02002080 f_ran_register_imsi(g_pars.imsi, tmsi);
Philipp Maier3983e702018-11-22 19:01:33 +01002081
Neels Hofmeyr6aaeccf2019-03-06 15:32:26 +01002082 f_vty_sms_send(hex2str(pars.imsi), "2342", "Hello SMS");
2083
Neels Hofmeyr16237742019-03-06 15:34:01 +01002084 /* Expect the MSC to page exactly once */
2085 BSSAP.receive(tr_BSSMAP_Paging(g_pars.imsi)) { };
Philipp Maier3983e702018-11-22 19:01:33 +01002086
2087 /* Wait some time to make sure the MSC is not delivering any further
2088 * paging messages or anything else that could be unexpected. */
2089 timer T := 20.0;
2090 T.start
2091 alt {
2092 [] BSSAP.receive(tr_BSSMAP_Paging(g_pars.imsi))
2093 {
2094 setverdict(fail, "paging seems not to stop!");
2095 mtc.stop;
2096 }
2097 [] BSSAP.receive {
2098 setverdict(fail, "unexpected BSSAP message received");
2099 self.stop;
2100 }
2101 [] T.timeout {
2102 setverdict(pass);
2103 }
2104 }
2105
Neels Hofmeyr8256ed22019-03-06 15:34:01 +01002106 f_vty_sms_clear(hex2str(g_pars.imsi));
2107
Philipp Maier3983e702018-11-22 19:01:33 +01002108 setverdict(pass);
2109}
2110testcase TC_lu_and_mt_sms_paging_and_nothing() runs on MTC_CT {
2111 var BSC_ConnHdlrPars pars;
2112 var BSC_ConnHdlr vc_conn;
2113 f_init();
Philipp Maiera99ad262019-01-22 15:35:42 +01002114 pars := f_init_pars(1843);
Philipp Maier3983e702018-11-22 19:01:33 +01002115 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 +01002116 vc_conn.done;
2117}
2118
Harald Weltef640a012018-04-14 17:49:21 +02002119/* mobile originated SMS from MS/BTS/BSC side to SMPP */
2120private function f_tc_smpp_mo_sms(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
2121 var SmsParameters spars := valueof(t_SmsPars);
Harald Weltef45efeb2018-04-09 18:19:24 +02002122
Harald Weltef640a012018-04-14 17:49:21 +02002123 f_init_handler(pars);
Harald Weltef45efeb2018-04-09 18:19:24 +02002124
Harald Weltef640a012018-04-14 17:49:21 +02002125 /* Perform location update so IMSI is known + registered in MSC/VLR */
2126 f_perform_lu();
2127 f_establish_fully(EST_TYPE_MO_SMS);
2128
2129 f_mo_sms(spars);
2130
2131 var SMPP_PDU smpp;
2132 var template SMPP_PDU tr_smpp := tr_SMPP(c_SMPP_command_id_deliver_sm, ESME_ROK);
2133 tr_smpp.body.deliver_sm := {
2134 service_type := "CMT",
2135 source_addr_ton := network_specific,
2136 source_addr_npi := isdn,
2137 source_addr := hex2str(pars.msisdn),
2138 dest_addr_ton := f_sm_ton_from_gsm(spars.tp.da.tP_DA_NoPad.tP_TypeOfNumber),
2139 dest_addr_npi := f_sm_npi_from_gsm(spars.tp.da.tP_DA_NoPad.tP_NumberingPlanID),
2140 destination_addr := hex2str(spars.tp.da.tP_DA_NoPad.tP_DAValue),
2141 esm_class := '00000001'B,
2142 protocol_id := 0,
2143 priority_flag := 0,
2144 schedule_delivery_time := "",
2145 replace_if_present := 0,
2146 data_coding := '00000001'B,
2147 sm_default_msg_id := 0,
2148 sm_length := ?,
2149 short_message := spars.tp.ud,
2150 opt_pars := {
2151 {
2152 tag := user_message_reference,
2153 len := 2,
2154 opt_value := {
2155 int2_val := oct2int(spars.tp.msg_ref)
2156 }
2157 }
2158 }
2159 };
2160 alt {
2161 [] SMPP.receive(tr_smpp) -> value smpp {
2162 SMPP.send(ts_SMPP_DELIVER_SM_resp(ESME_ROK, smpp.header.seq_num));
2163 }
2164 [] SMPP.receive(tr_SMPP(c_SMPP_command_id_alert_notification, ESME_ROK)) { repeat; }
2165 }
2166
2167 f_expect_clear();
2168}
2169testcase TC_smpp_mo_sms() runs on MTC_CT {
2170 var BSC_ConnHdlr vc_conn;
2171 f_init();
2172 f_vty_config2(MSCVTY, { "smpp", "esme msc_tester"}, "default-route");
2173 vc_conn := f_start_handler(refers(f_tc_smpp_mo_sms), 44);
2174 vc_conn.done;
2175 f_vty_config2(MSCVTY, { "smpp", "esme msc_tester"}, "no default-route");
2176}
2177
Vadim Yanitskiy103d09f2018-11-12 02:50:23 +07002178/* Test MO-SMS from MS/BTS/BSC towards HLR (via GSUP) */
2179private function f_tc_gsup_mo_sms(charstring id, BSC_ConnHdlrPars pars)
2180runs on BSC_ConnHdlr {
2181 var SmsParameters spars := valueof(t_SmsPars);
2182 var GSUP_PDU gsup_msg_rx;
2183 var octetstring sm_tpdu;
2184
2185 f_init_handler(pars);
2186
2187 /* We need to inspect GSUP activity */
2188 f_create_gsup_expect(hex2str(g_pars.imsi));
2189
2190 /* Perform location update */
2191 f_perform_lu();
2192
2193 /* Send CM Service Request for SMS */
2194 f_establish_fully(EST_TYPE_MO_SMS);
2195
2196 /* Prepare expected SM-RP-UI (SM TPDU) */
2197 enc_TPDU_RP_DATA_MS_SGSN_fast(
2198 valueof(ts_SMS_SUBMIT(spars.tp.msg_ref,
2199 spars.tp.da, spars.tp.pid, spars.tp.dcs,
2200 spars.tp.udl, spars.tp.ud)),
2201 sm_tpdu);
2202
2203 var template GSUP_PDU mo_forwardSM := tr_GSUP_MO_FORWARD_SM_REQ(
2204 imsi := g_pars.imsi,
2205 sm_rp_mr := spars.rp.msg_ref,
2206 /* FIXME: extract SM-RP-DA from spars.rp.dest */
2207 sm_rp_da := tr_GSUP_SM_RP_DA_SMSC_ADDR(?),
2208 /* FIXME: MSISDN coding troubles */
2209 sm_rp_oa := tr_GSUP_SM_RP_OA_MSISDN(?),
2210 /* TODO: can we use decmatch here? */
2211 sm_rp_ui := sm_tpdu
2212 );
2213
2214 /* Submit an SMS on DTAP and expect MO-forwardSM-Req on GSUP */
2215 f_mo_sms_submit(spars);
2216 alt {
2217 [] GSUP.receive(mo_forwardSM) -> value gsup_msg_rx {
2218 log("RX MO-forwardSM-Req");
2219 log(gsup_msg_rx);
2220 setverdict(pass);
2221 }
2222 [] GSUP.receive {
2223 log("RX unexpected GSUP message");
2224 setverdict(fail);
2225 mtc.stop;
2226 }
2227 }
2228
2229 /* Trigger RP-ACK by sending MO-forwardSM-Res */
2230 GSUP.send(valueof(ts_GSUP_MO_FORWARD_SM_RES(
2231 imsi := g_pars.imsi,
2232 sm_rp_mr := spars.rp.msg_ref)));
2233 /* Expect RP-ACK on DTAP */
2234 f_mo_sms_wait_rp_ack(spars);
2235
2236 f_expect_clear();
2237}
2238testcase TC_gsup_mo_sms() runs on MTC_CT {
2239 var BSC_ConnHdlr vc_conn;
2240 f_init();
2241 f_vty_config(MSCVTY, "msc", "sms-over-gsup");
2242 vc_conn := f_start_handler(refers(f_tc_gsup_mo_sms), 88);
2243 vc_conn.done;
2244 f_vty_config(MSCVTY, "msc", "no sms-over-gsup");
2245}
2246
Vadim Yanitskiy9cc019a2018-11-15 02:06:07 +07002247/* Test MO-SMMA from MS/BTS/BSC towards HLR (via GSUP) */
2248private function f_tc_gsup_mo_smma(charstring id, BSC_ConnHdlrPars pars)
2249runs on BSC_ConnHdlr {
2250 var SmsParameters spars := valueof(t_SmsPars);
2251 var GSUP_PDU gsup_msg_rx;
2252
2253 f_init_handler(pars);
2254
2255 /* We need to inspect GSUP activity */
2256 f_create_gsup_expect(hex2str(g_pars.imsi));
2257
2258 /* Perform location update */
2259 f_perform_lu();
2260
2261 /* Send CM Service Request for SMS */
2262 f_establish_fully(EST_TYPE_MO_SMS);
2263
2264 var template GSUP_PDU mo_ReadyForSM := tr_GSUP_MO_READY_FOR_SM_REQ(
2265 imsi := g_pars.imsi,
2266 sm_rp_mr := spars.rp.msg_ref,
2267 sm_alert_rsn := GSUP_SM_ALERT_RSN_TYPE_MEM_AVAIL
2268 );
2269
2270 /* Submit an SMS on DTAP and expect MO-forwardSM-Req on GSUP */
2271 f_mo_smma(spars);
2272 alt {
2273 [] GSUP.receive(mo_ReadyForSM) -> value gsup_msg_rx {
2274 log("RX MO-ReadyForSM-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_READY_FOR_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_smma() 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_smma), 89);
2299 vc_conn.done;
2300 f_vty_config(MSCVTY, "msc", "no sms-over-gsup");
2301}
2302
Vadim Yanitskiyd7b37ab2018-11-24 03:40:20 +07002303/* Helper for sending MT SMS over GSUP */
2304private function f_gsup_forwardSM_req(SmsParameters spars, OCT1 mms := '00'O)
2305runs on BSC_ConnHdlr {
2306 GSUP.send(ts_GSUP_MT_FORWARD_SM_REQ(
2307 imsi := g_pars.imsi,
2308 /* NOTE: MSC should assign RP-MR itself */
2309 sm_rp_mr := 'FF'O,
2310 /* FIXME: extract SM-RP-DA from spars.rp.dest */
2311 /* TODO: fix encoding of ts_GSUP_SM_RP_DA_IMSI */
2312 sm_rp_da := valueof(ts_GSUP_SM_RP_DA_MSISDN(g_pars.msisdn)),
2313 sm_rp_oa := valueof(ts_GSUP_SM_RP_OA_SMSC_ADDR(g_pars.msisdn)),
2314 /* Encoded SMS TPDU (taken from Wireshark)
2315 * FIXME: we should encode spars somehow */
2316 sm_rp_ui := '00068021436500008111328130858200'O,
2317 sm_rp_mms := mms
2318 ));
2319}
2320
2321/* Test successful MT-SMS (RP-ACK) over GSUP */
2322private function f_tc_gsup_mt_sms_ack(charstring id, BSC_ConnHdlrPars pars)
2323runs on BSC_ConnHdlr {
2324 var SmsParameters spars := valueof(t_SmsPars);
2325
2326 f_init_handler(pars);
2327
2328 /* We need to inspect GSUP activity */
2329 f_create_gsup_expect(hex2str(g_pars.imsi));
2330
2331 /* Perform location update */
2332 f_perform_lu();
2333
2334 /* Register an 'expect' for given IMSI (+TMSI) */
2335 if (isvalue(g_pars.tmsi)) {
Harald Welte6811d102019-04-14 22:23:14 +02002336 f_ran_register_imsi(g_pars.imsi, g_pars.tmsi);
Vadim Yanitskiyd7b37ab2018-11-24 03:40:20 +07002337 } else {
Harald Welte6811d102019-04-14 22:23:14 +02002338 f_ran_register_imsi(g_pars.imsi, 'FFFFFFFF'O);
Vadim Yanitskiyd7b37ab2018-11-24 03:40:20 +07002339 }
2340
2341 var template GSUP_PDU mt_forwardSM_res := tr_GSUP_MT_FORWARD_SM_RES(
2342 imsi := g_pars.imsi,
2343 /* NOTE: MSC should assign RP-MR itself */
2344 sm_rp_mr := ?
2345 );
2346
2347 /* Submit a MT SMS on GSUP */
2348 f_gsup_forwardSM_req(spars);
2349
2350 /* Expect Paging Request and Establish DTAP / BSSAP / SCCP connection */
Harald Weltee035e3e2019-04-21 17:32:05 +02002351 f_expect_paging();
Vadim Yanitskiyd7b37ab2018-11-24 03:40:20 +07002352 f_establish_fully(EST_TYPE_PAG_RESP);
2353
2354 /* Wait for MT SMS on DTAP */
2355 f_mt_sms_expect(spars);
2356
2357 /* Send RP-ACK and expect MT-forwardSM-Res on GSUP */
2358 f_mt_sms_send_rp_ack(spars);
2359 alt {
2360 [] GSUP.receive(mt_forwardSM_res) {
2361 log("RX MT-forwardSM-Res (RP-ACK)");
2362 setverdict(pass);
2363 }
2364 [] GSUP.receive {
2365 log("RX unexpected GSUP message");
2366 setverdict(fail);
2367 mtc.stop;
2368 }
2369 }
2370
2371 f_expect_clear();
2372}
2373testcase TC_gsup_mt_sms_ack() runs on MTC_CT {
2374 var BSC_ConnHdlrPars pars;
2375 var BSC_ConnHdlr vc_conn;
2376 f_init();
2377 pars := f_init_pars(90);
2378 f_vty_config(MSCVTY, "msc", "sms-over-gsup");
2379 vc_conn := f_start_handler_with_pars(refers(f_tc_gsup_mt_sms_ack), pars);
2380 vc_conn.done;
2381 f_vty_config(MSCVTY, "msc", "no sms-over-gsup");
2382}
2383
2384/* Test rejected MT-SMS (RP-ERROR) over GSUP */
2385private function f_tc_gsup_mt_sms_err(charstring id, BSC_ConnHdlrPars pars)
2386runs on BSC_ConnHdlr {
2387 var SmsParameters spars := valueof(t_SmsPars);
2388 var OCT1 sm_rp_cause := '78'O; /* dummy RP-Cause value */
2389
2390 f_init_handler(pars);
2391
2392 /* We need to inspect GSUP activity */
2393 f_create_gsup_expect(hex2str(g_pars.imsi));
2394
2395 /* Perform location update */
2396 f_perform_lu();
2397
2398 /* Register an 'expect' for given IMSI (+TMSI) */
2399 if (isvalue(g_pars.tmsi)) {
Harald Welte6811d102019-04-14 22:23:14 +02002400 f_ran_register_imsi(g_pars.imsi, g_pars.tmsi);
Vadim Yanitskiyd7b37ab2018-11-24 03:40:20 +07002401 } else {
Harald Welte6811d102019-04-14 22:23:14 +02002402 f_ran_register_imsi(g_pars.imsi, 'FFFFFFFF'O);
Vadim Yanitskiyd7b37ab2018-11-24 03:40:20 +07002403 }
2404
2405 var template GSUP_PDU mt_forwardSM_err := tr_GSUP_MT_FORWARD_SM_ERR(
2406 imsi := g_pars.imsi,
2407 /* NOTE: MSC should assign RP-MR itself */
2408 sm_rp_mr := ?,
2409 sm_rp_cause := sm_rp_cause
2410 );
2411
2412 /* Submit a MT SMS on GSUP */
2413 f_gsup_forwardSM_req(spars);
2414
2415 /* Expect Paging Request and Establish DTAP / BSSAP / SCCP connection */
Harald Weltee035e3e2019-04-21 17:32:05 +02002416 f_expect_paging();
Vadim Yanitskiyd7b37ab2018-11-24 03:40:20 +07002417 f_establish_fully(EST_TYPE_PAG_RESP);
2418
2419 /* Wait for MT SMS on DTAP */
2420 f_mt_sms_expect(spars);
2421
2422 /* Send RP-ERROR and expect MT-forwardSM-Err on GSUP */
2423 f_mt_sms_send_rp_error(spars, oct2int(sm_rp_cause));
2424 alt {
2425 [] GSUP.receive(mt_forwardSM_err) {
2426 log("RX MT-forwardSM-Err (RP-ERROR)");
2427 setverdict(pass);
2428 mtc.stop;
2429 }
2430 [] GSUP.receive {
2431 log("RX unexpected GSUP message");
2432 setverdict(fail);
2433 mtc.stop;
2434 }
2435 }
2436
2437 f_expect_clear();
2438}
2439testcase TC_gsup_mt_sms_err() runs on MTC_CT {
2440 var BSC_ConnHdlrPars pars;
2441 var BSC_ConnHdlr vc_conn;
2442 f_init();
2443 pars := f_init_pars(91);
2444 f_vty_config(MSCVTY, "msc", "sms-over-gsup");
2445 vc_conn := f_start_handler_with_pars(refers(f_tc_gsup_mt_sms_err), pars);
2446 vc_conn.done;
2447 f_vty_config(MSCVTY, "msc", "no sms-over-gsup");
2448}
2449
Vadim Yanitskiybe1ff4b2019-01-18 15:04:13 +07002450/* Test SM-RP-MR assignment for MT-SMS over GSUP */
2451private function f_tc_gsup_mt_sms_rp_mr(charstring id, BSC_ConnHdlrPars pars)
2452runs on BSC_ConnHdlr {
2453 var SmsParameters spars1 := valueof(t_SmsPars); /* 1st SMS */
2454 var SmsParameters spars2 := valueof(t_SmsPars); /* 2nd SMS */
2455
2456 f_init_handler(pars);
2457
2458 /* We need to inspect GSUP activity */
2459 f_create_gsup_expect(hex2str(g_pars.imsi));
2460
2461 /* Perform location update */
2462 f_perform_lu();
2463
2464 /* Register an 'expect' for given IMSI (+TMSI) */
2465 if (isvalue(g_pars.tmsi)) {
Harald Welte6811d102019-04-14 22:23:14 +02002466 f_ran_register_imsi(g_pars.imsi, g_pars.tmsi);
Vadim Yanitskiybe1ff4b2019-01-18 15:04:13 +07002467 } else {
Harald Welte6811d102019-04-14 22:23:14 +02002468 f_ran_register_imsi(g_pars.imsi, 'FFFFFFFF'O);
Vadim Yanitskiybe1ff4b2019-01-18 15:04:13 +07002469 }
2470
2471 /* Submit the 1st MT SMS on GSUP */
2472 log("TX MT-forwardSM-Req for the 1st SMS");
2473 f_gsup_forwardSM_req(spars1);
2474
2475 /* Expect Paging Request and Establish DTAP / BSSAP / SCCP connection */
Harald Weltee035e3e2019-04-21 17:32:05 +02002476 f_expect_paging();
Vadim Yanitskiybe1ff4b2019-01-18 15:04:13 +07002477 f_establish_fully(EST_TYPE_PAG_RESP);
2478
2479 /* Wait for 1st MT SMS on DTAP */
2480 f_mt_sms_expect(spars1);
2481 log("RX the 1st SMS on DTAP, DTAP TID is ", spars1.tid,
2482 ", SM-RP-MR is ", spars1.rp.msg_ref);
2483
2484 /* Submit the 2nd MT SMS on GSUP */
2485 log("TX MT-forwardSM-Req for the 2nd SMS");
2486 f_gsup_forwardSM_req(spars2);
2487
2488 /* Wait for 2nd MT SMS on DTAP */
2489 f_mt_sms_expect(spars2);
2490 log("RX the 2nd SMS on DTAP, DTAP TID is ", spars2.tid,
2491 ", SM-RP-MR is ", spars2.rp.msg_ref);
2492
2493 /* Both transaction IDs shall be different */
2494 if (spars1.tid == spars2.tid) {
2495 log("Both DTAP transaction IDs shall be different");
2496 setverdict(fail);
2497 }
2498
2499 /* Both SM-RP-MR values shall be different */
2500 if (spars1.rp.msg_ref == spars2.rp.msg_ref) {
2501 log("Both SM-RP-MR values shall be different");
2502 setverdict(fail);
2503 }
2504
2505 /* Both SM-RP-MR values shall be assigned */
2506 if (spars1.rp.msg_ref == 'FF'O) {
2507 log("Unassigned SM-RP-MR value for the 1st SMS");
2508 setverdict(fail);
2509 }
2510 if (spars2.rp.msg_ref == 'FF'O) {
2511 log("Unassigned SM-RP-MR value for the 2nd SMS");
2512 setverdict(fail);
2513 }
2514
2515 /* Send the 1st RP-ACK and expect MT-forwardSM-Res on GSUP */
2516 f_mt_sms_send_rp_ack(spars1);
2517 alt {
2518 [] GSUP.receive(tr_GSUP_MT_FORWARD_SM_RES(
2519 imsi := g_pars.imsi,
2520 sm_rp_mr := spars1.rp.msg_ref
2521 )) {
2522 log("RX MT-forwardSM-Res (RP-ACK)");
2523 setverdict(pass);
2524 }
2525 [] GSUP.receive {
2526 log("RX unexpected GSUP message");
2527 setverdict(fail);
2528 mtc.stop;
2529 }
2530 }
2531
2532 /* Send the 2nd RP-ACK and expect MT-forwardSM-Res on GSUP */
2533 f_mt_sms_send_rp_ack(spars2);
2534 alt {
2535 [] GSUP.receive(tr_GSUP_MT_FORWARD_SM_RES(
2536 imsi := g_pars.imsi,
2537 sm_rp_mr := spars2.rp.msg_ref
2538 )) {
2539 log("RX MT-forwardSM-Res (RP-ACK)");
2540 setverdict(pass);
2541 }
2542 [] GSUP.receive {
2543 log("RX unexpected GSUP message");
2544 setverdict(fail);
2545 mtc.stop;
2546 }
2547 }
2548
2549 f_expect_clear();
2550}
2551testcase TC_gsup_mt_sms_rp_mr() runs on MTC_CT {
2552 var BSC_ConnHdlrPars pars;
2553 var BSC_ConnHdlr vc_conn;
2554 f_init();
2555 pars := f_init_pars(92);
2556 f_vty_config(MSCVTY, "msc", "sms-over-gsup");
2557 vc_conn := f_start_handler_with_pars(refers(f_tc_gsup_mt_sms_rp_mr), pars);
2558 vc_conn.done;
2559 f_vty_config(MSCVTY, "msc", "no sms-over-gsup");
2560}
2561
Vadim Yanitskiy5ac49cc2019-01-24 16:57:31 +07002562/* Test SM-RP-MR assignment for MT-SMS over GSUP */
2563private function f_tc_gsup_mo_mt_sms_rp_mr(charstring id, BSC_ConnHdlrPars pars)
2564runs on BSC_ConnHdlr {
2565 var SmsParameters spars_mo := valueof(t_SmsPars); /* MO SMMA */
2566 var SmsParameters spars_mt := valueof(t_SmsPars); /* MT SMS */
2567
2568 f_init_handler(pars);
2569
2570 /* We need to inspect GSUP activity */
2571 f_create_gsup_expect(hex2str(g_pars.imsi));
2572
2573 /* Perform location update */
2574 f_perform_lu();
2575
2576 /* Register an 'expect' for given IMSI (+TMSI) */
2577 if (isvalue(g_pars.tmsi)) {
Harald Welte6811d102019-04-14 22:23:14 +02002578 f_ran_register_imsi(g_pars.imsi, g_pars.tmsi);
Vadim Yanitskiy5ac49cc2019-01-24 16:57:31 +07002579 } else {
Harald Welte6811d102019-04-14 22:23:14 +02002580 f_ran_register_imsi(g_pars.imsi, 'FFFFFFFF'O);
Vadim Yanitskiy5ac49cc2019-01-24 16:57:31 +07002581 }
2582
2583 /* Send CM Service Request for MO SMMA */
2584 f_establish_fully(EST_TYPE_MO_SMS);
2585
2586 /* Submit MO SMMA on DTAP */
2587 log("Submit MO SMMA on DTAP, SM-RP-MR is '00'O");
2588 spars_mo.rp.msg_ref := '00'O;
2589 f_mo_smma(spars_mo);
2590
2591 /* Expect MO-forwardSM-Req for MO SMMA on GSUP */
2592 alt {
2593 [] GSUP.receive(tr_GSUP_MO_READY_FOR_SM_REQ(
2594 imsi := g_pars.imsi,
2595 sm_rp_mr := spars_mo.rp.msg_ref,
2596 sm_alert_rsn := GSUP_SM_ALERT_RSN_TYPE_MEM_AVAIL
2597 )) {
2598 log("RX MO-ReadyForSM-Req, SM-RP-MR is '00'O");
2599 setverdict(pass);
2600 }
2601 [] GSUP.receive {
2602 log("RX unexpected GSUP message");
2603 setverdict(fail);
2604 mtc.stop;
2605 }
2606 }
2607
2608 /* Submit MT SMS on GSUP */
2609 log("TX MT-forwardSM-Req for the MT SMS");
2610 f_gsup_forwardSM_req(spars_mt);
2611
2612 /* Wait for MT SMS on DTAP */
2613 f_mt_sms_expect(spars_mt);
2614 log("RX MT SMS on DTAP, DTAP TID is ", spars_mt.tid,
2615 ", SM-RP-MR is ", spars_mt.rp.msg_ref);
2616
2617 /* Both SM-RP-MR values shall be different */
2618 if (spars_mo.rp.msg_ref == spars_mt.rp.msg_ref) {
2619 log("Both SM-RP-MR values shall be different");
2620 setverdict(fail);
2621 }
2622
2623 /* SM-RP-MR value for MT SMS shall be assigned */
2624 if (spars_mt.rp.msg_ref == 'FF'O) {
2625 log("Unassigned SM-RP-MR value for the MT SMS");
2626 setverdict(fail);
2627 }
2628
2629 /* Trigger RP-ACK for MO SMMA by sending MO-forwardSM-Res */
2630 GSUP.send(valueof(ts_GSUP_MO_READY_FOR_SM_RES(
2631 imsi := g_pars.imsi,
2632 sm_rp_mr := spars_mo.rp.msg_ref)));
2633 /* Expect RP-ACK for MO SMMA on DTAP */
2634 f_mo_sms_wait_rp_ack(spars_mo);
2635
2636 /* Send RP-ACK for MT SMS and expect MT-forwardSM-Res on GSUP */
2637 f_mt_sms_send_rp_ack(spars_mt);
2638 alt {
2639 [] GSUP.receive(tr_GSUP_MT_FORWARD_SM_RES(
2640 imsi := g_pars.imsi,
2641 sm_rp_mr := spars_mt.rp.msg_ref
2642 )) {
2643 log("RX MT-forwardSM-Res (RP-ACK)");
2644 setverdict(pass);
2645 }
2646 [] GSUP.receive {
2647 log("RX unexpected GSUP message");
2648 setverdict(fail);
2649 mtc.stop;
2650 }
2651 }
2652
2653 f_expect_clear();
2654}
2655testcase TC_gsup_mo_mt_sms_rp_mr() runs on MTC_CT {
2656 var BSC_ConnHdlrPars pars;
2657 var BSC_ConnHdlr vc_conn;
2658 f_init();
2659 pars := f_init_pars(93);
2660 f_vty_config(MSCVTY, "msc", "sms-over-gsup");
2661 vc_conn := f_start_handler_with_pars(refers(f_tc_gsup_mo_mt_sms_rp_mr), pars);
2662 vc_conn.done;
2663 f_vty_config(MSCVTY, "msc", "no sms-over-gsup");
2664}
2665
Vadim Yanitskiy1cd11a02018-12-03 02:43:35 +07002666/* Test multi-part MT-SMS over GSUP */
2667private function f_tc_gsup_mt_multi_part_sms(charstring id, BSC_ConnHdlrPars pars)
2668runs on BSC_ConnHdlr {
2669 var SmsParameters spars := valueof(t_SmsPars);
2670
2671 f_init_handler(pars);
2672
2673 /* We need to inspect GSUP activity */
2674 f_create_gsup_expect(hex2str(g_pars.imsi));
2675
2676 /* Perform location update */
2677 f_perform_lu();
2678
2679 /* Register an 'expect' for given IMSI (+TMSI) */
2680 if (isvalue(g_pars.tmsi)) {
Harald Welte6811d102019-04-14 22:23:14 +02002681 f_ran_register_imsi(g_pars.imsi, g_pars.tmsi);
Vadim Yanitskiy1cd11a02018-12-03 02:43:35 +07002682 } else {
Harald Welte6811d102019-04-14 22:23:14 +02002683 f_ran_register_imsi(g_pars.imsi, 'FFFFFFFF'O);
Vadim Yanitskiy1cd11a02018-12-03 02:43:35 +07002684 }
2685
2686 var template GSUP_PDU mt_forwardSM_res := tr_GSUP_MT_FORWARD_SM_RES(
2687 imsi := g_pars.imsi,
2688 /* NOTE: MSC should assign RP-MR itself */
2689 sm_rp_mr := ?
2690 );
2691
2692 /* Send 4 messages (NOTE: SM-RP-UI remains unchanged) */
2693 for (var integer i := 3; i >= 0; i := i-1) {
2694 /* Submit a MT SMS on GSUP (MMS is decremented) */
2695 f_gsup_forwardSM_req(spars, int2oct(i, 1));
2696
2697 /* Expect Paging Request and Establish connection */
2698 if (i == 3) { /* ... only once! */
2699 BSSAP.receive(tr_BSSMAP_Paging(g_pars.imsi));
2700 f_establish_fully(EST_TYPE_PAG_RESP);
2701 }
2702
2703 /* Wait for MT SMS on DTAP */
2704 f_mt_sms_expect(spars);
2705
2706 /* Send RP-ACK and expect MT-forwardSM-Res on GSUP */
2707 f_mt_sms_send_rp_ack(spars);
2708 alt {
2709 [] GSUP.receive(mt_forwardSM_res) {
2710 log("RX MT-forwardSM-Res (RP-ACK)");
2711 setverdict(pass);
2712 }
2713 [] GSUP.receive {
2714 log("RX unexpected GSUP message");
2715 setverdict(fail);
2716 mtc.stop;
2717 }
2718 }
2719
2720 /* Keep some 'distance' between transmissions */
2721 f_sleep(1.5);
2722 }
2723
2724 f_expect_clear();
2725}
2726testcase TC_gsup_mt_multi_part_sms() runs on MTC_CT {
2727 var BSC_ConnHdlrPars pars;
2728 var BSC_ConnHdlr vc_conn;
2729 f_init();
2730 pars := f_init_pars(91);
2731 f_vty_config(MSCVTY, "msc", "sms-over-gsup");
2732 vc_conn := f_start_handler_with_pars(refers(f_tc_gsup_mt_multi_part_sms), pars);
2733 vc_conn.done;
2734 f_vty_config(MSCVTY, "msc", "no sms-over-gsup");
2735}
2736
Harald Weltef640a012018-04-14 17:49:21 +02002737/* convert GSM L3 TON to SMPP_TON enum */
2738function f_sm_ton_from_gsm(BIT3 ton) return SMPP_TON {
2739 select (ton) {
2740 case ('000'B) { return unknown; }
2741 case ('001'B) { return international; }
2742 case ('010'B) { return national; }
2743 case ('011'B) { return network_specific; }
2744 case ('100'B) { return subscriber_number; }
2745 case ('101'B) { return alphanumeric; }
2746 case ('110'B) { return abbreviated; }
2747 }
2748 setverdict(fail, "Unknown TON ", ton);
Daniel Willmannafce8662018-07-06 23:11:32 +02002749 mtc.stop;
Harald Weltef640a012018-04-14 17:49:21 +02002750}
2751/* convert GSM L3 NPI to SMPP_NPI enum */
2752function f_sm_npi_from_gsm(BIT4 npi) return SMPP_NPI {
2753 select (npi) {
2754 case ('0000'B) { return unknown; }
2755 case ('0001'B) { return isdn; }
2756 case ('0011'B) { return data; }
2757 case ('0100'B) { return telex; }
2758 case ('0110'B) { return land_mobile; }
2759 case ('1000'B) { return national; }
2760 case ('1001'B) { return private_; }
2761 case ('1010'B) { return ermes; }
2762 }
2763 setverdict(fail, "Unknown NPI ", npi);
Daniel Willmannafce8662018-07-06 23:11:32 +02002764 mtc.stop;
Harald Weltef640a012018-04-14 17:49:21 +02002765}
2766
2767/* build a SMPP_SM from SmsParameters */
2768function f_mt_sm_from_spars(SmsParameters spars)
2769runs on BSC_ConnHdlr return SMPP_SM {
2770 var SMPP_SM sm := {
2771 service_type := "CMT",
2772 source_addr_ton := f_sm_ton_from_gsm(spars.tp.da.tP_DA_NoPad.tP_TypeOfNumber),
2773 source_addr_npi := f_sm_npi_from_gsm(spars.tp.da.tP_DA_NoPad.tP_NumberingPlanID),
2774 source_addr := hex2str(spars.tp.da.tP_DA_NoPad.tP_DAValue),
2775 dest_addr_ton := international,
2776 dest_addr_npi := isdn,
2777 destination_addr := hex2str(g_pars.msisdn),
2778 esm_class := '00000001'B,
2779 protocol_id := 0,
2780 priority_flag := 0,
2781 schedule_delivery_time := "",
2782 validity_period := "",
2783 registered_delivery := '00000000'B,
2784 replace_if_present := 0,
2785 data_coding := '00000001'B,
2786 sm_default_msg_id := 0,
2787 sm_length := spars.tp.udl,
2788 short_message := spars.tp.ud,
2789 opt_pars := {}
2790 };
2791 return sm;
2792}
2793
2794/* helper function to encode SMS from 'spars', send it via SMPP to MSC; receive it on MS side */
2795private function f_smpp_mt_sms(SmsParameters spars, boolean trans_mode) runs on BSC_ConnHdlr {
2796 var SMPP_SM sm := f_mt_sm_from_spars(spars);
2797 if (trans_mode) {
2798 sm.esm_class := '00000010'B;
2799 }
2800
2801 /* actually cause MSC to send a SMS via SUBMIT-SM from SMPP side */
2802 SMPP.send(ts_SMPP_SUBMIT_SM(sm));
2803 if (not match(sm.esm_class, tr_ESM_CLASS_TRANSACTION)) {
2804 /* if we're not in SMPP transaction mode, we expect the SMPP-level ACK
2805 * before we expect the SMS delivery on the BSC/radio side */
2806 SMPP.receive(tr_SMPP(c_SMPP_command_id_submit_sm_resp, ESME_ROK));
2807 }
2808
2809 /* MSC->BSC: expect PAGING from MSC */
Harald Weltee035e3e2019-04-21 17:32:05 +02002810 f_expect_paging();
Harald Weltef640a012018-04-14 17:49:21 +02002811 /* Establish DTAP / BSSAP / SCCP connection */
2812 f_establish_fully(EST_TYPE_PAG_RESP);
2813 SMPP.receive(tr_SMPP(c_SMPP_command_id_alert_notification, ESME_ROK));
2814
2815 f_mt_sms(spars);
2816
2817 if (match(sm.esm_class, tr_ESM_CLASS_TRANSACTION)) {
2818 SMPP.receive(tr_SMPP(c_SMPP_command_id_submit_sm_resp, ESME_ROK));
2819 }
2820 f_expect_clear();
2821}
2822
2823/* mobile terminated SMS, from SMPP to BSC/BTS/MS */
2824private function f_tc_smpp_mt_sms(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
2825 f_init_handler(pars);
2826
2827 /* Perform location update so IMSI is known + registered in MSC/VLR */
2828 f_perform_lu();
2829 SMPP.receive(tr_SMPP(c_SMPP_command_id_alert_notification, ESME_ROK));
2830
2831 /* register an 'expect' for given IMSI (+TMSI) */
2832 var OCT4 tmsi;
2833 if (isvalue(g_pars.tmsi)) {
2834 tmsi := g_pars.tmsi;
2835 } else {
2836 tmsi := 'FFFFFFFF'O;
2837 }
Harald Welte6811d102019-04-14 22:23:14 +02002838 f_ran_register_imsi(g_pars.imsi, tmsi);
Harald Weltef640a012018-04-14 17:49:21 +02002839
2840 var SmsParameters spars := valueof(t_SmsPars);
2841 /* TODO: test with more intelligent user data; test different coding schemes */
2842 spars.tp.ud := '00'O;
2843 spars.tp.udl := 1;
2844
2845 /* first test the non-transaction store+forward mode */
2846 f_smpp_mt_sms(spars, false);
2847
2848 /* then test the transaction mode */
2849 f_smpp_mt_sms(spars, true);
2850}
2851testcase TC_smpp_mt_sms() runs on MTC_CT {
2852 var BSC_ConnHdlr vc_conn;
2853 f_init();
2854 vc_conn := f_start_handler(refers(f_tc_smpp_mt_sms), 45);
2855 vc_conn.done;
2856}
2857
Vadim Yanitskiy7d1f9182018-05-28 16:21:42 +07002858/***********************************************************************
2859 * USSD Testing
2860 ***********************************************************************/
2861
Vadim Yanitskiyce8cc372018-06-21 01:46:33 +07002862private altstep as_unexp_gsup_or_bssap_msg()
2863runs on BSC_ConnHdlr {
2864 [] GSUP.receive {
2865 setverdict(fail, "Unknown/unexpected GSUP received");
2866 self.stop;
2867 }
2868 [] BSSAP.receive {
2869 setverdict(fail, "Unknown/unexpected BSSAP message received");
2870 self.stop;
2871 }
2872}
2873
2874private function f_expect_gsup_msg(template GSUP_PDU msg)
2875runs on BSC_ConnHdlr return GSUP_PDU {
2876 var GSUP_PDU gsup_msg_complete;
2877
2878 alt {
2879 [] GSUP.receive(msg) -> value gsup_msg_complete {
2880 setverdict(pass);
2881 }
2882 /* We don't expect anything else */
2883 [] as_unexp_gsup_or_bssap_msg();
2884 }
2885
2886 return gsup_msg_complete;
2887}
2888
2889private function f_expect_mt_dtap_msg(template PDU_ML3_NW_MS msg)
2890runs on BSC_ConnHdlr return PDU_ML3_NW_MS {
2891 var PDU_DTAP_MT bssap_msg_complete;
2892
2893 alt {
2894 [] BSSAP.receive(tr_PDU_DTAP_MT(msg)) -> value bssap_msg_complete {
2895 setverdict(pass);
2896 }
2897 /* We don't expect anything else */
2898 [] as_unexp_gsup_or_bssap_msg();
2899 }
2900
2901 return bssap_msg_complete.dtap;
2902}
2903
Vadim Yanitskiy2a978b92018-06-19 17:51:20 +07002904/* LU followed by MO USSD request */
2905private function f_tc_lu_and_mo_ussd_single_request(charstring id, BSC_ConnHdlrPars pars)
Vadim Yanitskiy7d1f9182018-05-28 16:21:42 +07002906runs on BSC_ConnHdlr {
2907 f_init_handler(pars);
2908
2909 /* Perform location update */
2910 f_perform_lu();
2911
2912 /* Send CM Service Request for SS/USSD */
2913 f_establish_fully(EST_TYPE_SS_ACT);
2914
Vadim Yanitskiy747689e2018-06-19 00:14:28 +07002915 /* We need to inspect GSUP activity */
2916 f_create_gsup_expect(hex2str(g_pars.imsi));
2917
2918 var template OCTN facility_req := f_USSD_FACILITY_IE_INVOKE(
2919 invoke_id := 5, /* Phone may not start from 0 or 1 */
2920 op_code := SS_OP_CODE_PROCESS_USS_REQ,
2921 ussd_string := "*#100#"
2922 );
2923
2924 var template OCTN facility_rsp := f_USSD_FACILITY_IE_RETURN_RESULT(
2925 invoke_id := 5, /* InvokeID shall be the same for both REQ and RSP */
2926 op_code := SS_OP_CODE_PROCESS_USS_REQ,
2927 ussd_string := "Your extension is " & hex2str(g_pars.msisdn) & "\r"
2928 )
2929
Vadim Yanitskiy7d1f9182018-05-28 16:21:42 +07002930 /* Compose a new SS/REGISTER message with request */
2931 var template (value) PDU_ML3_MS_NW ussd_req := ts_ML3_MO_SS_REGISTER(
2932 tid := 1, /* We just need a single transaction */
2933 ti_flag := c_TIF_ORIG, /* Sent from the side that originates the TI */
Vadim Yanitskiy747689e2018-06-19 00:14:28 +07002934 facility := valueof(facility_req)
Vadim Yanitskiy7d1f9182018-05-28 16:21:42 +07002935 );
2936
2937 /* Compose SS/RELEASE_COMPLETE template with expected response */
2938 var template PDU_ML3_NW_MS ussd_rsp := tr_ML3_MT_SS_RELEASE_COMPLETE(
2939 tid := 1, /* Response should arrive within the same transaction */
2940 ti_flag := c_TIF_REPL, /* Sent to the side that originates the TI */
Vadim Yanitskiy747689e2018-06-19 00:14:28 +07002941 facility := valueof(facility_rsp)
Vadim Yanitskiy7d1f9182018-05-28 16:21:42 +07002942 );
2943
Vadim Yanitskiy747689e2018-06-19 00:14:28 +07002944 /* Compose expected MSC -> HLR message */
2945 var template GSUP_PDU gsup_req := tr_GSUP_PROC_SS_REQ(
2946 imsi := g_pars.imsi,
2947 state := OSMO_GSUP_SESSION_STATE_BEGIN,
2948 ss := valueof(facility_req)
2949 );
2950
2951 /* To be used for sending response with correct session ID */
2952 var GSUP_PDU gsup_req_complete;
2953
2954 /* Request own number */
Vadim Yanitskiy7d1f9182018-05-28 16:21:42 +07002955 BSSAP.send(ts_PDU_DTAP_MO(ussd_req));
Vadim Yanitskiy747689e2018-06-19 00:14:28 +07002956 /* Expect GSUP message containing the SS payload */
2957 gsup_req_complete := f_expect_gsup_msg(gsup_req);
2958
2959 /* Compose the response from HLR using received session ID */
2960 var template GSUP_PDU gsup_rsp := ts_GSUP_PROC_SS_REQ(
2961 imsi := g_pars.imsi,
2962 sid := gsup_req_complete.ies[1].val.session_id,
2963 state := OSMO_GSUP_SESSION_STATE_END,
2964 ss := valueof(facility_rsp)
2965 );
2966
2967 /* Finally, HLR terminates the session */
2968 GSUP.send(gsup_rsp);
2969 /* Expect RELEASE_COMPLETE message with the response */
2970 f_expect_mt_dtap_msg(ussd_rsp);
Vadim Yanitskiy7d1f9182018-05-28 16:21:42 +07002971
2972 f_expect_clear();
2973}
Vadim Yanitskiy2a978b92018-06-19 17:51:20 +07002974testcase TC_lu_and_mo_ussd_single_request() runs on MTC_CT {
Vadim Yanitskiy7d1f9182018-05-28 16:21:42 +07002975 var BSC_ConnHdlr vc_conn;
2976 f_init();
Vadim Yanitskiy2a978b92018-06-19 17:51:20 +07002977 vc_conn := f_start_handler(refers(f_tc_lu_and_mo_ussd_single_request), 46);
Vadim Yanitskiy7d1f9182018-05-28 16:21:42 +07002978 vc_conn.done;
2979}
2980
Vadim Yanitskiy13e4a272018-06-19 18:24:31 +07002981/* LU followed by MT USSD notification */
2982private function f_tc_lu_and_mt_ussd_notification(charstring id, BSC_ConnHdlrPars pars)
2983runs on BSC_ConnHdlr {
2984 f_init_handler(pars);
2985
2986 /* Perform location update */
2987 f_perform_lu();
2988
Harald Welte6811d102019-04-14 22:23:14 +02002989 f_ran_register_imsi(g_pars.imsi, g_pars.tmsi);
Vadim Yanitskiy13e4a272018-06-19 18:24:31 +07002990
2991 /* We need to inspect GSUP activity */
2992 f_create_gsup_expect(hex2str(g_pars.imsi));
2993
2994 /* Facility IE with network-originated USSD notification */
2995 var template OCTN facility_req := f_USSD_FACILITY_IE_INVOKE(
2996 op_code := SS_OP_CODE_USS_NOTIFY,
2997 ussd_string := "Mahlzeit!"
2998 );
2999
3000 /* Facility IE with acknowledgment to the USSD notification */
3001 var template OCTN facility_rsp := enc_SS_FacilityInformation(
3002 /* In case of USSD notification, Return Result is empty */
3003 valueof(ts_SS_USSD_FACILITY_RETURN_RESULT_EMPTY())
3004 );
3005
3006 /* Compose a new MT SS/REGISTER message with USSD notification */
3007 var template PDU_ML3_NW_MS ussd_ntf := tr_ML3_MT_SS_REGISTER(
3008 tid := 0, /* FIXME: most likely, it should be 0 */
3009 ti_flag := c_TIF_ORIG, /* Sent from the side that originates the TI */
3010 facility := valueof(facility_req)
3011 );
3012
3013 /* Compose HLR -> MSC GSUP message */
3014 var template (value) GSUP_PDU gsup_req := ts_GSUP_PROC_SS_REQ(
3015 imsi := g_pars.imsi,
3016 sid := '20000101'O,
3017 state := OSMO_GSUP_SESSION_STATE_BEGIN,
3018 ss := valueof(facility_req)
3019 );
3020
3021 /* Send it to MSC and expect Paging Request */
3022 GSUP.send(gsup_req);
3023 alt {
3024 [] BSSAP.receive(tr_BSSMAP_Paging(g_pars.imsi)) {
3025 setverdict(pass);
3026 }
3027 /* We don't expect anything else */
3028 [] as_unexp_gsup_or_bssap_msg();
3029 }
3030
3031 /* Send Paging Response and expect USSD notification */
3032 f_establish_fully(EST_TYPE_PAG_RESP);
3033 /* Expect MT REGISTER message with USSD notification */
3034 f_expect_mt_dtap_msg(ussd_ntf);
3035
3036 /* Compose a new MO SS/FACILITY message with empty response */
3037 var template (value) PDU_ML3_MS_NW ussd_rsp := ts_ML3_MO_SS_FACILITY(
3038 tid := 0, /* FIXME: it shall match the request tid */
3039 ti_flag := c_TIF_REPL, /* Sent to the side that originates the TI */
3040 facility := valueof(facility_rsp)
3041 );
3042
3043 /* Compose expected MSC -> HLR GSUP message */
3044 var template GSUP_PDU gsup_rsp := tr_GSUP_PROC_SS_REQ(
3045 imsi := g_pars.imsi,
3046 sid := '20000101'O,
3047 state := OSMO_GSUP_SESSION_STATE_CONTINUE,
3048 ss := valueof(facility_rsp)
3049 );
3050
3051 /* MS sends response to the notification */
3052 BSSAP.send(ts_PDU_DTAP_MO(ussd_rsp));
3053 /* Expect GSUP message containing the SS payload */
3054 f_expect_gsup_msg(gsup_rsp);
3055
3056 /* Compose expected MT SS/RELEASE COMPLETE message */
3057 var template PDU_ML3_NW_MS ussd_term := tr_ML3_MT_SS_RELEASE_COMPLETE(
3058 tid := 0, /* FIXME: it shall match the request tid */
3059 ti_flag := c_TIF_ORIG, /* Sent from the side that originates the TI */
3060 facility := omit
3061 );
3062
3063 /* Compose MSC -> HLR GSUP message */
3064 var template GSUP_PDU gsup_term := ts_GSUP_PROC_SS_REQ(
3065 imsi := g_pars.imsi,
3066 sid := '20000101'O,
3067 state := OSMO_GSUP_SESSION_STATE_END
3068 );
3069
3070 /* Finally, HLR terminates the session */
3071 GSUP.send(gsup_term)
3072 /* Expect MT RELEASE COMPLETE without Facility IE */
3073 f_expect_mt_dtap_msg(ussd_term);
3074
3075 f_expect_clear();
3076}
3077testcase TC_lu_and_mt_ussd_notification() runs on MTC_CT {
3078 var BSC_ConnHdlr vc_conn;
3079 f_init();
3080 vc_conn := f_start_handler(refers(f_tc_lu_and_mt_ussd_notification), 47);
3081 vc_conn.done;
3082}
3083
Vadim Yanitskiy2a978b92018-06-19 17:51:20 +07003084/* LU followed by MT call and MO USSD request during this call */
3085private function f_tc_lu_and_mo_ussd_during_mt_call(charstring id, BSC_ConnHdlrPars pars)
Vadim Yanitskiy0aaf48d2018-06-06 07:02:47 +07003086runs on BSC_ConnHdlr {
3087 f_init_handler(pars);
3088
3089 /* Call parameters taken from f_tc_lu_and_mt_call */
3090 var CallParameters cpars := valueof(t_CallParams('123456'H, 0));
3091 cpars.mgcp_connection_id_bss := '10004'H;
3092 cpars.mgcp_connection_id_mss := '10005'H;
3093 cpars.mgcp_ep := "rtpbridge/1@mgw";
3094 cpars.bss_rtp_port := 1110;
3095
3096 /* Perform location update */
3097 f_perform_lu();
3098
3099 /* Establish a MT call */
3100 f_mt_call_establish(cpars);
3101
3102 /* Hold the call for some time */
3103 f_sleep(1.0);
3104
Vadim Yanitskiy747689e2018-06-19 00:14:28 +07003105 var template OCTN facility_req := f_USSD_FACILITY_IE_INVOKE(
3106 op_code := SS_OP_CODE_PROCESS_USS_REQ,
3107 ussd_string := "*#100#"
3108 );
3109
3110 var template OCTN facility_rsp := f_USSD_FACILITY_IE_RETURN_RESULT(
3111 op_code := SS_OP_CODE_PROCESS_USS_REQ,
3112 ussd_string := "Your extension is " & hex2str(g_pars.msisdn) & "\r"
3113 )
3114
Vadim Yanitskiy0aaf48d2018-06-06 07:02:47 +07003115 /* Compose a new SS/REGISTER message with request */
3116 var template (value) PDU_ML3_MS_NW ussd_req := ts_ML3_MO_SS_REGISTER(
3117 tid := 1, /* We just need a single transaction */
3118 ti_flag := c_TIF_ORIG, /* Sent from the side that originates the TI */
Vadim Yanitskiy747689e2018-06-19 00:14:28 +07003119 facility := valueof(facility_req)
Vadim Yanitskiy0aaf48d2018-06-06 07:02:47 +07003120 );
3121
3122 /* Compose SS/RELEASE_COMPLETE template with expected response */
3123 var template PDU_ML3_NW_MS ussd_rsp := tr_ML3_MT_SS_RELEASE_COMPLETE(
3124 tid := 1, /* Response should arrive within the same transaction */
3125 ti_flag := c_TIF_REPL, /* Sent to the side that originates the TI */
Vadim Yanitskiy747689e2018-06-19 00:14:28 +07003126 facility := valueof(facility_rsp)
Vadim Yanitskiy0aaf48d2018-06-06 07:02:47 +07003127 );
3128
Vadim Yanitskiy747689e2018-06-19 00:14:28 +07003129 /* Compose expected MSC -> HLR message */
3130 var template GSUP_PDU gsup_req := tr_GSUP_PROC_SS_REQ(
3131 imsi := g_pars.imsi,
3132 state := OSMO_GSUP_SESSION_STATE_BEGIN,
3133 ss := valueof(facility_req)
3134 );
3135
3136 /* To be used for sending response with correct session ID */
3137 var GSUP_PDU gsup_req_complete;
3138
3139 /* Request own number */
Vadim Yanitskiy0aaf48d2018-06-06 07:02:47 +07003140 BSSAP.send(ts_PDU_DTAP_MO(ussd_req));
Vadim Yanitskiy747689e2018-06-19 00:14:28 +07003141 /* Expect GSUP message containing the SS payload */
3142 gsup_req_complete := f_expect_gsup_msg(gsup_req);
3143
3144 /* Compose the response from HLR using received session ID */
3145 var template GSUP_PDU gsup_rsp := ts_GSUP_PROC_SS_REQ(
3146 imsi := g_pars.imsi,
3147 sid := gsup_req_complete.ies[1].val.session_id,
3148 state := OSMO_GSUP_SESSION_STATE_END,
3149 ss := valueof(facility_rsp)
3150 );
3151
3152 /* Finally, HLR terminates the session */
3153 GSUP.send(gsup_rsp);
3154 /* Expect RELEASE_COMPLETE message with the response */
3155 f_expect_mt_dtap_msg(ussd_rsp);
Vadim Yanitskiy0aaf48d2018-06-06 07:02:47 +07003156
3157 /* Hold the call for some time */
3158 f_sleep(1.0);
3159
3160 /* Release the call (does Clear Complete itself) */
3161 f_call_hangup(cpars, true);
3162}
Vadim Yanitskiy2a978b92018-06-19 17:51:20 +07003163testcase TC_lu_and_mo_ussd_during_mt_call() runs on MTC_CT {
Vadim Yanitskiy0aaf48d2018-06-06 07:02:47 +07003164 var BSC_ConnHdlr vc_conn;
3165 f_init();
Vadim Yanitskiy2a978b92018-06-19 17:51:20 +07003166 vc_conn := f_start_handler(refers(f_tc_lu_and_mo_ussd_during_mt_call), 48);
Vadim Yanitskiy0aaf48d2018-06-06 07:02:47 +07003167 vc_conn.done;
3168}
3169
Neels Hofmeyr692c9ee2018-04-10 02:07:13 +02003170/* BSSMAP Clear Request in the middle of a call, see OS#3062 */
3171private function f_tc_mo_cc_bssmap_clear(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
3172 f_init_handler(pars);
3173 var CallParameters cpars := valueof(t_CallParams('12345'H, 0));
3174 var MNCC_PDU mncc;
3175 var MgcpCommand mgcp_cmd;
3176
3177 f_perform_lu();
3178
3179 f_establish_fully();
3180 f_create_mncc_expect(hex2str(cpars.called_party));
3181 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
3182
3183 BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_CC_SETUP(cpars.transaction_id, cpars.called_party)));
3184 MNCC.receive(tr_MNCC_SETUP_ind(?, tr_MNCC_number(hex2str(cpars.called_party)))) -> value mncc;
3185 cpars.mncc_callref := mncc.u.signal.callref;
3186 log("mncc_callref=", cpars.mncc_callref);
3187 MNCC.send(ts_MNCC_CALL_PROC_req(cpars.mncc_callref, cpars.mncc_bearer_cap));
3188 BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_CC_CALL_PROC(cpars.transaction_id)));
3189
3190 MNCC.send(ts_MNCC_ALERT_req(cpars.mncc_callref));
3191 BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_CC_ALERTING(cpars.transaction_id)));
3192 MGCP.receive(tr_CRCX);
3193
3194 f_sleep(1.0);
3195 BSSAP.send(ts_BSSMAP_ClearRequest(0));
3196
Neels Hofmeyrde76f052019-02-26 05:02:46 +01003197 var default ccrel := activate(as_optional_cc_rel(cpars));
Neels Hofmeyr692c9ee2018-04-10 02:07:13 +02003198
Neels Hofmeyrde76f052019-02-26 05:02:46 +01003199 interleave {
3200 [] MNCC.receive(tr_MNCC_REL_ind(?, ?)) { };
3201 [] BSSAP.receive(tr_BSSMAP_ClearCommand) {
3202 BSSAP.send(ts_BSSMAP_ClearComplete);
3203 };
3204 }
3205
3206 deactivate(ccrel);
Neels Hofmeyr692c9ee2018-04-10 02:07:13 +02003207
3208 f_sleep(1.0);
3209}
3210testcase TC_mo_cc_bssmap_clear() runs on MTC_CT {
3211 var BSC_ConnHdlr vc_conn;
3212 f_init();
3213
3214 vc_conn := f_start_handler(refers(f_tc_mo_cc_bssmap_clear), 43);
3215 vc_conn.done;
3216}
3217
Vadim Yanitskiy13e4a272018-06-19 18:24:31 +07003218/* LU followed by MT call and MT USSD request during this call */
3219private function f_tc_lu_and_mt_ussd_during_mt_call(charstring id, BSC_ConnHdlrPars pars)
3220runs on BSC_ConnHdlr {
3221 f_init_handler(pars);
3222
3223 /* Call parameters taken from f_tc_lu_and_mt_call */
3224 var CallParameters cpars := valueof(t_CallParams('123456'H, 0));
3225 cpars.mgcp_connection_id_bss := '10004'H;
3226 cpars.mgcp_connection_id_mss := '10005'H;
3227 cpars.mgcp_ep := "rtpbridge/1@mgw";
3228 cpars.bss_rtp_port := 1110;
3229
3230 /* Perform location update */
3231 f_perform_lu();
3232
3233 /* Establish a MT call */
3234 f_mt_call_establish(cpars);
3235
3236 /* Hold the call for some time */
3237 f_sleep(1.0);
3238
3239 var template OCTN facility_req := f_USSD_FACILITY_IE_INVOKE(
3240 op_code := SS_OP_CODE_USS_REQUEST,
3241 ussd_string := "Please type anything..."
3242 );
3243
3244 var template OCTN facility_rsp := f_USSD_FACILITY_IE_RETURN_RESULT(
3245 op_code := SS_OP_CODE_USS_REQUEST,
3246 ussd_string := "Nope."
3247 )
3248
3249 /* Compose MT SS/REGISTER message with network-originated request */
3250 var template (value) PDU_ML3_NW_MS ussd_req := ts_ML3_MT_SS_REGISTER(
3251 tid := 0, /* FIXME: most likely, it should be 0 */
3252 ti_flag := c_TIF_ORIG, /* Sent from the side that originates the TI */
3253 facility := valueof(facility_req)
3254 );
3255
3256 /* Compose HLR -> MSC GSUP message */
3257 var template (value) GSUP_PDU gsup_req := ts_GSUP_PROC_SS_REQ(
3258 imsi := g_pars.imsi,
3259 sid := '20000101'O,
3260 state := OSMO_GSUP_SESSION_STATE_BEGIN,
3261 ss := valueof(facility_req)
3262 );
3263
3264 /* Send it to MSC */
3265 GSUP.send(gsup_req);
3266 /* Expect MT REGISTER message with USSD request */
3267 f_expect_mt_dtap_msg(ussd_req);
3268
3269 /* Compose a new MO SS/FACILITY message with response */
3270 var template (value) PDU_ML3_MS_NW ussd_rsp := ts_ML3_MO_SS_FACILITY(
3271 tid := 0, /* FIXME: it shall match the request tid */
3272 ti_flag := c_TIF_REPL, /* Sent to the side that originates the TI */
3273 facility := valueof(facility_rsp)
3274 );
3275
3276 /* Compose expected MSC -> HLR GSUP message */
3277 var template GSUP_PDU gsup_rsp := tr_GSUP_PROC_SS_REQ(
3278 imsi := g_pars.imsi,
3279 sid := '20000101'O,
3280 state := OSMO_GSUP_SESSION_STATE_CONTINUE,
3281 ss := valueof(facility_rsp)
3282 );
3283
3284 /* MS sends response */
3285 BSSAP.send(ts_PDU_DTAP_MO(ussd_rsp));
3286 f_expect_gsup_msg(gsup_rsp);
3287
3288 /* Compose expected MT SS/RELEASE COMPLETE message */
3289 var template PDU_ML3_NW_MS ussd_term := tr_ML3_MT_SS_RELEASE_COMPLETE(
3290 tid := 0, /* FIXME: it shall match the request tid */
3291 ti_flag := c_TIF_ORIG, /* Sent from the side that originates the TI */
3292 facility := omit
3293 );
3294
3295 /* Compose MSC -> HLR GSUP message */
3296 var template GSUP_PDU gsup_term := ts_GSUP_PROC_SS_REQ(
3297 imsi := g_pars.imsi,
3298 sid := '20000101'O,
3299 state := OSMO_GSUP_SESSION_STATE_END
3300 );
3301
3302 /* Finally, HLR terminates the session */
3303 GSUP.send(gsup_term);
3304 /* Expect MT RELEASE COMPLETE without Facility IE */
3305 f_expect_mt_dtap_msg(ussd_term);
3306
3307 /* Hold the call for some time */
3308 f_sleep(1.0);
3309
3310 /* Release the call (does Clear Complete itself) */
3311 f_call_hangup(cpars, true);
3312}
3313testcase TC_lu_and_mt_ussd_during_mt_call() runs on MTC_CT {
3314 var BSC_ConnHdlr vc_conn;
3315 f_init();
3316 vc_conn := f_start_handler(refers(f_tc_lu_and_mt_ussd_during_mt_call), 49);
3317 vc_conn.done;
3318}
3319
Vadim Yanitskiy2daf52d2018-06-21 04:19:58 +07003320/* LU followed by MO USSD request and MO Release during transaction */
3321private function f_tc_lu_and_mo_ussd_mo_release(charstring id, BSC_ConnHdlrPars pars)
3322runs on BSC_ConnHdlr {
3323 f_init_handler(pars);
3324
3325 /* Perform location update */
3326 f_perform_lu();
3327
3328 /* Send CM Service Request for SS/USSD */
3329 f_establish_fully(EST_TYPE_SS_ACT);
3330
3331 /* We need to inspect GSUP activity */
3332 f_create_gsup_expect(hex2str(g_pars.imsi));
3333
3334 var template OCTN facility_ms_req := f_USSD_FACILITY_IE_INVOKE(
3335 invoke_id := 1, /* Initial request */
3336 op_code := SS_OP_CODE_PROCESS_USS_REQ,
3337 ussd_string := "*6766*266#"
3338 );
3339
3340 var template OCTN facility_net_req := f_USSD_FACILITY_IE_INVOKE(
3341 invoke_id := 2, /* Counter request */
3342 op_code := SS_OP_CODE_USS_REQUEST,
3343 ussd_string := "Password?!?"
3344 )
3345
3346 /* Compose MO SS/REGISTER message with request */
3347 var template (value) PDU_ML3_MS_NW ussd_ms_req := ts_ML3_MO_SS_REGISTER(
3348 tid := 1, /* We just need a single transaction */
3349 ti_flag := c_TIF_ORIG, /* Sent from the side that originates the TI */
3350 facility := valueof(facility_ms_req)
3351 );
3352
3353 /* Compose expected MSC -> HLR message */
3354 var template GSUP_PDU gsup_ms_req := tr_GSUP_PROC_SS_REQ(
3355 imsi := g_pars.imsi,
3356 state := OSMO_GSUP_SESSION_STATE_BEGIN,
3357 ss := valueof(facility_ms_req)
3358 );
3359
3360 /* To be used for sending response with correct session ID */
3361 var GSUP_PDU gsup_ms_req_complete;
3362
3363 /* Initiate a new transaction */
3364 BSSAP.send(ts_PDU_DTAP_MO(ussd_ms_req));
3365 /* Expect GSUP request with original Facility IE */
3366 gsup_ms_req_complete := f_expect_gsup_msg(gsup_ms_req);
3367
3368 /* Compose the response from HLR using received session ID */
3369 var template (value) GSUP_PDU gsup_net_req := ts_GSUP_PROC_SS_REQ(
3370 imsi := g_pars.imsi,
3371 sid := gsup_ms_req_complete.ies[1].val.session_id,
3372 state := OSMO_GSUP_SESSION_STATE_CONTINUE,
3373 ss := valueof(facility_net_req)
3374 );
3375
3376 /* Compose expected MT SS/FACILITY template with counter request */
3377 var template PDU_ML3_NW_MS ussd_net_req := tr_ML3_MT_SS_FACILITY(
3378 tid := 1, /* Response should arrive within the same transaction */
3379 ti_flag := c_TIF_REPL, /* Sent to the side that originates the TI */
3380 facility := valueof(facility_net_req)
3381 );
3382
3383 /* Send response over GSUP */
3384 GSUP.send(gsup_net_req);
3385 /* Expect MT SS/FACILITY message with counter request */
3386 f_expect_mt_dtap_msg(ussd_net_req);
3387
3388 /* Compose MO SS/RELEASE COMPLETE */
3389 var template (value) PDU_ML3_MS_NW ussd_abort := ts_ML3_MO_SS_RELEASE_COMPLETE(
3390 tid := 1, /* Response should arrive within the same transaction */
3391 ti_flag := c_TIF_ORIG, /* Sent from the side that originates the TI */
3392 facility := omit
3393 /* TODO: cause? */
3394 );
3395
3396 /* Compose expected HLR -> MSC abort message */
3397 var template GSUP_PDU gsup_abort := tr_GSUP_PROC_SS_REQ(
3398 imsi := g_pars.imsi,
3399 sid := gsup_ms_req_complete.ies[1].val.session_id,
3400 state := OSMO_GSUP_SESSION_STATE_END
3401 );
3402
3403 /* Abort transaction */
3404 BSSAP.send(ts_PDU_DTAP_MO(ussd_abort));
3405 /* Expect GSUP message indicating abort */
3406 f_expect_gsup_msg(gsup_abort);
3407
3408 f_expect_clear();
3409}
3410testcase TC_lu_and_mo_ussd_mo_release() runs on MTC_CT {
3411 var BSC_ConnHdlr vc_conn;
3412 f_init();
3413 vc_conn := f_start_handler(refers(f_tc_lu_and_mo_ussd_mo_release), 50);
3414 vc_conn.done;
3415}
3416
Vadim Yanitskiy0e392dd2018-11-29 00:47:54 +07003417/* LU followed by MO USSD request and MT Release due to timeout */
3418private function f_tc_lu_and_ss_session_timeout(charstring id, BSC_ConnHdlrPars pars)
3419runs on BSC_ConnHdlr {
3420 f_init_handler(pars);
3421
3422 /* Perform location update */
3423 f_perform_lu();
3424
3425 /* Send CM Service Request for SS/USSD */
3426 f_establish_fully(EST_TYPE_SS_ACT);
3427
3428 /* We need to inspect GSUP activity */
3429 f_create_gsup_expect(hex2str(g_pars.imsi));
3430
3431 var template OCTN facility_ms_req := f_USSD_FACILITY_IE_INVOKE(
3432 invoke_id := 1,
3433 op_code := SS_OP_CODE_PROCESS_USS_REQ,
3434 ussd_string := "#release_me");
3435
3436 /* Compose MO SS/REGISTER message with request */
3437 var template (value) PDU_ML3_MS_NW ussd_ms_req := ts_ML3_MO_SS_REGISTER(
3438 tid := 1, /* An arbitrary transaction identifier */
3439 ti_flag := c_TIF_ORIG, /* Sent from the side that originates the TI */
3440 facility := valueof(facility_ms_req));
3441
3442 /* Compose expected MSC -> HLR message */
3443 var template GSUP_PDU gsup_ms_req := tr_GSUP_PROC_SS_REQ(
3444 imsi := g_pars.imsi,
3445 state := OSMO_GSUP_SESSION_STATE_BEGIN,
3446 ss := valueof(facility_ms_req));
3447
3448 /* To be used for sending response with correct session ID */
3449 var GSUP_PDU gsup_ms_req_complete;
3450
3451 /* Initiate a new SS transaction */
3452 BSSAP.send(ts_PDU_DTAP_MO(ussd_ms_req));
3453 /* Expect GSUP request with original Facility IE */
3454 gsup_ms_req_complete := f_expect_gsup_msg(gsup_ms_req);
3455
3456 /* Don't respond, wait for timeout */
3457 f_sleep(3.0);
3458
3459 var template PDU_ML3_NW_MS dtap_rel := tr_ML3_MT_SS_RELEASE_COMPLETE(
3460 tid := 1, /* Should match the request's tid */
3461 ti_flag := c_TIF_REPL, /* Sent to the side that originates the TI */
3462 cause := *, /* TODO: expect some specific value */
3463 facility := omit);
3464
3465 var template GSUP_PDU gsup_rel := tr_GSUP_PROC_SS_ERR(
3466 imsi := g_pars.imsi,
3467 sid := gsup_ms_req_complete.ies[1].val.session_id,
3468 state := OSMO_GSUP_SESSION_STATE_END,
3469 cause := ?); /* TODO: expect some specific value */
3470
3471 /* Expect release on both interfaces */
3472 interleave {
3473 [] BSSAP.receive(tr_PDU_DTAP_MT(dtap_rel)) { };
3474 [] GSUP.receive(gsup_rel) { };
3475 }
3476
3477 f_expect_clear();
3478 setverdict(pass);
3479}
3480testcase TC_lu_and_ss_session_timeout() runs on MTC_CT {
3481 var BSC_ConnHdlr vc_conn;
3482 f_init();
Vadim Yanitskiy36d28dd2018-12-03 02:45:45 +07003483 f_vty_config(MSCVTY, "msc", "ncss guard-timeout 3");
Vadim Yanitskiy0e392dd2018-11-29 00:47:54 +07003484 vc_conn := f_start_handler(refers(f_tc_lu_and_ss_session_timeout), 51);
3485 vc_conn.done;
Vadim Yanitskiy36d28dd2018-12-03 02:45:45 +07003486 f_vty_config(MSCVTY, "msc", "ncss guard-timeout 0");
Vadim Yanitskiy0e392dd2018-11-29 00:47:54 +07003487}
3488
Stefan Sperling89eb1f32018-12-17 15:06:20 +01003489/* A5/1 only permitted on network side; attempt an invalid CIPHER MODE COMPLETE with A5/3 which MSC should reject. */
3490private function f_tc_cipher_complete_with_invalid_cipher(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
3491 pars.net.expect_auth := true;
3492 pars.net.expect_ciph := true;
3493 pars.net.kc_support := '02'O; /* A5/1 only */
3494 f_init_handler(pars);
3495
3496 g_pars.vec := f_gen_auth_vec_2g();
3497
3498 /* Can't use f_perform_lu() directly. Code below is based on it. */
3499
3500 /* tell GSUP dispatcher to send this IMSI to us */
3501 f_create_gsup_expect(hex2str(g_pars.imsi));
3502
3503 /* Send BSSAP_Conn_Req with COMPL L3 INFO to MSC */
3504 var PDU_ML3_MS_NW l3_lu := f_build_lu_imsi(g_pars.imsi)
Harald Weltedceacc72019-04-21 20:58:35 +02003505 f_cl3_or_initial_ue(l3_lu);
Stefan Sperling89eb1f32018-12-17 15:06:20 +01003506
3507 f_mm_auth();
3508
3509 var OCT1 a5_net := f_alg_mask_from_cm(g_pars.cm2);
3510 var OCT1 a5_intersect := g_pars.net.kc_support and4b a5_net;
3511 alt {
3512 [] BSSAP.receive(tr_BSSMAP_CipherModeCmd(a5_intersect, g_pars.vec.kc)) {
3513 BSSAP.send(ts_BSSMAP_CipherModeCompl(int2oct(4 /* "accept" A5/3 */, 1)));
3514 }
3515 [] BSSAP.receive(tr_BSSMAP_CipherModeCmd(?, g_pars.vec.kc)) {
3516 setverdict(fail, "Wrong ciphering algorithm mask in CiphModCmd");
3517 mtc.stop;
3518 }
3519 [] BSSAP.receive {
3520 setverdict(fail, "Unknown/unexpected BSSAP received");
3521 mtc.stop;
3522 }
3523 }
3524
3525 /* Expect LU reject from MSC. */
3526 alt {
3527 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Rej)) {
3528 setverdict(pass);
3529 }
3530 [] BSSAP.receive {
3531 setverdict(fail, "Unknown/unexpected BSSAP received");
3532 mtc.stop;
3533 }
3534 }
Stefan Sperlingc620b352018-12-18 17:23:36 +01003535 f_expect_clear();
Stefan Sperling89eb1f32018-12-17 15:06:20 +01003536}
3537
3538testcase TC_cipher_complete_with_invalid_cipher() runs on MTC_CT {
3539 var BSC_ConnHdlr vc_conn;
3540 f_init();
3541 f_vty_config(MSCVTY, "network", "encryption a5 1");
3542
3543 vc_conn := f_start_handler(refers(f_tc_cipher_complete_with_invalid_cipher), 52);
3544 vc_conn.done;
3545}
3546
Harald Weltef640a012018-04-14 17:49:21 +02003547/* TODO (SMS):
3548 * different user data lengths
3549 * SMPP transaction mode with unsuccessful delivery
3550 * queued MT-SMS with no paging response + later delivery
3551 * different data coding schemes
3552 * multi-part SMS
3553 * user-data headers
3554 * TP-PID for SMS to SIM
3555 * behavior if SMS memory is full + RP-SMMA
3556 * delivery reports
3557 * SMPP osmocom extensions
3558 * more-messages-to-send
3559 * SMS during ongoing call (SACCH/SAPI3)
3560 */
3561
3562/* TODO (General):
Harald Welteba7b6d92018-01-23 21:32:34 +01003563 * continue to send repeated MO signalling messages to keep channel open: does MSC tmeout?
3564 * malformed messages (missing IE, invalid message type): properly rejected?
3565 * MT call while LU or is ongoing: Do we use existing lchan or page while lchan active?
3566 * 3G/2G auth permutations
3567 * encryption algorithms vs. classmark vs. vty config
Harald Welteba7b6d92018-01-23 21:32:34 +01003568 * send new transaction after/during clear (like SMS, ...)
Harald Welte45164da2018-01-24 12:51:27 +01003569 * too long L3 INFO in DTAP
3570 * too long / padded BSSAP
3571 * too long / short TLV values
Harald Welteba7b6d92018-01-23 21:32:34 +01003572 */
Harald Weltef6dd64d2017-11-19 12:09:51 +01003573
Philipp Maier948747b2019-04-02 15:22:33 +02003574/* Check if a subscriber exists in the VLR */
3575private function f_ctrl_subscr_in_vlr(charstring imsi_or_msisdn) runs on BSC_ConnHdlr return boolean {
3576
3577 var CtrlValue active_subsribers;
3578 var integer rc;
3579 active_subsribers := f_ctrl_get(IPA_CTRL, "subscriber-list-active-v1");
3580
3581 rc := f_strstr(active_subsribers, imsi_or_msisdn);
3582 if (rc < 0) {
3583 return false;
3584 }
3585
3586 return true;
3587}
3588
Harald Welte4263c522018-12-06 11:56:27 +01003589/* Perform a location updatye at the A-Interface and run some checks to confirm
3590 * that everything is back to normal. */
3591private function f_sgsap_bssmap_screening() runs on BSC_ConnHdlr {
3592 var SmsParameters spars := valueof(t_SmsPars);
3593
3594 /* Perform a location update, the SGs association is expected to fall
3595 * back to NULL */
3596 f_perform_lu();
3597 f_ctrl_get_exp(IPA_CTRL, "fsm.SGs-UE.id.imsi:" & hex2str(g_pars.imsi) & ".state", "SGs-NULL");
3598
3599 /* Trigger a paging request and expect the paging on BSSMAP, this is
3600 * to make sure that pagings are sent throught the A-Interface again
3601 * and not throught the SGs interface.*/
Harald Welte6811d102019-04-14 22:23:14 +02003602 f_ran_register_imsi(g_pars.imsi, g_pars.tmsi);
Harald Welte4263c522018-12-06 11:56:27 +01003603 f_vty_transceive(MSCVTY, "subscriber imsi " & hex2str(g_pars.imsi) & " paging");
3604
3605 alt {
3606 [] BSSAP.receive(tr_BSSMAP_Paging(g_pars.imsi)); {
3607 setverdict(pass);
3608 }
3609 [] SGsAP.receive {
3610 setverdict(fail, "Received unexpected message on SGs");
3611 }
3612 }
3613
3614 /* Send an SMS to make sure that also payload messages are routed
3615 * throught the A-Interface again */
3616 f_establish_fully(EST_TYPE_MO_SMS);
3617 f_mo_sms(spars);
3618 f_expect_clear();
3619}
3620
3621private function f_tc_sgsap_reset(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
3622 var charstring vlr_name;
3623 f_init_handler(pars);
3624
3625 vlr_name := f_sgsap_reset_mme(mp_mme_name);
3626 log("VLR name: ", vlr_name);
3627 setverdict(pass);
Neels Hofmeyrc0b520d2019-03-06 15:35:50 +01003628 f_sleep(1.0);
Harald Welte4263c522018-12-06 11:56:27 +01003629}
3630
3631testcase TC_sgsap_reset() runs on MTC_CT {
Philipp Maier8e07a4a2019-02-14 18:23:28 +01003632 var BSC_ConnHdlrPars pars;
Harald Welte4263c522018-12-06 11:56:27 +01003633 var BSC_ConnHdlr vc_conn;
Philipp Maier8e07a4a2019-02-14 18:23:28 +01003634 f_init(1, true);
3635 pars := f_init_pars(11810, true);
3636 vc_conn := f_start_handler_with_pars(refers(f_tc_sgsap_reset), pars);
Harald Welte4263c522018-12-06 11:56:27 +01003637 vc_conn.done;
3638}
3639
3640/* like f_mm_auth() but for SGs */
3641function f_mm_auth_sgs() runs on BSC_ConnHdlr {
3642 if (g_pars.net.expect_auth) {
3643 g_pars.vec := f_gen_auth_vec_3g();
3644 var GSUP_IE auth_tuple := valueof(ts_GSUP_IE_AuthTuple2G3G(g_pars.vec.rand,
3645 g_pars.vec.sres,
3646 g_pars.vec.kc,
3647 g_pars.vec.ik,
3648 g_pars.vec.ck,
3649 g_pars.vec.autn,
3650 g_pars.vec.res));
3651 GSUP.receive(tr_GSUP_SAI_REQ(g_pars.imsi));
3652 GSUP.send(ts_GSUP_SAI_RES(g_pars.imsi, auth_tuple));
3653 SGsAP.receive(tr_ML3_MT_MM_AUTH_REQ_3G(g_pars.vec.rand, g_pars.vec.autn));
3654 SGsAP.send(ts_ML3_MT_MM_AUTH_RESP_3G(g_pars.vec.sres, g_pars.vec.res));
3655 }
3656}
3657
3658/* like f_perform_lu(), but on SGs rather than BSSAP */
3659function f_sgs_perform_lu() runs on BSC_ConnHdlr {
3660 var octetstring mme_name := f_enc_dns_hostname(mp_mme_name);
3661 var PDU_SGsAP lur;
3662 var PDU_SGsAP lua;
3663 var PDU_SGsAP mm_info;
3664 var octetstring mm_info_dtap;
3665
3666 /* tell GSUP dispatcher to send this IMSI to us */
3667 f_create_gsup_expect(hex2str(g_pars.imsi));
3668
3669 lur := valueof(ts_SGsAP_LU_REQ(g_pars.imsi, mme_name, IMSI_attach,
3670 ts_SGsAP_LAI('901'H, '70'H, 2342)));
3671 /* Old LAI, if MS sends it */
3672 /* TMSI status, if MS has no valid TMSI */
3673 /* IMEISV, if it supports "automatic device detection" */
3674 /* TAI, if available in MME */
3675 /* E-CGI, if available in MME */
3676 SGsAP.send(lur);
3677
3678 /* FIXME: is this really done over SGs? The Ue is already authenticated
3679 * via the MME ... */
3680 f_mm_auth_sgs();
3681
3682 /* Expect MSC to perform LU with HLR */
3683 GSUP.receive(tr_GSUP_UL_REQ(g_pars.imsi));
3684 GSUP.send(ts_GSUP_ISD_REQ(g_pars.imsi, g_pars.msisdn));
3685 GSUP.receive(tr_GSUP_ISD_RES(g_pars.imsi));
3686 GSUP.send(ts_GSUP_UL_RES(g_pars.imsi));
3687
3688 alt {
3689 [] SGsAP.receive(tr_SGsAP_LU_ACCEPT(g_pars.imsi, ?)) -> value lua {
3690 if (isvalue(lua.sGsAP_LOCATION_UPDATE_ACCEPT.newTMSIorIMSI.iD.iD.tmsi_ptmsi.octets)) {
3691 g_pars.tmsi :=lua.sGsAP_LOCATION_UPDATE_ACCEPT.newTMSIorIMSI.iD.iD.tmsi_ptmsi.octets
3692 SGsAP.send(ts_SGsAP_TMSI_REALL_CMPL(g_pars.imsi));
3693 }
3694 setverdict(pass);
3695 }
3696 [] SGsAP.receive(tr_SGsAP_LU_REJECT(g_pars.imsi, ?, ?)) {
3697 setverdict(fail, "Received LU-REJECT instead of ACCEPT");
3698 }
3699 [] SGsAP.receive {
3700 setverdict(fail, "Received unexpected message on SGs");
3701 }
3702 }
3703
3704 /* Check MM information */
3705 if (mp_mm_info == true) {
3706 SGsAP.receive(tr_SGsAP_MM_INFO_REQ(g_pars.imsi, ?)) -> value mm_info;
3707 mm_info_dtap := '0532'O & mm_info.sGsAP_MM_INFORMATION_REQUEST.mM_Information.information;
3708 if (not match(dec_PDU_ML3_NW_MS(mm_info_dtap), tr_ML3_MT_MM_Info)) {
3709 setverdict(fail, "Unexpected MM Information");
3710 }
3711 }
3712
3713 f_ctrl_get_exp(IPA_CTRL, "fsm.SGs-UE.id.imsi:" & hex2str(g_pars.imsi) & ".state", "SGs-ASSOCIATED");
3714}
3715
3716private function f_tc_sgsap_lu(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
3717 f_init_handler(pars);
3718 f_sgs_perform_lu();
3719 f_ctrl_get_exp(IPA_CTRL, "fsm.SGs-UE.id.imsi:" & hex2str(g_pars.imsi) & ".state", "SGs-ASSOCIATED");
3720
3721 f_sgsap_bssmap_screening();
3722
3723 setverdict(pass);
3724}
3725testcase TC_sgsap_lu() runs on MTC_CT {
Philipp Maier8e07a4a2019-02-14 18:23:28 +01003726 var BSC_ConnHdlrPars pars;
Harald Welte4263c522018-12-06 11:56:27 +01003727 var BSC_ConnHdlr vc_conn;
Philipp Maier8e07a4a2019-02-14 18:23:28 +01003728 f_init(1, true);
3729 pars := f_init_pars(11811, true);
3730 vc_conn := f_start_handler_with_pars(refers(f_tc_sgsap_lu), pars);
Harald Welte4263c522018-12-06 11:56:27 +01003731 vc_conn.done;
3732}
3733
3734/* Do LU by IMSI, refuse it on GSUP and expect LU REJ back to MS */
3735private function f_tc_sgsap_lu_imsi_reject(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
3736 f_init_handler(pars);
3737 var PDU_SGsAP lur;
3738
3739 f_create_gsup_expect(hex2str(g_pars.imsi));
3740 var octetstring mme_name := f_enc_dns_hostname(mp_mme_name);
3741 lur := valueof(ts_SGsAP_LU_REQ(g_pars.imsi, mme_name, IMSI_attach,
3742 ts_SGsAP_LAI('901'H, '70'H, 2342)));
3743 SGsAP.send(lur);
3744
3745 GSUP.receive(tr_GSUP_UL_REQ(g_pars.imsi));
3746 GSUP.send(ts_GSUP_UL_ERR(g_pars.imsi, 23));
3747 alt {
3748 [] SGsAP.receive(tr_SGsAP_LU_REJECT(g_pars.imsi, ?, ?)) {
3749 setverdict(pass);
3750 }
3751 [] SGsAP.receive(tr_SGsAP_LU_ACCEPT(g_pars.imsi, ?)) {
3752 setverdict(fail, "Expecting LU REJ, but got ACCEPT");
3753 mtc.stop;
3754 }
3755 [] SGsAP.receive {
3756 setverdict(fail, "Received unexpected message on SGs");
3757 }
3758 }
3759
3760 f_sgsap_bssmap_screening();
3761
3762 setverdict(pass);
3763}
3764testcase TC_sgsap_lu_imsi_reject() runs on MTC_CT {
Philipp Maier8e07a4a2019-02-14 18:23:28 +01003765 var BSC_ConnHdlrPars pars;
Harald Welte4263c522018-12-06 11:56:27 +01003766 var BSC_ConnHdlr vc_conn;
Philipp Maier8e07a4a2019-02-14 18:23:28 +01003767 f_init(1, true);
3768 pars := f_init_pars(11812, true);
Harald Welte4263c522018-12-06 11:56:27 +01003769
Philipp Maier8e07a4a2019-02-14 18:23:28 +01003770 vc_conn := f_start_handler_with_pars(refers(f_tc_sgsap_lu_imsi_reject), pars);
Harald Welte4263c522018-12-06 11:56:27 +01003771 vc_conn.done;
3772}
3773
3774/* Do LU by IMSI, but then remain silent so that Ts6-1 times out */
3775private function f_tc_sgsap_lu_and_nothing(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
3776 var octetstring mme_name := f_enc_dns_hostname(mp_mme_name);
3777 var PDU_SGsAP lur;
3778
3779 f_init_handler(pars);
3780
3781 /* tell GSUP dispatcher to send this IMSI to us */
3782 f_create_gsup_expect(hex2str(g_pars.imsi));
3783
3784 lur := valueof(ts_SGsAP_LU_REQ(g_pars.imsi, mme_name, IMSI_attach,
3785 ts_SGsAP_LAI('901'H, '70'H, 2342)));
3786 /* Old LAI, if MS sends it */
3787 /* TMSI status, if MS has no valid TMSI */
3788 /* IMEISV, if it supports "automatic device detection" */
3789 /* TAI, if available in MME */
3790 /* E-CGI, if available in MME */
3791 SGsAP.send(lur);
3792
3793 /* FIXME: is this really done over SGs? The Ue is already authenticated
3794 * via the MME ... */
3795 f_mm_auth_sgs();
3796
3797 /* Expect MSC to perform LU with HLR */
3798 GSUP.receive(tr_GSUP_UL_REQ(g_pars.imsi));
3799 GSUP.send(ts_GSUP_ISD_REQ(g_pars.imsi, g_pars.msisdn));
3800 GSUP.receive(tr_GSUP_ISD_RES(g_pars.imsi));
3801 GSUP.send(ts_GSUP_UL_RES(g_pars.imsi));
3802
3803 alt {
3804 [] SGsAP.receive(tr_SGsAP_LU_ACCEPT(g_pars.imsi, ?)) {
3805 setverdict(pass);
3806 }
3807 [] SGsAP.receive(tr_SGsAP_LU_REJECT(g_pars.imsi, ?, ?)) {
3808 setverdict(fail, "Received LU-REJECT instead of ACCEPT");
3809 }
3810 [] SGsAP.receive {
3811 setverdict(fail, "Received unexpected message on SGs");
3812 }
3813 }
3814
3815 f_ctrl_get_exp(IPA_CTRL, "fsm.SGs-UE.id.imsi:" & hex2str(g_pars.imsi) & ".state", "SGs-ASSOCIATED");
3816
3817 /* Wait until the VLR has abort the TMSI reallocation procedure */
3818 f_sleep(45.0);
3819
3820 /* The outcome does not change the SGs state, see also 5.2.3.4 */
3821 f_ctrl_get_exp(IPA_CTRL, "fsm.SGs-UE.id.imsi:" & hex2str(g_pars.imsi) & ".state", "SGs-ASSOCIATED");
3822
3823 f_sgsap_bssmap_screening();
3824
3825 setverdict(pass);
3826}
3827testcase TC_sgsap_lu_and_nothing() runs on MTC_CT {
Philipp Maier8e07a4a2019-02-14 18:23:28 +01003828 var BSC_ConnHdlrPars pars;
Harald Welte4263c522018-12-06 11:56:27 +01003829 var BSC_ConnHdlr vc_conn;
Philipp Maier8e07a4a2019-02-14 18:23:28 +01003830 f_init(1, true);
3831 pars := f_init_pars(11813, true);
Harald Welte4263c522018-12-06 11:56:27 +01003832
Philipp Maier8e07a4a2019-02-14 18:23:28 +01003833 vc_conn := f_start_handler_with_pars(refers(f_tc_sgsap_lu_and_nothing), pars);
Harald Welte4263c522018-12-06 11:56:27 +01003834 vc_conn.done;
3835}
3836
3837private function f_tc_sgsap_expl_imsi_det_eps(charstring id, BSC_ConnHdlrPars pars)
3838runs on BSC_ConnHdlr {
3839 f_init_handler(pars);
3840 f_sgs_perform_lu();
3841 f_sleep(3.0);
3842
3843 var octetstring mme_name := f_enc_dns_hostname(mp_mme_name);
3844 SGsAP.send(ts_SGsAP_EPS_DETACH_IND(g_pars.imsi, mme_name, UE_initiated));
3845 SGsAP.receive(tr_SGsAP_EPS_DETACH_ACK(g_pars.imsi));
3846 f_ctrl_get_exp(IPA_CTRL, "fsm.SGs-UE.id.imsi:" & hex2str(g_pars.imsi) & ".state", "SGs-NULL");
3847
3848 f_sgsap_bssmap_screening();
3849
3850 setverdict(pass);
3851}
3852testcase TC_sgsap_expl_imsi_det_eps() runs on MTC_CT {
Philipp Maier8e07a4a2019-02-14 18:23:28 +01003853 var BSC_ConnHdlrPars pars;
Harald Welte4263c522018-12-06 11:56:27 +01003854 var BSC_ConnHdlr vc_conn;
Philipp Maier8e07a4a2019-02-14 18:23:28 +01003855 f_init(1, true);
3856 pars := f_init_pars(11814, true);
3857 vc_conn := f_start_handler_with_pars(refers(f_tc_sgsap_expl_imsi_det_eps), pars);
Harald Welte4263c522018-12-06 11:56:27 +01003858 vc_conn.done;
3859}
3860
Philipp Maierfc19f172019-03-21 11:17:54 +01003861private function f_tc_sgsap_impl_imsi_det_eps(charstring id, BSC_ConnHdlrPars pars)
3862runs on BSC_ConnHdlr {
3863 f_init_handler(pars);
3864 f_sgs_perform_lu();
3865 f_sleep(3.0);
3866
3867 var octetstring mme_name := f_enc_dns_hostname(mp_mme_name);
3868 SGsAP.send(ts_SGsAP_EPS_DETACH_IND(g_pars.imsi, mme_name, network_initiated));
3869 SGsAP.receive(tr_SGsAP_EPS_DETACH_ACK(g_pars.imsi));
3870 f_ctrl_get_exp(IPA_CTRL, "fsm.SGs-UE.id.imsi:" & hex2str(g_pars.imsi) & ".state", "SGs-NULL");
3871
3872 f_sgsap_bssmap_screening();
3873
3874 setverdict(pass);
3875}
3876testcase TC_sgsap_impl_imsi_det_eps() runs on MTC_CT {
3877 var BSC_ConnHdlrPars pars;
3878 var BSC_ConnHdlr vc_conn;
3879 f_init(1, true);
3880 pars := f_init_pars(11814, true);
3881 vc_conn := f_start_handler_with_pars(refers(f_tc_sgsap_impl_imsi_det_eps), pars);
3882 vc_conn.done;
3883}
3884
Harald Welte4263c522018-12-06 11:56:27 +01003885private function f_tc_sgsap_expl_imsi_det_noneps(charstring id, BSC_ConnHdlrPars pars)
3886runs on BSC_ConnHdlr {
3887 f_init_handler(pars);
3888 f_sgs_perform_lu();
3889 f_sleep(3.0);
3890
3891 var octetstring mme_name := f_enc_dns_hostname(mp_mme_name);
3892 SGsAP.send(ts_SGsAP_IMSI_DETACH_IND(g_pars.imsi, mme_name, combined_UE_initiated));
3893 SGsAP.receive(tr_SGsAP_IMSI_DETACH_ACK(g_pars.imsi));
Philipp Maierd08e7e72019-04-02 15:27:10 +02003894
3895 if (f_ctrl_subscr_in_vlr(hex2str(g_pars.imsi))) {
3896 setverdict(fail, "subscriber not removed from VLR");
3897 }
Harald Welte4263c522018-12-06 11:56:27 +01003898
3899 f_sgsap_bssmap_screening();
3900
3901 setverdict(pass);
3902}
3903testcase TC_sgsap_expl_imsi_det_noneps() runs on MTC_CT {
Philipp Maier8e07a4a2019-02-14 18:23:28 +01003904 var BSC_ConnHdlrPars pars;
Harald Welte4263c522018-12-06 11:56:27 +01003905 var BSC_ConnHdlr vc_conn;
Philipp Maier8e07a4a2019-02-14 18:23:28 +01003906 f_init(1, true);
3907 pars := f_init_pars(11815, true);
3908 vc_conn := f_start_handler_with_pars(refers(f_tc_sgsap_expl_imsi_det_noneps), pars);
Harald Welte4263c522018-12-06 11:56:27 +01003909 vc_conn.done;
3910}
3911
Philipp Maier5d812702019-03-21 10:51:26 +01003912private function f_tc_sgsap_impl_imsi_det_noneps(charstring id, BSC_ConnHdlrPars pars)
3913runs on BSC_ConnHdlr {
3914 f_init_handler(pars);
3915 f_sgs_perform_lu();
3916 f_sleep(3.0);
3917
3918 var octetstring mme_name := f_enc_dns_hostname(mp_mme_name);
3919 SGsAP.send(ts_SGsAP_IMSI_DETACH_IND(g_pars.imsi, mme_name, implicit_network_initiated));
3920 SGsAP.receive(tr_SGsAP_IMSI_DETACH_ACK(g_pars.imsi));
3921
3922 if (f_ctrl_subscr_in_vlr(hex2str(g_pars.imsi))) {
3923 setverdict(fail, "subscriber not removed from VLR");
3924 }
3925
3926 f_sgsap_bssmap_screening();
3927
3928 setverdict(pass);
3929}
3930testcase TC_sgsap_impl_imsi_det_noneps() runs on MTC_CT {
3931 var BSC_ConnHdlrPars pars;
3932 var BSC_ConnHdlr vc_conn;
3933 f_init(1, true);
3934 pars := f_init_pars(11815, true);
3935 vc_conn := f_start_handler_with_pars(refers(f_tc_sgsap_impl_imsi_det_noneps), pars);
3936 vc_conn.done;
3937}
3938
Harald Welte4263c522018-12-06 11:56:27 +01003939/* Trigger a paging request via VTY and send a paging reject in response */
3940private function f_tc_sgsap_paging_rej(charstring id, BSC_ConnHdlrPars pars)
3941runs on BSC_ConnHdlr {
3942 f_init_handler(pars);
3943 f_sgs_perform_lu();
3944 f_sleep(1.0);
3945
3946 var octetstring vlr_name := f_enc_dns_hostname(mp_vlr_name);
3947 var template PDU_SGsAP exp_resp := tr_SGsAP_PAGING_REQ(g_pars.imsi, vlr_name, CS_call_indicator, omit);
3948 var template LocationAreaId exp_lai := ts_SGsAP_IE_Lai(valueof(ts_SGsAP_LAI('901'H, '70'H, 2342)));
3949 exp_resp.sGsAP_PAGING_REQUEST.locationAreaId := exp_lai;
3950
3951 /* Initiate paging via VTY */
3952 f_vty_transceive(MSCVTY, "subscriber imsi " & hex2str(g_pars.imsi) & " paging");
3953 alt {
3954 [] SGsAP.receive(exp_resp) {
3955 setverdict(pass);
3956 }
3957 [] SGsAP.receive {
3958 setverdict(fail, "Received unexpected message on SGs");
3959 }
3960 }
3961
3962 /* Now reject the paging */
3963 SGsAP.send(ts_SGsAP_PAGING_REJ(g_pars.imsi, IMSI_unknown));
3964
3965 /* Wait for the states inside the MSC to settle and check the state
3966 * of the SGs Association */
3967 f_sleep(1.0);
3968 f_ctrl_get_exp(IPA_CTRL, "fsm.SGs-UE.id.imsi:" & hex2str(g_pars.imsi) & ".state", "SGs-NULL");
3969
3970 /* FIXME: At the moment we send an IMSI_unknown as cause code, which is fine,
3971 * but we also need to cover tha case where the cause code indicates an
3972 * "IMSI detached for EPS services". In those cases the VLR is expected to
3973 * try paging on tha A/Iu interface. This will be another testcase similar to
3974 * this one, but extended with checks for the presence of the A/Iu paging
3975 * messages. */
3976
3977 f_sgsap_bssmap_screening();
3978
3979 setverdict(pass);
3980}
3981testcase TC_sgsap_paging_rej() runs on MTC_CT {
Philipp Maier8e07a4a2019-02-14 18:23:28 +01003982 var BSC_ConnHdlrPars pars;
Harald Welte4263c522018-12-06 11:56:27 +01003983 var BSC_ConnHdlr vc_conn;
Philipp Maier8e07a4a2019-02-14 18:23:28 +01003984 f_init(1, true);
3985 pars := f_init_pars(11816, true);
3986 vc_conn := f_start_handler_with_pars(refers(f_tc_sgsap_paging_rej), pars);
Harald Welte4263c522018-12-06 11:56:27 +01003987 vc_conn.done;
3988}
3989
3990/* Trigger a paging request via VTY and send a paging reject that indicates
3991 * that the subscriber intentionally rejected the call. */
3992private function f_tc_sgsap_paging_subscr_rej(charstring id, BSC_ConnHdlrPars pars)
3993runs on BSC_ConnHdlr {
3994 f_init_handler(pars);
3995 f_sgs_perform_lu();
3996 f_sleep(1.0);
3997
3998 var octetstring vlr_name := f_enc_dns_hostname(mp_vlr_name);
3999 var template PDU_SGsAP exp_resp := tr_SGsAP_PAGING_REQ(g_pars.imsi, vlr_name, CS_call_indicator, omit);
4000 var template LocationAreaId exp_lai := ts_SGsAP_IE_Lai(valueof(ts_SGsAP_LAI('901'H, '70'H, 2342)));
4001 exp_resp.sGsAP_PAGING_REQUEST.locationAreaId := exp_lai;
4002
4003 /* Initiate paging via VTY */
4004 f_vty_transceive(MSCVTY, "subscriber imsi " & hex2str(g_pars.imsi) & " paging");
4005 alt {
4006 [] SGsAP.receive(exp_resp) {
4007 setverdict(pass);
4008 }
4009 [] SGsAP.receive {
4010 setverdict(fail, "Received unexpected message on SGs");
4011 }
4012 }
4013
4014 /* Now reject the paging */
4015 SGsAP.send(ts_SGsAP_PAGING_REJ(g_pars.imsi, user_rejected_mobile_terminating_CS_fallback_call));
4016
4017 /* Wait for the states inside the MSC to settle and check the state
4018 * of the SGs Association */
4019 f_sleep(1.0);
4020 f_ctrl_get_exp(IPA_CTRL, "fsm.SGs-UE.id.imsi:" & hex2str(g_pars.imsi) & ".state", "SGs-ASSOCIATED");
4021
4022 /* FIXME: The VLR is supposed to trigger an User Determined User Busy (UDUB) as specified
4023 * in 3GPP TS 24.082, this is not yet implemented in the MSC or in this tests, we need
4024 * to check back how this works and how it can be tested */
4025
4026 f_sgsap_bssmap_screening();
4027
4028 setverdict(pass);
4029}
4030testcase TC_sgsap_paging_subscr_rej() runs on MTC_CT {
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004031 var BSC_ConnHdlrPars pars;
Harald Welte4263c522018-12-06 11:56:27 +01004032 var BSC_ConnHdlr vc_conn;
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004033 f_init(1, true);
4034 pars := f_init_pars(11817, true);
4035 vc_conn := f_start_handler_with_pars(refers(f_tc_sgsap_paging_subscr_rej), pars);
Harald Welte4263c522018-12-06 11:56:27 +01004036 vc_conn.done;
4037}
4038
4039/* Trigger a paging request via VTY and send an UE unreacable messge in response */
4040private function f_tc_sgsap_paging_ue_unr(charstring id, BSC_ConnHdlrPars pars)
4041runs on BSC_ConnHdlr {
4042 f_init_handler(pars);
4043 f_sgs_perform_lu();
4044 f_sleep(1.0);
4045
4046 var octetstring vlr_name := f_enc_dns_hostname(mp_vlr_name);
4047 var template PDU_SGsAP exp_resp := tr_SGsAP_PAGING_REQ(g_pars.imsi, vlr_name, CS_call_indicator, omit);
4048 var template LocationAreaId exp_lai := ts_SGsAP_IE_Lai(valueof(ts_SGsAP_LAI('901'H, '70'H, 2342)));
4049 exp_resp.sGsAP_PAGING_REQUEST.locationAreaId := exp_lai;
4050
4051 /* Initiate paging via VTY */
4052 f_vty_transceive(MSCVTY, "subscriber imsi " & hex2str(g_pars.imsi) & " paging");
4053 alt {
4054 [] SGsAP.receive(exp_resp) {
4055 setverdict(pass);
4056 }
4057 [] SGsAP.receive {
4058 setverdict(fail, "Received unexpected message on SGs");
4059 }
4060 }
4061
4062 /* Now pretend that the UE is unreachable */
4063 SGsAP.send(ts_SGsAP_UE_UNREACHABLE(g_pars.imsi, UE_unreachable));
4064
4065 /* Wait for the states inside the MSC to settle and check the state
4066 * of the SGs Association. */
4067 f_sleep(1.0);
4068 f_ctrl_get_exp(IPA_CTRL, "fsm.SGs-UE.id.imsi:" & hex2str(g_pars.imsi) & ".state", "SGs-ASSOCIATED");
4069
4070 f_sgsap_bssmap_screening();
4071
4072 setverdict(pass);
4073}
4074testcase TC_sgsap_paging_ue_unr() runs on MTC_CT {
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004075 var BSC_ConnHdlrPars pars;
Harald Welte4263c522018-12-06 11:56:27 +01004076 var BSC_ConnHdlr vc_conn;
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004077 f_init(1, true);
4078 pars := f_init_pars(11818, true);
4079 vc_conn := f_start_handler_with_pars(refers(f_tc_sgsap_paging_ue_unr), pars);
Harald Welte4263c522018-12-06 11:56:27 +01004080 vc_conn.done;
4081}
4082
4083/* Trigger a paging request via VTY but don't respond to it */
4084private function f_tc_sgsap_paging_and_nothing(charstring id, BSC_ConnHdlrPars pars)
4085runs on BSC_ConnHdlr {
4086 f_init_handler(pars);
4087 f_sgs_perform_lu();
4088 f_sleep(1.0);
4089
4090 var octetstring vlr_name := f_enc_dns_hostname(mp_vlr_name);
4091 var template PDU_SGsAP exp_resp := tr_SGsAP_PAGING_REQ(g_pars.imsi, vlr_name, CS_call_indicator, omit);
4092 var template LocationAreaId exp_lai := ts_SGsAP_IE_Lai(valueof(ts_SGsAP_LAI('901'H, '70'H, 2342)));
4093 exp_resp.sGsAP_PAGING_REQUEST.locationAreaId := exp_lai;
4094
4095 /* Initiate paging via VTY */
4096 f_vty_transceive(MSCVTY, "subscriber imsi " & hex2str(g_pars.imsi) & " paging");
4097 alt {
4098 [] SGsAP.receive(exp_resp) {
4099 setverdict(pass);
4100 }
4101 [] SGsAP.receive {
4102 setverdict(fail, "Received unexpected message on SGs");
4103 }
4104 }
4105
4106 /* Now do nothing, the MSC/VLR should fail silently to page after a
4107 * few seconds, The SGs association must remain unchanged. */
4108 f_sleep(15.0);
4109 f_ctrl_get_exp(IPA_CTRL, "fsm.SGs-UE.id.imsi:" & hex2str(g_pars.imsi) & ".state", "SGs-ASSOCIATED");
4110
4111 f_sgsap_bssmap_screening();
4112
4113 setverdict(pass);
4114}
4115testcase TC_sgsap_paging_and_nothing() runs on MTC_CT {
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004116 var BSC_ConnHdlrPars pars;
Harald Welte4263c522018-12-06 11:56:27 +01004117 var BSC_ConnHdlr vc_conn;
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004118 f_init(1, true);
4119 pars := f_init_pars(11819, true);
4120 vc_conn := f_start_handler_with_pars(refers(f_tc_sgsap_paging_and_nothing), pars);
Harald Welte4263c522018-12-06 11:56:27 +01004121 vc_conn.done;
4122}
4123
4124/* Trigger a paging request via VTY and slip in an LU */
4125private function f_tc_sgsap_paging_and_lu(charstring id, BSC_ConnHdlrPars pars)
4126runs on BSC_ConnHdlr {
4127 var octetstring vlr_name := f_enc_dns_hostname(mp_vlr_name);
4128 f_init_handler(pars);
4129
4130 /* First we prepar the situation, where the SGs association is in state
4131 * NULL and the confirmed by radio contact indicator is set to false
4132 * as well. This can be archived by performing an SGs LU and then
4133 * resetting the VLR */
4134 f_sgs_perform_lu();
4135 f_sgsap_reset_mme(mp_mme_name);
4136 f_sleep(1.0);
4137 f_ctrl_get_exp(IPA_CTRL, "fsm.SGs-UE.id.imsi:" & hex2str(g_pars.imsi) & ".state", "SGs-NULL");
4138
4139 /* Perform a paging, expect the paging messages on the SGs interface */
4140 f_vty_transceive(MSCVTY, "subscriber imsi " & hex2str(g_pars.imsi) & " paging");
4141 alt {
4142 [] SGsAP.receive(tr_SGsAP_PAGING_REQ(pars.imsi, vlr_name, CS_call_indicator, omit)) {
4143 setverdict(pass);
4144 }
4145 [] SGsAP.receive {
4146 setverdict(fail, "Received unexpected message on SGs");
4147 }
4148 }
4149
4150 /* Perform the LU as normal */
4151 f_sgs_perform_lu();
4152 f_ctrl_get_exp(IPA_CTRL, "fsm.SGs-UE.id.imsi:" & hex2str(g_pars.imsi) & ".state", "SGs-ASSOCIATED");
4153
4154 /* Expect a new paging request right after the LU */
4155 alt {
4156 [] SGsAP.receive(tr_SGsAP_PAGING_REQ(pars.imsi, vlr_name, CS_call_indicator, omit)) {
4157 setverdict(pass);
4158 }
4159 [] SGsAP.receive {
4160 setverdict(fail, "Received unexpected message on SGs");
4161 }
4162 }
4163
4164 /* Test is done now, lets round everything up by rejecting the paging
4165 * cleanly. */
4166 SGsAP.send(ts_SGsAP_PAGING_REJ(g_pars.imsi, user_rejected_mobile_terminating_CS_fallback_call));
4167 f_ctrl_get_exp(IPA_CTRL, "fsm.SGs-UE.id.imsi:" & hex2str(g_pars.imsi) & ".state", "SGs-ASSOCIATED");
4168
4169 f_sgsap_bssmap_screening();
4170
4171 setverdict(pass);
4172}
4173testcase TC_sgsap_paging_and_lu() runs on MTC_CT {
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004174 var BSC_ConnHdlrPars pars;
Harald Welte4263c522018-12-06 11:56:27 +01004175 var BSC_ConnHdlr vc_conn;
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004176 f_init(1, true);
4177 pars := f_init_pars(11820, true);
4178 vc_conn := f_start_handler_with_pars(refers(f_tc_sgsap_paging_and_lu), pars);
Harald Welte4263c522018-12-06 11:56:27 +01004179 vc_conn.done;
4180}
4181
4182/* Send unexpected unit-data through the SGs interface */
4183private function f_tc_sgsap_unexp_ud(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
4184 f_init_handler(pars);
4185 f_sleep(1.0);
4186
4187 /* This simulates what happens when a subscriber without SGs
4188 * association gets unitdata via the SGs interface. */
4189
4190 /* Make sure the subscriber exists and the SGs association
4191 * is in NULL state */
4192 f_perform_lu();
4193 f_ctrl_get_exp(IPA_CTRL, "fsm.SGs-UE.id.imsi:" & hex2str(g_pars.imsi) & ".state", "SGs-NULL");
4194
4195 /* Send some random unit data, the MSC/VLR should send a release
4196 * immediately. */
4197 SGsAP.send(ts_SGsAP_UL_UD(pars.imsi,'1234'O));
4198 SGsAP.receive(tr_SGsAP_RELEASE_REQ(pars.imsi, IMSI_detached_for_EPS_nonEPS_services));
4199
4200 f_sgsap_bssmap_screening();
4201
4202 setverdict(pass);
4203}
4204testcase TC_sgsap_unexp_ud() runs on MTC_CT {
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004205 var BSC_ConnHdlrPars pars;
Harald Welte4263c522018-12-06 11:56:27 +01004206 var BSC_ConnHdlr vc_conn;
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004207 f_init(1, true);
4208 pars := f_init_pars(11821, true);
4209 vc_conn := f_start_handler_with_pars(refers(f_tc_sgsap_unexp_ud), pars);
Harald Welte4263c522018-12-06 11:56:27 +01004210 vc_conn.done;
4211}
4212
4213/* Send unsolicited unit-data through the SGs interface */
4214private function f_tc_sgsap_unsol_ud(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
4215 f_init_handler(pars);
4216 f_sleep(1.0);
4217
4218 /* This simulates what happens when the MME attempts to send unitdata
4219 * to a subscriber that is completely unknown to the VLR */
4220
4221 /* Send some random unit data, the MSC/VLR should send a release
4222 * immediately. */
4223 SGsAP.send(ts_SGsAP_UL_UD(pars.imsi,'1234'O));
4224 SGsAP.receive(tr_SGsAP_RELEASE_REQ(pars.imsi, IMSI_unknown));
4225
4226 f_sgsap_bssmap_screening();
4227
4228 setverdict(pass);
4229}
4230testcase TC_sgsap_unsol_ud() runs on MTC_CT {
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004231 var BSC_ConnHdlrPars pars;
Harald Welte4263c522018-12-06 11:56:27 +01004232 var BSC_ConnHdlr vc_conn;
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004233 f_init(1, true);
4234 pars := f_init_pars(11822, true);
4235 vc_conn := f_start_handler_with_pars(refers(f_tc_sgsap_unsol_ud), pars);
Harald Welte4263c522018-12-06 11:56:27 +01004236 vc_conn.done;
4237}
4238
4239private altstep as_other_sms_sgs() runs on BSC_ConnHdlr {
4240 /* FIXME: Match an actual payload (second questionmark), the type is
4241 * octetstring, how do we use a tr_PDU_DTAP_MT here? */
4242 [] SGsAP.receive(tr_SGsAP_DL_UD(?,?)) {
4243 setverdict(fail, "Unexpected SMS related PDU from MSC");
4244 mtc.stop;
4245 }
4246}
4247
4248/* receive a MT-SMS delivered from the MSC/SMSC over an already existing SGsAP connection */
4249function f_mt_sms_sgs(inout SmsParameters spars)
4250runs on BSC_ConnHdlr {
4251 var template (value) TPDU_RP_DATA_MS_SGSN tp_mo;
4252 var template (value) RPDU_MS_SGSN rp_mo;
4253 var template (value) PDU_ML3_MS_NW l3_mo;
4254
4255 var template TPDU_RP_DATA_SGSN_MS tp_mt;
4256 var template RPDU_SGSN_MS rp_mt;
4257 var template PDU_ML3_NW_MS l3_mt;
4258
4259 var PDU_ML3_NW_MS sgsap_l3_mt;
4260
4261 var default d := activate(as_other_sms_sgs());
4262
4263 /* Expect CP-DATA(RP-DATA(SMS-DELIVER)) */
4264 tp_mt := tr_SMS_DELIVER(?, spars.tp.ud, spars.tp.pid, spars.tp.dcs, ?);
4265 rp_mt := tr_RP_DATA_MT(?, ?, omit, tp_mt);
4266 l3_mt := tr_ML3_MT_SMS(?, c_TIF_ORIG, tr_CP_DATA_MT(rp_mt));
4267
4268 SGsAP.receive(l3_mt) -> value sgsap_l3_mt;
4269
4270 /* Extract relevant identifiers */
4271 spars.tid := bit2int(sgsap_l3_mt.tiOrSkip.transactionId.tio);
4272 spars.rp.msg_ref := sgsap_l3_mt.msgs.sms.cP_DATA.cP_User_Data.cP_RPDU.rP_DATA_SGSN_MS.rP_MessageReference;
4273
4274 /* send CP-ACK for CP-DATA just received */
4275 l3_mo := ts_ML3_MO_SMS(spars.tid, c_TIF_REPL, ts_CP_ACK_MO);
4276
4277 SGsAP.send(l3_mo);
4278
4279 /* send RP-ACK for RP-DATA */
4280 rp_mo := ts_RP_ACK_MO(spars.rp.msg_ref);
4281 l3_mo := ts_ML3_MO_SMS(spars.tid, c_TIF_REPL, ts_CP_DATA_MO(rp_mo));
4282
4283 SGsAP.send(l3_mo);
4284
4285 /* expect CP-ACK for CP-DATA(RP-ACK) just sent */
4286 l3_mt := tr_ML3_MT_SMS(spars.tid, c_TIF_ORIG, tr_CP_ACK_MT);
4287
4288 SGsAP.receive(l3_mt);
4289
4290 deactivate(d);
4291
4292 setverdict(pass);
4293}
4294
4295/* submit a MO-SMS to MSC/SMSC over an already existing SGsAP connection */
4296function f_mo_sms_sgs(inout SmsParameters spars)
4297runs on BSC_ConnHdlr {
4298 var template (value) TPDU_RP_DATA_MS_SGSN tp_mo;
4299 var template (value) RPDU_MS_SGSN rp_mo;
4300 var template (value) PDU_ML3_MS_NW l3_mo;
4301
4302 var template TPDU_RP_DATA_SGSN_MS tp_mt;
4303 var template RPDU_SGSN_MS rp_mt;
4304 var template PDU_ML3_NW_MS l3_mt;
4305
4306 var default d := activate(as_other_sms_sgs());
4307
4308 /* just in case this is routed to SMPP.. */
4309 f_create_smpp_expect(hex2str(spars.tp.da.tP_DA_NoPad.tP_DAValue));
4310
4311 tp_mo := ts_SMS_SUBMIT(spars.tp.msg_ref, spars.tp.da, spars.tp.pid, spars.tp.dcs,
4312 spars.tp.udl, spars.tp.ud);
4313 rp_mo := ts_RP_DATA_MO(spars.rp.msg_ref, spars.rp.orig, spars.rp.dest, tp_mo);
4314 l3_mo := ts_ML3_MO_SMS(spars.tid, c_TIF_ORIG, ts_CP_DATA_MO(rp_mo));
4315
4316 SGsAP.send(l3_mo);
4317
4318 /* receive CP-ACK for CP-DATA above */
4319 SGsAP.receive(tr_ML3_MT_SMS(spars.tid, c_TIF_REPL, tr_CP_ACK_MT));
4320
4321 if (ispresent(spars.exp_rp_err)) {
4322 /* expect an RP-ERROR message from MSC with given cause */
4323 rp_mt := tr_RP_ERROR_MT(spars.rp.msg_ref, spars.exp_rp_err);
4324 l3_mt := tr_ML3_MT_SMS(spars.tid, c_TIF_REPL, tr_CP_DATA_MT(rp_mt));
4325 SGsAP.receive(l3_mt);
4326 /* send CP-ACK for CP-DATA just received */
4327 l3_mo := ts_ML3_MO_SMS(spars.tid, c_TIF_ORIG, ts_CP_ACK_MO);
4328 SGsAP.send(l3_mo);
4329 } else {
4330 /* expect RP-ACK for RP-DATA */
4331 rp_mt := tr_RP_ACK_MT(spars.rp.msg_ref);
4332 l3_mt := tr_ML3_MT_SMS(spars.tid, c_TIF_REPL, tr_CP_DATA_MT(rp_mt));
4333 SGsAP.receive(l3_mt);
4334 /* send CP-ACO for CP-DATA just received */
4335 l3_mo := ts_ML3_MO_SMS(spars.tid, c_TIF_ORIG, ts_CP_ACK_MO);
4336 SGsAP.send(l3_mo);
4337 }
4338
4339 deactivate(d);
4340
4341 setverdict(pass);
4342}
4343
4344private function f_vty_sms_send_conn_hdlr(charstring imsi, charstring msisdn, charstring text)
4345runs on BSC_ConnHdlr {
4346 f_vty_transceive(MSCVTY, "subscriber imsi "&imsi&" sms sender msisdn "&msisdn&" send "&text);
4347}
4348
4349/* Send a MT SMS via SGs interface */
4350private function f_tc_sgsap_mt_sms(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
4351 f_init_handler(pars);
4352 f_sgs_perform_lu();
4353 f_sleep(1.0);
4354 var SmsParameters spars := valueof(t_SmsPars);
4355 spars.tp.ud := 'C8329BFD064D9B53'O;
4356
4357 /* Trigger SMS via VTY */
4358 f_vty_sms_send_conn_hdlr(hex2str(pars.imsi), "2342", "Hello SMS");
4359 var octetstring vlr_name := f_enc_dns_hostname(mp_vlr_name);
4360
4361 /* Expect a paging request and respond accordingly with a service request */
4362 SGsAP.receive(tr_SGsAP_PAGING_REQ(pars.imsi, vlr_name, SMS_indicator, omit));
4363 SGsAP.send(ts_SGsAP_SERVICE_REQ(pars.imsi, SMS_indicator, EMM_CONNECTED));
4364
4365 /* Connection is now live, receive the MT-SMS */
4366 f_mt_sms_sgs(spars);
4367
4368 /* Expect a concluding release from the MSC */
4369 SGsAP.receive(tr_SGsAP_RELEASE_REQ(pars.imsi, omit));
4370
4371 /* Make sure that subscriber is still present and the SGs association is in tact (ref-counting) */
4372 f_ctrl_get_exp(IPA_CTRL, "fsm.SGs-UE.id.imsi:" & hex2str(g_pars.imsi) & ".state", "SGs-ASSOCIATED");
4373
4374 f_sgsap_bssmap_screening();
4375
4376 setverdict(pass);
4377}
4378testcase TC_sgsap_mt_sms() runs on MTC_CT {
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004379 var BSC_ConnHdlrPars pars;
Harald Welte4263c522018-12-06 11:56:27 +01004380 var BSC_ConnHdlr vc_conn;
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004381 f_init(1, true);
4382 pars := f_init_pars(11823, true);
4383 vc_conn := f_start_handler_with_pars(refers(f_tc_sgsap_mt_sms), pars);
Harald Welte4263c522018-12-06 11:56:27 +01004384 vc_conn.done;
4385}
4386
4387/* Send a MO SMS via SGs interface */
4388private function f_tc_sgsap_mo_sms(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
4389 f_init_handler(pars);
4390 f_sgs_perform_lu();
4391 f_sleep(1.0);
4392 var SmsParameters spars := valueof(t_SmsPars);
4393 spars.tp.ud := 'C8329BFD064D9B53'O;
4394
4395 /* Send the MO-SMS */
4396 f_mo_sms_sgs(spars);
4397
4398 /* Expect a concluding release from the MSC/VLR */
4399 SGsAP.receive(tr_SGsAP_RELEASE_REQ(pars.imsi, omit));
4400
4401 /* Make sure that subscriber is still present and the SGs association is in tact (ref-counting) */
4402 f_ctrl_get_exp(IPA_CTRL, "fsm.SGs-UE.id.imsi:" & hex2str(g_pars.imsi) & ".state", "SGs-ASSOCIATED");
4403
4404 setverdict(pass);
4405
4406 f_sgsap_bssmap_screening()
4407}
4408testcase TC_sgsap_mo_sms() runs on MTC_CT {
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004409 var BSC_ConnHdlrPars pars;
Harald Welte4263c522018-12-06 11:56:27 +01004410 var BSC_ConnHdlr vc_conn;
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004411 f_init(1, true);
4412 pars := f_init_pars(11824, true);
4413 vc_conn := f_start_handler_with_pars(refers(f_tc_sgsap_mo_sms), pars);
Harald Welte4263c522018-12-06 11:56:27 +01004414 vc_conn.done;
4415}
4416
4417/* Trigger sending of an MT sms via VTY but never respond to anything */
4418private function f_tc_sgsap_mt_sms_and_nothing(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
4419 f_init_handler(pars, 170.0);
4420 f_sgs_perform_lu();
4421 f_sleep(1.0);
4422
4423 var SmsParameters spars := valueof(t_SmsPars);
4424 spars.tp.ud := 'C8329BFD064D9B53'O;
4425 var integer page_count := 0;
4426 var octetstring vlr_name := f_enc_dns_hostname(mp_vlr_name);
4427 var template PDU_SGsAP exp_pag_req := tr_SGsAP_PAGING_REQ(g_pars.imsi, vlr_name, SMS_indicator, omit);
4428 var template LocationAreaId exp_lai := ts_SGsAP_IE_Lai(valueof(ts_SGsAP_LAI('901'H, '70'H, 2342)));
4429 exp_pag_req.sGsAP_PAGING_REQUEST.locationAreaId := exp_lai;
4430
4431 /* Trigger SMS via VTY */
4432 f_vty_sms_send_conn_hdlr(hex2str(pars.imsi), "2342", "Hello SMS");
4433
Neels Hofmeyr16237742019-03-06 15:34:01 +01004434 /* Expect the MSC/VLR to page exactly once */
4435 SGsAP.receive(exp_pag_req);
Harald Welte4263c522018-12-06 11:56:27 +01004436
4437 /* Wait some time to make sure the MSC is not delivering any further
4438 * paging messages or anything else that could be unexpected. */
4439 timer T := 20.0;
4440 T.start
4441 alt {
4442 [] SGsAP.receive(exp_pag_req)
4443 {
4444 setverdict(fail, "paging seems not to stop!");
4445 mtc.stop;
4446 }
4447 [] SGsAP.receive {
4448 setverdict(fail, "unexpected SGsAP message received");
4449 self.stop;
4450 }
4451 [] T.timeout {
4452 setverdict(pass);
4453 }
4454 }
4455
4456 /* Even on a failed paging the SGs Association should stay intact */
4457 f_ctrl_get_exp(IPA_CTRL, "fsm.SGs-UE.id.imsi:" & hex2str(g_pars.imsi) & ".state", "SGs-ASSOCIATED");
4458
4459 /* Note: We do not execute f_sgsap_bssmap_screening() here since the
4460 * MSC/VLR would re-try to deliver the test SMS trigered above and
4461 * so the screening would fail. */
4462
Neels Hofmeyr8256ed22019-03-06 15:34:01 +01004463 f_vty_sms_clear(hex2str(g_pars.imsi));
4464
Harald Welte4263c522018-12-06 11:56:27 +01004465 f_vty_transceive(MSCVTY, "subscriber imsi " & hex2str(g_pars.imsi) & " expire");
4466
4467 setverdict(pass);
Neels Hofmeyrb0f82342019-03-06 15:36:51 +01004468
4469 f_sgsap_bssmap_screening();
Harald Welte4263c522018-12-06 11:56:27 +01004470}
4471testcase TC_sgsap_mt_sms_and_nothing() runs on MTC_CT {
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004472 var BSC_ConnHdlrPars pars;
Harald Welte4263c522018-12-06 11:56:27 +01004473 var BSC_ConnHdlr vc_conn;
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004474 f_init(1, true);
4475 pars := f_init_pars(11825, true);
4476 vc_conn := f_start_handler_with_pars(refers(f_tc_sgsap_mt_sms_and_nothing), pars);
Harald Welte4263c522018-12-06 11:56:27 +01004477 vc_conn.done;
4478}
4479
4480/* Trigger sending of an MT sms via VTY but reject the paging immediately */
4481private function f_tc_sgsap_mt_sms_and_reject(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
4482 f_init_handler(pars, 150.0);
4483 f_sgs_perform_lu();
4484 f_sleep(1.0);
4485
4486 var SmsParameters spars := valueof(t_SmsPars);
4487 spars.tp.ud := 'C8329BFD064D9B53'O;
4488 var integer page_count := 0;
4489 var octetstring vlr_name := f_enc_dns_hostname(mp_vlr_name);
4490 var template PDU_SGsAP exp_pag_req := tr_SGsAP_PAGING_REQ(g_pars.imsi, vlr_name, SMS_indicator, omit);
4491 var template LocationAreaId exp_lai := ts_SGsAP_IE_Lai(valueof(ts_SGsAP_LAI('901'H, '70'H, 2342)));
4492 exp_pag_req.sGsAP_PAGING_REQUEST.locationAreaId := exp_lai;
4493
4494 /* Trigger SMS via VTY */
4495 f_vty_sms_send_conn_hdlr(hex2str(pars.imsi), "2342", "Hello SMS");
4496
4497 /* Expect a paging request and reject it immediately */
4498 SGsAP.receive(exp_pag_req);
4499 SGsAP.send(ts_SGsAP_PAGING_REJ(g_pars.imsi, IMSI_unknown));
4500
4501 /* The MSC/VLR should no longer try to page once the paging has been
4502 * rejected. Wait some time and check if there are no unexpected
4503 * messages on the SGs interface. */
4504 timer T := 20.0;
4505 T.start
4506 alt {
4507 [] SGsAP.receive(exp_pag_req)
4508 {
4509 setverdict(fail, "paging seems not to stop!");
4510 mtc.stop;
4511 }
4512 [] SGsAP.receive {
4513 setverdict(fail, "unexpected SGsAP message received");
4514 self.stop;
4515 }
4516 [] T.timeout {
4517 setverdict(pass);
4518 }
4519 }
4520
Neels Hofmeyr8256ed22019-03-06 15:34:01 +01004521 f_vty_sms_clear(hex2str(g_pars.imsi));
4522
Harald Welte4263c522018-12-06 11:56:27 +01004523 /* A rejected paging with IMSI_unknown (see above) should always send
4524 * the SGs association to NULL. */
4525 f_ctrl_get_exp(IPA_CTRL, "fsm.SGs-UE.id.imsi:" & hex2str(g_pars.imsi) & ".state", "SGs-NULL");
4526
4527 f_sgsap_bssmap_screening();
4528
Harald Welte4263c522018-12-06 11:56:27 +01004529 setverdict(pass);
4530}
4531testcase TC_sgsap_mt_sms_and_reject() runs on MTC_CT {
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004532 var BSC_ConnHdlrPars pars;
Harald Welte4263c522018-12-06 11:56:27 +01004533 var BSC_ConnHdlr vc_conn;
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004534 f_init(1, true);
4535 pars := f_init_pars(11826, true);
4536 vc_conn := f_start_handler_with_pars(refers(f_tc_sgsap_mt_sms_and_reject), pars);
Harald Welte4263c522018-12-06 11:56:27 +01004537 vc_conn.done;
4538}
4539
4540/* Perform an MT CSDB call including LU */
4541private function f_mt_lu_and_csfb_call(charstring id, BSC_ConnHdlrPars pars, boolean bssmap_lu) runs on BSC_ConnHdlr {
4542 f_init_handler(pars);
4543
4544 /* Be sure that the BSSMAP reset is done before we begin. */
4545 f_sleep(2.0);
4546
4547 /* Testcase variation: See what happens when we do a regular BSSMAP
4548 * LU first (this should not hurt in any way!) */
4549 if (bssmap_lu) {
4550 f_perform_lu();
4551 }
4552
4553 f_sgs_perform_lu();
4554 f_sleep(1.0);
4555
4556 var octetstring vlr_name := f_enc_dns_hostname(mp_vlr_name);
4557 var CallParameters cpars := valueof(t_CallParams('12345'H, 0));
4558 cpars.bss_rtp_port := 1110;
4559 cpars.mgcp_connection_id_bss := '10004'H;
4560 cpars.mgcp_connection_id_mss := '10005'H;
4561
4562 /* Note: This is an optional parameter. When the call-agent (MSC) does
4563 * supply a full endpoint name this setting will be overwritten. */
4564 cpars.mgcp_ep := "rtpbridge/1@mgw";
4565
4566 /* Initiate a call via MNCC interface */
4567 f_mt_call_initate(cpars);
4568
4569 /* Expect a paging request and respond accordingly with a service request */
4570 SGsAP.receive(tr_SGsAP_PAGING_REQ(pars.imsi, vlr_name, CS_call_indicator, omit));
4571 SGsAP.send(ts_SGsAP_SERVICE_REQ(pars.imsi, CS_call_indicator, EMM_CONNECTED));
4572
4573 /* Complete the call, hold it for some time and then tear it down */
4574 f_mt_call_complete(cpars);
4575 f_sleep(3.0);
Harald Welte4c422b72019-02-17 16:27:10 +01004576 f_call_hangup(cpars, true, is_csfb := true);
Harald Welte4263c522018-12-06 11:56:27 +01004577
4578 /* Make sure that subscriber is still present and the SGs association is in tact (ref-counting) */
4579 f_ctrl_get_exp(IPA_CTRL, "fsm.SGs-UE.id.imsi:" & hex2str(g_pars.imsi) & ".state", "SGs-ASSOCIATED");
4580
4581 /* Finally simulate the return of the UE to the 4G network */
4582 SGsAP.send(ts_SGsAP_MO_CSFB_IND(pars.imsi));
4583
4584 /* Test for successful return by triggering a paging, when the paging
4585 * request is received via SGs, we can be sure that the MSC/VLR has
4586 * recognized that the UE is now back on 4G */
4587 f_sleep(1.0);
4588 f_vty_transceive(MSCVTY, "subscriber imsi " & hex2str(g_pars.imsi) & " paging");
4589 alt {
4590 [] SGsAP.receive(tr_SGsAP_PAGING_REQ(pars.imsi, vlr_name, CS_call_indicator, omit)) {
4591 setverdict(pass);
4592 }
4593 [] SGsAP.receive {
4594 setverdict(fail, "Received unexpected message on SGs");
4595 }
4596 }
4597
4598 f_sgsap_bssmap_screening();
4599
4600 setverdict(pass);
4601}
4602
4603/* Perform a regular BSSAP LU first, do a SGSAP LU and then make a CSFB call */
4604private function f_tc_bssap_lu_sgsap_lu_and_mt_call(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
4605 f_mt_lu_and_csfb_call(id, pars, true);
4606}
4607testcase TC_bssap_lu_sgsap_lu_and_mt_call() runs on MTC_CT {
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004608 var BSC_ConnHdlrPars pars;
Harald Welte4263c522018-12-06 11:56:27 +01004609 var BSC_ConnHdlr vc_conn;
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004610 f_init(1, true);
4611 pars := f_init_pars(118139, true);
Harald Welte4263c522018-12-06 11:56:27 +01004612
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004613 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 +01004614 vc_conn.done;
4615}
4616
4617
4618/* Perform a SGSAP LU and then make a CSFB call */
4619private function f_tc_sgsap_lu_and_mt_call(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
4620 f_mt_lu_and_csfb_call(id, pars, false);
4621}
4622testcase TC_sgsap_lu_and_mt_call() 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(11827, true);
Harald Welte4263c522018-12-06 11:56:27 +01004627
Philipp Maier8e07a4a2019-02-14 18:23:28 +01004628 vc_conn := f_start_handler_with_pars(refers(f_tc_sgsap_lu_and_mt_call), pars);
Harald Welte4263c522018-12-06 11:56:27 +01004629 vc_conn.done;
4630}
4631
Philipp Maier628c0052019-04-09 17:36:57 +02004632/* Simulate an HLR/VLR failure */
4633private function f_tc_sgsap_vlr_failure(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
4634 var octetstring mme_name := f_enc_dns_hostname(mp_mme_name);
4635 var octetstring vlr_name := f_enc_dns_hostname(mp_vlr_name);
4636
4637 var PDU_SGsAP lur;
4638
4639 f_init_handler(pars);
4640
4641 /* Attempt location update (which is expected to fail) */
4642 lur := valueof(ts_SGsAP_LU_REQ(g_pars.imsi, mme_name, IMSI_attach,
4643 ts_SGsAP_LAI('901'H, '70'H, 2342)));
4644 SGsAP.send(lur);
4645
4646 /* Respond to SGsAP-RESET-INDICATION from VLR */
4647 alt {
4648 [] SGsAP.receive(tr_SGsAP_RESET_IND_VLR(vlr_name)); {
4649 SGsAP.send(valueof(ts_SGsAP_RESET_ACK_MME(mme_name)));
4650 setverdict(pass);
4651 }
4652 [] SGsAP.receive {
4653 setverdict(fail, "Received unexpected message on SGs");
4654 }
4655 }
4656
4657 f_sleep(1.0);
4658 setverdict(pass);
4659}
4660testcase TC_sgsap_vlr_failure() runs on MTC_CT {
4661 var BSC_ConnHdlrPars pars;
4662 var BSC_ConnHdlr vc_conn;
4663 f_init(1, true, false);
4664 pars := f_init_pars(11811, true, false);
4665 vc_conn := f_start_handler_with_pars(refers(f_tc_sgsap_vlr_failure), pars);
4666 vc_conn.done;
4667}
4668
Harald Welte4263c522018-12-06 11:56:27 +01004669/* SGs TODO:
4670 * LU attempt for IMSI without NAM_PS in HLR
4671 * LU attempt with AUTH FAIL due to invalid RES/SRES
4672 * LU attempt with no response from HLR (VLR should timeout + LU REJ)
4673 * LU attempt with new TMSI but without TMSI REALL CMPL baco to VLR
4674 * implicit IMSI detach from EPS
4675 * implicit IMSI detach from non-EPS
4676 * MM INFO
4677 *
4678 */
Harald Weltef6dd64d2017-11-19 12:09:51 +01004679
4680control {
Philipp Maier328d1662018-03-07 10:40:27 +01004681 execute( TC_cr_before_reset() );
Harald Weltea49e36e2018-01-21 19:29:33 +01004682 execute( TC_lu_imsi_noauth_tmsi() );
Harald Welted2328a22018-01-27 14:27:16 +01004683 execute( TC_lu_imsi_noauth_notmsi() );
Harald Weltea49e36e2018-01-21 19:29:33 +01004684 execute( TC_lu_imsi_reject() );
4685 execute( TC_lu_imsi_timeout_gsup() );
Harald Welted2328a22018-01-27 14:27:16 +01004686 execute( TC_lu_imsi_auth_tmsi() );
Harald Welte8a397ae2019-04-21 22:03:37 +02004687 execute( TC_lu_imsi_auth3g_tmsi() );
Harald Welted2328a22018-01-27 14:27:16 +01004688 execute( TC_cmserv_imsi_unknown() );
Harald Welte2bb825f2018-01-22 11:31:18 +01004689 execute( TC_lu_and_mo_call() );
Harald Welte071ed732018-01-23 19:53:52 +01004690 execute( TC_lu_auth_sai_timeout() );
4691 execute( TC_lu_auth_sai_err() );
Harald Weltee1a2f3c2018-01-24 17:28:48 +01004692 execute( TC_lu_clear_request() );
4693 execute( TC_lu_disconnect() );
4694 execute( TC_lu_by_imei() );
4695 execute( TC_lu_by_tmsi_noauth_unknown() );
4696 execute( TC_imsi_detach_by_imsi() );
4697 execute( TC_imsi_detach_by_tmsi() );
4698 execute( TC_imsi_detach_by_imei() );
4699 execute( TC_emerg_call_imei_reject() );
4700 execute( TC_emerg_call_imsi() );
4701 execute( TC_cm_serv_req_vgcs_reject() );
4702 execute( TC_cm_serv_req_vbs_reject() );
4703 execute( TC_cm_serv_req_lcs_reject() );
Harald Welte0195ab12018-01-24 21:50:20 +01004704 execute( TC_cm_reest_req_reject() );
Harald Welte1af6ea82018-01-25 18:33:15 +01004705 execute( TC_lu_auth_2G_fail() );
4706 execute( TC_lu_imsi_auth_tmsi_encr_13_13() );
4707 execute( TC_cl3_no_payload() );
4708 execute( TC_cl3_rnd_payload() );
Harald Welte1852a842018-01-26 22:53:36 +01004709 execute( TC_establish_and_nothing() );
4710 execute( TC_mo_setup_and_nothing() );
4711 execute( TC_mo_crcx_ran_timeout() );
4712 execute( TC_mo_crcx_ran_reject() );
Harald Welted2328a22018-01-27 14:27:16 +01004713 execute( TC_mt_crcx_ran_reject() );
Daniel Willmann8b084372018-02-04 13:35:26 +01004714 execute( TC_mo_setup_and_dtmf_dup() );
Harald Welteaa54cf82018-01-30 08:15:32 +01004715 //execute( TC_mt_t310() );
Harald Welte167458a2018-01-27 15:58:16 +01004716 execute( TC_gsup_cancel() );
Harald Welte9de84792018-01-28 01:06:35 +01004717 execute( TC_lu_imsi_auth_tmsi_encr_1_13() );
4718 execute( TC_lu_imsi_auth_tmsi_encr_3_13() );
4719 execute( TC_lu_imsi_auth_tmsi_encr_3_1() );
Neels Hofmeyr29b8da02018-03-01 18:09:45 +01004720 execute( TC_lu_imsi_auth_tmsi_encr_3_1_no_cm() );
Harald Welte9de84792018-01-28 01:06:35 +01004721 execute( TC_lu_imsi_auth_tmsi_encr_13_2() );
4722 execute( TC_lu_imsi_auth_tmsi_encr_013_2() );
Philipp Maier94f3f1b2018-03-15 18:54:13 +01004723 execute( TC_mo_release_timeout() );
Philipp Maier2a98a732018-03-19 16:06:12 +01004724 execute( TC_lu_and_mt_call_no_dlcx_resp() );
Philipp Maier75932982018-03-27 14:52:35 +02004725 execute( TC_reset_two() );
Harald Welte33ec09b2018-02-10 15:34:46 +01004726
4727 execute( TC_lu_and_mt_call() );
4728
Harald Weltef45efeb2018-04-09 18:19:24 +02004729 execute( TC_lu_and_mo_sms() );
4730 execute( TC_lu_and_mt_sms() );
Philipp Maier3983e702018-11-22 19:01:33 +01004731 execute( TC_lu_and_mt_sms_paging_and_nothing() );
Harald Weltef640a012018-04-14 17:49:21 +02004732 execute( TC_smpp_mo_sms() );
4733 execute( TC_smpp_mt_sms() );
Harald Weltef45efeb2018-04-09 18:19:24 +02004734
Vadim Yanitskiy103d09f2018-11-12 02:50:23 +07004735 execute( TC_gsup_mo_sms() );
Vadim Yanitskiy9cc019a2018-11-15 02:06:07 +07004736 execute( TC_gsup_mo_smma() );
Vadim Yanitskiyd7b37ab2018-11-24 03:40:20 +07004737 execute( TC_gsup_mt_sms_ack() );
4738 execute( TC_gsup_mt_sms_err() );
Vadim Yanitskiybe1ff4b2019-01-18 15:04:13 +07004739 execute( TC_gsup_mt_sms_rp_mr() );
Vadim Yanitskiy5ac49cc2019-01-24 16:57:31 +07004740 execute( TC_gsup_mo_mt_sms_rp_mr() );
Vadim Yanitskiy103d09f2018-11-12 02:50:23 +07004741
Vadim Yanitskiy2a978b92018-06-19 17:51:20 +07004742 execute( TC_lu_and_mo_ussd_single_request() );
Vadim Yanitskiy13e4a272018-06-19 18:24:31 +07004743 execute( TC_lu_and_mt_ussd_notification() );
Vadim Yanitskiy2a978b92018-06-19 17:51:20 +07004744 execute( TC_lu_and_mo_ussd_during_mt_call() );
Vadim Yanitskiy13e4a272018-06-19 18:24:31 +07004745 execute( TC_lu_and_mt_ussd_during_mt_call() );
Vadim Yanitskiy2daf52d2018-06-21 04:19:58 +07004746 execute( TC_lu_and_mo_ussd_mo_release() );
Vadim Yanitskiy0e392dd2018-11-29 00:47:54 +07004747 execute( TC_lu_and_ss_session_timeout() );
Vadim Yanitskiy7d1f9182018-05-28 16:21:42 +07004748
Stefan Sperling89eb1f32018-12-17 15:06:20 +01004749 execute( TC_cipher_complete_with_invalid_cipher() );
4750
Harald Welte4263c522018-12-06 11:56:27 +01004751 execute( TC_sgsap_reset() );
4752 execute( TC_sgsap_lu() );
4753 execute( TC_sgsap_lu_imsi_reject() );
4754 execute( TC_sgsap_lu_and_nothing() );
4755 execute( TC_sgsap_expl_imsi_det_eps() );
Philipp Maierfc19f172019-03-21 11:17:54 +01004756 execute( TC_sgsap_impl_imsi_det_eps() );
Harald Welte4263c522018-12-06 11:56:27 +01004757 execute( TC_sgsap_expl_imsi_det_noneps() );
Philipp Maier5d812702019-03-21 10:51:26 +01004758 execute( TC_sgsap_impl_imsi_det_noneps() );
Harald Welte4263c522018-12-06 11:56:27 +01004759 execute( TC_sgsap_paging_rej() );
4760 execute( TC_sgsap_paging_subscr_rej() );
4761 execute( TC_sgsap_paging_ue_unr() );
4762 execute( TC_sgsap_paging_and_nothing() );
4763 execute( TC_sgsap_paging_and_lu() );
4764 execute( TC_sgsap_mt_sms() );
4765 execute( TC_sgsap_mo_sms() );
4766 execute( TC_sgsap_mt_sms_and_nothing() );
4767 execute( TC_sgsap_mt_sms_and_reject() );
4768 execute( TC_sgsap_unexp_ud() );
4769 execute( TC_sgsap_unsol_ud() );
4770 execute( TC_bssap_lu_sgsap_lu_and_mt_call() );
4771 execute( TC_sgsap_lu_and_mt_call() );
Philipp Maier628c0052019-04-09 17:36:57 +02004772 execute( TC_sgsap_vlr_failure() );
Harald Welte4263c522018-12-06 11:56:27 +01004773
Neels Hofmeyr1b3c6e32018-03-01 17:52:21 +01004774 /* Run this last: at the time of writing this test crashes the MSC */
4775 execute( TC_lu_imsi_auth_tmsi_encr_3_1_log_msc_debug() );
Philipp Maierdb7fb8d2019-02-11 10:50:13 +01004776 execute( TC_gsup_mt_multi_part_sms() );
Neels Hofmeyr692c9ee2018-04-10 02:07:13 +02004777 execute( TC_mo_cc_bssmap_clear() );
Harald Weltef6dd64d2017-11-19 12:09:51 +01004778}
4779
4780
4781}