blob: aee01652b493bbae5976dca9659f48eb776f60ca [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 Weltea49e36e2018-01-21 19:29:33 +010045import from MobileL3_Types all;
46import from MobileL3_CommonIE_Types all;
47import from L3_Templates all;
Harald Weltef6dd64d2017-11-19 12:09:51 +010048
Harald Weltef6dd64d2017-11-19 12:09:51 +010049
Harald Weltea49e36e2018-01-21 19:29:33 +010050type component MTC_CT extends BSSAP_Adapter_CT, CTRL_Adapter_CT {
Harald Weltef6dd64d2017-11-19 12:09:51 +010051 var boolean g_initialized := false;
Harald Weltea49e36e2018-01-21 19:29:33 +010052
53 /* no 'adapter_CT' for MNCC or GSUP */
54 var MNCC_Emulation_CT vc_MNCC;
Harald Welte4aa970c2018-01-26 10:38:09 +010055 var MGCP_Emulation_CT vc_MGCP;
Harald Weltea49e36e2018-01-21 19:29:33 +010056 var GSUP_Emulation_CT vc_GSUP;
57 var IPA_Emulation_CT vc_GSUP_IPA;
58
59 /* only to get events from IPA underneath GSUP */
60 port IPA_CTRL_PT GSUP_IPA_EVENT;
Harald Welte3ca1c902018-01-24 18:51:27 +010061 /* VTY to MSC */
62 port TELNETasp_PT MSCVTY;
Harald Weltef6dd64d2017-11-19 12:09:51 +010063}
64
65modulepar {
Harald Weltea49e36e2018-01-21 19:29:33 +010066 /* remote parameters of IUT */
67 charstring mp_msc_ip := "127.0.0.1";
68 integer mp_msc_ctrl_port := 4255;
69 integer mp_msc_vty_port := 4254;
Harald Weltef6dd64d2017-11-19 12:09:51 +010070
Harald Weltea49e36e2018-01-21 19:29:33 +010071 /* local parameters of emulated HLR */
72 charstring mp_hlr_ip := "127.0.0.1";
73 integer mp_hlr_port := 4222;
Harald Weltef6dd64d2017-11-19 12:09:51 +010074
Harald Weltea49e36e2018-01-21 19:29:33 +010075 charstring mp_msc_mncc := "/tmp/mncc";
Harald Weltef6dd64d2017-11-19 12:09:51 +010076}
77
78
Harald Weltea49e36e2018-01-21 19:29:33 +010079function f_init_mncc(charstring id) runs on MTC_CT {
80 id := id & "-MNCC";
81 var MnccOps ops := {
82 create_cb := refers(MNCC_Emulation.ExpectedCreateCallback),
83 unitdata_cb := refers(MNCC_Emulation.DummyUnitdataCallback)
84 }
85
86 vc_MNCC := MNCC_Emulation_CT.create(id);
87 map(vc_MNCC:MNCC, system:MNCC_CODEC_PT);
88 vc_MNCC.start(MNCC_Emulation.main(ops, id, mp_msc_mncc));
Harald Weltef6dd64d2017-11-19 12:09:51 +010089}
90
Harald Welte4aa970c2018-01-26 10:38:09 +010091function f_init_mgcp(charstring id) runs on MTC_CT {
92 id := id & "-MGCP";
93 var MGCPOps ops := {
94 create_cb := refers(MGCP_Emulation.ExpectedCreateCallback),
95 unitdata_cb := refers(MGCP_Emulation.DummyUnitdataCallback)
96 }
97 var MGCP_conn_parameters pars := {
98 callagent_ip := "127.0.0.1",
99 callagent_udp_port := -1,
100 mgw_ip := "127.0.0.1",
101 mgw_udp_port := 2427
102 }
103
104 vc_MGCP := MGCP_Emulation_CT.create(id);
105 map(vc_MGCP:MGCP, system:MGCP_CODEC_PT);
106 vc_MGCP.start(MGCP_Emulation.main(ops, pars, id));
107}
108
Harald Weltea49e36e2018-01-21 19:29:33 +0100109function f_init_gsup(charstring id) runs on MTC_CT {
110 id := id & "-GSUP";
111 var GsupOps ops := {
112 create_cb := refers(GSUP_Emulation.ExpectedCreateCallback)
113 }
114
115 vc_GSUP_IPA := IPA_Emulation_CT.create(id & "-IPA");
116 vc_GSUP := GSUP_Emulation_CT.create(id);
117
118 map(vc_GSUP_IPA:IPA_PORT, system:IPA_CODEC_PT);
119 connect(vc_GSUP:GSUP, vc_GSUP_IPA:IPA_GSUP_PORT);
120 /* we use this hack to get events like ASP_IPA_EVENT_UP */
121 connect(vc_GSUP_IPA:IPA_CTRL_PORT, self:GSUP_IPA_EVENT);
122
123 vc_GSUP.start(GSUP_Emulation.main(ops, id));
124 vc_GSUP_IPA.start(IPA_Emulation.main_server(mp_hlr_ip, mp_hlr_port));
125
126 /* wait for incoming connection to GSUP port before proceeding */
127 timer T := 10.0;
128 T.start;
129 alt {
130 [] GSUP_IPA_EVENT.receive(t_ASP_IPA_EVT_UD(ASP_IPA_EVENT_UP)) { }
131 [] T.timeout {
132 setverdict(inconc, "No connection to GSUP Port");
133 self.stop
134 }
135 }
Harald Weltef6dd64d2017-11-19 12:09:51 +0100136}
137
Harald Weltea49e36e2018-01-21 19:29:33 +0100138function f_init() runs on MTC_CT {
Harald Weltef6dd64d2017-11-19 12:09:51 +0100139
140 if (g_initialized == true) {
141 return;
142 }
143 g_initialized := true;
144
Harald Weltea49e36e2018-01-21 19:29:33 +0100145 f_bssap_init("MSC_Test", BSC_BssmapOps);
146 f_ipa_ctrl_start(mp_msc_ip, mp_msc_ctrl_port);
147 f_init_mncc("MSC_Test");
Harald Welte4aa970c2018-01-26 10:38:09 +0100148 f_init_mgcp("MSC_Test");
Harald Weltea49e36e2018-01-21 19:29:33 +0100149 f_init_gsup("MSC_Test");
Harald Welte3ca1c902018-01-24 18:51:27 +0100150
151 map(self:MSCVTY, system:MSCVTY);
152 f_vty_set_prompts(MSCVTY);
153 f_vty_transceive(MSCVTY, "enable");
Harald Welteb14c77a2018-01-25 17:25:44 +0100154
155 /* set some defaults */
156 f_vty_config(MSCVTY, "network", "authentication optional");
157 f_vty_config(MSCVTY, "msc", "assign-tmsi");
158 f_vty_config(MSCVTY, "network", "encryption a5 0");
Harald Weltef6dd64d2017-11-19 12:09:51 +0100159}
160
161template PDU_BSSAP ts_BSSAP_BSSMAP := {
162 discriminator := '0'B,
163 spare := '0000000'B,
164 dlci := omit,
165 lengthIndicator := 0, /* overwritten by codec */
166 pdu := ?
167}
168
169template PDU_BSSAP tr_BSSAP_BSSMAP := {
170 discriminator := '0'B,
171 spare := '0000000'B,
172 dlci := omit,
173 lengthIndicator := ?,
174 pdu := {
175 bssmap := ?
176 }
177}
178
179
180type integer BssmapCause;
181
182template (value) BSSMAP_IE_Cause ts_BSSMAP_IE_Cause(BssmapCause val) := {
183 elementIdentifier := '04'O,
184 lengthIndicator := 0,
185 causeValue := int2bit(val, 7),
186 extensionCauseValue := '0'B,
187 spare1 := omit
188}
189
190template (value) PDU_BSSAP ts_BSSMAP_Reset(BssmapCause cause) modifies ts_BSSAP_BSSMAP := {
191 pdu := {
192 bssmap := {
193 reset := {
194 messageType := '30'O,
195 cause := ts_BSSMAP_IE_Cause(cause),
196 a_InterfaceSelectorForReset := omit
197 }
198 }
199 }
200}
201
202template (value) PDU_BSSAP ts_BSSMAP_ResetAck modifies ts_BSSAP_BSSMAP := {
203 pdu := {
204 bssmap := {
205 resetAck := {
206 messageType := '31'O,
207 a_InterfaceSelectorForReset := omit
208 }
209 }
210 }
211}
212
213template PDU_BSSAP tr_BSSMAP_ResetAck modifies tr_BSSAP_BSSMAP := {
214 pdu := {
215 bssmap := {
216 resetAck := {
217 messageType := '31'O,
218 a_InterfaceSelectorForReset := *
219 }
220 }
221 }
222}
223
224template BSSMAP_IE_CellIdentifier ts_BSSMAP_IE_CellID := {
225 elementIdentifier := '05'O,
226 lengthIndicator := 0,
227 cellIdentifierDiscriminator := '0000'B,
228 spare1_4 := '0000'B,
229 cellIdentification := ?
230}
231
232type uint16_t BssmapLAC;
233type uint16_t BssmapCI;
234
235/*
236template BSSMAP_IE_CellIdentifier ts_CellId_CGI(mcc, mnc, lac, ci)
237modifies ts_BSSMAP_IE_CellID := {
238 cellIdentification := {
239 cI_LAC_CGI := {
240 mnc_mcc := FIXME,
241 lac := int2oct(lac, 2),
242 ci := int2oct(ci, 2)
243 }
244 }
245}
246*/
247
248template BSSMAP_IE_CellIdentifier ts_CellID_LAC_CI(BssmapLAC lac, BssmapCI ci)
249modifies ts_BSSMAP_IE_CellID := {
250 cellIdentification := {
251 cI_LAC_CI := {
252 lac := int2oct(lac, 2),
253 ci := int2oct(ci, 2)
254 }
255 }
256}
257
258template BSSMAP_IE_CellIdentifier ts_CellId_CI(BssmapCI ci)
259modifies ts_BSSMAP_IE_CellID := {
260 cellIdentification := {
261 cI_CI := int2oct(ci, 2)
262 }
263}
264
265template BSSMAP_IE_CellIdentifier ts_CellId_none
266modifies ts_BSSMAP_IE_CellID := {
267 cellIdentification := {
268 cI_noCell := ''O
269 }
270}
271
272
273template BSSMAP_IE_Layer3Information ts_BSSMAP_IE_L3Info(octetstring l3info) := {
274 elementIdentifier := '17'O,
275 lengthIndicator := 0,
276 layer3info := l3info
277}
278
279template PDU_BSSAP ts_BSSMAP_ComplL3(BSSMAP_IE_CellIdentifier cell_id, octetstring l3_info)
280modifies ts_BSSAP_BSSMAP := {
281 pdu := {
282 bssmap := {
283 completeLayer3Information := {
284 messageType := '57'O,
285 cellIdentifier := cell_id,
286 layer3Information := ts_BSSMAP_IE_L3Info(l3_info),
287 chosenChannel := omit,
288 lSAIdentifier := omit,
289 aPDU := omit,
290 codecList := omit,
291 redirectAttemptFlag := omit,
292 sendSequenceNumber := omit,
293 iMSI := omit
294 }
295 }
296 }
297}
298
299template PDU_BSSAP ts_BSSMAP_HandoReq(BssmapCause cause, BSSMAP_IE_CellIdentifierList cid_list)
300modifies ts_BSSAP_BSSMAP := {
301 pdu := {
302 bssmap := {
303 handoverRequired := {
304 messageType := '11'O,
305 cause := ts_BSSMAP_IE_Cause(cause),
306 responseRequest := omit,
307 cellIdentifierList := cid_list,
308 circuitPoolList := omit,
309 currentChannelType1 := omit,
310 speechVersion := omit,
311 queueingIndicator := omit,
312 oldToNewBSSInfo := omit,
313 sourceToTargetRNCTransparentInfo := omit,
314 sourceToTargetRNCTransparentInfoCDMA := omit,
315 gERANClassmark := omit,
316 talkerPriority := omit,
317 speechCodec := omit,
318 cSG_Identifier := omit
319 }
320 }
321 }
322}
323
324// enc_PDU_BSSAP
325
326function f_send_BSSAP_UNITDATA(template PDU_BSSAP bssap) runs on MTC_CT {
Harald Weltea49e36e2018-01-21 19:29:33 +0100327 BSSAP.send(ts_BSSAP_UNITDATA_req(g_sccp_addr_peer, g_sccp_addr_own, bssap))
Harald Weltef6dd64d2017-11-19 12:09:51 +0100328}
329
Harald Weltea49e36e2018-01-21 19:29:33 +0100330type function void_fn(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr;
Harald Weltef6dd64d2017-11-19 12:09:51 +0100331
Harald Welte81b7f9d2018-01-24 19:06:24 +0100332private function f_concat_pad(integer tot_len, hexstring prefix, integer suffix) return hexstring {
333 var integer suffix_len := tot_len - lengthof(prefix);
334 var charstring suffix_ch := int2str(suffix);
335 var integer pad_len := suffix_len - lengthof(suffix_ch);
336
337 return prefix & int2hex(0, pad_len) & str2hex(suffix_ch);
Harald Welte256571e2018-01-24 18:47:19 +0100338}
339
Harald Welte81b7f9d2018-01-24 19:06:24 +0100340function f_gen_imei(integer suffix) return hexstring {
341 return f_concat_pad(15, '49999'H, suffix);
Harald Weltea49e36e2018-01-21 19:29:33 +0100342}
343
Harald Welte81b7f9d2018-01-24 19:06:24 +0100344function f_gen_imsi(integer suffix) return hexstring {
345 return f_concat_pad(15, '26242'H, suffix);
346}
347
348function f_gen_msisdn(integer suffix) return hexstring {
349 return f_concat_pad(12, '49123'H, suffix);
Harald Weltea49e36e2018-01-21 19:29:33 +0100350}
351
352/* FIXME: move into BSC_ConnectionHandler? */
353function f_start_handler(void_fn fn, charstring id, integer imsi_suffix) runs on MTC_CT return BSC_ConnHdlr {
354 var BSC_ConnHdlr vc_conn;
355 var BSC_ConnHdlrPars pars := {
356 sccp_addr_own := g_sccp_addr_own,
357 sccp_addr_peer := g_sccp_addr_peer,
358 cell_id := valueof(ts_CellId_CGI('262'H, '042'H, 23, 42)),
Harald Welte81b7f9d2018-01-24 19:06:24 +0100359 imei := f_gen_imei(imsi_suffix),
360 imsi := f_gen_imsi(imsi_suffix),
361 msisdn := f_gen_msisdn(imsi_suffix),
Harald Welte256571e2018-01-24 18:47:19 +0100362 tmsi := omit,
Harald Welte82600572018-01-21 20:54:08 +0100363 cm2 := valueof(ts_CM2_default),
Harald Welte16114282018-01-24 22:41:21 +0100364 cm3 := omit,
365 kc := omit
Harald Weltea49e36e2018-01-21 19:29:33 +0100366 };
367
368 vc_conn := BSC_ConnHdlr.create(id);
369 /* BSSMAP part / A interface */
370 connect(vc_conn:BSSAP, vc_BSSMAP:CLIENT);
371 connect(vc_conn:BSSAP_PROC, vc_BSSMAP:PROC);
372 /* MNCC part */
373 connect(vc_conn:MNCC, vc_MNCC:MNCC_CLIENT);
374 connect(vc_conn:MNCC_PROC, vc_MNCC:MNCC_PROC);
Harald Welte4aa970c2018-01-26 10:38:09 +0100375 /* MGCP part */
376 connect(vc_conn:MGCP, vc_MGCP:MGCP_CLIENT);
377 connect(vc_conn:MGCP_PROC, vc_MGCP:MGCP_PROC);
Harald Weltea49e36e2018-01-21 19:29:33 +0100378 /* GSUP part */
379 connect(vc_conn:GSUP, vc_GSUP:GSUP_CLIENT);
380 connect(vc_conn:GSUP_PROC, vc_GSUP:GSUP_PROC);
381
382 vc_conn.start(derefers(fn)(id, pars));
383 return vc_conn;
384}
385
386function f_sleep(float seconds) {
387 timer T := seconds;
Harald Weltef6dd64d2017-11-19 12:09:51 +0100388 T.start;
389 T.timeout;
Harald Weltea49e36e2018-01-21 19:29:33 +0100390}
Harald Weltef6dd64d2017-11-19 12:09:51 +0100391
Harald Welte3ca1c902018-01-24 18:51:27 +0100392function f_vty_config(TELNETasp_PT pt, charstring config_node, charstring cmd)
393{
394 /* enter config mode; enter node */
395 f_vty_enter_config(pt);
396 f_vty_transceive(pt, config_node);
397 /* execute command */
398 f_vty_transceive(pt, cmd);
399 /* leave config mode */
400 f_vty_transceive(pt, "end");
401}
402
Harald Weltea49e36e2018-01-21 19:29:33 +0100403private function f_tc_lu_imsi_noauth_tmsi(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
404 g_pars := pars;
Harald Welte8a121b32018-01-22 03:00:41 +0100405 f_perform_lu(false, true, true);
Harald Weltea49e36e2018-01-21 19:29:33 +0100406}
Harald Weltea49e36e2018-01-21 19:29:33 +0100407testcase TC_lu_imsi_noauth_tmsi() runs on MTC_CT {
408 var BSC_ConnHdlr vc_conn;
409 f_init();
410
411 vc_conn := f_start_handler(refers(f_tc_lu_imsi_noauth_tmsi), testcasename(), 1);
412 vc_conn.done;
413}
414
415private function f_tc_lu_imsi_noauth_notmsi(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
416 g_pars := pars;
Harald Welte8a121b32018-01-22 03:00:41 +0100417 f_perform_lu(false, false, true);
Harald Weltea49e36e2018-01-21 19:29:33 +0100418}
Harald Weltea49e36e2018-01-21 19:29:33 +0100419testcase TC_lu_imsi_noauth_notmsi() runs on MTC_CT {
420 var BSC_ConnHdlr vc_conn;
421 f_init();
Harald Welte3ca1c902018-01-24 18:51:27 +0100422 f_vty_config(MSCVTY, "msc", "no assign-tmsi");
Harald Weltea49e36e2018-01-21 19:29:33 +0100423
424 vc_conn := f_start_handler(refers(f_tc_lu_imsi_noauth_notmsi), testcasename(), 2);
425 vc_conn.done;
426}
427
428/* Do LU by IMSI, refuse it on GSUP and expect LU REJ back to MS */
429private function f_tc_lu_imsi_reject(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
430 g_pars := pars;
431 var PDU_ML3_MS_NW l3_lu := f_build_lu_imsi(g_pars.imsi);
432
433 f_create_gsup_expect(hex2str(g_pars.imsi));
434 f_bssap_compl_l3(l3_lu);
435 GSUP.receive(tr_GSUP_UL_REQ(g_pars.imsi));
436 GSUP.send(ts_GSUP_UL_ERR(g_pars.imsi, 23));
437 alt {
438 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Rej(int2oct(23,1)))) { }
439 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Acc)) {
440 setverdict(fail, "Expecting LU REJ, but got ACCEPT");
441 self.stop;
442 }
443 }
444 BSSAP.receive(tr_BSSMAP_ClearCommand);
445 BSSAP.send(ts_BSSMAP_ClearComplete);
446 BSSAP.receive(BSSAP_Conn_Prim:MSC_CONN_PRIM_DISC_IND);
447 setverdict(pass);
448}
449testcase TC_lu_imsi_reject() runs on MTC_CT {
450 var BSC_ConnHdlr vc_conn;
451 f_init();
452
453 vc_conn := f_start_handler(refers(f_tc_lu_imsi_reject), testcasename(), 3);
454 vc_conn.done;
455}
456
457/* Do LU by IMSI, timeout on GSUP */
458private function f_tc_lu_imsi_timeout_gsup(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
459 g_pars := pars;
460 var PDU_ML3_MS_NW l3_lu := f_build_lu_imsi(g_pars.imsi);
461
462 f_create_gsup_expect(hex2str(g_pars.imsi));
463 f_bssap_compl_l3(l3_lu);
464 GSUP.receive(tr_GSUP_UL_REQ(g_pars.imsi));
465 /* Normally the HLR would need to respond here, but we decide to force a timeout here */
466 alt {
467 /* FIXME: Expect specific reject cause */
468 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Rej)) { }
469 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Acc)) {
470 setverdict(fail, "Expecting LU REJ, but got ACCEPT");
471 self.stop;
472 }
473 }
474 BSSAP.receive(tr_BSSMAP_ClearCommand);
475 BSSAP.send(ts_BSSMAP_ClearComplete);
476 BSSAP.receive(BSSAP_Conn_Prim:MSC_CONN_PRIM_DISC_IND);
477 setverdict(pass);
478}
479testcase TC_lu_imsi_timeout_gsup() runs on MTC_CT {
480 var BSC_ConnHdlr vc_conn;
481 f_init();
482
483 vc_conn := f_start_handler(refers(f_tc_lu_imsi_timeout_gsup), testcasename(), 4);
484 vc_conn.done;
485}
486
Harald Welte7b1b2812018-01-22 21:23:06 +0100487private function f_tc_lu_imsi_auth_tmsi(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
488 g_pars := pars;
489 f_perform_lu(true, true, true);
490}
491testcase TC_lu_imsi_auth_tmsi() runs on MTC_CT {
492 var BSC_ConnHdlr vc_conn;
493 f_init();
Harald Welte3ca1c902018-01-24 18:51:27 +0100494 f_vty_config(MSCVTY, "network", "authentication required");
Harald Welte7b1b2812018-01-22 21:23:06 +0100495
496 vc_conn := f_start_handler(refers(f_tc_lu_imsi_auth_tmsi), testcasename(), 5);
497 vc_conn.done;
498}
499
Harald Weltea49e36e2018-01-21 19:29:33 +0100500
501/* Send CM SERVICE REQ for IMSI that has never performed LU before */
502private function f_tc_cmserv_imsi_unknown(charstring id, BSC_ConnHdlrPars pars)
503runs on BSC_ConnHdlr {
504
505 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
506 var BSSMAP_IE_CellIdentifier cell_id := valueof(ts_CellId_CGI('262'H, '042'H, 23, 42));
Harald Welte6ed6bf92018-01-24 21:09:15 +0100507 var PDU_ML3_MS_NW l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, mi));
Harald Weltea49e36e2018-01-21 19:29:33 +0100508
509 f_create_gsup_expect(hex2str(g_pars.imsi));
510
511 /* Send BSSAP_Conn_Req with COMPL L3 INFO to MSC */
512 f_bssap_compl_l3(l3_info);
513
514 timer T := 10.0;
Harald Weltef6dd64d2017-11-19 12:09:51 +0100515 T.start;
516 alt {
Harald Weltea49e36e2018-01-21 19:29:33 +0100517 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_CM_SERV_REJ)) { }
518 //[] BSSAP.receive(tr_PDU_DTAP_MT(tr_CM_SERV_ACC)) { }
519 [] BSSAP.receive { setverdict(fail, "Received unexpected BSSAP"); }
520 [] GSUP.receive(tr_GSUP_UL_REQ(g_pars.imsi)) {
521 setverdict(fail, "Unexpected GSUP UL REQ");
522 }
523 [] T.timeout { setverdict(inconc, "Timeout waiting for CM SERV REQ"); }
Harald Weltef6dd64d2017-11-19 12:09:51 +0100524 }
525
Harald Weltea49e36e2018-01-21 19:29:33 +0100526 alt {
527 [] BSSAP.receive(tr_BSSMAP_ClearCommand) {
528 setverdict(pass);
529 }
530 [] BSSAP.receive { setverdict(fail, "Received unexpected BSSAP"); }
531 [] T.timeout { setverdict(inconc, "Timeout waiting for CM SERV REQ"); }
532 }
Harald Weltef6dd64d2017-11-19 12:09:51 +0100533}
Harald Weltea49e36e2018-01-21 19:29:33 +0100534testcase TC_cmserv_imsi_unknown() runs on MTC_CT {
535 var BSC_ConnHdlr vc_conn;
536 f_init();
Harald Welte81b7f9d2018-01-24 19:06:24 +0100537 vc_conn := f_start_handler(refers(f_tc_cmserv_imsi_unknown), testcasename(), 6);
Harald Weltea49e36e2018-01-21 19:29:33 +0100538 vc_conn.done;
539}
540
Harald Welte2bb825f2018-01-22 11:31:18 +0100541private function f_tc_lu_and_mo_call(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
542 g_pars := pars;
543 f_perform_lu(false, true, true);
544
545 f_establish_fully(valueof(ts_MI_IMSI_LV(g_pars.imsi)), false);
546
547 var hexstring called := '12345'H;
548 var integer tid := 0;
549 var MNCC_PDU mncc;
Harald Welte1623e6e2018-01-26 10:38:53 +0100550 var MgcpCommand mgcp_cmd;
Harald Welte2bb825f2018-01-22 11:31:18 +0100551 f_create_mncc_expect(hex2str(called));
Harald Welte1623e6e2018-01-26 10:38:53 +0100552 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
Harald Welte2bb825f2018-01-22 11:31:18 +0100553
554 BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_CC_SETUP(tid, called)));
Harald Welte1623e6e2018-01-26 10:38:53 +0100555 interleave {
556 [] MNCC.receive(tr_MNCC_SETUP_ind(?, tr_MNCC_number(hex2str(called)))) -> value mncc {
557 /* FIXME: extract call_id */
558 /* Call Proceeding */
559 MNCC.send(ts_MNCC_CALL_PROC_req(mncc.u.signal.callref, ts_MNCC_bcap_voice));
560 BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_CC_CALL_PROC(tid)));
561 };
562 [] MGCP.receive(tr_CRCX) -> value mgcp_cmd {
563 var SDP_Message sdp := valueof(ts_SDP("127.0.0.2", "127.0.0.1", "23", "42", 1234,
564 { "98" },
565 { valueof(ts_SDP_rtpmap(98, "AMR/8000")),
566 valueof(ts_SDP_ptime(20)) }));
567 MGCP.send(ts_CRCX_ACK(mgcp_cmd.line.trans_id, '1234'H, sdp));
568 }
569 }
Harald Welte2bb825f2018-01-22 11:31:18 +0100570
571 /* Alerting */
572 MNCC.send(ts_MNCC_ALERT_req(mncc.u.signal.callref));
573 BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_CC_ALERTING(tid)));
574
Harald Welte1623e6e2018-01-26 10:38:53 +0100575 BSSAP.receive(tr_BSSMAP_AssignmentReq);
576 BSSAP.send(ts_BSSMAP_AssignmentComplete);
577
Harald Welte2bb825f2018-01-22 11:31:18 +0100578 /* Answer. This causes TCH assignment in case of "late assignment" */
579 MNCC.send(ts_MNCC_SETUP_COMPL_req(mncc.u.signal.callref));
580
581 f_sleep(3.0);
582
583 /* Hangup by "B" side */
584 MNCC.send(ts_MNCC_DISC_req(mncc.u.signal.callref, valueof(ts_MNCC_cause(23))));
585 BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_CC_DISC(tid)));
586
587 /* Release of call */
588 MNCC.send(ts_MNCC_REL_req(mncc.u.signal.callref, valueof(ts_MNCC_cause(42))));
589 BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_CC_RELEASE(tid)));
590
591 /* clearing of radio channel */
592 BSSAP.receive(tr_BSSMAP_ClearCommand);
593 BSSAP.send(ts_BSSMAP_ClearComplete);
594 BSSAP.receive(BSSAP_Conn_Prim:MSC_CONN_PRIM_DISC_IND);
595
596 f_sleep(5.0);
597}
598testcase TC_lu_and_mo_call() runs on MTC_CT {
599 var BSC_ConnHdlr vc_conn;
600 f_init();
601
Harald Welte81b7f9d2018-01-24 19:06:24 +0100602 vc_conn := f_start_handler(refers(f_tc_lu_and_mo_call), testcasename(), 7);
Harald Welte071ed732018-01-23 19:53:52 +0100603 vc_conn.done;
604}
605
606/* Test LU (with authentication enabled), where HLR times out sending SAI response */
607private function f_tc_lu_auth_sai_timeout(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
608 g_pars := pars;
609
610 var PDU_ML3_MS_NW l3_lu := f_build_lu_imsi(g_pars.imsi)
611 var PDU_DTAP_MT dtap_mt;
612
613 /* tell GSUP dispatcher to send this IMSI to us */
614 f_create_gsup_expect(hex2str(g_pars.imsi));
615
616 /* Send BSSAP_Conn_Req with COMPL L3 INFO to MSC */
617 f_bssap_compl_l3(l3_lu);
618
619 /* Send Early Classmark, just for the fun of it */
620 BSSAP.send(ts_BSSMAP_ClassmarkUpd(g_pars.cm2, g_pars.cm3));
621
622 GSUP.receive(tr_GSUP_SAI_REQ(g_pars.imsi));
623 /* The HLR would normally return an auth vector here, but we fail to do so. */
624
625 BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Rej));
626 BSSAP.receive(tr_BSSMAP_ClearCommand);
627 BSSAP.send(ts_BSSMAP_ClearComplete);
628 BSSAP.receive(BSSAP_Conn_Prim:MSC_CONN_PRIM_DISC_IND);
629 setverdict(pass);
630}
631testcase TC_lu_auth_sai_timeout() runs on MTC_CT {
632 var BSC_ConnHdlr vc_conn;
633 f_init();
Harald Welte3ca1c902018-01-24 18:51:27 +0100634 f_vty_config(MSCVTY, "network", "authentication required");
Harald Welte071ed732018-01-23 19:53:52 +0100635
Harald Welte81b7f9d2018-01-24 19:06:24 +0100636 vc_conn := f_start_handler(refers(f_tc_lu_auth_sai_timeout), testcasename(), 8);
Harald Welte071ed732018-01-23 19:53:52 +0100637 vc_conn.done;
638}
639
640/* Test LU (with authentication enabled), where HLR rejects sending SAI error */
641private function f_tc_lu_auth_sai_err(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
642 g_pars := pars;
643
644 var PDU_ML3_MS_NW l3_lu := f_build_lu_imsi(g_pars.imsi)
645 var PDU_DTAP_MT dtap_mt;
646
647 /* tell GSUP dispatcher to send this IMSI to us */
648 f_create_gsup_expect(hex2str(g_pars.imsi));
649
650 /* Send BSSAP_Conn_Req with COMPL L3 INFO to MSC */
651 f_bssap_compl_l3(l3_lu);
652
653 /* Send Early Classmark, just for the fun of it */
654 BSSAP.send(ts_BSSMAP_ClassmarkUpd(g_pars.cm2, g_pars.cm3));
655
656 GSUP.receive(tr_GSUP_SAI_REQ(g_pars.imsi));
657 GSUP.send(ts_GSUP_SAI_ERR(g_pars.imsi, 13));
658
659 BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Rej));
660 BSSAP.receive(tr_BSSMAP_ClearCommand);
661 BSSAP.send(ts_BSSMAP_ClearComplete);
662 BSSAP.receive(BSSAP_Conn_Prim:MSC_CONN_PRIM_DISC_IND);
663 setverdict(pass);
664}
665testcase TC_lu_auth_sai_err() runs on MTC_CT {
666 var BSC_ConnHdlr vc_conn;
667 f_init();
Harald Welte3ca1c902018-01-24 18:51:27 +0100668 f_vty_config(MSCVTY, "network", "authentication required");
Harald Welte071ed732018-01-23 19:53:52 +0100669
Harald Welte81b7f9d2018-01-24 19:06:24 +0100670 vc_conn := f_start_handler(refers(f_tc_lu_auth_sai_err), testcasename(), 9);
Harald Welte2bb825f2018-01-22 11:31:18 +0100671 vc_conn.done;
672}
Harald Weltea49e36e2018-01-21 19:29:33 +0100673
Harald Weltebc881782018-01-23 20:09:15 +0100674/* Test LU but BSC will send a clear request in the middle */
675private function f_tc_lu_clear_request(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
676 g_pars := pars;
677
678 var PDU_ML3_MS_NW l3_lu := f_build_lu_imsi(g_pars.imsi)
679 var PDU_DTAP_MT dtap_mt;
680
681 /* tell GSUP dispatcher to send this IMSI to us */
682 f_create_gsup_expect(hex2str(g_pars.imsi));
683
684 /* Send BSSAP_Conn_Req with COMPL L3 INFO to MSC */
685 f_bssap_compl_l3(l3_lu);
686
687 /* Send Early Classmark, just for the fun of it */
688 BSSAP.send(ts_BSSMAP_ClassmarkUpd(g_pars.cm2, g_pars.cm3));
689
690 f_sleep(1.0);
691 /* send clear request in the middle of the LU */
692 BSSAP.send(ts_BSSMAP_ClearRequest(0));
693 BSSAP.receive(tr_BSSMAP_ClearCommand);
694 BSSAP.send(ts_BSSMAP_ClearComplete);
695 BSSAP.receive(BSSAP_Conn_Prim:MSC_CONN_PRIM_DISC_IND);
696 setverdict(pass);
697}
698testcase TC_lu_clear_request() runs on MTC_CT {
699 var BSC_ConnHdlr vc_conn;
700 f_init();
701
Harald Welte81b7f9d2018-01-24 19:06:24 +0100702 vc_conn := f_start_handler(refers(f_tc_lu_clear_request), testcasename(), 10);
Harald Weltebc881782018-01-23 20:09:15 +0100703 vc_conn.done;
704}
705
Harald Welte66af9e62018-01-24 17:28:21 +0100706/* Test LU but BSC will send a clear request in the middle */
707private function f_tc_lu_disconnect(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
708 g_pars := pars;
709
710 var PDU_ML3_MS_NW l3_lu := f_build_lu_imsi(g_pars.imsi)
711 var PDU_DTAP_MT dtap_mt;
712
713 /* tell GSUP dispatcher to send this IMSI to us */
714 f_create_gsup_expect(hex2str(g_pars.imsi));
715
716 /* Send BSSAP_Conn_Req with COMPL L3 INFO to MSC */
717 f_bssap_compl_l3(l3_lu);
718
719 /* Send Early Classmark, just for the fun of it */
720 BSSAP.send(ts_BSSMAP_ClassmarkUpd(g_pars.cm2, g_pars.cm3));
721
722 f_sleep(1.0);
723 /* send clear request in the middle of the LU */
724 BSSAP.send(BSSAP_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
725 setverdict(pass);
726}
727testcase TC_lu_disconnect() runs on MTC_CT {
728 var BSC_ConnHdlr vc_conn;
729 f_init();
730
Harald Welte81b7f9d2018-01-24 19:06:24 +0100731 vc_conn := f_start_handler(refers(f_tc_lu_disconnect), testcasename(), 11);
Harald Welte66af9e62018-01-24 17:28:21 +0100732 vc_conn.done;
733}
734
735
Harald Welteba7b6d92018-01-23 21:32:34 +0100736/* Test LU but with illegal mobile identity type = IMEI */
737private function f_tc_lu_by_imei(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
738 g_pars := pars;
739
Harald Welte256571e2018-01-24 18:47:19 +0100740 var PDU_ML3_MS_NW l3_lu := f_build_lu_imei(g_pars.imei)
Harald Welteba7b6d92018-01-23 21:32:34 +0100741 var PDU_DTAP_MT dtap_mt;
742
743 /* tell GSUP dispatcher to send this IMSI to us */
744 f_create_gsup_expect(hex2str(g_pars.imsi));
745
746 /* Send BSSAP_Conn_Req with COMPL L3 INFO to MSC */
747 f_bssap_compl_l3(l3_lu);
748
749 /* Send Early Classmark, just for the fun of it */
750 BSSAP.send(ts_BSSMAP_ClassmarkUpd(g_pars.cm2, g_pars.cm3));
751 /* wait for LU reject, ignore any ID REQ */
752 alt {
753 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Rej)) { }
754 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_MM_ID_Req)) { repeat; }
755 }
756 /* wait for normal teardown */
757 BSSAP.receive(tr_BSSMAP_ClearCommand);
758 BSSAP.send(ts_BSSMAP_ClearComplete);
759 BSSAP.receive(BSSAP_Conn_Prim:MSC_CONN_PRIM_DISC_IND);
760 setverdict(pass);
761}
762testcase TC_lu_by_imei() runs on MTC_CT {
763 var BSC_ConnHdlr vc_conn;
764 f_init();
765
Harald Welte81b7f9d2018-01-24 19:06:24 +0100766 vc_conn := f_start_handler(refers(f_tc_lu_by_imei), testcasename(), 12);
Harald Welteba7b6d92018-01-23 21:32:34 +0100767 vc_conn.done;
768}
769
770/* Test LU by TMSI with unknown TMSI, expect (and answer) ID REQ. */
771private function f_tc_lu_tmsi_noauth_unknown(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
772 g_pars := pars;
773
774 var PDU_ML3_MS_NW l3_lu := f_build_lu_tmsi('01020304'O); /* FIXME: Random */
775 var PDU_DTAP_MT dtap_mt;
776
777 /* tell GSUP dispatcher to send this IMSI to us */
778 f_create_gsup_expect(hex2str(g_pars.imsi));
779
780 /* Send BSSAP_Conn_Req with COMPL L3 INFO to MSC */
781 f_bssap_compl_l3(l3_lu);
782
783 /* Send Early Classmark, just for the fun of it */
784 BSSAP.send(ts_BSSMAP_ClassmarkUpd(g_pars.cm2, g_pars.cm3));
785
786 /* Wait for + respond to ID REQ (IMSI) */
787 BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_MM_ID_Req('001'B)));
788 BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_MM_ID_Rsp_IMSI(g_pars.imsi)));
789
790 /* Expect MSC to do UpdateLocation to HLR; respond to it */
791 GSUP.receive(tr_GSUP_UL_REQ(g_pars.imsi));
792 GSUP.send(ts_GSUP_ISD_REQ(g_pars.imsi, g_pars.msisdn));
793 GSUP.receive(tr_GSUP_ISD_RES(g_pars.imsi));
794 GSUP.send(ts_GSUP_UL_RES(g_pars.imsi));
795
796 alt {
797 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Acc)) { }
798 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Rej)) {
799 setverdict(fail, "Expected LU ACK, but received REJ");
800 }
801 }
802
803 /* wait for normal teardown */
804 BSSAP.receive(tr_BSSMAP_ClearCommand);
805 BSSAP.send(ts_BSSMAP_ClearComplete);
806 BSSAP.receive(BSSAP_Conn_Prim:MSC_CONN_PRIM_DISC_IND);
807 setverdict(pass);
808}
809testcase TC_lu_by_tmsi_noauth_unknown() runs on MTC_CT {
810 var BSC_ConnHdlr vc_conn;
811 f_init();
812
Harald Welte81b7f9d2018-01-24 19:06:24 +0100813 vc_conn := f_start_handler(refers(f_tc_lu_tmsi_noauth_unknown), testcasename(), 13);
Harald Welteba7b6d92018-01-23 21:32:34 +0100814 vc_conn.done;
815}
816
817
Harald Welte45164da2018-01-24 12:51:27 +0100818/* Test IMSI DETACH (MI=IMSI) */
819private function f_tc_imsi_detach_by_imsi(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
820 g_pars := pars;
821
822 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
823
824 /* Send BSSAP_Conn_Req with COMPL L3 INFO to MSC */
825 f_bssap_compl_l3(valueof(ts_ML3_MO_MM_IMSI_DET_Ind(mi)));
826
827 /* Send Early Classmark, just for the fun of it? */
828 BSSAP.send(ts_BSSMAP_ClassmarkUpd(g_pars.cm2, g_pars.cm3));
829
830 /* wait for normal teardown */
831 BSSAP.receive(tr_BSSMAP_ClearCommand);
832 BSSAP.send(ts_BSSMAP_ClearComplete);
833 BSSAP.receive(BSSAP_Conn_Prim:MSC_CONN_PRIM_DISC_IND);
834 setverdict(pass);
835}
836testcase TC_imsi_detach_by_imsi() runs on MTC_CT {
837 var BSC_ConnHdlr vc_conn;
838 f_init();
839
Harald Welte81b7f9d2018-01-24 19:06:24 +0100840 vc_conn := f_start_handler(refers(f_tc_imsi_detach_by_imsi), testcasename(), 14);
Harald Welte45164da2018-01-24 12:51:27 +0100841 vc_conn.done;
842}
843
844/* Test IMSI DETACH (MI=TMSI) */
845private function f_tc_imsi_detach_by_tmsi(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
846 g_pars := pars;
847
848 var MobileIdentityLV mi := valueof(ts_MI_TMSI_LV('01020304'O));
849
850 /* Send BSSAP_Conn_Req with COMPL L3 INFO to MSC */
851 f_bssap_compl_l3(valueof(ts_ML3_MO_MM_IMSI_DET_Ind(mi)));
852
853 /* Send Early Classmark, just for the fun of it? */
854 BSSAP.send(ts_BSSMAP_ClassmarkUpd(g_pars.cm2, g_pars.cm3));
855
856 /* wait for normal teardown */
857 BSSAP.receive(tr_BSSMAP_ClearCommand);
858 BSSAP.send(ts_BSSMAP_ClearComplete);
859 BSSAP.receive(BSSAP_Conn_Prim:MSC_CONN_PRIM_DISC_IND);
860 setverdict(pass);
861}
862testcase TC_imsi_detach_by_tmsi() runs on MTC_CT {
863 var BSC_ConnHdlr vc_conn;
864 f_init();
865
Harald Welte81b7f9d2018-01-24 19:06:24 +0100866 vc_conn := f_start_handler(refers(f_tc_imsi_detach_by_tmsi), testcasename(), 15);
Harald Welte45164da2018-01-24 12:51:27 +0100867 vc_conn.done;
868}
869
870/* Test IMSI DETACH (MI=IMEI), which is illegal */
871private function f_tc_imsi_detach_by_imei(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
872 g_pars := pars;
873
Harald Welte256571e2018-01-24 18:47:19 +0100874 var MobileIdentityLV mi := valueof(ts_MI_IMEI_LV(g_pars.imei));
Harald Welte45164da2018-01-24 12:51:27 +0100875
876 /* Send BSSAP_Conn_Req with COMPL L3 INFO to MSC */
877 f_bssap_compl_l3(valueof(ts_ML3_MO_MM_IMSI_DET_Ind(mi)));
878
879 /* Send Early Classmark, just for the fun of it? */
880 BSSAP.send(ts_BSSMAP_ClassmarkUpd(g_pars.cm2, g_pars.cm3));
881
882 /* wait for normal teardown */
883 BSSAP.receive(tr_BSSMAP_ClearCommand);
884 BSSAP.send(ts_BSSMAP_ClearComplete);
885 BSSAP.receive(BSSAP_Conn_Prim:MSC_CONN_PRIM_DISC_IND);
886 setverdict(pass);
887}
888testcase TC_imsi_detach_by_imei() runs on MTC_CT {
889 var BSC_ConnHdlr vc_conn;
890 f_init();
891
Harald Welte81b7f9d2018-01-24 19:06:24 +0100892 vc_conn := f_start_handler(refers(f_tc_imsi_detach_by_imei), testcasename(), 16);
Harald Welte45164da2018-01-24 12:51:27 +0100893 vc_conn.done;
894}
895
896
897/* helper function for an emergency call. caller passes in mobile identity to use */
898private function f_emerg_call(MobileIdentityLV mi) runs on BSC_ConnHdlr {
899
Harald Welte6ed6bf92018-01-24 21:09:15 +0100900 var PDU_ML3_MS_NW l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_EMERG_CALL, mi));
Harald Welte45164da2018-01-24 12:51:27 +0100901 f_bssap_compl_l3(l3_info);
902 BSSAP.receive(tr_PDU_DTAP_MT(tr_CM_SERV_ACC));
903
904 var hexstring called := '112'H;
905 var integer tid := 0;
906 var MNCC_PDU mncc;
907 f_create_mncc_expect(hex2str(called));
908
909 BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_CC_EMERG_SETUP(tid)));
910 MNCC.receive(tr_MNCC_SETUP_ind(?, tr_MNCC_number(hex2str(called)))) -> value mncc;
911 /* FIXME: extract call_id */
912
913 /* Call Proceeding */
914 MNCC.send(ts_MNCC_CALL_PROC_req(mncc.u.signal.callref, ts_MNCC_bcap_voice));
915 BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_CC_CALL_PROC(tid)));
916
917 /* Alerting */
918 MNCC.send(ts_MNCC_ALERT_req(mncc.u.signal.callref));
919 BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_CC_ALERTING(tid)));
920
921 /* Answer. This causes TCH assignment in case of "late assignment" */
922 MNCC.send(ts_MNCC_SETUP_COMPL_req(mncc.u.signal.callref));
923
924 f_sleep(3.0);
925
926 /* Hangup by "B" side */
927 MNCC.send(ts_MNCC_DISC_req(mncc.u.signal.callref, valueof(ts_MNCC_cause(23))));
928 BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_CC_DISC(tid)));
929
930 /* Release of call */
931 MNCC.send(ts_MNCC_REL_req(mncc.u.signal.callref, valueof(ts_MNCC_cause(42))));
932 BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_CC_RELEASE(tid)));
933
934 /* clearing of radio channel */
935 BSSAP.receive(tr_BSSMAP_ClearCommand);
936 BSSAP.send(ts_BSSMAP_ClearComplete);
937 BSSAP.receive(BSSAP_Conn_Prim:MSC_CONN_PRIM_DISC_IND);
938
939 f_sleep(5.0);
940}
941
942/* establish an emergency call by IMEI, no SIM inserted (and hence no IMSI) */
943private function f_tc_emerg_call_imei_reject(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
944 g_pars := pars;
945
Harald Welte256571e2018-01-24 18:47:19 +0100946 var MobileIdentityLV mi := valueof(ts_MI_IMEI_LV(g_pars.imei));
Harald Welte6ed6bf92018-01-24 21:09:15 +0100947 var PDU_ML3_MS_NW l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_EMERG_CALL, mi));
Harald Welte45164da2018-01-24 12:51:27 +0100948 f_bssap_compl_l3(l3_info);
949 BSSAP.receive(tr_PDU_DTAP_MT(tr_CM_SERV_REJ('05'O)));
Harald Weltef6b62ee2018-01-24 21:49:32 +0100950 BSSAP.receive(tr_BSSMAP_ClearCommand);
951 BSSAP.send(ts_BSSMAP_ClearComplete);
952 BSSAP.receive(BSSAP_Conn_Prim:MSC_CONN_PRIM_DISC_IND);
Harald Welte45164da2018-01-24 12:51:27 +0100953 setverdict(pass);
954}
955testcase TC_emerg_call_imei_reject() runs on MTC_CT {
956 var BSC_ConnHdlr vc_conn;
957 f_init();
958
Harald Welte81b7f9d2018-01-24 19:06:24 +0100959 vc_conn := f_start_handler(refers(f_tc_emerg_call_imei_reject), testcasename(), 17);
Harald Welte45164da2018-01-24 12:51:27 +0100960 vc_conn.done;
961}
962
Harald Welted5b91402018-01-24 18:48:16 +0100963/* establish an emergency call by IMSI, SIM inserted (and hence IMSI) */
Harald Welte45164da2018-01-24 12:51:27 +0100964private function f_tc_emerg_call_imsi(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
965 g_pars := pars;
966 /* First perform location update to ensure subscriber is known */
967 f_perform_lu(false, true, true);
968 /* Then issue emergency call identified by IMSI */
969 f_emerg_call(valueof(ts_MI_IMSI_LV(g_pars.imsi)));
970}
971testcase TC_emerg_call_imsi() runs on MTC_CT {
972 var BSC_ConnHdlr vc_conn;
973 f_init();
974
Harald Welte81b7f9d2018-01-24 19:06:24 +0100975 vc_conn := f_start_handler(refers(f_tc_emerg_call_imsi), testcasename(), 18);
Harald Welte45164da2018-01-24 12:51:27 +0100976 vc_conn.done;
977}
978
979/* CM Service Request for VGCS -> reject */
980private function f_tc_cm_serv_req_vgcs_reject(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
981 g_pars := pars;
982
983 /* First perform location update to ensure subscriber is known */
984 f_perform_lu(false, true, true);
985
986 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
Harald Welte6ed6bf92018-01-24 21:09:15 +0100987 var PDU_ML3_MS_NW l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_VGCS, mi));
Harald Welte45164da2018-01-24 12:51:27 +0100988 f_bssap_compl_l3(l3_info);
989 BSSAP.receive(tr_PDU_DTAP_MT(tr_CM_SERV_REJ(int2oct(32,1))));
Harald Weltef6b62ee2018-01-24 21:49:32 +0100990 BSSAP.receive(tr_BSSMAP_ClearCommand);
991 BSSAP.send(ts_BSSMAP_ClearComplete);
992 BSSAP.receive(BSSAP_Conn_Prim:MSC_CONN_PRIM_DISC_IND);
Harald Welte45164da2018-01-24 12:51:27 +0100993 setverdict(pass);
994}
995testcase TC_cm_serv_req_vgcs_reject() runs on MTC_CT {
996 var BSC_ConnHdlr vc_conn;
997 f_init();
998
Harald Welte81b7f9d2018-01-24 19:06:24 +0100999 vc_conn := f_start_handler(refers(f_tc_cm_serv_req_vgcs_reject), testcasename(), 19);
Harald Welte45164da2018-01-24 12:51:27 +01001000 vc_conn.done;
1001}
1002
1003/* CM Service Request for VBS -> reject */
1004private function f_tc_cm_serv_req_vbs_reject(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
1005 g_pars := pars;
1006
1007 /* First perform location update to ensure subscriber is known */
1008 f_perform_lu(false, true, true);
1009
1010 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
Harald Welte6ed6bf92018-01-24 21:09:15 +01001011 var PDU_ML3_MS_NW l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_VBS, mi));
Harald Welte45164da2018-01-24 12:51:27 +01001012 f_bssap_compl_l3(l3_info);
1013 BSSAP.receive(tr_PDU_DTAP_MT(tr_CM_SERV_REJ(int2oct(32,1))));
Harald Weltef6b62ee2018-01-24 21:49:32 +01001014 BSSAP.receive(tr_BSSMAP_ClearCommand);
1015 BSSAP.send(ts_BSSMAP_ClearComplete);
1016 BSSAP.receive(BSSAP_Conn_Prim:MSC_CONN_PRIM_DISC_IND);
Harald Welte45164da2018-01-24 12:51:27 +01001017 setverdict(pass);
1018}
1019testcase TC_cm_serv_req_vbs_reject() runs on MTC_CT {
1020 var BSC_ConnHdlr vc_conn;
1021 f_init();
1022
Harald Welte81b7f9d2018-01-24 19:06:24 +01001023 vc_conn := f_start_handler(refers(f_tc_cm_serv_req_vbs_reject), testcasename(), 20);
Harald Welte45164da2018-01-24 12:51:27 +01001024 vc_conn.done;
1025}
1026
1027/* CM Service Request for LCS -> reject */
1028private function f_tc_cm_serv_req_lcs_reject(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
1029 g_pars := pars;
1030
1031 /* First perform location update to ensure subscriber is known */
1032 f_perform_lu(false, true, true);
1033
1034 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
Harald Welte6ed6bf92018-01-24 21:09:15 +01001035 var PDU_ML3_MS_NW l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_LCS, mi));
Harald Welte45164da2018-01-24 12:51:27 +01001036 f_bssap_compl_l3(l3_info);
1037 BSSAP.receive(tr_PDU_DTAP_MT(tr_CM_SERV_REJ(int2oct(32,1))));
Harald Welte0195ab12018-01-24 21:50:20 +01001038 BSSAP.receive(tr_BSSMAP_ClearCommand);
1039 BSSAP.send(ts_BSSMAP_ClearComplete);
1040 BSSAP.receive(BSSAP_Conn_Prim:MSC_CONN_PRIM_DISC_IND);
Harald Welte45164da2018-01-24 12:51:27 +01001041 setverdict(pass);
1042}
1043testcase TC_cm_serv_req_lcs_reject() runs on MTC_CT {
1044 var BSC_ConnHdlr vc_conn;
1045 f_init();
1046
Harald Welte81b7f9d2018-01-24 19:06:24 +01001047 vc_conn := f_start_handler(refers(f_tc_cm_serv_req_lcs_reject), testcasename(), 21);
Harald Welte45164da2018-01-24 12:51:27 +01001048 vc_conn.done;
1049}
1050
Harald Welte0195ab12018-01-24 21:50:20 +01001051/* CM Re-Establishment Request */
1052private function f_tc_cm_reest_req_reject(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
1053 g_pars := pars;
1054
1055 /* First perform location update to ensure subscriber is known */
1056 f_perform_lu(false, true, true);
1057
1058 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
1059 var PDU_ML3_MS_NW l3_info := valueof(ts_CM_REEST_REQ(0, mi));
1060 f_bssap_compl_l3(l3_info);
1061 BSSAP.receive(tr_PDU_DTAP_MT(tr_CM_SERV_REJ(int2oct(32,1))));
1062 BSSAP.receive(tr_BSSMAP_ClearCommand);
1063 BSSAP.send(ts_BSSMAP_ClearComplete);
1064 BSSAP.receive(BSSAP_Conn_Prim:MSC_CONN_PRIM_DISC_IND);
1065 setverdict(pass);
1066}
1067testcase TC_cm_reest_req_reject() runs on MTC_CT {
1068 var BSC_ConnHdlr vc_conn;
1069 f_init();
Harald Welte0195ab12018-01-24 21:50:20 +01001070
1071 vc_conn := f_start_handler(refers(f_tc_cm_reest_req_reject), testcasename(), 22);
1072 vc_conn.done;
1073}
1074
Harald Weltec638f4d2018-01-24 22:00:36 +01001075/* Test LU (with authentication enabled), with wrong response from MS */
1076private function f_tc_lu_auth_2G_fail(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
1077 g_pars := pars;
1078
1079 var PDU_ML3_MS_NW l3_lu := f_build_lu_imsi(g_pars.imsi)
1080
1081 /* tell GSUP dispatcher to send this IMSI to us */
1082 f_create_gsup_expect(hex2str(g_pars.imsi));
1083
1084 /* Send BSSAP_Conn_Req with COMPL L3 INFO to MSC */
1085 f_bssap_compl_l3(l3_lu);
1086
1087 /* Send Early Classmark, just for the fun of it */
1088 BSSAP.send(ts_BSSMAP_ClassmarkUpd(g_pars.cm2, g_pars.cm3));
1089
1090 var AuthVector vec := f_gen_auth_vec_2g();
1091 var GSUP_IE auth_tuple := valueof(ts_GSUP_IE_AuthTuple2G(vec.rand, vec.sres, vec.kc));
1092 GSUP.receive(tr_GSUP_SAI_REQ(g_pars.imsi));
1093 GSUP.send(ts_GSUP_SAI_RES(g_pars.imsi, auth_tuple));
1094
1095 BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_MM_AUTH_REQ(vec.rand)));
1096 /* Send back wrong auth response */
1097 BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MT_MM_AUTH_RESP_2G('00000000'O)));
1098
1099 /* Expect GSUP AUTH FAIL REP to HLR */
1100 GSUP.receive(tr_GSUP_AUTH_FAIL_IND(g_pars.imsi));
1101
1102 /* Expect LU REJECT with Cause == Illegal MS */
1103 BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Rej('03'O)));
1104 BSSAP.receive(tr_BSSMAP_ClearCommand);
1105 BSSAP.send(ts_BSSMAP_ClearComplete);
1106 BSSAP.receive(BSSAP_Conn_Prim:MSC_CONN_PRIM_DISC_IND);
1107 setverdict(pass);
1108}
1109testcase TC_lu_auth_2G_fail() runs on MTC_CT {
1110 var BSC_ConnHdlr vc_conn;
1111 f_init();
1112 f_vty_config(MSCVTY, "network", "authentication required");
1113 f_vty_config(MSCVTY, "msc", "assign-tmsi");
1114
1115 vc_conn := f_start_handler(refers(f_tc_lu_auth_2G_fail), testcasename(), 23);
1116 vc_conn.done;
1117}
1118
Harald Welte16114282018-01-24 22:41:21 +01001119private function f_tc_lu_imsi_auth_tmsi_encr_13_13(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
1120 g_pars := pars;
1121 f_perform_lu(true, true, true, true);
1122}
1123testcase TC_lu_imsi_auth_tmsi_encr_13_13() runs on MTC_CT {
1124 var BSC_ConnHdlr vc_conn;
1125 f_init();
1126 f_vty_config(MSCVTY, "network", "authentication required");
1127 f_vty_config(MSCVTY, "msc", "assign-tmsi");
1128 f_vty_config(MSCVTY, "network", "encryption a5 1 3");
1129
1130 vc_conn := f_start_handler(refers(f_tc_lu_imsi_auth_tmsi_encr_13_13), testcasename(), 24);
1131 vc_conn.done;
1132}
1133
Harald Welte1af6ea82018-01-25 18:33:15 +01001134/* Test Complete L3 without payload */
1135private function f_tc_cl3_no_payload(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
1136 g_pars := pars;
1137
1138 /* Send Complete L3 Info with empty L3 frame */
1139 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_peer, g_pars.sccp_addr_own,
1140 valueof(ts_BSSMAP_ComplL3(g_pars.cell_id, ''O))));
1141
1142 alt {
1143 [] BSSAP.receive(BSSAP_Conn_Prim:MSC_CONN_PRIM_DISC_IND) {}
1144 /* Expect LU REJECT with Cause == Illegal MS */
1145 [] BSSAP.receive(tr_BSSMAP_ClearCommand) {
1146 BSSAP.send(ts_BSSMAP_ClearComplete);
1147 BSSAP.receive(BSSAP_Conn_Prim:MSC_CONN_PRIM_DISC_IND);
1148 }
1149 }
1150 setverdict(pass);
1151}
1152testcase TC_cl3_no_payload() runs on MTC_CT {
1153 var BSC_ConnHdlr vc_conn;
1154 f_init();
1155
1156 vc_conn := f_start_handler(refers(f_tc_cl3_no_payload), testcasename(), 24);
1157 vc_conn.done;
1158}
1159
1160/* Test Complete L3 with random payload */
1161private function f_tc_cl3_rnd_payload(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
1162 g_pars := pars;
1163
1164 var integer len := float2int(rnd() * 256.0);
1165 var octetstring payl := f_rnd_octstring(len);
1166
1167 /* Send Complete L3 Info with empty L3 frame */
1168 BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_peer, g_pars.sccp_addr_own,
1169 valueof(ts_BSSMAP_ComplL3(g_pars.cell_id, payl))));
1170
1171 alt {
1172 /* Immediate disconnect */
1173 [] BSSAP.receive(BSSAP_Conn_Prim:MSC_CONN_PRIM_DISC_IND) {}
1174 /* Expect LU REJECT with Cause == Illegal MS */
1175 [] BSSAP.receive(tr_BSSMAP_ClearCommand) {
1176 BSSAP.send(ts_BSSMAP_ClearComplete);
1177 BSSAP.receive(BSSAP_Conn_Prim:MSC_CONN_PRIM_DISC_IND);
1178 }
1179 [] BSSAP.receive(tr_PDU_DTAP_MT(?)) { repeat; }
1180 }
1181 setverdict(pass);
1182}
1183testcase TC_cl3_rnd_payload() runs on MTC_CT {
1184 var BSC_ConnHdlr vc_conn;
1185 f_init();
1186
1187 vc_conn := f_start_handler(refers(f_tc_cl3_rnd_payload), testcasename(), 24);
1188 vc_conn.done;
1189}
1190
Harald Welte45164da2018-01-24 12:51:27 +01001191
Harald Welteba7b6d92018-01-23 21:32:34 +01001192/* TODO:
1193 * continue to send repeated MO signalling messages to keep channel open: does MSC tmeout?
1194 * malformed messages (missing IE, invalid message type): properly rejected?
1195 * MT call while LU or is ongoing: Do we use existing lchan or page while lchan active?
1196 * 3G/2G auth permutations
1197 * encryption algorithms vs. classmark vs. vty config
Harald Welteba7b6d92018-01-23 21:32:34 +01001198 * send new transaction after/during clear (like SMS, ...)
Harald Welte45164da2018-01-24 12:51:27 +01001199 * too long L3 INFO in DTAP
1200 * too long / padded BSSAP
1201 * too long / short TLV values
Harald Welteba7b6d92018-01-23 21:32:34 +01001202 */
Harald Weltef6dd64d2017-11-19 12:09:51 +01001203
1204
1205control {
Harald Weltea49e36e2018-01-21 19:29:33 +01001206 execute( TC_cmserv_imsi_unknown() );
1207 execute( TC_lu_imsi_noauth_tmsi() );
1208 //execute( TC_lu_imsi_noauth_notmsi() );
1209 execute( TC_lu_imsi_reject() );
1210 execute( TC_lu_imsi_timeout_gsup() );
Harald Welte2bb825f2018-01-22 11:31:18 +01001211 execute( TC_lu_and_mo_call() );
Harald Welte071ed732018-01-23 19:53:52 +01001212 execute( TC_lu_auth_sai_timeout() );
1213 execute( TC_lu_auth_sai_err() );
Harald Weltee1a2f3c2018-01-24 17:28:48 +01001214 execute( TC_lu_clear_request() );
1215 execute( TC_lu_disconnect() );
1216 execute( TC_lu_by_imei() );
1217 execute( TC_lu_by_tmsi_noauth_unknown() );
1218 execute( TC_imsi_detach_by_imsi() );
1219 execute( TC_imsi_detach_by_tmsi() );
1220 execute( TC_imsi_detach_by_imei() );
1221 execute( TC_emerg_call_imei_reject() );
1222 execute( TC_emerg_call_imsi() );
1223 execute( TC_cm_serv_req_vgcs_reject() );
1224 execute( TC_cm_serv_req_vbs_reject() );
1225 execute( TC_cm_serv_req_lcs_reject() );
Harald Welte0195ab12018-01-24 21:50:20 +01001226 execute( TC_cm_reest_req_reject() );
Harald Welte1af6ea82018-01-25 18:33:15 +01001227 execute( TC_lu_auth_2G_fail() );
1228 execute( TC_lu_imsi_auth_tmsi_encr_13_13() );
1229 execute( TC_cl3_no_payload() );
1230 execute( TC_cl3_rnd_payload() );
Harald Weltef6dd64d2017-11-19 12:09:51 +01001231}
1232
1233
1234}