blob: bf703e6bc8b6c4be8b2bd0aeca442f8fd3f82383 [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 Weltea49e36e2018-01-21 19:29:33 +010039import from BSSAP_Adapter all;
40import from BSSAP_CodecPort all;
41import from BSSMAP_Templates all;
42import from BSSMAP_Emulation all;
43import 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 Maier75932982018-03-27 14:52:35 +020066const integer NUM_BSC := 2;
67type record of BSSAP_Configuration BSSAP_Configurations;
Harald Weltef6dd64d2017-11-19 12:09:51 +010068
Harald Welte4263c522018-12-06 11:56:27 +010069/* Needed for SGsAP SMS */
70import from MobileL3_SMS_Types all;
71
Harald Weltea4ca4462018-02-09 00:17:14 +010072type component MTC_CT extends CTRL_Adapter_CT {
Harald Weltef6dd64d2017-11-19 12:09:51 +010073 var boolean g_initialized := false;
Harald Weltea49e36e2018-01-21 19:29:33 +010074
Philipp Maier75932982018-03-27 14:52:35 +020075 var BSSAP_Adapter g_bssap[NUM_BSC];
Harald Weltea4ca4462018-02-09 00:17:14 +010076
Harald Weltea49e36e2018-01-21 19:29:33 +010077 /* no 'adapter_CT' for MNCC or GSUP */
78 var MNCC_Emulation_CT vc_MNCC;
Harald Welte4aa970c2018-01-26 10:38:09 +010079 var MGCP_Emulation_CT vc_MGCP;
Harald Weltea49e36e2018-01-21 19:29:33 +010080 var GSUP_Emulation_CT vc_GSUP;
81 var IPA_Emulation_CT vc_GSUP_IPA;
Harald Weltef640a012018-04-14 17:49:21 +020082 var SMPP_Emulation_CT vc_SMPP;
Harald Welte4263c522018-12-06 11:56:27 +010083 var SGsAP_Emulation_CT vc_SGsAP;
Harald Weltea49e36e2018-01-21 19:29:33 +010084
85 /* only to get events from IPA underneath GSUP */
86 port IPA_CTRL_PT GSUP_IPA_EVENT;
Harald Welte3ca1c902018-01-24 18:51:27 +010087 /* VTY to MSC */
88 port TELNETasp_PT MSCVTY;
Philipp Maier328d1662018-03-07 10:40:27 +010089
90 /* A port to directly send BSSAP messages. This port is used for
91 * tests that require low level access to sen arbitrary BSSAP
92 * messages. Run f_init_bssap_direct() to connect and initialize */
93 port BSSAP_CODEC_PT BSSAP_DIRECT;
94
95 /* When BSSAP messages are directly sent, then the connection
96 * handler is not active, which means that also no guard timer is
97 * set up. The following timer will serve as a replacement */
98 timer Tguard_direct := 60.0;
Harald Weltef6dd64d2017-11-19 12:09:51 +010099}
100
101modulepar {
Harald Weltea49e36e2018-01-21 19:29:33 +0100102 /* remote parameters of IUT */
103 charstring mp_msc_ip := "127.0.0.1";
104 integer mp_msc_ctrl_port := 4255;
105 integer mp_msc_vty_port := 4254;
Harald Weltef6dd64d2017-11-19 12:09:51 +0100106
Harald Weltea49e36e2018-01-21 19:29:33 +0100107 /* local parameters of emulated HLR */
Philipp Maier9b690e42018-12-21 11:50:03 +0100108 boolean mp_mm_info := false;
Harald Weltea49e36e2018-01-21 19:29:33 +0100109 charstring mp_hlr_ip := "127.0.0.1";
110 integer mp_hlr_port := 4222;
Harald Welte6126fb02018-01-27 20:08:24 +0100111 charstring mp_mgw_ip := "127.0.0.1";
112 integer mp_mgw_port := 2427;
Harald Weltef6dd64d2017-11-19 12:09:51 +0100113
Harald Weltea49e36e2018-01-21 19:29:33 +0100114 charstring mp_msc_mncc := "/tmp/mncc";
Harald Weltea4ca4462018-02-09 00:17:14 +0100115
Harald Weltef640a012018-04-14 17:49:21 +0200116 integer mp_msc_smpp_port := 2775;
117 charstring mp_smpp_system_id := "msc_tester";
118 charstring mp_smpp_password := "osmocom1";
Harald Welte4263c522018-12-06 11:56:27 +0100119 charstring mp_mme_name := "mmec01.mmegi0001.mme.epc.mnc070.mcc901.3gppnetwork.org";
120 charstring mp_vlr_name := "vlr.example.net";
Harald Weltef640a012018-04-14 17:49:21 +0200121
Philipp Maier75932982018-03-27 14:52:35 +0200122 BSSAP_Configurations mp_bssap_cfg := {
123 {
124 sccp_service_type := "mtp3_itu",
125 sctp_addr := { 23905, "127.0.0.1", 2905, "127.0.0.1" },
126 own_pc := 185,
127 own_ssn := 254,
128 peer_pc := 187,
129 peer_ssn := 254,
130 sio := '83'O,
131 rctx := 0
132 },
133 {
134 sccp_service_type := "mtp3_itu",
135 sctp_addr := { 23906, "127.0.0.1", 2905, "127.0.0.1" },
136 own_pc := 186,
137 own_ssn := 254,
138 peer_pc := 187,
139 peer_ssn := 254,
140 sio := '83'O,
141 rctx := 1
142 }
Harald Weltea4ca4462018-02-09 00:17:14 +0100143 };
Harald Weltef6dd64d2017-11-19 12:09:51 +0100144}
145
Philipp Maier328d1662018-03-07 10:40:27 +0100146/* altstep for the global guard timer (only used when BSSAP_DIRECT
147 * is used for communication */
148private altstep as_Tguard_direct() runs on MTC_CT {
149 [] Tguard_direct.timeout {
150 setverdict(fail, "Tguard timeout");
Daniel Willmannafce8662018-07-06 23:11:32 +0200151 mtc.stop;
Philipp Maier328d1662018-03-07 10:40:27 +0100152 }
153}
Harald Weltef6dd64d2017-11-19 12:09:51 +0100154
Harald Weltef640a012018-04-14 17:49:21 +0200155function f_init_smpp(charstring id) runs on MTC_CT {
156 id := id & "-SMPP";
157 var EsmePars pars := {
158 mode := MODE_TRANSCEIVER,
159 bind := {
160 system_id := mp_smpp_system_id,
161 password := mp_smpp_password,
162 system_type := "MSC_Tests",
163 interface_version := hex2int('34'H),
164 addr_ton := unknown,
165 addr_npi := unknown,
166 address_range := ""
167 },
168 esme_role := true
169 }
170
171 vc_SMPP := SMPP_Emulation_CT.create(id);
172 map(vc_SMPP:SMPP_PORT, system:SMPP_PORT);
173 vc_SMPP.start(SMPP_Emulation.main_client(pars, mp_msc_ip, mp_msc_smpp_port, "", -1));
174}
175
176
Harald Weltea49e36e2018-01-21 19:29:33 +0100177function f_init_mncc(charstring id) runs on MTC_CT {
178 id := id & "-MNCC";
179 var MnccOps ops := {
180 create_cb := refers(MNCC_Emulation.ExpectedCreateCallback),
181 unitdata_cb := refers(MNCC_Emulation.DummyUnitdataCallback)
182 }
183
184 vc_MNCC := MNCC_Emulation_CT.create(id);
185 map(vc_MNCC:MNCC, system:MNCC_CODEC_PT);
186 vc_MNCC.start(MNCC_Emulation.main(ops, id, mp_msc_mncc));
Harald Weltef6dd64d2017-11-19 12:09:51 +0100187}
188
Harald Welte4aa970c2018-01-26 10:38:09 +0100189function f_init_mgcp(charstring id) runs on MTC_CT {
190 id := id & "-MGCP";
191 var MGCPOps ops := {
192 create_cb := refers(MGCP_Emulation.ExpectedCreateCallback),
193 unitdata_cb := refers(MGCP_Emulation.DummyUnitdataCallback)
194 }
195 var MGCP_conn_parameters pars := {
Harald Welte6126fb02018-01-27 20:08:24 +0100196 callagent_ip := mp_msc_ip,
Harald Welte4aa970c2018-01-26 10:38:09 +0100197 callagent_udp_port := -1,
Harald Welte6126fb02018-01-27 20:08:24 +0100198 mgw_ip := mp_mgw_ip,
199 mgw_udp_port := mp_mgw_port
Harald Welte4aa970c2018-01-26 10:38:09 +0100200 }
201
202 vc_MGCP := MGCP_Emulation_CT.create(id);
203 map(vc_MGCP:MGCP, system:MGCP_CODEC_PT);
204 vc_MGCP.start(MGCP_Emulation.main(ops, pars, id));
205}
206
Harald Welte4263c522018-12-06 11:56:27 +0100207function f_init_sgsap(charstring id) runs on MTC_CT {
208 id := id & "-SGsAP";
209 var SGsAPOps ops := {
210 create_cb := refers(SGsAP_Emulation.ExpectedCreateCallback),
211 unitdata_cb := refers(SGsAP_Emulation.DummyUnitdataCallback)
212 }
213 var SGsAP_conn_parameters pars := {
214 remote_ip := mp_msc_ip,
215 remote_sctp_port := 29118,
216 local_ip := "",
217 local_sctp_port := -1
218 }
219
220 vc_SGsAP := SGsAP_Emulation_CT.create(id);
221 map(vc_SGsAP:SGsAP, system:SGsAP_CODEC_PT);
222 vc_SGsAP.start(SGsAP_Emulation.main(ops, pars, id));
223}
224
225
Harald Weltea49e36e2018-01-21 19:29:33 +0100226function f_init_gsup(charstring id) runs on MTC_CT {
227 id := id & "-GSUP";
228 var GsupOps ops := {
229 create_cb := refers(GSUP_Emulation.ExpectedCreateCallback)
230 }
231
232 vc_GSUP_IPA := IPA_Emulation_CT.create(id & "-IPA");
233 vc_GSUP := GSUP_Emulation_CT.create(id);
234
235 map(vc_GSUP_IPA:IPA_PORT, system:IPA_CODEC_PT);
236 connect(vc_GSUP:GSUP, vc_GSUP_IPA:IPA_GSUP_PORT);
237 /* we use this hack to get events like ASP_IPA_EVENT_UP */
238 connect(vc_GSUP_IPA:IPA_CTRL_PORT, self:GSUP_IPA_EVENT);
239
240 vc_GSUP.start(GSUP_Emulation.main(ops, id));
241 vc_GSUP_IPA.start(IPA_Emulation.main_server(mp_hlr_ip, mp_hlr_port));
242
243 /* wait for incoming connection to GSUP port before proceeding */
244 timer T := 10.0;
245 T.start;
246 alt {
247 [] GSUP_IPA_EVENT.receive(t_ASP_IPA_EVT_UD(ASP_IPA_EVENT_UP)) { }
248 [] T.timeout {
Harald Welte458fd372018-03-21 11:26:23 +0100249 setverdict(fail, "No connection to GSUP Port");
Daniel Willmannafce8662018-07-06 23:11:32 +0200250 mtc.stop
Harald Weltea49e36e2018-01-21 19:29:33 +0100251 }
252 }
Harald Weltef6dd64d2017-11-19 12:09:51 +0100253}
254
Philipp Maier75932982018-03-27 14:52:35 +0200255function f_init(integer num_bsc := 1) runs on MTC_CT {
Harald Weltef6dd64d2017-11-19 12:09:51 +0100256
257 if (g_initialized == true) {
258 return;
259 }
260 g_initialized := true;
261
Philipp Maier75932982018-03-27 14:52:35 +0200262 if (num_bsc > NUM_BSC) {
Daniel Willmannafce8662018-07-06 23:11:32 +0200263 testcase.stop("excess number of BSC instances requested");
Philipp Maier75932982018-03-27 14:52:35 +0200264 }
265
266 for (var integer i := 0; i < num_bsc; i := i + 1) {
267 if (isbound(mp_bssap_cfg[i])) {
Philipp Maierdefd9482018-05-16 16:44:37 +0200268 f_bssap_init(g_bssap[i], mp_bssap_cfg[i], "MSC_Test_" & int2str(i), BSC_BssmapOps);
Harald Welted5833a82018-05-27 16:52:56 +0200269 f_bssap_start(g_bssap[i]);
Philipp Maier75932982018-03-27 14:52:35 +0200270 } else {
Daniel Willmannafce8662018-07-06 23:11:32 +0200271 testcase.stop("missing BSSAP configuration");
Philipp Maier75932982018-03-27 14:52:35 +0200272 }
273 }
274
Harald Weltea49e36e2018-01-21 19:29:33 +0100275 f_ipa_ctrl_start(mp_msc_ip, mp_msc_ctrl_port);
276 f_init_mncc("MSC_Test");
Harald Welte4aa970c2018-01-26 10:38:09 +0100277 f_init_mgcp("MSC_Test");
Harald Weltea49e36e2018-01-21 19:29:33 +0100278 f_init_gsup("MSC_Test");
Harald Weltef640a012018-04-14 17:49:21 +0200279 f_init_smpp("MSC_Test");
Harald Welte4263c522018-12-06 11:56:27 +0100280 f_init_sgsap("MSC_Test");
Harald Welte3ca1c902018-01-24 18:51:27 +0100281
282 map(self:MSCVTY, system:MSCVTY);
283 f_vty_set_prompts(MSCVTY);
284 f_vty_transceive(MSCVTY, "enable");
Harald Welteb14c77a2018-01-25 17:25:44 +0100285
286 /* set some defaults */
287 f_vty_config(MSCVTY, "network", "authentication optional");
288 f_vty_config(MSCVTY, "msc", "assign-tmsi");
289 f_vty_config(MSCVTY, "network", "encryption a5 0");
Harald Weltef6dd64d2017-11-19 12:09:51 +0100290}
291
Philipp Maier328d1662018-03-07 10:40:27 +0100292/* Initialize for a direct connection to BSSAP. This function is an alternative
293 * to f_init() when the high level functions of the BSC_ConnectionHandler are
294 * not needed. */
295function f_init_bssap_direct() runs on MTC_CT {
Philipp Maier75932982018-03-27 14:52:35 +0200296 f_bssap_init(g_bssap[0], mp_bssap_cfg[0], "MSC_Test", omit);
297 connect(g_bssap[0].vc_SCCP:SCCP_SP_PORT, self:BSSAP_DIRECT);
Philipp Maier328d1662018-03-07 10:40:27 +0100298
299 /* Start guard timer and activate it as default */
300 Tguard_direct.start
301 activate(as_Tguard_direct());
302}
303
Harald Weltef6dd64d2017-11-19 12:09:51 +0100304template PDU_BSSAP ts_BSSAP_BSSMAP := {
305 discriminator := '0'B,
306 spare := '0000000'B,
307 dlci := omit,
308 lengthIndicator := 0, /* overwritten by codec */
309 pdu := ?
310}
311
312template PDU_BSSAP tr_BSSAP_BSSMAP := {
313 discriminator := '0'B,
314 spare := '0000000'B,
315 dlci := omit,
316 lengthIndicator := ?,
317 pdu := {
318 bssmap := ?
319 }
320}
321
322
323type integer BssmapCause;
324
325template (value) BSSMAP_IE_Cause ts_BSSMAP_IE_Cause(BssmapCause val) := {
326 elementIdentifier := '04'O,
327 lengthIndicator := 0,
328 causeValue := int2bit(val, 7),
329 extensionCauseValue := '0'B,
330 spare1 := omit
331}
332
333template (value) PDU_BSSAP ts_BSSMAP_Reset(BssmapCause cause) modifies ts_BSSAP_BSSMAP := {
334 pdu := {
335 bssmap := {
336 reset := {
337 messageType := '30'O,
338 cause := ts_BSSMAP_IE_Cause(cause),
339 a_InterfaceSelectorForReset := omit
340 }
341 }
342 }
343}
344
345template (value) PDU_BSSAP ts_BSSMAP_ResetAck modifies ts_BSSAP_BSSMAP := {
346 pdu := {
347 bssmap := {
348 resetAck := {
349 messageType := '31'O,
350 a_InterfaceSelectorForReset := omit
351 }
352 }
353 }
354}
355
356template PDU_BSSAP tr_BSSMAP_ResetAck modifies tr_BSSAP_BSSMAP := {
357 pdu := {
358 bssmap := {
359 resetAck := {
360 messageType := '31'O,
361 a_InterfaceSelectorForReset := *
362 }
363 }
364 }
365}
366
367template BSSMAP_IE_CellIdentifier ts_BSSMAP_IE_CellID := {
368 elementIdentifier := '05'O,
369 lengthIndicator := 0,
370 cellIdentifierDiscriminator := '0000'B,
371 spare1_4 := '0000'B,
372 cellIdentification := ?
373}
374
375type uint16_t BssmapLAC;
376type uint16_t BssmapCI;
377
378/*
379template BSSMAP_IE_CellIdentifier ts_CellId_CGI(mcc, mnc, lac, ci)
380modifies ts_BSSMAP_IE_CellID := {
381 cellIdentification := {
382 cI_LAC_CGI := {
383 mnc_mcc := FIXME,
384 lac := int2oct(lac, 2),
385 ci := int2oct(ci, 2)
386 }
387 }
388}
389*/
390
391template BSSMAP_IE_CellIdentifier ts_CellID_LAC_CI(BssmapLAC lac, BssmapCI ci)
392modifies ts_BSSMAP_IE_CellID := {
393 cellIdentification := {
394 cI_LAC_CI := {
395 lac := int2oct(lac, 2),
396 ci := int2oct(ci, 2)
397 }
398 }
399}
400
401template BSSMAP_IE_CellIdentifier ts_CellId_CI(BssmapCI ci)
402modifies ts_BSSMAP_IE_CellID := {
403 cellIdentification := {
404 cI_CI := int2oct(ci, 2)
405 }
406}
407
408template BSSMAP_IE_CellIdentifier ts_CellId_none
409modifies ts_BSSMAP_IE_CellID := {
410 cellIdentification := {
411 cI_noCell := ''O
412 }
413}
414
415
416template BSSMAP_IE_Layer3Information ts_BSSMAP_IE_L3Info(octetstring l3info) := {
417 elementIdentifier := '17'O,
418 lengthIndicator := 0,
419 layer3info := l3info
420}
421
422template PDU_BSSAP ts_BSSMAP_ComplL3(BSSMAP_IE_CellIdentifier cell_id, octetstring l3_info)
423modifies ts_BSSAP_BSSMAP := {
424 pdu := {
425 bssmap := {
426 completeLayer3Information := {
427 messageType := '57'O,
428 cellIdentifier := cell_id,
429 layer3Information := ts_BSSMAP_IE_L3Info(l3_info),
430 chosenChannel := omit,
431 lSAIdentifier := omit,
432 aPDU := omit,
433 codecList := omit,
434 redirectAttemptFlag := omit,
435 sendSequenceNumber := omit,
436 iMSI := omit
437 }
438 }
439 }
440}
441
442template PDU_BSSAP ts_BSSMAP_HandoReq(BssmapCause cause, BSSMAP_IE_CellIdentifierList cid_list)
443modifies ts_BSSAP_BSSMAP := {
444 pdu := {
445 bssmap := {
446 handoverRequired := {
447 messageType := '11'O,
448 cause := ts_BSSMAP_IE_Cause(cause),
449 responseRequest := omit,
450 cellIdentifierList := cid_list,
451 circuitPoolList := omit,
452 currentChannelType1 := omit,
453 speechVersion := omit,
454 queueingIndicator := omit,
455 oldToNewBSSInfo := omit,
456 sourceToTargetRNCTransparentInfo := omit,
457 sourceToTargetRNCTransparentInfoCDMA := omit,
458 gERANClassmark := omit,
459 talkerPriority := omit,
460 speechCodec := omit,
461 cSG_Identifier := omit
462 }
463 }
464 }
465}
466
Harald Weltea49e36e2018-01-21 19:29:33 +0100467type function void_fn(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr;
Harald Weltef6dd64d2017-11-19 12:09:51 +0100468
Harald Weltea49e36e2018-01-21 19:29:33 +0100469/* FIXME: move into BSC_ConnectionHandler? */
Neels Hofmeyr9adaa702018-03-01 20:23:19 +0100470function f_init_pars(integer imsi_suffix) runs on MTC_CT return BSC_ConnHdlrPars {
Harald Weltede371492018-01-27 23:44:41 +0100471 var BSC_ConnHdlrNetworkPars net_pars := {
472 kc_support := '0A'O, /* A5/1 and A5/3 enabled */
473 expect_tmsi := true,
474 expect_auth := false,
475 expect_ciph := false
476 };
Harald Weltea49e36e2018-01-21 19:29:33 +0100477 var BSC_ConnHdlrPars pars := {
Philipp Maier75932982018-03-27 14:52:35 +0200478 sccp_addr_own := g_bssap[0].sccp_addr_own,
479 sccp_addr_peer := g_bssap[0].sccp_addr_peer,
Harald Welteedbab812018-03-18 16:02:25 +0100480 cell_id := valueof(ts_CellId_CGI('262'H, '42'H, 23, 42)),
Harald Welte81b7f9d2018-01-24 19:06:24 +0100481 imei := f_gen_imei(imsi_suffix),
482 imsi := f_gen_imsi(imsi_suffix),
483 msisdn := f_gen_msisdn(imsi_suffix),
Harald Welte256571e2018-01-24 18:47:19 +0100484 tmsi := omit,
Harald Welte9de84792018-01-28 01:06:35 +0100485 cm1 := valueof(ts_CM1),
Harald Welte82600572018-01-21 20:54:08 +0100486 cm2 := valueof(ts_CM2_default),
Harald Welte16114282018-01-24 22:41:21 +0100487 cm3 := omit,
Harald Weltede371492018-01-27 23:44:41 +0100488 vec := omit,
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +0100489 net := net_pars,
Philipp Maieraeb29a82018-11-08 17:40:53 +0100490 send_early_cm := true,
491 ipa_ctrl_ip := mp_msc_ip,
492 ipa_ctrl_port := mp_msc_ctrl_port,
Philipp Maier9b690e42018-12-21 11:50:03 +0100493 ipa_ctrl_enable := true,
494 mm_info := mp_mm_info
Harald Weltea49e36e2018-01-21 19:29:33 +0100495 };
Neels Hofmeyr9adaa702018-03-01 20:23:19 +0100496 return pars;
497}
498
499function f_start_handler_with_pars(void_fn fn, BSC_ConnHdlrPars pars) runs on MTC_CT return BSC_ConnHdlr {
500 var BSC_ConnHdlr vc_conn;
501 var charstring id := testcasename();
Harald Weltea49e36e2018-01-21 19:29:33 +0100502
503 vc_conn := BSC_ConnHdlr.create(id);
504 /* BSSMAP part / A interface */
Philipp Maier75932982018-03-27 14:52:35 +0200505 connect(vc_conn:BSSAP, g_bssap[0].vc_BSSMAP:CLIENT);
506 connect(vc_conn:BSSAP_PROC, g_bssap[0].vc_BSSMAP:PROC);
Harald Weltea49e36e2018-01-21 19:29:33 +0100507 /* MNCC part */
508 connect(vc_conn:MNCC, vc_MNCC:MNCC_CLIENT);
509 connect(vc_conn:MNCC_PROC, vc_MNCC:MNCC_PROC);
Harald Welte4aa970c2018-01-26 10:38:09 +0100510 /* MGCP part */
511 connect(vc_conn:MGCP, vc_MGCP:MGCP_CLIENT);
512 connect(vc_conn:MGCP_PROC, vc_MGCP:MGCP_PROC);
Harald Weltea49e36e2018-01-21 19:29:33 +0100513 /* GSUP part */
514 connect(vc_conn:GSUP, vc_GSUP:GSUP_CLIENT);
515 connect(vc_conn:GSUP_PROC, vc_GSUP:GSUP_PROC);
Harald Weltef640a012018-04-14 17:49:21 +0200516 /* SMPP part */
517 connect(vc_conn:SMPP, vc_SMPP:SMPP_CLIENT);
518 connect(vc_conn:SMPP_PROC, vc_SMPP:SMPP_PROC);
Harald Welte4263c522018-12-06 11:56:27 +0100519 /* SGs part */
520 connect(vc_conn:SGsAP, vc_SGsAP:SGsAP_CLIENT);
521 connect(vc_conn:SGsAP_PROC, vc_SGsAP:SGsAP_PROC);
Harald Weltea49e36e2018-01-21 19:29:33 +0100522
Harald Weltea10db902018-01-27 12:44:49 +0100523 /* We cannot use vc_conn.start(f_init_handler(fn, id, pars)); as we cannot have
524 * a stand-alone 'derefers()' call, see https://www.eclipse.org/forums/index.php/t/1091364/ */
Harald Weltea49e36e2018-01-21 19:29:33 +0100525 vc_conn.start(derefers(fn)(id, pars));
526 return vc_conn;
527}
528
Neels Hofmeyr9adaa702018-03-01 20:23:19 +0100529function f_start_handler(void_fn fn, integer imsi_suffix) runs on MTC_CT return BSC_ConnHdlr {
530 return f_start_handler_with_pars(fn, f_init_pars(imsi_suffix));
531}
532
Harald Weltea49e36e2018-01-21 19:29:33 +0100533private function f_tc_lu_imsi_noauth_tmsi(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +0100534 f_init_handler(pars);
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +0100535 f_perform_lu();
Harald Weltea49e36e2018-01-21 19:29:33 +0100536}
Harald Weltea49e36e2018-01-21 19:29:33 +0100537testcase TC_lu_imsi_noauth_tmsi() runs on MTC_CT {
538 var BSC_ConnHdlr vc_conn;
539 f_init();
540
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +0100541 vc_conn := f_start_handler(refers(f_tc_lu_imsi_noauth_tmsi), 1);
Harald Weltea49e36e2018-01-21 19:29:33 +0100542 vc_conn.done;
543}
544
545private function f_tc_lu_imsi_noauth_notmsi(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltede371492018-01-27 23:44:41 +0100546 pars.net.expect_tmsi := false;
Harald Weltea10db902018-01-27 12:44:49 +0100547 f_init_handler(pars);
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +0100548 f_perform_lu();
Harald Weltea49e36e2018-01-21 19:29:33 +0100549}
Harald Weltea49e36e2018-01-21 19:29:33 +0100550testcase TC_lu_imsi_noauth_notmsi() runs on MTC_CT {
551 var BSC_ConnHdlr vc_conn;
552 f_init();
Harald Welte3ca1c902018-01-24 18:51:27 +0100553 f_vty_config(MSCVTY, "msc", "no assign-tmsi");
Harald Weltea49e36e2018-01-21 19:29:33 +0100554
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +0100555 vc_conn := f_start_handler(refers(f_tc_lu_imsi_noauth_notmsi), 2);
Harald Weltea49e36e2018-01-21 19:29:33 +0100556 vc_conn.done;
557}
558
559/* Do LU by IMSI, refuse it on GSUP and expect LU REJ back to MS */
560private function f_tc_lu_imsi_reject(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +0100561 f_init_handler(pars);
Harald Weltea49e36e2018-01-21 19:29:33 +0100562 var PDU_ML3_MS_NW l3_lu := f_build_lu_imsi(g_pars.imsi);
563
564 f_create_gsup_expect(hex2str(g_pars.imsi));
565 f_bssap_compl_l3(l3_lu);
566 GSUP.receive(tr_GSUP_UL_REQ(g_pars.imsi));
567 GSUP.send(ts_GSUP_UL_ERR(g_pars.imsi, 23));
568 alt {
Harald Welte5946b332018-03-18 23:32:21 +0100569 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Rej(int2oct(23,1)))) {
570 f_expect_clear();
571 }
Harald Weltea49e36e2018-01-21 19:29:33 +0100572 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Acc)) {
573 setverdict(fail, "Expecting LU REJ, but got ACCEPT");
Daniel Willmannafce8662018-07-06 23:11:32 +0200574 mtc.stop;
Harald Weltea49e36e2018-01-21 19:29:33 +0100575 }
576 }
Harald Weltea49e36e2018-01-21 19:29:33 +0100577}
578testcase TC_lu_imsi_reject() runs on MTC_CT {
579 var BSC_ConnHdlr vc_conn;
580 f_init();
581
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +0100582 vc_conn := f_start_handler(refers(f_tc_lu_imsi_reject), 3);
Harald Weltea49e36e2018-01-21 19:29:33 +0100583 vc_conn.done;
584}
585
586/* Do LU by IMSI, timeout on GSUP */
587private function f_tc_lu_imsi_timeout_gsup(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +0100588 f_init_handler(pars);
Harald Weltea49e36e2018-01-21 19:29:33 +0100589 var PDU_ML3_MS_NW l3_lu := f_build_lu_imsi(g_pars.imsi);
590
591 f_create_gsup_expect(hex2str(g_pars.imsi));
592 f_bssap_compl_l3(l3_lu);
593 GSUP.receive(tr_GSUP_UL_REQ(g_pars.imsi));
594 /* Normally the HLR would need to respond here, but we decide to force a timeout here */
595 alt {
596 /* FIXME: Expect specific reject cause */
Harald Welte5946b332018-03-18 23:32:21 +0100597 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Rej)) {
598 f_expect_clear();
599 }
Harald Weltea49e36e2018-01-21 19:29:33 +0100600 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Acc)) {
601 setverdict(fail, "Expecting LU REJ, but got ACCEPT");
Daniel Willmannafce8662018-07-06 23:11:32 +0200602 mtc.stop;
Harald Weltea49e36e2018-01-21 19:29:33 +0100603 }
604 }
Harald Weltea49e36e2018-01-21 19:29:33 +0100605}
606testcase TC_lu_imsi_timeout_gsup() runs on MTC_CT {
607 var BSC_ConnHdlr vc_conn;
608 f_init();
609
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +0100610 vc_conn := f_start_handler(refers(f_tc_lu_imsi_timeout_gsup), 4);
Harald Weltea49e36e2018-01-21 19:29:33 +0100611 vc_conn.done;
612}
613
Harald Welte7b1b2812018-01-22 21:23:06 +0100614private function f_tc_lu_imsi_auth_tmsi(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltede371492018-01-27 23:44:41 +0100615 pars.net.expect_auth := true;
Harald Weltea10db902018-01-27 12:44:49 +0100616 f_init_handler(pars);
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +0100617 f_perform_lu();
Harald Welte7b1b2812018-01-22 21:23:06 +0100618}
619testcase TC_lu_imsi_auth_tmsi() runs on MTC_CT {
620 var BSC_ConnHdlr vc_conn;
621 f_init();
Harald Welte3ca1c902018-01-24 18:51:27 +0100622 f_vty_config(MSCVTY, "network", "authentication required");
Harald Welte7b1b2812018-01-22 21:23:06 +0100623
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +0100624 vc_conn := f_start_handler(refers(f_tc_lu_imsi_auth_tmsi), 5);
Harald Welte7b1b2812018-01-22 21:23:06 +0100625 vc_conn.done;
626}
627
Harald Weltea49e36e2018-01-21 19:29:33 +0100628
629/* Send CM SERVICE REQ for IMSI that has never performed LU before */
630private function f_tc_cmserv_imsi_unknown(charstring id, BSC_ConnHdlrPars pars)
631runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +0100632 f_init_handler(pars);
Harald Weltea49e36e2018-01-21 19:29:33 +0100633
634 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
Harald Welteedbab812018-03-18 16:02:25 +0100635 var BSSMAP_IE_CellIdentifier cell_id := valueof(ts_CellId_CGI('262'H, '42'H, 23, 42));
Harald Welte6ed6bf92018-01-24 21:09:15 +0100636 var PDU_ML3_MS_NW l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, mi));
Harald Weltea49e36e2018-01-21 19:29:33 +0100637
638 f_create_gsup_expect(hex2str(g_pars.imsi));
639
640 /* Send BSSAP_Conn_Req with COMPL L3 INFO to MSC */
641 f_bssap_compl_l3(l3_info);
642
643 timer T := 10.0;
Harald Weltef6dd64d2017-11-19 12:09:51 +0100644 T.start;
645 alt {
Harald Weltea49e36e2018-01-21 19:29:33 +0100646 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_CM_SERV_REJ)) { }
647 //[] BSSAP.receive(tr_PDU_DTAP_MT(tr_CM_SERV_ACC)) { }
Daniel Willmannafce8662018-07-06 23:11:32 +0200648 [] BSSAP.receive {
649 setverdict(fail, "Received unexpected BSSAP");
650 mtc.stop;
651 }
Harald Weltea49e36e2018-01-21 19:29:33 +0100652 [] GSUP.receive(tr_GSUP_UL_REQ(g_pars.imsi)) {
653 setverdict(fail, "Unexpected GSUP UL REQ");
Daniel Willmannafce8662018-07-06 23:11:32 +0200654 mtc.stop;
Harald Weltea49e36e2018-01-21 19:29:33 +0100655 }
Daniel Willmannafce8662018-07-06 23:11:32 +0200656 [] T.timeout {
657 setverdict(fail, "Timeout waiting for CM SERV REQ");
658 mtc.stop;
659 }
Harald Weltef6dd64d2017-11-19 12:09:51 +0100660 }
661
Harald Welte1ddc7162018-01-27 14:25:46 +0100662 f_expect_clear();
Harald Weltef6dd64d2017-11-19 12:09:51 +0100663}
Harald Weltea49e36e2018-01-21 19:29:33 +0100664testcase TC_cmserv_imsi_unknown() runs on MTC_CT {
665 var BSC_ConnHdlr vc_conn;
666 f_init();
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +0100667 vc_conn := f_start_handler(refers(f_tc_cmserv_imsi_unknown), 6);
Harald Weltea49e36e2018-01-21 19:29:33 +0100668 vc_conn.done;
669}
670
Harald Welte2bb825f2018-01-22 11:31:18 +0100671private function f_tc_lu_and_mo_call(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +0100672 f_init_handler(pars);
Harald Welteb71901a2018-01-26 19:16:05 +0100673 var CallParameters cpars := valueof(t_CallParams('12345'H, 0));
674 cpars.bss_rtp_port := 1110;
675 cpars.mgcp_connection_id_bss := '22222'H;
676 cpars.mgcp_connection_id_mss := '33333'H;
Philipp Maierf1e02bb2018-03-15 16:30:00 +0100677 cpars.mgcp_ep := "rtpbridge/1@mgw";
Harald Welte2bb825f2018-01-22 11:31:18 +0100678
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +0100679 f_perform_lu();
Harald Welteb71901a2018-01-26 19:16:05 +0100680 f_mo_call(cpars);
Harald Welte2bb825f2018-01-22 11:31:18 +0100681}
682testcase TC_lu_and_mo_call() runs on MTC_CT {
683 var BSC_ConnHdlr vc_conn;
684 f_init();
685
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +0100686 vc_conn := f_start_handler(refers(f_tc_lu_and_mo_call), 7);
Harald Welte071ed732018-01-23 19:53:52 +0100687 vc_conn.done;
688}
689
690/* Test LU (with authentication enabled), where HLR times out sending SAI response */
691private function f_tc_lu_auth_sai_timeout(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +0100692 f_init_handler(pars);
Harald Welte071ed732018-01-23 19:53:52 +0100693
694 var PDU_ML3_MS_NW l3_lu := f_build_lu_imsi(g_pars.imsi)
695 var PDU_DTAP_MT dtap_mt;
696
697 /* tell GSUP dispatcher to send this IMSI to us */
698 f_create_gsup_expect(hex2str(g_pars.imsi));
699
700 /* Send BSSAP_Conn_Req with COMPL L3 INFO to MSC */
701 f_bssap_compl_l3(l3_lu);
702
703 /* Send Early Classmark, just for the fun of it */
704 BSSAP.send(ts_BSSMAP_ClassmarkUpd(g_pars.cm2, g_pars.cm3));
705
706 GSUP.receive(tr_GSUP_SAI_REQ(g_pars.imsi));
707 /* The HLR would normally return an auth vector here, but we fail to do so. */
708
709 BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Rej));
Harald Welte1ddc7162018-01-27 14:25:46 +0100710 f_expect_clear();
Harald Welte071ed732018-01-23 19:53:52 +0100711}
712testcase TC_lu_auth_sai_timeout() runs on MTC_CT {
713 var BSC_ConnHdlr vc_conn;
714 f_init();
Harald Welte3ca1c902018-01-24 18:51:27 +0100715 f_vty_config(MSCVTY, "network", "authentication required");
Harald Welte071ed732018-01-23 19:53:52 +0100716
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +0100717 vc_conn := f_start_handler(refers(f_tc_lu_auth_sai_timeout), 8);
Harald Welte071ed732018-01-23 19:53:52 +0100718 vc_conn.done;
719}
720
721/* Test LU (with authentication enabled), where HLR rejects sending SAI error */
722private function f_tc_lu_auth_sai_err(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +0100723 f_init_handler(pars);
Harald Welte071ed732018-01-23 19:53:52 +0100724
725 var PDU_ML3_MS_NW l3_lu := f_build_lu_imsi(g_pars.imsi)
726 var PDU_DTAP_MT dtap_mt;
727
728 /* tell GSUP dispatcher to send this IMSI to us */
729 f_create_gsup_expect(hex2str(g_pars.imsi));
730
731 /* Send BSSAP_Conn_Req with COMPL L3 INFO to MSC */
732 f_bssap_compl_l3(l3_lu);
733
734 /* Send Early Classmark, just for the fun of it */
735 BSSAP.send(ts_BSSMAP_ClassmarkUpd(g_pars.cm2, g_pars.cm3));
736
737 GSUP.receive(tr_GSUP_SAI_REQ(g_pars.imsi));
738 GSUP.send(ts_GSUP_SAI_ERR(g_pars.imsi, 13));
739
740 BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Rej));
Harald Welte1ddc7162018-01-27 14:25:46 +0100741 f_expect_clear();
Harald Welte071ed732018-01-23 19:53:52 +0100742}
743testcase TC_lu_auth_sai_err() runs on MTC_CT {
744 var BSC_ConnHdlr vc_conn;
745 f_init();
Harald Welte3ca1c902018-01-24 18:51:27 +0100746 f_vty_config(MSCVTY, "network", "authentication required");
Harald Welte071ed732018-01-23 19:53:52 +0100747
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +0100748 vc_conn := f_start_handler(refers(f_tc_lu_auth_sai_err), 9);
Harald Welte2bb825f2018-01-22 11:31:18 +0100749 vc_conn.done;
750}
Harald Weltea49e36e2018-01-21 19:29:33 +0100751
Harald Weltebc881782018-01-23 20:09:15 +0100752/* Test LU but BSC will send a clear request in the middle */
753private function f_tc_lu_clear_request(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +0100754 f_init_handler(pars);
Harald Weltebc881782018-01-23 20:09:15 +0100755
756 var PDU_ML3_MS_NW l3_lu := f_build_lu_imsi(g_pars.imsi)
757 var PDU_DTAP_MT dtap_mt;
758
759 /* tell GSUP dispatcher to send this IMSI to us */
760 f_create_gsup_expect(hex2str(g_pars.imsi));
761
762 /* Send BSSAP_Conn_Req with COMPL L3 INFO to MSC */
763 f_bssap_compl_l3(l3_lu);
764
765 /* Send Early Classmark, just for the fun of it */
766 BSSAP.send(ts_BSSMAP_ClassmarkUpd(g_pars.cm2, g_pars.cm3));
767
768 f_sleep(1.0);
769 /* send clear request in the middle of the LU */
770 BSSAP.send(ts_BSSMAP_ClearRequest(0));
Neels Hofmeyr2b326fa2018-04-06 00:59:36 +0200771 alt {
772 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Rej)) { repeat; }
773 [] BSSAP.receive(tr_BSSMAP_ClearCommand) {}
774 }
Harald Weltebc881782018-01-23 20:09:15 +0100775 BSSAP.send(ts_BSSMAP_ClearComplete);
Harald Welte89a32492018-01-27 19:07:28 +0100776 alt {
777 /* See https://osmocom.org/issues/2862 */
Neels Hofmeyr2b326fa2018-04-06 00:59:36 +0200778 [] BSSAP.receive(tr_BSSMAP_ClearCommand) {
779 setverdict(fail, "Got a second Clear Command, only one expected");
Daniel Willmannafce8662018-07-06 23:11:32 +0200780 mtc.stop;
Neels Hofmeyr2b326fa2018-04-06 00:59:36 +0200781 repeat;
782 }
Harald Welte89a32492018-01-27 19:07:28 +0100783 [] BSSAP.receive(BSSAP_Conn_Prim:MSC_CONN_PRIM_DISC_IND) {}
784 }
Harald Weltebc881782018-01-23 20:09:15 +0100785 setverdict(pass);
786}
787testcase TC_lu_clear_request() runs on MTC_CT {
788 var BSC_ConnHdlr vc_conn;
789 f_init();
790
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +0100791 vc_conn := f_start_handler(refers(f_tc_lu_clear_request), 10);
Harald Weltebc881782018-01-23 20:09:15 +0100792 vc_conn.done;
793}
794
Harald Welte66af9e62018-01-24 17:28:21 +0100795/* Test LU but BSC will send a clear request in the middle */
796private function f_tc_lu_disconnect(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +0100797 f_init_handler(pars);
Harald Welte66af9e62018-01-24 17:28:21 +0100798
799 var PDU_ML3_MS_NW l3_lu := f_build_lu_imsi(g_pars.imsi)
800 var PDU_DTAP_MT dtap_mt;
801
802 /* tell GSUP dispatcher to send this IMSI to us */
803 f_create_gsup_expect(hex2str(g_pars.imsi));
804
805 /* Send BSSAP_Conn_Req with COMPL L3 INFO to MSC */
806 f_bssap_compl_l3(l3_lu);
807
808 /* Send Early Classmark, just for the fun of it */
809 BSSAP.send(ts_BSSMAP_ClassmarkUpd(g_pars.cm2, g_pars.cm3));
810
811 f_sleep(1.0);
812 /* send clear request in the middle of the LU */
813 BSSAP.send(BSSAP_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
814 setverdict(pass);
815}
816testcase TC_lu_disconnect() runs on MTC_CT {
817 var BSC_ConnHdlr vc_conn;
818 f_init();
819
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +0100820 vc_conn := f_start_handler(refers(f_tc_lu_disconnect), 11);
Harald Welte66af9e62018-01-24 17:28:21 +0100821 vc_conn.done;
822}
823
824
Harald Welteba7b6d92018-01-23 21:32:34 +0100825/* Test LU but with illegal mobile identity type = IMEI */
826private function f_tc_lu_by_imei(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +0100827 f_init_handler(pars);
Harald Welteba7b6d92018-01-23 21:32:34 +0100828
Harald Welte256571e2018-01-24 18:47:19 +0100829 var PDU_ML3_MS_NW l3_lu := f_build_lu_imei(g_pars.imei)
Harald Welteba7b6d92018-01-23 21:32:34 +0100830 var PDU_DTAP_MT dtap_mt;
831
832 /* tell GSUP dispatcher to send this IMSI to us */
833 f_create_gsup_expect(hex2str(g_pars.imsi));
834
835 /* Send BSSAP_Conn_Req with COMPL L3 INFO to MSC */
836 f_bssap_compl_l3(l3_lu);
837
838 /* Send Early Classmark, just for the fun of it */
839 BSSAP.send(ts_BSSMAP_ClassmarkUpd(g_pars.cm2, g_pars.cm3));
840 /* wait for LU reject, ignore any ID REQ */
841 alt {
842 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Rej)) { }
843 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_MM_ID_Req)) { repeat; }
844 }
845 /* wait for normal teardown */
Harald Welte1ddc7162018-01-27 14:25:46 +0100846 f_expect_clear();
Harald Welteba7b6d92018-01-23 21:32:34 +0100847}
848testcase TC_lu_by_imei() runs on MTC_CT {
849 var BSC_ConnHdlr vc_conn;
850 f_init();
851
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +0100852 vc_conn := f_start_handler(refers(f_tc_lu_by_imei), 12);
Harald Welteba7b6d92018-01-23 21:32:34 +0100853 vc_conn.done;
854}
855
856/* Test LU by TMSI with unknown TMSI, expect (and answer) ID REQ. */
857private function f_tc_lu_tmsi_noauth_unknown(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Stefan Sperling04fc4bc2018-06-25 17:44:57 +0200858 /* We piggyback a test for an MSC crash on overlong IMSI (OS#2864) onto this test. */
859 var hexstring overlong_imsi := '012345789ABCDEF0123456789ABCDEF'H;
Harald Weltea10db902018-01-27 12:44:49 +0100860 f_init_handler(pars);
Harald Welteba7b6d92018-01-23 21:32:34 +0100861
862 var PDU_ML3_MS_NW l3_lu := f_build_lu_tmsi('01020304'O); /* FIXME: Random */
863 var PDU_DTAP_MT dtap_mt;
864
865 /* tell GSUP dispatcher to send this IMSI to us */
866 f_create_gsup_expect(hex2str(g_pars.imsi));
867
868 /* Send BSSAP_Conn_Req with COMPL L3 INFO to MSC */
869 f_bssap_compl_l3(l3_lu);
870
871 /* Send Early Classmark, just for the fun of it */
872 BSSAP.send(ts_BSSMAP_ClassmarkUpd(g_pars.cm2, g_pars.cm3));
873
874 /* Wait for + respond to ID REQ (IMSI) */
875 BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_MM_ID_Req('001'B)));
Stefan Sperling04fc4bc2018-06-25 17:44:57 +0200876 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 +0100877 BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_MM_ID_Rsp_IMSI(g_pars.imsi)));
878
879 /* Expect MSC to do UpdateLocation to HLR; respond to it */
880 GSUP.receive(tr_GSUP_UL_REQ(g_pars.imsi));
881 GSUP.send(ts_GSUP_ISD_REQ(g_pars.imsi, g_pars.msisdn));
882 GSUP.receive(tr_GSUP_ISD_RES(g_pars.imsi));
883 GSUP.send(ts_GSUP_UL_RES(g_pars.imsi));
884
885 alt {
Harald Welte7ec4fa82018-01-27 10:57:40 +0100886 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Acc)) {
887 BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_TmsiRealloc_Cmpl));
888 }
Harald Welteba7b6d92018-01-23 21:32:34 +0100889 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Rej)) {
890 setverdict(fail, "Expected LU ACK, but received REJ");
Daniel Willmannafce8662018-07-06 23:11:32 +0200891 mtc.stop;
Harald Welteba7b6d92018-01-23 21:32:34 +0100892 }
893 }
894
Philipp Maier9b690e42018-12-21 11:50:03 +0100895 /* Wait for MM-Information (if enabled) */
896 f_expect_mm_info();
897
Harald Welteba7b6d92018-01-23 21:32:34 +0100898 /* wait for normal teardown */
Harald Welte1ddc7162018-01-27 14:25:46 +0100899 f_expect_clear();
Harald Welteba7b6d92018-01-23 21:32:34 +0100900}
901testcase TC_lu_by_tmsi_noauth_unknown() runs on MTC_CT {
902 var BSC_ConnHdlr vc_conn;
903 f_init();
904
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +0100905 vc_conn := f_start_handler(refers(f_tc_lu_tmsi_noauth_unknown), 13);
Harald Welteba7b6d92018-01-23 21:32:34 +0100906 vc_conn.done;
907}
908
909
Harald Welte45164da2018-01-24 12:51:27 +0100910/* Test IMSI DETACH (MI=IMSI) */
911private function f_tc_imsi_detach_by_imsi(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +0100912 f_init_handler(pars);
Harald Welte45164da2018-01-24 12:51:27 +0100913
914 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
915
916 /* Send BSSAP_Conn_Req with COMPL L3 INFO to MSC */
917 f_bssap_compl_l3(valueof(ts_ML3_MO_MM_IMSI_DET_Ind(mi)));
918
919 /* Send Early Classmark, just for the fun of it? */
920 BSSAP.send(ts_BSSMAP_ClassmarkUpd(g_pars.cm2, g_pars.cm3));
921
922 /* wait for normal teardown */
Harald Welte1ddc7162018-01-27 14:25:46 +0100923 f_expect_clear();
Harald Welte45164da2018-01-24 12:51:27 +0100924}
925testcase TC_imsi_detach_by_imsi() runs on MTC_CT {
926 var BSC_ConnHdlr vc_conn;
927 f_init();
928
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +0100929 vc_conn := f_start_handler(refers(f_tc_imsi_detach_by_imsi), 14);
Harald Welte45164da2018-01-24 12:51:27 +0100930 vc_conn.done;
931}
932
933/* Test IMSI DETACH (MI=TMSI) */
934private function f_tc_imsi_detach_by_tmsi(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +0100935 f_init_handler(pars);
Harald Welte45164da2018-01-24 12:51:27 +0100936
937 var MobileIdentityLV mi := valueof(ts_MI_TMSI_LV('01020304'O));
938
939 /* Send BSSAP_Conn_Req with COMPL L3 INFO to MSC */
940 f_bssap_compl_l3(valueof(ts_ML3_MO_MM_IMSI_DET_Ind(mi)));
941
942 /* Send Early Classmark, just for the fun of it? */
943 BSSAP.send(ts_BSSMAP_ClassmarkUpd(g_pars.cm2, g_pars.cm3));
944
945 /* wait for normal teardown */
Harald Welte1ddc7162018-01-27 14:25:46 +0100946 f_expect_clear();
Harald Welte45164da2018-01-24 12:51:27 +0100947}
948testcase TC_imsi_detach_by_tmsi() runs on MTC_CT {
949 var BSC_ConnHdlr vc_conn;
950 f_init();
951
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +0100952 vc_conn := f_start_handler(refers(f_tc_imsi_detach_by_tmsi), 15);
Harald Welte45164da2018-01-24 12:51:27 +0100953 vc_conn.done;
954}
955
956/* Test IMSI DETACH (MI=IMEI), which is illegal */
957private function f_tc_imsi_detach_by_imei(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +0100958 f_init_handler(pars);
Harald Welte45164da2018-01-24 12:51:27 +0100959
Harald Welte256571e2018-01-24 18:47:19 +0100960 var MobileIdentityLV mi := valueof(ts_MI_IMEI_LV(g_pars.imei));
Harald Welte45164da2018-01-24 12:51:27 +0100961
962 /* Send BSSAP_Conn_Req with COMPL L3 INFO to MSC */
963 f_bssap_compl_l3(valueof(ts_ML3_MO_MM_IMSI_DET_Ind(mi)));
964
965 /* Send Early Classmark, just for the fun of it? */
966 BSSAP.send(ts_BSSMAP_ClassmarkUpd(g_pars.cm2, g_pars.cm3));
967
968 /* wait for normal teardown */
Harald Welte1ddc7162018-01-27 14:25:46 +0100969 f_expect_clear();
Harald Welte45164da2018-01-24 12:51:27 +0100970}
971testcase TC_imsi_detach_by_imei() runs on MTC_CT {
972 var BSC_ConnHdlr vc_conn;
973 f_init();
974
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +0100975 vc_conn := f_start_handler(refers(f_tc_imsi_detach_by_imei), 16);
Harald Welte45164da2018-01-24 12:51:27 +0100976 vc_conn.done;
977}
978
979
980/* helper function for an emergency call. caller passes in mobile identity to use */
981private function f_emerg_call(MobileIdentityLV mi) runs on BSC_ConnHdlr {
Harald Welte0bef21e2018-02-10 09:48:23 +0100982 var CallParameters cpars := valueof(t_CallParams('112'H, 0));
983 cpars.emergency := true;
Philipp Maierf1e02bb2018-03-15 16:30:00 +0100984 cpars.mgcp_ep := "rtpbridge/1@mgw";
Harald Welte45164da2018-01-24 12:51:27 +0100985
Harald Welte0bef21e2018-02-10 09:48:23 +0100986 f_mo_call(cpars);
Harald Welte45164da2018-01-24 12:51:27 +0100987}
988
989/* establish an emergency call by IMEI, no SIM inserted (and hence no IMSI) */
990private function f_tc_emerg_call_imei_reject(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +0100991 f_init_handler(pars);
Harald Welte45164da2018-01-24 12:51:27 +0100992
Harald Welte256571e2018-01-24 18:47:19 +0100993 var MobileIdentityLV mi := valueof(ts_MI_IMEI_LV(g_pars.imei));
Harald Welte6ed6bf92018-01-24 21:09:15 +0100994 var PDU_ML3_MS_NW l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_EMERG_CALL, mi));
Harald Welte45164da2018-01-24 12:51:27 +0100995 f_bssap_compl_l3(l3_info);
996 BSSAP.receive(tr_PDU_DTAP_MT(tr_CM_SERV_REJ('05'O)));
Harald Welte1ddc7162018-01-27 14:25:46 +0100997 f_expect_clear();
Harald Welte45164da2018-01-24 12:51:27 +0100998}
999testcase TC_emerg_call_imei_reject() runs on MTC_CT {
1000 var BSC_ConnHdlr vc_conn;
1001 f_init();
1002
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001003 vc_conn := f_start_handler(refers(f_tc_emerg_call_imei_reject), 17);
Harald Welte45164da2018-01-24 12:51:27 +01001004 vc_conn.done;
1005}
1006
Harald Welted5b91402018-01-24 18:48:16 +01001007/* establish an emergency call by IMSI, SIM inserted (and hence IMSI) */
Harald Welte45164da2018-01-24 12:51:27 +01001008private function f_tc_emerg_call_imsi(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +01001009 f_init_handler(pars);
Harald Welte45164da2018-01-24 12:51:27 +01001010 /* First perform location update to ensure subscriber is known */
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +01001011 f_perform_lu();
Harald Welte45164da2018-01-24 12:51:27 +01001012 /* Then issue emergency call identified by IMSI */
1013 f_emerg_call(valueof(ts_MI_IMSI_LV(g_pars.imsi)));
1014}
1015testcase TC_emerg_call_imsi() runs on MTC_CT {
1016 var BSC_ConnHdlr vc_conn;
1017 f_init();
1018
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001019 vc_conn := f_start_handler(refers(f_tc_emerg_call_imsi), 18);
Harald Welte45164da2018-01-24 12:51:27 +01001020 vc_conn.done;
1021}
1022
1023/* CM Service Request for VGCS -> reject */
1024private function f_tc_cm_serv_req_vgcs_reject(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +01001025 f_init_handler(pars);
Harald Welte45164da2018-01-24 12:51:27 +01001026
1027 /* First perform location update to ensure subscriber is known */
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +01001028 f_perform_lu();
Harald Welte45164da2018-01-24 12:51:27 +01001029
1030 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
Harald Welte6ed6bf92018-01-24 21:09:15 +01001031 var PDU_ML3_MS_NW l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_VGCS, mi));
Harald Welte45164da2018-01-24 12:51:27 +01001032 f_bssap_compl_l3(l3_info);
1033 BSSAP.receive(tr_PDU_DTAP_MT(tr_CM_SERV_REJ(int2oct(32,1))));
Harald Welte1ddc7162018-01-27 14:25:46 +01001034 f_expect_clear();
Harald Welte45164da2018-01-24 12:51:27 +01001035}
1036testcase TC_cm_serv_req_vgcs_reject() runs on MTC_CT {
1037 var BSC_ConnHdlr vc_conn;
1038 f_init();
1039
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001040 vc_conn := f_start_handler(refers(f_tc_cm_serv_req_vgcs_reject), 19);
Harald Welte45164da2018-01-24 12:51:27 +01001041 vc_conn.done;
1042}
1043
1044/* CM Service Request for VBS -> reject */
1045private function f_tc_cm_serv_req_vbs_reject(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +01001046 f_init_handler(pars);
Harald Welte45164da2018-01-24 12:51:27 +01001047
1048 /* First perform location update to ensure subscriber is known */
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +01001049 f_perform_lu();
Harald Welte45164da2018-01-24 12:51:27 +01001050
1051 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
Harald Welte6ed6bf92018-01-24 21:09:15 +01001052 var PDU_ML3_MS_NW l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_VBS, mi));
Harald Welte45164da2018-01-24 12:51:27 +01001053 f_bssap_compl_l3(l3_info);
1054 BSSAP.receive(tr_PDU_DTAP_MT(tr_CM_SERV_REJ(int2oct(32,1))));
Harald Welte1ddc7162018-01-27 14:25:46 +01001055 f_expect_clear();
Harald Welte45164da2018-01-24 12:51:27 +01001056}
1057testcase TC_cm_serv_req_vbs_reject() runs on MTC_CT {
1058 var BSC_ConnHdlr vc_conn;
1059 f_init();
1060
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001061 vc_conn := f_start_handler(refers(f_tc_cm_serv_req_vbs_reject), 20);
Harald Welte45164da2018-01-24 12:51:27 +01001062 vc_conn.done;
1063}
1064
1065/* CM Service Request for LCS -> reject */
1066private function f_tc_cm_serv_req_lcs_reject(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +01001067 f_init_handler(pars);
Harald Welte45164da2018-01-24 12:51:27 +01001068
1069 /* First perform location update to ensure subscriber is known */
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +01001070 f_perform_lu();
Harald Welte45164da2018-01-24 12:51:27 +01001071
1072 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
Harald Welte6ed6bf92018-01-24 21:09:15 +01001073 var PDU_ML3_MS_NW l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_LCS, mi));
Harald Welte45164da2018-01-24 12:51:27 +01001074 f_bssap_compl_l3(l3_info);
1075 BSSAP.receive(tr_PDU_DTAP_MT(tr_CM_SERV_REJ(int2oct(32,1))));
Harald Welte1ddc7162018-01-27 14:25:46 +01001076 f_expect_clear();
Harald Welte45164da2018-01-24 12:51:27 +01001077}
1078testcase TC_cm_serv_req_lcs_reject() runs on MTC_CT {
1079 var BSC_ConnHdlr vc_conn;
1080 f_init();
1081
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001082 vc_conn := f_start_handler(refers(f_tc_cm_serv_req_lcs_reject), 21);
Harald Welte45164da2018-01-24 12:51:27 +01001083 vc_conn.done;
1084}
1085
Harald Welte0195ab12018-01-24 21:50:20 +01001086/* CM Re-Establishment Request */
1087private function f_tc_cm_reest_req_reject(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +01001088 f_init_handler(pars);
Harald Welte0195ab12018-01-24 21:50:20 +01001089
1090 /* First perform location update to ensure subscriber is known */
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +01001091 f_perform_lu();
Harald Welte0195ab12018-01-24 21:50:20 +01001092
1093 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
1094 var PDU_ML3_MS_NW l3_info := valueof(ts_CM_REEST_REQ(0, mi));
1095 f_bssap_compl_l3(l3_info);
1096 BSSAP.receive(tr_PDU_DTAP_MT(tr_CM_SERV_REJ(int2oct(32,1))));
Harald Welte1ddc7162018-01-27 14:25:46 +01001097 f_expect_clear();
Harald Welte0195ab12018-01-24 21:50:20 +01001098}
1099testcase TC_cm_reest_req_reject() runs on MTC_CT {
1100 var BSC_ConnHdlr vc_conn;
1101 f_init();
Harald Welte0195ab12018-01-24 21:50:20 +01001102
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001103 vc_conn := f_start_handler(refers(f_tc_cm_reest_req_reject), 22);
Harald Welte0195ab12018-01-24 21:50:20 +01001104 vc_conn.done;
1105}
1106
Harald Weltec638f4d2018-01-24 22:00:36 +01001107/* Test LU (with authentication enabled), with wrong response from MS */
1108private function f_tc_lu_auth_2G_fail(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +01001109 f_init_handler(pars);
Harald Weltec638f4d2018-01-24 22:00:36 +01001110
1111 var PDU_ML3_MS_NW l3_lu := f_build_lu_imsi(g_pars.imsi)
1112
1113 /* tell GSUP dispatcher to send this IMSI to us */
1114 f_create_gsup_expect(hex2str(g_pars.imsi));
1115
1116 /* Send BSSAP_Conn_Req with COMPL L3 INFO to MSC */
1117 f_bssap_compl_l3(l3_lu);
1118
1119 /* Send Early Classmark, just for the fun of it */
1120 BSSAP.send(ts_BSSMAP_ClassmarkUpd(g_pars.cm2, g_pars.cm3));
1121
1122 var AuthVector vec := f_gen_auth_vec_2g();
1123 var GSUP_IE auth_tuple := valueof(ts_GSUP_IE_AuthTuple2G(vec.rand, vec.sres, vec.kc));
1124 GSUP.receive(tr_GSUP_SAI_REQ(g_pars.imsi));
1125 GSUP.send(ts_GSUP_SAI_RES(g_pars.imsi, auth_tuple));
1126
1127 BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_MM_AUTH_REQ(vec.rand)));
1128 /* Send back wrong auth response */
1129 BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MT_MM_AUTH_RESP_2G('00000000'O)));
1130
1131 /* Expect GSUP AUTH FAIL REP to HLR */
1132 GSUP.receive(tr_GSUP_AUTH_FAIL_IND(g_pars.imsi));
1133
1134 /* Expect LU REJECT with Cause == Illegal MS */
1135 BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Rej('03'O)));
Harald Welte1ddc7162018-01-27 14:25:46 +01001136 f_expect_clear();
Harald Weltec638f4d2018-01-24 22:00:36 +01001137}
1138testcase TC_lu_auth_2G_fail() runs on MTC_CT {
1139 var BSC_ConnHdlr vc_conn;
1140 f_init();
1141 f_vty_config(MSCVTY, "network", "authentication required");
Harald Weltec638f4d2018-01-24 22:00:36 +01001142
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001143 vc_conn := f_start_handler(refers(f_tc_lu_auth_2G_fail), 23);
Harald Weltec638f4d2018-01-24 22:00:36 +01001144 vc_conn.done;
1145}
1146
Harald Weltede371492018-01-27 23:44:41 +01001147/* A5/1 + A5/3 permitted on network side, and MS capable to do it */
Harald Welte16114282018-01-24 22:41:21 +01001148private 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 +01001149 pars.net.expect_auth := true;
1150 pars.net.expect_ciph := true;
Harald Weltea10db902018-01-27 12:44:49 +01001151 f_init_handler(pars);
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +01001152 f_perform_lu();
Harald Welte16114282018-01-24 22:41:21 +01001153}
1154testcase TC_lu_imsi_auth_tmsi_encr_13_13() runs on MTC_CT {
1155 var BSC_ConnHdlr vc_conn;
1156 f_init();
1157 f_vty_config(MSCVTY, "network", "authentication required");
Harald Welte16114282018-01-24 22:41:21 +01001158 f_vty_config(MSCVTY, "network", "encryption a5 1 3");
1159
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001160 vc_conn := f_start_handler(refers(f_tc_lu_imsi_auth_tmsi_encr_13_13), 24);
Harald Welte16114282018-01-24 22:41:21 +01001161 vc_conn.done;
1162}
1163
Harald Welte1af6ea82018-01-25 18:33:15 +01001164/* Test Complete L3 without payload */
1165private function f_tc_cl3_no_payload(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +01001166 f_init_handler(pars);
Harald Welte1af6ea82018-01-25 18:33:15 +01001167
1168 /* Send Complete L3 Info with empty L3 frame */
1169 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_peer, g_pars.sccp_addr_own,
1170 valueof(ts_BSSMAP_ComplL3(g_pars.cell_id, ''O))));
1171
Harald Weltef466eb42018-01-27 14:26:54 +01001172 timer T := 5.0;
1173 T.start;
Harald Welte1af6ea82018-01-25 18:33:15 +01001174 alt {
1175 [] BSSAP.receive(BSSAP_Conn_Prim:MSC_CONN_PRIM_DISC_IND) {}
1176 /* Expect LU REJECT with Cause == Illegal MS */
Harald Weltebdb3c452018-03-18 22:43:06 +01001177 [] BSSAP.receive(tr_PDU_DTAP_MT(?)) { repeat; }
1178 [] BSSAP.receive(BSSAP_Conn_Prim:MSC_CONN_PRIM_CONF_IND) { repeat; }
Harald Welte5946b332018-03-18 23:32:21 +01001179 [] as_clear_cmd_compl_disc();
Harald Weltef466eb42018-01-27 14:26:54 +01001180 [] T.timeout {
Daniel Willmann90829d62018-02-15 17:45:14 +01001181 setverdict(fail, "Timeout waiting for ClearCommand or SCCP Release");
Daniel Willmannafce8662018-07-06 23:11:32 +02001182 mtc.stop;
Harald Weltef466eb42018-01-27 14:26:54 +01001183 }
Harald Welte1af6ea82018-01-25 18:33:15 +01001184 }
1185 setverdict(pass);
1186}
1187testcase TC_cl3_no_payload() runs on MTC_CT {
1188 var BSC_ConnHdlr vc_conn;
1189 f_init();
1190
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001191 vc_conn := f_start_handler(refers(f_tc_cl3_no_payload), 25);
Harald Welte1af6ea82018-01-25 18:33:15 +01001192 vc_conn.done;
1193}
1194
1195/* Test Complete L3 with random payload */
1196private function f_tc_cl3_rnd_payload(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +01001197 f_init_handler(pars);
Harald Welte1af6ea82018-01-25 18:33:15 +01001198
Daniel Willmannaa14a382018-07-26 08:29:45 +02001199 /* length is limited by PDU_BSSAP length field which includes some
1200 * other fields beside l3info payload. So payl can only be 240 bytes
1201 * Since rnd() returns values < 1 multiply with 241
1202 */
1203 var integer len := float2int(rnd() * 241.0);
Harald Welte1af6ea82018-01-25 18:33:15 +01001204 var octetstring payl := f_rnd_octstring(len);
1205
1206 /* Send Complete L3 Info with empty L3 frame */
1207 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_peer, g_pars.sccp_addr_own,
1208 valueof(ts_BSSMAP_ComplL3(g_pars.cell_id, payl))));
1209
Harald Weltef466eb42018-01-27 14:26:54 +01001210 timer T := 5.0;
1211 T.start;
Harald Welte1af6ea82018-01-25 18:33:15 +01001212 alt {
1213 /* Immediate disconnect */
1214 [] BSSAP.receive(BSSAP_Conn_Prim:MSC_CONN_PRIM_DISC_IND) {}
Harald Welte1af6ea82018-01-25 18:33:15 +01001215 [] BSSAP.receive(tr_PDU_DTAP_MT(?)) { repeat; }
Harald Weltebdb3c452018-03-18 22:43:06 +01001216 [] BSSAP.receive(BSSAP_Conn_Prim:MSC_CONN_PRIM_CONF_IND) { repeat; }
Harald Welte5946b332018-03-18 23:32:21 +01001217 [] as_clear_cmd_compl_disc();
Harald Weltef466eb42018-01-27 14:26:54 +01001218 [] T.timeout {
Daniel Willmann90829d62018-02-15 17:45:14 +01001219 setverdict(fail, "Timeout waiting for ClearCommand or SCCP Release");
Daniel Willmannafce8662018-07-06 23:11:32 +02001220 mtc.stop;
Harald Weltef466eb42018-01-27 14:26:54 +01001221 }
Harald Welte1af6ea82018-01-25 18:33:15 +01001222 }
1223 setverdict(pass);
1224}
1225testcase TC_cl3_rnd_payload() runs on MTC_CT {
1226 var BSC_ConnHdlr vc_conn;
1227 f_init();
1228
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001229 vc_conn := f_start_handler(refers(f_tc_cl3_rnd_payload), 26);
Harald Welte1af6ea82018-01-25 18:33:15 +01001230 vc_conn.done;
1231}
1232
Harald Welte116e4332018-01-26 22:17:48 +01001233/* Test Complete L3 with random payload */
1234private function f_tc_establish_and_nothing(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +01001235 f_init_handler(pars);
Harald Welte116e4332018-01-26 22:17:48 +01001236
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +01001237 f_perform_lu();
Harald Welte116e4332018-01-26 22:17:48 +01001238
Harald Welteb9e86fa2018-04-09 18:18:31 +02001239 f_establish_fully();
Daniel Willmann898a7e02018-05-17 12:16:16 +02001240 f_expect_clear(10.0);
Harald Welte116e4332018-01-26 22:17:48 +01001241}
1242testcase TC_establish_and_nothing() runs on MTC_CT {
1243 var BSC_ConnHdlr vc_conn;
1244 f_init();
1245
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001246 vc_conn := f_start_handler(refers(f_tc_establish_and_nothing), 27);
Harald Welte116e4332018-01-26 22:17:48 +01001247 vc_conn.done;
1248}
1249
Harald Welte12510c52018-01-26 22:26:24 +01001250/* Test MO Call SETUP with no response from MNCC */
1251private function f_tc_mo_setup_and_nothing(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Philipp Maier109e6aa2018-10-17 10:53:32 +02001252 f_init_handler(pars, 190.0);
Harald Weltea10db902018-01-27 12:44:49 +01001253
Harald Welte12510c52018-01-26 22:26:24 +01001254 var CallParameters cpars := valueof(t_CallParams('12345'H, 0));
1255
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +01001256 f_perform_lu();
Harald Welte12510c52018-01-26 22:26:24 +01001257
Harald Welteb9e86fa2018-04-09 18:18:31 +02001258 f_establish_fully();
Harald Welte12510c52018-01-26 22:26:24 +01001259 f_create_mncc_expect(hex2str(cpars.called_party));
1260 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
1261
1262 BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_CC_SETUP(cpars.transaction_id, cpars.called_party)));
1263
Philipp Maier109e6aa2018-10-17 10:53:32 +02001264 f_expect_clear(185.0);
Harald Welte12510c52018-01-26 22:26:24 +01001265}
1266testcase TC_mo_setup_and_nothing() runs on MTC_CT {
1267 var BSC_ConnHdlr vc_conn;
1268 f_init();
1269
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001270 vc_conn := f_start_handler(refers(f_tc_mo_setup_and_nothing), 28);
Harald Welte12510c52018-01-26 22:26:24 +01001271 vc_conn.done;
1272}
1273
Harald Welte3ab88002018-01-26 22:37:25 +01001274/* Test MO Call with no response to RAN-side CRCX */
1275private function f_tc_mo_crcx_ran_timeout(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +01001276 f_init_handler(pars);
Harald Welte3ab88002018-01-26 22:37:25 +01001277 var CallParameters cpars := valueof(t_CallParams('12345'H, 0));
1278 var MNCC_PDU mncc;
1279 var MgcpCommand mgcp_cmd;
1280
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +01001281 f_perform_lu();
Harald Welte3ab88002018-01-26 22:37:25 +01001282
Harald Welteb9e86fa2018-04-09 18:18:31 +02001283 f_establish_fully();
Harald Welte3ab88002018-01-26 22:37:25 +01001284 f_create_mncc_expect(hex2str(cpars.called_party));
1285 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
1286
1287 BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_CC_SETUP(cpars.transaction_id, cpars.called_party)));
1288 MNCC.receive(tr_MNCC_SETUP_ind(?, tr_MNCC_number(hex2str(cpars.called_party)))) -> value mncc;
1289 cpars.mncc_callref := mncc.u.signal.callref;
1290 MNCC.send(ts_MNCC_CALL_PROC_req(cpars.mncc_callref, cpars.mncc_bearer_cap));
1291 BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_CC_CALL_PROC(cpars.transaction_id)));
1292
1293 MGCP.receive(tr_CRCX) -> value mgcp_cmd;
Harald Welte1852a842018-01-26 22:53:36 +01001294 cpars.mgcp_call_id := f_MgcpCmd_extract_call_id(mgcp_cmd);
1295 cpars.mgcp_ep := mgcp_cmd.line.ep;
Harald Welte3ab88002018-01-26 22:37:25 +01001296 /* never respond to this */
1297
Philipp Maier8e58f592018-03-14 11:10:56 +01001298 /* When the connection with the MGW fails, the MSC will first request
1299 * a release via call control. We will answer this request normally. */
1300 BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_CC_RELEASE(cpars.transaction_id)));
1301 BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_CC_REL_COMPL(cpars.transaction_id)));
1302
Harald Welte1ddc7162018-01-27 14:25:46 +01001303 f_expect_clear(30.0);
Harald Welte3ab88002018-01-26 22:37:25 +01001304}
1305testcase TC_mo_crcx_ran_timeout() runs on MTC_CT {
1306 var BSC_ConnHdlr vc_conn;
1307 f_init();
1308
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001309 vc_conn := f_start_handler(refers(f_tc_mo_crcx_ran_timeout), 29);
Harald Welte3ab88002018-01-26 22:37:25 +01001310 vc_conn.done;
1311}
1312
Harald Welte0cc82d92018-01-26 22:52:34 +01001313/* Test MO Call with reject to RAN-side CRCX */
1314private function f_tc_mo_crcx_ran_reject(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +01001315 f_init_handler(pars);
Harald Welte0cc82d92018-01-26 22:52:34 +01001316 var CallParameters cpars := valueof(t_CallParams('12345'H, 0));
1317 var MNCC_PDU mncc;
1318 var MgcpCommand mgcp_cmd;
1319
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +01001320 f_perform_lu();
Harald Welte0cc82d92018-01-26 22:52:34 +01001321
Harald Welteb9e86fa2018-04-09 18:18:31 +02001322 f_establish_fully();
Harald Welte0cc82d92018-01-26 22:52:34 +01001323 f_create_mncc_expect(hex2str(cpars.called_party));
1324 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
1325
1326 BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_CC_SETUP(cpars.transaction_id, cpars.called_party)));
1327 MNCC.receive(tr_MNCC_SETUP_ind(?, tr_MNCC_number(hex2str(cpars.called_party)))) -> value mncc;
1328 cpars.mncc_callref := mncc.u.signal.callref;
1329 MNCC.send(ts_MNCC_CALL_PROC_req(cpars.mncc_callref, cpars.mncc_bearer_cap));
1330 BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_CC_CALL_PROC(cpars.transaction_id)));
1331
1332 MGCP.receive(tr_CRCX) -> value mgcp_cmd;
Philipp Maierf1e02bb2018-03-15 16:30:00 +01001333
1334 /* Detect if the received CRCX is a wildcarded CRCX request. If yes,
1335 * set an endpoint name that fits the pattern. If not, just use the
1336 * endpoint name from the request */
1337 if (match(mgcp_cmd.line.ep, t_MGCP_EP_wildcard)) {
1338 cpars.mgcp_ep := "rtpbridge/1@mgw";
1339 } else {
1340 cpars.mgcp_ep := mgcp_cmd.line.ep;
1341 }
1342
Harald Welte0cc82d92018-01-26 22:52:34 +01001343 cpars.mgcp_call_id := f_MgcpCmd_extract_call_id(mgcp_cmd);
Philipp Maierf1e02bb2018-03-15 16:30:00 +01001344
Harald Welte0cc82d92018-01-26 22:52:34 +01001345 /* Respond to CRCX with error */
1346 var MgcpResponse mgcp_rsp := {
1347 line := {
1348 code := "542",
1349 trans_id := mgcp_cmd.line.trans_id,
1350 string := "FORCED_FAIL"
1351 },
Harald Welte0cc82d92018-01-26 22:52:34 +01001352 sdp := omit
1353 }
Philipp Maierf1e02bb2018-03-15 16:30:00 +01001354 var MgcpParameter mgcp_rsp_param := {
1355 code := "Z",
1356 val := cpars.mgcp_ep
1357 };
1358 mgcp_rsp.params[0] := mgcp_rsp_param;
Harald Welte0cc82d92018-01-26 22:52:34 +01001359 MGCP.send(mgcp_rsp);
1360
1361 timer T := 30.0;
1362 T.start;
1363 alt {
Daniel Willmannafce8662018-07-06 23:11:32 +02001364 [] T.timeout {
1365 setverdict(fail, "Timeout waiting for channel release");
1366 mtc.stop;
1367 }
Daniel Willmann5868e622018-02-15 17:42:59 +01001368 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_CC_RELEASE(cpars.transaction_id))) {
1369 BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_CC_REL_COMPL(cpars.transaction_id)));
1370 repeat;
1371 }
Harald Welte0cc82d92018-01-26 22:52:34 +01001372 [] MNCC.receive { repeat; }
1373 [] GSUP.receive { repeat; }
Philipp Maierc6e06f72018-04-11 18:12:23 +02001374 /* Note: As we did not respond properly to the CRCX from the MSC we
1375 * expect the MSC to omit any further MGCP operation (At least in the
1376 * the current implementation, there is no recovery mechanism implemented
1377 * and a DLCX can not be performed as the MSC does not know a specific
1378 * endpoint yet. */
Daniel Willmannafce8662018-07-06 23:11:32 +02001379 [] MGCP.receive {
1380 setverdict(fail, "Unexpected MGCP message");
1381 mtc.stop;
1382 }
Harald Welte5946b332018-03-18 23:32:21 +01001383 [] as_clear_cmd_compl_disc();
Harald Welte0cc82d92018-01-26 22:52:34 +01001384 }
1385}
1386testcase TC_mo_crcx_ran_reject() runs on MTC_CT {
1387 var BSC_ConnHdlr vc_conn;
1388 f_init();
1389
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001390 vc_conn := f_start_handler(refers(f_tc_mo_crcx_ran_reject), 30);
Harald Welte0cc82d92018-01-26 22:52:34 +01001391 vc_conn.done;
1392}
1393
Harald Welte3ab88002018-01-26 22:37:25 +01001394
Harald Welte812f7a42018-01-27 00:49:18 +01001395/* helper function to start a MT call: MNCC SETUP; Paging; DChan est.; DTAP SETUP */
1396private function f_mt_call_start(inout CallParameters cpars) runs on BSC_ConnHdlr {
1397 var MNCC_PDU mncc;
1398 var MgcpCommand mgcp_cmd;
1399 var OCT4 tmsi;
1400
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +01001401 f_perform_lu();
Harald Welte812f7a42018-01-27 00:49:18 +01001402 if (isvalue(g_pars.tmsi)) {
1403 tmsi := g_pars.tmsi;
1404 } else {
1405 tmsi := 'FFFFFFFF'O;
1406 }
1407 f_bssmap_register_imsi(g_pars.imsi, tmsi);
1408
1409 /* Allocate call reference and send SETUP via MNCC to MSC */
1410 cpars.mncc_callref := f_rnd_int(2147483648);
1411 MNCC.send(ts_MNCC_SETUP_req(cpars.mncc_callref, hex2str(g_pars.msisdn),
1412 hex2str(cpars.called_party), hex2str(g_pars.imsi)));
1413
1414 /* MSC->BSC: expect PAGING from MSC */
1415 BSSAP.receive(tr_BSSMAP_Paging(g_pars.imsi));
1416 /* MS -> MSC: PAGING RESPONSE */
Harald Welteb9e86fa2018-04-09 18:18:31 +02001417 f_establish_fully(EST_TYPE_PAG_RESP);
Harald Welte812f7a42018-01-27 00:49:18 +01001418
1419 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
1420
1421 /* MSC->MS: SETUP */
1422 BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_CC_SETUP(cpars.transaction_id, *, cpars.called_party)));
1423}
1424
1425/* Test MT Call */
1426private function f_tc_mt_crcx_ran_reject(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltea10db902018-01-27 12:44:49 +01001427 f_init_handler(pars);
Harald Welte812f7a42018-01-27 00:49:18 +01001428 var CallParameters cpars := valueof(t_CallParams('123456'H, 0));
1429 var MNCC_PDU mncc;
1430 var MgcpCommand mgcp_cmd;
1431
1432 f_mt_call_start(cpars);
1433
1434 /* MS->MSC: CALL CONFIRMED */
1435 BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_CC_CALL_CONF(cpars.transaction_id)));
1436
1437 MNCC.receive(tr_MNCC_CALL_CONF_ind(cpars.mncc_callref));
1438
1439 MGCP.receive(tr_CRCX) -> value mgcp_cmd;
1440 cpars.mgcp_call_id := f_MgcpCmd_extract_call_id(mgcp_cmd);
Philipp Maierf1e02bb2018-03-15 16:30:00 +01001441
1442 /* Detect if the received CRCX is a wildcarded CRCX request. If yes,
1443 * set an endpoint name that fits the pattern. If not, just use the
1444 * endpoint name from the request */
1445 if (match(mgcp_cmd.line.ep, t_MGCP_EP_wildcard)) {
1446 cpars.mgcp_ep := "rtpbridge/1@mgw";
1447 } else {
1448 cpars.mgcp_ep := mgcp_cmd.line.ep;
1449 }
1450
Harald Welte812f7a42018-01-27 00:49:18 +01001451 /* Respond to CRCX with error */
1452 var MgcpResponse mgcp_rsp := {
1453 line := {
1454 code := "542",
1455 trans_id := mgcp_cmd.line.trans_id,
1456 string := "FORCED_FAIL"
1457 },
Harald Welte812f7a42018-01-27 00:49:18 +01001458 sdp := omit
1459 }
Philipp Maierf1e02bb2018-03-15 16:30:00 +01001460 var MgcpParameter mgcp_rsp_param := {
1461 code := "Z",
1462 val := cpars.mgcp_ep
1463 };
1464 mgcp_rsp.params[0] := mgcp_rsp_param;
Harald Welte812f7a42018-01-27 00:49:18 +01001465 MGCP.send(mgcp_rsp);
1466
1467 timer T := 30.0;
1468 T.start;
1469 alt {
Daniel Willmannafce8662018-07-06 23:11:32 +02001470 [] T.timeout {
1471 setverdict(fail, "Timeout waiting for channel release");
1472 mtc.stop;
1473 }
Harald Welte812f7a42018-01-27 00:49:18 +01001474 [] BSSAP.receive { repeat; }
1475 [] MNCC.receive { repeat; }
1476 [] GSUP.receive { repeat; }
1477 [] MGCP.receive(tr_DLCX(?)) -> value mgcp_cmd {
1478 MGCP.send(ts_DLCX_ACK2(mgcp_cmd.line.trans_id));
1479 f_create_mgcp_delete_ep(cpars.mgcp_ep);
1480 repeat;
1481 }
1482 [] MGCP.receive { repeat; }
Harald Welte5946b332018-03-18 23:32:21 +01001483 [] as_clear_cmd_compl_disc();
Harald Welte812f7a42018-01-27 00:49:18 +01001484 }
1485}
1486testcase TC_mt_crcx_ran_reject() runs on MTC_CT {
1487 var BSC_ConnHdlr vc_conn;
1488 f_init();
1489
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001490 vc_conn := f_start_handler(refers(f_tc_mt_crcx_ran_reject), 31);
Harald Welte812f7a42018-01-27 00:49:18 +01001491 vc_conn.done;
1492}
1493
1494
1495/* Test MT Call T310 timer */
1496private function f_tc_mt_t310(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
Harald Weltead2952e2018-01-27 14:12:46 +01001497 f_init_handler(pars, 200.0);
Harald Welte812f7a42018-01-27 00:49:18 +01001498 var CallParameters cpars := valueof(t_CallParams('123456'H, 0));
1499 var MNCC_PDU mncc;
1500 var MgcpCommand mgcp_cmd;
1501
1502 f_mt_call_start(cpars);
1503
1504 /* MS->MSC: CALL CONFIRMED */
1505 BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_CC_CALL_CONF(cpars.transaction_id)));
1506 MNCC.receive(tr_MNCC_CALL_CONF_ind(cpars.mncc_callref));
1507
1508 MGCP.receive(tr_CRCX) -> value mgcp_cmd;
1509 cpars.mgcp_call_id := f_MgcpCmd_extract_call_id(mgcp_cmd);
1510 cpars.mgcp_ep := mgcp_cmd.line.ep;
1511 /* FIXME: Respond to CRCX */
1512
1513 /* old libosmocore T310 default timeout is 180s. so let's wait 190 */
1514 timer T := 190.0;
1515 T.start;
1516 alt {
Daniel Willmannafce8662018-07-06 23:11:32 +02001517 [] T.timeout {
1518 setverdict(fail, "Timeout waiting for T310");
1519 mtc.stop;
1520 }
Harald Welte812f7a42018-01-27 00:49:18 +01001521 [] MNCC.receive(tr_MNCC_DISC_ind(cpars.mncc_callref)) {
1522 MNCC.send(ts_MNCC_REL_req(cpars.mncc_callref, valueof(ts_MNCC_cause(23))));
1523 }
1524 }
1525 BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_CC_DISC(cpars.transaction_id)));
1526 BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_CC_RELEASE(cpars.transaction_id)));
1527 /* FIXME: We're sending this with TIflag 0: allocated by sender, which is wrong */
1528 BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_CC_REL_COMPL(cpars.transaction_id)));
1529
1530 alt {
Harald Welte812f7a42018-01-27 00:49:18 +01001531 [] MGCP.receive(tr_DLCX(?)) -> value mgcp_cmd {
1532 MGCP.send(ts_DLCX_ACK2(mgcp_cmd.line.trans_id));
1533 f_create_mgcp_delete_ep(cpars.mgcp_ep);
1534 repeat;
1535 }
Harald Welte5946b332018-03-18 23:32:21 +01001536 [] as_clear_cmd_compl_disc();
Harald Welte812f7a42018-01-27 00:49:18 +01001537 }
1538}
1539testcase TC_mt_t310() runs on MTC_CT {
1540 var BSC_ConnHdlr vc_conn;
1541 f_init();
1542
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001543 vc_conn := f_start_handler(refers(f_tc_mt_t310), 32);
Harald Welte812f7a42018-01-27 00:49:18 +01001544 vc_conn.done;
1545}
1546
Harald Welte167458a2018-01-27 15:58:16 +01001547/* Perform successful LU + MO call, then GSUP LocationCancel. Subscriber must be denied CM SERV */
1548private function f_tc_gsup_cancel(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
1549 f_init_handler(pars);
1550 var CallParameters cpars := valueof(t_CallParams('12345'H, 0));
1551 cpars.bss_rtp_port := 1110;
1552 cpars.mgcp_connection_id_bss := '22222'H;
1553 cpars.mgcp_connection_id_mss := '33333'H;
Daniel Willmann9b0235b2018-07-24 12:13:34 +02001554 cpars.mgcp_ep := "rtpbridge/1@mgw";
Harald Welte167458a2018-01-27 15:58:16 +01001555
1556 /* Location Update to make subscriber known */
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +01001557 f_perform_lu();
Harald Welte167458a2018-01-27 15:58:16 +01001558
1559 /* First MO call should succeed */
1560 f_mo_call(cpars);
1561
1562 /* Cancel the subscriber in the VLR */
1563 GSUP.send(ts_GSUP_CL_REQ(g_pars.imsi, OSMO_GSUP_CANCEL_TYPE_WITHDRAW));
1564 alt {
1565 [] GSUP.receive(tr_GSUP_CL_RES(g_pars.imsi)) { }
1566 [] GSUP.receive(tr_GSUP_CL_ERR(g_pars.imsi)) {
1567 setverdict(fail, "Received GSUP Location Cancel Error");
Daniel Willmannafce8662018-07-06 23:11:32 +02001568 mtc.stop;
Harald Welte167458a2018-01-27 15:58:16 +01001569 }
1570 }
1571
1572 /* Follow-up transactions should fail */
1573 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
1574 var PDU_ML3_MS_NW l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, mi));
1575 f_bssap_compl_l3(l3_info);
1576 alt {
1577 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_CM_SERV_REJ)) { }
1578 [] BSSAP.receive {
1579 setverdict(fail, "Received unexpected BSSAP instead of CM SERV REJ");
Daniel Willmannafce8662018-07-06 23:11:32 +02001580 mtc.stop;
Harald Welte167458a2018-01-27 15:58:16 +01001581 }
1582 }
1583 setverdict(pass);
1584}
1585testcase TC_gsup_cancel() runs on MTC_CT {
1586 var BSC_ConnHdlr vc_conn;
1587 f_init();
1588
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001589 vc_conn := f_start_handler(refers(f_tc_gsup_cancel), 33);
Harald Welte167458a2018-01-27 15:58:16 +01001590 vc_conn.done;
1591}
1592
Harald Welte9de84792018-01-28 01:06:35 +01001593/* A5/1 only permitted on network side, and MS capable to do it */
1594private function f_tc_lu_imsi_auth_tmsi_encr_1_13(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
1595 pars.net.expect_auth := true;
1596 pars.net.expect_ciph := true;
1597 pars.net.kc_support := '02'O; /* A5/1 only */
1598 f_init_handler(pars);
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +01001599 f_perform_lu();
Harald Welte9de84792018-01-28 01:06:35 +01001600}
1601testcase TC_lu_imsi_auth_tmsi_encr_1_13() runs on MTC_CT {
1602 var BSC_ConnHdlr vc_conn;
1603 f_init();
1604 f_vty_config(MSCVTY, "network", "authentication required");
1605 f_vty_config(MSCVTY, "network", "encryption a5 1");
1606
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001607 vc_conn := f_start_handler(refers(f_tc_lu_imsi_auth_tmsi_encr_1_13), 34);
Harald Welte9de84792018-01-28 01:06:35 +01001608 vc_conn.done;
1609}
1610
1611/* A5/3 only permitted on network side, and MS capable to do it */
1612private function f_tc_lu_imsi_auth_tmsi_encr_3_13(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
1613 pars.net.expect_auth := true;
1614 pars.net.expect_ciph := true;
1615 pars.net.kc_support := '08'O; /* A5/3 only */
1616 f_init_handler(pars);
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +01001617 f_perform_lu();
Harald Welte9de84792018-01-28 01:06:35 +01001618}
1619testcase TC_lu_imsi_auth_tmsi_encr_3_13() runs on MTC_CT {
1620 var BSC_ConnHdlr vc_conn;
1621 f_init();
1622 f_vty_config(MSCVTY, "network", "authentication required");
1623 f_vty_config(MSCVTY, "network", "encryption a5 3");
1624
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001625 vc_conn := f_start_handler(refers(f_tc_lu_imsi_auth_tmsi_encr_3_13), 35);
Harald Welte9de84792018-01-28 01:06:35 +01001626 vc_conn.done;
1627}
1628
1629/* A5/3 only permitted on network side, and MS with only A5/1 support */
1630private function f_tc_lu_imsi_auth_tmsi_encr_3_1(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
1631 pars.net.expect_auth := true;
1632 pars.net.expect_ciph := true;
1633 pars.net.kc_support := '08'O; /* A5/3 only */
1634 pars.cm2.classmarkInformationType2_oct5.a5_3 := '0'B;
1635 f_init_handler(pars, 15.0);
1636
1637 /* cannot use f_perform_lu() as we expect a reject */
1638 var PDU_ML3_MS_NW l3_lu := f_build_lu_imsi(g_pars.imsi);
1639 f_create_gsup_expect(hex2str(g_pars.imsi));
1640 f_bssap_compl_l3(l3_lu);
Neels Hofmeyr29b8da02018-03-01 18:09:45 +01001641 if (pars.send_early_cm) {
1642 BSSAP.send(ts_BSSMAP_ClassmarkUpd(g_pars.cm2, g_pars.cm3));
1643 } else {
1644 pars.cm1.esind := '0'B;
1645 }
Harald Welte9de84792018-01-28 01:06:35 +01001646 f_mm_auth();
1647 alt {
Daniel Willmann52918e52018-09-20 14:39:09 +02001648 [] BSSAP.receive(tr_BSSMAP_ClassmarkReq) {
1649 BSSAP.send(ts_BSSMAP_ClassmarkUpd(g_pars.cm2, g_pars.cm3));
1650 repeat;
1651 }
Harald Welte5946b332018-03-18 23:32:21 +01001652 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Rej)) {
1653 f_expect_clear();
1654 }
Harald Welte9de84792018-01-28 01:06:35 +01001655 [] BSSAP.receive(tr_BSSMAP_CipherModeCmd(?,?)) {
1656 setverdict(fail, "CipherModeCommand despite no A5 intersection");
Daniel Willmannafce8662018-07-06 23:11:32 +02001657 mtc.stop;
Harald Welte9de84792018-01-28 01:06:35 +01001658 }
1659 [] BSSAP.receive {
Harald Welte458fd372018-03-21 11:26:23 +01001660 setverdict(fail, "Unknown/unexpected BSSAP received");
Daniel Willmannafce8662018-07-06 23:11:32 +02001661 mtc.stop;
Harald Welte9de84792018-01-28 01:06:35 +01001662 }
1663 }
1664 setverdict(pass);
1665}
1666testcase TC_lu_imsi_auth_tmsi_encr_3_1() runs on MTC_CT {
1667 var BSC_ConnHdlr vc_conn;
1668 f_init();
1669 f_vty_config(MSCVTY, "network", "authentication required");
1670 f_vty_config(MSCVTY, "network", "encryption a5 3");
1671
Neels Hofmeyr29b8da02018-03-01 18:09:45 +01001672 vc_conn := f_start_handler(refers(f_tc_lu_imsi_auth_tmsi_encr_3_1), 360);
1673 vc_conn.done;
1674}
1675testcase TC_lu_imsi_auth_tmsi_encr_3_1_no_cm() runs on MTC_CT {
1676 var BSC_ConnHdlrPars pars;
1677 var BSC_ConnHdlr vc_conn;
1678 f_init();
1679 f_vty_config(MSCVTY, "network", "authentication required");
1680 f_vty_config(MSCVTY, "network", "encryption a5 3");
1681
1682 pars := f_init_pars(361);
1683 pars.send_early_cm := false;
1684 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 +01001685 vc_conn.done;
1686}
Neels Hofmeyr1b3c6e32018-03-01 17:52:21 +01001687testcase TC_lu_imsi_auth_tmsi_encr_3_1_log_msc_debug() runs on MTC_CT {
1688 var BSC_ConnHdlr vc_conn;
1689 f_init();
1690 f_vty_config(MSCVTY, "network", "authentication required");
1691 f_vty_config(MSCVTY, "network", "encryption a5 3");
1692
1693 /* Make sure the MSC category is on DEBUG level to trigger the log
1694 * message that is reported in OS#2947 to trigger the segfault */
1695 f_vty_config(MSCVTY, "log stderr", "logging level msc debug");
1696
1697 vc_conn := f_start_handler(refers(f_tc_lu_imsi_auth_tmsi_encr_3_1), 362);
1698 vc_conn.done;
1699}
Harald Welte9de84792018-01-28 01:06:35 +01001700
1701/* A5/1 + A5/3 only permitted on network side, and MS with only A5/2 support */
1702private function f_tc_lu_imsi_auth_tmsi_encr_13_2(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
1703 pars.net.expect_auth := true;
1704 pars.net.expect_ciph := true;
1705 pars.net.kc_support := '0A'O; /* A5/1 + A5/3 */
1706 pars.cm1.a5_1 := '1'B;
1707 pars.cm2.a5_1 := '1'B;
1708 pars.cm2.classmarkInformationType2_oct5.a5_3 := '0'B;
1709 pars.cm2.classmarkInformationType2_oct5.a5_2 := '1'B;
1710 f_init_handler(pars, 15.0);
1711
1712 /* cannot use f_perform_lu() as we expect a reject */
1713 var PDU_ML3_MS_NW l3_lu := f_build_lu_imsi(g_pars.imsi);
1714 f_create_gsup_expect(hex2str(g_pars.imsi));
1715 f_bssap_compl_l3(l3_lu);
1716 BSSAP.send(ts_BSSMAP_ClassmarkUpd(g_pars.cm2, g_pars.cm3));
1717 f_mm_auth();
1718 alt {
Harald Welte5946b332018-03-18 23:32:21 +01001719 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Rej)) {
1720 f_expect_clear();
1721 }
Harald Welte9de84792018-01-28 01:06:35 +01001722 [] BSSAP.receive(tr_BSSMAP_CipherModeCmd(?,?)) {
1723 setverdict(fail, "CipherModeCommand despite no A5 intersection");
Daniel Willmannafce8662018-07-06 23:11:32 +02001724 mtc.stop;
Harald Welte9de84792018-01-28 01:06:35 +01001725 }
1726 [] BSSAP.receive {
Harald Welte458fd372018-03-21 11:26:23 +01001727 setverdict(fail, "Unknown/unexpected BSSAP received");
Daniel Willmannafce8662018-07-06 23:11:32 +02001728 mtc.stop;
Harald Welte9de84792018-01-28 01:06:35 +01001729 }
1730 }
1731 setverdict(pass);
1732}
1733testcase TC_lu_imsi_auth_tmsi_encr_13_2() runs on MTC_CT {
1734 var BSC_ConnHdlr vc_conn;
1735 f_init();
1736 f_vty_config(MSCVTY, "network", "authentication required");
1737 f_vty_config(MSCVTY, "network", "encryption a5 1 3");
1738
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001739 vc_conn := f_start_handler(refers(f_tc_lu_imsi_auth_tmsi_encr_13_2), 37);
Harald Welte9de84792018-01-28 01:06:35 +01001740 vc_conn.done;
1741}
1742
1743/* A5/0 + A5/1 + A5/3 only permitted on network side, and MS with only A5/2 support */
1744private function f_tc_lu_imsi_auth_tmsi_encr_013_2(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
1745 pars.net.expect_auth := true;
1746 pars.net.expect_ciph := true;
1747 pars.net.kc_support := '0B'O; /* A5/1 + A5/3 */
1748 pars.cm1.a5_1 := '1'B;
1749 pars.cm2.a5_1 := '1'B;
1750 pars.cm2.classmarkInformationType2_oct5.a5_3 := '0'B;
1751 pars.cm2.classmarkInformationType2_oct5.a5_2 := '1'B;
1752 f_init_handler(pars, 15.0);
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +01001753 f_perform_lu();
Harald Welte9de84792018-01-28 01:06:35 +01001754}
1755testcase TC_lu_imsi_auth_tmsi_encr_013_2() runs on MTC_CT {
1756 var BSC_ConnHdlr vc_conn;
1757 f_init();
1758 f_vty_config(MSCVTY, "network", "authentication required");
1759 f_vty_config(MSCVTY, "network", "encryption a5 0 1 3");
1760
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001761 vc_conn := f_start_handler(refers(f_tc_lu_imsi_auth_tmsi_encr_013_2), 38);
Harald Welte9de84792018-01-28 01:06:35 +01001762 vc_conn.done;
1763}
1764
Harald Welte33ec09b2018-02-10 15:34:46 +01001765/* LU followed by MT call (including paging) */
1766private function f_tc_lu_and_mt_call(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
1767 f_init_handler(pars);
Stefan Sperling26d57be2018-11-12 17:03:26 +01001768 var CallParameters cpars := valueof(t_CallParams('12345'H, 0));
Harald Welte33ec09b2018-02-10 15:34:46 +01001769 cpars.bss_rtp_port := 1110;
1770 cpars.mgcp_connection_id_bss := '10004'H;
1771 cpars.mgcp_connection_id_mss := '10005'H;
1772
Philipp Maier4b2692d2018-03-14 16:37:48 +01001773 /* Note: This is an optional parameter. When the call-agent (MSC) does
1774 * supply a full endpoint name this setting will be overwritten. */
1775 cpars.mgcp_ep := "rtpbridge/1@mgw";
1776
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +01001777 f_perform_lu();
Harald Welte33ec09b2018-02-10 15:34:46 +01001778 f_mt_call(cpars);
1779}
1780testcase TC_lu_and_mt_call() runs on MTC_CT {
1781 var BSC_ConnHdlr vc_conn;
1782 f_init();
1783
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001784 vc_conn := f_start_handler(refers(f_tc_lu_and_mt_call), 39);
Harald Welte33ec09b2018-02-10 15:34:46 +01001785 vc_conn.done;
1786}
1787
Daniel Willmann8b084372018-02-04 13:35:26 +01001788/* Test MO Call SETUP with DTMF */
1789private function f_tc_mo_setup_dtmf_dup(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
1790 f_init_handler(pars);
1791 var CallParameters cpars := valueof(t_CallParams('12345'H, 0));
1792 cpars.bss_rtp_port := 1110;
1793 cpars.mgcp_connection_id_bss := '22222'H;
1794 cpars.mgcp_connection_id_mss := '33333'H;
1795
Neels Hofmeyrc1f105a2018-03-01 20:00:19 +01001796 f_perform_lu();
Daniel Willmann8b084372018-02-04 13:35:26 +01001797 f_mo_seq_dtmf_dup(cpars);
1798}
1799testcase TC_mo_setup_and_dtmf_dup() runs on MTC_CT {
1800 var BSC_ConnHdlr vc_conn;
1801 f_init();
1802
Neels Hofmeyre9b8eeb2018-03-01 20:29:58 +01001803 vc_conn := f_start_handler(refers(f_tc_mo_setup_dtmf_dup), 39);
Daniel Willmann8b084372018-02-04 13:35:26 +01001804 vc_conn.done;
1805}
Harald Welte9de84792018-01-28 01:06:35 +01001806
Philipp Maier328d1662018-03-07 10:40:27 +01001807testcase TC_cr_before_reset() runs on MTC_CT {
1808 timer T := 4.0;
1809 var boolean reset_ack_seen := false;
1810 f_init_bssap_direct();
1811
Daniel Willmann42d1d5b2018-08-07 15:18:41 +02001812 f_bssap_start(g_bssap[0]);
1813
Daniel Willmanne8018962018-08-21 14:18:00 +02001814 f_sleep(3.0);
1815
Philipp Maier328d1662018-03-07 10:40:27 +01001816 /* Make a blind connection attemt, to trigger the deadlock condition */
Philipp Maier75932982018-03-27 14:52:35 +02001817 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 +01001818
1819 /* Send a BSSMAP reset */
Philipp Maier75932982018-03-27 14:52:35 +02001820 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 +01001821 T.start
1822 alt {
1823 [] BSSAP_DIRECT.receive(tr_BSSAP_UNITDATA_ind(?, ?, tr_BSSMAP_ResetAck)) {
1824 reset_ack_seen := true;
1825 repeat;
1826 }
1827
1828 /* Acknowledge MSC sided reset requests */
1829 [] BSSAP_DIRECT.receive(tr_BSSAP_UNITDATA_ind(?, ?, tr_BSSMAP_Reset)) {
Philipp Maier75932982018-03-27 14:52:35 +02001830 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 +01001831 repeat;
1832 }
1833
1834 /* Ignore all other messages (e.g CR from the connection request) */
1835 [] BSSAP_DIRECT.receive { repeat }
1836
1837 /* If we got no BSSMAP RESET ACK back, then the MSC entered the
1838 * deadlock situation. The MSC is then unable to respond to any
1839 * further BSSMAP RESET or any other sort of traffic. */
1840 [reset_ack_seen == true] T.timeout { setverdict(pass) }
1841 [reset_ack_seen == false] T.timeout {
1842 setverdict(fail, "no BSSMAP RESET ACK seen!");
Daniel Willmannafce8662018-07-06 23:11:32 +02001843 mtc.stop;
Philipp Maier328d1662018-03-07 10:40:27 +01001844 }
1845 }
1846}
Harald Welte9de84792018-01-28 01:06:35 +01001847
Philipp Maier94f3f1b2018-03-15 18:54:13 +01001848/* Test MO Call with no response to RAN-side CRCX or DTAP Release */
1849private function f_tc_mo_release_timeout(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
1850 f_init_handler(pars);
1851 var CallParameters cpars := valueof(t_CallParams('12345'H, 0));
1852 var MNCC_PDU mncc;
1853 var MgcpCommand mgcp_cmd;
1854
1855 f_perform_lu();
1856
Harald Welteb9e86fa2018-04-09 18:18:31 +02001857 f_establish_fully();
Philipp Maier94f3f1b2018-03-15 18:54:13 +01001858 f_create_mncc_expect(hex2str(cpars.called_party));
1859 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
1860
1861 BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_CC_SETUP(cpars.transaction_id, cpars.called_party)));
1862 MNCC.receive(tr_MNCC_SETUP_ind(?, tr_MNCC_number(hex2str(cpars.called_party)))) -> value mncc;
1863 cpars.mncc_callref := mncc.u.signal.callref;
1864 MNCC.send(ts_MNCC_CALL_PROC_req(cpars.mncc_callref, cpars.mncc_bearer_cap));
1865 BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_CC_CALL_PROC(cpars.transaction_id)));
1866
1867 /* Drop CRCX */
1868 MGCP.receive(tr_CRCX) -> value mgcp_cmd;
1869
1870 /* Drop DTAP Release */
1871 BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_CC_RELEASE(cpars.transaction_id)));
1872
1873 /* Drop resent DTAP Release */
1874 BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_CC_RELEASE(cpars.transaction_id)));
1875
1876 f_expect_clear(60.0);
1877}
1878testcase TC_mo_release_timeout() runs on MTC_CT {
1879 var BSC_ConnHdlr vc_conn;
1880 f_init();
1881
1882 vc_conn := f_start_handler(refers(f_tc_mo_release_timeout), 40);
1883 vc_conn.done;
1884}
1885
Harald Welte12510c52018-01-26 22:26:24 +01001886
Philipp Maier2a98a732018-03-19 16:06:12 +01001887/* LU followed by MT call (including paging) */
1888private function f_tc_lu_and_mt_call_no_dlcx_resp(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
1889 f_init_handler(pars);
Stefan Sperling26d57be2018-11-12 17:03:26 +01001890 var CallParameters cpars := valueof(t_CallParams('12345'H, 0));
Philipp Maier2a98a732018-03-19 16:06:12 +01001891 cpars.bss_rtp_port := 1110;
1892 cpars.mgcp_connection_id_bss := '10004'H;
1893 cpars.mgcp_connection_id_mss := '10005'H;
1894
1895 /* Note: This is an optional parameter. When the call-agent (MSC) does
1896 * supply a full endpoint name this setting will be overwritten. */
1897 cpars.mgcp_ep := "rtpbridge/1@mgw";
1898
1899 /* Intentionally disable the CRCX response */
1900 cpars.mgw_drop_dlcx := true;
1901
1902 /* Perform location update and call */
1903 f_perform_lu();
1904 f_mt_call(cpars);
1905}
1906testcase TC_lu_and_mt_call_no_dlcx_resp() runs on MTC_CT {
1907 var BSC_ConnHdlr vc_conn;
1908 f_init();
1909
1910 /* Perform an almost normal looking locationupdate + mt-call, but do
1911 * not respond to the DLCX at the end of the call */
1912 vc_conn := f_start_handler(refers(f_tc_lu_and_mt_call_no_dlcx_resp), 41);
1913 vc_conn.done;
1914
1915 /* Wait a guard period until the MGCP layer in the MSC times out,
1916 * if the MSC is vulnerable to the use-after-free situation that is
1917 * fixed by I78f1b6a9149488a4ad3f120c1e190a83c07d4b89 then it should
1918 * segfault now */
1919 f_sleep(6.0);
1920
1921 /* Run the init procedures once more. If the MSC has crashed, this
1922 * this will fail */
1923 f_init();
1924}
Harald Welte45164da2018-01-24 12:51:27 +01001925
Philipp Maier75932982018-03-27 14:52:35 +02001926/* Two BSSMAP resets from two different BSCs */
1927testcase TC_reset_two() runs on MTC_CT {
1928 var BSC_ConnHdlr vc_conn;
1929 f_init(2);
1930 f_sleep(2.0);
1931 setverdict(pass);
1932}
1933
Harald Weltef640a012018-04-14 17:49:21 +02001934/***********************************************************************
1935 * SMS Testing
1936 ***********************************************************************/
1937
Harald Weltef45efeb2018-04-09 18:19:24 +02001938/* LU followed by MO SMS */
1939private function f_tc_lu_and_mo_sms(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
1940 var SmsParameters spars := valueof(t_SmsPars);
1941
1942 f_init_handler(pars);
1943
1944 /* Perform location update and call */
1945 f_perform_lu();
1946
1947 f_establish_fully(EST_TYPE_MO_SMS);
1948
1949 //spars.exp_rp_err := 96; /* invalid mandatory information */
1950 f_mo_sms(spars);
1951
1952 f_expect_clear();
1953}
1954testcase TC_lu_and_mo_sms() runs on MTC_CT {
1955 var BSC_ConnHdlr vc_conn;
1956 f_init();
1957 vc_conn := f_start_handler(refers(f_tc_lu_and_mo_sms), 42);
1958 vc_conn.done;
1959}
1960
1961private function f_vty_sms_send(charstring imsi, charstring msisdn, charstring text)
1962runs on MTC_CT {
1963 f_vty_transceive(MSCVTY, "subscriber imsi "&imsi&" sms sender msisdn "&msisdn&" send "&text);
1964}
1965
1966/* LU followed by MT SMS */
1967private function f_tc_lu_and_mt_sms(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
1968 var SmsParameters spars := valueof(t_SmsPars);
1969 var OCT4 tmsi;
1970
1971 f_init_handler(pars);
1972
1973 /* Perform location update and call */
1974 f_perform_lu();
1975
1976 /* register an 'expect' for given IMSI (+TMSI) */
1977 if (isvalue(g_pars.tmsi)) {
1978 tmsi := g_pars.tmsi;
1979 } else {
1980 tmsi := 'FFFFFFFF'O;
1981 }
1982 f_bssmap_register_imsi(g_pars.imsi, tmsi);
1983
1984 /* FIXME: actually cause MSC to send a SMS via VTY or SMPP */
1985
1986 /* MSC->BSC: expect PAGING from MSC */
1987 BSSAP.receive(tr_BSSMAP_Paging(g_pars.imsi));
1988 /* Establish DTAP / BSSAP / SCCP connection */
1989 f_establish_fully(EST_TYPE_PAG_RESP);
1990
1991 spars.tp.ud := 'C8329BFD064D9B53'O;
1992 f_mt_sms(spars);
1993
1994 f_expect_clear();
1995}
1996testcase TC_lu_and_mt_sms() runs on MTC_CT {
1997 var BSC_ConnHdlrPars pars;
1998 var BSC_ConnHdlr vc_conn;
1999 f_init();
2000 pars := f_init_pars(43);
2001 vc_conn := f_start_handler_with_pars(refers(f_tc_lu_and_mt_sms), pars);
2002 f_sleep(2.0);
2003 f_vty_sms_send(hex2str(pars.imsi), "2342", "Hello SMS");
2004 vc_conn.done;
2005}
2006
Harald Weltef640a012018-04-14 17:49:21 +02002007/* mobile originated SMS from MS/BTS/BSC side to SMPP */
2008private function f_tc_smpp_mo_sms(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
2009 var SmsParameters spars := valueof(t_SmsPars);
Harald Weltef45efeb2018-04-09 18:19:24 +02002010
Harald Weltef640a012018-04-14 17:49:21 +02002011 f_init_handler(pars);
Harald Weltef45efeb2018-04-09 18:19:24 +02002012
Harald Weltef640a012018-04-14 17:49:21 +02002013 /* Perform location update so IMSI is known + registered in MSC/VLR */
2014 f_perform_lu();
2015 f_establish_fully(EST_TYPE_MO_SMS);
2016
2017 f_mo_sms(spars);
2018
2019 var SMPP_PDU smpp;
2020 var template SMPP_PDU tr_smpp := tr_SMPP(c_SMPP_command_id_deliver_sm, ESME_ROK);
2021 tr_smpp.body.deliver_sm := {
2022 service_type := "CMT",
2023 source_addr_ton := network_specific,
2024 source_addr_npi := isdn,
2025 source_addr := hex2str(pars.msisdn),
2026 dest_addr_ton := f_sm_ton_from_gsm(spars.tp.da.tP_DA_NoPad.tP_TypeOfNumber),
2027 dest_addr_npi := f_sm_npi_from_gsm(spars.tp.da.tP_DA_NoPad.tP_NumberingPlanID),
2028 destination_addr := hex2str(spars.tp.da.tP_DA_NoPad.tP_DAValue),
2029 esm_class := '00000001'B,
2030 protocol_id := 0,
2031 priority_flag := 0,
2032 schedule_delivery_time := "",
2033 replace_if_present := 0,
2034 data_coding := '00000001'B,
2035 sm_default_msg_id := 0,
2036 sm_length := ?,
2037 short_message := spars.tp.ud,
2038 opt_pars := {
2039 {
2040 tag := user_message_reference,
2041 len := 2,
2042 opt_value := {
2043 int2_val := oct2int(spars.tp.msg_ref)
2044 }
2045 }
2046 }
2047 };
2048 alt {
2049 [] SMPP.receive(tr_smpp) -> value smpp {
2050 SMPP.send(ts_SMPP_DELIVER_SM_resp(ESME_ROK, smpp.header.seq_num));
2051 }
2052 [] SMPP.receive(tr_SMPP(c_SMPP_command_id_alert_notification, ESME_ROK)) { repeat; }
2053 }
2054
2055 f_expect_clear();
2056}
2057testcase TC_smpp_mo_sms() runs on MTC_CT {
2058 var BSC_ConnHdlr vc_conn;
2059 f_init();
2060 f_vty_config2(MSCVTY, { "smpp", "esme msc_tester"}, "default-route");
2061 vc_conn := f_start_handler(refers(f_tc_smpp_mo_sms), 44);
2062 vc_conn.done;
2063 f_vty_config2(MSCVTY, { "smpp", "esme msc_tester"}, "no default-route");
2064}
2065
Vadim Yanitskiy103d09f2018-11-12 02:50:23 +07002066/* Test MO-SMS from MS/BTS/BSC towards HLR (via GSUP) */
2067private function f_tc_gsup_mo_sms(charstring id, BSC_ConnHdlrPars pars)
2068runs on BSC_ConnHdlr {
2069 var SmsParameters spars := valueof(t_SmsPars);
2070 var GSUP_PDU gsup_msg_rx;
2071 var octetstring sm_tpdu;
2072
2073 f_init_handler(pars);
2074
2075 /* We need to inspect GSUP activity */
2076 f_create_gsup_expect(hex2str(g_pars.imsi));
2077
2078 /* Perform location update */
2079 f_perform_lu();
2080
2081 /* Send CM Service Request for SMS */
2082 f_establish_fully(EST_TYPE_MO_SMS);
2083
2084 /* Prepare expected SM-RP-UI (SM TPDU) */
2085 enc_TPDU_RP_DATA_MS_SGSN_fast(
2086 valueof(ts_SMS_SUBMIT(spars.tp.msg_ref,
2087 spars.tp.da, spars.tp.pid, spars.tp.dcs,
2088 spars.tp.udl, spars.tp.ud)),
2089 sm_tpdu);
2090
2091 var template GSUP_PDU mo_forwardSM := tr_GSUP_MO_FORWARD_SM_REQ(
2092 imsi := g_pars.imsi,
2093 sm_rp_mr := spars.rp.msg_ref,
2094 /* FIXME: extract SM-RP-DA from spars.rp.dest */
2095 sm_rp_da := tr_GSUP_SM_RP_DA_SMSC_ADDR(?),
2096 /* FIXME: MSISDN coding troubles */
2097 sm_rp_oa := tr_GSUP_SM_RP_OA_MSISDN(?),
2098 /* TODO: can we use decmatch here? */
2099 sm_rp_ui := sm_tpdu
2100 );
2101
2102 /* Submit an SMS on DTAP and expect MO-forwardSM-Req on GSUP */
2103 f_mo_sms_submit(spars);
2104 alt {
2105 [] GSUP.receive(mo_forwardSM) -> value gsup_msg_rx {
2106 log("RX MO-forwardSM-Req");
2107 log(gsup_msg_rx);
2108 setverdict(pass);
2109 }
2110 [] GSUP.receive {
2111 log("RX unexpected GSUP message");
2112 setverdict(fail);
2113 mtc.stop;
2114 }
2115 }
2116
2117 /* Trigger RP-ACK by sending MO-forwardSM-Res */
2118 GSUP.send(valueof(ts_GSUP_MO_FORWARD_SM_RES(
2119 imsi := g_pars.imsi,
2120 sm_rp_mr := spars.rp.msg_ref)));
2121 /* Expect RP-ACK on DTAP */
2122 f_mo_sms_wait_rp_ack(spars);
2123
2124 f_expect_clear();
2125}
2126testcase TC_gsup_mo_sms() runs on MTC_CT {
2127 var BSC_ConnHdlr vc_conn;
2128 f_init();
2129 f_vty_config(MSCVTY, "msc", "sms-over-gsup");
2130 vc_conn := f_start_handler(refers(f_tc_gsup_mo_sms), 88);
2131 vc_conn.done;
2132 f_vty_config(MSCVTY, "msc", "no sms-over-gsup");
2133}
2134
Vadim Yanitskiy9cc019a2018-11-15 02:06:07 +07002135/* Test MO-SMMA from MS/BTS/BSC towards HLR (via GSUP) */
2136private function f_tc_gsup_mo_smma(charstring id, BSC_ConnHdlrPars pars)
2137runs on BSC_ConnHdlr {
2138 var SmsParameters spars := valueof(t_SmsPars);
2139 var GSUP_PDU gsup_msg_rx;
2140
2141 f_init_handler(pars);
2142
2143 /* We need to inspect GSUP activity */
2144 f_create_gsup_expect(hex2str(g_pars.imsi));
2145
2146 /* Perform location update */
2147 f_perform_lu();
2148
2149 /* Send CM Service Request for SMS */
2150 f_establish_fully(EST_TYPE_MO_SMS);
2151
2152 var template GSUP_PDU mo_ReadyForSM := tr_GSUP_MO_READY_FOR_SM_REQ(
2153 imsi := g_pars.imsi,
2154 sm_rp_mr := spars.rp.msg_ref,
2155 sm_alert_rsn := GSUP_SM_ALERT_RSN_TYPE_MEM_AVAIL
2156 );
2157
2158 /* Submit an SMS on DTAP and expect MO-forwardSM-Req on GSUP */
2159 f_mo_smma(spars);
2160 alt {
2161 [] GSUP.receive(mo_ReadyForSM) -> value gsup_msg_rx {
2162 log("RX MO-ReadyForSM-Req");
2163 log(gsup_msg_rx);
2164 setverdict(pass);
2165 }
2166 [] GSUP.receive {
2167 log("RX unexpected GSUP message");
2168 setverdict(fail);
2169 mtc.stop;
2170 }
2171 }
2172
2173 /* Trigger RP-ACK by sending MO-forwardSM-Res */
2174 GSUP.send(valueof(ts_GSUP_MO_READY_FOR_SM_RES(
2175 imsi := g_pars.imsi,
2176 sm_rp_mr := spars.rp.msg_ref)));
2177 /* Expect RP-ACK on DTAP */
2178 f_mo_sms_wait_rp_ack(spars);
2179
2180 f_expect_clear();
2181}
2182testcase TC_gsup_mo_smma() runs on MTC_CT {
2183 var BSC_ConnHdlr vc_conn;
2184 f_init();
2185 f_vty_config(MSCVTY, "msc", "sms-over-gsup");
2186 vc_conn := f_start_handler(refers(f_tc_gsup_mo_smma), 89);
2187 vc_conn.done;
2188 f_vty_config(MSCVTY, "msc", "no sms-over-gsup");
2189}
2190
Harald Weltef640a012018-04-14 17:49:21 +02002191/* convert GSM L3 TON to SMPP_TON enum */
2192function f_sm_ton_from_gsm(BIT3 ton) return SMPP_TON {
2193 select (ton) {
2194 case ('000'B) { return unknown; }
2195 case ('001'B) { return international; }
2196 case ('010'B) { return national; }
2197 case ('011'B) { return network_specific; }
2198 case ('100'B) { return subscriber_number; }
2199 case ('101'B) { return alphanumeric; }
2200 case ('110'B) { return abbreviated; }
2201 }
2202 setverdict(fail, "Unknown TON ", ton);
Daniel Willmannafce8662018-07-06 23:11:32 +02002203 mtc.stop;
Harald Weltef640a012018-04-14 17:49:21 +02002204}
2205/* convert GSM L3 NPI to SMPP_NPI enum */
2206function f_sm_npi_from_gsm(BIT4 npi) return SMPP_NPI {
2207 select (npi) {
2208 case ('0000'B) { return unknown; }
2209 case ('0001'B) { return isdn; }
2210 case ('0011'B) { return data; }
2211 case ('0100'B) { return telex; }
2212 case ('0110'B) { return land_mobile; }
2213 case ('1000'B) { return national; }
2214 case ('1001'B) { return private_; }
2215 case ('1010'B) { return ermes; }
2216 }
2217 setverdict(fail, "Unknown NPI ", npi);
Daniel Willmannafce8662018-07-06 23:11:32 +02002218 mtc.stop;
Harald Weltef640a012018-04-14 17:49:21 +02002219}
2220
2221/* build a SMPP_SM from SmsParameters */
2222function f_mt_sm_from_spars(SmsParameters spars)
2223runs on BSC_ConnHdlr return SMPP_SM {
2224 var SMPP_SM sm := {
2225 service_type := "CMT",
2226 source_addr_ton := f_sm_ton_from_gsm(spars.tp.da.tP_DA_NoPad.tP_TypeOfNumber),
2227 source_addr_npi := f_sm_npi_from_gsm(spars.tp.da.tP_DA_NoPad.tP_NumberingPlanID),
2228 source_addr := hex2str(spars.tp.da.tP_DA_NoPad.tP_DAValue),
2229 dest_addr_ton := international,
2230 dest_addr_npi := isdn,
2231 destination_addr := hex2str(g_pars.msisdn),
2232 esm_class := '00000001'B,
2233 protocol_id := 0,
2234 priority_flag := 0,
2235 schedule_delivery_time := "",
2236 validity_period := "",
2237 registered_delivery := '00000000'B,
2238 replace_if_present := 0,
2239 data_coding := '00000001'B,
2240 sm_default_msg_id := 0,
2241 sm_length := spars.tp.udl,
2242 short_message := spars.tp.ud,
2243 opt_pars := {}
2244 };
2245 return sm;
2246}
2247
2248/* helper function to encode SMS from 'spars', send it via SMPP to MSC; receive it on MS side */
2249private function f_smpp_mt_sms(SmsParameters spars, boolean trans_mode) runs on BSC_ConnHdlr {
2250 var SMPP_SM sm := f_mt_sm_from_spars(spars);
2251 if (trans_mode) {
2252 sm.esm_class := '00000010'B;
2253 }
2254
2255 /* actually cause MSC to send a SMS via SUBMIT-SM from SMPP side */
2256 SMPP.send(ts_SMPP_SUBMIT_SM(sm));
2257 if (not match(sm.esm_class, tr_ESM_CLASS_TRANSACTION)) {
2258 /* if we're not in SMPP transaction mode, we expect the SMPP-level ACK
2259 * before we expect the SMS delivery on the BSC/radio side */
2260 SMPP.receive(tr_SMPP(c_SMPP_command_id_submit_sm_resp, ESME_ROK));
2261 }
2262
2263 /* MSC->BSC: expect PAGING from MSC */
2264 BSSAP.receive(tr_BSSMAP_Paging(g_pars.imsi));
2265 /* Establish DTAP / BSSAP / SCCP connection */
2266 f_establish_fully(EST_TYPE_PAG_RESP);
2267 SMPP.receive(tr_SMPP(c_SMPP_command_id_alert_notification, ESME_ROK));
2268
2269 f_mt_sms(spars);
2270
2271 if (match(sm.esm_class, tr_ESM_CLASS_TRANSACTION)) {
2272 SMPP.receive(tr_SMPP(c_SMPP_command_id_submit_sm_resp, ESME_ROK));
2273 }
2274 f_expect_clear();
2275}
2276
2277/* mobile terminated SMS, from SMPP to BSC/BTS/MS */
2278private function f_tc_smpp_mt_sms(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
2279 f_init_handler(pars);
2280
2281 /* Perform location update so IMSI is known + registered in MSC/VLR */
2282 f_perform_lu();
2283 SMPP.receive(tr_SMPP(c_SMPP_command_id_alert_notification, ESME_ROK));
2284
2285 /* register an 'expect' for given IMSI (+TMSI) */
2286 var OCT4 tmsi;
2287 if (isvalue(g_pars.tmsi)) {
2288 tmsi := g_pars.tmsi;
2289 } else {
2290 tmsi := 'FFFFFFFF'O;
2291 }
2292 f_bssmap_register_imsi(g_pars.imsi, tmsi);
2293
2294 var SmsParameters spars := valueof(t_SmsPars);
2295 /* TODO: test with more intelligent user data; test different coding schemes */
2296 spars.tp.ud := '00'O;
2297 spars.tp.udl := 1;
2298
2299 /* first test the non-transaction store+forward mode */
2300 f_smpp_mt_sms(spars, false);
2301
2302 /* then test the transaction mode */
2303 f_smpp_mt_sms(spars, true);
2304}
2305testcase TC_smpp_mt_sms() runs on MTC_CT {
2306 var BSC_ConnHdlr vc_conn;
2307 f_init();
2308 vc_conn := f_start_handler(refers(f_tc_smpp_mt_sms), 45);
2309 vc_conn.done;
2310}
2311
Vadim Yanitskiy7d1f9182018-05-28 16:21:42 +07002312/***********************************************************************
2313 * USSD Testing
2314 ***********************************************************************/
2315
Vadim Yanitskiyce8cc372018-06-21 01:46:33 +07002316private altstep as_unexp_gsup_or_bssap_msg()
2317runs on BSC_ConnHdlr {
2318 [] GSUP.receive {
2319 setverdict(fail, "Unknown/unexpected GSUP received");
2320 self.stop;
2321 }
2322 [] BSSAP.receive {
2323 setverdict(fail, "Unknown/unexpected BSSAP message received");
2324 self.stop;
2325 }
2326}
2327
2328private function f_expect_gsup_msg(template GSUP_PDU msg)
2329runs on BSC_ConnHdlr return GSUP_PDU {
2330 var GSUP_PDU gsup_msg_complete;
2331
2332 alt {
2333 [] GSUP.receive(msg) -> value gsup_msg_complete {
2334 setverdict(pass);
2335 }
2336 /* We don't expect anything else */
2337 [] as_unexp_gsup_or_bssap_msg();
2338 }
2339
2340 return gsup_msg_complete;
2341}
2342
2343private function f_expect_mt_dtap_msg(template PDU_ML3_NW_MS msg)
2344runs on BSC_ConnHdlr return PDU_ML3_NW_MS {
2345 var PDU_DTAP_MT bssap_msg_complete;
2346
2347 alt {
2348 [] BSSAP.receive(tr_PDU_DTAP_MT(msg)) -> value bssap_msg_complete {
2349 setverdict(pass);
2350 }
2351 /* We don't expect anything else */
2352 [] as_unexp_gsup_or_bssap_msg();
2353 }
2354
2355 return bssap_msg_complete.dtap;
2356}
2357
Vadim Yanitskiy2a978b92018-06-19 17:51:20 +07002358/* LU followed by MO USSD request */
2359private function f_tc_lu_and_mo_ussd_single_request(charstring id, BSC_ConnHdlrPars pars)
Vadim Yanitskiy7d1f9182018-05-28 16:21:42 +07002360runs on BSC_ConnHdlr {
2361 f_init_handler(pars);
2362
2363 /* Perform location update */
2364 f_perform_lu();
2365
2366 /* Send CM Service Request for SS/USSD */
2367 f_establish_fully(EST_TYPE_SS_ACT);
2368
Vadim Yanitskiy747689e2018-06-19 00:14:28 +07002369 /* We need to inspect GSUP activity */
2370 f_create_gsup_expect(hex2str(g_pars.imsi));
2371
2372 var template OCTN facility_req := f_USSD_FACILITY_IE_INVOKE(
2373 invoke_id := 5, /* Phone may not start from 0 or 1 */
2374 op_code := SS_OP_CODE_PROCESS_USS_REQ,
2375 ussd_string := "*#100#"
2376 );
2377
2378 var template OCTN facility_rsp := f_USSD_FACILITY_IE_RETURN_RESULT(
2379 invoke_id := 5, /* InvokeID shall be the same for both REQ and RSP */
2380 op_code := SS_OP_CODE_PROCESS_USS_REQ,
2381 ussd_string := "Your extension is " & hex2str(g_pars.msisdn) & "\r"
2382 )
2383
Vadim Yanitskiy7d1f9182018-05-28 16:21:42 +07002384 /* Compose a new SS/REGISTER message with request */
2385 var template (value) PDU_ML3_MS_NW ussd_req := ts_ML3_MO_SS_REGISTER(
2386 tid := 1, /* We just need a single transaction */
2387 ti_flag := c_TIF_ORIG, /* Sent from the side that originates the TI */
Vadim Yanitskiy747689e2018-06-19 00:14:28 +07002388 facility := valueof(facility_req)
Vadim Yanitskiy7d1f9182018-05-28 16:21:42 +07002389 );
2390
2391 /* Compose SS/RELEASE_COMPLETE template with expected response */
2392 var template PDU_ML3_NW_MS ussd_rsp := tr_ML3_MT_SS_RELEASE_COMPLETE(
2393 tid := 1, /* Response should arrive within the same transaction */
2394 ti_flag := c_TIF_REPL, /* Sent to the side that originates the TI */
Vadim Yanitskiy747689e2018-06-19 00:14:28 +07002395 facility := valueof(facility_rsp)
Vadim Yanitskiy7d1f9182018-05-28 16:21:42 +07002396 );
2397
Vadim Yanitskiy747689e2018-06-19 00:14:28 +07002398 /* Compose expected MSC -> HLR message */
2399 var template GSUP_PDU gsup_req := tr_GSUP_PROC_SS_REQ(
2400 imsi := g_pars.imsi,
2401 state := OSMO_GSUP_SESSION_STATE_BEGIN,
2402 ss := valueof(facility_req)
2403 );
2404
2405 /* To be used for sending response with correct session ID */
2406 var GSUP_PDU gsup_req_complete;
2407
2408 /* Request own number */
Vadim Yanitskiy7d1f9182018-05-28 16:21:42 +07002409 BSSAP.send(ts_PDU_DTAP_MO(ussd_req));
Vadim Yanitskiy747689e2018-06-19 00:14:28 +07002410 /* Expect GSUP message containing the SS payload */
2411 gsup_req_complete := f_expect_gsup_msg(gsup_req);
2412
2413 /* Compose the response from HLR using received session ID */
2414 var template GSUP_PDU gsup_rsp := ts_GSUP_PROC_SS_REQ(
2415 imsi := g_pars.imsi,
2416 sid := gsup_req_complete.ies[1].val.session_id,
2417 state := OSMO_GSUP_SESSION_STATE_END,
2418 ss := valueof(facility_rsp)
2419 );
2420
2421 /* Finally, HLR terminates the session */
2422 GSUP.send(gsup_rsp);
2423 /* Expect RELEASE_COMPLETE message with the response */
2424 f_expect_mt_dtap_msg(ussd_rsp);
Vadim Yanitskiy7d1f9182018-05-28 16:21:42 +07002425
2426 f_expect_clear();
2427}
Vadim Yanitskiy2a978b92018-06-19 17:51:20 +07002428testcase TC_lu_and_mo_ussd_single_request() runs on MTC_CT {
Vadim Yanitskiy7d1f9182018-05-28 16:21:42 +07002429 var BSC_ConnHdlr vc_conn;
2430 f_init();
Vadim Yanitskiy2a978b92018-06-19 17:51:20 +07002431 vc_conn := f_start_handler(refers(f_tc_lu_and_mo_ussd_single_request), 46);
Vadim Yanitskiy7d1f9182018-05-28 16:21:42 +07002432 vc_conn.done;
2433}
2434
Vadim Yanitskiy13e4a272018-06-19 18:24:31 +07002435/* LU followed by MT USSD notification */
2436private function f_tc_lu_and_mt_ussd_notification(charstring id, BSC_ConnHdlrPars pars)
2437runs on BSC_ConnHdlr {
2438 f_init_handler(pars);
2439
2440 /* Perform location update */
2441 f_perform_lu();
2442
2443 f_bssmap_register_imsi(g_pars.imsi, g_pars.tmsi);
2444
2445 /* We need to inspect GSUP activity */
2446 f_create_gsup_expect(hex2str(g_pars.imsi));
2447
2448 /* Facility IE with network-originated USSD notification */
2449 var template OCTN facility_req := f_USSD_FACILITY_IE_INVOKE(
2450 op_code := SS_OP_CODE_USS_NOTIFY,
2451 ussd_string := "Mahlzeit!"
2452 );
2453
2454 /* Facility IE with acknowledgment to the USSD notification */
2455 var template OCTN facility_rsp := enc_SS_FacilityInformation(
2456 /* In case of USSD notification, Return Result is empty */
2457 valueof(ts_SS_USSD_FACILITY_RETURN_RESULT_EMPTY())
2458 );
2459
2460 /* Compose a new MT SS/REGISTER message with USSD notification */
2461 var template PDU_ML3_NW_MS ussd_ntf := tr_ML3_MT_SS_REGISTER(
2462 tid := 0, /* FIXME: most likely, it should be 0 */
2463 ti_flag := c_TIF_ORIG, /* Sent from the side that originates the TI */
2464 facility := valueof(facility_req)
2465 );
2466
2467 /* Compose HLR -> MSC GSUP message */
2468 var template (value) GSUP_PDU gsup_req := ts_GSUP_PROC_SS_REQ(
2469 imsi := g_pars.imsi,
2470 sid := '20000101'O,
2471 state := OSMO_GSUP_SESSION_STATE_BEGIN,
2472 ss := valueof(facility_req)
2473 );
2474
2475 /* Send it to MSC and expect Paging Request */
2476 GSUP.send(gsup_req);
2477 alt {
2478 [] BSSAP.receive(tr_BSSMAP_Paging(g_pars.imsi)) {
2479 setverdict(pass);
2480 }
2481 /* We don't expect anything else */
2482 [] as_unexp_gsup_or_bssap_msg();
2483 }
2484
2485 /* Send Paging Response and expect USSD notification */
2486 f_establish_fully(EST_TYPE_PAG_RESP);
2487 /* Expect MT REGISTER message with USSD notification */
2488 f_expect_mt_dtap_msg(ussd_ntf);
2489
2490 /* Compose a new MO SS/FACILITY message with empty response */
2491 var template (value) PDU_ML3_MS_NW ussd_rsp := ts_ML3_MO_SS_FACILITY(
2492 tid := 0, /* FIXME: it shall match the request tid */
2493 ti_flag := c_TIF_REPL, /* Sent to the side that originates the TI */
2494 facility := valueof(facility_rsp)
2495 );
2496
2497 /* Compose expected MSC -> HLR GSUP message */
2498 var template GSUP_PDU gsup_rsp := tr_GSUP_PROC_SS_REQ(
2499 imsi := g_pars.imsi,
2500 sid := '20000101'O,
2501 state := OSMO_GSUP_SESSION_STATE_CONTINUE,
2502 ss := valueof(facility_rsp)
2503 );
2504
2505 /* MS sends response to the notification */
2506 BSSAP.send(ts_PDU_DTAP_MO(ussd_rsp));
2507 /* Expect GSUP message containing the SS payload */
2508 f_expect_gsup_msg(gsup_rsp);
2509
2510 /* Compose expected MT SS/RELEASE COMPLETE message */
2511 var template PDU_ML3_NW_MS ussd_term := tr_ML3_MT_SS_RELEASE_COMPLETE(
2512 tid := 0, /* FIXME: it shall match the request tid */
2513 ti_flag := c_TIF_ORIG, /* Sent from the side that originates the TI */
2514 facility := omit
2515 );
2516
2517 /* Compose MSC -> HLR GSUP message */
2518 var template GSUP_PDU gsup_term := ts_GSUP_PROC_SS_REQ(
2519 imsi := g_pars.imsi,
2520 sid := '20000101'O,
2521 state := OSMO_GSUP_SESSION_STATE_END
2522 );
2523
2524 /* Finally, HLR terminates the session */
2525 GSUP.send(gsup_term)
2526 /* Expect MT RELEASE COMPLETE without Facility IE */
2527 f_expect_mt_dtap_msg(ussd_term);
2528
2529 f_expect_clear();
2530}
2531testcase TC_lu_and_mt_ussd_notification() runs on MTC_CT {
2532 var BSC_ConnHdlr vc_conn;
2533 f_init();
2534 vc_conn := f_start_handler(refers(f_tc_lu_and_mt_ussd_notification), 47);
2535 vc_conn.done;
2536}
2537
Vadim Yanitskiy2a978b92018-06-19 17:51:20 +07002538/* LU followed by MT call and MO USSD request during this call */
2539private function f_tc_lu_and_mo_ussd_during_mt_call(charstring id, BSC_ConnHdlrPars pars)
Vadim Yanitskiy0aaf48d2018-06-06 07:02:47 +07002540runs on BSC_ConnHdlr {
2541 f_init_handler(pars);
2542
2543 /* Call parameters taken from f_tc_lu_and_mt_call */
2544 var CallParameters cpars := valueof(t_CallParams('123456'H, 0));
2545 cpars.mgcp_connection_id_bss := '10004'H;
2546 cpars.mgcp_connection_id_mss := '10005'H;
2547 cpars.mgcp_ep := "rtpbridge/1@mgw";
2548 cpars.bss_rtp_port := 1110;
2549
2550 /* Perform location update */
2551 f_perform_lu();
2552
2553 /* Establish a MT call */
2554 f_mt_call_establish(cpars);
2555
2556 /* Hold the call for some time */
2557 f_sleep(1.0);
2558
Vadim Yanitskiy747689e2018-06-19 00:14:28 +07002559 var template OCTN facility_req := f_USSD_FACILITY_IE_INVOKE(
2560 op_code := SS_OP_CODE_PROCESS_USS_REQ,
2561 ussd_string := "*#100#"
2562 );
2563
2564 var template OCTN facility_rsp := f_USSD_FACILITY_IE_RETURN_RESULT(
2565 op_code := SS_OP_CODE_PROCESS_USS_REQ,
2566 ussd_string := "Your extension is " & hex2str(g_pars.msisdn) & "\r"
2567 )
2568
Vadim Yanitskiy0aaf48d2018-06-06 07:02:47 +07002569 /* Compose a new SS/REGISTER message with request */
2570 var template (value) PDU_ML3_MS_NW ussd_req := ts_ML3_MO_SS_REGISTER(
2571 tid := 1, /* We just need a single transaction */
2572 ti_flag := c_TIF_ORIG, /* Sent from the side that originates the TI */
Vadim Yanitskiy747689e2018-06-19 00:14:28 +07002573 facility := valueof(facility_req)
Vadim Yanitskiy0aaf48d2018-06-06 07:02:47 +07002574 );
2575
2576 /* Compose SS/RELEASE_COMPLETE template with expected response */
2577 var template PDU_ML3_NW_MS ussd_rsp := tr_ML3_MT_SS_RELEASE_COMPLETE(
2578 tid := 1, /* Response should arrive within the same transaction */
2579 ti_flag := c_TIF_REPL, /* Sent to the side that originates the TI */
Vadim Yanitskiy747689e2018-06-19 00:14:28 +07002580 facility := valueof(facility_rsp)
Vadim Yanitskiy0aaf48d2018-06-06 07:02:47 +07002581 );
2582
Vadim Yanitskiy747689e2018-06-19 00:14:28 +07002583 /* Compose expected MSC -> HLR message */
2584 var template GSUP_PDU gsup_req := tr_GSUP_PROC_SS_REQ(
2585 imsi := g_pars.imsi,
2586 state := OSMO_GSUP_SESSION_STATE_BEGIN,
2587 ss := valueof(facility_req)
2588 );
2589
2590 /* To be used for sending response with correct session ID */
2591 var GSUP_PDU gsup_req_complete;
2592
2593 /* Request own number */
Vadim Yanitskiy0aaf48d2018-06-06 07:02:47 +07002594 BSSAP.send(ts_PDU_DTAP_MO(ussd_req));
Vadim Yanitskiy747689e2018-06-19 00:14:28 +07002595 /* Expect GSUP message containing the SS payload */
2596 gsup_req_complete := f_expect_gsup_msg(gsup_req);
2597
2598 /* Compose the response from HLR using received session ID */
2599 var template GSUP_PDU gsup_rsp := ts_GSUP_PROC_SS_REQ(
2600 imsi := g_pars.imsi,
2601 sid := gsup_req_complete.ies[1].val.session_id,
2602 state := OSMO_GSUP_SESSION_STATE_END,
2603 ss := valueof(facility_rsp)
2604 );
2605
2606 /* Finally, HLR terminates the session */
2607 GSUP.send(gsup_rsp);
2608 /* Expect RELEASE_COMPLETE message with the response */
2609 f_expect_mt_dtap_msg(ussd_rsp);
Vadim Yanitskiy0aaf48d2018-06-06 07:02:47 +07002610
2611 /* Hold the call for some time */
2612 f_sleep(1.0);
2613
2614 /* Release the call (does Clear Complete itself) */
2615 f_call_hangup(cpars, true);
2616}
Vadim Yanitskiy2a978b92018-06-19 17:51:20 +07002617testcase TC_lu_and_mo_ussd_during_mt_call() runs on MTC_CT {
Vadim Yanitskiy0aaf48d2018-06-06 07:02:47 +07002618 var BSC_ConnHdlr vc_conn;
2619 f_init();
Vadim Yanitskiy2a978b92018-06-19 17:51:20 +07002620 vc_conn := f_start_handler(refers(f_tc_lu_and_mo_ussd_during_mt_call), 48);
Vadim Yanitskiy0aaf48d2018-06-06 07:02:47 +07002621 vc_conn.done;
2622}
2623
Neels Hofmeyr692c9ee2018-04-10 02:07:13 +02002624/* BSSMAP Clear Request in the middle of a call, see OS#3062 */
2625private function f_tc_mo_cc_bssmap_clear(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
2626 f_init_handler(pars);
2627 var CallParameters cpars := valueof(t_CallParams('12345'H, 0));
2628 var MNCC_PDU mncc;
2629 var MgcpCommand mgcp_cmd;
2630
2631 f_perform_lu();
2632
2633 f_establish_fully();
2634 f_create_mncc_expect(hex2str(cpars.called_party));
2635 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
2636
2637 BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_CC_SETUP(cpars.transaction_id, cpars.called_party)));
2638 MNCC.receive(tr_MNCC_SETUP_ind(?, tr_MNCC_number(hex2str(cpars.called_party)))) -> value mncc;
2639 cpars.mncc_callref := mncc.u.signal.callref;
2640 log("mncc_callref=", cpars.mncc_callref);
2641 MNCC.send(ts_MNCC_CALL_PROC_req(cpars.mncc_callref, cpars.mncc_bearer_cap));
2642 BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_CC_CALL_PROC(cpars.transaction_id)));
2643
2644 MNCC.send(ts_MNCC_ALERT_req(cpars.mncc_callref));
2645 BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_CC_ALERTING(cpars.transaction_id)));
2646 MGCP.receive(tr_CRCX);
2647
2648 f_sleep(1.0);
2649 BSSAP.send(ts_BSSMAP_ClearRequest(0));
2650
2651 MNCC.receive(tr_MNCC_REL_ind(?, ?)) -> value mncc;
2652
2653 BSSAP.receive(tr_BSSMAP_ClearCommand);
2654 BSSAP.send(ts_BSSMAP_ClearComplete);
2655
2656 f_sleep(1.0);
2657}
2658testcase TC_mo_cc_bssmap_clear() runs on MTC_CT {
2659 var BSC_ConnHdlr vc_conn;
2660 f_init();
2661
2662 vc_conn := f_start_handler(refers(f_tc_mo_cc_bssmap_clear), 43);
2663 vc_conn.done;
2664}
2665
Vadim Yanitskiy13e4a272018-06-19 18:24:31 +07002666/* LU followed by MT call and MT USSD request during this call */
2667private function f_tc_lu_and_mt_ussd_during_mt_call(charstring id, BSC_ConnHdlrPars pars)
2668runs on BSC_ConnHdlr {
2669 f_init_handler(pars);
2670
2671 /* Call parameters taken from f_tc_lu_and_mt_call */
2672 var CallParameters cpars := valueof(t_CallParams('123456'H, 0));
2673 cpars.mgcp_connection_id_bss := '10004'H;
2674 cpars.mgcp_connection_id_mss := '10005'H;
2675 cpars.mgcp_ep := "rtpbridge/1@mgw";
2676 cpars.bss_rtp_port := 1110;
2677
2678 /* Perform location update */
2679 f_perform_lu();
2680
2681 /* Establish a MT call */
2682 f_mt_call_establish(cpars);
2683
2684 /* Hold the call for some time */
2685 f_sleep(1.0);
2686
2687 var template OCTN facility_req := f_USSD_FACILITY_IE_INVOKE(
2688 op_code := SS_OP_CODE_USS_REQUEST,
2689 ussd_string := "Please type anything..."
2690 );
2691
2692 var template OCTN facility_rsp := f_USSD_FACILITY_IE_RETURN_RESULT(
2693 op_code := SS_OP_CODE_USS_REQUEST,
2694 ussd_string := "Nope."
2695 )
2696
2697 /* Compose MT SS/REGISTER message with network-originated request */
2698 var template (value) PDU_ML3_NW_MS ussd_req := ts_ML3_MT_SS_REGISTER(
2699 tid := 0, /* FIXME: most likely, it should be 0 */
2700 ti_flag := c_TIF_ORIG, /* Sent from the side that originates the TI */
2701 facility := valueof(facility_req)
2702 );
2703
2704 /* Compose HLR -> MSC GSUP message */
2705 var template (value) GSUP_PDU gsup_req := ts_GSUP_PROC_SS_REQ(
2706 imsi := g_pars.imsi,
2707 sid := '20000101'O,
2708 state := OSMO_GSUP_SESSION_STATE_BEGIN,
2709 ss := valueof(facility_req)
2710 );
2711
2712 /* Send it to MSC */
2713 GSUP.send(gsup_req);
2714 /* Expect MT REGISTER message with USSD request */
2715 f_expect_mt_dtap_msg(ussd_req);
2716
2717 /* Compose a new MO SS/FACILITY message with response */
2718 var template (value) PDU_ML3_MS_NW ussd_rsp := ts_ML3_MO_SS_FACILITY(
2719 tid := 0, /* FIXME: it shall match the request tid */
2720 ti_flag := c_TIF_REPL, /* Sent to the side that originates the TI */
2721 facility := valueof(facility_rsp)
2722 );
2723
2724 /* Compose expected MSC -> HLR GSUP message */
2725 var template GSUP_PDU gsup_rsp := tr_GSUP_PROC_SS_REQ(
2726 imsi := g_pars.imsi,
2727 sid := '20000101'O,
2728 state := OSMO_GSUP_SESSION_STATE_CONTINUE,
2729 ss := valueof(facility_rsp)
2730 );
2731
2732 /* MS sends response */
2733 BSSAP.send(ts_PDU_DTAP_MO(ussd_rsp));
2734 f_expect_gsup_msg(gsup_rsp);
2735
2736 /* Compose expected MT SS/RELEASE COMPLETE message */
2737 var template PDU_ML3_NW_MS ussd_term := tr_ML3_MT_SS_RELEASE_COMPLETE(
2738 tid := 0, /* FIXME: it shall match the request tid */
2739 ti_flag := c_TIF_ORIG, /* Sent from the side that originates the TI */
2740 facility := omit
2741 );
2742
2743 /* Compose MSC -> HLR GSUP message */
2744 var template GSUP_PDU gsup_term := ts_GSUP_PROC_SS_REQ(
2745 imsi := g_pars.imsi,
2746 sid := '20000101'O,
2747 state := OSMO_GSUP_SESSION_STATE_END
2748 );
2749
2750 /* Finally, HLR terminates the session */
2751 GSUP.send(gsup_term);
2752 /* Expect MT RELEASE COMPLETE without Facility IE */
2753 f_expect_mt_dtap_msg(ussd_term);
2754
2755 /* Hold the call for some time */
2756 f_sleep(1.0);
2757
2758 /* Release the call (does Clear Complete itself) */
2759 f_call_hangup(cpars, true);
2760}
2761testcase TC_lu_and_mt_ussd_during_mt_call() runs on MTC_CT {
2762 var BSC_ConnHdlr vc_conn;
2763 f_init();
2764 vc_conn := f_start_handler(refers(f_tc_lu_and_mt_ussd_during_mt_call), 49);
2765 vc_conn.done;
2766}
2767
Vadim Yanitskiy2daf52d2018-06-21 04:19:58 +07002768/* LU followed by MO USSD request and MO Release during transaction */
2769private function f_tc_lu_and_mo_ussd_mo_release(charstring id, BSC_ConnHdlrPars pars)
2770runs on BSC_ConnHdlr {
2771 f_init_handler(pars);
2772
2773 /* Perform location update */
2774 f_perform_lu();
2775
2776 /* Send CM Service Request for SS/USSD */
2777 f_establish_fully(EST_TYPE_SS_ACT);
2778
2779 /* We need to inspect GSUP activity */
2780 f_create_gsup_expect(hex2str(g_pars.imsi));
2781
2782 var template OCTN facility_ms_req := f_USSD_FACILITY_IE_INVOKE(
2783 invoke_id := 1, /* Initial request */
2784 op_code := SS_OP_CODE_PROCESS_USS_REQ,
2785 ussd_string := "*6766*266#"
2786 );
2787
2788 var template OCTN facility_net_req := f_USSD_FACILITY_IE_INVOKE(
2789 invoke_id := 2, /* Counter request */
2790 op_code := SS_OP_CODE_USS_REQUEST,
2791 ussd_string := "Password?!?"
2792 )
2793
2794 /* Compose MO SS/REGISTER message with request */
2795 var template (value) PDU_ML3_MS_NW ussd_ms_req := ts_ML3_MO_SS_REGISTER(
2796 tid := 1, /* We just need a single transaction */
2797 ti_flag := c_TIF_ORIG, /* Sent from the side that originates the TI */
2798 facility := valueof(facility_ms_req)
2799 );
2800
2801 /* Compose expected MSC -> HLR message */
2802 var template GSUP_PDU gsup_ms_req := tr_GSUP_PROC_SS_REQ(
2803 imsi := g_pars.imsi,
2804 state := OSMO_GSUP_SESSION_STATE_BEGIN,
2805 ss := valueof(facility_ms_req)
2806 );
2807
2808 /* To be used for sending response with correct session ID */
2809 var GSUP_PDU gsup_ms_req_complete;
2810
2811 /* Initiate a new transaction */
2812 BSSAP.send(ts_PDU_DTAP_MO(ussd_ms_req));
2813 /* Expect GSUP request with original Facility IE */
2814 gsup_ms_req_complete := f_expect_gsup_msg(gsup_ms_req);
2815
2816 /* Compose the response from HLR using received session ID */
2817 var template (value) GSUP_PDU gsup_net_req := ts_GSUP_PROC_SS_REQ(
2818 imsi := g_pars.imsi,
2819 sid := gsup_ms_req_complete.ies[1].val.session_id,
2820 state := OSMO_GSUP_SESSION_STATE_CONTINUE,
2821 ss := valueof(facility_net_req)
2822 );
2823
2824 /* Compose expected MT SS/FACILITY template with counter request */
2825 var template PDU_ML3_NW_MS ussd_net_req := tr_ML3_MT_SS_FACILITY(
2826 tid := 1, /* Response should arrive within the same transaction */
2827 ti_flag := c_TIF_REPL, /* Sent to the side that originates the TI */
2828 facility := valueof(facility_net_req)
2829 );
2830
2831 /* Send response over GSUP */
2832 GSUP.send(gsup_net_req);
2833 /* Expect MT SS/FACILITY message with counter request */
2834 f_expect_mt_dtap_msg(ussd_net_req);
2835
2836 /* Compose MO SS/RELEASE COMPLETE */
2837 var template (value) PDU_ML3_MS_NW ussd_abort := ts_ML3_MO_SS_RELEASE_COMPLETE(
2838 tid := 1, /* Response should arrive within the same transaction */
2839 ti_flag := c_TIF_ORIG, /* Sent from the side that originates the TI */
2840 facility := omit
2841 /* TODO: cause? */
2842 );
2843
2844 /* Compose expected HLR -> MSC abort message */
2845 var template GSUP_PDU gsup_abort := tr_GSUP_PROC_SS_REQ(
2846 imsi := g_pars.imsi,
2847 sid := gsup_ms_req_complete.ies[1].val.session_id,
2848 state := OSMO_GSUP_SESSION_STATE_END
2849 );
2850
2851 /* Abort transaction */
2852 BSSAP.send(ts_PDU_DTAP_MO(ussd_abort));
2853 /* Expect GSUP message indicating abort */
2854 f_expect_gsup_msg(gsup_abort);
2855
2856 f_expect_clear();
2857}
2858testcase TC_lu_and_mo_ussd_mo_release() runs on MTC_CT {
2859 var BSC_ConnHdlr vc_conn;
2860 f_init();
2861 vc_conn := f_start_handler(refers(f_tc_lu_and_mo_ussd_mo_release), 50);
2862 vc_conn.done;
2863}
2864
Vadim Yanitskiy0e392dd2018-11-29 00:47:54 +07002865/* LU followed by MO USSD request and MT Release due to timeout */
2866private function f_tc_lu_and_ss_session_timeout(charstring id, BSC_ConnHdlrPars pars)
2867runs on BSC_ConnHdlr {
2868 f_init_handler(pars);
2869
2870 /* Perform location update */
2871 f_perform_lu();
2872
2873 /* Send CM Service Request for SS/USSD */
2874 f_establish_fully(EST_TYPE_SS_ACT);
2875
2876 /* We need to inspect GSUP activity */
2877 f_create_gsup_expect(hex2str(g_pars.imsi));
2878
2879 var template OCTN facility_ms_req := f_USSD_FACILITY_IE_INVOKE(
2880 invoke_id := 1,
2881 op_code := SS_OP_CODE_PROCESS_USS_REQ,
2882 ussd_string := "#release_me");
2883
2884 /* Compose MO SS/REGISTER message with request */
2885 var template (value) PDU_ML3_MS_NW ussd_ms_req := ts_ML3_MO_SS_REGISTER(
2886 tid := 1, /* An arbitrary transaction identifier */
2887 ti_flag := c_TIF_ORIG, /* Sent from the side that originates the TI */
2888 facility := valueof(facility_ms_req));
2889
2890 /* Compose expected MSC -> HLR message */
2891 var template GSUP_PDU gsup_ms_req := tr_GSUP_PROC_SS_REQ(
2892 imsi := g_pars.imsi,
2893 state := OSMO_GSUP_SESSION_STATE_BEGIN,
2894 ss := valueof(facility_ms_req));
2895
2896 /* To be used for sending response with correct session ID */
2897 var GSUP_PDU gsup_ms_req_complete;
2898
2899 /* Initiate a new SS transaction */
2900 BSSAP.send(ts_PDU_DTAP_MO(ussd_ms_req));
2901 /* Expect GSUP request with original Facility IE */
2902 gsup_ms_req_complete := f_expect_gsup_msg(gsup_ms_req);
2903
2904 /* Don't respond, wait for timeout */
2905 f_sleep(3.0);
2906
2907 var template PDU_ML3_NW_MS dtap_rel := tr_ML3_MT_SS_RELEASE_COMPLETE(
2908 tid := 1, /* Should match the request's tid */
2909 ti_flag := c_TIF_REPL, /* Sent to the side that originates the TI */
2910 cause := *, /* TODO: expect some specific value */
2911 facility := omit);
2912
2913 var template GSUP_PDU gsup_rel := tr_GSUP_PROC_SS_ERR(
2914 imsi := g_pars.imsi,
2915 sid := gsup_ms_req_complete.ies[1].val.session_id,
2916 state := OSMO_GSUP_SESSION_STATE_END,
2917 cause := ?); /* TODO: expect some specific value */
2918
2919 /* Expect release on both interfaces */
2920 interleave {
2921 [] BSSAP.receive(tr_PDU_DTAP_MT(dtap_rel)) { };
2922 [] GSUP.receive(gsup_rel) { };
2923 }
2924
2925 f_expect_clear();
2926 setverdict(pass);
2927}
2928testcase TC_lu_and_ss_session_timeout() runs on MTC_CT {
2929 var BSC_ConnHdlr vc_conn;
2930 f_init();
Vadim Yanitskiy36d28dd2018-12-03 02:45:45 +07002931 f_vty_config(MSCVTY, "msc", "ncss guard-timeout 3");
Vadim Yanitskiy0e392dd2018-11-29 00:47:54 +07002932 vc_conn := f_start_handler(refers(f_tc_lu_and_ss_session_timeout), 51);
2933 vc_conn.done;
Vadim Yanitskiy36d28dd2018-12-03 02:45:45 +07002934 f_vty_config(MSCVTY, "msc", "ncss guard-timeout 0");
Vadim Yanitskiy0e392dd2018-11-29 00:47:54 +07002935}
2936
Stefan Sperling89eb1f32018-12-17 15:06:20 +01002937/* A5/1 only permitted on network side; attempt an invalid CIPHER MODE COMPLETE with A5/3 which MSC should reject. */
2938private function f_tc_cipher_complete_with_invalid_cipher(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
2939 pars.net.expect_auth := true;
2940 pars.net.expect_ciph := true;
2941 pars.net.kc_support := '02'O; /* A5/1 only */
2942 f_init_handler(pars);
2943
2944 g_pars.vec := f_gen_auth_vec_2g();
2945
2946 /* Can't use f_perform_lu() directly. Code below is based on it. */
2947
2948 /* tell GSUP dispatcher to send this IMSI to us */
2949 f_create_gsup_expect(hex2str(g_pars.imsi));
2950
2951 /* Send BSSAP_Conn_Req with COMPL L3 INFO to MSC */
2952 var PDU_ML3_MS_NW l3_lu := f_build_lu_imsi(g_pars.imsi)
2953 f_bssap_compl_l3(l3_lu);
2954
2955 f_mm_auth();
2956
2957 var OCT1 a5_net := f_alg_mask_from_cm(g_pars.cm2);
2958 var OCT1 a5_intersect := g_pars.net.kc_support and4b a5_net;
2959 alt {
2960 [] BSSAP.receive(tr_BSSMAP_CipherModeCmd(a5_intersect, g_pars.vec.kc)) {
2961 BSSAP.send(ts_BSSMAP_CipherModeCompl(int2oct(4 /* "accept" A5/3 */, 1)));
2962 }
2963 [] BSSAP.receive(tr_BSSMAP_CipherModeCmd(?, g_pars.vec.kc)) {
2964 setverdict(fail, "Wrong ciphering algorithm mask in CiphModCmd");
2965 mtc.stop;
2966 }
2967 [] BSSAP.receive {
2968 setverdict(fail, "Unknown/unexpected BSSAP received");
2969 mtc.stop;
2970 }
2971 }
2972
2973 /* Expect LU reject from MSC. */
2974 alt {
2975 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Rej)) {
2976 setverdict(pass);
2977 }
2978 [] BSSAP.receive {
2979 setverdict(fail, "Unknown/unexpected BSSAP received");
2980 mtc.stop;
2981 }
2982 }
Stefan Sperlingc620b352018-12-18 17:23:36 +01002983 f_expect_clear();
Stefan Sperling89eb1f32018-12-17 15:06:20 +01002984}
2985
2986testcase TC_cipher_complete_with_invalid_cipher() runs on MTC_CT {
2987 var BSC_ConnHdlr vc_conn;
2988 f_init();
2989 f_vty_config(MSCVTY, "network", "encryption a5 1");
2990
2991 vc_conn := f_start_handler(refers(f_tc_cipher_complete_with_invalid_cipher), 52);
2992 vc_conn.done;
2993}
2994
Harald Weltef640a012018-04-14 17:49:21 +02002995/* TODO (SMS):
2996 * different user data lengths
2997 * SMPP transaction mode with unsuccessful delivery
2998 * queued MT-SMS with no paging response + later delivery
2999 * different data coding schemes
3000 * multi-part SMS
3001 * user-data headers
3002 * TP-PID for SMS to SIM
3003 * behavior if SMS memory is full + RP-SMMA
3004 * delivery reports
3005 * SMPP osmocom extensions
3006 * more-messages-to-send
3007 * SMS during ongoing call (SACCH/SAPI3)
3008 */
3009
3010/* TODO (General):
Harald Welteba7b6d92018-01-23 21:32:34 +01003011 * continue to send repeated MO signalling messages to keep channel open: does MSC tmeout?
3012 * malformed messages (missing IE, invalid message type): properly rejected?
3013 * MT call while LU or is ongoing: Do we use existing lchan or page while lchan active?
3014 * 3G/2G auth permutations
3015 * encryption algorithms vs. classmark vs. vty config
Harald Welteba7b6d92018-01-23 21:32:34 +01003016 * send new transaction after/during clear (like SMS, ...)
Harald Welte45164da2018-01-24 12:51:27 +01003017 * too long L3 INFO in DTAP
3018 * too long / padded BSSAP
3019 * too long / short TLV values
Harald Welteba7b6d92018-01-23 21:32:34 +01003020 */
Harald Weltef6dd64d2017-11-19 12:09:51 +01003021
Harald Welte4263c522018-12-06 11:56:27 +01003022/* Perform a location updatye at the A-Interface and run some checks to confirm
3023 * that everything is back to normal. */
3024private function f_sgsap_bssmap_screening() runs on BSC_ConnHdlr {
3025 var SmsParameters spars := valueof(t_SmsPars);
3026
3027 /* Perform a location update, the SGs association is expected to fall
3028 * back to NULL */
3029 f_perform_lu();
3030 f_ctrl_get_exp(IPA_CTRL, "fsm.SGs-UE.id.imsi:" & hex2str(g_pars.imsi) & ".state", "SGs-NULL");
3031
3032 /* Trigger a paging request and expect the paging on BSSMAP, this is
3033 * to make sure that pagings are sent throught the A-Interface again
3034 * and not throught the SGs interface.*/
3035 f_bssmap_register_imsi(g_pars.imsi, g_pars.tmsi);
3036 f_vty_transceive(MSCVTY, "subscriber imsi " & hex2str(g_pars.imsi) & " paging");
3037
3038 alt {
3039 [] BSSAP.receive(tr_BSSMAP_Paging(g_pars.imsi)); {
3040 setverdict(pass);
3041 }
3042 [] SGsAP.receive {
3043 setverdict(fail, "Received unexpected message on SGs");
3044 }
3045 }
3046
3047 /* Send an SMS to make sure that also payload messages are routed
3048 * throught the A-Interface again */
3049 f_establish_fully(EST_TYPE_MO_SMS);
3050 f_mo_sms(spars);
3051 f_expect_clear();
3052}
3053
3054private function f_tc_sgsap_reset(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
3055 var charstring vlr_name;
3056 f_init_handler(pars);
3057
3058 vlr_name := f_sgsap_reset_mme(mp_mme_name);
3059 log("VLR name: ", vlr_name);
3060 setverdict(pass);
3061}
3062
3063testcase TC_sgsap_reset() runs on MTC_CT {
3064 var BSC_ConnHdlr vc_conn;
3065 f_init();
3066 vc_conn := f_start_handler(refers(f_tc_sgsap_reset), 10);
3067 vc_conn.done;
3068}
3069
3070/* like f_mm_auth() but for SGs */
3071function f_mm_auth_sgs() runs on BSC_ConnHdlr {
3072 if (g_pars.net.expect_auth) {
3073 g_pars.vec := f_gen_auth_vec_3g();
3074 var GSUP_IE auth_tuple := valueof(ts_GSUP_IE_AuthTuple2G3G(g_pars.vec.rand,
3075 g_pars.vec.sres,
3076 g_pars.vec.kc,
3077 g_pars.vec.ik,
3078 g_pars.vec.ck,
3079 g_pars.vec.autn,
3080 g_pars.vec.res));
3081 GSUP.receive(tr_GSUP_SAI_REQ(g_pars.imsi));
3082 GSUP.send(ts_GSUP_SAI_RES(g_pars.imsi, auth_tuple));
3083 SGsAP.receive(tr_ML3_MT_MM_AUTH_REQ_3G(g_pars.vec.rand, g_pars.vec.autn));
3084 SGsAP.send(ts_ML3_MT_MM_AUTH_RESP_3G(g_pars.vec.sres, g_pars.vec.res));
3085 }
3086}
3087
3088/* like f_perform_lu(), but on SGs rather than BSSAP */
3089function f_sgs_perform_lu() runs on BSC_ConnHdlr {
3090 var octetstring mme_name := f_enc_dns_hostname(mp_mme_name);
3091 var PDU_SGsAP lur;
3092 var PDU_SGsAP lua;
3093 var PDU_SGsAP mm_info;
3094 var octetstring mm_info_dtap;
3095
3096 /* tell GSUP dispatcher to send this IMSI to us */
3097 f_create_gsup_expect(hex2str(g_pars.imsi));
3098
3099 lur := valueof(ts_SGsAP_LU_REQ(g_pars.imsi, mme_name, IMSI_attach,
3100 ts_SGsAP_LAI('901'H, '70'H, 2342)));
3101 /* Old LAI, if MS sends it */
3102 /* TMSI status, if MS has no valid TMSI */
3103 /* IMEISV, if it supports "automatic device detection" */
3104 /* TAI, if available in MME */
3105 /* E-CGI, if available in MME */
3106 SGsAP.send(lur);
3107
3108 /* FIXME: is this really done over SGs? The Ue is already authenticated
3109 * via the MME ... */
3110 f_mm_auth_sgs();
3111
3112 /* Expect MSC to perform LU with HLR */
3113 GSUP.receive(tr_GSUP_UL_REQ(g_pars.imsi));
3114 GSUP.send(ts_GSUP_ISD_REQ(g_pars.imsi, g_pars.msisdn));
3115 GSUP.receive(tr_GSUP_ISD_RES(g_pars.imsi));
3116 GSUP.send(ts_GSUP_UL_RES(g_pars.imsi));
3117
3118 alt {
3119 [] SGsAP.receive(tr_SGsAP_LU_ACCEPT(g_pars.imsi, ?)) -> value lua {
3120 if (isvalue(lua.sGsAP_LOCATION_UPDATE_ACCEPT.newTMSIorIMSI.iD.iD.tmsi_ptmsi.octets)) {
3121 g_pars.tmsi :=lua.sGsAP_LOCATION_UPDATE_ACCEPT.newTMSIorIMSI.iD.iD.tmsi_ptmsi.octets
3122 SGsAP.send(ts_SGsAP_TMSI_REALL_CMPL(g_pars.imsi));
3123 }
3124 setverdict(pass);
3125 }
3126 [] SGsAP.receive(tr_SGsAP_LU_REJECT(g_pars.imsi, ?, ?)) {
3127 setverdict(fail, "Received LU-REJECT instead of ACCEPT");
3128 }
3129 [] SGsAP.receive {
3130 setverdict(fail, "Received unexpected message on SGs");
3131 }
3132 }
3133
3134 /* Check MM information */
3135 if (mp_mm_info == true) {
3136 SGsAP.receive(tr_SGsAP_MM_INFO_REQ(g_pars.imsi, ?)) -> value mm_info;
3137 mm_info_dtap := '0532'O & mm_info.sGsAP_MM_INFORMATION_REQUEST.mM_Information.information;
3138 if (not match(dec_PDU_ML3_NW_MS(mm_info_dtap), tr_ML3_MT_MM_Info)) {
3139 setverdict(fail, "Unexpected MM Information");
3140 }
3141 }
3142
3143 f_ctrl_get_exp(IPA_CTRL, "fsm.SGs-UE.id.imsi:" & hex2str(g_pars.imsi) & ".state", "SGs-ASSOCIATED");
3144}
3145
3146private function f_tc_sgsap_lu(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
3147 f_init_handler(pars);
3148 f_sgs_perform_lu();
3149 f_ctrl_get_exp(IPA_CTRL, "fsm.SGs-UE.id.imsi:" & hex2str(g_pars.imsi) & ".state", "SGs-ASSOCIATED");
3150
3151 f_sgsap_bssmap_screening();
3152
3153 setverdict(pass);
3154}
3155testcase TC_sgsap_lu() runs on MTC_CT {
3156 var BSC_ConnHdlr vc_conn;
3157 f_init();
3158 vc_conn := f_start_handler(refers(f_tc_sgsap_lu), 10);
3159 vc_conn.done;
3160}
3161
3162/* Do LU by IMSI, refuse it on GSUP and expect LU REJ back to MS */
3163private function f_tc_sgsap_lu_imsi_reject(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
3164 f_init_handler(pars);
3165 var PDU_SGsAP lur;
3166
3167 f_create_gsup_expect(hex2str(g_pars.imsi));
3168 var octetstring mme_name := f_enc_dns_hostname(mp_mme_name);
3169 lur := valueof(ts_SGsAP_LU_REQ(g_pars.imsi, mme_name, IMSI_attach,
3170 ts_SGsAP_LAI('901'H, '70'H, 2342)));
3171 SGsAP.send(lur);
3172
3173 GSUP.receive(tr_GSUP_UL_REQ(g_pars.imsi));
3174 GSUP.send(ts_GSUP_UL_ERR(g_pars.imsi, 23));
3175 alt {
3176 [] SGsAP.receive(tr_SGsAP_LU_REJECT(g_pars.imsi, ?, ?)) {
3177 setverdict(pass);
3178 }
3179 [] SGsAP.receive(tr_SGsAP_LU_ACCEPT(g_pars.imsi, ?)) {
3180 setverdict(fail, "Expecting LU REJ, but got ACCEPT");
3181 mtc.stop;
3182 }
3183 [] SGsAP.receive {
3184 setverdict(fail, "Received unexpected message on SGs");
3185 }
3186 }
3187
3188 f_sgsap_bssmap_screening();
3189
3190 setverdict(pass);
3191}
3192testcase TC_sgsap_lu_imsi_reject() runs on MTC_CT {
3193 var BSC_ConnHdlr vc_conn;
3194 f_init();
3195
3196 vc_conn := f_start_handler(refers(f_tc_sgsap_lu_imsi_reject), 3);
3197 vc_conn.done;
3198}
3199
3200/* Do LU by IMSI, but then remain silent so that Ts6-1 times out */
3201private function f_tc_sgsap_lu_and_nothing(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
3202 var octetstring mme_name := f_enc_dns_hostname(mp_mme_name);
3203 var PDU_SGsAP lur;
3204
3205 f_init_handler(pars);
3206
3207 /* tell GSUP dispatcher to send this IMSI to us */
3208 f_create_gsup_expect(hex2str(g_pars.imsi));
3209
3210 lur := valueof(ts_SGsAP_LU_REQ(g_pars.imsi, mme_name, IMSI_attach,
3211 ts_SGsAP_LAI('901'H, '70'H, 2342)));
3212 /* Old LAI, if MS sends it */
3213 /* TMSI status, if MS has no valid TMSI */
3214 /* IMEISV, if it supports "automatic device detection" */
3215 /* TAI, if available in MME */
3216 /* E-CGI, if available in MME */
3217 SGsAP.send(lur);
3218
3219 /* FIXME: is this really done over SGs? The Ue is already authenticated
3220 * via the MME ... */
3221 f_mm_auth_sgs();
3222
3223 /* Expect MSC to perform LU with HLR */
3224 GSUP.receive(tr_GSUP_UL_REQ(g_pars.imsi));
3225 GSUP.send(ts_GSUP_ISD_REQ(g_pars.imsi, g_pars.msisdn));
3226 GSUP.receive(tr_GSUP_ISD_RES(g_pars.imsi));
3227 GSUP.send(ts_GSUP_UL_RES(g_pars.imsi));
3228
3229 alt {
3230 [] SGsAP.receive(tr_SGsAP_LU_ACCEPT(g_pars.imsi, ?)) {
3231 setverdict(pass);
3232 }
3233 [] SGsAP.receive(tr_SGsAP_LU_REJECT(g_pars.imsi, ?, ?)) {
3234 setverdict(fail, "Received LU-REJECT instead of ACCEPT");
3235 }
3236 [] SGsAP.receive {
3237 setverdict(fail, "Received unexpected message on SGs");
3238 }
3239 }
3240
3241 f_ctrl_get_exp(IPA_CTRL, "fsm.SGs-UE.id.imsi:" & hex2str(g_pars.imsi) & ".state", "SGs-ASSOCIATED");
3242
3243 /* Wait until the VLR has abort the TMSI reallocation procedure */
3244 f_sleep(45.0);
3245
3246 /* The outcome does not change the SGs state, see also 5.2.3.4 */
3247 f_ctrl_get_exp(IPA_CTRL, "fsm.SGs-UE.id.imsi:" & hex2str(g_pars.imsi) & ".state", "SGs-ASSOCIATED");
3248
3249 f_sgsap_bssmap_screening();
3250
3251 setverdict(pass);
3252}
3253testcase TC_sgsap_lu_and_nothing() runs on MTC_CT {
3254 var BSC_ConnHdlr vc_conn;
3255 f_init();
3256
3257 vc_conn := f_start_handler(refers(f_tc_sgsap_lu_and_nothing), 3);
3258 vc_conn.done;
3259}
3260
3261private function f_tc_sgsap_expl_imsi_det_eps(charstring id, BSC_ConnHdlrPars pars)
3262runs on BSC_ConnHdlr {
3263 f_init_handler(pars);
3264 f_sgs_perform_lu();
3265 f_sleep(3.0);
3266
3267 var octetstring mme_name := f_enc_dns_hostname(mp_mme_name);
3268 SGsAP.send(ts_SGsAP_EPS_DETACH_IND(g_pars.imsi, mme_name, UE_initiated));
3269 SGsAP.receive(tr_SGsAP_EPS_DETACH_ACK(g_pars.imsi));
3270 f_ctrl_get_exp(IPA_CTRL, "fsm.SGs-UE.id.imsi:" & hex2str(g_pars.imsi) & ".state", "SGs-NULL");
3271
3272 f_sgsap_bssmap_screening();
3273
3274 setverdict(pass);
3275}
3276testcase TC_sgsap_expl_imsi_det_eps() runs on MTC_CT {
3277 var BSC_ConnHdlr vc_conn;
3278 f_init();
3279 vc_conn := f_start_handler(refers(f_tc_sgsap_expl_imsi_det_eps), 10);
3280 vc_conn.done;
3281}
3282
3283private function f_tc_sgsap_expl_imsi_det_noneps(charstring id, BSC_ConnHdlrPars pars)
3284runs on BSC_ConnHdlr {
3285 f_init_handler(pars);
3286 f_sgs_perform_lu();
3287 f_sleep(3.0);
3288
3289 var octetstring mme_name := f_enc_dns_hostname(mp_mme_name);
3290 SGsAP.send(ts_SGsAP_IMSI_DETACH_IND(g_pars.imsi, mme_name, combined_UE_initiated));
3291 SGsAP.receive(tr_SGsAP_IMSI_DETACH_ACK(g_pars.imsi));
3292 f_ctrl_get_exp(IPA_CTRL, "fsm.SGs-UE.id.imsi:" & hex2str(g_pars.imsi) & ".state", "SGs-NULL");
3293 /* FIXME: How to verify that VLR has removed MM context? */
3294
3295 f_sgsap_bssmap_screening();
3296
3297 setverdict(pass);
3298}
3299testcase TC_sgsap_expl_imsi_det_noneps() runs on MTC_CT {
3300 var BSC_ConnHdlr vc_conn;
3301 f_init();
3302 vc_conn := f_start_handler(refers(f_tc_sgsap_expl_imsi_det_noneps), 1081);
3303 vc_conn.done;
3304}
3305
3306/* Trigger a paging request via VTY and send a paging reject in response */
3307private function f_tc_sgsap_paging_rej(charstring id, BSC_ConnHdlrPars pars)
3308runs on BSC_ConnHdlr {
3309 f_init_handler(pars);
3310 f_sgs_perform_lu();
3311 f_sleep(1.0);
3312
3313 var octetstring vlr_name := f_enc_dns_hostname(mp_vlr_name);
3314 var template PDU_SGsAP exp_resp := tr_SGsAP_PAGING_REQ(g_pars.imsi, vlr_name, CS_call_indicator, omit);
3315 var template LocationAreaId exp_lai := ts_SGsAP_IE_Lai(valueof(ts_SGsAP_LAI('901'H, '70'H, 2342)));
3316 exp_resp.sGsAP_PAGING_REQUEST.locationAreaId := exp_lai;
3317
3318 /* Initiate paging via VTY */
3319 f_vty_transceive(MSCVTY, "subscriber imsi " & hex2str(g_pars.imsi) & " paging");
3320 alt {
3321 [] SGsAP.receive(exp_resp) {
3322 setverdict(pass);
3323 }
3324 [] SGsAP.receive {
3325 setverdict(fail, "Received unexpected message on SGs");
3326 }
3327 }
3328
3329 /* Now reject the paging */
3330 SGsAP.send(ts_SGsAP_PAGING_REJ(g_pars.imsi, IMSI_unknown));
3331
3332 /* Wait for the states inside the MSC to settle and check the state
3333 * of the SGs Association */
3334 f_sleep(1.0);
3335 f_ctrl_get_exp(IPA_CTRL, "fsm.SGs-UE.id.imsi:" & hex2str(g_pars.imsi) & ".state", "SGs-NULL");
3336
3337 /* FIXME: At the moment we send an IMSI_unknown as cause code, which is fine,
3338 * but we also need to cover tha case where the cause code indicates an
3339 * "IMSI detached for EPS services". In those cases the VLR is expected to
3340 * try paging on tha A/Iu interface. This will be another testcase similar to
3341 * this one, but extended with checks for the presence of the A/Iu paging
3342 * messages. */
3343
3344 f_sgsap_bssmap_screening();
3345
3346 setverdict(pass);
3347}
3348testcase TC_sgsap_paging_rej() runs on MTC_CT {
3349 var BSC_ConnHdlr vc_conn;
3350 f_init();
3351 vc_conn := f_start_handler(refers(f_tc_sgsap_paging_rej), 1082);
3352 vc_conn.done;
3353}
3354
3355/* Trigger a paging request via VTY and send a paging reject that indicates
3356 * that the subscriber intentionally rejected the call. */
3357private function f_tc_sgsap_paging_subscr_rej(charstring id, BSC_ConnHdlrPars pars)
3358runs on BSC_ConnHdlr {
3359 f_init_handler(pars);
3360 f_sgs_perform_lu();
3361 f_sleep(1.0);
3362
3363 var octetstring vlr_name := f_enc_dns_hostname(mp_vlr_name);
3364 var template PDU_SGsAP exp_resp := tr_SGsAP_PAGING_REQ(g_pars.imsi, vlr_name, CS_call_indicator, omit);
3365 var template LocationAreaId exp_lai := ts_SGsAP_IE_Lai(valueof(ts_SGsAP_LAI('901'H, '70'H, 2342)));
3366 exp_resp.sGsAP_PAGING_REQUEST.locationAreaId := exp_lai;
3367
3368 /* Initiate paging via VTY */
3369 f_vty_transceive(MSCVTY, "subscriber imsi " & hex2str(g_pars.imsi) & " paging");
3370 alt {
3371 [] SGsAP.receive(exp_resp) {
3372 setverdict(pass);
3373 }
3374 [] SGsAP.receive {
3375 setverdict(fail, "Received unexpected message on SGs");
3376 }
3377 }
3378
3379 /* Now reject the paging */
3380 SGsAP.send(ts_SGsAP_PAGING_REJ(g_pars.imsi, user_rejected_mobile_terminating_CS_fallback_call));
3381
3382 /* Wait for the states inside the MSC to settle and check the state
3383 * of the SGs Association */
3384 f_sleep(1.0);
3385 f_ctrl_get_exp(IPA_CTRL, "fsm.SGs-UE.id.imsi:" & hex2str(g_pars.imsi) & ".state", "SGs-ASSOCIATED");
3386
3387 /* FIXME: The VLR is supposed to trigger an User Determined User Busy (UDUB) as specified
3388 * in 3GPP TS 24.082, this is not yet implemented in the MSC or in this tests, we need
3389 * to check back how this works and how it can be tested */
3390
3391 f_sgsap_bssmap_screening();
3392
3393 setverdict(pass);
3394}
3395testcase TC_sgsap_paging_subscr_rej() runs on MTC_CT {
3396 var BSC_ConnHdlr vc_conn;
3397 f_init();
3398 vc_conn := f_start_handler(refers(f_tc_sgsap_paging_subscr_rej), 1083);
3399 vc_conn.done;
3400}
3401
3402/* Trigger a paging request via VTY and send an UE unreacable messge in response */
3403private function f_tc_sgsap_paging_ue_unr(charstring id, BSC_ConnHdlrPars pars)
3404runs on BSC_ConnHdlr {
3405 f_init_handler(pars);
3406 f_sgs_perform_lu();
3407 f_sleep(1.0);
3408
3409 var octetstring vlr_name := f_enc_dns_hostname(mp_vlr_name);
3410 var template PDU_SGsAP exp_resp := tr_SGsAP_PAGING_REQ(g_pars.imsi, vlr_name, CS_call_indicator, omit);
3411 var template LocationAreaId exp_lai := ts_SGsAP_IE_Lai(valueof(ts_SGsAP_LAI('901'H, '70'H, 2342)));
3412 exp_resp.sGsAP_PAGING_REQUEST.locationAreaId := exp_lai;
3413
3414 /* Initiate paging via VTY */
3415 f_vty_transceive(MSCVTY, "subscriber imsi " & hex2str(g_pars.imsi) & " paging");
3416 alt {
3417 [] SGsAP.receive(exp_resp) {
3418 setverdict(pass);
3419 }
3420 [] SGsAP.receive {
3421 setverdict(fail, "Received unexpected message on SGs");
3422 }
3423 }
3424
3425 /* Now pretend that the UE is unreachable */
3426 SGsAP.send(ts_SGsAP_UE_UNREACHABLE(g_pars.imsi, UE_unreachable));
3427
3428 /* Wait for the states inside the MSC to settle and check the state
3429 * of the SGs Association. */
3430 f_sleep(1.0);
3431 f_ctrl_get_exp(IPA_CTRL, "fsm.SGs-UE.id.imsi:" & hex2str(g_pars.imsi) & ".state", "SGs-ASSOCIATED");
3432
3433 f_sgsap_bssmap_screening();
3434
3435 setverdict(pass);
3436}
3437testcase TC_sgsap_paging_ue_unr() runs on MTC_CT {
3438 var BSC_ConnHdlr vc_conn;
3439 f_init();
3440 vc_conn := f_start_handler(refers(f_tc_sgsap_paging_ue_unr), 10);
3441 vc_conn.done;
3442}
3443
3444/* Trigger a paging request via VTY but don't respond to it */
3445private function f_tc_sgsap_paging_and_nothing(charstring id, BSC_ConnHdlrPars pars)
3446runs on BSC_ConnHdlr {
3447 f_init_handler(pars);
3448 f_sgs_perform_lu();
3449 f_sleep(1.0);
3450
3451 var octetstring vlr_name := f_enc_dns_hostname(mp_vlr_name);
3452 var template PDU_SGsAP exp_resp := tr_SGsAP_PAGING_REQ(g_pars.imsi, vlr_name, CS_call_indicator, omit);
3453 var template LocationAreaId exp_lai := ts_SGsAP_IE_Lai(valueof(ts_SGsAP_LAI('901'H, '70'H, 2342)));
3454 exp_resp.sGsAP_PAGING_REQUEST.locationAreaId := exp_lai;
3455
3456 /* Initiate paging via VTY */
3457 f_vty_transceive(MSCVTY, "subscriber imsi " & hex2str(g_pars.imsi) & " paging");
3458 alt {
3459 [] SGsAP.receive(exp_resp) {
3460 setverdict(pass);
3461 }
3462 [] SGsAP.receive {
3463 setverdict(fail, "Received unexpected message on SGs");
3464 }
3465 }
3466
3467 /* Now do nothing, the MSC/VLR should fail silently to page after a
3468 * few seconds, The SGs association must remain unchanged. */
3469 f_sleep(15.0);
3470 f_ctrl_get_exp(IPA_CTRL, "fsm.SGs-UE.id.imsi:" & hex2str(g_pars.imsi) & ".state", "SGs-ASSOCIATED");
3471
3472 f_sgsap_bssmap_screening();
3473
3474 setverdict(pass);
3475}
3476testcase TC_sgsap_paging_and_nothing() runs on MTC_CT {
3477 var BSC_ConnHdlr vc_conn;
3478 f_init();
3479 vc_conn := f_start_handler(refers(f_tc_sgsap_paging_and_nothing), 92);
3480 vc_conn.done;
3481}
3482
3483/* Trigger a paging request via VTY and slip in an LU */
3484private function f_tc_sgsap_paging_and_lu(charstring id, BSC_ConnHdlrPars pars)
3485runs on BSC_ConnHdlr {
3486 var octetstring vlr_name := f_enc_dns_hostname(mp_vlr_name);
3487 f_init_handler(pars);
3488
3489 /* First we prepar the situation, where the SGs association is in state
3490 * NULL and the confirmed by radio contact indicator is set to false
3491 * as well. This can be archived by performing an SGs LU and then
3492 * resetting the VLR */
3493 f_sgs_perform_lu();
3494 f_sgsap_reset_mme(mp_mme_name);
3495 f_sleep(1.0);
3496 f_ctrl_get_exp(IPA_CTRL, "fsm.SGs-UE.id.imsi:" & hex2str(g_pars.imsi) & ".state", "SGs-NULL");
3497
3498 /* Perform a paging, expect the paging messages on the SGs interface */
3499 f_vty_transceive(MSCVTY, "subscriber imsi " & hex2str(g_pars.imsi) & " paging");
3500 alt {
3501 [] SGsAP.receive(tr_SGsAP_PAGING_REQ(pars.imsi, vlr_name, CS_call_indicator, omit)) {
3502 setverdict(pass);
3503 }
3504 [] SGsAP.receive {
3505 setverdict(fail, "Received unexpected message on SGs");
3506 }
3507 }
3508
3509 /* Perform the LU as normal */
3510 f_sgs_perform_lu();
3511 f_ctrl_get_exp(IPA_CTRL, "fsm.SGs-UE.id.imsi:" & hex2str(g_pars.imsi) & ".state", "SGs-ASSOCIATED");
3512
3513 /* Expect a new paging request right after the LU */
3514 alt {
3515 [] SGsAP.receive(tr_SGsAP_PAGING_REQ(pars.imsi, vlr_name, CS_call_indicator, omit)) {
3516 setverdict(pass);
3517 }
3518 [] SGsAP.receive {
3519 setverdict(fail, "Received unexpected message on SGs");
3520 }
3521 }
3522
3523 /* Test is done now, lets round everything up by rejecting the paging
3524 * cleanly. */
3525 SGsAP.send(ts_SGsAP_PAGING_REJ(g_pars.imsi, user_rejected_mobile_terminating_CS_fallback_call));
3526 f_ctrl_get_exp(IPA_CTRL, "fsm.SGs-UE.id.imsi:" & hex2str(g_pars.imsi) & ".state", "SGs-ASSOCIATED");
3527
3528 f_sgsap_bssmap_screening();
3529
3530 setverdict(pass);
3531}
3532testcase TC_sgsap_paging_and_lu() runs on MTC_CT {
3533 var BSC_ConnHdlr vc_conn;
3534 f_init();
3535 vc_conn := f_start_handler(refers(f_tc_sgsap_paging_and_lu), 9792);
3536 vc_conn.done;
3537}
3538
3539/* Send unexpected unit-data through the SGs interface */
3540private function f_tc_sgsap_unexp_ud(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
3541 f_init_handler(pars);
3542 f_sleep(1.0);
3543
3544 /* This simulates what happens when a subscriber without SGs
3545 * association gets unitdata via the SGs interface. */
3546
3547 /* Make sure the subscriber exists and the SGs association
3548 * is in NULL state */
3549 f_perform_lu();
3550 f_ctrl_get_exp(IPA_CTRL, "fsm.SGs-UE.id.imsi:" & hex2str(g_pars.imsi) & ".state", "SGs-NULL");
3551
3552 /* Send some random unit data, the MSC/VLR should send a release
3553 * immediately. */
3554 SGsAP.send(ts_SGsAP_UL_UD(pars.imsi,'1234'O));
3555 SGsAP.receive(tr_SGsAP_RELEASE_REQ(pars.imsi, IMSI_detached_for_EPS_nonEPS_services));
3556
3557 f_sgsap_bssmap_screening();
3558
3559 setverdict(pass);
3560}
3561testcase TC_sgsap_unexp_ud() runs on MTC_CT {
3562 var BSC_ConnHdlr vc_conn;
3563 f_init();
3564 vc_conn := f_start_handler(refers(f_tc_sgsap_unexp_ud), 2145);
3565 vc_conn.done;
3566}
3567
3568/* Send unsolicited unit-data through the SGs interface */
3569private function f_tc_sgsap_unsol_ud(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
3570 f_init_handler(pars);
3571 f_sleep(1.0);
3572
3573 /* This simulates what happens when the MME attempts to send unitdata
3574 * to a subscriber that is completely unknown to the VLR */
3575
3576 /* Send some random unit data, the MSC/VLR should send a release
3577 * immediately. */
3578 SGsAP.send(ts_SGsAP_UL_UD(pars.imsi,'1234'O));
3579 SGsAP.receive(tr_SGsAP_RELEASE_REQ(pars.imsi, IMSI_unknown));
3580
3581 f_sgsap_bssmap_screening();
3582
3583 setverdict(pass);
3584}
3585testcase TC_sgsap_unsol_ud() runs on MTC_CT {
3586 var BSC_ConnHdlr vc_conn;
3587 f_init();
3588 vc_conn := f_start_handler(refers(f_tc_sgsap_unsol_ud), 146);
3589 vc_conn.done;
3590}
3591
3592private altstep as_other_sms_sgs() runs on BSC_ConnHdlr {
3593 /* FIXME: Match an actual payload (second questionmark), the type is
3594 * octetstring, how do we use a tr_PDU_DTAP_MT here? */
3595 [] SGsAP.receive(tr_SGsAP_DL_UD(?,?)) {
3596 setverdict(fail, "Unexpected SMS related PDU from MSC");
3597 mtc.stop;
3598 }
3599}
3600
3601/* receive a MT-SMS delivered from the MSC/SMSC over an already existing SGsAP connection */
3602function f_mt_sms_sgs(inout SmsParameters spars)
3603runs on BSC_ConnHdlr {
3604 var template (value) TPDU_RP_DATA_MS_SGSN tp_mo;
3605 var template (value) RPDU_MS_SGSN rp_mo;
3606 var template (value) PDU_ML3_MS_NW l3_mo;
3607
3608 var template TPDU_RP_DATA_SGSN_MS tp_mt;
3609 var template RPDU_SGSN_MS rp_mt;
3610 var template PDU_ML3_NW_MS l3_mt;
3611
3612 var PDU_ML3_NW_MS sgsap_l3_mt;
3613
3614 var default d := activate(as_other_sms_sgs());
3615
3616 /* Expect CP-DATA(RP-DATA(SMS-DELIVER)) */
3617 tp_mt := tr_SMS_DELIVER(?, spars.tp.ud, spars.tp.pid, spars.tp.dcs, ?);
3618 rp_mt := tr_RP_DATA_MT(?, ?, omit, tp_mt);
3619 l3_mt := tr_ML3_MT_SMS(?, c_TIF_ORIG, tr_CP_DATA_MT(rp_mt));
3620
3621 SGsAP.receive(l3_mt) -> value sgsap_l3_mt;
3622
3623 /* Extract relevant identifiers */
3624 spars.tid := bit2int(sgsap_l3_mt.tiOrSkip.transactionId.tio);
3625 spars.rp.msg_ref := sgsap_l3_mt.msgs.sms.cP_DATA.cP_User_Data.cP_RPDU.rP_DATA_SGSN_MS.rP_MessageReference;
3626
3627 /* send CP-ACK for CP-DATA just received */
3628 l3_mo := ts_ML3_MO_SMS(spars.tid, c_TIF_REPL, ts_CP_ACK_MO);
3629
3630 SGsAP.send(l3_mo);
3631
3632 /* send RP-ACK for RP-DATA */
3633 rp_mo := ts_RP_ACK_MO(spars.rp.msg_ref);
3634 l3_mo := ts_ML3_MO_SMS(spars.tid, c_TIF_REPL, ts_CP_DATA_MO(rp_mo));
3635
3636 SGsAP.send(l3_mo);
3637
3638 /* expect CP-ACK for CP-DATA(RP-ACK) just sent */
3639 l3_mt := tr_ML3_MT_SMS(spars.tid, c_TIF_ORIG, tr_CP_ACK_MT);
3640
3641 SGsAP.receive(l3_mt);
3642
3643 deactivate(d);
3644
3645 setverdict(pass);
3646}
3647
3648/* submit a MO-SMS to MSC/SMSC over an already existing SGsAP connection */
3649function f_mo_sms_sgs(inout SmsParameters spars)
3650runs on BSC_ConnHdlr {
3651 var template (value) TPDU_RP_DATA_MS_SGSN tp_mo;
3652 var template (value) RPDU_MS_SGSN rp_mo;
3653 var template (value) PDU_ML3_MS_NW l3_mo;
3654
3655 var template TPDU_RP_DATA_SGSN_MS tp_mt;
3656 var template RPDU_SGSN_MS rp_mt;
3657 var template PDU_ML3_NW_MS l3_mt;
3658
3659 var default d := activate(as_other_sms_sgs());
3660
3661 /* just in case this is routed to SMPP.. */
3662 f_create_smpp_expect(hex2str(spars.tp.da.tP_DA_NoPad.tP_DAValue));
3663
3664 tp_mo := ts_SMS_SUBMIT(spars.tp.msg_ref, spars.tp.da, spars.tp.pid, spars.tp.dcs,
3665 spars.tp.udl, spars.tp.ud);
3666 rp_mo := ts_RP_DATA_MO(spars.rp.msg_ref, spars.rp.orig, spars.rp.dest, tp_mo);
3667 l3_mo := ts_ML3_MO_SMS(spars.tid, c_TIF_ORIG, ts_CP_DATA_MO(rp_mo));
3668
3669 SGsAP.send(l3_mo);
3670
3671 /* receive CP-ACK for CP-DATA above */
3672 SGsAP.receive(tr_ML3_MT_SMS(spars.tid, c_TIF_REPL, tr_CP_ACK_MT));
3673
3674 if (ispresent(spars.exp_rp_err)) {
3675 /* expect an RP-ERROR message from MSC with given cause */
3676 rp_mt := tr_RP_ERROR_MT(spars.rp.msg_ref, spars.exp_rp_err);
3677 l3_mt := tr_ML3_MT_SMS(spars.tid, c_TIF_REPL, tr_CP_DATA_MT(rp_mt));
3678 SGsAP.receive(l3_mt);
3679 /* send CP-ACK for CP-DATA just received */
3680 l3_mo := ts_ML3_MO_SMS(spars.tid, c_TIF_ORIG, ts_CP_ACK_MO);
3681 SGsAP.send(l3_mo);
3682 } else {
3683 /* expect RP-ACK for RP-DATA */
3684 rp_mt := tr_RP_ACK_MT(spars.rp.msg_ref);
3685 l3_mt := tr_ML3_MT_SMS(spars.tid, c_TIF_REPL, tr_CP_DATA_MT(rp_mt));
3686 SGsAP.receive(l3_mt);
3687 /* send CP-ACO for CP-DATA just received */
3688 l3_mo := ts_ML3_MO_SMS(spars.tid, c_TIF_ORIG, ts_CP_ACK_MO);
3689 SGsAP.send(l3_mo);
3690 }
3691
3692 deactivate(d);
3693
3694 setverdict(pass);
3695}
3696
3697private function f_vty_sms_send_conn_hdlr(charstring imsi, charstring msisdn, charstring text)
3698runs on BSC_ConnHdlr {
3699 f_vty_transceive(MSCVTY, "subscriber imsi "&imsi&" sms sender msisdn "&msisdn&" send "&text);
3700}
3701
3702/* Send a MT SMS via SGs interface */
3703private function f_tc_sgsap_mt_sms(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
3704 f_init_handler(pars);
3705 f_sgs_perform_lu();
3706 f_sleep(1.0);
3707 var SmsParameters spars := valueof(t_SmsPars);
3708 spars.tp.ud := 'C8329BFD064D9B53'O;
3709
3710 /* Trigger SMS via VTY */
3711 f_vty_sms_send_conn_hdlr(hex2str(pars.imsi), "2342", "Hello SMS");
3712 var octetstring vlr_name := f_enc_dns_hostname(mp_vlr_name);
3713
3714 /* Expect a paging request and respond accordingly with a service request */
3715 SGsAP.receive(tr_SGsAP_PAGING_REQ(pars.imsi, vlr_name, SMS_indicator, omit));
3716 SGsAP.send(ts_SGsAP_SERVICE_REQ(pars.imsi, SMS_indicator, EMM_CONNECTED));
3717
3718 /* Connection is now live, receive the MT-SMS */
3719 f_mt_sms_sgs(spars);
3720
3721 /* Expect a concluding release from the MSC */
3722 SGsAP.receive(tr_SGsAP_RELEASE_REQ(pars.imsi, omit));
3723
3724 /* Make sure that subscriber is still present and the SGs association is in tact (ref-counting) */
3725 f_ctrl_get_exp(IPA_CTRL, "fsm.SGs-UE.id.imsi:" & hex2str(g_pars.imsi) & ".state", "SGs-ASSOCIATED");
3726
3727 f_sgsap_bssmap_screening();
3728
3729 setverdict(pass);
3730}
3731testcase TC_sgsap_mt_sms() runs on MTC_CT {
3732 var BSC_ConnHdlr vc_conn;
3733 f_init();
3734 vc_conn := f_start_handler(refers(f_tc_sgsap_mt_sms), 1145);
3735 vc_conn.done;
3736}
3737
3738/* Send a MO SMS via SGs interface */
3739private function f_tc_sgsap_mo_sms(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
3740 f_init_handler(pars);
3741 f_sgs_perform_lu();
3742 f_sleep(1.0);
3743 var SmsParameters spars := valueof(t_SmsPars);
3744 spars.tp.ud := 'C8329BFD064D9B53'O;
3745
3746 /* Send the MO-SMS */
3747 f_mo_sms_sgs(spars);
3748
3749 /* Expect a concluding release from the MSC/VLR */
3750 SGsAP.receive(tr_SGsAP_RELEASE_REQ(pars.imsi, omit));
3751
3752 /* Make sure that subscriber is still present and the SGs association is in tact (ref-counting) */
3753 f_ctrl_get_exp(IPA_CTRL, "fsm.SGs-UE.id.imsi:" & hex2str(g_pars.imsi) & ".state", "SGs-ASSOCIATED");
3754
3755 setverdict(pass);
3756
3757 f_sgsap_bssmap_screening()
3758}
3759testcase TC_sgsap_mo_sms() runs on MTC_CT {
3760 var BSC_ConnHdlr vc_conn;
3761 f_init();
3762 vc_conn := f_start_handler(refers(f_tc_sgsap_mo_sms), 3145);
3763 vc_conn.done;
3764}
3765
3766/* Trigger sending of an MT sms via VTY but never respond to anything */
3767private function f_tc_sgsap_mt_sms_and_nothing(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
3768 f_init_handler(pars, 170.0);
3769 f_sgs_perform_lu();
3770 f_sleep(1.0);
3771
3772 var SmsParameters spars := valueof(t_SmsPars);
3773 spars.tp.ud := 'C8329BFD064D9B53'O;
3774 var integer page_count := 0;
3775 var octetstring vlr_name := f_enc_dns_hostname(mp_vlr_name);
3776 var template PDU_SGsAP exp_pag_req := tr_SGsAP_PAGING_REQ(g_pars.imsi, vlr_name, SMS_indicator, omit);
3777 var template LocationAreaId exp_lai := ts_SGsAP_IE_Lai(valueof(ts_SGsAP_LAI('901'H, '70'H, 2342)));
3778 exp_pag_req.sGsAP_PAGING_REQUEST.locationAreaId := exp_lai;
3779
3780 /* Trigger SMS via VTY */
3781 f_vty_sms_send_conn_hdlr(hex2str(pars.imsi), "2342", "Hello SMS");
3782
3783 /* Expect the MSC/VLR to page exactly 10 times before giving up */
3784 alt {
3785 [] SGsAP.receive(exp_pag_req)
3786 {
3787 page_count := page_count + 1;
3788
3789 if (page_count < 10) {
3790 repeat;
3791 }
3792 }
3793 [] SGsAP.receive {
3794 setverdict(fail, "unexpected SGsAP message received");
3795 self.stop;
3796 }
3797 }
3798
3799 /* Wait some time to make sure the MSC is not delivering any further
3800 * paging messages or anything else that could be unexpected. */
3801 timer T := 20.0;
3802 T.start
3803 alt {
3804 [] SGsAP.receive(exp_pag_req)
3805 {
3806 setverdict(fail, "paging seems not to stop!");
3807 mtc.stop;
3808 }
3809 [] SGsAP.receive {
3810 setverdict(fail, "unexpected SGsAP message received");
3811 self.stop;
3812 }
3813 [] T.timeout {
3814 setverdict(pass);
3815 }
3816 }
3817
3818 /* Even on a failed paging the SGs Association should stay intact */
3819 f_ctrl_get_exp(IPA_CTRL, "fsm.SGs-UE.id.imsi:" & hex2str(g_pars.imsi) & ".state", "SGs-ASSOCIATED");
3820
3821 /* Note: We do not execute f_sgsap_bssmap_screening() here since the
3822 * MSC/VLR would re-try to deliver the test SMS trigered above and
3823 * so the screening would fail. */
3824
3825 /* Expire the subscriber now to avoid that the MSC will try the SMS
3826 * delivery at some later point. */
3827 f_vty_transceive(MSCVTY, "subscriber imsi " & hex2str(g_pars.imsi) & " expire");
3828
3829 setverdict(pass);
3830}
3831testcase TC_sgsap_mt_sms_and_nothing() runs on MTC_CT {
3832 var BSC_ConnHdlr vc_conn;
3833 f_init();
3834 vc_conn := f_start_handler(refers(f_tc_sgsap_mt_sms_and_nothing), 4581);
3835 vc_conn.done;
3836}
3837
3838/* Trigger sending of an MT sms via VTY but reject the paging immediately */
3839private function f_tc_sgsap_mt_sms_and_reject(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
3840 f_init_handler(pars, 150.0);
3841 f_sgs_perform_lu();
3842 f_sleep(1.0);
3843
3844 var SmsParameters spars := valueof(t_SmsPars);
3845 spars.tp.ud := 'C8329BFD064D9B53'O;
3846 var integer page_count := 0;
3847 var octetstring vlr_name := f_enc_dns_hostname(mp_vlr_name);
3848 var template PDU_SGsAP exp_pag_req := tr_SGsAP_PAGING_REQ(g_pars.imsi, vlr_name, SMS_indicator, omit);
3849 var template LocationAreaId exp_lai := ts_SGsAP_IE_Lai(valueof(ts_SGsAP_LAI('901'H, '70'H, 2342)));
3850 exp_pag_req.sGsAP_PAGING_REQUEST.locationAreaId := exp_lai;
3851
3852 /* Trigger SMS via VTY */
3853 f_vty_sms_send_conn_hdlr(hex2str(pars.imsi), "2342", "Hello SMS");
3854
3855 /* Expect a paging request and reject it immediately */
3856 SGsAP.receive(exp_pag_req);
3857 SGsAP.send(ts_SGsAP_PAGING_REJ(g_pars.imsi, IMSI_unknown));
3858
3859 /* The MSC/VLR should no longer try to page once the paging has been
3860 * rejected. Wait some time and check if there are no unexpected
3861 * messages on the SGs interface. */
3862 timer T := 20.0;
3863 T.start
3864 alt {
3865 [] SGsAP.receive(exp_pag_req)
3866 {
3867 setverdict(fail, "paging seems not to stop!");
3868 mtc.stop;
3869 }
3870 [] SGsAP.receive {
3871 setverdict(fail, "unexpected SGsAP message received");
3872 self.stop;
3873 }
3874 [] T.timeout {
3875 setverdict(pass);
3876 }
3877 }
3878
3879 /* A rejected paging with IMSI_unknown (see above) should always send
3880 * the SGs association to NULL. */
3881 f_ctrl_get_exp(IPA_CTRL, "fsm.SGs-UE.id.imsi:" & hex2str(g_pars.imsi) & ".state", "SGs-NULL");
3882
3883 f_sgsap_bssmap_screening();
3884
3885 /* Expire the subscriber now to avoid that the MSC will try the SMS
3886 * delivery at some later point. */
3887 f_vty_transceive(MSCVTY, "subscriber imsi " & hex2str(g_pars.imsi) & " expire");
3888
3889 setverdict(pass);
3890}
3891testcase TC_sgsap_mt_sms_and_reject() runs on MTC_CT {
3892 var BSC_ConnHdlr vc_conn;
3893 f_init();
3894 vc_conn := f_start_handler(refers(f_tc_sgsap_mt_sms_and_reject), 4145);
3895 vc_conn.done;
3896}
3897
3898/* Perform an MT CSDB call including LU */
3899private function f_mt_lu_and_csfb_call(charstring id, BSC_ConnHdlrPars pars, boolean bssmap_lu) runs on BSC_ConnHdlr {
3900 f_init_handler(pars);
3901
3902 /* Be sure that the BSSMAP reset is done before we begin. */
3903 f_sleep(2.0);
3904
3905 /* Testcase variation: See what happens when we do a regular BSSMAP
3906 * LU first (this should not hurt in any way!) */
3907 if (bssmap_lu) {
3908 f_perform_lu();
3909 }
3910
3911 f_sgs_perform_lu();
3912 f_sleep(1.0);
3913
3914 var octetstring vlr_name := f_enc_dns_hostname(mp_vlr_name);
3915 var CallParameters cpars := valueof(t_CallParams('12345'H, 0));
3916 cpars.bss_rtp_port := 1110;
3917 cpars.mgcp_connection_id_bss := '10004'H;
3918 cpars.mgcp_connection_id_mss := '10005'H;
3919
3920 /* Note: This is an optional parameter. When the call-agent (MSC) does
3921 * supply a full endpoint name this setting will be overwritten. */
3922 cpars.mgcp_ep := "rtpbridge/1@mgw";
3923
3924 /* Initiate a call via MNCC interface */
3925 f_mt_call_initate(cpars);
3926
3927 /* Expect a paging request and respond accordingly with a service request */
3928 SGsAP.receive(tr_SGsAP_PAGING_REQ(pars.imsi, vlr_name, CS_call_indicator, omit));
3929 SGsAP.send(ts_SGsAP_SERVICE_REQ(pars.imsi, CS_call_indicator, EMM_CONNECTED));
3930
3931 /* Complete the call, hold it for some time and then tear it down */
3932 f_mt_call_complete(cpars);
3933 f_sleep(3.0);
3934 f_call_hangup(cpars, true);
3935
3936 /* Make sure that subscriber is still present and the SGs association is in tact (ref-counting) */
3937 f_ctrl_get_exp(IPA_CTRL, "fsm.SGs-UE.id.imsi:" & hex2str(g_pars.imsi) & ".state", "SGs-ASSOCIATED");
3938
3939 /* Finally simulate the return of the UE to the 4G network */
3940 SGsAP.send(ts_SGsAP_MO_CSFB_IND(pars.imsi));
3941
3942 /* Test for successful return by triggering a paging, when the paging
3943 * request is received via SGs, we can be sure that the MSC/VLR has
3944 * recognized that the UE is now back on 4G */
3945 f_sleep(1.0);
3946 f_vty_transceive(MSCVTY, "subscriber imsi " & hex2str(g_pars.imsi) & " paging");
3947 alt {
3948 [] SGsAP.receive(tr_SGsAP_PAGING_REQ(pars.imsi, vlr_name, CS_call_indicator, omit)) {
3949 setverdict(pass);
3950 }
3951 [] SGsAP.receive {
3952 setverdict(fail, "Received unexpected message on SGs");
3953 }
3954 }
3955
3956 f_sgsap_bssmap_screening();
3957
3958 setverdict(pass);
3959}
3960
3961/* Perform a regular BSSAP LU first, do a SGSAP LU and then make a CSFB call */
3962private function f_tc_bssap_lu_sgsap_lu_and_mt_call(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
3963 f_mt_lu_and_csfb_call(id, pars, true);
3964}
3965testcase TC_bssap_lu_sgsap_lu_and_mt_call() runs on MTC_CT {
3966 var BSC_ConnHdlr vc_conn;
3967 f_init();
3968
3969 vc_conn := f_start_handler(refers(f_tc_bssap_lu_sgsap_lu_and_mt_call), 139);
3970 vc_conn.done;
3971}
3972
3973
3974/* Perform a SGSAP LU and then make a CSFB call */
3975private function f_tc_sgsap_lu_and_mt_call(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
3976 f_mt_lu_and_csfb_call(id, pars, false);
3977}
3978testcase TC_sgsap_lu_and_mt_call() runs on MTC_CT {
3979 var BSC_ConnHdlr vc_conn;
3980 f_init();
3981
3982 vc_conn := f_start_handler(refers(f_tc_sgsap_lu_and_mt_call), 239);
3983 vc_conn.done;
3984}
3985
3986/* SGs TODO:
3987 * LU attempt for IMSI without NAM_PS in HLR
3988 * LU attempt with AUTH FAIL due to invalid RES/SRES
3989 * LU attempt with no response from HLR (VLR should timeout + LU REJ)
3990 * LU attempt with new TMSI but without TMSI REALL CMPL baco to VLR
3991 * implicit IMSI detach from EPS
3992 * implicit IMSI detach from non-EPS
3993 * MM INFO
3994 *
3995 */
Harald Weltef6dd64d2017-11-19 12:09:51 +01003996
3997control {
Philipp Maier328d1662018-03-07 10:40:27 +01003998 execute( TC_cr_before_reset() );
Harald Weltea49e36e2018-01-21 19:29:33 +01003999 execute( TC_lu_imsi_noauth_tmsi() );
Harald Welted2328a22018-01-27 14:27:16 +01004000 execute( TC_lu_imsi_noauth_notmsi() );
Harald Weltea49e36e2018-01-21 19:29:33 +01004001 execute( TC_lu_imsi_reject() );
4002 execute( TC_lu_imsi_timeout_gsup() );
Harald Welted2328a22018-01-27 14:27:16 +01004003 execute( TC_lu_imsi_auth_tmsi() );
4004 execute( TC_cmserv_imsi_unknown() );
Harald Welte2bb825f2018-01-22 11:31:18 +01004005 execute( TC_lu_and_mo_call() );
Harald Welte071ed732018-01-23 19:53:52 +01004006 execute( TC_lu_auth_sai_timeout() );
4007 execute( TC_lu_auth_sai_err() );
Harald Weltee1a2f3c2018-01-24 17:28:48 +01004008 execute( TC_lu_clear_request() );
4009 execute( TC_lu_disconnect() );
4010 execute( TC_lu_by_imei() );
4011 execute( TC_lu_by_tmsi_noauth_unknown() );
4012 execute( TC_imsi_detach_by_imsi() );
4013 execute( TC_imsi_detach_by_tmsi() );
4014 execute( TC_imsi_detach_by_imei() );
4015 execute( TC_emerg_call_imei_reject() );
4016 execute( TC_emerg_call_imsi() );
4017 execute( TC_cm_serv_req_vgcs_reject() );
4018 execute( TC_cm_serv_req_vbs_reject() );
4019 execute( TC_cm_serv_req_lcs_reject() );
Harald Welte0195ab12018-01-24 21:50:20 +01004020 execute( TC_cm_reest_req_reject() );
Harald Welte1af6ea82018-01-25 18:33:15 +01004021 execute( TC_lu_auth_2G_fail() );
4022 execute( TC_lu_imsi_auth_tmsi_encr_13_13() );
4023 execute( TC_cl3_no_payload() );
4024 execute( TC_cl3_rnd_payload() );
Harald Welte1852a842018-01-26 22:53:36 +01004025 execute( TC_establish_and_nothing() );
4026 execute( TC_mo_setup_and_nothing() );
4027 execute( TC_mo_crcx_ran_timeout() );
4028 execute( TC_mo_crcx_ran_reject() );
Harald Welted2328a22018-01-27 14:27:16 +01004029 execute( TC_mt_crcx_ran_reject() );
Daniel Willmann8b084372018-02-04 13:35:26 +01004030 execute( TC_mo_setup_and_dtmf_dup() );
Harald Welteaa54cf82018-01-30 08:15:32 +01004031 //execute( TC_mt_t310() );
Harald Welte167458a2018-01-27 15:58:16 +01004032 execute( TC_gsup_cancel() );
Harald Welte9de84792018-01-28 01:06:35 +01004033 execute( TC_lu_imsi_auth_tmsi_encr_1_13() );
4034 execute( TC_lu_imsi_auth_tmsi_encr_3_13() );
4035 execute( TC_lu_imsi_auth_tmsi_encr_3_1() );
Neels Hofmeyr29b8da02018-03-01 18:09:45 +01004036 execute( TC_lu_imsi_auth_tmsi_encr_3_1_no_cm() );
Harald Welte9de84792018-01-28 01:06:35 +01004037 execute( TC_lu_imsi_auth_tmsi_encr_13_2() );
4038 execute( TC_lu_imsi_auth_tmsi_encr_013_2() );
Philipp Maier94f3f1b2018-03-15 18:54:13 +01004039 execute( TC_mo_release_timeout() );
Philipp Maier2a98a732018-03-19 16:06:12 +01004040 execute( TC_lu_and_mt_call_no_dlcx_resp() );
Philipp Maier75932982018-03-27 14:52:35 +02004041 execute( TC_reset_two() );
Harald Welte33ec09b2018-02-10 15:34:46 +01004042
4043 execute( TC_lu_and_mt_call() );
4044
Harald Weltef45efeb2018-04-09 18:19:24 +02004045 execute( TC_lu_and_mo_sms() );
4046 execute( TC_lu_and_mt_sms() );
Harald Weltef640a012018-04-14 17:49:21 +02004047 execute( TC_smpp_mo_sms() );
4048 execute( TC_smpp_mt_sms() );
Harald Weltef45efeb2018-04-09 18:19:24 +02004049
Vadim Yanitskiy103d09f2018-11-12 02:50:23 +07004050 execute( TC_gsup_mo_sms() );
Vadim Yanitskiy9cc019a2018-11-15 02:06:07 +07004051 execute( TC_gsup_mo_smma() );
Vadim Yanitskiy103d09f2018-11-12 02:50:23 +07004052
Vadim Yanitskiy2a978b92018-06-19 17:51:20 +07004053 execute( TC_lu_and_mo_ussd_single_request() );
Vadim Yanitskiy13e4a272018-06-19 18:24:31 +07004054 execute( TC_lu_and_mt_ussd_notification() );
Vadim Yanitskiy2a978b92018-06-19 17:51:20 +07004055 execute( TC_lu_and_mo_ussd_during_mt_call() );
Vadim Yanitskiy13e4a272018-06-19 18:24:31 +07004056 execute( TC_lu_and_mt_ussd_during_mt_call() );
Vadim Yanitskiy2daf52d2018-06-21 04:19:58 +07004057 execute( TC_lu_and_mo_ussd_mo_release() );
Vadim Yanitskiy0e392dd2018-11-29 00:47:54 +07004058 execute( TC_lu_and_ss_session_timeout() );
Vadim Yanitskiy7d1f9182018-05-28 16:21:42 +07004059
Stefan Sperling89eb1f32018-12-17 15:06:20 +01004060 execute( TC_cipher_complete_with_invalid_cipher() );
4061
Harald Welte4263c522018-12-06 11:56:27 +01004062 execute( TC_sgsap_reset() );
4063 execute( TC_sgsap_lu() );
4064 execute( TC_sgsap_lu_imsi_reject() );
4065 execute( TC_sgsap_lu_and_nothing() );
4066 execute( TC_sgsap_expl_imsi_det_eps() );
4067 execute( TC_sgsap_expl_imsi_det_noneps() );
4068 execute( TC_sgsap_paging_rej() );
4069 execute( TC_sgsap_paging_subscr_rej() );
4070 execute( TC_sgsap_paging_ue_unr() );
4071 execute( TC_sgsap_paging_and_nothing() );
4072 execute( TC_sgsap_paging_and_lu() );
4073 execute( TC_sgsap_mt_sms() );
4074 execute( TC_sgsap_mo_sms() );
4075 execute( TC_sgsap_mt_sms_and_nothing() );
4076 execute( TC_sgsap_mt_sms_and_reject() );
4077 execute( TC_sgsap_unexp_ud() );
4078 execute( TC_sgsap_unsol_ud() );
4079 execute( TC_bssap_lu_sgsap_lu_and_mt_call() );
4080 execute( TC_sgsap_lu_and_mt_call() );
4081
Neels Hofmeyr1b3c6e32018-03-01 17:52:21 +01004082 /* Run this last: at the time of writing this test crashes the MSC */
4083 execute( TC_lu_imsi_auth_tmsi_encr_3_1_log_msc_debug() );
Neels Hofmeyr692c9ee2018-04-10 02:07:13 +02004084 execute( TC_mo_cc_bssmap_clear() );
Harald Weltef6dd64d2017-11-19 12:09:51 +01004085}
4086
4087
4088}